Skip to content

UI Professionalization Audit β€” Aldilaijan & Khobara App ​

Date: 2026-07-18 Scope: Full Flutter frontend β€” lib/ (~900 Dart files, ~272 screens, 48 feature modules), theme layer, shared primitives, all feature clusters, plus an external benchmark review (premium SaaS + Arabic/RTL enterprise standards). Method: 9 parallel specialist audits (theme system, core widgets, shell/nav, properties, public web, CRM/comms, valuations/finance/admin, quantitative hardcode sweep, design-benchmark research).


1. Executive Summary ​

The foundation is not generic β€” the adoption is. The app already owns the assets of a professional product: a generated design-token pipeline (lib/core/theme/tokens.dart), a hand-built 30-slot Material 3 ColorScheme (not ColorScheme.fromSeed), a distinctive 5-font type system (Readex Pro / Plus Jakarta Sans / Cairo Arabic fallback / Noto Naskh / IBM Plex Mono with tabular figures), a bespoke SVG icon family (Daleel), a real illustration system, and flagship surfaces (PropertyCard, WhatsApp inbox, deals kanban, auth backdrop) that are genuinely well designed.

What makes it read as generic in practice is a consistent set of leaks and contradictions:

  1. Stock Material leaks through the seams β€” unthemed tooltips/menus/date-pickers, 2,237 default Icons.* usages vs only 27 bespoke DaleelIcons uses, default spinners next to bespoke skeletons.
  2. Tokens are bypassed at scale β€” ~4,500 raw spacing call sites (only ~16% adoption of AkSpace), 500 raw BorderRadius.circular, 807 inline TextStyle, and ~230 off-grid values that silently break the 4px rhythm.
  3. Sibling screens improvise their own idioms β€” three different metric tiles, two chip dialects, three divider rules, rogue private palettes.
  4. Dev-build artifacts are visible to users β€” untranslated intake/qualify/execute wire strings on chips, hardcoded 'en_GB' dates in 19 files, a πŸ‘ emoji in a list tile, raw '$e' error text.
  5. Arabic/RTL polish gaps β€” 14 synthesized (fake-slanted) italic sites, toUpperCase() + letter-spacing applied to Arabic, Icons.chevron_right never mirroring (14+ sites).
  6. The brand system contradicts itself β€” dead amber/navy dual-brand tokens still generated while the app is unified navy/cyan; amber map pins leak; the "cyan points, navy fills" rule is violated by a full-width cyan selection bar.

Bottom line: this is not a redesign problem β€” it is a convergence problem. The fastest path to a professional look is (a) closing the unthemed-component gaps, (b) enforcing token discipline with codemods + lints, (c) unifying the 3–4 competing idioms per pattern into the kit that already exists, and (d) eliminating the dev-look artifacts. A phased roadmap with effort estimates is in Β§5.


2. What's Already Professional (keep and extend) ​

AssetEvidenceWhy it matters
Canonical token filelib/core/theme/tokens.dart (hand-authored; no generator, no upstream), re-exported via ak_scheme.dartSingle source of truth for this repo; values can't drift between the Ak layer and the palette
Hand-built ColorSchemecolor_scheme.dart:1-32, all surfaceContainer* tiers filledDeliberate anti-generic choice; dark mode is a real designed scheme
5-font type systemtext_theme.dart:22-115, fonts bundled in pubspec.yaml:356-400Signature typography; Arabic fallback wired into every style; tabular figures for data
TokenCard hairline aesthetictoken_card.dart:51-98; elevation-0 + hairline border + ink-tinted shadowThe "one product" surface language β€” exactly the Stripe/Vercel pattern
Daleel bespoke iconsdaleel_icons.g.dart, RTL auto-mirroring, line/solid weightsA custom icon family exists β€” it is purely an adoption problem
Illustration systemillustrations.dart:97-288 (14 slots, currentColor SVG + painters)Empty states can look bespoke everywhere
Flagship surfacesproperty_card.dart, whatsapp_inbox_screen.dart:631-786, deals_kanban_screen.dart:204-455, auth_backdrop.dart:55-115Proof the team can hit professional bar; these are the reference standard

3. The Generic-Look Drivers (ranked by visual impact) ​

3.1 Stock Material leaking through the seams ​

  • 13+ component themes missing β€” no tooltipTheme, popupMenuTheme, menuTheme, checkboxTheme, radioTheme, datePickerTheme, timePickerTheme, drawerTheme, dataTableTheme, expansionTileTheme, searchBarTheme, textSelectionTheme in component_themes.dart. Every tooltip, overflow menu, and date picker renders stock M3 gray-blue.
  • Default icon domination β€” 2,237 Icons.* hits across 386 files vs 27 DaleelIcons uses in 7 files (mostly bottom nav). Quick actions mix shopping_cart_outlined, beach_access_outlined, construction_outlined (dashboard_quick_actions.dart:104-200). The single biggest generic-look driver.
  • Default spinners next to bespoke skeletons β€” ceo_dashboard_screen.dart:64, agent_dashboard_screen.dart:42, engagements_list_screen.dart:99, smart_alerts_screen.dart:35 use bare CircularProgressIndicator while siblings use CardSkeletonList.
  • 56% of empty states use stock icons β€” 139 EmptyState( calls but only 61 pass a bespoke illustration:; default is Icons.inbox_outlined at 56px (empty_state.dart:24,80-82).
  • Two parallel toast systems β€” stock SnackBar for errors (error_snackbar.dart:27-33) while the styled AkToast exists (ak_feedback.dart:101-139).

3.2 Token adoption gap (the "almost aligned" amateur feel) ​

  • Spacing: ~1,874 EdgeInsets + ~2,639 numeric SizedBox sites; AkSpace used in only 143/900 files. Off-grid values (14 Γ—73, 10 Γ—69, 6 Γ—54, 3, 5, 7, 9, 13…) silently break the 4px grid. Worst files: valuation_workflow_screen.dart (56), hermes_dashboard_screen.dart (50), properties_filters_sheet.dart (37).
  • Radius: 500 raw BorderRadius.circular(N) in 199 files (worst: add_property_screen.dart 15, site_inspection_screen.dart 13).
  • Type: 807 inline TextStyle( across 226 files re-specifying size/weight (worst: comparables_screen.dart 25, site_inspection_screen.dart 24), incl. fractional sizes 13.5/12.5/10.5/9.5 in comms screens.
  • Color: 182 stock Colors.* hits in 90 files (data_completeness_screen.dart Γ—11 green/orange), 45 hardcoded Color(0x…) outside the theme, and a rogue 17–20-color private theme in launch_checklist_screen.dart:29-49.
  • Buttons: AkButton used in only 10 files; 47 per-screen styleFrom overrides in 29 files.

3.3 Competing idioms for the same pattern ​

  • Metric tiles Γ—3: AkMetricTile vs _MiniMetric tonal box (dashboard_welcome_panel.dart:204-211) vs raw Card(margin:4) (ceo_dashboard_screen.dart:269-275).
  • Chips Γ—2: tokenized BrandChip vs raw ChoiceChip/FilterChip one nav level apart (engagements_list_screen.dart:160, filter_primitives.dart:75-87).
  • Dividers Γ—3 rules: indent 16 / indent 76 / full-bleed across deals, WhatsApp, reminders.
  • Sheets Γ—2 chrome: quick-add sheet bare (shell_quick_add_sheet.dart:12-15) vs tools sheet with drag handle + radius 20 (bottom_nav_tools_sheet.dart:83-90).
  • Cards: raw Card() beside hairline TokenCard on the same screens (property_detail_tabs.dart:842,1008, showcases_list_screen.dart:104, contact/services/about public pages).

3.4 Dev-build artifacts visible to users ​

  • Untranslated wire strings as labels: Text(p.wire) / row.phase.wire render raw intake/qualify/execute in the Arabic UI (engagements_list_screen.dart:212,288).
  • Broken i18n keys: reports hub tiles render English-only in Arabic (reports_hub_screen.dart:220 passes human strings to l.t('reports.$titleKey')).
  • Hardcoded 'en_GB' dates: 25 sites in 19 files (English "MAR" in Arabic UI) despite a locale-aware helper existing at core/formatting/app_dates.dart:27-30.
  • Emoji in UI: raw πŸ‘ in showcases_list_screen.dart:104-123; raw '$e' error text in invoice_revenue_chart.dart:67-70.
  • Dead code telling on itself: color: featured ? scheme.primary : scheme.primary (public_tool_tile.dart:41).

3.5 Arabic / RTL polish gaps ​

  • Synthesized italics: 14 FontStyle.italic sites but only upright fonts registered β€” Flutter fake-slants Arabic glyphs (individuals_list_screen.dart:917, tiptap_parser.dart:187).
  • Latin-only idioms applied to Arabic: toUpperCase() + 0.8 letter-spacing in section_divider.dart:42-46 (Arabic has no case; spacing breaks cursive joining); same in notifications_screen.dart:404-416.
  • Non-mirroring chevrons: Icons.chevron_right (never auto-mirrors) at 14+ drill-in sites incl. smart_alerts_screen.dart:121, deal_detail_screen.dart:301, public_landing_screen.dart:386,514.
  • LTR/RTL inconsistency: EdgeInsets.fromLTRB (brokerage_drawer.dart:65) vs EdgeInsetsDirectional (khobara_drawer.dart:46); internal chat bubble tail uses non-directional corners β€” tail on the wrong side in RTL (internal_chat_thread_screen.dart:221-226).
  • Numeral-locale strategy undefined: Kuwaiti/Saudi enterprise convention is Eastern Arabic numerals (Ω Ω‘Ω’Ω£); dates currently hardcode en_GB. Numbers/phones must stay LTR inside RTL.

3.6 Brand-system contradictions ​

  • Dead dual-brand ramps: AldilaijanTokens (amber) / KhobaraTokens still generated while color_scheme.dart:15-18 declares one unified navy/cyan palette; amber leaks onto map pins (daleel_pin.dart:176,350); stale comment promises gold accents (app.dart:30-32).
  • Brand-blind accent rail: the 2px rail on every app bar (app_bar.dart:103) is hardwired to unified cyan β€” the most visible brand signal ignores brand mode.
  • MultiSelectBar violates the documented "navy fills, cyan points" rule with a full-width cyan slab (multi_select_bar.dart:41-74).
  • Hardcoded AkColors.cyan on shared widgets (deal_detail_stepper.dart:70, mailbox_screen.dart:132,463) instead of scheme.primary.

3.7 Missing professional patterns ​

  • No real data tables β€” invoices, AR aging, audit log, admin users all use ListTile lists (35+ sites); ledgers read as chat lists. Only bulk_valuation_screen.dart uses DataTable.
  • Flat settings/admin IA β€” settings is one 543-line flat ListView with 12 identical chevron tiles (settings_screen.dart:190-319); admin hub is a raw 24-row list (admin_config_hub_screen.dart:153-164).
  • Drawers are stock NavigationDrawer β€” no brand block, no grouping, no user footer (brokerage_drawer.dart:28, khobara_drawer.dart:25); nav rail carries no brand mark.
  • Public landing is a stretched mobile screen β€” 640px-capped text column, no property imagery, icon-in-circle ListTiles for featured listings (public_landing_screen.dart:69,111-173, public_property_tile.dart:36-44).
  • Timeline with no timeline β€” interactions are divider-separated rows, no rail/nodes/date grouping (interaction_timeline.dart:108-277).
  • One listing density β€” the compact PropertyListTile exists but is never instantiated; no grid/compact toggle.
  • Wizard progress is stock M3 β€” bare LinearProgressIndicator + "N of M" (property_form_screen.dart:3030-3059).

4. Benchmark Scorecard (2025–26 premium SaaS + Arabic enterprise standards) ​

#Quality (benchmark)VerdictNotes
1Signature custom font identityβœ… PASSReadex Pro / Jakarta / Cairo stack, bundled
2Arabic-first font stack (no system fallback)βœ… PASSCairo fallback on every style
3Per-script type tuning (Arabic line-height 1.6–1.8)βœ… PASStext_theme.dart:16-17,83-85
4No positive letter-spacing on Arabic❌ FAILsection_divider.dart:42-46, notifications_screen.dart:404
5Weights ≀3, hierarchy via size/tracking⚠️ PARTIAL807 inline TextStyles improvise weights
6Tabular numerals on all data⚠️ PARTIALStrong on KPIs; fractional raw sizes elsewhere
7Deliberate numeral-locale strategy (Ω Ω‘Ω’Ω£ for KW/SA)❌ FAILen_GB hardcoded Γ—25; no Eastern-Arabic policy
8Single accent discipline⚠️ PARTIALAmber leak, cyan slab violations, raw greens
9Neutral-first palette, no stock Material hues⚠️ PARTIAL182 Colors.* leaks in 90 files
104/8pt grid, token-only spacing❌ FAIL~4,500 raw sites, ~230 off-grid values
11Consistent density rhythm❌ FAIL3 metric-tile densities; per-screen improvisation
12≀3 elevation levels, hairline borders over shadowsβœ… PASSTokenCard idiom + shadow discipline (9 literals)
13Conservative radius scale, token-only⚠️ PARTIAL500 raw radii incl. off-scale 10px
14One icon family, RTL-mirroring policy❌ FAIL2,237 stock icons vs 27 bespoke; chevrons don't mirror
15Logical-property RTL correctness⚠️ PARTIALMostly good; drawers/chat tail/LTRB leaks
16Motion spec (150–250ms), hover/focus states❌ FAILMotion tokens adopted in 5 files; 62 hardcoded durations
17Status via tinted chips, not saturated fills⚠️ PARTIALStatusBadge does this; raw Colors.green/orange bypass
18Bilingual parity (real Arabic content everywhere)❌ FAILWire strings, English dates, broken report keys

Score: 4 pass / 7 partial / 7 fail. Every FAIL is an adoption/enforcement fix, not a redesign.


5. Roadmap: Generic β†’ Professional ​

Phase 0 β€” Kill the dev-look artifacts (1–3 days, pure polish-per-effort) ​

Status 2026-07-18: shipped. All 10 items landed (full flutter analyze clean, 3410/3410 tests). Notes: items 7, 8 and 10 were already conformant in-tree and were verified rather than re-done; item 2's numeral policy was already decided in app_dates.dart (Western digits in both locales) β€” 71 hardcoded-locale date sites across 57 files were routed through it, while 33 NumberFormat('en_GB') sites were deliberately kept (the pinned locale is what forces Western digits); item 9's 4 named sites were already skeleton-based, so the next 4 worst full-page spinners (reports dashboards) were converted instead.

  1. Engagements: translate phase labels, never render .wire (engagements_list_screen.dart:212,288).
  2. Centralize dates through app_dates.dart; sweep all 25 'en_GB' sites. Decide the numeral-locale policy (Eastern Arabic for ar-KW/ar-SA) in the same helper.
  3. Fix reports hub i18n keys β†’ existing camelCase set (reports_hub_screen.dart:24-225).
  4. Sweep Icons.chevron_right β†’ direction-aware chevron (shared TrailingChevron widget); fix the public landing pair first.
  5. Replace Colors.green/orange/shade600 with SharedTokens.status* / AkColors in data_completeness_screen.dart, follow_up_dashboard_screen.dart:492-505, price_index_screen.dart:302, property_portfolio_screen.dart.
  6. Remove πŸ‘ emoji (showcases_list_screen.dart), route raw '$e' through ErrorState.
  7. daleel_pin.dart:176,350 amber β†’ cyan/warning tokens; fix stale brand comment in app.dart:30-32.
  8. MultiSelectBar cyan slab β†’ navy fill (multi_select_bar.dart:41); AkBadge(solid) Colors.white β†’ scheme.onPrimary.
  9. Swap the 4 bare CircularProgressIndicator full-page loads for CardSkeletonList.
  10. Add tooltipTheme + popupMenuTheme + textSelectionTheme to component_themes.dart (~25 lines, kills the most frequent stock-Material sightings).

Phase 1 β€” System hardening: close the leaks (1–2 weeks) ​

  1. Complete component_themes.dart: menu, checkbox/radio, date/time picker (incl. Hijri), navigation bar, drawer, data table, expansion tile, search bar themes.

    Status 2026-07-18: shipped. timePickerTheme (dial hand as cyan selection point), navigationBarTheme (soft navy-wash indicator), drawerTheme (directional 16px open-edge radius), dataTableTheme (recessed header + hairline rules), expansionTileTheme (flat, no stock-grey fill), and searchBarTheme (input-matching recessed fill + hairline) joined the existing menu/checkbox/radio/datePicker set. Remaining gap: the custom HijriDatePicker's on-system pass (Phase 2 item 8).

  2. Codemods to tokens: raw spacing β†’ AkSpace (start with the 5 worst files β‰ˆ180 hits); off-grid values snap to the 4px grid (or add intermediate tokens to tokens.json); 500 raw radii β†’ AkRadius; inline TextStyle β†’ textTheme roles (add a labelSmall-adjacent micro role where 10–11px recurs).

    Status 2026-07-18 (radii, wave 1): exact-scale radius codemod shipped β€” 102 files fully migrated to AkRadius (4β†’sm, 8β†’md, 12β†’lg, 16β†’xl, 999/1000/9999β†’full) and removed from the burn-down list, zero pixel changes. Remaining 75 files/225 hits carry off-scale values (10, 6, 20, 14, 3, 2 …) that need the snap-vs-new-tokens decision (intermediate RadiusTokens slots via tokens.json regeneration) β€” deliberately untouched in this wave. Status 2026-07-18 (spacing, wave 1): exact-scale spacing codemod shipped β€” 5,314 call-site args rewritten to AkSpace across 383 files (132 fully migrated), zero pixel changes. New raw_spacing ban added to audit_design_tokens_test (6th class); remainder 254 files/989 hits (off-grid 6/10/14/2/3… + multiline calls) allowlisted for wave 2 (snap or new SpacingTokens slots β€” 6, 10, 14, 2 are the obvious candidates). TextStyle codemod not started. Status 2026-07-18 (wave 2 β€” conservative snap): with design-tokens/tokens.json absent from this repo, new intermediate slots were impossible β€” so off-grid values ≀2px from a scale slot were snapped (radius 5/7/9/10/14/18/20 β†’ sm/md/md/md/lg/xl/xl; spacing 5/7/9/10/14/18 β†’ s1/s2/s2/s2/s3/s4), max delta 2px except radius 20β†’xl (βˆ’4, lands on the 4px grid). Zero test/overflow failures. Radii 75 β†’ 47 files/145 hits, spacing 254 β†’ 217 files/626 hits. Remainder: ties (6), hairlines (1–3), multiline calls β€” these genuinely need intermediate token slots, deferred until tokens.json is back in-tree.

  3. Custom lints / CI greps: ban raw EdgeInsets.all(<num>), BorderRadius.circular(<num>), Color(0x…), Colors.green|orange, hardcoded Duration(, and FontStyle.italic outside lib/core/theme/. Add MotionDurations enforcement (62 literals today).

    Status 2026-07-18: shipped (5 of 6 bans). test/tool/audit_design_tokens_test.dart enforces status hues (Colors.green/orange/amber β€” 0 hits, enforced clean), Color(0x…) (9 files), BorderRadius/Radius.circular(<num>) (75 files/225 hits after the wave-1 codemod), Duration(<num>) (61 files/102 hits), and FontStyle.italic (13 files/14 hits) via burn-down allowlists in test/tool/design_tokens_allowlists/ (same only-shrinks mechanics as the formatters audit). Deferred: the EdgeInsets.all(<num>) ban β€” 4,500 raw spacing sites make the allowlist dead weight until the item-2 codemods burn it down.

  4. Delete rogue palettes: _ChecklistTheme (20 colors), animated_splash.dart literals, dead AldilaijanTokens/KhobaraTokens ramps from tokens.json.

    Status 2026-07-18: shipped. _ChecklistTheme deleted β€” launch checklist now reads the shared DS dark ramp + status hues (gold accent β†’ unified cyan). Splash gradient/overlay literals snapped to AkColors navy/cyan aliases. Dead ramps removed from tokens.dart with a hand-edit note (the generator input design-tokens/tokens.json is not in this repo β€” if a regeneration ever happens, delete the ramps at the source instead). raw_color_literals burn-down: 9 files/40 hits β†’ 7 files/15 hits.

  5. Unify idioms into the kit: one MetricTile (+ compact variant), one chip (BrandChip with multi-select mode), one AkListDivider, one sheet chrome, one toast (AkToast), one FAB theme, AkButton variants absorbing the 47 styleFrom overrides.

    Status 2026-07-18 (slices 1–2): MetricTile gained icon/accent/compact; migrated the 5 private _StatChip families (14 sites), _MiniMetric (3), and ceo_dashboard's raw-Card _Tile (10). New AkListDivider (full-bleed / .content() / .afterLeading()) replaces the indent-16/indent-76/full-bleed divider idioms in deals, WhatsApp inbox, reminders. BrandChip absorbed the raw ChoiceChip/FilterChip sites (engagements Γ—4, filter_primitives multi-select). Tools sheet's manual drag handle + radius-20 shape deleted (showAppBottomSheet's themed chrome wins). 2 raw Card() sites in property_detail_tabs β†’ AkCard. Status 2026-07-18 (slice 3 β€” buttons): AkButton extended with accent (info fill), success, dangerGhost variants, xs size (36px floor), and a loading busy flag; 18 styleFrom sites absorbed across two rounds (danger reject/discard, approve, 5 accent AI buttons, 3 loading submit/send, 3 destructive ghosts, dense/dense-block actions). Remaining ~22 overrides are deliberately bespoke and documented: tonal constructors (no variant), sub-36px density (below the a11y floor), circular/aligned one-offs, WidgetStateProperty styles, and the brand-cyan add-property CTA (brandAccent gap). Sheet/toast/FAB were already unified (showAppBottomSheet + bottomSheetTheme, AkToast, floatingActionButtonTheme). Status 2026-07-18 (rounds 4–5 β€” metric tiles, COMPLETE): the metric-tile family is unified β€” 32 more private classes migrated (dense chips β†’ MetricTile compact, hero stacks β†’ standard), totaling 54 classes eliminated across the epic. Documented remainders: valuation_data_quality's 18 key-value rows (needs an AkKeyValueRow pass), the two FittedBox scale-to-fit tiles (S-015 fix β€” needs a scale slot), block_renderer._MetricTile (unit-suffix slot), and entity scorecard/progress-bar tiles (not KPI tiles). Judgment calls: valuation_stats accent colors icon+value; individuals warning conveyed by error-colored value.

  6. Arabic emphasis: replace all 14 italics with a weight/color emphasis helper; locale-gate caps/letter-spacing in SectionDivider/_SectionLabel.

    Status 2026-07-18: shipped. Caps/letter-spacing were already locale-gated via core/i18n/locale_text.dart (Phase 0). All 12 UI-chrome italics (11 files) dropped in favor of the muted color already present (the honest de-emphasis); AkType.strong/AkType.soft added as the documented Arabic-safe emphasis helpers for future needs. Remaining 2 hits are deliberate keepers β€” tiptap_parser + block_renderer preserve user-authored italic marks (content fidelity), allowlisted with reasons. Burn-down: 13 files/14 hits β†’ 2 files/2 hits.

  7. Dark-mode status tints: per-brightness successTint/warningTint/dangerTint pairs on AkScheme.

    Status 2026-07-18: shipped. AkScheme now carries successTint/warningTint/dangerTint/infoTint (info included to complete the family); dark values are 22% washes of the status hues over surfaceDark, mirroring the light tints' restraint. All 17 consumer call sites (13 files) migrated from the light-only AkColors.*Tint constants to AkScheme.of(context).*; the shared aiPricingDataAccentLight const alias was retired in favor of context reads.

Phase 2 β€” Flagship surface upgrades (2–6 weeks, highest visible payoff) ​

Status 2026-07-18: PHASE COMPLETE (8/8 items shipped in one day). Full suite 3424/3424 green after every item; each shipped with its own commit.

  1. Brand the frame: AkDrawer (brand block + grouped sections + user footer) for both brands; brand mark on ShellNavigationRail; wire brand accent rail to AkScheme.of(context).

    Shipped (45230f94): AkDrawer widget with mode-flipping brand block, SectionDivider groups, user footer (avatar + settings shortcut); both drawers rebuilt on it; rail brand mark + tools FAB β†’ DaleelIcons.grid.

  2. Data-table/ledger component (AkDataRow β†’ sortable DataTable on wide) for invoices, AR aging, audit log, admin users; document-grade line-items tables on invoice/quotation details.

    Shipped (2cbd1c5c): AkDataTable<T> primitive (narrow cards / wide sortable DataTable); 4 screens migrated; invoice + quotation detail gained line-items sections (new repo list fns + providers); 6 component tests.

  3. Settings/admin IA: grouped TokenCard sections (iOS/Linear-style) for settings and the 24-row admin hub.

    Shipped (da164e80): both screens grouped (SectionDivider + TokenCard + hairlines); admin hub into 4 labeled groups with new adminConfig.groups.* keys.

  4. Public web: responsive two-column hero with real property imagery (break the 640px cap), photo-based PublicPropertyTile, real featured-tile hierarchy in the tools grid, unified PublicScaffold chrome, AuthBackdrop carried through the OTP step.

    Shipped (3812824e): two-column hero β‰₯840dp with featured-property photo; photo tiles; MoJ hero tile; new PublicScaffold unifying marketing chrome (OTP already had the backdrop). Follow-up noted: 21 calculator/portal screens still on raw AppBar.

  5. Properties: listing density toggle (wire the dead PropertyListTile as compact view / 2-col grid β‰₯720dp), property-detail facts row + display-family name, labeled wizard step indicator, sequential heat ramp for the heatmap, gallery empty state.

    Shipped (ce437b2c): all 5 sub-items (density toggle + 2-col grid, facts row, labeled wizard steps, sequential heat ramp, gallery EmptyState).

  6. CRM: interaction timeline with rail + channel nodes + date grouping; internal chat rebuilt on AkMessageBubble (fixes RTL tail); reminders re-skin with severity bar + Overdue/Today/Upcoming sections; fix kanban desktop width bug (deals_kanban_screen.dart:205).

    Shipped (391bd910 + 569da33b for the kanban width fix): timeline rail + Daleel channel nodes + date groups; chat on AkMessageBubble; reminders sections with severity bars.

  7. Icon coverage: extend Daleel glyphs to quick actions, tools sheet, rail FAB, notifications bell; set the policy "Daleel for domain glyphs, Icons.* only for generic chrome."

    Shipped (11207bd9): tools sheet glyph-aware, quick-add 7/8 Daleel, FAB β†’ pencil, 8 new destination glyph mappings; policy stated in daleel_icon.dart.

  8. HijriDatePicker on-system: AkDialog wrapper, InkWell cells, token radii/spacing, β‰₯9.5px secondary numeral.

    Shipped (e744e5c6): AkDialog wrapper (+scrollable-body hardening), InkWell cells, 9.5px secondary numeral.

Guardrails (permanent) ​

  • Token-only policy enforced by the Phase 1 lints; treat violations as build failures.
  • Extend the existing overflow/golden test catalog (test/overflow/screen_catalog.dart) with dark-mode + Arabic snapshots per screen.
  • Visual review checklist per PR: tokens only, Daleel icon policy, skeleton not spinner, mirrored chevrons, locale dates, no raw strings.

Remaining-work close-out (2026-07-18) ​

All follow-ups shipped. PublicScaffold sweep (23 calculator/portal screens; 3432fa83), AkKeyValueRow + onTap for valuation_data_quality (d66dc842), MetricTile unit/fit/background slots with their consumer migrations (31124b2b), AkButton brandAccent/secondaryDanger/tonal + AkIconButton filled-loading (a517cb5d), and the dark-lane overflow catalog (241 screens Γ— 2 themes Γ— 6 widths Γ— en/ar, zero new skips; 29dcf88d).

Wave-3 token burn-down (f3f6c193): radii 140β†’51 hits (documented micro-radius keepers), spacing 595β†’235 hits (the 6β†’s1 snap alone took 352), durations 102β†’82 hits (new MotionDurations.gentle=300; timeouts/debounce/choreography kept with concrete reasons), color literals 15β†’14 hits (5 documented keepers + persona gold). What remains on the lists is deliberately kept raw with per-file reasons β€” the lists are now exception registries, not debt.

Not agent-actionable (needs humans): native Kuwaiti-Arabic review of the ~135 l.* keys; TestFlight beta + on-device QA (mailbox, voice notes); Add Property submit path (product decision on Arabic-prefixed properties_base columns); comparables subject/chart/AI-estimate pipelines (3 backend pipelines needing product specs).


6. Module-by-Module Highlights ​

  • Theme system β€” Excellent bones; gaps are unthemed components, dead brand ramps, unadopted motion tokens, light-only status tints.
  • Core/shared widgets β€” TokenCard, Daleel icons, illustrations, ErrorState are the standard; AppBar hardcodes title type, MultiSelectBar breaks the color rule, Avatar hash-hues clash with palette.
  • Shell/nav β€” Custom bottom nav is genuinely designed; drawers and exec dashboards are the weak link (stock drawer, 3 metric idioms, spinner loads).
  • Properties β€” PropertyCard/detail hero are premium; radius/token leaks, stock filter chips, dead compact tile, and a control-panel header (~40% of viewport) hold it back.
  • Public web β€” Auth/splash/onboarding are the brand high-water mark; landing/tools/OTP are where the "generic Flutter web" impression concentrates.
  • CRM/comms β€” WhatsApp/mailbox/comms are a designed product; reminders/timeline/internal-chat/engagements are stock Material lists β€” closing the gap is mostly reusing the existing kit.
  • Valuations/finance/admin β€” Chart house style + mono money type are fintech-grade; the absence of real tables, flat admin/settings lists, and broken report i18n are the gaps.

Full per-module evidence (file:line) is preserved in the audit working notes; every claim above cites its source inline.

Aldilaijan & Khobara Real Estate Platform