diff --git a/.okf/design/house-visual-spec.md b/.okf/design/house-visual-spec.md index 0eeb45274..bdcd04fbb 100644 --- a/.okf/design/house-visual-spec.md +++ b/.okf/design/house-visual-spec.md @@ -6,7 +6,7 @@ resource: .stitch/prompts/course-inpost-visual-prompt.md tags: [svg, design, course] generated: by: process:okf-migrate - at: 2026-07-13T00:00:00Z + at: 2026-08-01T00:00:00Z --- # The spec in one table @@ -46,3 +46,190 @@ print-ready PDF (Wave M3 ships a download link on every printable page; print is the native format for pen-and-paper artifacts). Revisit only if pilot recordings show phone readers pinch-zooming worksheets instead of downloading. + +# v3 exhibit spec + +Source of authority: ADR 30.09 (premium-editorial pilot). This section is +the executable spec its Phase-A A/B pilot demanded - an SVG author renders +from it without guessing px, ratios, or weights. It ADDS to (does not +replace) the hand-drawn grammar above: O1 keeps that style, disciplined to +the numbers here; O2 is the flat-vector challenger. Everything below is +style-agnostic unless a row splits O1/O2. Dashes stay "-" everywhere, +green stays money-only, labels stay inside shapes. + +## The governing constant: the >=9px @390px legibility floor + +The current SVGs render at a 960-1000 viewBox and their smallest text lands +at ~5.5-7px on a 390px phone (ADR "Measured state"). That is the defect v3 +fixes. The fix is a formula, not a wish. + +An SVG scales to its container width, so rendered text size is: + + rendered_px = font_viewBox * (W_render / W_viewBox) + +Reference render width is **W_render = 390** (a phone's CSS viewport; the +real content column after page padding is ~358px, so 390 carries ~9% +built-in headroom). Require the SMALLEST rung (basis) to clear 9px: + + rendered_px(basis) >= 9 + => basis_viewBox >= 9 * W_viewBox / 390 = 0.02308 * W_viewBox + => equivalently W_viewBox <= basis_viewBox * 43.33 + +**Canonical exhibit viewBox width = 720.** At 720 the floor is +0.02308 * 720 = 16.62px, so the basis rung is set to **17px**, which renders +17 * 390/720 = **9.21px** at 390 - above floor by design. Only the basis rung +(the smallest) needs the check; every larger rung clears it automatically. + +If an exhibit needs a wider viewBox W, scale ALL five rungs by W/720 so the +floor still holds; never place text smaller than `ceil(9 * W/390)` px. +Widening the viewBox to fit more nodes is the trap that caused the 5.5px +defect - prefer fewer nodes at W=720 over more nodes at W=960. + +**O1 Caveat correction (calibration knob):** Caveat's x-height is ~15% +smaller than Space Grotesk at the same point size, so O1 multiplies the +required floor by 1.15 - O1 basis rung = ceil(1.15 * 17) = **20px** (renders +10.8px, perceived ~9.4px). This is a real font-metric compensation, not slack. + +## 1. Grid / column system + +| Property | Value (viewBox units at W=720) | +|---|---| +| Canonical viewBox width | 720 | +| Columns | 12 | +| Outer safe margin (no critical content past it) | 24 all sides | +| Gutter | 12 | +| Column width | (720 - 48 - 11*12)/12 = 45 | +| Vertical rhythm baseline | 8 | + +Nodes and axes snap to column edges; multi-column nodes span whole columns +plus the gutters between them (2 cols = 45+12+45 = 102). Vertical positions +snap to the 8px baseline. + +## 2. Spacing scale + +8px-based rung set (matches JetVelocity's 8px rhythm; 4 and 12 are the only +half-steps, reserved for tight in-node text padding): + + 4 - 8 - 12 - 16 - 24 - 32 - 48 - 64 + +- 4/8: in-node text padding, gap between a label and its icon. +- 12/16: node internal padding, gap between a bar and its value label. +- 24/32: gap between sibling nodes, chart plot inset. +- 48/64: gap between exhibit regions (title block -> body -> basis line). + +Every gap in an exhibit is one of these eight values. No off-rung spacing. + +## 3. Connector spec + +| Property | O2 flat-vector | O1 hand-drawn-normalized | +|---|---|---| +| Line weight | 2px uniform | 2-2.5px hand stroke | +| Routing | orthogonal (right-angle) | organic curve | +| Corner radius on turns | 4px | n/a (curve) | +| Arrowhead | filled triangle, 9 long x 7 base, same fill as line | open hand-drawn caret, ~10px | +| Attach point | node edge midpoint | node edge, loose | +| Turn clearance | >=16px straight off a node before the first turn | ~16px | +| Connector label | in a paper-tone pill centered ON the line, never crossing it | same | + +Line color = ink (#121212 O2 / #1a1a1a O1) for neutral flow; ruby only when +the connector itself is the anti-pattern / action edge; purple for the +alternate path (carried from the hand-drawn semantics above). + +## 4. Data-viz rules + +- **Chart-vs-diagram trigger:** message is a quantity / comparison / trend + -> chart. Message is a flow / relationship / sequence -> diagram. One + message per exhibit decides which. +- **Fill vs stroke (hard rule):** DATA marks are FILLED, no stroke (bars, + dots, bands, meter fill). STRUCTURE is STROKED, no fill (axes, gridlines, + connectors, node outlines). Never both on one mark. +- **Bars:** filled semantic color; inter-bar gap = 0.5x bar width; category + label below (label rung), value label above (annotation rung). +- **Dots/scatter:** 6px-radius filled dots, no stroke. +- **Gauge / meter / signal read:** horizontal track, bands filled by + semantic tone, 2px pointer tick, threshold marked with a labeled tick + (this is the `smoke-test-signal.svg` archetype). +- **Ruby-for-signal convention:** ruby marks the ONE actionable reading - + the threshold to act on, the kill zone, the number the exhibit exists to + show. Everything else stays ink or gray. If two things are ruby, the + exhibit has two messages - split it. +- **Threshold vs band:** a threshold is a 2px dashed ink line perpendicular + to the axis with a labeled tick. A band is a filled semantic-tone rect + BEHIND the data, its label inside at the label rung. +- **Axis:** single baseline axis 2px ink; no gridlines unless precise values + are read (then 1px #e5e5e5); no 3D, no chart junk. Plain-language chart + title sits in the action-title slot (see grammar). + +## 5. Aspect-ratio guidance + +| Exhibit type | Ratio | viewBox at W=720 | +|---|---|---| +| Signal meter / single-axis chart | 12:5 | 720 x 300 | +| Flow / process diagram | 16:9 | 720 x 405 | +| Comparison (bars) | 3:2 | 720 x 480 | +| Relationship / node map | 3:2 | 720 x 480 | +| Program map / synthesis | up to 4:5 portrait | 720 x 900 max | + +**Mobile-safe default = 3:2 (720 x 480)** - fills the phone column at ~1.3x +viewport height. Never exceed 4:5 portrait on a phone, and never breach the +hand-drawn spec's "taller than 2x viewport = wall, not hook" ceiling above. + +## 6. Five-rung type scale + +Sizes in viewBox units at the canonical W=720. Rendered column = value * +390/720 = value * 0.5417 (the >=9px floor check). + +| Rung | Role in exhibit | O2 size / font | O1 size / font | Rendered @390 (O2) | +|---|---|---|---|---| +| 1 Title | action title (the takeaway sentence) | 34 / Space Grotesk 700 | 34 / Caveat 700 | 18.4px | +| 2 Message | the one point proved (subtitle) | 24 / Space Grotesk 600 | 24 / Caveat 700 | 13.0px | +| 3 Label | in-node / axis labels | 20 / Space Grotesk 600 | 22 / Caveat 700 | 10.8px | +| 4 Annotation | callouts, value labels | 18 / system-ui 400 | 22 / Caveat 700 | 9.75px | +| 5 Basis | source/scope line | 17 / system-ui 400 | 20 / Caveat 700 | 9.21px | + +O2 uses Space Grotesk for title/message/label only; annotation and basis +(running text) stay system-ui per ADR ("Space Grotesk labels only, body +stays system-ui"). O1 keeps the full Caveat/Patrick Hand/Comic Sans stack at +the x-height-corrected sizes (rungs 3-5 bumped to satisfy the O1 floor). + +## Exhibit grammar (every exhibit, both styles) + +Zelazny doctrine, from ADR driver D2. Non-negotiable in either style: + +1. **One action title** - a sentence stating the takeaway, not a label. + "Under 3% conversion means kill the idea", never "Conversion signal". +2. **One message** - the single point the exhibit proves. If you need two, + make two exhibits. +3. **One basis line** - the data's source and scope, bottom of the exhibit. + "Basis: 7-day cold-traffic test, one channel." + +## O1 vs O2 scoring rubric (for the T2 A/B pair) + +Both variants MUST pass the grammar checklist and the measured >=9px @390px +floor - those are pass/fail gates, not scored preferences. The rows below +are where the two styles legitimately diverge, so T2 (and Paul's eye-test) +can score them on the same axes at equal zoom. + +| Axis | O1 hand-drawn-normalized | O2 premium-editorial flat-vector | +|---|---|---| +| Heading/label font | Caveat / Patrick Hand / Comic Sans stack | Space Grotesk 600-700 | +| Running-text font | same cursive stack | system-ui | +| Stroke | 2-2.5px hand feel | 1.5-2px uniform | +| Corner radius | organic / none | 4px | +| Texture filter | rough filter allowed | none (clean) | +| Background | paper tones (#fff5f5 / #faf7f2 / #f0f9f0 / #fbe9ff) | paper white #ffffff on #faf7f2 page | +| Ink color | #1a1a1a | #121212 | +| Accents | ruby=action/anti-pattern, purple=alt, green=money, amber=warn | same semantics | +| Basis-rung floor | 20px (Caveat x-height corrected) | 17px | +| Brand-identity fit | preserves the "handwritten = non-negotiable" mermaid brand rule | deliberately re-tests it (ADR: weak prior) | +| Sam-trust read (ADR) | risked reading "amateur / unfinished" | risked reading "generic startup" if overdone | +| When it wins | authenticity/warmth valued over polish; cheapest (no restyle) | craft/consistency read as premium; consulting-grade synthesis | + +## Verification against ADR 30.09 + +All six demanded components are present: (1) grid, (2) spacing scale, +(3) connector spec, (4) data-viz rules, (5) aspect-ratio, (6) 5-rung type +scale with the measured >=9px @390px floor formula - plus the exhibit +grammar and the O1/O2 rubric. Nothing in the ADR's Phase-A spec requirement +was left aspirational; the floor is a formula (basis 17px @ W=720 -> 9.21px) +and every dimension is a number an SVG author can render from. diff --git a/.okf/log.md b/.okf/log.md index e52aa4f32..8179f84be 100644 --- a/.okf/log.md +++ b/.okf/log.md @@ -580,3 +580,17 @@ untouched. ## 2026-08-01 - Removed toolchain drift-gate unit tests (config-mirror anti-pattern) * **Remove**: `test/unit/toolchain_pins_test.rb` deleted in full. It was a config-mirror "drift gate" asserting `.mise.toml` version pins equal the literal pins in the setup-hugo action, `_hugo.yml`, `.dev/compose.yml`, and `.ruby-version`. `test_setup_hugo_action_matches_mise` red-built on a FALSE invariant: `.mise.toml` `node = "latest"` (devs want latest) vs CI `node-version: '22'` (pinned on purpose in #393) - a correct divergence, not drift. Tests config agreement, not behavior; violates FIRST + the CLAUDE.md "no fragile config assertions" rule. Comparing CI-vs-local node explicitly was considered and rejected as overkill (Paul). Refs cleaned: Rakefile `:guards` list, `.mise.toml` / setup-hugo `action.yml` header comments, README, `docs/SETUP.md`, this bundle's [ci-gates](/build/ci-gates.md). Pins still need manual sync when bumping - now by convention, not a gate. + +## 2026-08-01 - W3-T1: v3 exhibit spec appended to house-visual-spec + +Added a `# v3 exhibit spec` section to `.okf/design/house-visual-spec.md` +(hand-drawn spec untouched, O1 still needs it) covering the six components +ADR 30.09 Phase A demanded: 12-col grid at a canonical 720 viewBox, 8px +spacing scale, connector spec (2px orthogonal + 4px radius O2 / hand-curve +O1), data-viz rules (fill=data / stroke=structure, ruby-for-signal, +threshold-vs-band), aspect-ratio table (mobile-safe default 3:2), and the +5-rung type scale. The >=9px @390px floor is a formula, not prose: +`rendered = font_viewBox * 390/W_viewBox`; basis rung 17px @ W=720 renders +9.21px. O1 bumps the floor x1.15 (basis 20px) for Caveat's small x-height. +Includes the action-title/one-message/basis-line grammar and an O1-vs-O2 +scoring rubric so the T2 A/B pair scores both on the same axes. diff --git a/content/course/tech-for-non-technical-founders-2026/form-your-founding-hypothesis-90-minute-sprint/hypothesis-mad-libs.svg b/content/course/tech-for-non-technical-founders-2026/form-your-founding-hypothesis-90-minute-sprint/hypothesis-mad-libs.svg index 53dcc5d71..99c27d79d 100644 --- a/content/course/tech-for-non-technical-founders-2026/form-your-founding-hypothesis-90-minute-sprint/hypothesis-mad-libs.svg +++ b/content/course/tech-for-non-technical-founders-2026/form-your-founding-hypothesis-90-minute-sprint/hypothesis-mad-libs.svg @@ -1,46 +1,58 @@ - - The founding-hypothesis Mad Libs sentence with five blanks: If we help [customer] solve [problem] with [approach], they'll choose it over [competition] because [differentiation]. - Five fill-in-the-blank pills stitched into one sentence. Three red pills name the customer, the problem, and the approach; two purple pills name the competition and the differentiation. Caption: five blanks, one sentence, no vagueness allowed. + + Fill five specific blanks and the hypothesis becomes one testable sentence. + A fill-in-the-blank sentence with five outlined placeholder chips: customer, problem, approach, competition and differentiation, stitched by the connecting words "If we help ... solve ... with ..., they'll choose it over ... because ...". Below, the customer blank is filled two ways to show what specific means: the vague fill "small businesses" gets a shrug, the specific fill "solo chiropractors" (marked in ruby) gets "that's me". Basis: the founding-hypothesis frame from Click by Knapp and Zeratsky, 2025. - - If we help - - - customer - - solve - - - problem - - with - - - approach - + + + - - they'll choose it over - - - competition - - because - - - differentiation - + + Five specific blanks, one testable sentence + Categories get a polite nod; specifics get pushback - - Five blanks. One sentence. No vagueness allowed. + + If we help + + CUSTOMER + solve + + PROBLEM + with + + APPROACH + + + they'll choose it over + + COMPETITION + because + + DIFFERENTIATION + + + + Fill it vague: + + small businesses + + + solo chiropractors + = "that's me" + + + Basis: the founding-hypothesis frame from Click (Knapp & Zeratsky, 2025) diff --git a/content/course/tech-for-non-technical-founders-2026/form-your-founding-hypothesis-90-minute-sprint/index.md b/content/course/tech-for-non-technical-founders-2026/form-your-founding-hypothesis-90-minute-sprint/index.md index 8b81d4a5b..8da3e92ee 100644 --- a/content/course/tech-for-non-technical-founders-2026/form-your-founding-hypothesis-90-minute-sprint/index.md +++ b/content/course/tech-for-non-technical-founders-2026/form-your-founding-hypothesis-90-minute-sprint/index.md @@ -67,7 +67,7 @@ Each blank is an assumption, and each assumption has a test waiting for it later - **`[COMPETITION]`**: what they currently use (a spreadsheet, a billing service, "doing nothing") - **`[DIFFERENTIATION]`**: why they'd switch - faster or cheaper, with numbers -![5 blanks of the Mad Libs hypothesis sentence with a filled example below](hypothesis-mad-libs.svg) +![The founding-hypothesis frame as five outlined blanks - customer, problem, approach, competition, differentiation - with the customer blank filled two ways to show specific beats vague: "small businesses" gets a shrug, "solo chiropractors" gets "that's me"](hypothesis-mad-libs.svg) Can't tell whether a blank is specific enough to bet on? The [validation tools field guide](/course/tech-for-non-technical-founders-2026/validation-tools-field-guide/) walks three AI tools that stress-test your five blanks in about ten minutes - a structured second opinion before you commit the sentence and start booking interviews. diff --git a/content/course/tech-for-non-technical-founders-2026/how-this-course-works/index.md b/content/course/tech-for-non-technical-founders-2026/how-this-course-works/index.md index 9e771e262..1fb636b70 100644 --- a/content/course/tech-for-non-technical-founders-2026/how-this-course-works/index.md +++ b/content/course/tech-for-non-technical-founders-2026/how-this-course-works/index.md @@ -42,7 +42,7 @@ This course takes a non-technical founder from a rough idea to a signed paid pil ## The Big Picture -![5-module pipeline: Module 1 Hypothesis & Smoke Test → Module 2 Validate the Problem → Module 3 Design from Evidence → Module 4 Build It Yourself → Module 5 First Paying Customer](module-pipeline.svg) +![Program map: five modules on one spine, each output feeding the next input. Module 1 Hypothesis & Smoke Test produces a tested hypothesis and a live page that takes payment; Module 2 Validate the Problem produces 10 customer interviews and a validated problem statement; Module 3 Design from Evidence produces a one-page product brief in real customer words; Module 4 Build It Yourself produces a live MVP at a real URL with every account in your name; Module 5 First Paying Customer produces a signed paid pilot with a deposit in the bank.](program-map.svg) {{< course-stat modules >}} modules. {{< course-stat chapters >}} lessons. {{< course-stat artifacts >}} artifacts you can hand to an investor or a co-founder. Each module's output is the next module's input. diff --git a/content/course/tech-for-non-technical-founders-2026/how-this-course-works/module-pipeline.svg b/content/course/tech-for-non-technical-founders-2026/how-this-course-works/module-pipeline.svg deleted file mode 100644 index 4de0c6bb1..000000000 --- a/content/course/tech-for-non-technical-founders-2026/how-this-course-works/module-pipeline.svg +++ /dev/null @@ -1,123 +0,0 @@ - - 5-module course pipeline: Hypothesis → Validate → Design → Build → First Paying Customer - - - - - - - - - - - - - - - - The 5-Module Pipeline - Each module's output is the next module's input - from rough idea to signed paid pilot - - - - Module 1 - Hypothesis - & Smoke Test - - ~7 days - - Artifact: - Hypothesis + - Smoke Test - STAGE 1 - - - - - - - - - - - Module 2 - Validate the - Problem - - ~2-3 weeks - - Artifact: - 10 Interviews + - Problem Stmt - STAGE 2 - - - - - - - - - - Module 3 - Design from - Evidence - - ~3-5 days - - Artifact: - Product Brief / - Vibe PRD - STAGE 3 - - - - - - - - - - Module 4 - Build It - Yourself - - ~2-4 weeks - - Artifact: - Live MVP at - real URL - STAGE 4 - - - - - - - - - - Module 5 - First Paying - Customer - - ~2-4 weeks - - Artifact: - Signed Paid - Pilot - DONE - - diff --git a/content/course/tech-for-non-technical-founders-2026/how-this-course-works/program-map.svg b/content/course/tech-for-non-technical-founders-2026/how-this-course-works/program-map.svg new file mode 100644 index 000000000..f2471cc6d --- /dev/null +++ b/content/course/tech-for-non-technical-founders-2026/how-this-course-works/program-map.svg @@ -0,0 +1,70 @@ + + The 5-module program map: from a rough idea to a signed paid pilot + A vertical spine links five numbered modules in order. Module 1 Hypothesis and Smoke Test produces a tested hypothesis and a live page that takes payment. Module 2 Validate the Problem produces 10 customer interviews and a validated problem statement. Module 3 Design from Evidence produces a one-page product brief in real customer words. Module 4 Build It Yourself produces a live MVP at a real URL with every account in your name. Module 5 First Paying Customer, shown in green, produces a signed paid pilot with a deposit in the bank. Each module's output is the next module's input. + + + + + + + + + Five modules carry a rough idea + to a signed paid pilot + Each module's output is the next module's input. + + + + + + + + + + + + + + 1 + Module 1 · Hypothesis & Smoke Test + A tested hypothesis + a live page that takes payment + + + + + 2 + Module 2 · Validate the Problem + 10 customer interviews + a validated problem statement + + + + + 3 + Module 3 · Design from Evidence + A one-page product brief in real customer words + + + + + 4 + Module 4 · Build It Yourself + A live MVP at a real URL - every account in your name + + + + + 5 + Module 5 · First Paying Customer + A signed paid pilot with a deposit in the bank + + + Basis: the course's 5-module spine - 20+ lessons, 6 artifacts. + v1.0 · August 2026 + diff --git a/content/course/tech-for-non-technical-founders-2026/price-hypothesis-on-smoke-test-page/index.md b/content/course/tech-for-non-technical-founders-2026/price-hypothesis-on-smoke-test-page/index.md index 97470fc15..51861635a 100644 --- a/content/course/tech-for-non-technical-founders-2026/price-hypothesis-on-smoke-test-page/index.md +++ b/content/course/tech-for-non-technical-founders-2026/price-hypothesis-on-smoke-test-page/index.md @@ -58,7 +58,7 @@ The copy matters more than the price number. Two framings we keep reaching for o Pick one pattern. Do not A/B test - 150 visits each on a $300 budget can't distinguish 4% from 5%. Ship one button copy. -![Same button, two framings side by side - an outcome-framed CTA reading "Stop spending 4 hours on reconciliation - $97" and a risk-reduction-framed CTA reading "Reserve your spot - $97 refundable for 30 days", both showing the identical $97 price](stripe-payment-link.svg) +![Two cards showing the same waitlist button written two ways - an outcome-framed CTA reading "Stop spending 4 hours on reconciliation - $97" and a risk-reduction-framed CTA reading "Reserve your spot - $97 refundable for 30 days" - both ruby buttons charging the identical $97](stripe-payment-link.svg) ## Add the Stripe button diff --git a/content/course/tech-for-non-technical-founders-2026/price-hypothesis-on-smoke-test-page/stripe-payment-link.svg b/content/course/tech-for-non-technical-founders-2026/price-hypothesis-on-smoke-test-page/stripe-payment-link.svg index 8b76d9aad..683a5c8ed 100644 --- a/content/course/tech-for-non-technical-founders-2026/price-hypothesis-on-smoke-test-page/stripe-payment-link.svg +++ b/content/course/tech-for-non-technical-founders-2026/price-hypothesis-on-smoke-test-page/stripe-payment-link.svg @@ -1,38 +1,44 @@ - - Same button, two framings side by side - an outcome-framed CTA and a risk-reduction-framed CTA, both showing the identical $97 price + + Same $97, two ways to frame the button - pick one, never A/B test. + Two side-by-side cards show the same ruby waitlist button written two ways. The outcome framing reads "Stop spending 4 hours on reconciliation - $97" and anchors the price to the problem it replaces. The risk-reduction framing reads "Reserve your spot - $97, refundable for 30 days" and reduces first-touch risk. Both charge the identical $97. Basis: one smoke-test price, only the wording differs. - Same button, two framings - The price ($97) is identical on both. Pick one - do not A/B test. + + + - - - OUTCOME FRAMING - - Stop spending 4 hours on reconciliation - $97 - anchors the price to the problem it replaces + + Same $97, two ways to frame the button + Pick one framing; never A/B test a smoke test - - - RISK-REDUCTION FRAMING - - Reserve your spot - $97 refundable 30 days - reduces first-touch risk + + + OUTCOME FRAMING + + Stop spending 4 hours + on reconciliation - $97 + anchors price to what it replaces - - - Same $97 either way - the frame changes what the visitor feels, not what they pay. + + + RISK-REDUCTION FRAMING + + Reserve your spot - $97 + refundable for 30 days + reduces first-touch risk + + + Basis: one smoke-test price of $97, only the wording differs diff --git a/content/course/tech-for-non-technical-founders-2026/smoke-test-build-page/index.md b/content/course/tech-for-non-technical-founders-2026/smoke-test-build-page/index.md index 4b445c5c8..305c05f82 100644 --- a/content/course/tech-for-non-technical-founders-2026/smoke-test-build-page/index.md +++ b/content/course/tech-for-non-technical-founders-2026/smoke-test-build-page/index.md @@ -51,7 +51,7 @@ The page has four copy blocks that decide whether it converts: - The **3-4 value props** describe what the visitor gets, in their words. "Stop calling 8 tutoring centers" is an outcome a parent wants; "Calendar integration" is a feature they read as noise. - The **CTA + footer** is "Get on the waitlist" plus a "Coming soon" line in the footer. (**CTA** = call to action, the button you want the visitor to click.) Never use "Buy now" on this page: selling something that does not exist yet *without saying so* is false advertising. [Lesson 1.5](/course/tech-for-non-technical-founders-2026/price-hypothesis-on-smoke-test-page/) adds a price test the honest way - a clearly labeled founding-member pre-order with a visible refund promise. -![Smoke-test page anatomy showing 4 labeled blocks - headline names customer plus outcome, sub-headline explains the mechanism, a row of 3-4 value props, and the CTA button with coming-soon footer line](page-anatomy.svg) +![A smoke-test page as four stacked blocks - headline names the customer plus outcome, sub-headline explains the mechanism, a row of four value props, then the ruby call-to-action button "Get on the waitlist" with a coming-soon footer](page-anatomy.svg) ## Step 1: get 2-3 real customer quotes (10 minutes) diff --git a/content/course/tech-for-non-technical-founders-2026/smoke-test-build-page/page-anatomy.svg b/content/course/tech-for-non-technical-founders-2026/smoke-test-build-page/page-anatomy.svg index b5f1a92c3..f5871f95d 100644 --- a/content/course/tech-for-non-technical-founders-2026/smoke-test-build-page/page-anatomy.svg +++ b/content/course/tech-for-non-technical-founders-2026/smoke-test-build-page/page-anatomy.svg @@ -1,51 +1,60 @@ - - Smoke-test page anatomy: 4 stacked blocks - headline names customer + outcome, sub-headline explains the mechanism, a row of 3-4 value props, and the CTA with coming-soon footer + + A smoke-test page is four copy blocks stacked above one call-to-action. + A stacked page layout. The headline block names the customer and outcome in a 3-second test. The sub-headline block explains the mechanism. A row of four value-prop blocks lists outcomes the customer wants, not features. At the bottom, the call-to-action block, marked in ruby as the one click-target, reads "Get on the waitlist" with a coming-soon footer. Basis: a one-page email-capture smoke test, built before any product exists. - A smoke-test page, anatomy + + + + + Four blocks, then one clear ask + The anatomy of a page strangers can act on + + - - HEADLINE - names the customer + the outcome (3-sec test) + + HEADLINE + names the customer + the outcome (3-second test) - - SUB-HEADLINE - explains HOW (the mechanism) + + SUB-HEADLINE + explains how - the mechanism - - VALUE - PROP 1 - - - VALUE - PROP 2 - - - VALUE - PROP 3 - - - VALUE - PROP 4 - - outcomes the customer wants, not features - - - - - Get on the waitlist - Coming soon. Email reserves your spot at launch. + + VALUE + PROP 1 + + VALUE + PROP 2 + + VALUE + PROP 3 + + VALUE + PROP 4 + + outcomes the customer wants, not features + + + + Get on the waitlist + Coming soon. Email reserves your spot at launch. + + + Basis: a one-page email-capture smoke test, before any product exists diff --git a/content/course/tech-for-non-technical-founders-2026/smoke-test-landing-page-7-day-demand-test/index.md b/content/course/tech-for-non-technical-founders-2026/smoke-test-landing-page-7-day-demand-test/index.md index 4edafdecb..28c99ef9b 100644 --- a/content/course/tech-for-non-technical-founders-2026/smoke-test-landing-page-7-day-demand-test/index.md +++ b/content/course/tech-for-non-technical-founders-2026/smoke-test-landing-page-7-day-demand-test/index.md @@ -54,7 +54,7 @@ Two routes get you 300 cold visitors: the **$0 organic path** on the [full chann You will not have to figure out the ad on your own: the launch checklist below links a [step-by-step recipe for your channel](/course/tech-for-non-technical-founders-2026/reference/smoke-test-channel-guide/#campaign-creation-recipes) (7 settings, click by click) plus a copy-paste prompt that writes the ad copy and image concept for you. -![Signal meter reading the smoke-test conversion rate: 0-3% kill or pivot, 3-6% iterate the message, 6-10% promising, 10-20% strong signal, over 20% suspicious - with the 6% go line marked](smoke-test-signal.svg) +![A signal meter mapping cold-traffic conversion to a decision: 0-3% kill or pivot, 3-6% iterate the message, 6-10% promising, 10-20% strong signal, over 20% suspicious - with the 6% go line marked in ruby as the point where demand is real enough to start building](smoke-test-signal.svg) ## Launch and read the signal diff --git a/content/course/tech-for-non-technical-founders-2026/smoke-test-landing-page-7-day-demand-test/smoke-test-signal.svg b/content/course/tech-for-non-technical-founders-2026/smoke-test-landing-page-7-day-demand-test/smoke-test-signal.svg index 53ab5fff9..efaebcbfb 100644 --- a/content/course/tech-for-non-technical-founders-2026/smoke-test-landing-page-7-day-demand-test/smoke-test-signal.svg +++ b/content/course/tech-for-non-technical-founders-2026/smoke-test-landing-page-7-day-demand-test/smoke-test-signal.svg @@ -1,70 +1,75 @@ - - Smoke-test signal meter: read your cold-traffic conversion rate against the kill / iterate / promising / strong / suspicious bands. - A horizontal meter from 0 to over 20 percent conversion. Under 3 percent is Kill or pivot (red). 3 to 6 percent is Iterate the message (amber). 6 to 10 percent is Promising (green). 10 to 20 percent is Strong signal (deep green). Over 20 percent is Suspicious - verify with a second channel (gray). A pointer marks the 6 percent line where the demand is real enough to start building. + + At 6% signups the demand is real: read your cold-traffic conversion rate against the kill, iterate, promising, strong and suspicious bands. + A horizontal signal meter. Under 3 percent conversion is kill or pivot (ruby). 3 to 6 percent is iterate the message (amber). 6 to 10 percent is promising (green). 10 to 20 percent is a strong signal (deep green). Over 20 percent is suspicious, verify with a second channel (gray). A ruby pointer marks the 6 percent go line where demand is real enough to start building. Basis: form submits divided by page views after 300 cold visitors on one channel. + - + + + - Read your conversion rate off the meter - form submits ÷ page views, after 300 cold visitors + + Your signup rate picks your move + Cold-traffic conversion, mapped to a decision - - - 6% = the go line - demand is real - start building - - + + + 6% = the go line + demand is real, start building + - - - - 0-3% - Kill / pivot - - - - 3-6% - Iterate msg - - - - 6-10% - Promising - - - - 10-20% - Strong signal + + + + + + + + - - - 20%+ - Suspicious? + + 0-3% + Kill / pivot + 3-6% + Iterate msg + 6-10% + Promising + 10-20% + Strong signal + 20%+ + Suspicious? - - - 0% - 3% - 6% - 10% - 20% + + + + + + + + 0% + 3% + 10% + 20% - - + + + 6% - - A stranger's signup is a real vote. A friend's "sounds great" is not. + + Basis: form submits ÷ page views, 300 cold visitors, one channel diff --git a/content/course/tech-for-non-technical-founders-2026/smoke-test-wire-tracking/index.md b/content/course/tech-for-non-technical-founders-2026/smoke-test-wire-tracking/index.md index 65db9b29d..cc91cef9d 100644 --- a/content/course/tech-for-non-technical-founders-2026/smoke-test-wire-tracking/index.md +++ b/content/course/tech-for-non-technical-founders-2026/smoke-test-wire-tracking/index.md @@ -63,7 +63,7 @@ The 3 numbers you will read in Lesson 1.4: Conversion rate = form submits ÷ page views. That is the number your hypothesis is judged against. -![Three tracking snippets stacked vertically: Microsoft Clarity (heatmap icon), ad-platform pixel (target icon), GA4 (chart icon), with arrows pointing to a landing page wireframe showing where each snippet fires (page view, CTA click, form submit)](tracking-snippets.svg) +![Three tracking snippets - Microsoft Clarity, an ad-platform pixel, and Google Analytics 4 - feeding into a landing page's head tag, which then emits three events shown in monospace where they fire: page_view at the headline, cta_click at the waitlist button, form_submit at the email field](tracking-snippets.svg) ## Install the tracking diff --git a/content/course/tech-for-non-technical-founders-2026/smoke-test-wire-tracking/tracking-snippets.svg b/content/course/tech-for-non-technical-founders-2026/smoke-test-wire-tracking/tracking-snippets.svg index ebb60b140..0784c3f54 100644 --- a/content/course/tech-for-non-technical-founders-2026/smoke-test-wire-tracking/tracking-snippets.svg +++ b/content/course/tech-for-non-technical-founders-2026/smoke-test-wire-tracking/tracking-snippets.svg @@ -1,75 +1,79 @@ - - Three tracking snippets stacked on the left side - Microsoft Clarity, Ad-platform pixel, Google Analytics 4 - with arrows pointing to a landing page wireframe on the right showing page_view, cta_click, and form_submit events firing + + Three snippets pasted into the head tag let you read three events off the page. + Three tool boxes on the left - Microsoft Clarity, an ad-platform pixel, and Google Analytics 4 - route into the head tag of a landing-page wireframe on the right. The page then emits three events, shown as monospace tokens where they fire: page_view at the headline, cta_click at the ruby waitlist button, and form_submit at the email field. Basis: three tracking snippets pasted once into the page's head tag. - - + + - 3 snippets in the head tag = 3 events you can read + + + - - - Microsoft Clarity - heatmaps + session replays + + Three snippets, three readable events + One head-tag paste turns visits into numbers - - Ad-platform pixel - Meta · LinkedIn · Reddit + + + Microsoft Clarity + session replays + heatmaps - - Google Analytics 4 - page views · clicks · form submits + + Ad-platform pixel + Meta / LinkedIn / Reddit - - - - + + Google Analytics 4 + views, clicks, form submits - - + + + + + + + + - - - Headline + + - - → page_view + + + <head> tag - - + + + › page_view - - - - - + + + + + - - - Get on the waitlist + + + Join waitlist + › cta_click - - → cta_click + + + › form_submit - - - - - → form_submit + + Basis: three tracking snippets pasted once into the page's head tag diff --git a/docs/projects/2605-tech-for-non-technical-founders/30-39-architecture-design/30.09-adr-visual-system-v3-premium-editorial.md b/docs/projects/2605-tech-for-non-technical-founders/30-39-architecture-design/30.09-adr-visual-system-v3-premium-editorial.md index 32707d6ff..0a0dc1b99 100644 --- a/docs/projects/2605-tech-for-non-technical-founders/30-39-architecture-design/30.09-adr-visual-system-v3-premium-editorial.md +++ b/docs/projects/2605-tech-for-non-technical-founders/30-39-architecture-design/30.09-adr-visual-system-v3-premium-editorial.md @@ -186,3 +186,34 @@ ACCEPT-WITH-CHANGES - every required change incorporated above):** shared blog CSS protected; alt-rewrite = body edit = full gate -> checkbox added; honest 2-3 sprint estimate; template change scheduled outside the Aug 1-14 campaign window. + +--- + +## STYLE-CALL GATE (W3, 2026-08-01) — PENDING PAUL'S DECISION + +The A/B exemplar is produced (lesson 1.4 signal exhibit rendered both ways, +same message, only style differs): `40-49-review/40.30-exemplar-1.4-O1.svg` +(hand-drawn-normalized) vs `40.30-exemplar-1.4-O2.svg` (flat-vector), +side-by-side `40.30-exemplar-ab-sidebyside.png`, scored in +`40.30-exemplar-ab-comparison.md`. + +**Both pass the ≥9px@390px legibility floor** (O1 10.83px, O2 9.21px, +measured in-browser with real webfonts) — neither is invalid; the choice is +pure taste + strategy. Rubric (no winner declared): O2 wins perceived craft +(3→5) and cross-SVG consistency (3→5) — the two things Paul's original +"old-time / lacks infographic quality" note named; O1 wins brand-continuity +with the existing handwritten house rule (5→2) and cost-to-adopt (5→2). +Sam-trust is a true wash (3/3, amateur-risk vs generic-startup-risk). + +**Context that raises the stakes (Sprint-Y audit 40.31):** 4 of 5 current M1 +SVGs FAIL the mobile floor today (the archetype signal SVG worst, 5.7-8.1px) +— so T5 fixes a live readability defect regardless of which style wins. + +**DECISION (Paul 2026-08-01): O2 flat-vector.** All M1 exhibits adopt the +flat-vector style (Space Grotesk titles / JetBrains Mono labels / white card / +geometric, 4px radius, basis 17px). Rationale: O2 directly answers Paul's +original "old-time / lacks infographic quality" note, scales consistently +across all 81 SVGs, and the handwritten house rule it breaks was already +flagged for re-test by the ADR reviewers. T5 UNBLOCKED: redesign 1.1/1.2/1.3/ +1.5 + finalize 1.4 into the lesson, all O2, honoring the Sprint-Y keep-as-is +list (40.31). The 4-of-5 mobile-floor failures get fixed in the same pass. diff --git a/docs/projects/2605-tech-for-non-technical-founders/40-49-review/40.30-exemplar-1.4-O1.svg b/docs/projects/2605-tech-for-non-technical-founders/40-49-review/40.30-exemplar-1.4-O1.svg new file mode 100644 index 000000000..82fc4aca7 --- /dev/null +++ b/docs/projects/2605-tech-for-non-technical-founders/40-49-review/40.30-exemplar-1.4-O1.svg @@ -0,0 +1,83 @@ + + At 6% signups the demand is real: read your cold-traffic conversion rate against the kill, iterate, promising, strong and suspicious bands. + A hand-drawn horizontal signal meter. Under 3 percent conversion is kill or pivot (ruby). 3 to 6 percent is iterate the message (amber). 6 to 10 percent is promising (green). 10 to 20 percent is a strong signal (deep green). Over 20 percent is suspicious, verify with a second channel (gray). A ruby pointer marks the 6 percent go line where demand is real enough to start building. Basis: form submits divided by ad-campaign visits after 300 cold visitors on one channel. + + + + + + + + + + + + + + Your signup rate picks your move + Cold-traffic conversion, mapped to a decision + + + + 6% = the go line + demand is real, start building + + + + + + + + + + + + + + + 0-3% + Kill / pivot + 3-6% + Iterate msg + 6-10% + Promising + 10-20% + Strong signal + 20%+ + Suspicious? + + + + + + + + + + + + + + 0% + 3% + 10% + 20% + + + + + 6% + + + Basis: form submits ÷ ad-campaign visits, 300 cold visitors, one channel + diff --git a/docs/projects/2605-tech-for-non-technical-founders/40-49-review/40.30-exemplar-1.4-O2.svg b/docs/projects/2605-tech-for-non-technical-founders/40-49-review/40.30-exemplar-1.4-O2.svg new file mode 100644 index 000000000..859b24745 --- /dev/null +++ b/docs/projects/2605-tech-for-non-technical-founders/40-49-review/40.30-exemplar-1.4-O2.svg @@ -0,0 +1,75 @@ + + At 6% signups the demand is real: read your cold-traffic conversion rate against the kill, iterate, promising, strong and suspicious bands. + A horizontal signal meter. Under 3 percent conversion is kill or pivot (ruby). 3 to 6 percent is iterate the message (amber). 6 to 10 percent is promising (green). 10 to 20 percent is a strong signal (deep green). Over 20 percent is suspicious, verify with a second channel (gray). A ruby pointer marks the 6 percent go line where demand is real enough to start building. Basis: form submits divided by ad-campaign visits after 300 cold visitors on one channel. + + + + + + + + + + + Your signup rate picks your move + Cold-traffic conversion, mapped to a decision + + + + 6% = the go line + demand is real, start building + + + + + + + + + + + + + + 0-3% + Kill / pivot + 3-6% + Iterate msg + 6-10% + Promising + 10-20% + Strong signal + 20%+ + Suspicious? + + + + + + + + + + 0% + 3% + 10% + 20% + + + + 6% + + + Basis: form submits ÷ ad-campaign visits, 300 cold visitors, one channel + diff --git a/docs/projects/2605-tech-for-non-technical-founders/40-49-review/40.30-exemplar-ab-comparison.md b/docs/projects/2605-tech-for-non-technical-founders/40-49-review/40.30-exemplar-ab-comparison.md new file mode 100644 index 000000000..419d48e50 --- /dev/null +++ b/docs/projects/2605-tech-for-non-technical-founders/40-49-review/40.30-exemplar-ab-comparison.md @@ -0,0 +1,133 @@ +# 40.30 - Exemplar A/B: lesson 1.4 signal exhibit, O1 vs O2 + +**Purpose:** the style gate for ADR 30.09 Phase A. One M1 exhibit (lesson +1.4's smoke-test signal meter) rendered BOTH ways against the v3 exhibit +spec, so Paul's eye-test picks O1 (hand-drawn-normalized) or O2 +(flat-vector). Neutral by design - this doc scores both on the same axes; +it does not pre-decide the call. + +- **Exhibit rendered:** the cold-traffic conversion signal meter (visits → + signups → the conversion rate that reads go / iterate / kill, with 6% as + the go line). Same message in both variants; only the style variable moves. +- **Spec bound:** `.okf/design/house-visual-spec.md` "v3 exhibit spec" + (grid W=720, 8-scale spacing, fill=data/stroke=structure, 5-rung type + scale, the ≥9px @390px floor formula, exhibit grammar, O1/O2 rubric). +- **Files (do NOT overwrite the lesson's committed SVG):** + - O1: `40.30-exemplar-1.4-O1.svg` + - O2: `40.30-exemplar-1.4-O2.svg` + - Side-by-side (equal zoom, real webfonts): `40.30-exemplar-ab-sidebyside.png` + +## Side-by-side (equal zoom, rendered with the real webfonts) + +![O1 hand-drawn-normalized above, O2 flat-vector below, same exhibit at equal zoom](40.30-exemplar-ab-sidebyside.png) + +O1 links: [40.30-exemplar-1.4-O1.svg](40.30-exemplar-1.4-O1.svg) · +O2 links: [40.30-exemplar-1.4-O2.svg](40.30-exemplar-1.4-O2.svg) + +> Rendering note: the standalone `.svg` files reference Caveat / Space +> Grotesk by family (the same way the lesson pages load them). Open them +> inside the course (fonts loaded) or view the PNG above for the faithful +> render - a raw file open with those fonts absent will substitute. + +--- + +## Pass/fail gates (both MUST pass - not scored) + +Grammar checklist and the measured floor are gates, not preferences. Both +variants clear both. + +| Gate | O1 | O2 | Evidence | +|---|---|---|---| +| One action title (a takeaway sentence, not a label) | PASS | PASS | "Your signup rate picks your move" | +| One message (single point proved) | PASS | PASS | "Cold-traffic conversion, mapped to a decision" | +| One basis line (source + scope) | PASS | PASS | "Basis: form submits ÷ ad-campaign visits, 300 cold visitors, one channel" | +| Ruby-for-signal = one actionable reading | PASS | PASS | the 6% go line is the only ruby reading; bands are the gauge tone-scale | +| Fill=data / stroke=structure | PASS | PASS | bands filled no-stroke; axis, ticks, threshold stroked no-fill | +| Grid W=720, 8-scale spacing, 24 margins | PASS | PASS | 12:5 signal-meter ratio (720×300); every gap on the 4/8/12/16/24/32 rungs | +| **≥9px @390px legibility floor (measured)** | **PASS** | **PASS** | see below | + +### Measured floor (the blocking gate) - real webfonts, container = 390px CSS + +Smallest text in each exhibit is the **basis line**. Measured in Chrome with +Caveat / Space Grotesk actually loaded, the SVG scaled to a 390px container +(scale = 390/720 = 0.5417): + +| Variant | Basis font (viewBox) | Rendered @390px | Floor (≥9px) | Font confirmed | +|---|---|---|---|---| +| O1 | 20px (Caveat x-height corrected) | **10.83px** | PASS (+1.83) | Caveat loaded | +| O2 | 17px | **9.21px** | PASS (+0.21) | system-ui basis, Space Grotesk title | + +Both hold the floor by design (the spec's formula: O2 basis 17px → 9.21px; +O1 basis 20px → 10.83px). O2 sits closest to the floor (17px is the exact +canonical basis rung), which is correct - the spec sets it there on purpose. +All larger rungs clear automatically. Band labels also verified to fit +inside their bands with the real (condensed) fonts - tightest is O1 +"Iterate msg" at 90.4 of 96 viewBox units. + +--- + +## Scored axes (where the two legitimately diverge - Paul's eye resolves) + +Same axes, both variants, 1-5. These are the trade-off, not a total: a high +score on one is often the mirror of a risk on another. No sum, no winner +declared. + +| Axis | O1 hand-drawn-normalized | O2 premium-editorial flat-vector | +|---|---|---| +| Perceived craft / "consulting-grade" | 3 - clean and disciplined, but the hand style caps how "premium" it can read | 5 - Space Grotesk + 4px radius + white card reads editorial/Stripe-Press | +| Brand-identity fit (handwritten = house rule) | 5 - preserves the mermaid/Caveat brand rule intact | 2 - deliberately breaks it (that is the point of the test) | +| Sam-trust (anti-marketing, not amateur, not generic-startup) | 3 - warm and human, but ADR's Sam-lens flagged hand-drawn as "amateur / unfinished" | 3 - crisp and trustworthy, but risks "generic startup" if it reads too polished | +| Legibility at 390px | 4 - 10.83px basis, condensed Caveat stays readable | 4 - 9.21px basis, system-ui at the floor is clean and dense | +| Consistency across 81 SVGs (the loudest premium signal per ADR D3) | 3 - hand style drifts stroke/texture more easily across many files | 5 - geometric spec is far easier to hold identical at scale | +| Cost to adopt | 5 - cheapest, no restyle of the existing hand-drawn library | 2 - restyle every M1 SVG, then roll forward | + +**How the axes cut:** O1 wins on brand-continuity, warmth, and cost; it is +the safe, cheap keep. O2 wins on perceived craft and scale-consistency - +the two things Paul's 2026-07-31 "old-time / lacks infographic quality" +assessment actually named - at the cost of breaking the handwritten house +rule and a full M1 restyle. Sam-trust is a genuine wash: each carries a +different, opposite risk (amateur vs generic), and only real reader signal +settles it. The exhibit above is deliberately the smoke-test signal meter +because its data-viz (semantic tone bands + ruby threshold) is where O2's +flat-vector discipline shows the most and O1's hand style shows its warmth - +the fairest single test of the divergence. + +--- + +## Spec-ambiguity flags (rendered consistently across BOTH, so they don't bias the A/B) + +1. **Gauge tone-scale vs the single-ruby / green=money-only rules.** The + spec names `smoke-test-signal.svg` as THE gauge/meter archetype, whose + whole encoding is a bad→good tonal scale (ruby kill → amber → green go → + gray). That legitimately uses (a) red in the kill zone and (b) green in + the go zones, which brushes against "ruby marks the ONE actionable + reading" and "green stays money-only". Resolution used in BOTH variants: + the gauge tone-scale is treated as the meter archetype's data encoding; + the single hero **ruby** reading is reserved for the **6% go-line + pointer** (the number the exhibit exists to show), and green reads as + "go / proceed" not money. Applied identically to O1 and O2, so it does + not tilt the comparison. If Paul wants the letter of green=money-only + enforced, the go-zones would need a non-green positive tone (the palette + has none today - worth a spec note before M1 rollout). + +2. **Meter band widths are semi-linear, not strictly linear.** Low bands + (0-3, 3-6) get readable width even though they are narrow percentage + ranges, and 20%+ is a fixed cap. This matches the committed lesson SVG's + treatment and keeps the decision-relevant low end legible; it is a + meter-readability choice, identical in both. + +3. **Class names are generic (`.title`, `.label`, `.basis`).** Matches the + existing course-SVG convention and is correct for the shipping pattern + (each SVG loads as its own `` document). Only collides if + multiple of these SVGs are inlined into ONE HTML document - which the + lesson pages never do. (This bit the render harness mid-build and was + worked around by rendering each in isolation.) + +## Method (repeatable) + +- Rendered each SVG alone in an HTML page with Caveat + Space Grotesk from + Google Fonts, `await document.fonts.ready`, measured the smallest text's + computed font-size × (renderedWidth / viewBoxWidth) at a 390px container. +- Screenshotted each at 720px (equal zoom) for the side-by-side. +- Do NOT inline both SVGs in one page to measure - shared class names + cross-contaminate sizes; render each isolated. diff --git a/docs/projects/2605-tech-for-non-technical-founders/40-49-review/40.30-exemplar-ab-sidebyside.png b/docs/projects/2605-tech-for-non-technical-founders/40-49-review/40.30-exemplar-ab-sidebyside.png new file mode 100644 index 000000000..32a2a4478 Binary files /dev/null and b/docs/projects/2605-tech-for-non-technical-founders/40-49-review/40.30-exemplar-ab-sidebyside.png differ diff --git a/docs/projects/2605-tech-for-non-technical-founders/40-49-review/40.31-sprint-y-classify-audit.md b/docs/projects/2605-tech-for-non-technical-founders/40-49-review/40.31-sprint-y-classify-audit.md new file mode 100644 index 000000000..9b8b58762 --- /dev/null +++ b/docs/projects/2605-tech-for-non-technical-founders/40-49-review/40.31-sprint-y-classify-audit.md @@ -0,0 +1,191 @@ +# 40.31 — Sprint-Y classify-first audit (M1 SVGs, pre-T5) + +**Date:** 2026-08-01 +**Status:** Read-only audit — no SVGs edited +**Scope:** the 5 M1 SVGs, ahead of T5 (style conversion). Outcome-independent — +valid whether Paul picks O1 (hand-drawn-normalized), O2 (flat-vector), or a +mix per ADR 30.09. + +**Binding sources:** `.okf/design/house-visual-spec.md` (hand-drawn section + +v3 exhibit spec / O1-O2 rubric), `docs/projects/2605-tech-for-non-technical-founders/30-39-architecture-design/30.07-media-design-guidelines.md`. + +**Method:** for each SVG, every distinct visual element is classified CONVERT +(generic hand-drawn styling — moves with whichever O1/O2 outcome wins), +KEEP-AS-IS (carries meaning independent of style, cited to a spec rule), or +REVIEW (ambiguous semantic-color usage that doesn't cleanly match the spec's +literal color table — a judgment call for T5/Paul, not a style question). +Legibility floor uses the v3 formula: `rendered_px = font_viewBox * +390/W_viewBox`; the floor is 9px at 390 (a phone viewport). + +--- + +## 1. `form-your-founding-hypothesis-90-minute-sprint/hypothesis-mad-libs.svg` + +viewBox 680×190. Only file that clears the legibility floor today. + +| Element | Convert/Keep | Reason | +|---|---|---| +| Cursive font stack (Caveat/Patrick Hand/Comic Sans) | CONVERT | O1/O2 divergent — O2 uses Space Grotesk for labels (v3 §6) | +| Rotation wobble on pill rects (±0.6–0.8°) | CONVERT | O1 organic feel vs O2's no-wobble orthogonal routing (v3 §3, O1/O2 rubric) | +| Paper-tint pill fills (#fff5f5 red / #fbe9ff purple) | CONVERT | O1 paper-tone background vs O2 "paper white on cream page" (v3 rubric) | +| Pill rx=8 corners | CONVERT | O1 has no fixed-radius target (organic); O2 target is 4px (v3 §3) — needs a deliberate pick either way | +| Labels inside pill shapes (customer/problem/approach/competition/differentiation each printed inside its own pill) | **KEEP-AS-IS** | Sweller split-attention rule — "Labels: INSIDE shapes... never bare diamonds," restated as non-negotiable exhibit grammar in v3 | +| Red = customer/problem/approach; purple = competition/differentiation | REVIEW | Not literally "action/anti-pattern" vs "alternate path" per the color table — reads as a grouping convention (your-build vs market-context), not the spec's literal semantics. Flag for T5/Paul, don't auto-flatten | +| Dash usage in caption | compliant, no finding | no "—" present | + +--- + +## 2. `smoke-test-build-page/page-anatomy.svg` + +viewBox 800×600. + +| Element | Convert/Keep | Reason | +|---|---|---| +| Cursive font stack | CONVERT | same as above | +| Rotation wobble on all 4 blocks (±0.2–0.5°) | CONVERT | same as above | +| Paper-tint red-bordered blocks (#fff5f5/#cc342d) for headline/sub-headline/value-props | CONVERT | O1 paper palette vs O2 white-on-cream | +| CTA block, solid red fill (`.block-cta`) | **KEEP-AS-IS (semantic)** | ruby = the one actionable reading — this IS the click-target, so red-for-action is correct; the hex may shift (#cc342d O1 → equivalent O2 ruby) but the assignment must survive conversion | +| Labels inside blocks (HEADLINE, SUB-HEADLINE, VALUE PROP 1–4, CTA text all printed inside their own rect) | **KEEP-AS-IS** | Sweller rule, non-negotiable grammar | +| `.note` text at 17px viewBox | **OFF-SPEC-TODAY** | renders 17×390/800 = **8.29px @390** — below the 9px floor | +| viewBox 800×600, not W=720 | OFF-SPEC-TODAY | doesn't match the grid/column system or any v3 aspect-ratio bucket | + +--- + +## 3. `smoke-test-wire-tracking/tracking-snippets.svg` + +viewBox 900×500. + +| Element | Convert/Keep | Reason | +|---|---|---| +| Cursive stack for headings/labels/wireframe text | CONVERT | same as above | +| **Monospace (JetBrains Mono/Courier) for event names** (`→ page_view`, `→ cta_click`, `→ form_submit`) | **KEEP-AS-IS** | deliberate typographic split between prose and literal machine-readable tokens — this is the exact "mono code snippet that should stay mono" case; v3's font-swap rule (§6) only governs heading/label/running-text fonts, not literal code/event-name strings | +| Rotation wobble on the 3 snippet boxes + wireframe (±0.2–0.4°) | CONVERT | same as above | +| Purple Clarity box / red pixel box / amber(#b8860b) GA4 box | REVIEW | three tools get three colors as a categorical key, not literal action/alt-path/warning semantics — purple≠alt-path here, amber≠warning here. Flag for T5/Paul before deciding whether to keep as a house "3rd-party-tool key" convention or fold into one neutral color | +| Dashed curved (Q-path) arrows with arrowhead marker | CONVERT-if-O2 | O2's connector spec wants orthogonal routing + filled-triangle arrowhead (9×7); O1 keeps organic curve + open hand-drawn caret (v3 §3) | +| Event markers (`→ page_view` etc.) as bare text near the wireframe, not wrapped in a pill | REVIEW | functions like a connector label but isn't in "a paper-tone pill centered ON the line" per v3 §3 connector spec — T5 should decide whether to formalize as a pill during conversion | +| `.sub` 16px, `.event` 16px, `.wf-text` 18px, `.cta-text` 18px | **OFF-SPEC-TODAY** | render 6.93px / 6.93px / 7.8px / 7.8px @390 — all below floor. `.heading` (28px→12.1px) and `.label` (22px→9.5px) clear it | +| viewBox 900×500, not W=720 | OFF-SPEC-TODAY | same as above | + +--- + +## 4. `smoke-test-landing-page-7-day-demand-test/smoke-test-signal.svg` + +viewBox 960×380. **This is the file the v3 spec cites by name as the canonical +gauge/meter archetype** (house-visual-spec.md v3 §4: "this is the +`smoke-test-signal.svg` archetype") — and it is also, today, the clearest +instance of the "5.5–7px on a 390px phone" defect the same spec opens by +describing. + +| Element | Convert/Keep | Reason | +|---|---|---| +| Cursive stack (Patrick Hand/Caveat) | CONVERT | same as above | +| Ruby "Kill / pivot" 0-3% band | **KEEP-AS-IS** | literally the v3 spec's own worked example: "Ruby-for-signal convention: ruby marks the ONE actionable reading... this is the `smoke-test-signal.svg` archetype" | +| Green "Promising" (6-10%) / "Strong signal" (10-20%) bands | **KEEP-AS-IS** | green = money/success-outcome only (house-spec table) — correctly scoped; this is the ONLY green usage across all 5 files | +| Amber "Iterate msg" (3-6%) band | **KEEP-AS-IS** | amber = warning, used correctly — the one clean amber usage across all 5 files | +| Gray "Suspicious?" (20%+) band | compliant, no finding | neutral/inconclusive reading, no semantic-color rule broken by using gray | +| Band rects: filled, no stroke | **KEEP-AS-IS (compliant already)** | matches v3 §4 hard rule "DATA marks are FILLED, no stroke" — preserve when redrawing | +| 6% threshold: solid line, stroke-width 3 | **OFF-SPEC-TODAY** | v3 §4 requires "a threshold is a 2px DASHED ink line perpendicular to the axis with a labeled tick" — this is solid AND 3px, wrong on both counts | +| `.sub` 15px, `.band-pct` 20px, `.band-verd` 16px, `.tick` 15px, `.ptr` 17px (sub-label 14px), `.rule` 19px | **OFF-SPEC-TODAY** | render 6.09 / 8.13 / 6.5 / 6.09 / 6.91 (5.69) / 7.72 px @390 — every text class except `.title` (27px→10.97px) is below floor. Worst legibility failure of the 5 files by breadth (7 of 8 type classes fail) | +| viewBox 960×380 | OFF-SPEC-TODAY | matches the exact "960-1000 viewBox" defect named in the spec intro; should be 720×300 per the v3 aspect-ratio table (signal meter = 12:5) | + +--- + +## 5. `price-hypothesis-on-smoke-test-page/stripe-payment-link.svg` + +viewBox 960×360. + +| Element | Convert/Keep | Reason | +|---|---|---| +| Cursive stack | CONVERT | same as above | +| Rotation wobble on both cards (±0.3°) | CONVERT | same as above | +| Paper-tint card fills (#fff5f5 outcome / #fff8e0 risk) | CONVERT | O1 paper palette vs O2 white-on-cream | +| Red CTA buttons on both cards | **KEEP-AS-IS (semantic)** | ruby = the actionable click-target on both cards — assignment must survive conversion even if hex shifts | +| Purple bottom callout box (#fbe9ff/#a855f7) | REVIEW | wraps a synthesis statement, not an alternate path — same open question as the mad-libs/tracking-snippets purple usage | +| Amber "RISK-REDUCTION FRAMING" card label/border (#b8860b) | REVIEW | second option label, not literally a warning — same open question as tracking-snippets' amber | +| Labels inside/above their cards (OUTCOME FRAMING / RISK-REDUCTION FRAMING) and CTA text inside buttons | **KEEP-AS-IS** | Sweller rule | +| Identical "$97" repeated on both cards, not colored green | compliant, no finding | correctly NOT treated as the money/success-outcome signal (it's a static repeated fact, not the reading the exhibit proves) | +| `.note` 16px, `.card-label` 22px, `.cta-text` 16px, `.cta-price` 19px, `.card-note` 15px, `.callout` 17px | **OFF-SPEC-TODAY** | render 6.5 / 8.94 / 6.5 / 7.7 / 6.09 / 6.9 px @390 — every text class is below floor, including `.card-label` at 8.94px (just under). `.heading` (28px→11.4px) clears it | +| viewBox 960×360, not W=720 | OFF-SPEC-TODAY | doesn't match the 3:2 comparison-card recommendation in the v3 aspect-ratio table | + +--- + +## Consolidated KEEP-AS-IS list (feeds T5 — preserve regardless of O1/O2) + +1. **Sweller labels-inside-shapes** — every label lives inside or directly on + its own shape in all 5 files (pills, blocks, bars, cards, buttons). Never + redraw a bare/floating label. Non-negotiable exhibit grammar. +2. **Dash discipline ("-" not "—")** — already compliant in all 5 files; must + not regress during redraw. +3. **Monospace for literal event/code tokens** — `tracking-snippets.svg`'s + `→ page_view` / `→ cta_click` / `→ form_submit` stay in JetBrains + Mono/Courier even if the surrounding prose font switches to Space Grotesk + under O2. This is the one clear "should stay mono" case across all 5 files. +4. **Ruby = the one actionable reading** — CTA buttons in `page-anatomy.svg` + and both `stripe-payment-link.svg` cards, and the "Kill/pivot" band in + `smoke-test-signal.svg` (the spec's own worked example of this rule). +5. **Green = money/success-outcome only** — `smoke-test-signal.svg`'s + "Promising"/"Strong signal" bands are the sole green usage across all 5 + files; keep that scarcity, don't spread green decoratively during redraw. +6. **Amber = warning, used correctly once** — `smoke-test-signal.svg`'s + "Iterate msg" band. (Other amber usages are REVIEW items, not clean keeps + — see below.) +7. **Filled-no-stroke data marks** — `smoke-test-signal.svg`'s band rects are + already fill-only, matching the v3 hard rule; preserve this when redrawing + as bars/charts. + +## REVIEW list (ambiguous semantic-color usage — Paul/T5 judgment call, not auto-convert) + +- Purple used as a 3rd/4th categorical color rather than literally + "alternate path": mad-libs' competition/differentiation pills, + tracking-snippets' Clarity box, stripe-payment-link's bottom callout. +- Amber used as a 3rd categorical color rather than literally "warning": + tracking-snippets' GA4 box, stripe-payment-link's risk-reduction card. +- tracking-snippets' event markers function as connector labels but aren't + wrapped in a pill per the v3 §3 connector spec — decide whether to + formalize during conversion. + +Decide once, apply everywhere: either these files intentionally established +a house convention ("purple/amber = 3rd/4th category slot" beyond the +literal 4-color table) worth keeping, or they should be flattened to neutral +grays during T5. Either answer is fine — the point of this audit is that +it's a decision, not a default. + +## Off-spec-today list (fix regardless of which O1/O2 outcome T5 ships) + +1. **Legibility floor violated in 4 of 5 files** (all but + `hypothesis-mad-libs.svg`, viewBox 680, which clears it today): + - `page-anatomy.svg`: `.note` 17px → 8.29px @390 + - `tracking-snippets.svg`: `.sub`/`.event`/`.wf-text`/`.cta-text` → + 6.93/6.93/7.8/7.8px @390 + - `smoke-test-signal.svg`: 7 of 8 text classes fail (5.69–8.13px @390) — + worst breadth of the 5 files, and it's the spec's own cited defect + example + - `stripe-payment-link.svg`: 6 of 7 text classes fail (6.09–8.94px @390) +2. **No file uses the canonical 720 viewBox width** — widths today are 680, + 800, 900, 960, 960; none map to the grid/column system (12 cols, 24 + margin, 12 gutter) or the v3 aspect-ratio table's recommended buckets. +3. **`smoke-test-signal.svg`'s 6% threshold line is solid, 3px** — the v3 + spec requires a threshold to be "a 2px dashed ink line perpendicular to + the axis with a labeled tick." Wrong on both style and width. +4. **Stroke-width inconsistency**: `smoke-test-signal.svg`'s threshold line + (3px) exceeds the 2-2.5px range everywhere else uses; + `stripe-payment-link.svg`'s button stroke (1.5px) is thinner than its own + card stroke (2.5px) in the same file. +5. **Corner radii are ungoverned** — rx ranges from 4 to 31 across the 5 + files with no consistent application of either O1 ("n/a, organic curve") + or O2 (4px) — T5 needs to pick one value set systematically, not + file-by-file. + +--- + +## Bottom line for T5 + +- 7 KEEP-AS-IS items, all cited to a specific spec rule — these transfer + unchanged into whichever O1/O2 outcome ships. +- 6 REVIEW items (purple/amber used as generic 3rd/4th category colors, and + one un-pilled connector label) — these need a decision before T5 redraws, + not a default flatten. +- 5 off-spec-today findings, the biggest being the legibility floor failing + on 4 of 5 files (worst: `smoke-test-signal.svg`, the file the spec itself + names as the archetype) and no file using the canonical W=720 viewBox — + T5 fixes these in either O1 or O2, they are not style-dependent.