File: stage-4-19-standards-and-validation.md
Kestrel Medical: Standards and Validation (Stage 4)
Re-run 24-Oct-26 for Business Requirements v1.3 (Adam approved Sharon's change): Average discount off list price on big deals shows 17.03%, its trend, "Target set in Phase 2" and a neutral "Not rated: target open". No target, path to 14%, gap, pace or status colour. Jennifer's fixes were re-applied to Viktor's rebuilt page; three of her exact text replacements were adjusted to Viktor's new wording (item 1 below), with the same shortening.
Test case, Sample data. This report now covers Experimental A (the dot swarm circle of lost tenders), chosen by Adam on 24-Oct-26. It replaces the Standard version's report. Built by Jennifer (Stage 4) from Viktor's Experimental A dashboard, Business Requirements v1.3, Calculation Pack v1.2 and the saved Monochrome blue and Charcoal and teal palettes. No story line, KPI, number or chart was changed.
Date: 24-Oct-26 (re-run) · Output: 02 - Deliverables/2026.10.23 - Kestrel Medical - 04 Dashboard.html · Re-run: 03 - Working Files/jennifer_finish.py (fixes), jennifer_checks.py (widths, errors), jennifer_screenshots.py (screenshots)
1. Verdict
- Both standards: all clear-cut items fixed, and Adam's 4 items approved on 24-Oct-26 and applied (section 5). Still failing: 9 long caption and definition lines (not in the main flow), and core content drawn by script (accepted)
- Validation checklist: 5 of 5 pass, with the four Phase 2 KPIs recorded as "Phase 2 placeholder, as documented"
- Width sweep: 56 checks (14 widths from 375 to 1600, dark and light, sections closed and open): 0 sideways scrolling, 0 elements poking out, 0 controls under 44px, 0 script errors
- Nothing published
2. Palette
- Monochrome blue throughout (default). Accent, surfaces, lines and the growing and going backwards bars are the saved values, dark and light
- Charcoal and teal on the six scoring areas (3 or more categories), in fixed slots: service and support teal, price coral, then clinical fit, supply reliability, training, sustainability. Same colour on every chart they appear in, including the circle of 25 lost tenders (legend underneath names each colour with its count)
- Status colours (green, amber, red) only on the one rated tile (Revenue growth on the year, Off track), always with an icon and a word
- Checked in both modes: lowest text contrast 5.07 to 1 dark, 4.80 to 1 light (target 4.5 to 1)
3. What Jennifer fixed (clear-cut, all in jennifer_finish.py)
| # | Fix | Why (standard) |
|---|---|---|
| 1 | Phones: tiles now sit one per row. Before, the number and sparkline on tiles 2, 3 and 4 ran past the tile edge and were clipped at 375px | UX 1 and 2: fits without clipping on phones |
| 2 | Value labels on long bars (for example +4.35) stay inside their card; the three boxes in the reports detail wrap instead of overflowing at tablet width (768px, 40px over) | Web 3: no horizontal overflow |
| 3 | Smallest text raised from 9.6px to 11.2px (tags, owner lines, axis labels, table headings) | UX 3: readability |
| 4 | Light mode: "service and support" in the headline was 3.0 to 1; now 4.5 or better | Web 2: text contrast 4.5 to 1 |
| 5 | Page follows the system light or dark setting until the reader picks one (their pick is remembered) | UX 4: follow prefers-color-scheme |
| 6 | The five big tender dots in the What changed chart can be focused with the keyboard but had no name; each now reads "Won or Lost, customer, closed date" | Web 2: screen readers |
| 7 | "Skip to main content" link; "On this page" jump links in the header (wide screens); "Back to top" at the bottom of each section (desktop) | UX 3 and Web 1 |
| 8 | noindex added (customer names and tender values must not reach Google) | Web 6 |
| 9 | First screen kept inside 800px at 1280 to 1600 wide: tiles end at 785 to 791px (they would have run to 805 to 811px after fix 3) | 30-second test |
| 10 | Circle (new): each of the 25 dots now has a name for screen readers, for example "Lost tender, Highlands Ambulance, closed 19/09/2025, $11.80m, biggest gap: Service and support, one of the 3 big losses" | Web 2: names for focusable items |
| 11 | Circle (new): the numbers 1 to 3 on the ringed dots were white (about 2.9 to 1 on teal). They now sit on a small disc in the page colour with text at 14.6 to 1 dark, 17.5 to 1 light | Web 2: text contrast 4.5 to 1 |
| 12 | Circle (new): dots were drawn at 90% and 45% strength, so light-mode teal was 2.85 to 1 and the grey "no scoring table" dots 1.8 to 1 against the card. Now full strength: lowest dot is 3.2 to 1 light, 3.6 to 1 dark (3 to 1 needed for a graphic). The legend swatches match. Colours, counts and sizes are unchanged | UX 4 / Web 2: graphics visible in both modes |
| 13 | Stage label "Stage 4 · Finished first draft · Experimental A" and footer credit; Business Requirements v1.3 and Calculation Pack v1.2 in the header and footer | Change control |
4. Standards results
UX Standards Reference (and the UXPin principles)
| Area | Check | Result | Evidence |
|---|---|---|---|
| Layout | No sideways scroll, 375 upright, 568 × 320 and 740 × 360 sideways, 768, 1100+ | Pass | Width sweep, 0 of 56 |
| Layout | Layout changes live across 900px and 640px without reload | Pass | Charts redraw on resize; sweep loads each width fresh |
| Layout | Phone bottom tab bar, tablet and desktop top tabs | Not applicable | One scrolling page with no tabs. Sharon: "Not phone" (a screen and a pack) |
| Layout | Tables become cards on phones | Pass | The few tables are "See data" tables, fixed layout, wrap at 375px |
| Layout | Safe areas | Pass | Side padding uses env(safe-area-inset) |
| Touch | Controls under 44px on phones | Pass | 0 buttons, links or summaries under 44px at every width |
| Touch | Inputs 16px | Not applicable | No text inputs |
| Readability | Headings front-loaded, sections by use | Pass | What changed, Why, What to do, Detail. Answer first, working behind "See data" and collapsed sections |
| Readability | Bullets within the word limit | Pass for the main flow; 9 lines over 30 words in captions and definitions remain | The three in the main flow were shortened (item 1, approved and applied). The rest are captions and definitions Adam did not ask to change |
| Readability | One term per idea | Pass, one note | Headings say "Discount on big deals"; the tile uses the full name "Average discount off list price on big deals" |
| Visual | Dark and light | Pass | Both screenshotted and measured |
| Visual | Reduced motion | Pass | Charts and count-up numbers switch off |
| Visual | Colour never the only signal | Pass | Status chips have icon and word; won or lost tenders are filled or hollow; bars carry signed values; area colours have a legend, labels and counts; the circle legend gives each area's name and count, big losses are ringed and numbered, and the See data table lists every tender |
| Visual | Secondary links low weight, buttons not underlined | Pass | Jump and Back to top links grey and thin; buttons plain |
| Trust | Shared output shows only what the audience needs | Pass | No weights or internal codes; plain names; Sample data label on the page |
| Trust | No silent failures | Pass | Storage wrapped in try/catch; no script errors |
| UXPin | Consistency, scannability, visual grammar, hierarchy, plain language, familiar patterns | Pass | Same tile, bar and table forms throughout |
| UXPin | Progressive disclosure, whitespace | Pass | Detail sections open by default at 1100px and wider, closed on phones (item 2, approved and applied) |
| UXPin | User control | Pass | Colour mode toggle works; replay removed, so nothing is mouse only except the hover detail, which the See data tables repeat |
| UXPin | User at the centre, define the problem first, iterate on evidence | Not tested | Build process, not page |
| UXPin | Accessibility (#10) | Covered below | Web Build Standards |
Web Build Standards
| Section | Check | Result | Evidence |
|---|---|---|---|
| HTML | doctype, lang="en-AU", charset, viewport, 4-word title | Pass | "Kestrel Medical Tender Dashboard" |
| HTML | One h1, headings in order, unique ids, semantic elements, details and summary | Pass | h1 then h2, h3, h4, no skipped levels. 0 duplicate ids. WHATWG §4.3 and §4.11.1 |
| HTML | No clickable divs | Pass | Click-to-replay removed (item 3, approved and applied). Charts still play once on first view |
| Accessibility | Contrast 4.5 to 1, both modes | Pass | 5.07 dark, 4.80 light, after fix 4 |
| Accessibility | Keyboard: focus ring, everything reachable | Pass | Focus ring on every control; skip link added. Chart rows, bars and the 25 circle dots are no longer tab stops (item 4, approved and applied): 5 KPI tile stops remain, plus the real controls. Not walked through by hand: structure and CSS checked |
| Accessibility | Names for focusable items, charts with text summary | Pass | 0 unnamed focusable items (the 25 circle dots checked in the Browser pane); each chart has a summary and a "See data" table |
| Accessibility | Reduced motion, 200% zoom | Pass | 200% on 1280 is 640px: no overflow |
| CSS | Colour tokens with dark mode, relative units | Pass | :root tokens, JS swaps the set per mode |
| JavaScript | 0 console errors on load, in both modes, all widths | Pass | 0 in the Browser pane and in headless Chrome |
| JavaScript | Storage in try/catch, no popups, pinned libraries | Pass | No libraries; only Google Fonts (see note) |
| JavaScript | Core content shows if script fails | Fail, accepted | Tiles and charts are drawn by script. Same as every Kestrel build; a pack for global would be printed from a working browser. Not proposed for change |
| Performance | Page weight, fonts | Note | 73 KB page. Six font files from Google Fonts (Lexend 300, 400, 500, 600; IBM Plex Mono 400, 500). Core Web Vitals: not measured |
| Security | No keys or tokens, no personal data in URLs, noindex, no external links | Pass | No links out; no secrets. Customer names are in the page: see the privacy open question in the Business Requirements (section 10) |
| Security | HTTPS | Not applicable | Not published |
| PWA | Manifest and service worker | Not applicable | None |
| Release | 7-step list | Steps 1 to 6 done; step 7 respected | Nothing published |
5. Before/After items: all four approved by Adam, 24-Oct-26, and applied (jennifer_finish.py)
| # | Where | Before | After | Why (standard) | Status |
|---|---|---|---|---|---|
| 1 | Three long lines in the main flow (these are Viktor's words, so I'd like your yes) | a. "The axis starts at 12% so the step can be read. No target in the first pass: it is set in Phase 2. Big deal means tender contract orders until the sales leader sets a size rule. Click the chart to replay." (v1.3 wording, 38 words) b. "Average discount off list price on tender contract orders, by year of order (2026 is Jan to Sep). Below: the last 5 tenders of $5m or more, by close date." (v1.3 wording, 31) c. First action note: "2 of the last 5 now. Gary's starting proposal, 3 of the last 5 by Dec-27, means winning the next 2 big tenders (Working Hypothesis). A service measure is a Phase 2 question for the sales leader." (37) | a. "The axis starts at 12% so the step can be read. No target yet: it is set in Phase 2. Big deal means tender contract orders for now." b. "Discount on tender contract orders by order year (2026 is Jan to Sep). Below: the last 5 tenders of $5m or more." c. "2 of the last 5 now. A target of 3 of 5 by Dec-27 means winning the next 2 (Working Hypothesis)." The service measure question stays in the open questions for Phase 2 | UX 3: about 20 words per line, 30 at most | Approved by Adam, 24-Oct-26, applied |
| 2 | Detail section, desktop | All five sections closed; reader taps each | Open by default at 1100px and wider, closed on phones. The page gets longer on a big screen | UX 3: on desktop, keep everything open with jump links (jump links are done). Viktor closed them to keep the walk-through short, so it is your call | Approved by Adam, 24-Oct-26, applied |
| 3 | "What changed" and the other charts | Clicking a chart replays its animation. Mouse only, and the caption says "Click the chart to replay" | Remove the click and the caption; charts still animate once on first view | Web 1 and 2: no clickable divs; keyboard users cannot replay. A "Replay" button is the alternative, but it adds 8 buttons | Approved by Adam, 24-Oct-26, applied |
| 4 | Chart rows and circle dots (about 115 tab stops) | Every bar, row and circle dot can be tabbed to, to show its hover detail (the dots are named, so a screen reader reads each one) | Rows and dots stop being tab stops; the "See data" tables carry the same figures for keyboard and screen reader users | Web 2: keyboard pass in reasonable steps. The detail on hover then stays mouse only | Approved by Adam, 24-Oct-26, applied |
Also for Adam (no change proposed): in the circle, dot size shows contract value only roughly (Viktor's caption says so; the See data table has the exact values). Six area colours on small dots need the legend, so the legend sits directly underneath and carries names and counts. Hovering or focusing a dot also names its area. Also: the pack for global is the main use, and the page is dark by default when a reader has no system setting. Printing a dark page uses a lot of ink. I'd suggest a print version that is always light, but that is a new feature, so I've left it for Stage 5.
↑ Back to top6. Validation checklist
| # | Check | Result | Evidence |
|---|---|---|---|
| 1 | Every Must Have KPI is on the dashboard, calculated as documented | Pass | Built (7): Average discount off list price on big deals 17.03%; Revenue growth on the year -6.8%; Big tender win rate 2 of 5; Revenue growth by product group and by rep (detail); Why we lost, from the debriefs (the three big losses by scoring area, and the circle of all 25 lost tenders by biggest gap); Who is winning the tenders we lose. Numbers match the Calculation Pack: discount 17.03% with trend flat (no pace, as no target), growth -6.8% with +0.72 needed and +0.27 trend, 5 tenders, Net price realisation 87.36%, reports 3 of 30 with 17 combinations. Phase 2 placeholder, as documented (4): Gross margin per cent, Gross margin by product group, Monthly reports that match the agreed set of numbers, Our price against the winning price on lost tenders. Each placeholder shows its exact name, owner, "Phase 2: waiting for data", and no number, status colour, sparkline, gap or pace. Each stand-in carries "Stand-in, not the KPI" and "Sample data", and never takes the KPI's name, target or status colour. The stated 41% appears only as a note on the margin placeholder, not on the stand-in |
| 2 | Every business objective shows its progress (actual, target, gap, pace needed) | Pass | Lift gross margin: discount tile shows actual 17.03% and its trend (flat, 0.00 points a month) with "Target set in Phase 2": no target number, gap, pace, path or status colour (Phase 2, as documented, per v1.3); the 43% margin target shows as text with "Phase 2: waiting for data" (as documented). Grow revenue: -6.8% against +4%, gap -10.8 points, needs +0.72 a month. Stop losing the big tenders: 2 of 5 with "Target set in Phase 2", no colour, gap or pace (Phase 2, as documented). One agreed set of numbers: "Phase 2: waiting for data" (Phase 2, as documented) |
| 3 | Every action owner can see their KPI's status at a glance | Pass | Sales leader: Not rated Phase 2 (margin), Not rated: target open (discount, neutral grey chip and icon, no green, amber or red; no dashed target line on its sparkline; no "On track" or "Amber from" wording anywhere on the page: checked in the finished page), Off track (revenue). Bid manager: Not rated, target open. Finance report owner: Not rated Phase 2. Owner named on every tile. A KPI with an open target shows no status colour: checked |
| 4 | The 30-second test passes | Pass | At 1280 to 1600 wide, the headline (3 of 5 lost, service and support, not price), the three actions with owners and dates, and all five tiles with status end at 785 to 791px, inside an 800px screen. On a phone the same order scrolls: headline, actions, tiles |
| 5 | The Business Requirements version in the footer matches the latest | Pass | Header and footer say Business Requirements v1.3 and Calculation Pack v1.2; the files are v1.3 and v1.2 |
7. Screenshots (in 02 - Deliverables/)
2026.10.23 - Kestrel Medical - 04 Screenshot Desktop dark.pngand... Desktop light.png(1440 wide, full page, Detail sections open as they now are by default)2026.10.23 - Kestrel Medical - 04 Screenshot Phone dark.pngand... Phone light.png(375 wide, full page; the page sits in a 500px frame because headless Chrome will not go narrower)- Screenshots are taken with motion off so every chart and number is in its finished state
8. How the checks were run
- Browser pane (Edge-based): at 375 confirmed the circle fits (310px wide, legend ends at 335px of 375, no sideways scroll, 25 of 25 dots named); opened the page at 375 and 1280, measured contrast in both modes, focusable items, names, ids, console (no errors), touch targets and sideways scroll, and looked at the phone layout
- Headless Chrome:
jennifer_checks.pyfor the 14-width sweep in both modes with sections closed and open;jennifer_screenshots.pyfor the four screenshots - Not done: a hand keyboard walk-through, Core Web Vitals, the slowest action in seconds. They are marked "Not tested" above, not guessed