@domandigital/craft 0.22.0 → 0.23.0

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.
Files changed (33) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/CHARACTER.md +138 -5
  3. package/COPY.md +35 -9
  4. package/PRINCIPLES.md +9 -0
  5. package/README.md +6 -0
  6. package/design-review.schema.json +156 -0
  7. package/dist/{audit-LQ2TDISV.js → audit-CRTC7JSF.js} +3 -3
  8. package/dist/audit.cjs +365 -15
  9. package/dist/audit.js +365 -15
  10. package/dist/{chunk-DE2ZAV4G.js → chunk-3LCBLDAO.js} +171 -3
  11. package/dist/{chunk-6PZG4MJS.js → chunk-3LHIKF5L.js} +5 -5
  12. package/dist/{chunk-G47ZCBD5.js → chunk-4NON4PVK.js} +2 -2
  13. package/dist/{chunk-6DRBFDWT.js → chunk-A7KUKNX6.js} +1 -1
  14. package/dist/{chunk-OVWVKMPS.js → chunk-KGEJ2TGT.js} +14 -14
  15. package/dist/{chunk-ONA73THJ.js → chunk-KIBDFRHT.js} +195 -13
  16. package/dist/{chunk-ZS7PQNJU.js → chunk-OTQQTXXK.js} +4 -4
  17. package/dist/{chunk-RBQCGDQQ.js → chunk-Y2LGYHJ5.js} +5 -5
  18. package/dist/{cli-R2HBESHI.js → cli-E2CFVIGZ.js} +5 -5
  19. package/dist/{cli-SZ4SZLUN.js → cli-HWGSNSDD.js} +4 -4
  20. package/dist/{cli-7DL4BKA7.js → cli-IYRJZWMN.js} +6 -6
  21. package/dist/{cli-YNIJOEJK.js → cli-RHU3MAZY.js} +3 -3
  22. package/dist/{cli-AM4FLXGM.js → cli-ROVZDHVR.js} +5 -5
  23. package/dist/{cli-T7A3BU5J.js → cli-TPV2EIIN.js} +9 -9
  24. package/dist/{cli-WZA5IXSR.js → cli-X3RZE4GM.js} +6 -6
  25. package/dist/{cli-7QL26YPR.js → cli-YRRBBU27.js} +1 -1
  26. package/dist/cli.js +3 -3
  27. package/dist/index.cjs +368 -15
  28. package/dist/index.d.cts +49 -3
  29. package/dist/index.d.ts +49 -3
  30. package/dist/index.js +367 -15
  31. package/dist/{viewports-cli-F7KJIVZL.js → viewports-cli-EAUVLHFJ.js} +3 -3
  32. package/package.json +1 -1
  33. package/word-lists.json +11 -2
@@ -9,7 +9,7 @@ import {
9
9
  parseFile,
10
10
  sentencesOf,
11
11
  specificity
12
- } from "./chunk-ONA73THJ.js";
12
+ } from "./chunk-KIBDFRHT.js";
13
13
  import {
14
14
  SNAPSHOT_VERSION
15
15
  } from "./chunk-QYBAVU3P.js";
@@ -770,6 +770,69 @@ function eyebrowChipHits(ctx) {
770
770
  }
771
771
  return hits;
772
772
  }
773
+ var HERO_OPEN = /<(section|header|div|main|article|Section|Container)\b[^>]*?\b(?:class|className|id)\s*=\s*(?:"|'|\{\s*[`"']?)[^"'`>]*?(?<![a-z])hero(?![a-z])[^>]*>/gi;
774
+ function closeOf(text, tag, from) {
775
+ const re = new RegExp(`<(/?)${tag}\\b[^>]*?(/?)>`, "g");
776
+ re.lastIndex = from;
777
+ let depth = 0;
778
+ for (let m = re.exec(text); m; m = re.exec(text)) {
779
+ if (m[2] === "/") continue;
780
+ depth += m[1] === "/" ? -1 : 1;
781
+ if (depth === 0) return m.index + m[0].length;
782
+ if (m.index - from > 8e3) break;
783
+ }
784
+ return Math.min(text.length, from + 4e3);
785
+ }
786
+ function heroSpans(path, text) {
787
+ if (/(?:^|[\\/])[\w-]*hero[\w-]*\.(?:astro|tsx|jsx|vue|svelte)$/i.test(path)) return [[0, text.length]];
788
+ const spans = [];
789
+ for (const m of text.matchAll(HERO_OPEN)) {
790
+ const at = m.index ?? 0;
791
+ if (spans.some(([a, b]) => at >= a && at < b)) continue;
792
+ spans.push([at, closeOf(text, m[1], at)]);
793
+ }
794
+ if (spans.length > 0) return spans;
795
+ const h1 = text.search(/<h1\b/);
796
+ if (h1 === -1) return [];
797
+ const rest = text.slice(h1);
798
+ const end = rest.search(/<\/(?:section|header)>|<section\b/);
799
+ return [[h1, h1 + Math.min(end === -1 ? rest.length : end, 1500)]];
800
+ }
801
+ var CONTROL = /<(a|button|Button|ButtonLink|LinkButton|Link|Cta|CTA|CallToAction)\b([^>]*)>([\s\S]{0,300}?)<\/\1>/g;
802
+ var BUTTON_COMPONENT = /^(?:Button|ButtonLink|LinkButton|Cta|CTA|CallToAction)$/;
803
+ var BUTTON_CLASS = /(?<![a-z])(?:btn|button|cta)(?![a-z])/i;
804
+ var TOGGLE = /\baria-(?:expanded|controls|haspopup)\b|\btype\s*=\s*["']submit["']/;
805
+ var NOT_A_LANDING = /(?:^|[\\/])(?:error|global-error|not-found|404|500)\.\w+$|[\\/](?:admin|portal|dashboard|account|\(qa\)|\(app\)|qa)[\\/]/i;
806
+ function buttonLabel(attrs, inner) {
807
+ const text = inner.replace(/<[^>]*>/g, " ").replace(/\{[^}]*\}/g, " ").replace(/\s+/g, " ").trim();
808
+ if (text && !/[{}()=]/.test(text)) return text.slice(0, 40);
809
+ return attrs.match(/\bhref\s*=\s*["'{`$]*\{?([^"'}`\s]+)/)?.[1] ?? "a button";
810
+ }
811
+ function heroCtaPairHits(ctx) {
812
+ const hits = [];
813
+ for (const file of ctx.files) {
814
+ if (file.kind !== "markup" || NOT_A_LANDING.test(file.path)) continue;
815
+ const text = file.text.replace(/\\"/g, ' "');
816
+ for (const [start, end] of heroSpans(file.path, text)) {
817
+ const span = text.slice(start, end).replace(/<(nav|form)\b[\s\S]*?<\/\1>/gi, (s) => " ".repeat(s.length));
818
+ const buttons = [];
819
+ for (const m of span.matchAll(CONTROL)) {
820
+ const [, tag, attrs, inner] = m;
821
+ if (TOGGLE.test(attrs)) continue;
822
+ const cls = attrs.match(/\b(?:class|className|variant)\s*=\s*(?:"([^"]*)"|'([^']*)'|\{([^}]*)\})/g)?.join(" ") ?? "";
823
+ const tw = /\bpx-\d/.test(cls) && /\bpy-\d/.test(cls) && /\b(?:bg-|border\b|border-|rounded)/.test(cls);
824
+ if (BUTTON_COMPONENT.test(tag) || BUTTON_CLASS.test(cls) || tw || /\brole\s*=\s*["']button["']/.test(attrs)) {
825
+ buttons.push({ label: buttonLabel(attrs, inner), offset: start + (m.index ?? 0) });
826
+ }
827
+ }
828
+ if (buttons.length >= 2) {
829
+ const names = buttons.slice(0, 3).map((b) => `"${b.label}"`).join(", ");
830
+ hits.push({ path: file.path, offset: buttons[1].offset, message: `${buttons.length} buttons side by side in the hero: ${names}` });
831
+ }
832
+ }
833
+ }
834
+ return hits;
835
+ }
773
836
  function iconTiles(file) {
774
837
  return file.classUnits.filter((unit) => {
775
838
  const sized = has(unit, /^size-(?:8|9|10|11|12|14)$/) || (find(unit, /^h-(?:8|9|10|11|12|14)$/) ?? "x").slice(2) === (find(unit, /^w-(?:8|9|10|11|12|14)$/) ?? "y").slice(2);
@@ -1220,6 +1283,75 @@ const inter = Inter({ subsets: ["latin"] });`),
1220
1283
  <span className="inline-flex rounded-full border px-3 py-1 text-xs">Tag</span>`)]
1221
1284
  }
1222
1285
  },
1286
+ {
1287
+ id: "hero-cta-pair",
1288
+ name: "Two buttons in the hero",
1289
+ generation: 1,
1290
+ severity: "warn",
1291
+ surface: "source",
1292
+ why: "A filled button beside an outline or ghost one ('Get a free quote' / 'See our plans') is in 140 of 140 heroes Claude builds for a brief. Two equal asks make the visitor choose before they know anything, and say nobody decided what the page is for.",
1293
+ fix: "Keep one button, the ask the page exists for. Put the second route in the copy as a text link ('or see the work first'), or lower down where it answers a question.",
1294
+ detect: heroCtaPairHits,
1295
+ fixtures: {
1296
+ flag: [
1297
+ // Eunice Ordor's #5 and #36 (Pastel 986559): the DD site's own hero and process close.
1298
+ f(
1299
+ "src/components/Hero.astro",
1300
+ `<section class="hero">
1301
+ <h1>We run the systems behind your website</h1>
1302
+ <a href="/contact" class="btn btn-primary">Get in touch</a>
1303
+ <a href="/work" class="btn btn-ghost">See our work</a>
1304
+ </section>`
1305
+ ),
1306
+ // The null build's hero, verbatim in shape (calibration/null/rmp/pages/05.html).
1307
+ f(
1308
+ "index.html",
1309
+ `<nav><a class="btn" href="#contact">Quote</a></nav>
1310
+ <section id="hero" class="hero">
1311
+ <h1>Electricians in Uxbridge</h1>
1312
+ <a href="#contact" class="btn btn-primary">Book a Free Quote</a>
1313
+ <a href="tel:+441895555210" class="btn btn-outline">Call 01895 555 210</a>
1314
+ </section>`
1315
+ ),
1316
+ f(
1317
+ "app/page.tsx",
1318
+ `<section className="relative py-24">
1319
+ <h1 className="text-5xl">Nails in Brackley</h1>
1320
+ <div className="flex gap-4">
1321
+ <Button asChild><a href="/book">Book now</a></Button>
1322
+ <Button variant="outline">View treatments</Button>
1323
+ </div>
1324
+ </section>`
1325
+ )
1326
+ ],
1327
+ pass: [
1328
+ // One button, and the second route as a text link in the sentence.
1329
+ f(
1330
+ "src/components/Hero.astro",
1331
+ `<section class="hero">
1332
+ <h1>We run the systems behind your website</h1>
1333
+ <p>Tell us what's going on, or <a href="/work">see the work first</a>.</p>
1334
+ <a href="/contact" class="btn btn-primary">Get in touch</a>
1335
+ </section>`
1336
+ ),
1337
+ // A button in the nav and a search form are not the hero's ask.
1338
+ f(
1339
+ "index.html",
1340
+ `<header class="hero">
1341
+ <nav><a class="btn" href="/book">Book</a></nav>
1342
+ <h1>Barbers in Manchester</h1>
1343
+ <a class="btn" href="/book">Book a cut</a>
1344
+ <form><button class="btn" type="submit">Search</button></form>
1345
+ </header>`
1346
+ ),
1347
+ f("app/page.tsx", `<section className="py-24">
1348
+ <h1 className="text-5xl">Nails in Brackley</h1>
1349
+ <a className="rounded bg-ink px-5 py-3" href="/book">Book now</a>
1350
+ </section>
1351
+ <section><a className="rounded bg-ink px-5 py-3" href="/prices">Prices</a></section>`)
1352
+ ]
1353
+ }
1354
+ },
1223
1355
  {
1224
1356
  id: "icon-tile-stack",
1225
1357
  name: "Icon in a tinted tile",
@@ -2418,7 +2550,9 @@ var HOUSE = {
2418
2550
  "no-x-badge": { tier: "block", label: 'standalone "No X" badge. Reads as a slapped-on kicker, and worse when reused across pieces' },
2419
2551
  "ai-phrase": { tier: "block", label: "AI tell" },
2420
2552
  "plainer-word": { tier: "block", label: "a plainer word exists. Name the mechanism instead" },
2421
- "plain-english": { tier: "block", label: 'use "properly explained"' },
2553
+ // Widened 2026-10-20 (founder) to bare "plainly" and "in plain terms/language/words";
2554
+ // estate hits read first (DOM-1058), nearly all the stock "stated plainly".
2555
+ "plain-english": { tier: "block", label: 'the plain-English family. Drop the adverb and say the thing, or use "properly explained"' },
2422
2556
  buzzword: { tier: "block", label: "forbidden phrase" },
2423
2557
  "negative-reassurance": { tier: "block", label: "negative reassurance, say what they get" },
2424
2558
  // Evidence of a pasted chat reply, not a matter of style. Moved from review
@@ -2432,6 +2566,13 @@ var HOUSE = {
2432
2566
  "stock-email-line": { tier: "review", label: "stock email line, start with the reason for writing and end with the next step" },
2433
2567
  // New 2026-10-19 (founder): review first, like every new tell, until estate hits are read.
2434
2568
  "matey-register": { tier: "review", label: "matey register, write plain and complete British English" },
2569
+ // New 2026-10-20 (founder, from Eunice Ordor's review): review first, like every new tell.
2570
+ "confession-line": { tier: "review", label: "confession line, scope the work by saying precisely what is true" },
2571
+ // New 2026-10-23 (a 92EL report passed the gate with three): review, because a
2572
+ // genuine disclaimer has the same shape. The gerund pair joined not-just-but.
2573
+ // New 2026-10-23 (founder, from 92EL deliverables): review, since a short slide label is often fine.
2574
+ "parallel-pair": { tier: "review", label: "verbless parallel pair, write the sentence it stands for" },
2575
+ "trailing-contrast": { tier: "review", label: "trailing contrast. Say the positive claim, unless it is a disclaimer the reader needs" },
2435
2576
  "ai-vocabulary": { tier: "review", label: "AI vocabulary" },
2436
2577
  "stock-phrase": { tier: "review", label: "stock phrase" },
2437
2578
  "hollow-imperative": { tier: "review", label: "hollow imperative" },
@@ -2614,6 +2755,33 @@ var RENDERED_PATHS = {
2614
2755
  detect: (s) => s.effects.eyebrowChip ? [hit(s, "a small bordered pill sits above the headline")] : [],
2615
2756
  fixtures: { flag: [makeSnapshot({ effects: { eyebrowChip: true } })], pass: [makeSnapshot()] }
2616
2757
  },
2758
+ "hero-cta-pair": {
2759
+ // Version 2 geometry counts buttons and button-styled links per section. A
2760
+ // header painted inside the hero's box adds its own button, which the
2761
+ // source path can tell apart and this one cannot; a ghost button with no
2762
+ // fill or border is not counted, so this path under-reports.
2763
+ detect: (s) => {
2764
+ const first = s.sections[0];
2765
+ const controls = first?.geometry?.controls ?? 0;
2766
+ return first && (first.role ?? first.kind) === "hero" && controls >= 2 ? [hit(s, `${controls} buttons in the hero`, first.label)] : [];
2767
+ },
2768
+ fixtures: {
2769
+ flag: [
2770
+ {
2771
+ ...makeSnapshot(),
2772
+ sections: makeSnapshot().sections.map((x, i) => i === 0 ? { ...x, role: "hero", geometry: { centredShare: 0.2, mirrorSymmetry: 0.6, whitespaceRatio: 0.6, contentWidthRatio: 0.8, background: "rgb(255, 255, 255)", controls: 2 } } : x)
2773
+ }
2774
+ ],
2775
+ pass: [
2776
+ makeSnapshot(),
2777
+ // One button, with the second route as a text link: one control.
2778
+ {
2779
+ ...makeSnapshot(),
2780
+ sections: makeSnapshot().sections.map((x, i) => i === 0 ? { ...x, role: "hero", geometry: { centredShare: 0.2, mirrorSymmetry: 0.6, whitespaceRatio: 0.6, contentWidthRatio: 0.8, background: "rgb(255, 255, 255)", controls: 1 } } : x)
2781
+ }
2782
+ ]
2783
+ }
2784
+ },
2617
2785
  "icon-tile-grid": {
2618
2786
  detect: (s) => s.sections.filter((x) => x.cards >= 3 && x.iconCards >= 3).map((x) => hit(s, `${x.iconCards} icon cards in a row`, x.label)),
2619
2787
  fixtures: {
@@ -3027,7 +3195,7 @@ var IMAGERY_TELLS = [
3027
3195
  ];
3028
3196
 
3029
3197
  // src/character/check.ts
3030
- var CATALOGUE_VERSION = "2026.10.4";
3198
+ var CATALOGUE_VERSION = "2026.10.7";
3031
3199
  var CATALOGUE = [
3032
3200
  ...[...SOURCE_TELLS, ...COPY_TELLS, ...RESEARCH_TELLS, ...DENSITY_TELLS].map((t) => RENDERED_PATHS[t.id] ? { ...t, rendered: RENDERED_PATHS[t.id] } : t),
3033
3201
  ...SPECIFICITY_COPY_TELLS,
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-OQXTQQAU.js";
4
4
  import {
5
5
  parseFlags
6
- } from "./chunk-OVWVKMPS.js";
6
+ } from "./chunk-KGEJ2TGT.js";
7
7
  import {
8
8
  toJson
9
9
  } from "./chunk-QIEDBL4J.js";
@@ -22,10 +22,10 @@ import {
22
22
  hueSwatch,
23
23
  nullPrompt,
24
24
  scanSource
25
- } from "./chunk-DE2ZAV4G.js";
25
+ } from "./chunk-3LCBLDAO.js";
26
26
  import {
27
27
  extractStrings
28
- } from "./chunk-ONA73THJ.js";
28
+ } from "./chunk-KIBDFRHT.js";
29
29
 
30
30
  // src/null/cli.ts
31
31
  import { existsSync, mkdirSync, readdirSync, readFileSync, rmSync, statSync, writeFileSync } from "fs";
@@ -120,7 +120,7 @@ async function build(flags, io) {
120
120
  const toShoot = ids.filter((id) => existsSync(join(pages, `${id}.html`)) && !existsSync(join(shots, `${id}.json`)));
121
121
  if (toShoot.length) {
122
122
  io.out(`craft null: snapshotting ${toShoot.length} page${toShoot.length === 1 ? "" : "s"}`);
123
- const { snapshotUrls } = await import("./audit-LQ2TDISV.js");
123
+ const { snapshotUrls } = await import("./audit-CRTC7JSF.js");
124
124
  const results = await snapshotUrls(toShoot.map((id) => pathToFileURL(join(pages, `${id}.html`)).href));
125
125
  results.forEach((r, i) => {
126
126
  const id = toShoot[i];
@@ -241,7 +241,7 @@ async function importPages(flags, io) {
241
241
  const toShoot = pages.filter((p) => !existsSync(join(shots, `${p.id}.json`)));
242
242
  if (toShoot.length) {
243
243
  io.out(`craft null: snapshotting ${toShoot.length} page${toShoot.length === 1 ? "" : "s"} from ${flags.builder}`);
244
- const { snapshotUrls } = await import("./audit-LQ2TDISV.js");
244
+ const { snapshotUrls } = await import("./audit-CRTC7JSF.js");
245
245
  const servers = /* @__PURE__ */ new Map();
246
246
  try {
247
247
  for (const p of toShoot) if (!servers.has(p.root)) servers.set(p.root, await serveDir(p.root));
@@ -10,10 +10,10 @@ import {
10
10
  levenshtein,
11
11
  normaliseFamily,
12
12
  parseColour
13
- } from "./chunk-DE2ZAV4G.js";
13
+ } from "./chunk-3LCBLDAO.js";
14
14
  import {
15
15
  TRADE_NOUNS
16
- } from "./chunk-ONA73THJ.js";
16
+ } from "./chunk-KIBDFRHT.js";
17
17
 
18
18
  // src/direction/types.ts
19
19
  var DIRECTION_VERSION = 2;
@@ -4,7 +4,7 @@ import {
4
4
  import {
5
5
  auditSnapshot,
6
6
  fingerprint
7
- } from "./chunk-DE2ZAV4G.js";
7
+ } from "./chunk-3LCBLDAO.js";
8
8
  import {
9
9
  SNAPSHOT_VERSION
10
10
  } from "./chunk-QYBAVU3P.js";
@@ -10,7 +10,7 @@ import {
10
10
  holdHouseBlocks,
11
11
  houseRule,
12
12
  scanSource
13
- } from "./chunk-DE2ZAV4G.js";
13
+ } from "./chunk-3LCBLDAO.js";
14
14
  import {
15
15
  compareCompetitor,
16
16
  compareFacts,
@@ -21,7 +21,7 @@ import {
21
21
  pageCopy,
22
22
  protectedFacts,
23
23
  visibleText
24
- } from "./chunk-ONA73THJ.js";
24
+ } from "./chunk-KIBDFRHT.js";
25
25
 
26
26
  // src/character/config.ts
27
27
  var DEFAULT_IGNORE = [".claude", ".agents", ".cursor"];
@@ -622,7 +622,7 @@ async function pageSnapshot(target, cwd) {
622
622
  return readSnapshot(JSON.parse(readFileSync(local, "utf8")), target);
623
623
  }
624
624
  if (!/^https?:\/\//.test(target)) throw new Error(`${target} is neither a URL nor a snapshot file`);
625
- const { snapshotUrl } = await import("./audit-LQ2TDISV.js");
625
+ const { snapshotUrl } = await import("./audit-CRTC7JSF.js");
626
626
  return snapshotUrl(target);
627
627
  }
628
628
  async function briefFor(flags, cwd) {
@@ -633,7 +633,7 @@ async function briefFor(flags, cwd) {
633
633
  if (typeof brief === "string" && brief.trim()) return brief;
634
634
  } else if (flags.direction) throw new Error(`no such file: ${flags.direction}`);
635
635
  if (flags.null) {
636
- const { loadNull } = await import("./cli-SZ4SZLUN.js");
636
+ const { loadNull } = await import("./cli-HWGSNSDD.js");
637
637
  return loadNull(flags.null, cwd).brief;
638
638
  }
639
639
  return void 0;
@@ -659,37 +659,37 @@ async function compareWithCompetitor(flags, io) {
659
659
  function run(argv, io) {
660
660
  const [command, ...rest] = argv;
661
661
  if (command === "direction") {
662
- return import("./cli-R2HBESHI.js").then((m) => m.runDirection(rest, io));
662
+ return import("./cli-E2CFVIGZ.js").then((m) => m.runDirection(rest, io));
663
663
  }
664
664
  if (command === "report" || command === "retrofit") {
665
- return import("./cli-T7A3BU5J.js").then((m) => m.runReport(command, rest, io));
665
+ return import("./cli-TPV2EIIN.js").then((m) => m.runReport(command, rest, io));
666
666
  }
667
667
  if (command === "register") {
668
- return import("./cli-7QL26YPR.js").then((m) => m.runRegister(rest, io));
668
+ return import("./cli-YRRBBU27.js").then((m) => m.runRegister(rest, io));
669
669
  }
670
670
  if (command === "estate") {
671
- return import("./cli-WZA5IXSR.js").then((m) => m.runEstate(rest, io));
671
+ return import("./cli-X3RZE4GM.js").then((m) => m.runEstate(rest, io));
672
672
  }
673
673
  if (command === "null") {
674
- return import("./cli-SZ4SZLUN.js").then((m) => m.runNull(rest, io));
674
+ return import("./cli-HWGSNSDD.js").then((m) => m.runNull(rest, io));
675
675
  }
676
676
  if (command === "calibrate") {
677
- return import("./cli-AM4FLXGM.js").then((m) => m.runCalibrate(rest, io));
677
+ return import("./cli-ROVZDHVR.js").then((m) => m.runCalibrate(rest, io));
678
678
  }
679
679
  if (command === "tells" && rest[0] === "harvest") {
680
- return import("./cli-SZ4SZLUN.js").then((m) => m.runHarvest(rest, io)).catch((error) => {
680
+ return import("./cli-HWGSNSDD.js").then((m) => m.runHarvest(rest, io)).catch((error) => {
681
681
  io.err(`craft: ${error.message}`);
682
682
  return 2;
683
683
  });
684
684
  }
685
685
  if (command === "phone-first") {
686
- return import("./cli-YNIJOEJK.js").then((m) => m.runPhoneFirst(rest, io));
686
+ return import("./cli-RHU3MAZY.js").then((m) => m.runPhoneFirst(rest, io));
687
687
  }
688
688
  if (command === "viewports") {
689
- return import("./viewports-cli-F7KJIVZL.js").then((m) => m.runViewports(rest, io));
689
+ return import("./viewports-cli-EAUVLHFJ.js").then((m) => m.runViewports(rest, io));
690
690
  }
691
691
  if (command === "snapshot" || command === "audit") {
692
- return import("./cli-7DL4BKA7.js").then((m) => m.runAudit(command, rest, io));
692
+ return import("./cli-IYRJZWMN.js").then((m) => m.runAudit(command, rest, io));
693
693
  }
694
694
  if (!command || command === "help" || command === "--help" || command === "-h") {
695
695
  io.out(HELP);