diff --git a/apps/web/src/pages.tsx b/apps/web/src/pages.tsx index b41fb80..cc08817 100644 --- a/apps/web/src/pages.tsx +++ b/apps/web/src/pages.tsx @@ -7,7 +7,6 @@ import { ChevronLeft, ChevronRight, ChevronsUpDown, - CircleUserRound, FileText, Folder, Inbox, @@ -19,7 +18,6 @@ import { MailOpen, Menu, MoreHorizontal, - PanelRightClose, Paperclip, Pencil, Plus, @@ -128,7 +126,7 @@ function Header({ t, }: { locale: Locale; - onLocaleChange: () => void; + onLocaleChange: (locale: Locale) => void; query: string; onQueryChange: (value: string) => void; onSearch: (value: string) => void; @@ -145,7 +143,9 @@ function Header({ const searchInput = useRef(null); const [showSearchHelp, setShowSearchHelp] = useState(false); const [showAccounts, setShowAccounts] = useState(false); + const [showLocales, setShowLocales] = useState(false); const accountMenu = useRef(null); + const localeMenu = useRef(null); const activeAccount = accounts.find(({ id }) => id === activeAccountId); useEffect(() => { const focusSearch = (event: KeyboardEvent) => { @@ -167,12 +167,17 @@ function Header({ }; }, []); useEffect(() => { - if (!showAccounts) return; + if (!showAccounts && !showLocales) return; const close = (event: PointerEvent) => { - if (!accountMenu.current?.contains(event.target as Node)) setShowAccounts(false); + const target = event.target as Node; + if (!accountMenu.current?.contains(target)) setShowAccounts(false); + if (!localeMenu.current?.contains(target)) setShowLocales(false); }; const handleEscape = (event: KeyboardEvent) => { - if (event.key === "Escape") setShowAccounts(false); + if (event.key === "Escape") { + setShowAccounts(false); + setShowLocales(false); + } }; window.addEventListener("pointerdown", close); window.addEventListener("keydown", handleEscape); @@ -180,7 +185,7 @@ function Header({ window.removeEventListener("pointerdown", close); window.removeEventListener("keydown", handleEscape); }; - }, [showAccounts]); + }, [showAccounts, showLocales]); return (
@@ -263,9 +268,45 @@ function Header({ - +
+ + {showLocales && ( +
+ {(["en", "es"] as const).map((option) => ( + + ))} +
+ )} +
@@ -426,6 +470,7 @@ function Sidebar({ mailboxes, labels, onLabelSelect, + onMailboxSelect, t, canCompose, }: { @@ -434,15 +479,29 @@ function Sidebar({ mailboxes: Mailbox[]; labels: MailLabel[]; onLabelSelect: (label: MailLabel) => void; + onMailboxSelect: (mailbox: Mailbox) => void; t: Translator; canCompose: boolean; }) { const mailboxByRole = new Map(mailboxes.map((mailbox) => [mailbox.role, mailbox])); const [collapsedLabels, setCollapsedLabels] = useState>(new Set()); + const [showMore, setShowMore] = useState(false); const userLabels = useMemo( () => buildLabelTree(labels.filter((label) => label.kind === "user")), [labels], ); + useEffect(() => { + const collectParents = (nodes: LabelTreeNode[]): string[] => + nodes.flatMap((node) => [ + ...(node.children.length ? [node.path] : []), + ...collectParents(node.children), + ]); + setCollapsedLabels(new Set(collectParents(userLabels))); + }, [userLabels]); + const extraMailboxes = mailboxes.filter((mailbox) => + (["archive", "trash", "junk"] as const).includes(mailbox.role as "archive" | "trash" | "junk"), + ); + const extraIcons = { archive: Archive, trash: Trash2, junk: Mail } as const; return ( - ); -} - function VirtualMessageList({ messages, selected, @@ -913,7 +1005,9 @@ function VirtualMessageList({ readActionLabel={`${t(message.isRead ? "markUnread" : "markRead")} ${ message.subject || message.senderName }`} + readActionText={t(message.isRead ? "markUnread" : "markRead")} openLabel={`${t("openMessage")} ${message.subject || message.senderName}`} + openActionText={t("openMessage")} actionsEnabled={actionsEnabled} />
@@ -1364,10 +1458,10 @@ export function MailPage({ initialLocale = "en" }: { initialLocale?: Locale }) { }; return ( -
+
setLocale(locale === "en" ? "es" : "en")} + onLocaleChange={setLocale} query={query} onQueryChange={setQuery} onSearch={submitSearch} @@ -1400,6 +1494,22 @@ export function MailPage({ initialLocale = "en" }: { initialLocale?: Locale }) { setQuery(nextQuery); submitSearch(nextQuery); }} + onMailboxSelect={(mailbox) => { + setActiveThreadId(null); + setPageCursor(undefined); + setCursorHistory([]); + if (mailbox.role === "inbox") { + setQuery(""); + setSubmittedSearch(""); + setSearchResults([]); + setCategory("primary"); + window.history.replaceState(null, "", "/"); + return; + } + const nextQuery = `in:"${mailbox.remoteName.replaceAll('"', '\\"')}"`; + setQuery(nextQuery); + submitSearch(nextQuery); + }} t={t} canCompose={canCompose} /> @@ -1577,7 +1687,6 @@ export function MailPage({ initialLocale = "en" }: { initialLocale?: Locale }) { )} -
{composeOpen && activeAccountId && canCompose && ( span:nth-child(2) { - min-width: 0; - display: grid; - text-align: left; -} -.account-option strong, -.account-option small { - overflow: hidden; - text-overflow: ellipsis; -} -.app-body { - display: grid; - grid-template-columns: var(--sidebar-width) minmax(0, 1fr) var(--rail-width); - min-height: 0; - overflow: hidden; - gap: 0; - padding: 0 12px 12px 0; -} -.app-body.sidebar-is-collapsed { - grid-template-columns: var(--sidebar-collapsed-width) minmax(0, 1fr) var(--rail-width); -} -.sidebar { - min-width: 0; - width: 100%; - overflow-x: hidden; - overflow-y: auto; - overscroll-behavior: contain; - padding: 14px 12px 18px; - transition: padding var(--duration-fast) var(--ease-out); -} -.sidebar.collapsed { - padding-inline: 8px; -} -.sidebar.collapsed .compose-button { - width: 44px; - padding: 0; -} -.sidebar.collapsed .compose-button span, -.sidebar.collapsed .nav-item span:not(.label-dot):not(.provider-icon), -.sidebar.collapsed .nav-item strong, -.sidebar.collapsed .sidebar-section-title, -.sidebar.collapsed .accounts { - display: none; -} -.compose-button { - width: 100%; - max-width: 172px; - height: 44px; - justify-content: flex-start; - margin-bottom: 14px; - padding-left: 16px; - color: #000; - transition: - max-width var(--duration-fast) var(--ease-out), - padding var(--duration-fast) var(--ease-out), - transform var(--duration-fast) var(--ease-out); -} -.nav-list { - display: grid; - gap: 2px; -} -.nav-item { - width: 100%; - min-height: 38px; - display: grid; - grid-template-columns: 22px 1fr auto; - align-items: center; - gap: 9px; - padding: 0 10px; - border: 0; - border-radius: 7px; - background: transparent; - color: #b9b9bf; - text-align: left; - font-size: 14px; - cursor: pointer; -} -.nav-item:hover { - background: #111; - color: white; -} -.nav-item.active { - background: #1d1d1f; - color: white; - box-shadow: inset 2px 0 white; -} -.nav-item strong { - color: #d4d4d8; - font-size: 12px; - font-weight: 600; -} -.sidebar-section-title { - height: 44px; - display: flex; - align-items: center; - justify-content: space-between; - margin-top: 16px; - padding: 0 10px; - color: #f4f4f5; - font-size: 14px; - font-weight: 600; -} -.label-tree-row { - display: grid; - grid-template-columns: 20px minmax(0, 1fr); - align-items: center; - padding-left: calc(var(--label-depth) * 16px); -} -.label-disclosure, -.label-disclosure-spacer { - width: 20px; - height: 32px; - display: grid; - place-items: center; -} -.label-disclosure { - padding: 0; - border: 0; - background: transparent; - color: var(--muted); - cursor: pointer; -} -.label-disclosure[aria-expanded="true"] svg { - transform: rotate(90deg); -} -.label-item { - grid-template-columns: 20px minmax(0, 1fr) auto; - padding-left: 4px; -} -.label-item:disabled { - opacity: 1; - cursor: default; -} -.label-dot { - width: 13px; - height: 10px; - border-radius: 3px 5px 5px 3px; - background: #71717a; -} -.label-dot.violet { - background: #a78bfa; -} -.label-dot.amber { - background: #f59e0b; -} -.label-dot.blue { - background: #60a5fa; -} -.provider-icon { - width: 19px; - height: 19px; - display: grid; - place-items: center; - border: 1px solid #52525b; - border-radius: 5px; - color: white; - font-size: 11px; - font-weight: 700; -} -.accounts .online-dot { - justify-self: end; - width: 6px; - height: 6px; -} -.mail-surface { - min-width: 0; - min-height: 0; - overflow: hidden; - background: var(--surface); - border: 1px solid var(--border); - border-radius: 9px 0 0 9px; -} -.mail-toolbar { - height: 48px; - display: flex; - align-items: center; - justify-content: space-between; - padding: 0 12px; - border-bottom: 1px solid var(--border); -} -.toolbar-group { - gap: 3px; - color: var(--muted); -} -.range-controls { - gap: 2px; - font-size: 12px; -} -.range-controls > span { - margin-right: 8px; -} -.select-box { - width: 18px; - height: 18px; - display: grid; - place-items: center; - flex: 0 0 auto; - padding: 0; - border: 1px solid #52525b; - border-radius: 3px; - background: transparent; - color: #000; - font-size: 12px; - cursor: pointer; -} -.select-box.checked { - border-color: white; - background: white; -} -.category-tabs { - height: 56px; - display: grid; - grid-template-columns: repeat(5, minmax(120px, 1fr)); - border-bottom: 1px solid var(--border); - overflow-x: auto; -} -.category-tab { - position: relative; - min-width: 120px; - display: flex; - align-items: center; - gap: 9px; - padding: 0 18px; - border: 0; - background: transparent; - color: var(--muted); - cursor: pointer; - font-size: 14px; -} -.category-tab:hover { - background: #111; - color: white; -} -.category-tab.active { - color: white; -} -.category-tab.active::after { - content: ""; - position: absolute; - right: 12px; - bottom: 0; - left: 12px; - height: 2px; - background: white; -} -.category-tab strong { - padding: 2px 6px; - border-radius: 999px; - background: white; - color: black; - font-size: 11px; -} -.message-list { - height: calc(100% - 104px); - overflow-y: auto; -} -.virtual-message-list { - position: relative; - width: 100%; -} -.virtual-message-row { - position: absolute; - top: 0; - left: 0; - width: 100%; -} -.message-row { - position: relative; - min-height: 45px; - display: grid; - grid-template-columns: 22px 24px 24px minmax(0, 1fr) 108px; - align-items: center; - gap: 5px; - padding: 0 12px; - border-bottom: 1px solid #202022; - color: #b7b7bd; -} -.message-row:hover { - background: var(--hover); - color: #e4e4e7; -} -.message-row.selected { - background: #1e1e20; -} -.message-row.unread { - background: #111; - color: var(--text); -} -.message-row.unread:hover { - background: #191919; -} -.row-icon { - width: 24px; - height: 36px; - display: grid; - place-items: center; - padding: 0; - border: 0; - background: transparent; - color: #626269; - cursor: pointer; -} -.row-icon:hover { - color: white; -} -.row-icon.starred { - color: white; -} -.row-icon.important { - transform: rotate(90deg); -} -.message-content { - min-width: 0; - min-height: 44px; - display: grid; - grid-template-columns: minmax(120px, 190px) minmax(180px, 1fr) auto 24px 72px; - align-items: center; - gap: 10px; - padding: 0; - border: 0; - background: transparent; - color: inherit; - text-align: left; - cursor: pointer; -} -.sender, -.subject-line { - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} -.sender { - color: inherit; - font-size: 14px; -} -.subject-line { - font-size: 14px; -} -.subject-line strong { - color: inherit; - font-weight: 500; -} -.subject-line span { - color: #85858d; -} -.unread .sender, -.unread .subject-line strong { - font-weight: 650; -} -.attachment-chip { - display: flex; - align-items: center; - gap: 4px; - max-width: 180px; - overflow: hidden; - padding: 4px 8px; - border: 1px solid #36363a; - border-radius: 999px; - color: #a1a1aa; - font-size: 12px; - text-overflow: ellipsis; - white-space: nowrap; -} -.provider-badge { - width: 20px; - height: 20px; - display: grid; - place-items: center; - border: 1px solid #36363a; - border-radius: 5px; - color: #8c8c94; - font: - 600 10px ui-monospace, - monospace; -} -.message-content time { - justify-self: end; - color: #a1a1aa; - font-size: 12px; - font-weight: 500; -} -.quick-actions { - position: static; - display: flex; - justify-content: flex-end; - align-items: center; - visibility: hidden; -} -.message-row:hover .quick-actions { - visibility: visible; -} -.message-context-menu { - position: fixed; - z-index: 120; - width: 216px; - padding: 6px; -} -.message-context-menu .ui-menu-item { - width: 100%; -} -.message-context-menu .danger { - color: #fca5a5; -} -.empty-state { - height: 280px; - display: grid; - place-content: center; - justify-items: center; - gap: 12px; - color: var(--faint); -} -.mail-state { - height: calc(100% - 104px); - display: grid; - place-content: center; - justify-items: center; - gap: 12px; - padding: 24px; - color: var(--faint); - text-align: center; -} -.mail-state strong { - color: var(--text); -} -.partial-banner { - min-height: 32px; - display: flex; - align-items: center; - padding: 6px 14px; - border-bottom: 1px solid #422006; - background: #1c1205; - color: #fbbf24; - font-size: 12px; -} -.loading-spinner { - width: 24px; - height: 24px; - border: 2px solid var(--border-strong); - border-top-color: white; - border-radius: 50%; - animation: spin 800ms linear infinite; -} -@keyframes spin { - to { - transform: rotate(360deg); + .ui-popover, + .ui-menu { + z-index: 80; + overflow: hidden; + border: 1px solid var(--border-strong); + border-radius: var(--radius-lg); + background: var(--surface-overlay); + box-shadow: var(--shadow-overlay); + color: var(--text); + transform-origin: top right; + transition: + opacity 160ms var(--ease-out), + transform 160ms var(--ease-out); + @starting-style { + opacity: 0; + transform: translateY(-4px) scale(0.98); + } + } + .ui-menu { + min-width: 220px; + padding: 6px; + } + .ui-menu-item { + width: 100%; + min-height: 36px; + display: flex; + align-items: center; + gap: 10px; + padding: 0 10px; + border: 0; + border-radius: var(--radius-sm); + background: transparent; + color: var(--text); + text-align: left; + cursor: default; + @apply text-[13px] leading-[1.2]; + transition: + background-color var(--duration-fast) ease, + color var(--duration-fast) ease, + transform var(--duration-fast) var(--ease-out); + } + .ui-menu-item > svg { + @apply shrink-0; + } + .ui-menu-item > span:not(.menu-check):not(.provider-icon):not(.online-dot):not(.offline-dot) { + @apply min-w-0 truncate; + } + .ui-menu-item:hover, + .ui-menu-item:focus-visible, + .ui-menu-item[data-highlighted="true"] { + outline: 0; + background: var(--active); + } + .ui-menu-item:disabled, + .ui-menu-item[aria-disabled="true"] { + color: var(--faint); + pointer-events: none; + } + .ui-menu-item.danger { + color: #fca5a5; + } + .ui-menu-separator { + height: 1px; + margin: 6px -6px; + background: var(--border); + } + .ui-field { + min-width: 0; + min-height: 40px; + border: 1px solid var(--border-strong); + border-radius: var(--radius); + background: var(--surface-subtle); + color: var(--text); + } + .ui-field:hover { + border-color: var(--border-hover); + } + .ui-field:focus-within { + border-color: var(--focus); + box-shadow: 0 0 0 1px var(--focus); + } + .ui-notice, + .ui-empty-state { + border: 1px solid var(--border); + border-radius: var(--radius); + background: var(--surface-subtle); } -} -@media (prefers-reduced-motion: reduce) { - .loading-spinner { - animation: none; - border-top-color: var(--border-strong); + + .app-shell { + height: 100dvh; + min-width: 0; + display: grid; + grid-template-rows: var(--topbar-height) minmax(0, 1fr); + overflow: hidden; + background: var(--background); } -} -.context-rail { - min-width: 0; - min-height: 0; - display: flex; - flex-direction: column; - align-items: center; - gap: 8px; - padding-top: 6px; - border: 1px solid var(--border); - border-left: 0; - border-radius: 0 9px 9px 0; - background: #070707; -} -.rail-spacer { - flex: 1; -} -.conversation { - height: 100%; - overflow-y: auto; -} -.conversation-toolbar { - height: 48px; - display: flex; - align-items: center; - gap: 2px; - padding: 0 12px; - border-bottom: 1px solid var(--border); -} -.conversation-heading { - display: flex; - align-items: center; - justify-content: space-between; - gap: 16px; - padding: 26px 32px 18px 58px; -} -.conversation-heading > div { - display: flex; - align-items: center; - gap: 10px; -} -.conversation-heading h1 { - margin: 0; - color: white; - font-size: 23px; - letter-spacing: -0.02em; -} -.thread-label, -.provider-pill { - padding: 4px 8px; - border: 1px solid #36363a; - border-radius: 5px; - color: #a1a1aa; - font-size: 12px; -} -.sender-avatar { - width: 40px; - height: 40px; - display: grid; - place-items: center; - border-radius: 50%; - background: white; - color: black; - font-weight: 700; -} -.attachment-card { - display: flex; - align-items: center; - gap: 12px; - margin: 20px 0; - padding: 12px 18px; - border: 1px solid #36363a; - border-radius: 8px; - background: #111; - color: #e4e4e7; - text-align: left; -} -.attachment-card span { - display: grid; - min-width: 0; - flex: 1; - gap: 3px; -} -.attachment-card small { - color: #85858d; -} -.reply-actions { - display: flex; - gap: 8px; - margin-top: 28px; -} -.conversation-messages { - display: grid; - gap: 0; - padding: 0 32px 40px; -} -.conversation-messages > .mail-state { - height: 260px; -} -.conversation-messages > .h-9 { - justify-self: center; -} -.mail-body-card { - display: block; - padding: 0; - overflow: hidden; - border: 0; - border-top: 1px solid var(--border); - border-radius: 0; - background: transparent; -} -.message-summary { - width: 100%; - min-height: 68px; - display: grid; - grid-template-columns: 40px minmax(0, 1fr) auto 20px; - align-items: center; - gap: 12px; - padding: 12px 16px; - border: 0; - background: transparent; - text-align: left; - cursor: pointer; -} -.message-summary:hover { - background: var(--hover); -} -.message-summary-copy { - min-width: 0; - display: grid; - gap: 4px; -} -.message-summary-copy strong, -.message-summary-copy small { - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} -.message-summary-copy small, -.message-summary time, -.message-addresses { - color: var(--muted); - font-size: 12px; -} -.mail-message-content { - display: grid; - gap: 16px; - padding: 0 16px 20px 68px; - border-top: 1px solid var(--border); -} -.message-addresses { - display: grid; - gap: 3px; - padding-top: 14px; -} -.safe-mail-frame { - width: 100%; - min-height: 300px; - border: 0; - background: #fff; -} -.plain-mail-body { - margin: 0; - color: var(--text); - font: - 14px / 1.65 "Geist", - "Inter", - sans-serif; - white-space: pre-wrap; - overflow-wrap: anywhere; -} -.conversation-attachments { - display: flex; - flex-wrap: wrap; - gap: 8px; - margin: 0; - padding: 0; - list-style: none; -} -.conversation-attachments .attachment-card { - margin: 0; -} -@media (max-width: 620px) { - .conversation-heading { - align-items: flex-start; - flex-direction: column; - padding: 20px 14px; + .topbar { + display: grid; + grid-template-columns: var(--sidebar-width) minmax(320px, 720px) minmax(0, 1fr); + align-items: center; + gap: 20px; + padding: 0 14px; + border-bottom: 1px solid var(--border); + background: var(--background); } - .conversation-heading h1 { - font-size: 19px; + .topbar-start, + .topbar-actions, + .toolbar-group { + display: flex; + align-items: center; } - .conversation-messages { - padding: 0 8px 24px; + .topbar-start { + gap: 8px; } - .message-summary { - grid-template-columns: 34px minmax(0, 1fr) 18px; - gap: 9px; - padding-inline: 10px; + .brand { + display: flex; + align-items: center; + gap: 10px; + font-size: 20px; + font-weight: 600; + letter-spacing: -0.04em; + } + .brand-mark { + position: relative; + width: 25px; + height: 21px; + border: 2px solid white; + border-radius: 5px; + overflow: hidden; + } + .brand-mark span { + position: absolute; + top: 5px; + width: 17px; + height: 2px; + background: white; + } + .brand-mark span:first-child { + left: -2px; + transform: rotate(36deg); + } + .brand-mark span:last-child { + right: -2px; + transform: rotate(-36deg); + } + .search-box { + position: relative; + height: 44px; + display: grid; + grid-template-columns: auto 1fr auto auto auto; + align-items: center; + gap: 10px; + padding: 0 4px 0 15px; + background: #111; + border: 1px solid var(--border); + border-radius: 9px; + color: var(--muted); + } + .search-help { + position: absolute; + z-index: 40; + top: calc(100% + 7px); + right: 0; + width: min(360px, 90vw); + display: flex; + flex-wrap: wrap; + gap: 6px; + padding: 10px; + border: 1px solid var(--border-strong); + border-radius: 8px; + background: #0a0a0a; + box-shadow: 0 12px 30px rgb(0 0 0 / 45%); + } + .search-help legend { + position: absolute; + width: 1px; + height: 1px; + overflow: hidden; + clip-path: inset(50%); + white-space: nowrap; + } + .search-help button { + padding: 5px 8px; + border: 1px solid var(--border); + border-radius: 5px; + background: #111; + color: #d4d4d8; + font: + 12px ui-monospace, + SFMono-Regular, + Menlo, + monospace; + cursor: pointer; + } + .search-help button:hover, + .search-help button:focus-visible { + border-color: #71717a; + color: white; + } + .search-box:focus-within { + border-color: #52525b; + box-shadow: 0 0 0 1px #52525b; + } + .search-box input { + min-width: 0; + background: transparent; + border: 0; + color: var(--text); + outline: 0; + font-size: 14px; + } + .search-results-heading { + padding: 10px 18px; + border-bottom: 1px solid var(--border); + color: #d4d4d8; + font-size: 13px; + font-weight: 600; + } + .search-error { + padding: 9px 18px; + border-bottom: 1px solid #7f1d1d; + background: #1c0909; + color: #fca5a5; + font-size: 13px; + } + .action-notice { + padding: 8px 18px; + border-bottom: 1px solid #365314; + background: #0d1608; + color: #bef264; + font-size: 13px; + } + .action-notice.error { + border-bottom-color: #7f1d1d; + background: #1c0909; + color: #fca5a5; + } + .search-box kbd { + min-width: 24px; + padding: 3px 7px; + border: 1px solid #3f3f46; + border-radius: 5px; + background: #090909; + color: #8d8d95; + text-align: center; + font-size: 12px; + } + .topbar-actions { + justify-content: flex-end; + gap: 2px; + } + .sync-dot, + .online-dot, + .offline-dot { + width: 7px; + height: 7px; + border-radius: 50%; + background: var(--success); + box-shadow: 0 0 0 3px rgb(34 197 94 / 10%); + } + .offline-dot { + width: 7px; + height: 7px; + border-radius: 50%; + background: var(--danger); + box-shadow: 0 0 0 3px rgb(239 68 68 / 10%); + } + .topbar-actions .sync-dot { + margin: 0 10px; + } + .locale-button { + @apply min-w-18 justify-center gap-1.5 text-zinc-400; + } + .locale-menu-anchor { + @apply relative; } - .message-summary .sender-avatar { + .locale-popover { + @apply absolute top-[calc(100%+10px)] right-0 w-46; + } + .locale-option { + @apply grid grid-cols-[32px_minmax(0,1fr)_16px]; + } + .locale-code { + @apply font-mono text-[11px] font-semibold text-zinc-400; + } + .menu-check { + @apply text-right text-zinc-100; + } + .avatar { width: 34px; height: 34px; + margin-left: 8px; + border: 1px solid #52525b; + border-radius: 50%; + background: white; + color: #000; + font-weight: 700; + } + .account-menu-anchor { + position: relative; + } + .account-popover { + @apply absolute top-[calc(100%+10px)] right-0 z-80 w-[min(304px,calc(100vw-24px))] p-1.5; + } + .account-popover header { + @apply flex items-center justify-between px-[9px] pt-[7px] pb-[9px] text-[13px] font-semibold text-zinc-100; + } + .account-popover header small, + .account-option small { + color: var(--muted); } - .message-summary time { + .account-option > span:nth-child(2) { + min-width: 0; + display: grid; + text-align: left; + } + .account-option strong, + .account-option small { + @apply truncate; + } + .app-body { + @apply grid min-h-0 grid-cols-[var(--sidebar-width)_minmax(0,1fr)] gap-0 overflow-hidden pr-3 pb-3; + } + .app-body.sidebar-is-collapsed { + @apply grid-cols-[var(--sidebar-collapsed-width)_minmax(0,1fr)]; + } + .sidebar { + min-width: 0; + width: 100%; + overflow-x: hidden; + overflow-y: auto; + overscroll-behavior: contain; + padding: 14px 12px 18px; + transition: padding var(--duration-fast) var(--ease-out); + } + .sidebar.collapsed { + padding-inline: 8px; + } + .sidebar.collapsed .compose-button { + width: 44px; + padding: 0; + } + .sidebar.collapsed .compose-button span, + .sidebar.collapsed .nav-item span:not(.label-dot):not(.provider-icon), + .sidebar.collapsed .nav-item strong, + .sidebar.collapsed .sidebar-section-title, + .sidebar.collapsed .accounts { display: none; } - .mail-message-content { - padding: 0 10px 16px; + .sidebar.collapsed .labels, + .sidebar.collapsed .secondary-mailboxes { + @apply hidden; } -} -.compose-panel { - position: fixed; - z-index: 20; - right: 68px; - bottom: 18px; - width: min(560px, calc(100vw - 32px)); - height: 520px; - display: grid; - grid-template-rows: 44px auto auto minmax(0, 1fr) 54px; - overflow: hidden; - border: 1px solid #3f3f46; - border-radius: 9px; - background: #0a0a0a; - box-shadow: 0 24px 80px rgb(0 0 0 / 70%); -} -.compose-panel.minimized { - width: min(360px, calc(100vw - 32px)); - height: 44px; - grid-template-rows: 44px; -} -.compose-panel.maximized { - inset: 7vh 8vw; - width: auto; - height: auto; -} -.compose-panel > header, -.compose-panel > footer { - display: flex; - align-items: center; - justify-content: space-between; - padding: 0 8px 0 15px; - background: #151515; -} -.compose-panel > footer { - min-height: 54px; - order: 2; -} -.compose-panel > header > div, -.compose-panel > footer > div { - display: flex; -} -.compose-panel > footer .bg-white { - color: #000; -} -.compose-panel > header strong { - font-size: 13px; -} -.draft-status { - min-width: 0; - margin-left: auto; - color: #a1a1aa; - font-size: 11px; -} -.draft-status.conflict, -.draft-status.ambiguous { - color: #fbbf24; -} -.compose-field { - display: flex; - align-items: center; - gap: 8px; - padding: 0 14px; - border-bottom: 1px solid var(--border); - color: #a1a1aa; - font-size: 13px; -} -.compose-field input { - min-width: 0; - flex: 1; - height: 100%; - border: 0; - outline: 0; - background: transparent; - color: white; -} -.compose-field button { - border: 0; - background: transparent; - color: #a1a1aa; -} -.compose-copies { - display: grid; - grid-template-columns: 1fr 1fr; -} -.compose-editor-shell { - position: relative; - min-height: 0; - overflow-y: auto; -} -.compose-editor { - min-height: 100%; - padding: 18px 14px; - outline: 0; - background: #0a0a0a; - color: #ededed; - font-size: 14px; - line-height: 1.6; -} -.compose-editor p { - margin: 0 0 0.75em; -} -.compose-placeholder { - position: absolute; - top: 18px; - left: 14px; - color: #71717a; - pointer-events: none; - font-size: 14px; -} -.compose-format { - display: flex; - margin-left: 6px; -} -.compose-file-input { - position: absolute; - width: 1px; - height: 1px; - overflow: hidden; - clip-path: inset(50%); -} -.compose-attachments { - order: 1; - display: flex; - gap: 8px; - margin: 0; - padding: 8px 12px; - overflow-x: auto; - border-top: 1px solid var(--border); - list-style: none; -} -.compose-attachments li { - min-width: 180px; - display: grid; - grid-template-columns: minmax(0, 1fr) auto; - align-items: center; - gap: 2px 8px; - padding: 5px 7px 5px 10px; - border: 1px solid var(--border-strong); - border-radius: 6px; - background: #111; -} -.compose-attachments span, -.compose-attachments small { - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} -.compose-attachments small, -.compose-attachments progress { - grid-column: 1; - color: var(--muted); - font-size: 10px; -} -.compose-attachments button { - grid-column: 2; - grid-row: 1 / span 2; -} -.admin-shell { - min-height: 100vh; - display: grid; - grid-template-columns: 240px 1fr; - grid-template-rows: 64px 1fr; - overflow: auto; - background: #000; - color: var(--text); -} - -.settings-shell { - min-height: 100dvh; - background: - radial-gradient(circle at 50% -20%, rgb(255 255 255 / 5%), transparent 38%), var(--background); -} - -.settings-content { - width: min(1040px, calc(100% - 40px)); - margin: 0 auto; - padding: 48px 0 72px; -} - -.settings-heading { - display: flex; - align-items: end; - justify-content: space-between; - gap: 24px; - padding: 24px; - border: 1px solid var(--border); - border-radius: calc(var(--radius) + 3px); - background: var(--surface-raised); -} - -.settings-actions { - display: flex; - flex-wrap: wrap; - gap: 8px; -} - -.settings-heading span, -.account-list small { - color: var(--muted-foreground); -} - -.settings-heading h1 { - margin: 6px 0; - font-size: 28px; -} - -.settings-heading p { - margin: 0; - color: var(--muted-foreground); -} - -.settings-heading button.bg-white { - color: #000; -} - -.settings-notice { - display: flex; - align-items: center; - gap: 10px; - margin: 20px 0; - padding: 12px 14px; - border: 1px solid var(--border); - border-radius: calc(var(--radius) + 2px); - background: var(--surface-subtle); -} - -.settings-notice a { - margin-left: auto; - color: inherit; -} - -.native-notification-settings { - display: grid; - grid-template-columns: minmax(0, 1fr) auto auto; - align-items: center; - gap: 16px; - margin: 20px 0; - padding: 16px; - border: 1px solid var(--border); - border-radius: calc(var(--radius) + 2px); - background: var(--surface-subtle); -} - -.native-notification-settings > div, -.native-notification-settings > label { - display: flex; - align-items: center; - gap: 10px; -} - -.native-notification-settings > label { - color: var(--muted-foreground); -} - -.native-notification-settings select { - min-height: 36px; - padding: 0 32px 0 10px; - color: var(--foreground); - background: var(--background); - border: 1px solid var(--border); - border-radius: var(--radius); -} - -.native-notification-settings p { - grid-column: 1 / -1; - margin: 0; - color: var(--destructive); -} - -@media (max-width: 880px) { - .native-notification-settings { - grid-template-columns: 1fr; + .compose-button { + width: 100%; + max-width: 172px; + height: 44px; + justify-content: flex-start; + margin-bottom: 14px; + padding-left: 16px; + color: #000; + transition: + max-width var(--duration-fast) var(--ease-out), + padding var(--duration-fast) var(--ease-out), + transform var(--duration-fast) var(--ease-out); + } + .nav-list { + display: grid; + gap: 2px; + } + .nav-item { + width: 100%; + min-height: 38px; + display: grid; + grid-template-columns: 22px 1fr auto; + align-items: center; + gap: 9px; + padding: 0 10px; + border: 0; + border-radius: 7px; + background: transparent; + color: #b9b9bf; + text-align: left; + font-size: 14px; + cursor: pointer; + } + .nav-item:hover { + background: #111; + color: white; + } + .nav-item:disabled { + @apply cursor-default text-zinc-600; + } + .nav-item:disabled:hover { + @apply bg-transparent; + } + .nav-item.active { + background: #1d1d1f; + color: white; + box-shadow: inset 2px 0 white; + } + .nav-item strong { + color: #d4d4d8; + font-size: 12px; + font-weight: 600; + } + .sidebar-section-title { + height: 44px; + display: flex; + align-items: center; + justify-content: space-between; + margin-top: 16px; + padding: 0 10px; + color: #f4f4f5; + font-size: 14px; + font-weight: 600; + } + .label-tree-row { + display: grid; + grid-template-columns: 20px minmax(0, 1fr); + align-items: center; + padding-left: calc(var(--label-depth) * 16px); + } + .label-disclosure, + .label-disclosure-spacer { + width: 20px; + height: 32px; + display: grid; + place-items: center; + } + .label-disclosure { + padding: 0; + border: 0; + background: transparent; + color: var(--muted); + cursor: pointer; + } + .label-disclosure[aria-expanded="true"] svg { + transform: rotate(90deg); + } + .label-disclosure svg, + .more-toggle svg { + transition: transform 160ms var(--ease-out); + } + .more-toggle[aria-expanded="true"] svg { + transform: rotate(90deg); + } + .secondary-mailboxes { + @apply grid gap-0.5 pl-[18px]; + } + .label-item { + grid-template-columns: 20px minmax(0, 1fr) auto; + padding-left: 4px; + } + .label-item:disabled { + opacity: 1; + cursor: default; + } + .label-dot { + width: 13px; + height: 10px; + border-radius: 3px 5px 5px 3px; + background: #71717a; + } + .label-dot.violet { + background: #a78bfa; + } + .label-dot.amber { + background: #f59e0b; + } + .label-dot.blue { + background: #60a5fa; + } + .provider-icon { + width: 19px; + height: 19px; + display: grid; + place-items: center; + border: 1px solid #52525b; + border-radius: 5px; + color: white; + font-size: 11px; + font-weight: 700; + } + .accounts .online-dot { + justify-self: end; + width: 6px; + height: 6px; + } + .mail-surface { + min-width: 0; + min-height: 0; + overflow: hidden; + background: var(--surface); + border: 1px solid var(--border); + @apply rounded-[9px]; + } + .mail-toolbar { + height: 48px; + display: flex; + align-items: center; + justify-content: space-between; + padding: 0 12px; + border-bottom: 1px solid var(--border); + } + .toolbar-group { + gap: 3px; + color: var(--muted); + } + .range-controls { + gap: 2px; + font-size: 12px; + } + .range-controls > span { + margin-right: 8px; + } + .select-box { + width: 18px; + height: 18px; + display: grid; + place-items: center; + flex: 0 0 auto; + padding: 0; + border: 1px solid #52525b; + border-radius: 3px; + background: transparent; + color: #000; + font-size: 12px; + cursor: pointer; + } + .select-box.checked { + border-color: white; + background: white; + } + .category-tabs { + height: 56px; + display: grid; + grid-template-columns: repeat(5, minmax(120px, 1fr)); + border-bottom: 1px solid var(--border); + overflow-x: auto; + } + .category-tab { + position: relative; + min-width: 120px; + display: flex; + align-items: center; + gap: 9px; + padding: 0 18px; + border: 0; + background: transparent; + color: var(--muted); + cursor: pointer; + font-size: 14px; + } + .category-tab:hover { + background: #111; + color: white; + } + .category-tab.active { + color: white; + } + .category-tab.active::after { + content: ""; + position: absolute; + right: 12px; + bottom: 0; + left: 12px; + height: 2px; + background: white; + } + .category-tab strong { + padding: 2px 6px; + border-radius: 999px; + background: white; + color: black; + font-size: 11px; + } + .message-list { + height: calc(100% - 104px); + overflow-y: auto; + } + .virtual-message-list { + position: relative; + width: 100%; + } + .virtual-message-row { + position: absolute; + top: 0; + left: 0; + width: 100%; + } + .message-row { + position: relative; + min-height: 45px; + display: grid; + @apply grid-cols-[22px_24px_24px_minmax(0,1fr)]; + align-items: center; + gap: 5px; + padding: 0 12px; + border-bottom: 1px solid #202022; + color: #b7b7bd; + } + .message-row:hover { + background: var(--hover); + color: #e4e4e7; + } + .message-row.selected { + background: #1e1e20; + } + .message-row.unread { + background: #111; + color: var(--text); + } + .message-row.unread:hover { + background: #191919; + } + .row-icon { + width: 24px; + height: 36px; + display: grid; + place-items: center; + padding: 0; + border: 0; + background: transparent; + color: #626269; + cursor: pointer; + } + .row-icon:hover { + color: white; + } + .row-icon.starred { + color: white; + } + .row-icon.important { + transform: rotate(90deg); + } + .message-content { + min-width: 0; + min-height: 44px; + display: grid; + @apply grid-cols-[minmax(140px,200px)_minmax(0,1fr)_auto_24px_64px]; + align-items: center; + gap: 10px; + padding: 0; + border: 0; + background: transparent; + color: inherit; + text-align: left; + cursor: pointer; + } + .sender, + .subject-line { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + .sender { + color: inherit; + font-size: 14px; + } + .subject-line { + font-size: 14px; + } + .subject-line strong { + color: inherit; + font-weight: 500; + } + .subject-line span { + color: #85858d; + } + .unread .sender, + .unread .subject-line strong { + font-weight: 650; + } + .attachment-chip { + display: flex; + align-items: center; + gap: 4px; + max-width: 180px; + overflow: hidden; + padding: 4px 8px; + border: 1px solid #36363a; + border-radius: 999px; + color: #a1a1aa; + font-size: 12px; + text-overflow: ellipsis; + white-space: nowrap; + } + .provider-badge { + width: 20px; + height: 20px; + display: grid; + place-items: center; + border: 1px solid #36363a; + border-radius: 5px; + color: #8c8c94; + font: + 600 10px ui-monospace, + monospace; + } + .message-content time { + justify-self: end; + color: #a1a1aa; + font-size: 12px; + font-weight: 500; + } + .quick-actions { + @apply pointer-events-none absolute top-1 right-2 z-2 flex h-9 translate-x-[3px] items-center justify-end bg-zinc-900 pl-2 opacity-0; + transition: + opacity 120ms ease, + transform 140ms var(--ease-out); + } + .message-row:hover .quick-actions, + .message-row:focus-within .quick-actions { + @apply pointer-events-auto translate-x-0 opacity-100; + } + .message-context-menu { + @apply fixed z-120 w-[204px] p-[5px]; + transform-origin: top left; + } + .message-context-menu .ui-menu-item { + @apply min-h-[34px] w-full px-[9px]; + } + .message-context-menu .danger { + color: #fca5a5; + } + .empty-state { + height: 280px; + display: grid; + place-content: center; + justify-items: center; + gap: 12px; + color: var(--faint); + } + .mail-state { + height: calc(100% - 104px); + display: grid; + place-content: center; + justify-items: center; + gap: 12px; + padding: 24px; + color: var(--faint); + text-align: center; + } + .mail-state strong { + color: var(--text); + } + .partial-banner { + min-height: 32px; + display: flex; + align-items: center; + padding: 6px 14px; + border-bottom: 1px solid #422006; + background: #1c1205; + color: #fbbf24; + font-size: 12px; + } + .loading-spinner { + width: 24px; + height: 24px; + border: 2px solid var(--border-strong); + border-top-color: white; + border-radius: 50%; + animation: spin 800ms linear infinite; + } + @keyframes spin { + to { + transform: rotate(360deg); + } + } + @media (prefers-reduced-motion: reduce) { + .loading-spinner { + animation: none; + border-top-color: var(--border-strong); + } + } + .conversation { + height: 100%; + overflow-y: auto; + } + .conversation-toolbar { + height: 48px; + display: flex; + align-items: center; + gap: 2px; + padding: 0 12px; + border-bottom: 1px solid var(--border); + } + .conversation-heading { + display: flex; + align-items: center; + justify-content: space-between; + gap: 16px; + padding: 26px 32px 18px 58px; + } + .conversation-heading > div { + display: flex; + align-items: center; + gap: 10px; + } + .conversation-heading h1 { + margin: 0; + color: white; + font-size: 23px; + letter-spacing: -0.02em; + } + .thread-label, + .provider-pill { + padding: 4px 8px; + border: 1px solid #36363a; + border-radius: 5px; + color: #a1a1aa; + font-size: 12px; + } + .sender-avatar { + width: 40px; + height: 40px; + display: grid; + place-items: center; + border-radius: 50%; + background: white; + color: black; + font-weight: 700; + } + .attachment-card { + display: flex; + align-items: center; + gap: 12px; + margin: 20px 0; + padding: 12px 18px; + border: 1px solid #36363a; + border-radius: 8px; + background: #111; + color: #e4e4e7; + text-align: left; + } + .attachment-card span { + display: grid; + min-width: 0; + flex: 1; + gap: 3px; + } + .attachment-card small { + color: #85858d; + } + .reply-actions { + display: flex; + gap: 8px; + margin-top: 28px; + } + .conversation-messages { + display: grid; + gap: 0; + padding: 0 32px 40px; + } + .conversation-messages > .mail-state { + height: 260px; + } + .conversation-messages > .h-9 { + justify-self: center; + } + .mail-body-card { + display: block; + padding: 0; + overflow: hidden; + border: 0; + border-top: 1px solid var(--border); + border-radius: 0; + background: transparent; + } + .message-summary { + width: 100%; + min-height: 68px; + display: grid; + grid-template-columns: 40px minmax(0, 1fr) auto 20px; + align-items: center; + gap: 12px; + padding: 12px 16px; + border: 0; + background: transparent; + text-align: left; + cursor: pointer; + } + .message-summary:hover { + background: var(--hover); + } + .message-summary-copy { + min-width: 0; + display: grid; + gap: 4px; + } + .message-summary-copy strong, + .message-summary-copy small { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + .message-summary-copy small, + .message-summary time, + .message-addresses { + color: var(--muted); + font-size: 12px; + } + .mail-message-content { + display: grid; + gap: 16px; + padding: 0 16px 20px 68px; + border-top: 1px solid var(--border); + } + .message-addresses { + display: grid; + gap: 3px; + padding-top: 14px; + } + .safe-mail-frame { + width: 100%; + min-height: 300px; + border: 0; + background: #fff; + } + .plain-mail-body { + margin: 0; + color: var(--text); + font: + 14px / 1.65 "Geist", + "Inter", + sans-serif; + white-space: pre-wrap; + overflow-wrap: anywhere; + } + .conversation-attachments { + display: flex; + flex-wrap: wrap; + gap: 8px; + margin: 0; + padding: 0; + list-style: none; + } + .conversation-attachments .attachment-card { + margin: 0; + } + @media (max-width: 620px) { + .conversation-heading { + align-items: flex-start; + flex-direction: column; + padding: 20px 14px; + } + .conversation-heading h1 { + font-size: 19px; + } + .conversation-messages { + padding: 0 8px 24px; + } + .message-summary { + grid-template-columns: 34px minmax(0, 1fr) 18px; + gap: 9px; + padding-inline: 10px; + } + .message-summary .sender-avatar { + width: 34px; + height: 34px; + } + .message-summary time { + display: none; + } + .mail-message-content { + padding: 0 10px 16px; + } + } + .compose-panel { + position: fixed; + z-index: 20; + right: 68px; + bottom: 18px; + width: min(560px, calc(100vw - 32px)); + height: 520px; + display: grid; + grid-template-rows: 44px auto auto minmax(0, 1fr) 54px; + overflow: hidden; + border: 1px solid #3f3f46; + border-radius: 9px; + background: #0a0a0a; + box-shadow: 0 24px 80px rgb(0 0 0 / 70%); + } + .compose-panel.minimized { + width: min(360px, calc(100vw - 32px)); + height: 44px; + grid-template-rows: 44px; + } + .compose-panel.maximized { + inset: 7vh 8vw; + width: auto; + height: auto; + } + .compose-panel > header, + .compose-panel > footer { + display: flex; + align-items: center; + justify-content: space-between; + padding: 0 8px 0 15px; + background: #151515; + } + .compose-panel > footer { + min-height: 54px; + order: 2; + } + .compose-panel > header > div, + .compose-panel > footer > div { + display: flex; + } + .compose-panel > footer .bg-white { + color: #000; + } + .compose-panel > header strong { + font-size: 13px; + } + .draft-status { + min-width: 0; + margin-left: auto; + color: #a1a1aa; + font-size: 11px; + } + .draft-status.conflict, + .draft-status.ambiguous { + color: #fbbf24; + } + .compose-field { + display: flex; + align-items: center; + gap: 8px; + padding: 0 14px; + border-bottom: 1px solid var(--border); + color: #a1a1aa; + font-size: 13px; + } + .compose-field input { + min-width: 0; + flex: 1; + height: 100%; + border: 0; + outline: 0; + background: transparent; + color: white; + } + .compose-field button { + border: 0; + background: transparent; + color: #a1a1aa; + } + .compose-copies { + display: grid; + grid-template-columns: 1fr 1fr; + } + .compose-editor-shell { + position: relative; + min-height: 0; + overflow-y: auto; + } + .compose-editor { + min-height: 100%; + padding: 18px 14px; + outline: 0; + background: #0a0a0a; + color: #ededed; + font-size: 14px; + line-height: 1.6; + } + .compose-editor p { + margin: 0 0 0.75em; + } + .compose-placeholder { + position: absolute; + top: 18px; + left: 14px; + color: #71717a; + pointer-events: none; + font-size: 14px; + } + .compose-format { + display: flex; + margin-left: 6px; + } + .compose-file-input { + position: absolute; + width: 1px; + height: 1px; + overflow: hidden; + clip-path: inset(50%); + } + .compose-attachments { + order: 1; + display: flex; + gap: 8px; + margin: 0; + padding: 8px 12px; + overflow-x: auto; + border-top: 1px solid var(--border); + list-style: none; + } + .compose-attachments li { + min-width: 180px; + display: grid; + grid-template-columns: minmax(0, 1fr) auto; + align-items: center; + gap: 2px 8px; + padding: 5px 7px 5px 10px; + border: 1px solid var(--border-strong); + border-radius: 6px; + background: #111; + } + .compose-attachments span, + .compose-attachments small { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + .compose-attachments small, + .compose-attachments progress { + grid-column: 1; + color: var(--muted); + font-size: 10px; + } + .compose-attachments button { + grid-column: 2; + grid-row: 1 / span 2; + } + .admin-shell { + min-height: 100vh; + display: grid; + grid-template-columns: 240px 1fr; + grid-template-rows: 64px 1fr; + overflow: auto; + background: #000; + color: var(--text); } -} - -.imap-form { - display: grid; - grid-template-columns: repeat(3, minmax(0, 1fr)); - gap: 16px; - margin-top: 24px; - padding: 20px; - border: 1px solid var(--border); - border-radius: var(--radius); -} - -.imap-form-heading, -.imap-form fieldset, -.icloud-preset-note, -.imap-security-note, -.imap-form > .settings-actions, -.imap-form > .settings-notice { - grid-column: 1 / -1; -} - -.imap-form-heading { - display: flex; - justify-content: space-between; - gap: 16px; -} -.imap-form-heading h2 { - margin: 0 0 6px; -} -.imap-form-heading p, -.imap-security-note { - margin: 0; - color: var(--muted-foreground); -} - -.icloud-preset-note { - display: grid; - gap: 6px; - padding: 14px; - color: var(--muted-foreground); - font-size: 13px; - border: 1px solid var(--border); - border-radius: var(--radius); -} - -.icloud-preset-note strong { - color: var(--foreground); -} - -.icloud-preset-note a { - width: fit-content; - color: var(--foreground); - text-decoration: underline; - text-underline-offset: 3px; -} -.imap-form label { - display: flex; - flex-direction: column; - gap: 7px; - color: var(--muted-foreground); - font-size: 13px; -} -.imap-form input, -.imap-form select { - min-height: 38px; - padding: 0 10px; - color: var(--foreground); - background: var(--background); - border: 1px solid var(--border); - border-radius: var(--radius); -} -.imap-form fieldset { - display: grid; - grid-template-columns: 2fr 1fr 1fr; - gap: 12px; - padding: 14px; - border: 1px solid var(--border); - border-radius: var(--radius); -} -.imap-security-note { - display: flex; - align-items: center; - gap: 8px; -} - -.account-list { - display: grid; - gap: 10px; - margin-top: 20px; -} -.account-list article { - display: grid; - grid-template-columns: auto 1fr auto auto; - align-items: center; - gap: 14px; - padding: 16px; - border: 1px solid var(--border); - border-radius: calc(var(--radius) + 2px); - background: var(--surface-subtle); -} + .settings-shell { + min-height: 100dvh; + background: + radial-gradient(circle at 50% -20%, rgb(255 255 255 / 5%), transparent 38%), var(--background); + } -.account-list article div { - display: flex; - flex-direction: column; - gap: 4px; -} + .settings-content { + width: min(1040px, calc(100% - 40px)); + margin: 0 auto; + padding: 48px 0 72px; + } -@media (max-width: 700px) { .settings-heading { - align-items: stretch; - flex-direction: column; - } - .account-list article { - grid-template-columns: auto 1fr; - } - .account-list article button { - grid-column: span 2; + display: flex; + align-items: end; + justify-content: space-between; + gap: 24px; + padding: 24px; + border: 1px solid var(--border); + border-radius: calc(var(--radius) + 3px); + background: var(--surface-raised); } - .imap-form, - .imap-form fieldset { - grid-template-columns: 1fr; + + .settings-actions { + display: flex; + flex-wrap: wrap; + gap: 8px; } -} -.admin-header { - grid-column: 1 / -1; - display: flex; - align-items: center; - justify-content: space-between; - padding: 0 22px; - border-bottom: 1px solid var(--border); -} -.admin-sidebar { - padding: 30px 14px; - border-right: 1px solid var(--border); -} -.admin-sidebar h1 { - margin: 0 12px 22px; - font-size: 15px; -} -.admin-sidebar button { - width: 100%; - height: 38px; - padding: 0 12px; - border: 0; - border-radius: 6px; - background: transparent; - color: #929299; - text-align: left; - font-size: 14px; -} -.admin-sidebar button:hover, -.admin-sidebar button.active { - background: #171717; - color: white; -} -.admin-content { - min-width: 0; - width: 100%; - max-width: 1500px; - padding: 36px; -} -.admin-title { - display: flex; - align-items: flex-end; - justify-content: space-between; - margin-bottom: 28px; -} -.admin-title span { - color: #85858d; - font-size: 13px; -} -.admin-title h2 { - margin: 5px 0 0; - font-size: 25px; - letter-spacing: -0.03em; -} -.status-badge { - display: flex; - align-items: center; - gap: 7px; - padding: 7px 10px; - border: 1px solid #234b31; - border-radius: 6px; - color: #86efac; - font-size: 12px; -} -.metric-strip { - display: grid; - grid-template-columns: repeat(4, 1fr); - border: 1px solid var(--border); - border-radius: 8px; -} -.metric-strip article { - display: grid; - gap: 8px; - padding: 18px; - border-right: 1px solid var(--border); -} -.metric-strip article:last-child { - border: 0; -} -.metric-strip span, -.metric-strip small { - color: #83838b; - font-size: 12px; -} -.metric-strip strong { - font-size: 24px; - letter-spacing: -0.03em; -} -.admin-grid { - display: grid; - grid-template-columns: minmax(0, 1.5fr) minmax(320px, 0.8fr); - gap: 16px; - margin-top: 16px; -} -.admin-panel { - border: 1px solid var(--border); - border-radius: 8px; - background: var(--surface-subtle); - box-shadow: var(--shadow-card); -} -.admin-panel > header { - min-height: 50px; - display: flex; - align-items: center; - justify-content: space-between; - padding: 0 16px; - border-bottom: 1px solid var(--border); -} -.chart-panel header div { - display: grid; - gap: 2px; -} -.chart-panel header span { - color: #83838b; - font-size: 12px; -} -.chart-panel select { - border: 1px solid #36363a; - border-radius: 5px; - background: #111; - color: #b8b8c0; - padding: 5px 8px; -} -.chart-panel svg { - width: 100%; - height: 220px; - padding: 20px; - overflow: visible; -} -.grid-line { - fill: none; - stroke: #232326; - stroke-width: 1; -} -.chart-area { - fill: rgba(255, 255, 255, 0.08); - opacity: 0.12; -} -.chart-line { - fill: none; - stroke: white; - stroke-width: 2; -} -.service-table > div { - min-height: 45px; - display: grid; - grid-template-columns: 14px 1fr 80px 90px; - align-items: center; - gap: 8px; - padding: 0 16px; - border-bottom: 1px solid #1f1f21; - font-size: 13px; -} -.service-table > div:last-child { - border: 0; -} -.service-table span:not(.online-dot) { - color: #8f8f97; -} -.service-table code { - justify-self: end; - color: #a1a1aa; -} -.recent-events { - margin-top: 16px; -} -.event-row { - min-height: 44px; - display: grid; - grid-template-columns: 80px 54px 150px 1fr 90px; - align-items: center; - gap: 10px; - padding: 0 16px; - border-bottom: 1px solid #1f1f21; - color: #a1a1aa; - font-size: 12px; -} -.event-row:last-child { - border: 0; -} -.event-row code { - color: #d4d4d8; -} -.event-row small { - text-align: right; -} -.event-level { - width: max-content; - padding: 2px 5px; - border-radius: 4px; - font: - 10px ui-monospace, - monospace; -} -.event-level.info { - color: #93c5fd; - background: #172554; -} -.event-level.warn { - color: #fcd34d; - background: #451a03; -} -.admin-header-actions, -.admin-toolbar, -.admin-translation-actions { - display: flex; - align-items: center; - gap: 10px; -} -.admin-mobile-navigation { - display: none; -} -.admin-page-heading { - display: flex; - align-items: end; - justify-content: space-between; - gap: 20px; - margin-bottom: 24px; -} -.admin-page-heading span, -.admin-panel header span, -.admin-table time, -.admin-list small, -.admin-issue-list small { - color: var(--muted); - font-size: 12px; -} -.admin-page-heading h1 { - margin: 5px 0 0; - font-size: 26px; - letter-spacing: -0.03em; -} -.admin-health { - display: inline-flex; - align-items: center; - width: max-content; - gap: 6px; - padding: 5px 8px; - border: 1px solid var(--border-strong); - border-radius: 6px; - font-size: 12px; -} -.admin-health-healthy { - color: #86efac; - border-color: #234b31; -} -.admin-health-degraded { - color: #fcd34d; - border-color: #713f12; -} -.admin-health-blocked { - color: #fca5a5; - border-color: #7f1d1d; -} -.admin-health-stale { - color: #c4b5fd; - border-color: #4c1d95; -} -.health-dot { - width: 7px; - height: 7px; - border-radius: 50%; - background: #a1a1aa; -} -.health-dot-healthy { - background: #4ade80; -} -.health-dot-degraded { - background: #facc15; -} -.health-dot-blocked { - background: #f87171; -} -.health-dot-stale { - background: #a78bfa; -} -.admin-stat-grid { - display: grid; - grid-template-columns: repeat(4, minmax(0, 1fr)); - gap: 12px; - margin-top: 16px; -} -.admin-stat-grid article { - min-width: 0; - display: grid; - gap: 8px; - padding: 16px; - border: 1px solid var(--border); - border-radius: 8px; - background: #080808; -} -.admin-stat-grid span, -.admin-stat-grid small { - color: var(--muted); - font-size: 12px; -} -.admin-stat-grid strong { - font-size: 22px; - overflow-wrap: anywhere; -} -.admin-list, -.admin-issue-list, -.admin-log-table, -.admin-data-table, -.admin-table { - min-width: 0; -} -.admin-list article, -.admin-issue-list article { - display: grid; - grid-template-columns: auto minmax(0, 1fr) auto auto auto; - align-items: center; - gap: 12px; - min-height: 58px; - padding: 8px 16px; - border-bottom: 1px solid var(--border); -} -.admin-list article:last-child, -.admin-issue-list article:last-child { - border-bottom: 0; -} -.admin-list article > div, -.admin-issue-list article > div { - display: grid; - gap: 4px; -} -.admin-table > div, -.admin-data-table th, -.admin-data-table td, -.admin-log-table > div { - padding: 7px 16px; - border-bottom: 1px solid var(--border); - font-size: 12px; - text-align: left; -} -.admin-table > div, -.admin-log-table > div { - display: grid; - align-items: center; - gap: 12px; - min-height: 44px; -} -.admin-table > div { - grid-template-columns: minmax(180px, 1fr) 120px 180px; -} -.admin-log-table > div { - grid-template-columns: 170px 75px minmax(170px, 1fr) 150px 130px; -} -.admin-table > div:last-child, -.admin-log-table > div:last-child { - border-bottom: 0; -} -.admin-data-table table { - min-width: 680px; - width: 100%; - border-collapse: collapse; -} -.admin-data-table caption { - position: absolute; - width: 1px; - height: 1px; - overflow: hidden; - clip: rect(0 0 0 0); -} -.admin-data-table th { - color: var(--muted); - font-weight: 500; -} -.admin-toolbar { - justify-content: space-between; - flex-wrap: wrap; - margin-bottom: 14px; - padding: 12px; - border: 1px solid var(--border); - border-radius: 8px; - background: #080808; -} -.admin-toolbar label, -.admin-translation-grid label { - display: grid; - gap: 7px; - color: var(--muted); - font-size: 12px; -} -.admin-toolbar select, -.admin-mobile-navigation select, -.admin-translation-grid select, -.admin-translation-grid textarea { - border: 1px solid var(--border-strong); - border-radius: 6px; - background: #0d0d0d; - color: var(--text); -} -.admin-toolbar select, -.admin-mobile-navigation select, -.admin-translation-grid select { - min-height: 34px; - padding: 0 9px; -} -.admin-translation-grid { - display: grid; - grid-template-columns: repeat(2, minmax(0, 1fr)); - gap: 16px; - padding: 18px; - border: 1px solid var(--border); - border-radius: 8px; - background: #080808; -} -.admin-translation-grid label:first-child, -.admin-translation-actions, -.admin-translation-grid > p { - grid-column: 1 / -1; -} -.admin-translation-grid textarea { - min-height: 170px; - resize: vertical; - padding: 10px; -} -.admin-placeholder { - min-height: 240px; - display: grid; - place-items: center; - align-content: center; - gap: 12px; - padding: 24px; - border: 1px dashed var(--border-strong); - border-radius: 8px; - color: var(--muted); - text-align: center; -} -.admin-update-grid { - display: grid; - grid-template-columns: minmax(0, 1.4fr) minmax(280px, 0.6fr); - gap: 16px; -} -.admin-updater-content { - display: grid; - gap: 16px; - padding: 18px; -} -.admin-updater-content dl { - display: grid; - grid-template-columns: repeat(3, minmax(0, 1fr)); - gap: 12px; - margin: 0; -} -.admin-updater-content dl > div, -.admin-update-candidate { - display: grid; - gap: 5px; - min-width: 0; - padding: 12px; - border: 1px solid var(--border); - border-radius: 6px; -} -.admin-updater-content dt, -.admin-update-candidate time { - color: var(--muted); - font-size: 12px; -} -.admin-updater-content dd { - margin: 0; - overflow-wrap: anywhere; -} -.admin-update-candidate p { - margin: 6px 0 0; - color: var(--muted-foreground); - white-space: pre-wrap; -} -.admin-update-progress { - display: grid; - grid-template-columns: minmax(0, 1fr) auto; - align-items: center; - gap: 12px; -} -.admin-update-progress progress { - width: 100%; - accent-color: var(--foreground); -} -.admin-update-actions { - display: flex; - flex-wrap: wrap; - gap: 8px; -} -.admin-settings { - padding-bottom: 18px; -} -.admin-settings h3, -.admin-settings p { - margin: 16px 16px 0; -} -.admin-loading, -.admin-error, -.admin-notice { - margin: 0 0 16px; - padding: 10px 12px; - border: 1px solid var(--border); - border-radius: 6px; -} -.admin-error { - color: #fca5a5; - border-color: #7f1d1d; -} -.admin-notice { - color: #86efac; - border-color: #234b31; -} -.admin-confirm { - position: fixed; - z-index: 100; - inset: 50% auto auto 50%; - width: min(440px, calc(100vw - 32px)); - transform: translate(-50%, -50%); - display: grid; - gap: 14px; - padding: 20px; - border: 1px solid var(--border-strong); - border-radius: 10px; - background: #0a0a0a; - box-shadow: 0 0 0 100vmax rgba(0, 0, 0, 0.72); -} -.admin-confirm p { - margin: 0; - color: var(--muted); - line-height: 1.5; -} -.admin-confirm > div { - display: flex; - justify-content: flex-end; - gap: 8px; -} -.auth-shell { - min-height: 100dvh; - display: grid; - grid-template-rows: 64px 1fr 48px; - overflow-y: auto; - background: radial-gradient(circle at 50% 15%, rgb(255 255 255 / 6%), transparent 34%), #000; -} -.auth-header, -.auth-shell > footer { - position: relative; - z-index: 1; - display: flex; - align-items: center; - justify-content: space-between; - padding: 0 24px; - border-bottom: 1px solid var(--border); - background: rgb(0 0 0 / 88%); -} -.auth-shell > footer { - justify-content: center; - border-top: 1px solid var(--border); - border-bottom: 0; - color: #8f8f97; - font-size: 11px; - letter-spacing: 0.02em; -} -.auth-card, -.auth-state { - position: relative; - z-index: 1; - align-self: center; - justify-self: center; -} -.auth-card { - width: min(440px, calc(100vw - 32px)); - margin: 42px 0; - padding: 30px; - border: 1px solid var(--border-strong); - border-radius: 10px; - background: color-mix(in srgb, var(--surface-raised) 94%, transparent); - backdrop-filter: blur(18px); - box-shadow: 0 24px 80px rgb(0 0 0 / 65%); -} -.auth-card.compact { - width: min(400px, calc(100vw - 32px)); -} -.auth-icon { - width: 42px; - height: 42px; - display: grid; - place-items: center; - margin-bottom: 22px; - border: 1px solid var(--border-strong); - border-radius: 8px; - background: #111; -} -.auth-kicker { - color: #8f8f97; - font: - 11px ui-monospace, - "SFMono-Regular", - monospace; -} -.auth-card h1 { - margin: 8px 0; - color: white; - font-size: 24px; - letter-spacing: -0.035em; -} -.auth-card > p { - margin: 0 0 24px; - color: var(--muted); - font-size: 14px; - line-height: 1.5; -} -.auth-card form, -.auth-card label { - display: grid; -} -.auth-card form { - gap: 16px; -} -.auth-card label { - gap: 7px; - color: #d4d4d8; - font-size: 13px; -} -.auth-card input { - width: 100%; - height: 42px; - padding: 0 12px; - border: 1px solid #353539; - border-radius: 6px; - outline: 0; - background: #0f0f10; - color: white; -} -.auth-card input:focus { - border-color: var(--focus); - box-shadow: 0 0 0 3px var(--focus-ring); -} -.auth-card label small { - color: #8f8f97; - font-size: 11px; -} -.auth-card form > button { - width: 100%; - height: 42px; - margin-top: 4px; -} -.auth-card form > button.bg-white { - color: #000; -} -.auth-error { - margin: 0 !important; - padding: 10px 12px; - border: 1px solid #5d2727; - border-radius: 6px; - background: #210d0d; - color: #fca5a5 !important; - font-size: 12px !important; -} -.auth-state { - display: grid; - justify-items: center; - gap: 16px; - color: var(--muted); - font-size: 13px; -} -.spin { - animation: spin 800ms linear infinite; -} -@keyframes spin { - to { - transform: rotate(360deg); + .settings-heading span, + .account-list small { + color: var(--muted-foreground); } -} -@media (prefers-reduced-motion: reduce) { - .spin { - animation: none; + + .settings-heading h1 { + margin: 6px 0; + font-size: 28px; } -} -@media (max-width: 1199px) { - .topbar { - grid-template-columns: 80px minmax(280px, 1fr) auto; + .settings-heading p { + margin: 0; + color: var(--muted-foreground); } - .brand-name { - display: none; + + .settings-heading button.bg-white { + color: #000; } - .app-body { - grid-template-columns: 64px minmax(0, 1fr); + + .settings-notice { + display: flex; + align-items: center; + gap: 10px; + margin: 20px 0; + padding: 12px 14px; + border: 1px solid var(--border); + border-radius: calc(var(--radius) + 2px); + background: var(--surface-subtle); } - .app-body.sidebar-is-collapsed { - grid-template-columns: 64px minmax(0, 1fr); + + .settings-notice a { + margin-left: auto; + color: inherit; } - .sidebar { - width: 64px; - padding-inline: 8px; + + .native-notification-settings { + display: grid; + grid-template-columns: minmax(0, 1fr) auto auto; + align-items: center; + gap: 16px; + margin: 20px 0; + padding: 16px; + border: 1px solid var(--border); + border-radius: calc(var(--radius) + 2px); + background: var(--surface-subtle); } - .sidebar .compose-button { - width: 44px; - padding: 0; + + .native-notification-settings > div, + .native-notification-settings > label { + display: flex; + align-items: center; + gap: 10px; } - .sidebar .compose-button span, - .sidebar .nav-item span:not(.label-dot):not(.provider-icon), - .sidebar .nav-item strong, - .sidebar .sidebar-section-title, - .sidebar .accounts { - display: none; + + .native-notification-settings > label { + color: var(--muted-foreground); } - .context-rail { - display: none; + + .native-notification-settings select { + min-height: 36px; + padding: 0 32px 0 10px; + color: var(--foreground); + background: var(--background); + border: 1px solid var(--border); + border-radius: var(--radius); } - .mail-surface { - border-radius: 9px; + + .native-notification-settings p { + grid-column: 1 / -1; + margin: 0; + color: var(--destructive); } - .message-content { - grid-template-columns: 150px minmax(180px, 1fr) 24px 64px; + + @media (max-width: 880px) { + .native-notification-settings { + grid-template-columns: 1fr; + } } - .attachment-chip { - display: none; + + .imap-form { + display: grid; + grid-template-columns: repeat(3, minmax(0, 1fr)); + gap: 16px; + margin-top: 24px; + padding: 20px; + border: 1px solid var(--border); + border-radius: var(--radius); } -} -@media (max-width: 900px) { - .topbar { - grid-template-columns: auto 1fr auto; - gap: 8px; + + .imap-form-heading, + .imap-form fieldset, + .icloud-preset-note, + .imap-security-note, + .imap-form > .settings-actions, + .imap-form > .settings-notice { + grid-column: 1 / -1; } - .topbar-actions > :not(.account-menu-anchor):not(.locale-button) { - display: none; + + .imap-form-heading { + display: flex; + justify-content: space-between; + gap: 16px; } - .app-body { - grid-template-columns: 1fr; - padding-left: 12px; + .imap-form-heading h2 { + margin: 0 0 6px; } - .app-body.sidebar-is-collapsed { - grid-template-columns: 1fr; + .imap-form-heading p, + .imap-security-note { + margin: 0; + color: var(--muted-foreground); } - .sidebar { - position: fixed; - z-index: 30; - top: 64px; - bottom: 0; - left: 0; - width: 248px; - display: none; - background: #050505; - border-right: 1px solid var(--border); + + .icloud-preset-note { + display: grid; + gap: 6px; + padding: 14px; + color: var(--muted-foreground); + font-size: 13px; + border: 1px solid var(--border); + border-radius: var(--radius); } - .sidebar:not(.collapsed) { - display: block; + + .icloud-preset-note strong { + color: var(--foreground); } - .sidebar:not(.collapsed) .compose-button { - width: 172px; - padding-left: 16px; + + .icloud-preset-note a { + width: fit-content; + color: var(--foreground); + text-decoration: underline; + text-underline-offset: 3px; } - .sidebar:not(.collapsed) .compose-button span, - .sidebar:not(.collapsed) .nav-item span:not(.label-dot):not(.provider-icon), - .sidebar:not(.collapsed) .nav-item strong, - .sidebar:not(.collapsed) .sidebar-section-title, - .sidebar:not(.collapsed) .accounts { + .imap-form label { display: flex; + flex-direction: column; + gap: 7px; + color: var(--muted-foreground); + font-size: 13px; } - .category-tabs { - grid-template-columns: repeat(5, 150px); + .imap-form input, + .imap-form select { + min-height: 38px; + padding: 0 10px; + color: var(--foreground); + background: var(--background); + border: 1px solid var(--border); + border-radius: var(--radius); } - .message-content { - grid-template-columns: 110px minmax(160px, 1fr) 60px; + .imap-form fieldset { + display: grid; + grid-template-columns: 2fr 1fr 1fr; + gap: 12px; + padding: 14px; + border: 1px solid var(--border); + border-radius: var(--radius); + } + .imap-security-note { + display: flex; + align-items: center; + gap: 8px; } - .message-content .provider-badge { - display: none; + + .account-list { + display: grid; + gap: 10px; + margin-top: 20px; } - .admin-shell { - grid-template-columns: 1fr; + + .account-list article { + display: grid; + grid-template-columns: auto 1fr auto auto; + align-items: center; + gap: 14px; + padding: 16px; + border: 1px solid var(--border); + border-radius: calc(var(--radius) + 2px); + background: var(--surface-subtle); } - .admin-sidebar { - display: none; + + .account-list article div { + display: flex; + flex-direction: column; + gap: 4px; } - .admin-mobile-navigation { + + @media (max-width: 700px) { + .settings-heading { + align-items: stretch; + flex-direction: column; + } + .account-list article { + grid-template-columns: auto 1fr; + } + .account-list article button { + grid-column: span 2; + } + .imap-form, + .imap-form fieldset { + grid-template-columns: 1fr; + } + } + .admin-header { + grid-column: 1 / -1; display: flex; align-items: center; - gap: 6px; + justify-content: space-between; + padding: 0 22px; + border-bottom: 1px solid var(--border); } - .admin-stat-grid { - grid-template-columns: repeat(2, minmax(0, 1fr)); + .admin-sidebar { + padding: 30px 14px; + border-right: 1px solid var(--border); } - .admin-data-table, - .admin-log-table, - .admin-table { - overflow-x: auto; + .admin-sidebar h1 { + margin: 0 12px 22px; + font-size: 15px; } - .admin-data-table table, - .admin-log-table > div, - .admin-table > div { - min-width: 700px; + .admin-sidebar button { + width: 100%; + height: 38px; + padding: 0 12px; + border: 0; + border-radius: 6px; + background: transparent; + color: #929299; + text-align: left; + font-size: 14px; + } + .admin-sidebar button:hover, + .admin-sidebar button.active { + background: #171717; + color: white; } .admin-content { - padding: 24px 18px; + min-width: 0; + width: 100%; + max-width: 1500px; + padding: 36px; + } + .admin-title { + display: flex; + align-items: flex-end; + justify-content: space-between; + margin-bottom: 28px; + } + .admin-title span { + color: #85858d; + font-size: 13px; + } + .admin-title h2 { + margin: 5px 0 0; + font-size: 25px; + letter-spacing: -0.03em; + } + .status-badge { + display: flex; + align-items: center; + gap: 7px; + padding: 7px 10px; + border: 1px solid #234b31; + border-radius: 6px; + color: #86efac; + font-size: 12px; } .metric-strip { - grid-template-columns: repeat(2, 1fr); + display: grid; + grid-template-columns: repeat(4, 1fr); + border: 1px solid var(--border); + border-radius: 8px; + } + .metric-strip article { + display: grid; + gap: 8px; + padding: 18px; + border-right: 1px solid var(--border); } - .metric-strip article:nth-child(2) { - border-right: 0; + .metric-strip article:last-child { + border: 0; } - .metric-strip article:nth-child(-n + 2) { - border-bottom: 1px solid var(--border); + .metric-strip span, + .metric-strip small { + color: #83838b; + font-size: 12px; + } + .metric-strip strong { + font-size: 24px; + letter-spacing: -0.03em; } .admin-grid { - grid-template-columns: 1fr; + display: grid; + grid-template-columns: minmax(0, 1.5fr) minmax(320px, 0.8fr); + gap: 16px; + margin-top: 16px; + } + .admin-panel { + border: 1px solid var(--border); + border-radius: 8px; + background: var(--surface-subtle); + box-shadow: var(--shadow-card); + } + .admin-panel > header { + min-height: 50px; + display: flex; + align-items: center; + justify-content: space-between; + padding: 0 16px; + border-bottom: 1px solid var(--border); } - .admin-update-grid { - grid-template-columns: 1fr; + .chart-panel header div { + display: grid; + gap: 2px; } -} -@media (max-width: 620px) { - .app-shell { - grid-template-rows: 58px 1fr; + .chart-panel header span { + color: #83838b; + font-size: 12px; } - .topbar { - height: 58px; - grid-template-columns: auto minmax(0, 1fr) auto; - padding: 0 6px; + .chart-panel select { + border: 1px solid #36363a; + border-radius: 5px; + background: #111; + color: #b8b8c0; + padding: 5px 8px; } - .topbar .brand { - display: none; + .chart-panel svg { + width: 100%; + height: 220px; + padding: 20px; + overflow: visible; + } + .grid-line { + fill: none; + stroke: #232326; + stroke-width: 1; + } + .chart-area { + fill: rgba(255, 255, 255, 0.08); + opacity: 0.12; + } + .chart-line { + fill: none; + stroke: white; + stroke-width: 2; + } + .service-table > div { + min-height: 45px; + display: grid; + grid-template-columns: 14px 1fr 80px 90px; + align-items: center; + gap: 8px; + padding: 0 16px; + border-bottom: 1px solid #1f1f21; + font-size: 13px; } - .admin-updater-content dl { - grid-template-columns: 1fr; + .service-table > div:last-child { + border: 0; } - .search-box { - height: 40px; + .service-table span:not(.online-dot) { + color: #8f8f97; } - .search-box kbd, - .search-box .h-10 { - display: none; + .service-table code { + justify-self: end; + color: #a1a1aa; } - .topbar .locale-button { - display: none; + .recent-events { + margin-top: 16px; } - .app-body { - padding: 0; + .event-row { + min-height: 44px; + display: grid; + grid-template-columns: 80px 54px 150px 1fr 90px; + align-items: center; + gap: 10px; + padding: 0 16px; + border-bottom: 1px solid #1f1f21; + color: #a1a1aa; + font-size: 12px; } - .mail-surface { - border-right: 0; - border-left: 0; - border-radius: 0; + .event-row:last-child { + border: 0; } - .range-controls > span { + .event-row code { + color: #d4d4d8; + } + .event-row small { + text-align: right; + } + .event-level { + width: max-content; + padding: 2px 5px; + border-radius: 4px; + font: + 10px ui-monospace, + monospace; + } + .event-level.info { + color: #93c5fd; + background: #172554; + } + .event-level.warn { + color: #fcd34d; + background: #451a03; + } + .admin-header-actions, + .admin-toolbar, + .admin-translation-actions { + display: flex; + align-items: center; + gap: 10px; + } + .admin-mobile-navigation { display: none; } - .category-tabs { - height: 50px; - grid-template-columns: repeat(5, 130px); + .admin-page-heading { + display: flex; + align-items: end; + justify-content: space-between; + gap: 20px; + margin-bottom: 24px; + } + .admin-page-heading span, + .admin-panel header span, + .admin-table time, + .admin-list small, + .admin-issue-list small { + color: var(--muted); + font-size: 12px; + } + .admin-page-heading h1 { + margin: 5px 0 0; + font-size: 26px; + letter-spacing: -0.03em; + } + .admin-health { + display: inline-flex; + align-items: center; + width: max-content; + gap: 6px; + padding: 5px 8px; + border: 1px solid var(--border-strong); + border-radius: 6px; + font-size: 12px; } - .category-tab { - min-width: 130px; - padding: 0 12px; + .admin-health-healthy { + color: #86efac; + border-color: #234b31; } - .message-list { - height: calc(100% - 98px); + .admin-health-degraded { + color: #fcd34d; + border-color: #713f12; } - .message-row { - min-height: 64px; - grid-template-columns: 20px 24px minmax(0, 1fr); - padding: 0 10px; + .admin-health-blocked { + color: #fca5a5; + border-color: #7f1d1d; } - .message-row .important { - display: none; + .admin-health-stale { + color: #c4b5fd; + border-color: #4c1d95; } - .message-content { - min-height: 63px; - grid-template-columns: minmax(0, 1fr) 58px; - grid-template-rows: 22px 22px; - column-gap: 8px; + .health-dot { + width: 7px; + height: 7px; + border-radius: 50%; + background: #a1a1aa; } - .sender { - grid-column: 1; + .health-dot-healthy { + background: #4ade80; } - .subject-line { - grid-column: 1; - grid-row: 2; + .health-dot-degraded { + background: #facc15; } - .message-content time { - grid-column: 2; - grid-row: 1; + .health-dot-blocked { + background: #f87171; } - .message-content .provider-badge, - .attachment-chip { - display: none; + .health-dot-stale { + background: #a78bfa; } - .context-rail .quick-actions { - display: none; + .admin-stat-grid { + display: grid; + grid-template-columns: repeat(4, minmax(0, 1fr)); + gap: 12px; + margin-top: 16px; + } + .admin-stat-grid article { + min-width: 0; + display: grid; + gap: 8px; + padding: 16px; + border: 1px solid var(--border); + border-radius: 8px; + background: #080808; + } + .admin-stat-grid span, + .admin-stat-grid small { + color: var(--muted); + font-size: 12px; + } + .admin-stat-grid strong { + font-size: 22px; + overflow-wrap: anywhere; + } + .admin-list, + .admin-issue-list, + .admin-log-table, + .admin-data-table, + .admin-table { + min-width: 0; } - .conversation-heading { - padding: 22px 18px; + .admin-list article, + .admin-issue-list article { + display: grid; + grid-template-columns: auto minmax(0, 1fr) auto auto auto; + align-items: center; + gap: 12px; + min-height: 58px; + padding: 8px 16px; + border-bottom: 1px solid var(--border); } - .conversation-heading h1 { - font-size: 19px; + .admin-list article:last-child, + .admin-issue-list article:last-child { + border-bottom: 0; } - .compose-panel { - right: 8px; - bottom: 8px; - height: calc(100vh - 74px); + .admin-list article > div, + .admin-issue-list article > div { + display: grid; + gap: 4px; } - .compose-panel.maximized { - inset: 8px; + .admin-table > div, + .admin-data-table th, + .admin-data-table td, + .admin-log-table > div { + padding: 7px 16px; + border-bottom: 1px solid var(--border); + font-size: 12px; + text-align: left; } - .admin-header { - padding: 0 14px; + .admin-table > div, + .admin-log-table > div { + display: grid; + align-items: center; + gap: 12px; + min-height: 44px; } - .admin-content { - padding: 20px 12px; + .admin-table > div { + grid-template-columns: minmax(180px, 1fr) 120px 180px; } - .admin-header .brand { - display: none; + .admin-log-table > div { + grid-template-columns: 170px 75px minmax(170px, 1fr) 150px 130px; + } + .admin-table > div:last-child, + .admin-log-table > div:last-child { + border-bottom: 0; } - .admin-header-actions { + .admin-data-table table { + min-width: 680px; width: 100%; + border-collapse: collapse; + } + .admin-data-table caption { + position: absolute; + width: 1px; + height: 1px; + overflow: hidden; + clip: rect(0 0 0 0); + } + .admin-data-table th { + color: var(--muted); + font-weight: 500; + } + .admin-toolbar { + justify-content: space-between; + flex-wrap: wrap; + margin-bottom: 14px; + padding: 12px; + border: 1px solid var(--border); + border-radius: 8px; + background: #080808; + } + .admin-toolbar label, + .admin-translation-grid label { + display: grid; + gap: 7px; + color: var(--muted); + font-size: 12px; + } + .admin-toolbar select, + .admin-mobile-navigation select, + .admin-translation-grid select, + .admin-translation-grid textarea { + border: 1px solid var(--border-strong); + border-radius: 6px; + background: #0d0d0d; + color: var(--text); + } + .admin-toolbar select, + .admin-mobile-navigation select, + .admin-translation-grid select { + min-height: 34px; + padding: 0 9px; } - .admin-mobile-navigation { - flex: 1; + .admin-translation-grid { + display: grid; + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: 16px; + padding: 18px; + border: 1px solid var(--border); + border-radius: 8px; + background: #080808; + } + .admin-translation-grid label:first-child, + .admin-translation-actions, + .admin-translation-grid > p { + grid-column: 1 / -1; + } + .admin-translation-grid textarea { + min-height: 170px; + resize: vertical; + padding: 10px; + } + .admin-placeholder { + min-height: 240px; + display: grid; + place-items: center; + align-content: center; + gap: 12px; + padding: 24px; + border: 1px dashed var(--border-strong); + border-radius: 8px; + color: var(--muted); + text-align: center; + } + .admin-update-grid { + display: grid; + grid-template-columns: minmax(0, 1.4fr) minmax(280px, 0.6fr); + gap: 16px; + } + .admin-updater-content { + display: grid; + gap: 16px; + padding: 18px; + } + .admin-updater-content dl { + display: grid; + grid-template-columns: repeat(3, minmax(0, 1fr)); + gap: 12px; + margin: 0; + } + .admin-updater-content dl > div, + .admin-update-candidate { + display: grid; + gap: 5px; + min-width: 0; + padding: 12px; + border: 1px solid var(--border); + border-radius: 6px; + } + .admin-updater-content dt, + .admin-update-candidate time { + color: var(--muted); + font-size: 12px; + } + .admin-updater-content dd { + margin: 0; + overflow-wrap: anywhere; + } + .admin-update-candidate p { + margin: 6px 0 0; + color: var(--muted-foreground); + white-space: pre-wrap; + } + .admin-update-progress { + display: grid; + grid-template-columns: minmax(0, 1fr) auto; + align-items: center; + gap: 12px; } - .admin-mobile-navigation select { + .admin-update-progress progress { width: 100%; + accent-color: var(--foreground); } - .admin-header-actions > button:last-child { - font-size: 0; + .admin-update-actions { + display: flex; + flex-wrap: wrap; + gap: 8px; } - .admin-page-heading { - align-items: flex-start; - flex-direction: column; + .admin-settings { + padding-bottom: 18px; } - .admin-title { - align-items: flex-start; - flex-direction: column; - gap: 14px; + .admin-settings h3, + .admin-settings p { + margin: 16px 16px 0; } - .metric-strip { - grid-template-columns: 1fr; + .admin-loading, + .admin-error, + .admin-notice { + margin: 0 0 16px; + padding: 10px 12px; + border: 1px solid var(--border); + border-radius: 6px; } - .metric-strip article { - border-right: 0; - border-bottom: 1px solid var(--border); + .admin-error { + color: #fca5a5; + border-color: #7f1d1d; } - .admin-grid { - grid-template-columns: 1fr; + .admin-notice { + color: #86efac; + border-color: #234b31; } - .admin-stat-grid, - .admin-translation-grid { - grid-template-columns: 1fr; + .admin-confirm { + position: fixed; + z-index: 100; + inset: 50% auto auto 50%; + width: min(440px, calc(100vw - 32px)); + transform: translate(-50%, -50%); + display: grid; + gap: 14px; + padding: 20px; + border: 1px solid var(--border-strong); + border-radius: 10px; + background: #0a0a0a; + box-shadow: 0 0 0 100vmax rgba(0, 0, 0, 0.72); + } + .admin-confirm p { + margin: 0; + color: var(--muted); + line-height: 1.5; + } + .admin-confirm > div { + display: flex; + justify-content: flex-end; + gap: 8px; } - .admin-translation-grid label, - .admin-translation-actions, - .admin-translation-grid > p { - grid-column: 1; + + .auth-shell { + min-height: 100dvh; + display: grid; + grid-template-rows: 64px 1fr 48px; + overflow-y: auto; + background: radial-gradient(circle at 50% 15%, rgb(255 255 255 / 6%), transparent 34%), #000; + } + .auth-header, + .auth-shell > footer { + position: relative; + z-index: 1; + display: flex; + align-items: center; + justify-content: space-between; + padding: 0 24px; + border-bottom: 1px solid var(--border); + background: rgb(0 0 0 / 88%); + } + .auth-shell > footer { + justify-content: center; + border-top: 1px solid var(--border); + border-bottom: 0; + color: #8f8f97; + font-size: 11px; + letter-spacing: 0.02em; + } + .auth-card, + .auth-state { + position: relative; + z-index: 1; + align-self: center; + justify-self: center; + } + .auth-card { + width: min(440px, calc(100vw - 32px)); + margin: 42px 0; + padding: 30px; + border: 1px solid var(--border-strong); + border-radius: 10px; + background: color-mix(in srgb, var(--surface-raised) 94%, transparent); + backdrop-filter: blur(18px); + box-shadow: 0 24px 80px rgb(0 0 0 / 65%); + } + .auth-card.compact { + width: min(400px, calc(100vw - 32px)); + } + .auth-icon { + width: 42px; + height: 42px; + display: grid; + place-items: center; + margin-bottom: 22px; + border: 1px solid var(--border-strong); + border-radius: 8px; + background: #111; + } + .auth-kicker { + color: #8f8f97; + font: + 11px ui-monospace, + "SFMono-Regular", + monospace; + } + .auth-card h1 { + margin: 8px 0; + color: white; + font-size: 24px; + letter-spacing: -0.035em; + } + .auth-card > p { + margin: 0 0 24px; + color: var(--muted); + font-size: 14px; + line-height: 1.5; + } + .auth-card form, + .auth-card label { + display: grid; + } + .auth-card form { + gap: 16px; + } + .auth-card label { + gap: 7px; + color: #d4d4d8; + font-size: 13px; + } + .auth-card input { + width: 100%; + height: 42px; + padding: 0 12px; + border: 1px solid #353539; + border-radius: 6px; + outline: 0; + background: #0f0f10; + color: white; } - .admin-list article, - .admin-issue-list article { - grid-template-columns: auto minmax(0, 1fr); + .auth-card input:focus { + border-color: var(--focus); + box-shadow: 0 0 0 3px var(--focus-ring); } - .admin-list article > button, - .admin-issue-list article > .admin-health, - .admin-issue-list article > button { - grid-column: 2; - justify-self: start; + .auth-card label small { + color: #8f8f97; + font-size: 11px; } - .event-row { - grid-template-columns: 65px 54px 1fr; + .auth-card form > button { + width: 100%; + height: 42px; + margin-top: 4px; + } + .auth-card form > button.bg-white { + color: #000; + } + .auth-error { + margin: 0 !important; + padding: 10px 12px; + border: 1px solid #5d2727; + border-radius: 6px; + background: #210d0d; + color: #fca5a5 !important; + font-size: 12px !important; + } + .auth-state { + display: grid; + justify-items: center; + gap: 16px; + color: var(--muted); + font-size: 13px; } - .event-row span:nth-of-type(2), - .event-row small { - display: none; + .spin { + animation: spin 800ms linear infinite; } -} -@media (prefers-reduced-motion: reduce) { - *, - *::before, - *::after { - scroll-behavior: auto !important; - transition-duration: 0.01ms !important; - animation-duration: 0.01ms !important; + @keyframes spin { + to { + transform: rotate(360deg); + } + } + @media (prefers-reduced-motion: reduce) { + .spin { + animation: none; + } } -} -@media (prefers-contrast: more) { - :root { - --border: #52525b; - --border-strong: #71717a; - --muted: #d4d4d8; - --faint: #a1a1aa; + @media (max-width: 1199px) { + .topbar { + grid-template-columns: 80px minmax(280px, 1fr) auto; + } + .brand-name { + display: none; + } + .app-body { + grid-template-columns: 64px minmax(0, 1fr); + } + .app-body.sidebar-is-collapsed { + grid-template-columns: 64px minmax(0, 1fr); + } + .sidebar { + width: 64px; + padding-inline: 8px; + } + .sidebar .compose-button { + width: 44px; + padding: 0; + } + .sidebar .compose-button span, + .sidebar .nav-item span:not(.label-dot):not(.provider-icon), + .sidebar .nav-item strong, + .sidebar .sidebar-section-title, + .sidebar .accounts { + display: none; + } + .message-content { + grid-template-columns: 150px minmax(180px, 1fr) 24px 64px; + } + .attachment-chip { + display: none; + } + } + @media (max-width: 900px) { + .topbar { + grid-template-columns: auto 1fr auto; + gap: 8px; + } + .topbar-actions > :not(.account-menu-anchor):not(.locale-menu-anchor) { + display: none; + } + .app-body { + grid-template-columns: 1fr; + padding-left: 12px; + } + .app-body.sidebar-is-collapsed { + grid-template-columns: 1fr; + } + .sidebar { + position: fixed; + z-index: 30; + top: 64px; + bottom: 0; + left: 0; + width: 248px; + display: none; + background: #050505; + border-right: 1px solid var(--border); + } + .sidebar:not(.collapsed) { + display: block; + } + .sidebar:not(.collapsed) .compose-button { + width: 172px; + padding-left: 16px; + } + .sidebar:not(.collapsed) .compose-button span, + .sidebar:not(.collapsed) .nav-item span:not(.label-dot):not(.provider-icon), + .sidebar:not(.collapsed) .nav-item strong, + .sidebar:not(.collapsed) .sidebar-section-title, + .sidebar:not(.collapsed) .accounts { + display: flex; + } + .category-tabs { + grid-template-columns: repeat(5, 150px); + } + .message-content { + grid-template-columns: 110px minmax(160px, 1fr) 60px; + } + .message-content .provider-badge { + display: none; + } + .admin-shell { + grid-template-columns: 1fr; + } + .admin-sidebar { + display: none; + } + .admin-mobile-navigation { + display: flex; + align-items: center; + gap: 6px; + } + .admin-stat-grid { + grid-template-columns: repeat(2, minmax(0, 1fr)); + } + .admin-data-table, + .admin-log-table, + .admin-table { + overflow-x: auto; + } + .admin-data-table table, + .admin-log-table > div, + .admin-table > div { + min-width: 700px; + } + .admin-content { + padding: 24px 18px; + } + .metric-strip { + grid-template-columns: repeat(2, 1fr); + } + .metric-strip article:nth-child(2) { + border-right: 0; + } + .metric-strip article:nth-child(-n + 2) { + border-bottom: 1px solid var(--border); + } + .admin-grid { + grid-template-columns: 1fr; + } + .admin-update-grid { + grid-template-columns: 1fr; + } + } + @media (max-width: 620px) { + .app-shell { + grid-template-rows: 58px 1fr; + } + .topbar { + height: 58px; + grid-template-columns: auto minmax(0, 1fr) auto; + padding: 0 6px; + } + .topbar .brand { + display: none; + } + .admin-updater-content dl { + grid-template-columns: 1fr; + } + .search-box { + height: 40px; + } + .search-box kbd, + .search-box .h-10 { + display: none; + } + .topbar .locale-button { + @apply min-w-[42px] px-2; + } + .topbar .locale-button > svg:first-child { + display: none; + } + .topbar .locale-button > svg:last-child { + @apply w-[11px]; + } + .app-body { + padding: 0; + } + .mail-surface { + border-right: 0; + border-left: 0; + border-radius: 0; + } + .range-controls > span { + display: none; + } + .category-tabs { + height: 50px; + grid-template-columns: repeat(5, 130px); + } + .category-tab { + min-width: 130px; + padding: 0 12px; + } + .message-list { + height: calc(100% - 98px); + } + .message-row { + min-height: 64px; + grid-template-columns: 20px 24px minmax(0, 1fr); + padding: 0 10px; + } + .message-row .important { + display: none; + } + .message-content { + min-height: 63px; + grid-template-columns: minmax(0, 1fr) 58px; + grid-template-rows: 22px 22px; + column-gap: 8px; + } + .sender { + grid-column: 1; + } + .subject-line { + grid-column: 1; + grid-row: 2; + } + .message-content time { + grid-column: 2; + grid-row: 1; + } + .message-content .provider-badge, + .attachment-chip { + display: none; + } + .context-rail .quick-actions { + display: none; + } + .conversation-heading { + padding: 22px 18px; + } + .conversation-heading h1 { + font-size: 19px; + } + .compose-panel { + right: 8px; + bottom: 8px; + height: calc(100vh - 74px); + } + .compose-panel.maximized { + inset: 8px; + } + .admin-header { + padding: 0 14px; + } + .admin-content { + padding: 20px 12px; + } + .admin-header .brand { + display: none; + } + .admin-header-actions { + width: 100%; + } + .admin-mobile-navigation { + flex: 1; + } + .admin-mobile-navigation select { + width: 100%; + } + .admin-header-actions > button:last-child { + font-size: 0; + } + .admin-page-heading { + align-items: flex-start; + flex-direction: column; + } + .admin-title { + align-items: flex-start; + flex-direction: column; + gap: 14px; + } + .metric-strip { + grid-template-columns: 1fr; + } + .metric-strip article { + border-right: 0; + border-bottom: 1px solid var(--border); + } + .admin-grid { + grid-template-columns: 1fr; + } + .admin-stat-grid, + .admin-translation-grid { + grid-template-columns: 1fr; + } + .admin-translation-grid label, + .admin-translation-actions, + .admin-translation-grid > p { + grid-column: 1; + } + .admin-list article, + .admin-issue-list article { + grid-template-columns: auto minmax(0, 1fr); + } + .admin-list article > button, + .admin-issue-list article > .admin-health, + .admin-issue-list article > button { + grid-column: 2; + justify-self: start; + } + .event-row { + grid-template-columns: 65px 54px 1fr; + } + .event-row span:nth-of-type(2), + .event-row small { + display: none; + } + } + @media (prefers-reduced-motion: reduce) { + *, + *::before, + *::after { + scroll-behavior: auto !important; + transition-duration: 0.01ms !important; + animation-duration: 0.01ms !important; + } } -} -@media (forced-colors: active) { - :root { - --focus: Highlight; + @media (prefers-contrast: more) { + :root { + --border: #52525b; + --border-strong: #71717a; + --muted: #d4d4d8; + --faint: #a1a1aa; + } } - .sync-dot, - .online-dot, - .offline-dot, - .label-dot { - forced-color-adjust: none; + + @media (forced-colors: active) { + :root { + --focus: Highlight; + } + .sync-dot, + .online-dot, + .offline-dot, + .label-dot { + forced-color-adjust: none; + } } } diff --git a/apps/web/tests/inbox.spec.ts b/apps/web/tests/inbox.spec.ts index ee95270..59aa7b5 100644 --- a/apps/web/tests/inbox.spec.ts +++ b/apps/web/tests/inbox.spec.ts @@ -96,6 +96,24 @@ test("live inbox virtualizes large account-scoped pages and preserves selection" totalCount: itemCount, unreadCount: 1, }, + { + id: "mailbox-trash", + accountId: account.id, + remoteName: "Trash", + localName: null, + role: "trash", + totalCount: 2, + unreadCount: 0, + }, + { + id: "mailbox-junk", + accountId: account.id, + remoteName: "Spam", + localName: null, + role: "junk", + totalCount: 1, + unreadCount: 0, + }, ], }, }), @@ -309,7 +327,7 @@ test("live inbox virtualizes large account-scoped pages and preserves selection" }); await page.goto("/"); - await expect(page.getByText("Sender 0", { exact: true })).toBeVisible({ timeout: 10_000 }); + await expect(page.getByText("Sender 0", { exact: true })).toBeVisible({ timeout: 20_000 }); await expect.poll(() => Boolean(eventSocket)).toBe(true); expect(await page.locator(".message-row").count()).toBeLessThan(100); @@ -317,17 +335,37 @@ test("live inbox virtualizes large account-scoped pages and preserves selection" await expect(page.getByRole("menu", { name: "Accounts" })).toContainText("Personal"); await page.keyboard.press("Escape"); + await page.getByRole("button", { name: "EN", exact: true }).click(); + await expect(page.getByRole("menu", { name: "Language" })).toBeVisible(); + await expect(page.getByRole("menuitemradio", { name: "EN English" })).toHaveAttribute( + "aria-checked", + "true", + ); + await page.getByRole("menuitemradio", { name: "ES Spanish" }).click(); + await expect(page.getByRole("button", { name: "ES", exact: true })).toBeVisible(); + await page.getByRole("button", { name: "ES", exact: true }).click(); + await page.getByRole("menuitemradio", { name: "EN Inglés" }).click(); + + await expect(page.getByRole("button", { name: "Close rail" })).toHaveCount(0); + if ((page.viewportSize()?.width ?? 0) >= 1200) { + await expect(page.getByRole("button", { name: "Developer" })).toBeHidden(); + await page.getByRole("button", { name: "Expand Buzones" }).click(); await expect(page.getByRole("button", { name: "Developer" })).toBeVisible(); await page.getByRole("button", { name: "Collapse Buzones" }).click(); await expect(page.getByRole("button", { name: "Developer" })).toBeHidden(); - await page.getByRole("button", { name: "Expand Buzones" }).click(); + + await page.getByRole("button", { name: "More", exact: true }).click(); + await expect(page.getByRole("button", { name: "Trash", exact: true })).toBeVisible(); + await expect(page.getByRole("button", { name: "Spam", exact: true })).toBeVisible(); + await page.getByRole("button", { name: "More", exact: true }).click(); + await expect(page.getByRole("button", { name: "Trash", exact: true })).toBeHidden(); } await page.locator(".message-row").first().click({ button: "right" }); await expect(page.getByRole("menu", { name: /Actions for Sender 0/ })).toBeVisible(); await expect(page.getByRole("menuitem", { name: "Archive", exact: true })).toBeVisible(); - await page.getByRole("menuitem", { name: "Open Sender 0", exact: true }).click(); + await page.getByRole("menuitem", { name: "Open", exact: true }).click(); await expect.poll(() => openedThreadIds.at(-1)).toBe(syntheticThreads[0]?.id); await page.getByRole("button", { name: "Back to inbox" }).click(); await expect(page.getByText("Sender 0", { exact: true })).toBeVisible(); @@ -357,7 +395,7 @@ test("live inbox virtualizes large account-scoped pages and preserves selection" const firstSelection = page.getByRole("button", { name: "Select Sender 0" }); await firstSelection.click(); await page.getByRole("button", { name: "Refresh" }).click(); - await expect(firstSelection).toBeVisible(); + await expect(firstSelection).toBeVisible({ timeout: 20_000 }); await expect(firstSelection).toHaveClass(/checked/); await page.getByRole("button", { name: "Open Sender 0" }).focus(); diff --git a/biome.json b/biome.json index 6e5bcd5..facfcb6 100644 --- a/biome.json +++ b/biome.json @@ -34,5 +34,10 @@ "quoteStyle": "double", "semicolons": "always" } + }, + "css": { + "parser": { + "tailwindDirectives": true + } } } diff --git a/services/api/internal/modules/translations/catalogs.json b/services/api/internal/modules/translations/catalogs.json index e9dbe3a..4f8cfab 100644 --- a/services/api/internal/modules/translations/catalogs.json +++ b/services/api/internal/modules/translations/catalogs.json @@ -9,6 +9,9 @@ "drafts": "Drafts", "sent": "Sent", "more": "More", + "language": "Language", + "languageEnglish": "English", + "languageSpanish": "Spanish", "labels": "Labels", "accounts": "Accounts", "compose": "Compose", @@ -355,6 +358,9 @@ "drafts": "Borradores", "sent": "Enviados", "more": "Más", + "language": "Idioma", + "languageEnglish": "Inglés", + "languageSpanish": "Español", "labels": "Etiquetas", "accounts": "Cuentas", "compose": "Redactar",