# RustBox 0.2.14 - implementation status - Draft saves are realtime-silent: Drafts folder/list updates continue, but saving a draft does not surface as a new-mail notification. This file tracks the `0.2.14` source snapshot. Storage/search scope and outstanding acceptance work are tracked in `TODO.md`. A feature is only listed as implemented when working code exists in this source tree; partial items are called out explicitly. ## 0.2.14 browser mail UX - Wide message panes use a default-on compact single-line row layout (sender, subject/snippet, date and icons); users can disable it in Appearance settings. - Each identity can choose signature insertion: `silent` appends only during send and keeps the editor clean, while `visible` inserts an editable/removable signature into the composer. - Large To/Cc lists collapse to a compact recipient summary and expand on demand. - Message pagination exposes both `Load more` and `Load all`; both actions stretch evenly across the full list width, and the reader menu label is shortened to `Details`. - The composer can collapse From/To/Cc/Bcc/Subject/options from its header so the editor receives the freed vertical space; invalid recipient input automatically reopens the fields. - The composer exposes an explicit `Save draft` action before `Cancel`; it forces a real IMAP Drafts snapshot with the current MIME body and attachments while background autosave remains local/server-working-state only. - The composer exposes `Delete draft` for IMAP and recovered drafts; deletion verifies the current IMAP UID/UIDVALIDITY, expunges the server draft first, then removes the local autosave row, cascaded attachment rows and uploaded attachment blobs. - HTML composing embeds newly added PNG/JPEG/GIF/WebP images inline by default while preserving deleted inline content as reusable attachments. - Attachment chips can re-embed images or insert CID links for other files, and selected inline images expose quick size/alignment controls plus the advanced crop editor. - Clipboard image paste and file drag/drop insert at the current/drop caret; already embedded images can be dragged to a new body position. - Selected inline images expose four pointer resize handles that preserve aspect ratio, and attachment chips distinguish image attachments from ordinary files. - Message-body links without an explicit `target` default to `target="_blank"` so external navigation opens outside the sandboxed mail-preview iframe; explicit targets are preserved and `_blank` links receive `noopener noreferrer`. - Login success is shown only after a real login request; refreshing/restoring an existing authenticated session is silent. - Message/HTML preview documents explicitly declare UTF-8, and encoded-word header decoding delegates first to `mail-parser` for broader charset coverage, including UTF-8, ISO-8859-2 and Windows-1250 subjects and display names. - PDF attachments are previewed from the authenticated inline attachment URL instead of a `blob:` iframe, improving Safari/iPhone compatibility. - Composing displays attachment/message size limits as one compact line without configuration/MIME implementation details. - Initial synchronization remains silent for new-mail notifications; bulk operations retain one summary toast; browser/system modifier shortcuts remain preserved. - Mailbox pages default to 300 messages and the API/preferences accept values up to 300. - Blob deletion uses a durable SQL outbox for filesystem/shared POSIX/NFS and S3 backends; attachment/draft metadata deletion is transactionally paired with cleanup enqueue and failed deletes retry in the background. - Runtime migration V050 adds `mail_preferences.compact_wide_rows` and `identities.signature_insert_mode` on SQLite, MySQL and PostgreSQL; V051 is next. ## 0.2.8 browser security headers - `security_headers_enabled` remains opt-in and disabled by default for compatibility; optional browser-security headers are centralized in this middleware, so disabling it removes the RustBox-added security profile while normal response semantics such as `Content-Type` and route-specific caching remain. - HTML/XHTML documents receive the full document profile: CSP, `X-Frame-Options: DENY`, `Permissions-Policy`, `Cross-Origin-Opener-Policy: same-origin`, `Referrer-Policy: no-referrer` and `X-Content-Type-Options: nosniff`. - The HTML CSP allows only same-origin scripts (`script-src 'self'`) and disables inline script attributes; the theme bootstrap is an external fingerprinted asset. Stylesheets are same-origin only (`style-src 'self'`), while `style-src-attr 'unsafe-inline'` is narrowly retained because the current UI still sets per-element style attributes dynamically. - Private `/api` responses receive `Cache-Control: no-store`, `X-Content-Type-Options: nosniff` and `Cross-Origin-Resource-Policy: same-origin`. API responses are normally non-frameable (`frame-ancestors 'none'` / `X-Frame-Options: DENY`); `application/pdf` is the narrow exception and allows same-origin framing for the attachment preview (`frame-ancestors 'self'` / `SAMEORIGIN`). API JSON does not receive the full document CSP, `Permissions-Policy`, COOP or `Referrer-Policy`. - CSS receives `Referrer-Policy: no-referrer` and `X-Content-Type-Options: nosniff`; application assets also receive same-origin CORP without redundant HTML document policies. - HSTS is deliberately not synthesized by RustBox because the application may sit behind a TLS-terminating reverse proxy and cannot reliably determine the public HTTPS boundary; HSTS belongs at that HTTPS edge. - The public `/api/auth/policy` is data-minimized to the single login-form capability `rememberMeEnabled`. Optional feature availability (OpenPGP, Sieve, diagnostics, About) is returned only from authenticated `/api/auth/session-policy`; session/remember durations are not exposed to the browser policy endpoints. ## 0.2.8 storage/search architecture - SQL backend selection (`sqlite`/`mysql`/`pgsql`) is independent from blob storage and search backend selection. - Cluster mode clears an implicit/default `data_dir`; PostgreSQL/MySQL single-node deployments may still intentionally use `data_dir`-backed filesystem storage and local Tantivy. - Blob storage supports local/shared POSIX filesystems and S3-compatible object storage. Shared POSIX is an explicit capability (`storage.shared=true`) suitable for operator-provided NFS/CephFS/GlusterFS mounts. - Draft attachment upload/read/delete/snapshot/send paths use the `BlobStorage` abstraction and logical object keys instead of assuming node-local paths. - OpenSearch is available as the cluster-capable indexer. Local Tantivy remains single-node only; search may also be disabled. - Search mutations use a durable SQL outbox with claim/lease, retry/backoff and dead-letter state; the index remains rebuildable derived state. - V047 adds attachment checksum metadata and the search outbox across SQLite, MySQL and PostgreSQL. V048 adds monotonic folder-counter generations used by compare-and-set reconciliation of authoritative IMAP counts. V049 adds the durable blob deletion outbox. V050 adds compact-wide-row and signature insertion preferences; V051 is reserved as the next migration number. - SQL global-schema initialization is centralized in `db::pool::configure()`; database-backed sessions do not repeat startup DDL for SQLite, MySQL or PostgreSQL. - Docker Compose examples cover standalone SQLite, PostgreSQL + SILO (S3-compatible) + OpenSearch, and MySQL + NFS + OpenSearch. - Live SILO/MinIO/AWS S3/Ceph RGW, live NFS multi-host, live OpenSearch and full multi-node failover acceptance remain release-environment validation items and are not represented as completed here. ## Implemented / wired in this working snapshot ### Runtime and upstream - Single Rust runtime with embedded HTML/CSS/vanilla-JavaScript UI. - No TypeScript, React, Next.js, Node.js or Bun product build/runtime. - Oxi upstream tracking and mapped backend-port scripts retained. - EN/PL language assets embedded in the binary. ### Mail and IMAP workflow - Folder totals and unread counters use authoritative IMAP `STATUS (... MESSAGES UNSEEN ...)` data. If STATUS is unavailable for a selected mailbox, RustBox falls back to `UID SEARCH UNSEEN`; it never treats SELECT/EXAMINE `UNSEEN` (the first unseen sequence number) as an unread count. - Folder counter reconciliation runs independently from content synchronization and repairs `MESSAGES/UNSEEN` even when `HIGHESTMODSEQ` is unchanged. A manual counter refresh reuses the cached folder tree while it is fresh and batches STATUS calls on one IMAP session instead of forcing another LIST. - Read/unread/flag mutations update the affected row/badge optimistically, then reconcile against authoritative IMAP state and publish targeted flag/`FolderStatus` events without replacing the whole message list. The active folder is watched through IMAP IDLE; other folders are reconciled every 30 seconds. - Large folders may hydrate message headers incrementally, but the sidebar total/unread badge remains server-authoritative. IDLE/periodic reconciliation keeps the CONDSTORE cursor separate from counter refresh, falls back to a full `UID FLAGS` comparison when CONDSTORE is unavailable, and discards partial IMAP fetch streams rather than applying incomplete state. The top-right activity indicator distinguishes active synchronization/indexing from an incomplete local IMAP header cache and exposes backlog details in its tooltip. - Wide folder badges display `total / unread` while unread is non-zero and total alone at zero; narrow sidebars switch to the compact existing counter presentation. - IMAP folder list, hierarchy, create, create subfolder, rename, delete, subscribe/unsubscribe, plus collapsible branch navigation with per-account remembered expansion state. - Special folders stored per account: Sent, Drafts, Trash, Junk and Archive. Spam/Junk additionally supports a browser-wide default destination with a per-account override and IMAP special-use/name fallback. - Special-folder references follow folder renames and are cleared when a referenced folder is deleted. - Administrators can define server-wide default Sent/Drafts/Trash/Junk/Archive folder names; per-account settings still override them when present. - Sent-copy, delete-to-Trash, Archive and Junk actions use the configured special folders. - Mark-all-read and empty-folder operations. - Message move and copy operations. - Multi-select and bulk read/unread, flag/unflag, archive, move, copy, label and delete actions, including explicit select-all across the complete cached search result set. - Drag-and-drop a message onto a folder to move it. - Previous/next message navigation plus keyboard actions for common reader operations, compose, selection mode and selecting the current message. - After moving/deleting the currently opened message (including Spam, Not spam, Archive and Move), the reader automatically opens the next list item and falls back to the previous item when the removed message was last. - Message reading, collapsible thread navigation, attachments, raw headers, full RFC822 `.eml` download via `BODY.PEEK[]` and `.eml` import into a selected IMAP folder via APPEND. - Message/folder context menus with common Roundcube-style actions, including folder properties, full message source, Message-ID/address copy and mailing-list unsubscribe; the reader sender line also exposes compose/contact/search/filter actions. - Mailbox quota display where the IMAP server exposes quota, including warning/danger states at 80%/95%. - Per-account mailbox behavior: 20/50/100/200 messages per page, date/sender/subject/size sorting in both directions, configurable mark-read delay, threaded/flat reader mode, HTML/plain preference, remote-image policy including Contacts-only loading, quote limiting, optional list snippets and a default “flagged on top” mode. Each folder can inherit, force-enable or force-disable flagged-first ordering; sorting is applied before pagination. - IMAP capability diagnostics for IDLE, MOVE, UIDPLUS, CONDSTORE, QRESYNC, SORT, THREAD, NAMESPACE, SPECIAL-USE, QUOTA, ACL, LIST-EXTENDED and UTF8=ACCEPT. - Forward-as-attachment using `message/rfc822`. - Mailing-list unsubscribe action from `List-Unsubscribe`; RFC 8058 one-click HTTPS requests are sent by the backend only when `List-Unsubscribe-Post: List-Unsubscribe=One-Click` is advertised, with redirect-free public-address SSRF checks. Ordinary HTTPS/mailto links remain user-confirmed UI actions. - Explicit upload-body limits for attachments, contact imports/photos, ICS imports and `.eml` import so Axum does not reject allowed uploads at its smaller default limit. - Attachment context menu supports in-app preview/download for safe image/PDF/text/HTML/video classes; HTML is sandboxed and video uses native browser controls. Multiple attachments can be downloaded as a client-built UTF-8 ZIP without external runtime dependencies. - Message rows expose compact hover/focus quick actions for read/unread and flag/unflag; flagged rows also receive a subtle red lower-edge marker. ### Composer / identities - HTML, plain-text and Markdown compose modes. Markdown keeps its source text for the plain alternative and generates escaped/sanitized HTML for preview and delivery without accepting raw Markdown HTML. - Expanded HTML toolbar: bold, italic, underline, strike, lists, quote, alignment, links, font, size, color, clear formatting, undo/redo. - Draft autosave, explicit recovery of saved/browser-emergency drafts, and attachment upload/delete. IMAP Drafts messages are also first-class editable drafts: RustBox opens their RFC822/MIME content directly from IMAP (including external-client drafts), stages only the normal autosave/recovery state locally while editing, and replaces the source UID only after the new snapshot is appended and resolved safely. `X-RustBox-Draft-ID` remains an internal UID-resolution aid for RustBox-created snapshots, not a prerequisite for opening or editing a draft. - Drag-and-drop attachments with visible upload progress. Attachment uploads stream multipart chunks through `BlobStorage` with an enforced size limit instead of buffering the whole attachment in memory; filesystem and S3-compatible backends share the same logical-object flow. - Inline image upload using CID attachments, including paste and drag/drop of PNG/JPEG/GIF/WebP images into the composer. During editing, CID images use authenticated same-origin draft-attachment preview URLs and are serialized back to `cid:` references for saved/sent MIME content. Inline images can be resized, aligned left/center/right/inline and cropped in-app (GIF cropping is intentionally disabled to preserve animation); display-only resizing does not rewrite the source file. Unused CID attachments are cleaned when their image is removed from the editor. - Attachment reminder for common English/Polish wording. - Multiple identities. - Identity Reply-To, automatic Bcc, Organization metadata, text/HTML signatures and per-action signature rules/position; replies/forwards auto-select the matching identity from To/Cc/Delivered-To/Envelope-To when possible. - Composer From identity selection and signature insertion. - Outgoing priority (normal/high/low) and MDN/read-receipt requests are persisted in drafts and emitted consistently in SMTP delivery and the IMAP Sent copy; all envelope/header mailboxes are parsed before SMTP delivery. Administrators can also configure validated additional outgoing headers; structural/MIME headers and CR/LF-injected values are rejected. ### Search, labels and contacts - Tantivy/search backend retained. - Search operators including `from:`, `to:`, `subject:`, `folder:`, `has:attachment`, `is:read`, `is:unread`, `is:flagged`, `is:unflagged` and date filters. Active search terms are highlighted in sender, subject and snippet text using DOM text nodes rather than result HTML. - Advanced-search dialog and saved searches. - User labels/tags with validated HEX colors, message chips, context actions and bulk assignment. Optional native IMAP-keyword synchronization writes stable RustBox keywords only on folders advertising persistent custom-keyword support, imports observed RustBox keywords and provides an authoritative reconcile action that also applies remote removals only on confirmed keyword-capable folders. - Contacts CRUD/search with phone, job title, postal address, website and birthday fields. - Contact photo upload/remove/display (PNG/JPEG/WebP, 2 MB limit, MIME signature validation). - Contact groups, membership editing and group filtering. - vCard import/export includes the expanded profile fields and multiple e-mail/phone/address values. - Duplicate-contact detection checks primary and alternate e-mail addresses; merge keeps target data, alternate values, group memberships and a source photo when the target has none. - vCard attachments can be imported directly from a message attachment. - Composer To/Cc/Bcc fields use the existing contact/known-address autocomplete API with keyboard navigation. ### Sieve - ManageSieve raw script list/get/put/delete/rename/activate/deactivate/check. - STARTTLS, implicit TLS and explicit plaintext opt-in. - Quick filters generated from sender/domain/subject use an in-app wizard with condition/action preview, capability-aware actions, optional mark-as-read chaining, target-script selection, server validation and direct save/activation; an Advanced editor handoff remains available. The wizard explicitly states that Sieve changes apply to future incoming messages. - Visual rule builder with From/domain/To/Subject/List-ID/custom-header conditions, three-condition nested AND/OR grouping and per-condition negation. - Visual actions: move, copy, redirect, discard, mark read, add IMAP flag and keep, with an optional second action. - RustBox-generated visual rules carry stable markers and can be reordered by drag/drop or keyboard-accessible up/down controls without rewriting unrelated raw-script text. - Builder merges `require` extensions, disables actions unsupported by advertised server capabilities and validates generated scripts with the server. - Autoresponder/vacation builder supports subject, body, reply interval, mailing-list/automated-mail suppression and optional inclusive start/end dates using `currentdate` when the server advertises `date` + `relational`. - Sieve scripts can be backed up/restored as a validated RustBox JSON bundle; restore validates all scripts before writing, and saving over an active script requires an explicit application confirmation. ### Calendar and realtime - Calendar event CRUD UI with Month, Week, Day and Agenda views. - iCalendar/ICS import UI over the existing parser/backend, plus direct import from message attachments and full local ICS export. - Calendar event editor includes all-day mode, RRULE storage, attendees, organizer, status, reminder, meeting URL and color metadata. - Browser WebSocket client connected to the existing IMAP IDLE/event backend. - Realtime folder/message refresh for NewMessages/FlagsChanged/FolderUpdated events. - Desktop notifications, optional sound, per-folder selection and persisted Do Not Disturb hours. Aggregate unread count updates the browser-tab title and the application badge where the Badging API is available. - Account switch/remove/add workflow for multiple authenticated accounts in one browser session. - Active-session list across browsers while the RustBox process is running, with creation/last-active timestamps, friendly browser/device labels, full User-Agent hover detail, individual revoke and revoke-all-others. - Diagnostics panel exposing IMAP capabilities (including persistent custom-keyword support), authenticated SMTP connectivity, ManageSieve status, browser WebSocket state, local synchronization-cache timestamps/counts and live IMAP IDLE task/subscriber counts without returning server host names or credentials. Public liveness (`/api/health`) and local-storage readiness (`/api/ready`) endpoints are available for service supervision. - Optional administrator system diagnostics endpoint (disabled by default) supports explicit IP/CIDR allowlisting plus token/Basic authentication, redacts configured secrets, probes SQL/session/storage/search backends, reports active sessions and IMAP IDLE state, and surfaces bounded node-local security signals for failed logins, 403/429 responses and 5xx failures. - Search-index diagnostics expose cached/indexed counts, with a rebuild operation from the configured account-data backend. - IMAP reconnect control drops reusable request-path sessions and verifies a fresh authenticated connection. - Graceful SIGTERM/Ctrl+C shutdown stops accepting new requests and aborts dedicated IMAP IDLE tasks before process exit. ### Personalization - Persistent per-user display preferences in the configured application database. - Light/dark/system theme. - Presets: sage, blue, teal, cyan, indigo, slate, graphite, amber, orange, violet, rose, red and custom. - Custom accent, background, panel and text colors. - Font family and size, message row height, folder/message pane widths, border radius and contrast. Advanced controls include icon size, toolbar/sidebar density, reader/composer widths, selection color, unread font/badge styling, compact headers, border visibility, scrollbar density, monochrome mode and per-pane background overrides. - Date-format (locale/ISO/EU/US) and time-format (locale/24-hour/12-hour) preferences. - Compact/comfortable density, preview right/bottom/off, UI scale and reduced motion. - Avatar/attachment/flag visibility toggles. - Folder and message-list pane widths can also be adjusted directly with draggable splitters and persist through the existing per-user display preferences. Keyboard shortcuts are documented in an in-app reference dialog. ### Build/installation fixes in this snapshot - Fixed the `E0499` mutable-borrow failure in `mark_all_read`: the `uid_store()` stream is dropped before `session.logout()`. - Fixed a duplicate `else` introduced in the calendar delete handler during the calendar expansion. - All executable Rust SQL is centralized under `src/queries/{sqlite,mysql,pgsql}/queries.rs`, including session queries. ## Partially implemented - keep visible as incomplete - Sieve visual builder now supports a three-condition nested AND/OR group, negation, two actions, capability-aware disabling, managed-rule ordering and scheduled vacation dates. An arbitrary-depth condition tree, arbitrary-length action stack and full capability-aware condition/action matrix remain unfinished. - Composer autosave/recovery state is stored locally, while deliberately saved drafts are standard RFC822/MIME messages in the configured IMAP Drafts folder. IMAP drafts from RustBox or another client open directly in the composer; replacement is conservative (append/resolve first, then remove the prior UID after UIDVALIDITY verification). Wider real-server compatibility still needs the release gate. - Calendar is local/ICS-capable and stores recurrence/attendee/reminder metadata, but recurrence expansion/edit semantics, invitation responses and CalDAV synchronization are not finished. - Notifications are wired through IMAP IDLE/WebSocket, include permission status/test controls, and local calendar reminders can show browser notifications and play the configured sound while RustBox is open. Service-worker/background delivery is still not finished. - Identities emit Organization metadata; composer priority, MDN request headers and validated administrator-defined outbound headers are wired. SMTP DSN negotiation remains to be completed. ## Not yet complete - do not claim Roundcube parity - MOVE-based Undo is available for move/delete-to-Trash/archive/spam when the destination UID can be resolved unambiguously from pre-MOVE UIDNEXT plus exact Message-ID. A persistent multi-step undo history and servers/messages without a safely resolvable destination UID remain unfinished. - Contact model supports multiple e-mails/phones/addresses and duplicate merge UI; CardDAV and LDAP synchronization/UI remain. - OpenPGP roadmap scope is implemented end-to-end: per-user keyring, generate/import/export/delete, passphrase test/change, identity binding, sign/encrypt/sign+encrypt, PGP/MIME + inline PGP, verify/decrypt, trust/fingerprint UI, WKD and optional HTTPS HKP. Real `cargo test` and interoperability regression coverage are still release-gate work. - TNEF/`winmail.dat` decoding and full SMTP DSN negotiation are still not implemented. SMTPUTF8/IDN behavior still requires the real-server compatibility matrix from the release plan. - IMAP ACL/shared-folder management and full capabilities settings UI remain the next major protocol block. - Spam backend adapters for rspamd/SpamAssassin/custom command. - Calendar Month/Week/Day/Agenda views are present; recurrence expansion/exceptions, invitation response workflow and CalDAV remain. - Full CardDAV synchronization. - Password-change adapters remain unfinished. Session inventory/device metadata is now persistent across restarts and shared-session backends support cross-node listing/revocation. - Diagnostics now includes IMAP reconnect, SMTP connectivity, index rebuild and last local folder/message synchronization metadata; deeper background task/queue metrics and repair workflows remain. - Full live security, acceptance and performance matrix remains release-environment work tracked in `TODO.md`. ## UI reliability / workflow fixes in the current snapshot - Contact editor, calendar, raw-header and message-source dialogs use viewport-bounded layouts with independent scrolling and non-overlapping actions. Generic dialogs also fall back to whole-card scrolling when their content exceeds the browser workspace. Settings uses an explicit header + flexible-content grid so short panels no longer push the navigation/content block toward the bottom of the modal; settings navigation/content scroll independently when needed. - Month calendar grid and toolbar layout are responsive and remain usable under browser/UI scaling. - UI scale now affects font size, row height, pane widths, icons, field/button padding and control/header dimensions without being overwritten by the separate font-size setting. - Responsive layout keeps user-selected folder/message pane widths within safe viewport bounds instead of reverting to fixed widths. - The mobile composer keeps address labels and controls aligned, and the mobile folder drawer can be closed by its toggle, backdrop, Escape or folder selection while hierarchy disclosure controls keep larger touch targets. - Application actions have reusable success/error/warning/info toast feedback, including from within native modal dialogs. - Primary and bulk message toolbars include Spam / Not spam, driven by the configured Junk folder. - Reader includes Print, Source viewer and quick Create-filter-from-sender actions. - Reader addresses expose one-click contact actions; trusted senders can be added from a message so remote images load automatically unless the global policy is Never. - Header viewer shows a structured common-header summary and the raw header block. - vCard/iCalendar attachment SVG action icons no longer leak their markup as visible text; reader cleanup also strips only RustBox-owned icon-sprite fragments from malformed MIME content. - Message HTML receives an additional client-side sanitization pass before sandboxed iframe rendering; plain text is preserved exactly. - Embedded CSS/JS use content-fingerprinted URLs with `Cache-Control: public, max-age=31536000, immutable`; HTML and unversioned compatibility aliases remain `no-store`. - Native browser confirmation/text prompts are no longer used by the main UI workflows; destructive actions and folder/label/text choices use RustBox application dialogs. - Message selection has an explicit mode: per-row checkboxes only appear while selecting, with select-all and bulk actions grouped in the selection toolbar. - Search selection can materialize and select every cached matching result, not only the currently rendered page. - Folder/message list state now preserves the last folder, loaded-page depth and scroll position; active searches also retain their query and scroll position during normal realtime/refresh flows. - Network failures surface an offline/reconnecting banner. Only idempotent GET/HEAD requests receive bounded automatic retries; send/move/delete and other mutating requests are never auto-replayed. - Toasts with actions keep Undo and the close button adjacent in a dedicated action group so closing a toast cannot trigger Undo. - MOVE-based actions expose a toast Undo only when the backend can identify the server-assigned destination UID without guessing; bulk Undo reverses resolved moves in reverse order. - Thread lookup now validates complete References Message-ID tokens after the SQL candidate query, preventing partial-ID false matches. - Safe attachment previews stay inside a RustBox modal instead of opening a browser popup. - Composer uploads expose progress, clipboard images become CID inline attachments, and browser-local recovery preserves edits when a draft save fails. - Compact/comfortable density now visibly affects controls/toolbars/dialog headers without overwriting the separate row-height and pane-width preferences. - Toasts show the remaining auto-dismiss time and pause their countdown while hovered or keyboard-focused. - Appearance uses persisted `interface_skin` modes for RustBox (custom), Roundcube Classic, Roundcube Larry, Roundcube Elastic, Clean, Graphite and High contrast. The old Compact/Balanced/Comfortable/Reading preset cards were removed. Fixed interface styles apply their own visual geometry and palette without overwriting the user's stored RustBox custom values; selecting RustBox re-enables manual color, spacing, pane and typography controls. Classic Dark remains an adaptation because upstream Classic has no official dark skin. - Composing settings now persist the default format, autosave interval, default priority, default read-receipt request, attachment-reminder behavior, default font, reply placement, quote style, forward mode and browser spellcheck through display preferences. Saved/canned responses can be managed as text or sanitized HTML and inserted from the composer toolbar. - Message Print uses an in-page print frame instead of a popup and prints sanitized HTML or plain text with From/To/Date metadata.