@domandigital/craft 0.20.1 → 0.20.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,20 @@
1
1
  # @domandigital/craft
2
2
 
3
+ ## 0.20.3
4
+
5
+ ### Patch Changes
6
+
7
+ - 6800957: Compare carousel purposes before diagnosing duplication, avoid selecting a design by edit size alone, and allow explicit protected-staging placeholders while retaining outstanding publication requirements.
8
+ - d0d9234: Decision confidence: reviewing a proposed change, with attribution to Eunice Ordor and the provenance of the principle (a phone-layout review on 15 October 2026) in CHARACTER.md and PRINCIPLES.md. New `craft direction review --notes design-review.json` weighs feedback against the visitor's job in `art-direction.json`. Each note keeps the observation, the visitor problem under it, the proposed solution, the evidence and the smallest defensible change apart, and judges the suggestion and the recommendation separately. The problem is observed, inferred, preference or unknown: only something inspected (a screenshot, rendered behaviour, source, a measurement, the page's content) makes it observed, a report from an audit, stakeholder or customer makes it inferred, and a claim at a width nobody looked at stays unknown. A recommendation is a confirmed correction, a design hypothesis, an optional refinement or no change, and a review can end on "no change is recommended". Changes climb a ladder from copy to restructure; a structural step or an addition (carousel, script, dependency, animation, testimonial, call to action, repeated content) has to say why every smaller step was not enough. A second carousel is not supported where a gallery exists, information is not removed without an observed cost, a reasoned section order is not overridden by a preference, repetition and similarity to other sites are not defects without a stated cost to the visitor, and a change that needs a fact nobody supplied is held rather than written in. `craft direction validate` also raises an inferred identity finding when a job that worries about who the visitor would deal with first meets a person after three or more sections, and asks for a name and a line, not a biography moved up or a portrait. New `differentiation` lens, `design-review.schema.json`, and exports `assessReview`, `isStructural` and the review types. Fixtures: a calibration review of a plumbing homepage plus clinic and salon reviews, which reach different outcomes for different reasons.
9
+ - bb9b233: Decision confidence. A page in `art-direction.json` can now record `confidence`: the widths its decisions were examined at (`mobile`, `tablet`, `desktop`) and the evidence it offers (`proof`: work, people, credentials, reviews, experience or outcomes, each with a section, `first-look` or `on-request` depth, and a reason tied to the customer's job). `craft direction validate` reads it and prints findings tagged observed, inferred or unknown, each with the lens it belongs to (relevance, hierarchy, evidence, identity, action, disclosure, mobile) and why it matters to that visitor. There is no score and no conversion claim, and nothing is required: a file without `confidence` validates and reports exactly as before, and no evidence kind, founder portrait, slideshow, phone number or section order is ever demanded. A finding made on one width is never carried to another; widths nobody examined are reported as unknown. `craft direction research` asks where the visitor looks, what would settle it and what the next step is, without assuming a phone or a portrait. Exports `assessConfidence`, `validateConfidence`, `viewportOf` and the new types; the JSON Schema gains `confidence`. CHARACTER.md, PRINCIPLES.md, STANDARD.md section 10 and the README describe it, and three fixtures (sole-trader plumber, private physiotherapy practice, appointment-based salon) show one principle giving three different answers.
10
+ - 0dba997: Sites made with create-site deploy their preview to Cloudflare only. `scripts/gates/deploy-preview.mjs` no longer has a Vercel branch or looks for `.vercel/project.json`, `preview.host` in `site.programme.json` is `cloudflare` or null, the `host` answer prompt suggests `cloudflare`, and `docs/site-programme.md` and the README say so. A site that still sets `preview.host` to `vercel` now stops at Stage 06 with a message naming the host; remove the key or set it to `cloudflare`. The synthetic README and a craft comment no longer name Vercel; no behaviour changes in those two.
11
+
12
+ ## 0.20.2
13
+
14
+ ### Patch Changes
15
+
16
+ - 5199c0e: `measureRoute(open, options)` measures every viewport for a page only the caller can open, such as a portal screen behind a sign-in: the phone half in a page the caller opens in `PHONE`, the wide half in one it opens in `DESKTOP` (now exported), merged and written once for `craft phone-first --measured`, as `measureSite` does for a public page (DOM-835).
17
+
3
18
  ## 0.20.1
4
19
 
5
20
  ### Patch Changes
package/CHARACTER.md CHANGED
@@ -19,6 +19,10 @@ the floor in STANDARD.md and the page audit.
19
19
  Character also comes from the display face, accent, shape, motif and one
20
20
  signature moment, with evidence from the client's world.
21
21
 
22
+ Whether the order gives this visitor what they need to trust the business and
23
+ take the next step is the question [Decision confidence](#decision-confidence)
24
+ asks. It reads the same hierarchy layer; it is not a second standard.
25
+
22
26
  ## Three signals, and a reason behind every choice
23
27
 
24
28
  Any fixed list of tells goes stale. Ban Inter and a model moves to Space
@@ -296,6 +300,311 @@ words.
296
300
  The editor schema ships as `@domandigital/craft/art-direction.schema.json`.
297
301
  A file from phase A that holds only exceptions stays valid.
298
302
 
303
+ ### Decision confidence
304
+
305
+ Attributed to Eunice Ordor, Client Relations & Operations at Doman Digital
306
+ ("Eunice's Lens"). The question it asks of every page:
307
+
308
+ > What does this visitor need to see, understand and believe before they are
309
+ > comfortable taking the next appropriate action?
310
+
311
+ It sits beside usability, accessibility, visual quality, performance, brand
312
+ character and the business's own aims, and replaces none of them. It exists to
313
+ improve design judgement, not to make sites alike.
314
+
315
+ A page should give a visitor what they need to understand the business, trust
316
+ it and take the next appropriate step, in an order that follows how they
317
+ decide rather than a sequence of stock sections. Craft already records most of
318
+ that: the job says who is visiting, what worries them and how long they take;
319
+ the hierarchy says what leads, what order, and where the ask sits. Decision
320
+ confidence is the reading of those decisions against the visitor, with three
321
+ additions to the hierarchy layer and no new layer.
322
+
323
+ The questions, with where Craft already answers each. They are lenses to look
324
+ through, not a checklist or a score, and `evidence` and `identity` below are
325
+ the two that cover decision confidence and human accountability:
326
+
327
+ | | Question | Where it is decided or read |
328
+ | --- | --- | --- |
329
+ | A | Visitor relevance: does the page meet who this is and what worries them? | `job`, `hierarchy.*.lead`, and the finding that names a worry no decision answers |
330
+ | B | Information hierarchy: is related information together, and nothing needed early buried? | `hierarchy.*.order` and `journey` reasons; evidence placed in a section the order lacks |
331
+ | C | Evidence and credibility: is what is offered relevant, and does anything show it exists? | `confidence.proof` (kind: work, people, credentials, reviews, experience, outcomes) |
332
+ | D | Human identity and accountability, where relevant: can the visitor tell who they would deal with? | `confidence.proof` of kind `people`, in whatever form fits: a name, a register entry, a portrait |
333
+ | E | Action clarity: is the next step the one this visitor takes, and does the page offer it? | `hierarchy.*.primaryAction`: call, book, enquire, quote, explore, buy |
334
+ | F | Progressive disclosure: essential early, detail when sought, and a signal that the detail exists? | `confidence.proof[].depth`: `first-look` or `on-request` |
335
+ | G | Brand personality and contextual fit: does the character come from this business? | The token layer and its evidence, unchanged |
336
+ | H | Mobile experience: was it looked at on a phone, and what was not examined? | `confidence.examined` and STANDARD.md section 10 |
337
+ | I | Contextual differentiation: does it differ where that helps recognition, clarity, confidence or brand, and only there? | The token layer and `craft estate compare`. Similarity between conventional patterns is not a defect |
338
+
339
+ `confidence` is optional on each page and records two things the hierarchy did
340
+ not: which widths the decisions were looked at (`examined`), and the evidence
341
+ the page offers (`proof`). Each item says what it is, which section it sits in,
342
+ whether a visitor meets it without looking (`first-look`) or opens it
343
+ (`on-request`), and why this visitor needs it. The reason goes through the same
344
+ rule as every other reason: eight words, tied to this client's job, and a
345
+ default such as "social proof builds trust" fails. Cite a source when one shows
346
+ the evidence exists.
347
+
348
+ ```json
349
+ "confidence": {
350
+ "examined": ["mobile"],
351
+ "proof": [
352
+ {
353
+ "kind": "work",
354
+ "what": "one photograph of a finished boiler job with the street and date on a card in the shot",
355
+ "position": "hero",
356
+ "depth": "first-look",
357
+ "because": "The visitor wants to see the actual work before letting a stranger into the house, so one finished job is met on the first screen.",
358
+ "evidence": ["jobs"]
359
+ }
360
+ ]
361
+ }
362
+ ```
363
+
364
+ `craft direction validate` reads it and prints findings after the problems.
365
+ Each names the lens, where in the file, what was found, and why it matters to
366
+ this visitor, and carries one of three bases:
367
+
368
+ - **observed**: directly supported by the file or the snapshot. Evidence placed
369
+ in a section the declared order does not have; an ask positioned in a section
370
+ the order lacks.
371
+ - **inferred**: a reasonable reading that nobody has checked. Detail held back
372
+ for those who seek it, with nothing of its kind met first, so it may never be
373
+ found. This is a hypothesis, not a rule.
374
+ - **unknown**: needs the client or a test. Evidence no source shows exists (a
375
+ planned testimonial, a claimed credential, an outcome nobody has compiled);
376
+ a worry from the job no decision names; a width nobody examined.
377
+
378
+ Nothing here is a score, a count to push towards zero or a prediction. A
379
+ finding says what Craft could and could not establish. A page with no findings
380
+ is not "confident", and one with several is not wrong: unknown means ask.
381
+
382
+ What it deliberately does not do:
383
+
384
+ - Require any evidence kind. A sole trader, a clinic and a salon rely on
385
+ different evidence, and a page with none recorded validates.
386
+ - Require a slideshow, a founder portrait, testimonials above the fold, a
387
+ telephone number, an enquiry form, or any section order. The job decides
388
+ whether the ask is to call, book, enquire, request a quote, explore or
389
+ buy; a clinic whose patients are at work and would rather write is not
390
+ failed for lacking a phone button.
391
+ - Treat a conventional page as weaker. Conventional order is allowed with a
392
+ reason, as above.
393
+ - Carry a finding between widths. A review of a phone layout is evidence about
394
+ the phone. The desktop and tablet are reported as not examined until
395
+ someone examines them, and the findings are then made there.
396
+ - Treat an example claim as a fact. Example copy, a hypothetical years in
397
+ practice or a quote nobody collected is not a source; leave `evidence` empty
398
+ and it is reported as unknown.
399
+
400
+ Three executable fixtures show one principle giving three answers, in
401
+ `src/__tests__/fixtures/confidence/`: a sole-trader plumber (call at once,
402
+ the work and the man's name and van on the first screen, no portrait), a
403
+ private physiotherapy practice (write rather than ring, registration shown as
404
+ text, practitioners by name and specialism with no portraits, an outcomes
405
+ summary reported as unknown because nobody has compiled one), and an
406
+ appointment-based salon (book beside each stylist's own colour work, a full
407
+ gallery on request). They are invented, as the electrician is. None has a
408
+ slideshow; two have no phone action; none has a founder portrait; all validate.
409
+
410
+ #### Where it came from
411
+
412
+ On 15 October 2026 Eunice reviewed the phone layout of a UK plumbing
413
+ business's homepage. She did not review the desktop. Four things came out of
414
+ it, and they are kept apart on purpose:
415
+
416
+ 1. **Her observations.** The owner was introduced late. Information about the
417
+ work, services, reviews and the owner felt fragmented. Visitors should be
418
+ able to feel confident without searching. The site could show more
419
+ personality. Trust signals should read as a set.
420
+ 2. **Her proposed solutions.** A hero slideshow. Removing some project
421
+ captions.
422
+ 3. **An independent audit's conclusions.** It agreed with the underlying
423
+ concerns, that the owner should be met earlier and credibility shown sooner.
424
+ It did not accept two of the solutions. The site already had a swipeable
425
+ project gallery, so a slideshow would repeat it. The captions were short and
426
+ helped people move through the work. Services were early for a reason: a
427
+ visitor first needs to know the business does their job. Moving the whole
428
+ biography under the hero could make the page worse. It preferred targeted
429
+ changes to a redesign. These were the audit's findings, reported to Craft,
430
+ not measurements Craft took.
431
+ 4. **This principle.** A stakeholder can be right about the problem and wrong
432
+ about the fix, and the two are judged separately. Nothing from that one
433
+ site is a design law: it is the case Craft's reasoning is tested against.
434
+
435
+ Craft has no rule for that plumber or any other client. The same reasoning is
436
+ tested on a sole trader, a clinic and a salon, and gives a different answer
437
+ for each.
438
+
439
+ ### Reviewing a proposed change
440
+
441
+ `craft direction validate` reads a page's declared decisions. A review is
442
+ different: somebody has said something about a page, and Craft has to decide
443
+ what follows. `craft direction review --notes design-review.json` weighs the
444
+ notes against the visitor's job in `art-direction.json`. For each note it keeps
445
+ five things apart:
446
+
447
+ | | What it is | Held in |
448
+ | --- | --- | --- |
449
+ | 1 | The observation: what was said or seen, and by whom | `observation`, `raisedBy` |
450
+ | 2 | The underlying visitor problem, if there is one | `problem`, `impact` |
451
+ | 3 | The proposed solution, from whoever proposed it | `suggested` |
452
+ | 4 | The evidence, and what kind it is | `evidence`, `basis` |
453
+ | 5 | The smallest defensible improvement | `recommend` |
454
+
455
+ **How well the problem is known** (`basis`):
456
+
457
+ - **observed**: something was inspected. A screenshot, rendered behaviour,
458
+ source, a measurement, or what the page says. Evidence that was only
459
+ reported, by an audit, a stakeholder or a customer, can support
460
+ **inferred** at most, however confident it sounds.
461
+ - **inferred**: plausible, supported by something reported but not looked at.
462
+ - **preference**: taste, or a stakeholder's wish, with no stated cost to the
463
+ visitor. A fact with no visitor impact is also read this way when it is
464
+ inferred, and as polish at most when it is observed.
465
+ - **unknown**: cannot be established from what is available. Nothing is
466
+ recommended until it is.
467
+
468
+ Craft reads the declared basis against the evidence and says when it changed
469
+ it, in the note. A claim made at a width nobody looked at stays unknown there:
470
+ a review of the phone says nothing about the desktop.
471
+
472
+ **What the recommendation is worth** (`recommend.class`):
473
+
474
+ - **confirmed-correction**: fixes an observed defect that costs the visitor
475
+ something. Needs observed evidence and a stated impact.
476
+ - **design-hypothesis**: could help, and needs judgement or a check to know.
477
+ Names how it would be checked (`validation`).
478
+ - **optional-refinement**: polish. No important visitor problem is addressed.
479
+ - **no-change**: the design already does the job. This is a successful result,
480
+ and a review can end on it: "The existing design is already appropriate for
481
+ what was reviewed. No change is recommended." Craft never invents an issue to
482
+ have something to say.
483
+
484
+ **Minimum effective change.** `recommend.step` is on a ladder, smallest first:
485
+ `copy`, `relocate`, `group`, `imagery`, `trust-placement`, `adjust-component`,
486
+ `remove-redundancy`, then the structural `restructure` and `new-component`. A
487
+ change takes the smallest step that answers the problem. A structural step, or
488
+ any addition that costs something (`carousel`, `javascript`, `dependency`,
489
+ `animation`, `testimonial`, `cta`, `duplicate-content`), must say which smaller
490
+ steps were considered and why none was enough (`smaller`). A small step says why
491
+ nothing larger is needed (`whyEnough`).
492
+
493
+ The rules a review is held to, all checked without a model:
494
+
495
+ - A suggestion and a recommendation are each held to the same tests, so a
496
+ right observation can come with a suggestion that is not supported. Craft
497
+ then reports it as `supported`, `comparison-needed`, `not-supported` or `not-needed`. The legacy
498
+ `narrower-change-preferred` value remains readable, but a step rank alone no
499
+ longer selects a winner. Compare whether each proposal answers the problem.
500
+ - An existing gallery, slideshow or swipeable set prompts a comparison of
501
+ purpose, content and placement. `comparisons` records the exact `existing`
502
+ description, `samePurpose` and `because` on each proposal. A documented
503
+ duplicate should be reused; distinct roles can justify separate components.
504
+ A keyword alone does not establish duplication.
505
+ - Removing information needs an observation that it is redundant and a stated
506
+ cost to the visitor. Short useful captions are not redundancy.
507
+ - A structural change or an addition needs a problem that is observed, or
508
+ inferred with a stated impact. A preference does not justify it.
509
+ - A section the declared order already places with a reason is not moved on a
510
+ preference. Only something observed overrides it.
511
+ - Repetition, a long page, a conventional order and a likeness to other sites
512
+ are not defects. They become findings only through a stated cost to this
513
+ visitor.
514
+ - A change that depends on a fact or asset nobody has supplied (a register
515
+ number, the owner's own words) is held, and the note says what is
516
+ outstanding. Craft does not write it in, and does not infer a registration,
517
+ a qualification or a regulatory status from its absence or presence.
518
+
519
+ Impact is a reason like any other: eight words, about this client's job, and
520
+ neither a preference ("the client wants it") nor the category's default.
521
+
522
+ A note in a review:
523
+
524
+ ```json
525
+ {
526
+ "id": "owner-late",
527
+ "lens": "identity",
528
+ "observation": "The owner is introduced too far down the page.",
529
+ "raisedBy": "Eunice Ordor (stakeholder), agreed by the independent audit",
530
+ "problem": "A homeowner letting a stranger into the house cannot tell who is coming until well down the page.",
531
+ "basis": "observed",
532
+ "evidence": [
533
+ { "kind": "screenshot", "ref": "captures/home-375.png", "viewport": "mobile" },
534
+ { "kind": "audit", "ref": "independent audit of the phone layout", "viewport": "mobile" }
535
+ ],
536
+ "impact": "A homeowner with a stopped boiler cannot see who is coming into the house, so they may ring someone else or ask before reaching the introduction.",
537
+ "appliesTo": ["mobile"],
538
+ "suggested": { "change": "move the full biography directly below the hero", "step": "restructure" },
539
+ "recommend": {
540
+ "class": "confirmed-correction",
541
+ "change": "show the owner's name and one line about working alone beside the first call button",
542
+ "step": "trust-placement",
543
+ "because": "The visitor's worry is who is coming into the house, so a name and one line answer it where the call is first offered.",
544
+ "whyEnough": "The full biography already serves visitors who want it further down, so only a name and a line need to meet the homeowner early.",
545
+ "requires": [{ "what": "the owner's name and that he works alone and answers the phone", "source": "tom" }]
546
+ }
547
+ }
548
+ ```
549
+
550
+ The shape is `design-review.schema.json`. The calibration review in
551
+ `src/__tests__/fixtures/confidence/calibration-review.json` carries the case
552
+ above as a set of notes, against an invented plumber, with the answer Craft
553
+ gives to each: the owner met earlier by a name and a line, and not by moving the
554
+ biography; credibility earlier as a hypothesis with a check; no second carousel;
555
+ the captions left alone; the services left early; no decoration added for
556
+ personality; the owner's own words held until he supplies them; the desktop left
557
+ unknown. The clinic and salon reviews next to it reach different outcomes for
558
+ different reasons: a registration check joined to the profile but held for the
559
+ register numbers; a founder biography declined because booking comes first.
560
+
561
+
562
+ #### Context and learning from a later result
563
+
564
+ The 15 October calibration records the earlier audit's recommendation, not a
565
+ permanent verdict. The later Bellerose mobile comparison on 18 October preferred
566
+ work photographs followed by a compact owner introduction, then trust and contact.
567
+ The useful test is whether each alternative answers the visitor's question.
568
+ Considering smaller edits remains required; fewer edits alone do not establish
569
+ that the result is better. Keep human approval, observed layout changes and
570
+ unmeasured commercial outcomes separate.
571
+
572
+ For each carousel proposal, `comparisons` contains one entry per relevant existing
573
+ component: `{ existing, samePurpose, because }`. Match the existing description
574
+ exactly and explain the purpose, content and placement. This validates the
575
+ recorded reasoning, not the truth of an aesthetic judgment. Same-purpose
576
+ components prompt reuse; missing comparisons request an assessment without
577
+ claiming duplication. Review and photo carousels may answer different questions.
578
+
579
+ Reviews default to publication context. Explicit `context: "protected-staging"`
580
+ can proceed when an unsupplied requirement declares `kind: "asset"`, `phase: "publication"` and a
581
+ clearly marked `placeholder` description. Other requirements still hold the
582
+ change. Every missing item remains in `outstanding`, and `publicationReady`
583
+ remains false. This does not authorize publishing a placeholder or inventing a
584
+ fact. Record actual asset delivery before assessing publication again.
585
+
586
+ Save real before/after examples with capture dates, viewport, source commits,
587
+ feedback attribution, decisions and validation. Assess the page independently
588
+ before reading stakeholder recommendations when possible; if feedback is already
589
+ known, record that limitation. A preferred example is useful calibration, not a
590
+ universal order, a conversion claim or an exemption from future scrutiny.
591
+
592
+ #### Using it
593
+
594
+ Generating a page: run `craft direction research`, which asks where the
595
+ visitor looks, what would settle it for them and what the next step is, without
596
+ assuming a phone, a portrait or any one of them. Write the hierarchy from those
597
+ answers, add `confidence` where the page makes decisions about evidence, and run
598
+ `craft direction validate`. The findings are the list of what to confirm with
599
+ the client or look at before launch.
600
+
601
+ Reviewing a page or acting on feedback: write each remark as a note (what was
602
+ said, what the visitor loses, what was proposed, what was inspected), then run
603
+ `craft direction review --notes design-review.json`. Do the changes that come
604
+ back as `change`, ask for what is `hold`, find out what is `gather-evidence`,
605
+ and leave what is `no-change`. When a note names something that was not
606
+ inspected, look before you act on it.
607
+
299
608
  ## Declaring an exception
300
609
 
301
610
  Doman Digital's own brand is violet. A hue rule with no way to say so flags the
package/PRINCIPLES.md CHANGED
@@ -15,10 +15,10 @@ curves depending on which repo you were standing in.
15
15
 
16
16
  **`--ease-emphasized` was byte-identical to `--ease-standard`.** Both
17
17
  `cubic-bezier(0.2, 0, 0, 1)`. Every component reaching for emphasis got the
18
- standard curve and no emphasis. This is invisible on inspection — the names
18
+ standard curve and no emphasis. This is invisible on inspection: the names
19
19
  differ, the values are 26 characters apart, and nothing fails.
20
20
 
21
- **`--ease-exit` was `cubic-bezier(0.4, 0, 1, 1)` — an ease-*in* curve.** It
21
+ **`--ease-exit` was `cubic-bezier(0.4, 0, 1, 1)`, an ease-*in* curve.** It
22
22
  starts slow and accelerates out of view. It is the one curve never to use for
23
23
  UI: a dismissal on an ease-in reads as the interface dragging the thing away from
24
24
  you rather than getting out of your way.
@@ -34,7 +34,7 @@ the end state applies, and nothing moves.
34
34
  **141 classes painting nothing.** `bg-bg3` (48 uses) and `border-border` (93) in
35
35
  the portal reference Tailwind theme keys that do not exist under v4. They resolve
36
36
  to nothing and fall through to whatever the base rule said. Adding the missing
37
- keys would not be a fix — it would suddenly paint 48 surfaces nobody designed.
37
+ keys would not be a fix. It would suddenly paint 48 surfaces nobody designed.
38
38
 
39
39
  **Two guesses at one accessible accent.** Two client repos each hand-picked a
40
40
  "legible variant" of the brand accent and wrote the contrast ratio into a
@@ -59,7 +59,7 @@ silence.
59
59
 
60
60
  **Both contrast models, because they disagree and the disagreement matters.**
61
61
  The portal's shipped `--violet-400` (`#a78bfa`) scores 7.21:1 against the
62
- marketing canvas — comfortably AA — and Lc −49.1, which is under the house bar
62
+ marketing canvas, comfortably AA, and Lc −49.1, which is under the house bar
63
63
  for body text. WCAG 2.x is what an audit asks for; APCA is what tracks
64
64
  readability on dark backgrounds. The house bar is the pair.
65
65
 
@@ -71,7 +71,7 @@ passes: maximum brand, minimum sufficient contrast.
71
71
  **Motion is a decision before it is a curve.** The commonest motion defect is
72
72
  not a wrong easing, it is animating something that should have been instant.
73
73
  `shouldAnimate` refuses keyboard-triggered motion outright, refuses anything a
74
- user hits a hundred times a day, and always gives a reason — so a "no" is
74
+ user hits a hundred times a day, and always gives a reason, so a "no" is
75
75
  arguable rather than mysterious.
76
76
 
77
77
  **Plain custom properties, nothing else.** The consumers do not agree on a
@@ -84,7 +84,7 @@ decide: the styling engine, the motion library, or where the tokens live.
84
84
  An anchor's real lightness and the ramp's lightness curve contradict each other.
85
85
  `#7050f5` sits at OKLCh L=0.564; `LIGHTNESS_CURVE[500]` is 0.658. Pin the anchor
86
86
  at 500, generate 600 from the raw curve at 0.586, and step 600 comes out
87
- *lighter* than step 500 — a ramp that reverses direction halfway down.
87
+ *lighter* than step 500, a ramp that reverses direction halfway down.
88
88
 
89
89
  Both properties are required, so neither can be dropped. The curve is warped
90
90
  instead: a piecewise-linear map pinned at 0 and 1 that passes through
@@ -105,3 +105,27 @@ never the page grammar, because a page that looks typical for its category is
105
105
  the one visitors trust first. And it never asks for novelty. It asks for a
106
106
  reason: every expressive choice records where it came from in the client's own
107
107
  world, and a choice with no reason is the one flagged.
108
+
109
+ ## Decision confidence
110
+
111
+ The same restraint applies to trust. A page is judged against what this
112
+ visitor needs in order to understand the business, believe it and take the
113
+ next step: who they are, what worries them, which evidence would settle it, and
114
+ what the sensible next action is. That differs between a plumber with a
115
+ stopped boiler, a clinic whose patients want to check a register and a salon
116
+ whose clients want to see colour work before they book. So Craft asks for the
117
+ reasoning, never for a pattern: no required hero, portrait, slideshow, section
118
+ order or phone button, and no finding that a design is "less confident". What
119
+ it records is what was observed, what is inferred, and what is unknown and needs
120
+ the client or a test, and at which widths each was looked at. The phone is
121
+ where this is examined first; a finding made there is not assumed to hold on a
122
+ desktop. See [CHARACTER.md](./CHARACTER.md#decision-confidence).
123
+
124
+ The principle is Eunice Ordor's, from a review of a phone layout on 15 October 2026,
125
+ and its question is: what does this visitor need to see, understand and believe
126
+ before they are comfortable taking the next appropriate action? It adds to the
127
+ standards above and replaces none of them. It also sets how a change is chosen:
128
+ a stakeholder's observation, the visitor problem under it, the proposed fix and
129
+ the evidence are judged apart, and the smallest change that answers the problem
130
+ wins. "The existing design is already appropriate" is a result. See
131
+ [Reviewing a proposed change](./CHARACTER.md#reviewing-a-proposed-change).
package/README.md CHANGED
@@ -107,6 +107,20 @@ npx craft estate compare --estate estate.json --directions
107
107
  npx craft direction validate --snapshot http://localhost:3000 --page home --strict
108
108
  ```
109
109
 
110
+ A page may also record `confidence`: the widths its decisions were examined at
111
+ and the evidence it offers, each with a reason. `craft direction validate`
112
+ reports what is observed, inferred or unknown about it, with why it matters and
113
+ no score. Nothing in it is required: no evidence kind, portrait, slideshow,
114
+ phone button or section order. See [Decision confidence](./CHARACTER.md#decision-confidence).
115
+
116
+ Feedback on a page is weighed against the visitor. `craft direction review --notes
117
+ design-review.json` keeps what was said, the visitor problem under it, what was
118
+ proposed, the evidence and the smallest defensible change apart, says how well
119
+ each is known (observed, inferred, preference or unknown), and can conclude that
120
+ no change is needed. Evidence only reported by an audit or a stakeholder cannot
121
+ make a problem observed, and a width nobody looked at stays unknown. See
122
+ [Reviewing a proposed change](./CHARACTER.md#reviewing-a-proposed-change).
123
+
110
124
  `--snapshot` accepts saved files and preview or production URLs. Drift fails
111
125
  with `--strict`; declared estate comparisons stay advisory. Version 1 files
112
126
  still validate with a warning. See [CHARACTER.md](./CHARACTER.md) for the full
@@ -305,7 +319,10 @@ test(`every viewport: ${route}`, async ({ page }) => {
305
319
  ```
306
320
 
307
321
  `measureViewports` works on the page the suite opened and signed in, so a
308
- portal keeps its fixtures. `measureSite(browser, { base, routes })` opens each
322
+ portal keeps its fixtures. `measureRoute(open, { route, mainAction })` does
323
+ both halves for such a page: `open("phone")` and `open("wide")` return the
324
+ route opened and signed in, in a `PHONE` and a `DESKTOP` context, and the two
325
+ halves are merged and written once (DOM-835). `measureSite(browser, { base, routes })` opens each
309
326
  route itself, the phone half in a phone context and the wide half in a desktop
310
327
  one, for a page anyone can open: create-site's `measure.mjs` uses it.
311
328
  `craft viewports --url <base> --route /` is the same for the command line: it
@@ -340,3 +357,10 @@ routes measured only at 375 with `measurePhone`.
340
357
  ## Licence
341
358
 
342
359
  Apache-2.0
360
+
361
+
362
+ Design reviews compare proposed carousel purposes through `comparisons`; a shared
363
+ widget name no longer proves duplication. A smaller implementation does not
364
+ select a better design automatically. Protected staging reviews may reserve
365
+ explicitly marked publication assets while reporting `publicationReady: false`.
366
+ See CHARACTER.md, “Context and learning from a later result”.
package/STANDARD.md CHANGED
@@ -162,7 +162,11 @@ is designed, built and measured first, and every wider layout is derived from
162
162
  it. A desktop layout squeezed onto a phone keeps the desktop's priorities and
163
163
  drops whatever did not fit; a phone layout widened keeps what matters and adds.
164
164
  Fitting on a phone is the floor. The bar is a page optimised for the phone and
165
- intended at every width, and the two sub-sections below set it.
165
+ intended at every width, and the two sub-sections below set it. What the phone
166
+ visitor needs in order to trust the business and take the next step is a
167
+ judgement about the page, not a measurement; it is recorded and reported as
168
+ [decision confidence](./CHARACTER.md#decision-confidence), and a finding made on
169
+ the phone is not carried to another width without looking there.
166
170
 
167
171
  - **The phone is the base.** Base styles are the phone layout. Wider layouts
168
172
  are added with `min-width` queries only (Tailwind: unprefixed is the phone,
@@ -434,6 +434,88 @@
434
434
  "additionalProperties": false
435
435
  },
436
436
  "minItems": 2
437
+ },
438
+ "confidence": {
439
+ "type": "object",
440
+ "description": "Optional. Decision confidence for this page: the widths its decisions were examined at, and the evidence it offers, where it sits and how much is met first. Nothing in it is required: the job decides which kinds of evidence matter. Findings craft reads from it are never a score.",
441
+ "properties": {
442
+ "examined": {
443
+ "type": "array",
444
+ "items": {
445
+ "enum": [
446
+ "mobile",
447
+ "tablet",
448
+ "desktop"
449
+ ]
450
+ },
451
+ "description": "The widths the evidence behind these decisions was looked at. A finding from one width is not carried to another."
452
+ },
453
+ "proof": {
454
+ "type": "array",
455
+ "items": {
456
+ "$ref": "#/$defs/proofItem"
457
+ }
458
+ }
459
+ },
460
+ "additionalProperties": false
461
+ }
462
+ },
463
+ "additionalProperties": false
464
+ },
465
+ "proofItem": {
466
+ "type": "object",
467
+ "required": [
468
+ "kind",
469
+ "what",
470
+ "position",
471
+ "depth",
472
+ "because"
473
+ ],
474
+ "properties": {
475
+ "kind": {
476
+ "enum": [
477
+ "work",
478
+ "people",
479
+ "credentials",
480
+ "reviews",
481
+ "experience",
482
+ "outcomes"
483
+ ]
484
+ },
485
+ "what": {
486
+ "type": "string",
487
+ "description": "What it is, in a few words: photographs of three finished bathrooms, the register number."
488
+ },
489
+ "position": {
490
+ "anyOf": [
491
+ {
492
+ "$ref": "#/$defs/role"
493
+ },
494
+ {
495
+ "enum": [
496
+ "header",
497
+ "sticky"
498
+ ]
499
+ }
500
+ ],
501
+ "description": "Where it sits. A section role must be in the page's order."
502
+ },
503
+ "depth": {
504
+ "enum": [
505
+ "first-look",
506
+ "on-request"
507
+ ],
508
+ "description": "first-look is met without being sought; on-request is detail a visitor opens or follows."
509
+ },
510
+ "because": {
511
+ "type": "string"
512
+ },
513
+ "evidence": {
514
+ "type": "array",
515
+ "items": {
516
+ "type": "string"
517
+ },
518
+ "description": "Source ids that show this exists. With none it is a claim the client has yet to confirm."
437
519
  }
438
520
  },
439
521
  "additionalProperties": false