/* ========================================================================== ihasmail design system ========================================================================== */ :root { --font-sans: "Inter", system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif; --font-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace; --fs: 14px; --radius: 10px; --radius-sm: 6px; --radius-lg: 16px; --shadow-1: 0 1px 2px rgba(0, 0, 0, 0.06), 0 1px 3px rgba(0, 0, 0, 0.08); --shadow-2: 0 4px 16px rgba(0, 0, 0, 0.12), 0 2px 6px rgba(0, 0, 0, 0.08); --shadow-3: 0 12px 40px rgba(0, 0, 0, 0.18), 0 4px 12px rgba(0, 0, 0, 0.1); --row-h: 44px; --topbar-h: 56px; --sidebar-w: 256px; --sidebar-w-collapsed: 68px; --list-w: 42%; --ease: cubic-bezier(0.2, 0, 0, 1); /* Light palette */ --bg: #f6f8fa; --bg-elev: #ffffff; --bg-sunken: #eef1f4; --bg-hover: rgba(15, 23, 42, 0.05); --bg-active: rgba(15, 23, 42, 0.09); --fg: #111827; --fg-muted: #5b6472; --fg-faint: #8b94a3; --border: #e3e7ec; --border-strong: #cbd2da; --accent: #0f766e; --accent-fg: #ffffff; --accent-soft: #d9f1ee; --accent-soft-fg: #0b5750; --danger: #dc2626; --danger-soft: #fee2e2; --warn: #b45309; --warn-soft: #fef3c7; --success: #15803d; --success-soft: #dcfce7; --link: #0e7490; --unread-bg: #ffffff; --read-bg: #f3f5f7; --selected-bg: #d9f1ee; --focus-ring: 0 0 0 3px rgba(15, 118, 110, 0.35); --star: #f59e0b; --q1: #2563eb; --q2: #16a34a; --q3: #9333ea; --scrollbar: rgba(0, 0, 0, 0.25); color-scheme: light; } :root[data-theme="dark"] { --bg: #0b1220; --bg-elev: #111a2b; --bg-sunken: #0d1524; --bg-hover: rgba(255, 255, 255, 0.06); --bg-active: rgba(255, 255, 255, 0.1); --fg: #e5e9f0; --fg-muted: #9aa5b8; --fg-faint: #6b7689; --border: #1f2a3d; --border-strong: #31405a; --accent: #2dd4bf; --accent-fg: #052e2b; --accent-soft: rgba(45, 212, 191, 0.16); --accent-soft-fg: #99f6e4; --danger: #f87171; --danger-soft: rgba(248, 113, 113, 0.15); --warn: #fbbf24; --warn-soft: rgba(251, 191, 36, 0.15); --success: #4ade80; --success-soft: rgba(74, 222, 128, 0.15); --link: #67e8f9; --unread-bg: #121c2e; --read-bg: #0e1627; --selected-bg: rgba(45, 212, 191, 0.18); --focus-ring: 0 0 0 3px rgba(45, 212, 191, 0.4); --star: #fbbf24; --q1: #60a5fa; --q2: #4ade80; --q3: #c084fc; --scrollbar: rgba(255, 255, 255, 0.25); --shadow-1: 0 1px 2px rgba(0, 0, 0, 0.4); --shadow-2: 0 4px 16px rgba(0, 0, 0, 0.5); --shadow-3: 0 12px 40px rgba(0, 0, 0, 0.6); color-scheme: dark; } /* * The "ihasmail" theme: the palette from ihasmail.org, which is a teal-navy * rather than the blue-slate of the plain dark theme, warmed by the orange the * logo's cat is drawn in. * * It rides on data-theme="dark" rather than replacing it, so every dark-only * rule further down this file -- tooltips, toasts, the message frame -- keeps * applying without being duplicated. Only the palette is overridden. * * Specificity is doing deliberate work here. This block is [data-palette] plus * :root, so 0,2,0; the accent variants below are :root[data-theme][data-accent], * so 0,3,0 and they win. That is what makes the accent swatches keep working on * top of this theme -- and because the default accent ("teal") has no rule of * its own, ihasmail.org's own accent is what shows until someone picks another. */ :root[data-palette="ihasmail"] { --bg: #0d2430; --bg-elev: #12303e; --bg-sunken: #0a1c26; --bg-hover: rgba(70, 202, 195, 0.10); --bg-active: rgba(70, 202, 195, 0.16); --fg: #eaf6f6; --fg-muted: #a3c3cb; --fg-faint: #86aab4; --border: #21505f; --border-strong: #2e6a7a; --accent: #46cac3; --accent-fg: #062028; --accent-soft: rgba(70, 202, 195, 0.16); --accent-soft-fg: #9fe6e2; --danger: #f87171; --danger-soft: rgba(248, 113, 113, 0.15); --warn: #f9a34b; --warn-soft: rgba(249, 163, 75, 0.14); --success: #4ade80; --success-soft: rgba(74, 222, 128, 0.15); --link: #6fdcd6; --unread-bg: #163a4a; --read-bg: #12303e; --selected-bg: rgba(70, 202, 195, 0.18); --focus-ring: 0 0 0 3px rgba(70, 202, 195, 0.4); /* The cat is orange; so is the star. */ --star: #f9a34b; --q1: #6fdcd6; --q2: #4ade80; --q3: #c084fc; --scrollbar: rgba(163, 195, 203, 0.3); --shadow-1: 0 1px 2px rgba(0, 0, 0, 0.45); --shadow-2: 0 8px 24px rgba(0, 0, 0, 0.55); --shadow-3: 0 22px 60px -28px rgba(0, 0, 0, 0.75); color-scheme: dark; } /* Accent variants */ :root[data-accent="blue"] { --accent: #2563eb; --accent-soft: #dbeafe; --accent-soft-fg: #1e3a8a; --selected-bg: #dbeafe; --focus-ring: 0 0 0 3px rgba(37,99,235,.35); --link:#1d4ed8; } :root[data-accent="purple"] { --accent: #7c3aed; --accent-soft: #ede9fe; --accent-soft-fg: #4c1d95; --selected-bg: #ede9fe; --focus-ring: 0 0 0 3px rgba(124,58,237,.35); --link:#6d28d9; } :root[data-accent="rose"] { --accent: #e11d48; --accent-soft: #ffe4e6; --accent-soft-fg: #881337; --selected-bg: #ffe4e6; --focus-ring: 0 0 0 3px rgba(225,29,72,.35); --link:#be123c; } :root[data-accent="orange"] { --accent: #ea580c; --accent-soft: #ffedd5; --accent-soft-fg: #7c2d12; --selected-bg: #ffedd5; --focus-ring: 0 0 0 3px rgba(234,88,12,.35); --link:#c2410c; } :root[data-accent="green"] { --accent: #16a34a; --accent-soft: #dcfce7; --accent-soft-fg: #14532d; --selected-bg: #dcfce7; --focus-ring: 0 0 0 3px rgba(22,163,74,.35); --link:#15803d; } :root[data-theme="dark"][data-accent="blue"] { --accent: #60a5fa; --accent-fg:#0b1a33; --accent-soft: rgba(96,165,250,.18); --accent-soft-fg:#bfdbfe; --selected-bg: rgba(96,165,250,.2); --link:#93c5fd; } :root[data-theme="dark"][data-accent="purple"] { --accent: #a78bfa; --accent-fg:#1e1040; --accent-soft: rgba(167,139,250,.18); --accent-soft-fg:#ddd6fe; --selected-bg: rgba(167,139,250,.2); --link:#c4b5fd; } :root[data-theme="dark"][data-accent="rose"] { --accent: #fb7185; --accent-fg:#3b0716; --accent-soft: rgba(251,113,133,.18); --accent-soft-fg:#fecdd3; --selected-bg: rgba(251,113,133,.2); --link:#fda4af; } :root[data-theme="dark"][data-accent="orange"] { --accent: #fb923c; --accent-fg:#3b1605; --accent-soft: rgba(251,146,60,.18); --accent-soft-fg:#fed7aa; --selected-bg: rgba(251,146,60,.2); --link:#fdba74; } :root[data-theme="dark"][data-accent="green"] { --accent: #4ade80; --accent-fg:#052e16; --accent-soft: rgba(74,222,128,.18); --accent-soft-fg:#bbf7d0; --selected-bg: rgba(74,222,128,.2); --link:#86efac; } :root[data-density="comfortable"] { --row-h: 52px; } :root[data-density="cozy"] { --row-h: 44px; } :root[data-density="compact"] { --row-h: 36px; } :root[data-fontsize="small"] { --fs: 13px; } :root[data-fontsize="large"] { --fs: 15.5px; } /* Reset ------------------------------------------------------------------- */ *, *::before, *::after { box-sizing: border-box; } html, body, #root { height: 100%; } html { -webkit-text-size-adjust: 100%; } body { margin: 0; font-family: var(--font-sans); font-size: var(--fs); line-height: 1.45; color: var(--fg); background: var(--bg); -webkit-font-smoothing: antialiased; overscroll-behavior: none; } button, input, select, textarea { font: inherit; color: inherit; } button { cursor: pointer; background: none; border: 0; padding: 0; } a { color: var(--link); } img { max-width: 100%; } ::selection { background: var(--accent-soft); } * { scrollbar-width: thin; scrollbar-color: var(--scrollbar) transparent; } *::-webkit-scrollbar { width: 8px; height: 8px; } *::-webkit-scrollbar-thumb { background: var(--scrollbar); border-radius: 8px; } :focus-visible { outline: none; box-shadow: var(--focus-ring); border-radius: var(--radius-sm); } .sr-only { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; } .muted { color: var(--fg-muted); } .faint { color: var(--fg-faint); } .small { font-size: 0.875em; } .mono { font-family: var(--font-mono); } .truncate { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .row { display: flex; align-items: center; gap: 8px; } .col { display: flex; flex-direction: column; } .grow { flex: 1 1 auto; min-width: 0; } .spacer { flex: 1; } .hidden { display: none !important; } .wrap { flex-wrap: wrap; } .gap-2 { gap: 2px; } .gap-4 { gap: 4px; } .gap-8 { gap: 8px; } .gap-12 { gap: 12px; } .gap-16 { gap: 16px; } .mt-8 { margin-top: 8px; } .mt-16 { margin-top: 16px; } .mb-8 { margin-bottom: 8px; } .mb-16 { margin-bottom: 16px; } .p-16 { padding: 16px; } .center { display:flex; align-items:center; justify-content:center; } .nowrap { white-space: nowrap; } /* Buttons ---------------------------------------------------------------- */ .btn { display: inline-flex; align-items: center; justify-content: center; gap: 6px; height: 36px; padding: 0 14px; border-radius: var(--radius-sm); border: 1px solid var(--border-strong); background: var(--bg-elev); color: var(--fg); font-weight: 500; white-space: nowrap; user-select: none; transition: background .12s var(--ease), border-color .12s, box-shadow .12s, transform .05s; } .btn:hover { background: var(--bg-hover); } .btn:active { transform: translateY(1px); } .btn:disabled { opacity: .5; cursor: not-allowed; transform: none; } .btn-primary { background: var(--accent); border-color: transparent; color: var(--accent-fg); } .btn-primary:hover { filter: brightness(1.06); background: var(--accent); } .btn-danger { background: var(--danger); border-color: transparent; color: #fff; } .btn-danger:hover { filter: brightness(1.06); background: var(--danger); } .btn-ghost { border-color: transparent; background: transparent; } .btn-ghost:hover { background: var(--bg-hover); } .btn-soft { background: var(--accent-soft); border-color: transparent; color: var(--accent-soft-fg); } .btn-sm { height: 30px; padding: 0 10px; font-size: .9em; } .btn-lg { height: 44px; padding: 0 20px; font-size: 1.05em; border-radius: var(--radius); } .btn-pill { border-radius: 999px; } .btn-block { width: 100%; } .icon-btn { display: inline-flex; align-items: center; justify-content: center; width: 36px; height: 36px; border-radius: 50%; color: var(--fg-muted); flex: 0 0 auto; transition: background .12s var(--ease), color .12s; } .icon-btn:hover { background: var(--bg-hover); color: var(--fg); } .icon-btn:disabled { opacity: .4; cursor: not-allowed; } .icon-btn.active { color: var(--accent); background: var(--accent-soft); } .icon-btn.sm { width: 30px; height: 30px; } .icon-btn.xs { width: 26px; height: 26px; } .icon-btn.danger:hover { color: var(--danger); background: var(--danger-soft); } /* Inputs ----------------------------------------------------------------- */ .input, .select, .textarea { width: 100%; height: 38px; padding: 0 12px; border-radius: var(--radius-sm); border: 1px solid var(--border-strong); background: var(--bg-elev); color: var(--fg); transition: border-color .12s, box-shadow .12s; } .textarea { height: auto; min-height: 90px; padding: 10px 12px; resize: vertical; line-height: 1.5; } .input:focus, .select:focus, .textarea:focus { border-color: var(--accent); box-shadow: var(--focus-ring); outline: none; } .input::placeholder, .textarea::placeholder { color: var(--fg-faint); } .input.sm { height: 32px; padding: 0 10px; } .select { appearance: none; padding-right: 30px; background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%238b94a3' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E"); background-repeat: no-repeat; background-position: right 10px center; } .field { display: flex; flex-direction: column; gap: 6px; margin-bottom: 14px; } .field > label, .label { font-size: .85em; font-weight: 600; color: var(--fg-muted); letter-spacing: .01em; } .field-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 12px; } .hint { font-size: .85em; color: var(--fg-faint); } .check { display: flex; align-items: center; gap: 10px; cursor: pointer; padding: 6px 0; } .check input { width: 18px; height: 18px; accent-color: var(--accent); margin: 0; } .switch { position: relative; width: 40px; height: 22px; border-radius: 999px; background: var(--border-strong); transition: background .15s; flex: 0 0 auto; } .switch::after { content: ""; position: absolute; top: 2px; left: 2px; width: 18px; height: 18px; border-radius: 50%; background: #fff; box-shadow: var(--shadow-1); transition: transform .15s var(--ease); } .switch[aria-checked="true"] { background: var(--accent); } .switch[aria-checked="true"]::after { transform: translateX(18px); } .switch-row { display: flex; align-items: center; justify-content: space-between; gap: 16px; padding: 10px 0; border-bottom: 1px solid var(--border); } .switch-row:last-child { border-bottom: 0; } .switch-row .switch-text { display: flex; flex-direction: column; gap: 2px; } .switch-row .switch-text .hint { margin: 0; } .chip { display: inline-flex; align-items: center; gap: 6px; height: 26px; padding: 0 10px; border-radius: 999px; background: var(--bg-sunken); border: 1px solid var(--border); font-size: .85em; max-width: 100%; } .chip .chip-x { display: inline-flex; border-radius: 50%; padding: 2px; color: var(--fg-muted); } .chip .chip-x:hover { background: var(--bg-active); color: var(--fg); } .chip.invalid { border-color: var(--danger); color: var(--danger); } .badge { display: inline-flex; align-items: center; justify-content: center; min-width: 18px; height: 18px; padding: 0 5px; border-radius: 999px; font-size: 11px; font-weight: 700; background: var(--accent); color: var(--accent-fg); } .badge.muted { background: var(--bg-active); color: var(--fg-muted); } .tag { display: inline-flex; align-items: center; gap: 4px; height: 20px; padding: 0 8px; border-radius: 6px; font-size: 11.5px; font-weight: 600; color: #fff; } .kbd { display: inline-block; min-width: 20px; padding: 1px 6px; border-radius: 4px; border: 1px solid var(--border-strong); border-bottom-width: 2px; background: var(--bg-sunken); font-family: var(--font-mono); font-size: 11.5px; text-align: center; } /* Avatar ----------------------------------------------------------------- */ .avatar { display: inline-flex; align-items: center; justify-content: center; width: 36px; height: 36px; border-radius: 50%; color: #fff; font-weight: 600; font-size: 13px; flex: 0 0 auto; overflow: hidden; user-select: none; } .avatar img { width: 100%; height: 100%; object-fit: cover; } .avatar.sm { width: 28px; height: 28px; font-size: 11px; } .avatar.lg { width: 56px; height: 56px; font-size: 20px; } .avatar.xl { width: 88px; height: 88px; font-size: 30px; } /* Menus / popovers ------------------------------------------------------- */ .popover { position: fixed; z-index: 1000; min-width: 180px; max-width: min(420px, calc(100vw - 16px)); max-height: min(70vh, 520px); overflow: auto; background: var(--bg-elev); border: 1px solid var(--border); border-radius: var(--radius); box-shadow: var(--shadow-2); padding: 6px; animation: pop .12s var(--ease); } @keyframes pop { from { opacity: 0; transform: translateY(-4px) scale(.98); } to { opacity: 1; transform: none; } } .menu-item { display: flex; align-items: center; gap: 10px; width: 100%; padding: 8px 10px; border-radius: var(--radius-sm); text-align: left; color: var(--fg); white-space: nowrap; } .menu-item:hover, .menu-item.active { background: var(--bg-hover); } .menu-item:disabled { opacity: .5; cursor: default; } .menu-item.danger { color: var(--danger); } .menu-item .menu-kbd { margin-left: auto; color: var(--fg-faint); font-size: .85em; } .menu-item svg { color: var(--fg-muted); flex: 0 0 auto; } .menu-item.danger svg { color: var(--danger); } .menu-sep { height: 1px; background: var(--border); margin: 6px 4px; } .menu-title { padding: 6px 10px 4px; font-size: .78em; font-weight: 700; color: var(--fg-faint); text-transform: uppercase; letter-spacing: .05em; } .menu-search { padding: 4px 4px 6px; } .tooltip { position: fixed; z-index: 2000; background: #1f2937; color: #fff; padding: 5px 8px; border-radius: 6px; font-size: 12px; pointer-events: none; white-space: nowrap; box-shadow: var(--shadow-2); animation: pop .1s var(--ease); } :root[data-theme="dark"] .tooltip { background: #e5e9f0; color: #0b1220; } /* Dialogs ---------------------------------------------------------------- */ .dialog-backdrop { position: fixed; inset: 0; z-index: 900; background: rgba(2, 6, 23, 0.45); display: flex; align-items: center; justify-content: center; padding: 16px; animation: fade .15s var(--ease); backdrop-filter: blur(2px); } @keyframes fade { from { opacity: 0; } to { opacity: 1; } } .dialog { background: var(--bg-elev); border-radius: var(--radius-lg); box-shadow: var(--shadow-3); width: 100%; max-width: 520px; max-height: calc(100vh - 32px); display: flex; flex-direction: column; animation: rise .18s var(--ease); border: 1px solid var(--border); } @keyframes rise { from { opacity: 0; transform: translateY(10px) scale(.98); } to { opacity: 1; transform: none; } } .dialog.lg { max-width: 760px; } .dialog.xl { max-width: 980px; } .dialog.sm { max-width: 400px; } .dialog-head { display: flex; align-items: center; gap: 8px; padding: 16px 20px 8px; } .dialog-head h2 { margin: 0; font-size: 1.15em; font-weight: 650; flex: 1; } .dialog-body { padding: 8px 20px 16px; overflow: auto; } .dialog-foot { display: flex; align-items: center; justify-content: flex-end; gap: 8px; padding: 12px 20px 16px; border-top: 1px solid var(--border); } .dialog-foot .left { margin-right: auto; } /* Toasts ----------------------------------------------------------------- */ .toast-host { position: fixed; left: 50%; bottom: 24px; transform: translateX(-50%); z-index: 3000; display: flex; flex-direction: column; gap: 8px; align-items: center; pointer-events: none; padding: 0 12px; width: 100%; max-width: 520px; } .toast { pointer-events: auto; display: flex; align-items: center; gap: 12px; background: #1f2937; color: #fff; padding: 10px 10px 10px 16px; border-radius: var(--radius); box-shadow: var(--shadow-2); min-width: 260px; max-width: 100%; position: relative; overflow: hidden; animation: rise .2s var(--ease); } :root[data-theme="dark"] .toast { background: #e5e9f0; color: #0b1220; } .toast-error { background: #991b1b; color: #fff; } :root[data-theme="dark"] .toast-error { background: #fecaca; color: #450a0a; } .toast-success { background: #14532d; color: #fff; } :root[data-theme="dark"] .toast-success { background: #bbf7d0; color: #052e16; } .toast-msg { flex: 1; } .toast-action { color: #5eead4; font-weight: 700; padding: 6px 8px; border-radius: 6px; } .toast-action:hover { background: rgba(255,255,255,.12); } :root[data-theme="dark"] .toast-action { color: #0f766e; } .toast-close { color: inherit; opacity: .7; display: inline-flex; padding: 4px; border-radius: 50%; } .toast-close:hover { opacity: 1; background: rgba(255,255,255,.12); } .toast-progress { position: absolute; left: 0; bottom: 0; height: 3px; background: #5eead4; width: 100%; transform-origin: left; animation: shrink linear forwards; } @keyframes shrink { from { transform: scaleX(1); } to { transform: scaleX(0); } } /* Spinner / skeleton ----------------------------------------------------- */ .spinner { width: 20px; height: 20px; border: 2px solid var(--border-strong); border-top-color: var(--accent); border-radius: 50%; animation: spin .7s linear infinite; flex: 0 0 auto; } .spinner.lg { width: 32px; height: 32px; border-width: 3px; } @keyframes spin { to { transform: rotate(360deg); } } .skeleton { background: linear-gradient(90deg, var(--bg-sunken) 25%, var(--bg-hover) 37%, var(--bg-sunken) 63%); background-size: 400% 100%; animation: shimmer 1.4s ease infinite; border-radius: 6px; } @keyframes shimmer { 0% { background-position: 100% 50%; } 100% { background-position: 0 50%; } } .empty { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 8px; padding: 48px 24px; color: var(--fg-muted); text-align: center; } .empty svg { color: var(--fg-faint); } .empty h3 { margin: 8px 0 0; font-weight: 600; color: var(--fg); } .empty p { margin: 0; max-width: 360px; } .error-box { padding: 12px 14px; border-radius: var(--radius-sm); background: var(--danger-soft); color: var(--danger); border: 1px solid color-mix(in srgb, var(--danger) 30%, transparent); } .info-box { padding: 12px 14px; border-radius: var(--radius-sm); background: var(--accent-soft); color: var(--accent-soft-fg); } .warn-box { padding: 12px 14px; border-radius: var(--radius-sm); background: var(--warn-soft); color: var(--warn); } /* ========================================================================== App shell ========================================================================== */ .app { height: 100%; display: grid; grid-template-rows: var(--topbar-h) 1fr; overflow: hidden; } .topbar { display: flex; align-items: center; gap: 8px; padding: 0 12px; background: var(--bg); position: relative; z-index: 50; } .topbar .brand { display: flex; align-items: center; gap: 8px; font-weight: 700; font-size: 1.2em; letter-spacing: -.01em; color: var(--fg); text-decoration: none; padding-right: 8px; min-width: 0; } .topbar .brand img { width: 34px; height: 34px; object-fit: contain; } .topbar .brand .brand-name { color: #14b8a6; } .topbar .brand .brand-name span { color: var(--fg-muted); font-weight: 500; } .searchbar { flex: 1 1 auto; max-width: 720px; margin: 0 auto; position: relative; } .searchbar .search-input { display: flex; align-items: center; gap: 8px; height: 44px; padding: 0 8px 0 14px; border-radius: 999px; background: var(--bg-sunken); border: 1px solid transparent; transition: background .12s, box-shadow .12s, border-color .12s; } .searchbar .search-input:focus-within { background: var(--bg-elev); box-shadow: var(--shadow-1); border-color: var(--border); } .searchbar input { flex: 1; border: 0; background: transparent; outline: none; min-width: 0; height: 100%; } .searchbar input::placeholder { color: var(--fg-faint); } .search-panel { position: absolute; top: calc(100% + 6px); left: 0; right: 0; background: var(--bg-elev); border: 1px solid var(--border); border-radius: var(--radius); box-shadow: var(--shadow-2); padding: 16px; z-index: 60; animation: pop .12s var(--ease); } .search-panel .grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px 14px; } .search-suggest { position: absolute; top: calc(100% + 6px); left: 0; right: 0; background: var(--bg-elev); border: 1px solid var(--border); border-radius: var(--radius); box-shadow: var(--shadow-2); padding: 6px; z-index: 60; } .topbar-actions { display: flex; align-items: center; gap: 4px; } /* Live-updates indicator. Three states, and a raised bead rather than a flat speck: at 8px flat it was invisible against either theme. The gloss is a highlight over a solid colour rather than a colour-mix, so it needs no per-theme variant -- the same bead reads on light and dark alike. */ .push-status { display: inline-flex; align-items: center; padding: 0 4px; } .push-dot { width: 12px; height: 12px; border-radius: 50%; background: radial-gradient(circle at 34% 30%, rgba(255, 255, 255, .8), rgba(255, 255, 255, 0) 46%), var(--dot); box-shadow: 0 0 0 3px var(--dot-halo), 0 1px 2px rgba(0, 0, 0, .45), inset 0 -1px 2px rgba(0, 0, 0, .3); } .push-dot.connected { --dot: #16a34a; --dot-halo: rgba(22, 163, 74, .25); } .push-dot.connecting { --dot: #eab308; --dot-halo: rgba(234, 179, 8, .25); animation: push-pulse 1.6s ease-in-out infinite; } .push-dot.disconnected { --dot: #dc2626; --dot-halo: rgba(220, 38, 38, .25); } @keyframes push-pulse { 50% { opacity: .45; } } @media (prefers-reduced-motion: reduce) { .push-dot.connecting { animation: none; } } .app-body { display: grid; grid-template-columns: var(--sidebar-w) 1fr; min-height: 0; transition: grid-template-columns .2s var(--ease); } .app-body.collapsed { grid-template-columns: var(--sidebar-w-collapsed) 1fr; } .sidebar { display: flex; flex-direction: column; min-height: 0; padding: 4px 8px 8px 8px; gap: 2px; overflow: hidden; } .sidebar-scroll { overflow-y: auto; overflow-x: hidden; flex: 1; min-height: 0; padding-bottom: 8px; } .compose-btn { display: flex; align-items: center; gap: 12px; height: 52px; padding: 0 22px 0 18px; margin: 6px 4px 12px; border-radius: 16px; background: var(--bg-elev); box-shadow: var(--shadow-1); font-weight: 600; font-size: 1em; color: var(--fg); transition: box-shadow .15s, transform .05s, background .12s; white-space: nowrap; } .compose-btn:hover { box-shadow: var(--shadow-2); background: var(--bg-elev); } .compose-btn svg { color: var(--accent); } .collapsed .compose-btn { width: 52px; padding: 0; justify-content: center; margin-left: auto; margin-right: auto; } .collapsed .compose-btn span { display: none; } .nav-section { display: flex; align-items: center; justify-content: space-between; padding: 10px 12px 4px; font-size: .75em; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--fg-faint); } .nav-section .icon-btn { width: 24px; height: 24px; } .collapsed .nav-section { display: none; } .nav-item { position: relative; display: flex; align-items: center; gap: 12px; height: 36px; padding: 0 12px; border-radius: 0 999px 999px 0; margin-right: 8px; color: var(--fg); text-decoration: none; white-space: nowrap; transition: background .12s; user-select: none; font-weight: 450; } .nav-item:hover { background: var(--bg-hover); } .nav-item.unread .nav-label, .nav-item.unread .nav-count { font-weight: 700; color: var(--fg); } .nav-item.active { background: var(--accent-soft); color: var(--accent-soft-fg); font-weight: 650; } .nav-item.active.unread .nav-label, .nav-item.active.unread .nav-count { color: inherit; } .nav-item.drop-target { background: var(--accent-soft); outline: 2px dashed var(--accent); outline-offset: -2px; } .nav-item.folder-row.dragging { opacity: .45; } /* A folder colour tints its icon; the label keeps the sidebar's contrast. */ .folder-row .folder-icon { display: inline-flex; align-items: center; } /* .nav-item svg sets colour on the svg itself, so inheriting from the span is not enough -- the icon has to be targeted directly to win the cascade. The fill overrides lucide's own fill="none": a CSS rule beats a presentation attribute, and a solid folder reads at a glance where an outline does not. */ .folder-row .folder-icon[style*="--folder-color"] svg { color: var(--bg); fill: var(--folder-color); } /* The Folders heading doubles as the way back to the top level while dragging. */ .nav-section.drop-target { background: var(--accent-soft); outline: 2px dashed var(--accent); outline-offset: -2px; border-radius: var(--radius-sm); color: var(--accent-soft-fg); } .nav-item svg { flex: 0 0 auto; color: var(--fg-muted); } .nav-item.active svg { color: inherit; } .nav-item .nav-label { flex: 1; overflow: hidden; text-overflow: ellipsis; } .nav-item .nav-count { font-size: .8em; font-weight: 700; color: var(--fg-muted); } .nav-item.active .nav-count { color: inherit; } .nav-item .nav-more { opacity: 0; width: 24px; height: 24px; margin-right: -6px; } .nav-item:hover .nav-more, .nav-item:focus-within .nav-more { opacity: 1; } .nav-item .nav-twisty { width: 18px; height: 18px; display: inline-flex; align-items: center; justify-content: center; color: var(--fg-faint); border-radius: 4px; } .nav-item .nav-twisty:hover { background: var(--bg-active); } /* Folder rows keep the expand chevron in a gutter to the LEFT of the icon, so a folder with subfolders and one without still line up on their icon. */ .nav-item.folder-row { --folder-indent: 0px; position: relative; padding-left: calc(30px + var(--folder-indent)); } .nav-item.folder-row.depth-1 { --folder-indent: 16px; } .nav-item.folder-row.depth-2 { --folder-indent: 32px; } .nav-item.folder-row.depth-3 { --folder-indent: 48px; } .nav-item.folder-row.depth-4 { --folder-indent: 64px; } .nav-item.folder-row .nav-twisty { position: absolute; left: calc(8px + var(--folder-indent)); top: 50%; transform: translateY(-50%); margin: 0; } /* Labels sit in the same column: a 20px slot matching the folder icons. */ .nav-item.folder-row .nav-label-color { flex: 0 0 20px; width: 20px; height: 20px; border-radius: 0; display: inline-flex; align-items: center; justify-content: center; } .nav-item.folder-row .nav-label-color::before { content: ""; width: 11px; height: 11px; border-radius: 3px; background: var(--label-color, var(--accent)); } .collapsed .nav-item { justify-content: center; padding: 0; margin: 0 auto; width: 44px; border-radius: 999px; } .collapsed .nav-item .nav-label, .collapsed .nav-item .nav-count, .collapsed .nav-item .nav-more, .collapsed .nav-item .nav-twisty { display: none; } .collapsed .nav-item.depth-1, .collapsed .nav-item.depth-2, .collapsed .nav-item.depth-3 { display: none; } .collapsed .nav-item .nav-dot { position: absolute; top: 6px; right: 6px; width: 8px; height: 8px; border-radius: 50%; background: var(--accent); } .nav-label-color { width: 10px; height: 10px; border-radius: 3px; flex: 0 0 auto; } /* Outlook-style module bar at the bottom of the sidebar */ .module-bar { display: flex; align-items: stretch; justify-content: space-around; gap: 2px; padding: 6px 4px 4px; border-top: 1px solid var(--border); flex: 0 0 auto; } .module-link { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 3px; flex: 1; min-width: 0; padding: 6px 2px; border-radius: var(--radius-sm); color: var(--fg-muted); text-decoration: none; font-size: 11px; font-weight: 500; transition: background .12s, color .12s; } .module-link:hover { background: var(--bg-hover); color: var(--fg); } .module-link.active { color: var(--accent-soft-fg); background: var(--accent-soft); } .module-link svg { flex: 0 0 auto; } .module-link .module-label { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%; } .collapsed .module-bar { flex-direction: column; gap: 4px; } .collapsed .module-link .module-label { display: none; } .collapsed .module-link { width: 44px; height: 44px; margin: 0 auto; padding: 0; border-radius: 999px; } .quota { padding: 10px 12px; font-size: .8em; color: var(--fg-muted); } .quota-bar { height: 4px; background: var(--bg-active); border-radius: 4px; overflow: hidden; margin-top: 6px; } .quota-bar > span { display: block; height: 100%; background: var(--accent); } .quota-bar > span.warn { background: var(--warn); } .quota-bar > span.danger { background: var(--danger); } .collapsed .quota { display: none; } .main { min-height: 0; min-width: 0; display: flex; flex-direction: column; background: var(--bg-elev); border-radius: var(--radius-lg) 0 0 0; border: 1px solid var(--border); border-right: 0; border-bottom: 0; overflow: hidden; } /* Mobile drawer */ .drawer-backdrop { display: none; } .mobile-tabbar { display: none; } .fab { display: none; } /* ========================================================================== Mail ========================================================================== */ .mail-layout { display: grid; grid-template-columns: minmax(340px, var(--list-w)) 1fr; height: 100%; min-height: 0; flex: 1; } .mail-layout.pane-off { grid-template-columns: 1fr; } .mail-layout.pane-off.reading { grid-template-columns: 1fr; } .mail-layout .mail-list-pane { display: flex; flex-direction: column; min-height: 0; min-width: 0; border-right: 1px solid var(--border); } .mail-layout.pane-bottom .mail-list-pane { border-right: 0; border-bottom: 1px solid var(--border); } .mail-layout.pane-off .mail-list-pane { border-right: 0; } .mail-layout .mail-reading-pane { min-height: 0; min-width: 0; display: flex; flex-direction: column; background: var(--bg-elev); } .list-toolbar { display: flex; align-items: center; gap: 2px; height: 48px; padding: 0 8px 0 12px; border-bottom: 1px solid var(--border); flex: 0 0 auto; } .list-toolbar .tb-sep { width: 1px; height: 20px; background: var(--border); margin: 0 6px; } .list-toolbar .tb-title { font-weight: 650; font-size: 1.02em; margin-right: 8px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .list-toolbar .tb-count { color: var(--fg-muted); font-size: .85em; white-space: nowrap; } .select-all { width: 18px; height: 18px; accent-color: var(--accent); margin: 0 6px 0 0; cursor: pointer; } .mail-list { flex: 1; min-height: 0; overflow-y: auto; overflow-x: hidden; position: relative; outline: none; } .mail-list-inner { position: relative; width: 100%; } .msg-row { position: absolute; left: 0; right: 0; display: flex; align-items: center; gap: 8px; height: var(--row-h); padding: 0 12px 0 8px; border-bottom: 1px solid var(--border); background: var(--read-bg); cursor: pointer; user-select: none; -webkit-user-select: none; transition: box-shadow .1s; } .msg-row.unread { background: var(--unread-bg); } .msg-row.unread .msg-from, .msg-row.unread .msg-subject { font-weight: 700; color: var(--fg); } .msg-row:hover { box-shadow: inset 0 0 0 1px var(--border-strong), var(--shadow-1); z-index: 2; } .msg-row.selected { background: var(--selected-bg); } .msg-row.focused { box-shadow: inset 3px 0 0 var(--accent); } .msg-row.open { background: var(--selected-bg); } .msg-row.dragging { opacity: .5; } .msg-row .msg-check { width: 18px; height: 18px; accent-color: var(--accent); margin: 0; flex: 0 0 auto; opacity: 0; transition: opacity .1s; cursor: pointer; } .msg-row:hover .msg-check, .msg-row.selected .msg-check, .mail-list.has-selection .msg-check { opacity: 1; } .msg-row .msg-star { color: var(--fg-faint); flex: 0 0 auto; display: inline-flex; padding: 4px; border-radius: 50%; } .msg-row .msg-star:hover { color: var(--star); background: var(--bg-hover); } .msg-row .msg-star.on { color: var(--star); } .msg-row .msg-from { width: 180px; flex: 0 0 auto; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--fg); display: flex; align-items: center; gap: 6px; } .msg-row .msg-from .thread-count { color: var(--fg-muted); font-weight: 400; font-size: .9em; } .msg-row .msg-main { flex: 1; min-width: 0; display: flex; align-items: baseline; gap: 6px; overflow: hidden; } .msg-row .msg-subject { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; flex: 0 1 auto; min-width: 40%; max-width: 100%; color: var(--fg); } .msg-row .msg-preview { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; color: var(--fg-muted); flex: 1 1 0; min-width: 0; } .msg-row .msg-preview::before { content: " – "; } .msg-row .msg-meta { display: flex; align-items: center; gap: 6px; flex: 0 0 auto; color: var(--fg-muted); font-size: .85em; white-space: nowrap; } .msg-row.unread .msg-meta .msg-date { color: var(--fg); font-weight: 700; } .msg-row .msg-actions { display: none; align-items: center; gap: 0; margin-left: 4px; } .msg-row:hover .msg-actions { display: flex; } .msg-row:hover .msg-meta .msg-date { display: none; } .msg-row .msg-labels { display: inline-flex; gap: 4px; flex: 0 0 auto; } .msg-row .msg-labels .tag { height: 18px; font-size: 10.5px; padding: 0 6px; } .msg-row .avatar { width: 32px; height: 32px; font-size: 12px; } .mail-list.compact .msg-row .avatar { display: none; } .msg-row .msg-attach { color: var(--fg-faint); } .msg-row .msg-answered { color: var(--fg-faint); } .msg-row .msg-important { color: var(--warn); } .list-footer { padding: 12px; text-align: center; color: var(--fg-muted); font-size: .9em; } .list-hint { padding: 8px 12px; font-size: .85em; color: var(--fg-muted); background: var(--bg-sunken); border-bottom: 1px solid var(--border); display: flex; align-items: center; gap: 8px; } .list-hint button { color: var(--link); font-weight: 600; white-space: nowrap; } .drag-ghost { position: fixed; top: -1000px; left: -1000px; padding: 8px 12px; background: var(--accent); color: var(--accent-fg); border-radius: 999px; font-weight: 600; box-shadow: var(--shadow-2); pointer-events: none; z-index: 5000; } /* Splitter between list and reading pane */ .splitter { position: relative; background: var(--border); flex: 0 0 auto; z-index: 3; touch-action: none; } .splitter.vertical { width: 6px; cursor: col-resize; } .splitter.horizontal { height: 6px; cursor: row-resize; } .splitter:hover, .splitter:focus-visible { background: var(--accent); box-shadow: none; } .splitter .splitter-grip { position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); border-radius: 4px; background: var(--fg-faint); opacity: 0; transition: opacity .15s; } .splitter.vertical .splitter-grip { width: 3px; height: 36px; } .splitter.horizontal .splitter-grip { height: 3px; width: 36px; } .splitter:hover .splitter-grip { opacity: .8; } .mail-layout.pane-right { grid-template-columns: var(--list-size, 520px) auto 1fr; } .mail-layout.pane-bottom { grid-template-columns: 1fr; grid-template-rows: var(--list-size, 340px) auto 1fr; } /* Two-line rows (narrow lists / mobile) */ .mail-list.two-line .msg-row { height: calc(var(--row-h) * 1.5); align-items: flex-start; padding-top: 8px; } .mail-list.two-line .msg-row .msg-from { width: auto; flex: 1; } .mail-list.two-line .msg-row .msg-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; } .mail-list.two-line .msg-row .msg-line1 { display: flex; align-items: center; gap: 8px; } .mail-list.two-line .msg-row .msg-main { display: flex; gap: 6px; } .mail-list.two-line .msg-row .msg-subject { flex: 0 1 auto; } .mail-list.two-line .msg-row .msg-preview { flex: 1; } .mail-list.two-line .msg-row .msg-meta { margin-left: auto; } .mail-list.two-line .msg-row:hover .msg-meta .msg-date { display: inline; } .mail-list.two-line .msg-row:hover .msg-actions { display: none; } /* Reading pane / thread view */ .thread-view { display: flex; flex-direction: column; min-height: 0; height: 100%; } .thread-toolbar { display: flex; align-items: center; gap: 2px; height: 48px; padding: 0 8px; border-bottom: 1px solid var(--border); flex: 0 0 auto; } .thread-scroll { flex: 1; min-height: 0; overflow-y: auto; padding: 0 0 80px; } .thread-subject { padding: 20px 24px 8px; display: flex; align-items: flex-start; gap: 12px; } .thread-subject h1 { margin: 0; font-size: 1.35em; font-weight: 600; line-height: 1.3; flex: 1; overflow-wrap: anywhere; } .thread-subject .labels { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 6px; } .message { margin: 0 16px 8px; border: 1px solid var(--border); border-radius: var(--radius); background: var(--bg-elev); transition: box-shadow .12s; } .message.collapsed { cursor: pointer; } .message.collapsed:hover { box-shadow: var(--shadow-1); } .message.unread-msg { border-left: 3px solid var(--accent); } .message-head { display: flex; align-items: flex-start; gap: 12px; padding: 12px 16px; } .message-head .who { flex: 1; min-width: 0; } .message-head .who .from { font-weight: 650; display: flex; align-items: center; gap: 6px; flex-wrap: wrap; } .message-head .who .from .email { color: var(--fg-muted); font-weight: 400; font-size: .9em; } .message-head .who .to { color: var(--fg-muted); font-size: .88em; display: flex; align-items: center; gap: 4px; flex-wrap: wrap; } .message-head .who .to button { color: var(--fg-muted); display: inline-flex; align-items: center; } .message-head .who .snippet { color: var(--fg-muted); font-size: .92em; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .message-head .meta { display: flex; align-items: center; gap: 2px; color: var(--fg-muted); font-size: .85em; white-space: nowrap; flex: 0 0 auto; } .message-head .meta .date { margin-right: 6px; } .message-details { margin: 0 16px 8px; padding: 10px 12px; background: var(--bg-sunken); border-radius: var(--radius-sm); font-size: .88em; display: grid; grid-template-columns: auto 1fr; gap: 4px 12px; } .message-details dt { color: var(--fg-muted); } .message-details dd { margin: 0; overflow-wrap: anywhere; } /* * Layout containment here is a security control, not a layout tweak. * * Message bodies render in a shadow root, which scopes selectors but not * layout: a `position:fixed` rule in mail CSS is still positioned against the * viewport, so a sender could paint over the whole application. Containment * inside the shadow root cannot stop it — mail CSS lives in the same tree and * simply overrides it, and `:host` reaches the host element too (an * `!important` there even beats an `!important` from this file, because * importance reverses tree order). An ancestor of the host is the one thing * mail CSS has no selector for. `layout` rather than `paint`: it makes this a * containing block for fixed descendants without clipping tall messages. */ .message-body { padding: 4px 16px 16px; contain: layout; } .message-body .body-host { display: block; } .remote-banner { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin: 0 0 12px; padding: 8px 12px; background: var(--warn-soft); color: var(--warn); border-radius: var(--radius-sm); font-size: .9em; } .remote-banner button { color: inherit; font-weight: 700; text-decoration: underline; } .scheduled-banner { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin: 0 0 12px; padding: 8px 12px; background: var(--accent-soft); color: var(--accent-soft-fg); border-radius: var(--radius-sm); font-size: .9em; } .scheduled-banner button { color: inherit; font-weight: 700; text-decoration: underline; } .receipt-banner { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin: 0 0 12px; padding: 8px 12px; background: var(--warn-soft); color: var(--warn); border-radius: var(--radius-sm); font-size: .9em; } .receipt-banner button { color: inherit; font-weight: 700; text-decoration: underline; } .quote-toggle { display: inline-flex; align-items: center; gap: 4px; margin: 8px 0; padding: 2px 10px; border-radius: 999px; background: var(--bg-sunken); color: var(--fg-muted); font-size: 12px; border: 1px solid var(--border); } .quote-toggle:hover { background: var(--bg-active); } .attachments { display: flex; flex-wrap: wrap; gap: 10px; padding: 4px 16px 16px; } .attachment { display: flex; align-items: center; gap: 10px; width: 240px; max-width: 100%; padding: 8px 10px; border: 1px solid var(--border); border-radius: var(--radius-sm); background: var(--bg-elev); text-decoration: none; color: inherit; position: relative; transition: box-shadow .12s; } .attachment:hover { box-shadow: var(--shadow-1); } .attachment .att-icon { width: 36px; height: 36px; border-radius: 8px; display: flex; align-items: center; justify-content: center; background: var(--accent-soft); color: var(--accent-soft-fg); flex: 0 0 auto; overflow: hidden; } .attachment .att-icon img { width: 100%; height: 100%; object-fit: cover; } .attachment .att-text { flex: 1; min-width: 0; } .attachment .att-name { font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-size: .92em; } .attachment .att-size { color: var(--fg-muted); font-size: .8em; } .attachment .att-actions { display: none; gap: 0; } .attachment:hover .att-actions { display: flex; } .attachment:hover .att-size { display: none; } .attachment .att-progress { position: absolute; left: 0; bottom: 0; height: 3px; background: var(--accent); border-radius: 0 0 0 6px; } .attachment.error { border-color: var(--danger); } .thread-actions { display: flex; gap: 8px; padding: 8px 16px 16px; flex-wrap: wrap; } .invite-card { margin: 0 16px 12px; padding: 14px 16px; border: 1px solid var(--border); border-left: 4px solid var(--accent); border-radius: var(--radius-sm); background: var(--bg-sunken); } .invite-card h4 { margin: 0 0 4px; } .invite-card .rsvp { display: flex; gap: 8px; margin-top: 10px; flex-wrap: wrap; } .vcard-card { margin: 0 16px 12px; padding: 12px 16px; border: 1px solid var(--border); border-radius: var(--radius-sm); background: var(--bg-sunken); display: flex; align-items: center; gap: 12px; } .unsubscribe-row { margin: 0 16px 8px; font-size: .88em; color: var(--fg-muted); display: flex; align-items: center; gap: 8px; flex-wrap: wrap; } .reply-box { margin: 8px 16px 24px; } .reply-box .reply-prompt { display: flex; gap: 8px; align-items: center; padding: 12px; border: 1px solid var(--border); border-radius: var(--radius); color: var(--fg-muted); } .reply-box .reply-prompt button { display: inline-flex; align-items: center; gap: 6px; padding: 8px 14px; border-radius: 999px; border: 1px solid var(--border-strong); color: var(--fg); font-weight: 500; } .reply-box .reply-prompt button:hover { background: var(--bg-hover); } .no-thread { height: 100%; display: flex; align-items: center; justify-content: center; flex-direction: column; gap: 8px; color: var(--fg-muted); } .no-thread img { width: 140px; opacity: .6; filter: grayscale(.3); } .thread-nav { display: flex; align-items: center; gap: 2px; margin-left: auto; color: var(--fg-muted); font-size: .85em; } .print-only { display: none; } /* Labels (keywords) */ .label-dot { width: 8px; height: 8px; border-radius: 50%; display: inline-block; } /* ========================================================================== Composer ========================================================================== */ .composer-dock { position: fixed; right: 16px; bottom: 0; display: flex; align-items: flex-end; gap: 12px; z-index: 800; pointer-events: none; } .composer { pointer-events: auto; width: 580px; max-width: calc(100vw - 32px); height: 600px; max-height: calc(100vh - 24px); display: flex; flex-direction: column; background: var(--bg-elev); border-radius: var(--radius-lg) var(--radius-lg) 0 0; box-shadow: var(--shadow-3); border: 1px solid var(--border); border-bottom: 0; overflow: hidden; animation: rise .2s var(--ease); } .composer.minimized { height: 44px; width: 280px; } .composer.maximized { position: fixed; inset: 24px; width: auto; height: auto; max-width: none; max-height: none; border-radius: var(--radius-lg); border-bottom: 1px solid var(--border); } .composer-head { display: flex; align-items: center; gap: 4px; height: 44px; padding: 0 6px 0 14px; background: var(--bg-sunken); border-bottom: 1px solid var(--border); flex: 0 0 auto; cursor: default; } .composer-head .title { flex: 1; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .composer-head .status { color: var(--fg-faint); font-size: .8em; margin-right: 6px; white-space: nowrap; } .composer-body { display: flex; flex-direction: column; flex: 1; min-height: 0; } .composer-fields { flex: 0 0 auto; padding: 0 12px; } .composer-field { display: flex; align-items: center; gap: 8px; min-height: 40px; border-bottom: 1px solid var(--border); padding: 4px 0; } .composer-field > label { color: var(--fg-muted); width: 42px; flex: 0 0 auto; font-size: .92em; } .composer-field .field-extra { display: flex; gap: 4px; color: var(--fg-muted); font-size: .85em; } .composer-field .field-extra button { color: var(--fg-muted); padding: 2px 6px; border-radius: 4px; } .composer-field .field-extra button:hover { background: var(--bg-hover); color: var(--fg); } .composer-field input.plain { flex: 1; border: 0; background: transparent; outline: none; min-width: 80px; height: 30px; } .composer-field .from-select { flex: 1; border: 0; background: transparent; color: var(--fg); padding: 0; height: 30px; cursor: pointer; } /* * A native