# Compact clients and scheduled menu promotions Client summaries are compact, whole-card keyboard-accessible buttons. Name, phone, order count, turnover and loyalty discount remain visible; full addresses, orders and loyalty settings remain in the existing detail dialog. Search is retained. Menu editing now uses the ordinary price plus an explicit percentage or ruble discount, not a manually entered previous price. Duration presets (1, 7, 14, 30 days), an exact local date/time, and unlimited duration are supported. Existing finite promotions keep their original deadline when an unrelated field is edited. The editor validates values and previews the effective price and return deadline. `price` stores the ordinary price. `promotion` stores type, value, startsAt and endsAt (UTC instants). A shared pure price resolver calculates the effective price; at the deadline it returns the base price and no promotion badge. No background server write, open tab or cron is required. An open tab schedules the next boundary and rechecks after focus, visibility and cloud refresh. Saved order line price snapshots are not recalculated. The expiry event never writes orders or catalog. The client device clock is used, just like the existing app scheduling. Legacy price/oldPrice records retain their existing effective price and convert only when explicitly saved. JSON and spreadsheet catalog round-trips keep promotion metadata. Full JSON cloud payloads already preserve these fields; no migration, new permissions, database mutation or cross-project change is required. Regression coverage: compact client geometry/search/details; percentage and ruble validation; legacy conversion; fractional prices; exact deadline and reload; unchanged saved orders; foreground expiry without losing an unsaved editor. The production smoke uses fetched public assets with a synthetic, network-blocked workspace; no customer account or database is used for this verification.