← QuranFlow — the redesign

Sakīna Canvas — Consolidated Design Review & Adjudicated Resolutions

July 2026. Four parallel reviews (submission loop, schedule/time, comms/Today variants, appointments/onboarding/coach) audited the canvas after the F1–F5 screens (newer, built from the Apr–May coach-feedback synthesis) were added alongside the older sections (00–07). Findings below, each with an adjudicated resolution — these are decisions, not options. F screens are the source of truth wherever old and new conflict.

Status legend: ☐ todo · ✓ applied


A. Data contradictions (hard bugs — fix first)

A1 ✓ Duplicate revoke countdown

SakRecSubmitted (sak-recording.jsx:249-251) shows "Revoke window open · 9:12 left"; SakSubmissionPending (sak-feedback.jsx:361-375) shows "6:52 left" for the same submission. Resolution: Remove the inline revoke line from SakRecSubmitted entirely. Its "View my submission" CTA is the sole path; SakSubmissionPending owns all revoke UI. Keep the pending screen's countdown at 6:52.

A2 ✓ Week 7 lifecycle contradiction

SakSubmissionFeedback eyebrow says "Week 7 · Reviewed" (sak-feedback.jsx:198) while the SakSubmissions archive row for week 7 says status "practiced" (sak-extras.jsx:198). SakRecPractice is also scoped to Week 7. Resolution: Single timeline: week 7 = reviewed (feedback just arrived, not yet practiced — matches the feedback screen and practice screen). Change the archive row for week 7 to status: "reviewed". Weeks 1–6 in the archive stay practiced/heard as-is. Additionally add a week 8 row with status: "review" at the top of the archive (the in-flight submission SakSubmissionPending tracks), so the archive and the live loop agree. SubStatusPill (sak-extras.jsx:307-317) currently renders review and reviewed nearly identically — differentiate: review = muted/ink tint ("In review"), reviewed = warm/gold tint ("Feedback ready").

A3 ✓ Schedule day disagreement

Sessions tab (sak-schedule.jsx:17-23) puts all five week-8 items on Tuesday; SakWeekAtGlance (sak-feedback.jsx:486-498) spreads the same sessions across Mon/Tue/Thu/Sun. Resolution: F2's week layout is canonical: Mon 10:00 AM class "Idghām with ghunnah"; Tue 2:00 PM "Sisters' Reading Circle" + Tue 7:00 PM "Idghām review & practice"; Thu 9:00 PM "Drop-in Q&A"; Sun 11:59 PM submission deadline. Update the Sessions tab's Tuesday timeline to show only Tuesday's items (2:00 PM QRC, 7:00 PM class) plus a quiet trailing "Sunday · submission deadline" reference row is NOT needed — the day-strip owns other days. Update SakToday's "Sessions today" rows (sak-core.jsx:75-83) to the same Tuesday facts (2:00 PM QRC live-now can stay as the live example; second row = 7:00 PM class — adjust times/titles to match). The deadline on Today ("Due tonight · 11:59 PM EST", sak-core.jsx:621) becomes "Due Sunday · 11:59 PM".

A4 ✓ Coach identity: Rania vs Amina

F5 books the 1:1 with "Ust. Rania" (sak-appointments.jsx:77,154,207) while 25+ references everywhere else (onboarding, profile, recording, coach app) say Ust. Amina, and SakCoachSchedule (sak-coach.jsx:346) puts Sarah's recurring 1:1 on Amina's own schedule. Resolution: One coach. Sarah's coach is Ust. Amina for both async feedback and the Year-2 one-to-one. Rename Rania→Amina in sak-appointments.jsx (booking coach card becomes "Ust. Amina · Your coach" — keep the quiet "Change" link; changing coach is a legitimate affordance). The one legitimate Rania reference stays: SakCoachStudent's shared note "Ust. Rania · Week 6 · one-to-one" (sak-coach.jsx:302) — it demonstrates the cross-coach shared-notes requirement (a student may see a substitute coach); leave it.

A5 ✓ Timezone math between booking and coach schedule

Student books "Tuesdays 8:20 PM Toronto (EDT)"; coach schedule shows the same slot "4:20 PM Cairo (EEST)". EDT→EEST is +7h, so 8:20 PM Toronto = 3:20 AM Cairo. Wrong. Resolution: Change the student slot times to morning: booking grid becomes Tuesday 9:20 AM (selected) with neighbouring slots 9:00/9:40/10:00 etc., CTA copy "Book Tuesdays 9:20 AM · all 15 weeks". SakAppointmentDetail time = "Tue · 9:20 AM · 20 min". Coach side stays 4:20 PM Cairo (9:20 AM EDT + 7h = 4:20 PM EEST ✓).


B. Structural consolidation

B1 ✓ Today exists 7 ways — reduce to 1 component + named states

Canonical SakToday (sak-core.jsx), SakTodayRest (sak-states.jsx:18-95), SakTodayCountdown (sak-feedback.jsx:574-623), plus shoot-out B/C/D (sak-shootout.jsx). Glass reintroduces the "On track" pill banned by AUDIT rule R3. Resolution: (a) Remove section 07 from the canvas (main.jsx) and move sak-shootout.jsx to _archive/ — Manuscript (SakToday) is canonical per AUDIT.md; drop the <script> tag for sak-shootout.jsx from index.html. (b) Keep SakTodayRest and SakTodayCountdown as screens but visually align them to the canonical hero anatomy: same strip placement, same CTA slot conventions (countdown's "Add start date to calendar" stays its primary). Label them in main.jsx section 06 / F4 as "Today — state: rest day" / "Today — state: pre-semester" so it reads as one screen with states.

B2 ✓ Two "my week" surfaces

Sessions tab and SakWeekAtGlance both answer "what's on this week?"; Week-at-a-glance is an orphan (nothing routes to it). Resolution: Keep both, define the relationship: the Sessions tab's header calendar icon (sak-schedule.jsx:30) opens Week at a glance. Add a canvas annotation (DCPostIt or artboard sublabel) stating this routing on both artboards. Do NOT attempt a full merge in the mockup — the day timeline (zoom-in) and week list (overview) are two density levels of one surface; the spec will document that.

B3 ✓ Timezone treatment sweep

F2's banner ("All times shown in Toronto (EDT)") is the only correct treatment; bare "EST" strings survive in sak-schedule.jsx:290,300,301 (notif rows), sak-profile.jsx:238,246, sak-states.jsx:150, sak-core.jsx:621. Resolution: Delete every per-item "EST"/"EDT" suffix. Profile's timezone field becomes "Toronto · Eastern (EDT)" (one account = one city; Toronto is canonical, drop "EST · New York"). Notification rows show bare local times (the sheet inherits the app-wide local-time rule). Add the F2-style one-line zone banner to the Sessions tab header area (under the day strip, quiet, same copy pattern). Cohort line (sak-profile.jsx:246) becomes "Tuesday 2 PM local".

B4 ✓ Announcements exist in 3 places

Board (sak-comms.jsx), notif-sheet announcement rows (sak-schedule.jsx:301), settings toggle default OFF (sak-settings.jsx:52). Same schedule-change fact hardcoded twice with different copy. Resolution: (a) Settings "Announcements" toggle defaults ON. (b) Align the duplicated copy: both the board row and the notif row say "Thursday's Level Class moved to 11:00 AM". (c) The notifications sheet is the inbox; announcement-type rows deep-link to the board. Annotate this routing on the artboards. Keep both screens.

B5 ✓ "Message your coach" has 3 labels

"Send a question" (SakCoach, sak-extras.jsx:76-79), "Message" (SakProfile coach panel, sak-profile.jsx:104-113), "Write to your coach…" (thread composer). Resolution: Standardize the CTA verb to "Message" on both SakCoach (primary CTA becomes "Message Ust. Amina") and Profile's coach panel. Composer placeholder stays. Both route to SakMessageThread.


C. Orphaned screens / dead ends

C1 ✓ Announcements + Report-issue have zero entry points

Resolution: (a) Add an "Announcements" row to SakNotifSheet header area — a quiet "megaphone" row pinned above the New group ("Announcements · 1 pinned" with chevron), linking to the board. (b) In SakProfile's Support section (sak-profile.jsx:138-145), rename "Contact support" to "Report an issue" (it opens the SakReportIssue sheet — its auto-attached-context design supersedes a generic contact row). Keep "Help center" and "Resources".

C2 ✓ Appointments flow is an orphan

Nothing on Today/Sessions routes to SakBookAppointment/SakAppointmentDetail. Resolution: Add a "One-to-one" row to the Sessions tab's Tuesday timeline (the booked 9:20 AM slot, type chip "1:1", tinted like Hours) that drills to SakAppointmentDetail. Add an artboard annotation: "Year 2 only — Year 1 accounts never see 1:1 rows. Book flow entry: Sessions → calendar icon → 'Book your one-to-one' (also surfaced during Year-2 enrollment)."

C3 ✓ Practice loop dead-ends

SakRecPractice records a take with no next state (sak-feedback.jsx:451-467). Resolution: Reuse the existing review chrome: add a small "practice" variant state note — after recording, the student sees Play / Re-record / "Attach to feedback" (not "Submit to Ust. Amina") and no attempts dots (practice takes don't burn attempts). Implement as a new artboard "Practice — review take" in F1 using SakRecReview's components with the practice header (SakNavDrill "Week 7 · Practice") — do not modify SakRecReview itself.

C4 ✓ Orphaned session-detail frames

SakSessionDetail/SakSessionDetailQRC (sak-schedule.jsx:356-598) unreachable since rows became inline shelves. Resolution: Keep the components, but remove their standalone rationale confusion: annotate in main.jsx comments that they are notification-tap deep-link destinations (tapping a session reminder push opens the full page). No artboard changes needed; they aren't currently on the canvas.

C5 ✓ Availability grid is a fake onboarding step

SakOnbAvailability hardcodes SakDots total={6} done={4} and skips OnboardingShell (sak-appointments.jsx:263-271). Resolution: It is NOT part of first-run onboarding. Convert its header to SakNavDrill (eyebrow "Fall 2026 · Year 2", title "Availability"), remove the dots. Relabel the artboard in main.jsx F5: "Availability — asked during Year-2 booking". Core onboarding stays 6 steps.


D. Consistency debts

D1 ✓ Coach schedule doesn't distinguish fixed vs flex bookings

Resolution: In SakCoachSchedule, Sarah's row keeps "Recurring · Week 8"; Khadija's row gets "This week only" in the same slot — one-word vocabulary: Recurring / This week only.

D2 ✓ Bespoke audio primitives linger

SakRecReview hand-rolls a 54px play circle (sak-recording.jsx:174-180) instead of FbPlayBtn. Resolution: Swap it for FbPlayBtn. (Mic buttons: leave the three bespoke mic buttons as-is for the mockup; note in spec that production should share one component.)

D3 ✓ AUDIT.md has no entry for the F screens' anchors

Resolution: Append a short "F-screens" table to AUDIT.md's per-screen log after all fixes land (anchor + status ✓), and log the resolutions applied from this file.


Out of scope for the mockup (documented in the spec instead)