{
  "version": 1,
  "files": [
    {
      "path": ".vercelignore",
      "url": "source/files/.vercelignore.txt",
      "bytes": 58,
      "sha256": "e31a8feba84a26131a2f76b2a34be2efc7a10eccc379b8138393d2eab2934912",
      "content": "captures/\nreports/\nnode_modules/\ndist/\n.vercel/\n.DS_Store\n"
    },
    {
      "path": "ASSETS.md",
      "url": "source/files/ASSETS.md.txt",
      "bytes": 1857,
      "sha256": "7ab5ab00c8be67df9d6993b1f18c6f133dc9873b3c7580c8116503d46494a407",
      "content": "# Cosmos background sources\n\nSelected from the user-supplied [Blue Glass collection](https://www.cosmos.so/sarveshsea/blue-glass), September 8, 2026. These are actual collection images, not generated replacements. Images are served locally. Cropping, blur, blending, and overlays happen in CSS. The new hero references were supplied directly by the user and encoded as WebP at quality 86 without resizing.\n\n| Local file | Cosmos element | Cosmos upload credit | Dimensions | Placement |\n| --- | --- | --- | --- | --- |\n| `cosmos-folded-glass.webp` | [Folded glass](https://www.cosmos.so/e/2081991458) | 三日一物 SUNRIU | 1080 × 1080 | Agent backdrop |\n| `cosmos-ribbed-glass.webp` | [Ribbed glass](https://www.cosmos.so/e/1100722503) | Ponti Design Studio | 1080 × 1346 | Prepared section and quiet closing crop |\n\nCredits reflect the collection's upload labels. Full-resolution WebP assets are served locally, with no Cosmos request required at runtime. Product interfaces remain opaque white. The prepared section uses DualEntry brand-100 for the copy field and brand-800 beneath the glass field.\n\nThe former generated PNG plates are preserved in the previous source archive in the task workspace, and are no longer included in this build.\n\n## V5 splash references\n\n| Local file | Source | Dimensions | Placement |\n| --- | --- | --- | --- |\n| `cosmos-blue-loop.webp` | User-supplied blue-glass loop from the linked collection; exact element and creator not established | 1256 × 2760 | Right hero field |\n| `cosmos-blue-wave.webp` | User-supplied blue-glass wave from the linked collection; exact element and creator not established | 1200 × 2133 | Left hero field |\n\n`splash.css` applies 2px blur to the photographs and a deep navy-to-white overlay. The translucent screen rim uses 8px backdrop blur; the product surface remains opaque and sharp.\n"
    },
    {
      "path": "CAPTURES.md",
      "url": "source/files/CAPTURES.md.txt",
      "bytes": 2111,
      "sha256": "6e0bc3d9f91e63577791b38e769621d63529969c28ead5a29c46079fa4899921",
      "content": "# Current captures\n\n41 PNGs cover eleven sections at desktop 1440px, tablet 768px, phone 390px, plus seven animation phases and a 320px splash. Two WebM recordings show the mobile loop and agent preparation.\n\n|Section|Desktop|Tablet|Phone|\n|---|---|---|---|\n|Hero|[Desktop](captures/current/desktop-hero.png)|[Tablet](captures/current/tablet-hero.png)|[Phone](captures/current/mobile-hero.png)|\n|Workflow|[Desktop](captures/current/desktop-workflow.png)|[Tablet](captures/current/tablet-workflow.png)|[Phone](captures/current/mobile-workflow.png)|\n|Video|[Desktop](captures/current/desktop-video.png)|[Tablet](captures/current/tablet-video.png)|[Phone](captures/current/mobile-video.png)|\n|Selector|[Desktop](captures/current/desktop-selector.png)|[Tablet](captures/current/tablet-selector.png)|[Phone](captures/current/mobile-selector.png)|\n|Agent|[Desktop](captures/current/desktop-agent.png)|[Tablet](captures/current/tablet-agent.png)|[Phone](captures/current/mobile-agent.png)|\n|Prepared|[Desktop](captures/current/desktop-prepared.png)|[Tablet](captures/current/tablet-prepared.png)|[Phone](captures/current/mobile-prepared.png)|\n|Context|[Desktop](captures/current/desktop-context.png)|[Tablet](captures/current/tablet-context.png)|[Phone](captures/current/mobile-context.png)|\n|Progression|[Desktop](captures/current/desktop-progression.png)|[Tablet](captures/current/tablet-progression.png)|[Phone](captures/current/mobile-progression.png)|\n|Stats|[Desktop](captures/current/desktop-stats.png)|[Tablet](captures/current/tablet-stats.png)|[Phone](captures/current/mobile-stats.png)|\n|Modules|[Desktop](captures/current/desktop-modules.png)|[Tablet](captures/current/tablet-modules.png)|[Phone](captures/current/mobile-modules.png)|\n|Closing|[Desktop](captures/current/desktop-closing.png)|[Tablet](captures/current/tablet-closing.png)|[Phone](captures/current/mobile-closing.png)|\n\nRegenerate with `npm run capture` and `npm run record`. Capture URLs use `/?capture=1&section=stats`. Agent phases: queued,assigned,filling,review. Hero phases: queued,moving,review. Unsupported phases resolve to review.\n"
    },
    {
      "path": "CONCEPT-MAP.md",
      "url": "source/files/CONCEPT-MAP.md.txt",
      "bytes": 950,
      "sha256": "8dc99e1240e93426e0a1db5bf8432497a5902faa484cf2962e04996838904c71",
      "content": "# Reference composition\n\nHero: centered copy and actions above a glass-framed animated board.\nWorkflow: three aligned cards, preserving Scattered / One board / Self-resolving wording.\nVideo: neutral 16:7 desktop placeholder, responsive on phones.\nSelector: category rail and task preview.\nAgent: fixed journal form fills once on entering view.\nPrepared: full-width pale/deep teal split with journal summary.\nContext: task card with source/work/action controls.\nProgression: three aligned status stages.\nStatistics: three attributed customer result cards, without product screenshots.\nModules: centered One board. Live state. heading and two orderly desktop rows of icons.\nClosing: dark teal field and translucent CTA panel, followed by a dark navigation footer.\n\nMobile cards and diagrams stack; product text stays readable. All artwork, fonts, and editable product interfaces are local. `/source/` exposes complete readable source and asset hashes.\n"
    },
    {
      "path": "DEPLOYMENT.md",
      "url": "source/files/DEPLOYMENT.md.txt",
      "bytes": 1104,
      "sha256": "cf48105dadf3acfc3b73a1e3f33375d63a0f9bfcb0645402787db29a379ff6c7",
      "content": "# Deploying the reference landing page\n\nProduction URL: https://dualentry-landing.vercel.app/\nProject: `sarveshseas-projects/dualentry-landing`.\nBuild: `npm run build`. Output: `dist/`.\n\nLocal editing, building, testing, and packaging need no Vercel credentials. To deploy, an authorized account can link the existing project, then run:\n\n```sh\nvercel deploy --prod --yes --scope sarveshseas-projects\n```\n\nOnly generated output is served. The public `/source/` export contains authored source, safe configuration, documentation, and asset references; it excludes account linkage, dependencies, captures, and reports.\n\nVerification commands:\n\n```sh\nnpm test\nnpm run test:e2e\nBASE_URL=https://dualentry-landing.vercel.app/ npm run test:e2e\n```\n\nThe browser suite checks 14 widths between 320 and 1440 pixels, the reference section sequence, hero card alignment, replay, controls, visibility pauses, reduced motion, and public source retrieval. `npm run capture` and `npm run record` refresh the optional media package. `npm run package` also works in a source-only copy before captures have been generated.\n"
    },
    {
      "path": "MOTION.md",
      "url": "source/files/MOTION.md.txt",
      "bytes": 4690,
      "sha256": "2e2b065ad105ca626ccf619d2c02c4ca2d25dc8dc0dd543d70f63b7b833e1756",
      "content": "# Ramp Stack reference observations\n\nSource: https://ramp.com/stack, observed September 8, 2026. Browser frames captured with CDP timestamps; MP4s retain observed spacing and are encoded at 24fps. These are sampling-based recordings, not extracted source animation timelines.\n\nHero: three neutral board columns; center has greater contrast. A task lifts from its source queue, crosses the center, then settles into the destination. Ambient ivory/yellow sits behind the board, never as the main task-card fill. The sequence advances without clicking while the hero is visible. Heading computed weight 400, size 64px on observed desktop viewport.\n\nFeature: clicking a process heading changes the expanded explanatory text and corresponding right-hand product scene. The demo progresses through its own internal steps. Backdrop remains behind a white product window. Feature heading computed weight 400, size 48px.\n\nInterpretation applied to DualEntry: neutral product layers; lower-contrast sage/teal atmosphere instead of Ramp yellow; a short agent preparation sequence alongside the separate continuous splash loop; fixed form geometry and regular heading weights. Planned 5-second story and 160–220ms transitions are authored timings, not claimed measurements of Ramp source code.\n\n## Implemented agent sequence\n\n- 0ms: queued task and fixed skeletal journal-entry form.\n- 800ms: journal agent assigned; task lifts 3px with a 200ms transition.\n- 1700ms: entity and date appear as a group.\n- 2800ms: two account rows and balanced $1,200 debit/credit amounts appear.\n- 3800ms: memo appears.\n- 5000ms: Ready for review; the draft stops before any approval or posting.\n\nVisibility eligibility is half the stage, capped to half the viewport for tall phone layouts. Offscreen time and hidden-tab time do not advance the clock. Replay resets the state; finished demonstrations stay finished on re-entry. Capture and reduced-motion modes are static. No character-by-character typing or geometry shifts.\n\n## Current background treatment\n\nV4 replaces the generated plates with two actual images selected from the user's Cosmos collection. See [source credits](ASSETS.md). The files are unmodified WebP images. CSS supplies restrained 10–24px blur, oversized clipped edges, and luminosity blending over DualEntry teal. Only decorative pseudo-elements are filtered; product cards and text remain sharp. The new prepared section uses a single 180ms link-arrow hover response, disabled by capture and reduced-motion rules.\n\nReference recordings and the previous sampled agent recording remain in the task workspace. The current portable package includes fresh still captures, a mobile task-loop recording, and an agent-preparation recording. Agent timing and behavior are unchanged.\n\n## Current splash loop\n\nThe glass imagery stays still at 2px blur. Three real cards share an overlay and move between measured slots. Six adjacent exchanges make a seamless 36-second cycle. Each six-second interval holds for 3.8 seconds, moves over 1.4 seconds with smooth acceleration and deceleration, then settles. No reset, caption, Replay button, syncing label, or placeholder text is shown.\n\nDesktop movement uses a small 6px lift; phone movement uses vertical slots and a 6px sideways passing offset. Slots reserve the largest card height. Styles update only when a value changes. An icon-only pause/resume control is available. Offscreen and hidden-tab time do not advance the loop. Reduced motion and capture mode are static; changes to the preference take effect live.\n\n## Family reference\n\nReference: https://family.co/, inspected September 8, 2026. The “Effortless onboarding. Masterful management.” group uses phone previews, with the active Drag and Drop preview visibly lifted and enlarged from about 209 × 428 to 230 × 471 CSS pixels. Moving the pointer over that preview started its video; the neighboring videos were paused. The page exposes short 100ms icon-color transitions. A local observation recording is stored in work/family-v6. These observations informed the treatment; DualEntry's timing and paths are independently authored.\n\nSelector and progression controls retain short pointer feedback. Keyboard updates remain immediate. No image/background layer moves.\n\n## Refactor contract\n\n`src/scripts/main.js` initializes capture layout first, then each independent controller. Initializers return cleanup functions. Shared UI bindings cancel transient animations on reduced-motion changes and disposal. Agent Replay is an accessible icon in the form header; the external playback strip and explanatory form footer were removed. Phase announcements remain available to screen readers.\n"
    },
    {
      "path": "README.md",
      "url": "source/files/README.md.txt",
      "bytes": 6310,
      "sha256": "4a1a936643f43c319cdb121c97da6dd015b828a0f33da2aaace3c62d04dd5994",
      "content": "# DualEntry Tasks landing page\n\nEleven sections matching the selected reference built with plain HTML, CSS, SVG, and native JavaScript modules. No browser runtime dependencies, framework, backend, or account connections. Product examples use illustrative financial data. Customer statistics are attributed separately.\n\nLive: https://dualentry-landing.vercel.app/\n\n## Open on another computer\n\nInstall Node.js 22.22 or newer, extract the ZIP, and open a terminal in `dualentry-landing`:\n\n```sh\nnpm run preview\n```\n\nOpen the printed local URL (default http://127.0.0.1:4174). This builds and serves the site using Node alone; no dependency installation, Python, Vercel account, or original computer is needed. Stop with Ctrl+C. Set `PORT` to use another port. Native modules require this local server rather than double-clicking HTML.\n\nFor editing, use `npm run dev`. It rebuilds when files in `src/` change; refresh your browser to see changes. Keep assets at their existing paths or update references with your replacement.\n\n## Editing map\n\n| Folder | What to edit |\n| --- | --- |\n| `src/page.html` | Navigation, footer, metadata, shared SVG icons |\n| `src/sections/` | One HTML fragment per demonstration; copy and product UI |\n| `src/styles/tokens.css` | DualEntry colors, fonts, semantic aliases |\n| `src/styles/` | Readable shared and section styles; filenames match demonstrations |\n| `src/scripts/` | One entry point, independent controllers, immutable state helpers |\n| `src/scripts/section-order.mjs` | Page order and accepted capture section IDs |\n| `assets/` | Local fonts, logo, and glass background WebPs |\n| `scripts/` | Build, preview, tests, capture, recording, and packaging commands |\n| `tests/` | State, interaction, lifecycle, and isolated build regression tests |\n| `dist/` | Generated deployment output; do not edit |\n\nThe build uses an explicit ordered manifest in `scripts/manifest.mjs`. It joins source styles into one `app.css`, assembles section HTML into one page, and copies only named runtime modules and local assets. Builds never write into authored source. CSS asset paths are relative to the generated `dist/app.css`.\n\nTo reuse a section, take its HTML, corresponding stylesheet/controller, shared tokens/product styles, used SVG symbols, and referenced assets. Keep its `data-*` hooks if retaining interactions. Controllers return cleanup functions. `main.js` applies capture layout before initializing them; import controllers individually when embedding in another app.\n\n## Optional development tools\n\n```sh\nnpm ci\nnpx playwright install chromium\nnpm test\nnpm run test:e2e\nnpm run capture\nnpm run record\nnpm run package\n```\n\nOnly tests that use a browser, recording, and formatting require installed dev dependencies. Linux may additionally need `npx playwright install --with-deps chromium`. `npm test` uses Node's built-in runner and enforces 80% production JavaScript coverage for lines, branches, and functions. Test builds use separate temporary directories.\n\nBrowser verification starts and stops its own local server, tests 14 viewport widths, interactions, mobile targets, replay, and animation pauses. Set `BASE_URL` to verify a deployed site. Capture/record commands write to `captures/current`; reports go to ignored `reports/`. `npm run format` formats authored code.\n\n`npm run package` rebuilds and creates `../dualentry-landing.zip` with source, assets, production output, tests, docs, and current captures when present. It excludes dependencies, reports, old captures, and `.vercel` account linkage. Run capture/record first to refresh images after changing the design.\n\n## Capture URLs\n\n- Full page still: `/?capture=1`\n- Single section: `/?capture=1&section=video`\n- Agent phase: `/?capture=1&section=agent&phase=filling`\n- Splash phase: `/?capture=1&section=hero&phase=moving`\n\nSection IDs: hero, workflow, video, selector, agent, prepared, context, progression, stats, modules, closing.\n\nAgent phases: queued, assigned, filling, review. Splash phases: queued, moving, review. Missing or unsupported phases settle at review. Reduced motion shows the completed presentation; capture mode suppresses motion and hides playback buttons without changing layout.\n\n## Visual and motion contract\n\nPreserve Lausanne regular typography, white product surfaces, DualEntry teal actions, and the existing Cosmos backgrounds. Main headings and essential product information remain visible; repeated caption strips and decorative explanation have been removed.\n\nThe splash continuously exchanges three cards between anchored slots, returning seamlessly after 36 seconds. Phones use three vertical queues. The loop pauses offscreen, in hidden tabs, on reduced-motion preference, and with its accessible pause button. The agent prepares grouped form fields over five seconds, stops before approval, and offers an icon Replay control in its form header.\n\nSee [asset credits](ASSETS.md), [motion details](MOTION.md), [captures](CAPTURES.md), and [deployment notes](DEPLOYMENT.md).\n\n## Current page and public source\n\nThe reference sequence is hero → workflow → video placeholder → task selector → agent preparation → prepared entry → task context → progression → customer statistics → module index → closing CTA. The hero actions appear before its glass board. The video slot is an intentional placeholder, not a playable video.\n\nEvery build publishes `/source/`: readable code, individual raw text files, a SHA-256 manifest, and `/source/bundle.json` containing all authored text with paths. Assets are listed with URLs and hashes. Another agent can download the bundle, write each text file at its `path`, fetch each asset to its `path`, then run `npm run preview`. There are no private deployment credentials in this export. A source-only copy can package without generated captures; run capture/record first if those are wanted.\n\nThe statistics section uses attributed published customer results: [Slash](https://www.dualentry.com/customers/slash) reports 90% of manual tasks automated; [Graphite](https://www.dualentry.com/customers/graphite) reports close reduced from 20 days to one and $0 implementation costs. The displayed 95% is calculated as `(20 - 1) / 20 × 100`; it describes Graphite's close duration, not a universal time-saving promise.\n"
    },
    {
      "path": "package-lock.json",
      "url": "source/files/package-lock.json.txt",
      "bytes": 2336,
      "sha256": "6a4e0adad741e719105314514dab895fec3af87dd274cd3414d0cfcfcf6e4bc3",
      "content": "{\n  \"name\": \"dualentry-landing\",\n  \"version\": \"1.0.0\",\n  \"lockfileVersion\": 3,\n  \"requires\": true,\n  \"packages\": {\n    \"\": {\n      \"name\": \"dualentry-landing\",\n      \"version\": \"1.0.0\",\n      \"devDependencies\": {\n        \"playwright\": \"1.62.1\",\n        \"prettier\": \"3.6.2\"\n      },\n      \"engines\": {\n        \"node\": \">=22.22.0\"\n      }\n    },\n    \"node_modules/fsevents\": {\n      \"version\": \"2.3.2\",\n      \"resolved\": \"https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz\",\n      \"integrity\": \"sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==\",\n      \"dev\": true,\n      \"hasInstallScript\": true,\n      \"license\": \"MIT\",\n      \"optional\": true,\n      \"os\": [\n        \"darwin\"\n      ],\n      \"engines\": {\n        \"node\": \"^8.16.0 || ^10.6.0 || >=11.0.0\"\n      }\n    },\n    \"node_modules/playwright\": {\n      \"version\": \"1.62.1\",\n      \"resolved\": \"https://registry.npmjs.org/playwright/-/playwright-1.62.1.tgz\",\n      \"integrity\": \"sha512-0M+L3LAD8/nm554LOla9Ayx0j0tmFZ0FBcoQ7F1VuVHpM/XpiC8RcDzBQB8W5+hA8L22THxELzeF+2WcUzvcLg==\",\n      \"dev\": true,\n      \"license\": \"Apache-2.0\",\n      \"dependencies\": {\n        \"playwright-core\": \"1.62.1\"\n      },\n      \"bin\": {\n        \"playwright\": \"cli.js\"\n      },\n      \"engines\": {\n        \"node\": \">=20\"\n      },\n      \"optionalDependencies\": {\n        \"fsevents\": \"2.3.2\"\n      }\n    },\n    \"node_modules/playwright-core\": {\n      \"version\": \"1.62.1\",\n      \"resolved\": \"https://registry.npmjs.org/playwright-core/-/playwright-core-1.62.1.tgz\",\n      \"integrity\": \"sha512-wPYSwEBJY9GHraISXqyqtx0na0LpO3XEX7jNDhntbex7tzUS7kLnZsOlFruFJB4Hi/rhDMjXGqHewDZ68nYZVw==\",\n      \"dev\": true,\n      \"license\": \"Apache-2.0\",\n      \"bin\": {\n        \"playwright-core\": \"cli.js\"\n      },\n      \"engines\": {\n        \"node\": \">=20\"\n      }\n    },\n    \"node_modules/prettier\": {\n      \"version\": \"3.6.2\",\n      \"resolved\": \"https://registry.npmjs.org/prettier/-/prettier-3.6.2.tgz\",\n      \"integrity\": \"sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"bin\": {\n        \"prettier\": \"bin/prettier.cjs\"\n      },\n      \"engines\": {\n        \"node\": \">=14\"\n      },\n      \"funding\": {\n        \"url\": \"https://github.com/prettier/prettier?sponsor=1\"\n      }\n    }\n  }\n}\n"
    },
    {
      "path": "package.json",
      "url": "source/files/package.json.txt",
      "bytes": 648,
      "sha256": "2a9c9ea2da03fd718b928194c4dd36aaf9442c8e9d38f441b6d8122eccb425f7",
      "content": "{\n  \"name\": \"dualentry-landing\",\n  \"version\": \"1.0.0\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"engines\": {\n    \"node\": \">=22.22.0\"\n  },\n  \"scripts\": {\n    \"build\": \"node scripts/build.mjs\",\n    \"preview\": \"node scripts/preview.mjs\",\n    \"dev\": \"node scripts/preview.mjs --watch\",\n    \"test\": \"node scripts/test.mjs\",\n    \"test:e2e\": \"node scripts/verify.mjs\",\n    \"capture\": \"node scripts/verify.mjs --capture\",\n    \"record\": \"node scripts/record.mjs\",\n    \"package\": \"node scripts/package.mjs\",\n    \"format\": \"prettier --write src scripts tests package.json\"\n  },\n  \"devDependencies\": {\n    \"playwright\": \"1.62.1\",\n    \"prettier\": \"3.6.2\"\n  }\n}\n"
    },
    {
      "path": "scripts/build.mjs",
      "url": "source/files/scripts/build.mjs.txt",
      "bytes": 2242,
      "sha256": "e65d0b5f8f09b1e8c6695e027817cae085d88e1656ff0911b326c7c576e8c640",
      "content": "import { readFile, writeFile, mkdir, cp, rm } from \"node:fs/promises\";\nimport { fileURLToPath } from \"node:url\";\nimport { resolve } from \"node:path\";\nimport { styles, modules } from \"./manifest.mjs\";\nimport { sectionOrder } from \"../src/scripts/section-order.mjs\";\nimport { publishSource } from \"./publish-source.mjs\";\nexport const root = fileURLToPath(new URL(\"../\", import.meta.url));\nexport async function build(destination = resolve(root, \"dist\")) {\n  const source = resolve(root, \"src\");\n  const shell = await readFile(resolve(source, \"page.html\"), \"utf8\");\n  if (shell.split(\"<!-- SECTIONS -->\").length !== 2)\n    throw new Error(\n      \"Page template must have exactly one section insertion point.\",\n    );\n  const sections = await Promise.all(\n    sectionOrder.map((name) =>\n      readFile(resolve(source, \"sections\", `${name}.html`), \"utf8\"),\n    ),\n  );\n  const css = await Promise.all(\n    styles.map(\n      async (name) =>\n        `/* ${name} */\\n${await readFile(resolve(source, \"styles\", name), \"utf8\")}`,\n    ),\n  );\n  // Read all inputs before replacing generated output; authored source is never written.\n  await rm(destination, { recursive: true, force: true });\n  await mkdir(resolve(destination, \"scripts\"), { recursive: true });\n  await Promise.all(\n    modules.map((name) =>\n      cp(\n        resolve(source, \"scripts\", name),\n        resolve(destination, \"scripts\", name),\n      ),\n    ),\n  );\n  await cp(resolve(root, \"assets\"), resolve(destination, \"assets\"), {\n    recursive: true,\n  });\n  await writeFile(\n    resolve(destination, \"index.html\"),\n    shell\n      .replace(\"<!-- SECTIONS -->\", sections.join(\"\\n\"))\n      .replace(\n        \"</head>\",\n        '  <link rel=\"describedby\" type=\"application/json\" href=\"source/manifest.json\">\\n</head>',\n      ),\n  );\n  await writeFile(resolve(destination, \"app.css\"), css.join(\"\\n\"));\n  await publishSource(root, destination);\n  return destination;\n}\nif (\n  process.argv[1] &&\n  resolve(process.argv[1]) === fileURLToPath(import.meta.url)\n) {\n  build()\n    .then(() =>\n      console.log(\n        `Built ${sectionOrder.length} sections and readable source to dist/`,\n      ),\n    )\n    .catch((error) => {\n      console.error(error);\n      process.exitCode = 1;\n    });\n}\n"
    },
    {
      "path": "scripts/manifest.mjs",
      "url": "source/files/scripts/manifest.mjs.txt",
      "bytes": 647,
      "sha256": "a4d3faa5ca569541b555c15e18bb20d470d50e88a55fde2788503fa189385df6",
      "content": "/** Explicit ordered inputs: tooling can never be copied into the deployed site. */\nexport const styles = Object.freeze([\n  \"tokens.css\",\n  \"styles.css\",\n  \"product.css\",\n  \"scenes-flow.css\",\n  \"scenes-focus.css\",\n  \"agent.css\",\n  \"atmosphere.css\",\n  \"splash.css\",\n  \"splash-motion.css\",\n  \"microfeedback.css\",\n  \"workflow-cards.css\",\n  \"page-ending.css\",\n  \"reference-layout.css\",\n]);\nexport const modules = Object.freeze([\n  \"main.js\",\n  \"ui-runtime.js\",\n  \"interactions.js\",\n  \"state.mjs\",\n  \"section-order.mjs\",\n  \"agent.js\",\n  \"agent-state.mjs\",\n  \"splash-motion.js\",\n  \"splash-motion-state.mjs\",\n  \"scenes-flow.js\",\n  \"scenes-focus.js\",\n]);\n"
    },
    {
      "path": "scripts/package.mjs",
      "url": "source/files/scripts/package.mjs.txt",
      "bytes": 3323,
      "sha256": "a14966c08704fc07f451f71573a37ef1a62b134f6e50189892aa63664db5eacd",
      "content": "/** Portable ZIP using Node's built-in compression. No system zip command required. */\nimport { readFile, readdir, writeFile } from \"node:fs/promises\";\nimport { deflateRawSync } from \"node:zlib\";\nimport { resolve, relative } from \"node:path\";\nimport { build, root } from \"./build.mjs\";\nconst roots = [\n  \"src\",\n  \"scripts\",\n  \"assets\",\n  \"tests\",\n  \"dist\",\n  \"captures/current\",\n  \"package.json\",\n  \"package-lock.json\",\n  \"vercel.json\",\n  \".vercelignore\",\n  \".gitignore\",\n  \"README.md\",\n  \"ASSETS.md\",\n  \"CAPTURES.md\",\n  \"MOTION.md\",\n  \"CONCEPT-MAP.md\",\n  \"DEPLOYMENT.md\",\n];\nfunction crc32(bytes) {\n  let crc = 0xffffffff;\n  for (const byte of bytes) {\n    crc ^= byte;\n    for (let bit = 0; bit < 8; bit++)\n      crc = (crc >>> 1) ^ (crc & 1 ? 0xedb88320 : 0);\n  }\n  return (crc ^ 0xffffffff) >>> 0;\n}\nasync function filesAt(path) {\n  const entries = await readdir(path, { withFileTypes: true });\n  const groups = await Promise.all(\n    entries\n      .sort((a, b) => a.name.localeCompare(b.name))\n      .filter((x) => x.name !== \".DS_Store\")\n      .map((x) =>\n        x.isDirectory()\n          ? filesAt(resolve(path, x.name))\n          : [resolve(path, x.name)],\n      ),\n  );\n  return groups.flat();\n}\nawait build();\nconst files = [];\nfor (const name of roots) {\n  const path = resolve(root, name);\n  if (name.includes(\".\") && !name.includes(\"/\")) {\n    try {\n      await readFile(path);\n      files.push(path);\n    } catch (error) {\n      if (name !== \".gitignore\" || error.code !== \"ENOENT\") throw error;\n    }\n  } else {\n    try {\n      files.push(...(await filesAt(path)));\n    } catch (error) {\n      if (name !== \"captures/current\" || error.code !== \"ENOENT\") throw error;\n    }\n  }\n}\nlet offset = 0;\nconst records = [],\n  directory = [];\nfor (const path of files) {\n  const body = await readFile(path),\n    data = deflateRawSync(body),\n    name = Buffer.from(\n      \"dualentry-landing/\" + relative(root, path).split(\"\\\\\").join(\"/\"),\n    );\n  const crc = crc32(body),\n    header = Buffer.alloc(30);\n  header.writeUInt32LE(0x04034b50, 0);\n  header.writeUInt16LE(20, 4);\n  header.writeUInt16LE(0x800, 6);\n  header.writeUInt16LE(8, 8);\n  header.writeUInt16LE(33, 12);\n  header.writeUInt32LE(crc, 14);\n  header.writeUInt32LE(data.length, 18);\n  header.writeUInt32LE(body.length, 22);\n  header.writeUInt16LE(name.length, 26);\n  const central = Buffer.alloc(46);\n  central.writeUInt32LE(0x02014b50, 0);\n  central.writeUInt16LE(20, 4);\n  central.writeUInt16LE(20, 6);\n  central.writeUInt16LE(0x800, 8);\n  central.writeUInt16LE(8, 10);\n  central.writeUInt16LE(33, 14);\n  central.writeUInt32LE(crc, 16);\n  central.writeUInt32LE(data.length, 20);\n  central.writeUInt32LE(body.length, 24);\n  central.writeUInt16LE(name.length, 28);\n  central.writeUInt32LE(offset, 42);\n  records.push(header, name, data);\n  directory.push(central, name);\n  offset += header.length + name.length + data.length;\n}\nconst central = Buffer.concat(directory),\n  end = Buffer.alloc(22);\nend.writeUInt32LE(0x06054b50, 0);\nend.writeUInt16LE(files.length, 8);\nend.writeUInt16LE(files.length, 10);\nend.writeUInt32LE(central.length, 12);\nend.writeUInt32LE(offset, 16);\nconst output = resolve(root, \"../dualentry-landing.zip\");\nawait writeFile(output, Buffer.concat([...records, central, end]));\nconsole.log(`Packaged ${files.length} files: ${output}`);\n"
    },
    {
      "path": "scripts/preview.mjs",
      "url": "source/files/scripts/preview.mjs.txt",
      "bytes": 2808,
      "sha256": "f737126e75eebecccb92cb7df3de5f1454a0c6461ffece2096f48039b46b2fa5",
      "content": "import { createServer } from \"node:http\";\nimport { readFile, stat } from \"node:fs/promises\";\nimport { watch } from \"node:fs\";\nimport { resolve, extname, sep } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { build, root } from \"./build.mjs\";\nconst mime = {\n  \".json\": \"application/json; charset=utf-8\",\n  \".txt\": \"text/plain; charset=utf-8\",\n  \".html\": \"text/html; charset=utf-8\",\n  \".css\": \"text/css\",\n  \".js\": \"text/javascript\",\n  \".mjs\": \"text/javascript\",\n  \".svg\": \"image/svg+xml\",\n  \".webp\": \"image/webp\",\n  \".woff2\": \"font/woff2\",\n  \".png\": \"image/png\",\n};\nexport async function startPreview({ port = 4174, rebuild = true } = {}) {\n  if (rebuild) await build();\n  const directory = resolve(root, \"dist\");\n  const server = createServer(async (req, res) => {\n    try {\n      const path = decodeURIComponent(\n        new URL(req.url, \"http://localhost\").pathname,\n      );\n      let file = resolve(directory, \".\" + path);\n      if (file !== directory && !file.startsWith(directory + sep)) {\n        res.writeHead(403).end();\n        return;\n      }\n      if ((await stat(file)).isDirectory()) file = resolve(file, \"index.html\");\n      const body = await readFile(file);\n      res\n        .writeHead(200, {\n          \"Content-Type\": mime[extname(file)] || \"application/octet-stream\",\n          \"Cache-Control\": \"no-store\",\n        })\n        .end(body);\n    } catch (error) {\n      const status =\n        error.code === \"ENOENT\" ? 404 : error instanceof URIError ? 400 : 500;\n      if (status === 500) console.error(error);\n      res\n        .writeHead(status)\n        .end(status === 404 ? \"Not found\" : \"Unable to serve this file\");\n    }\n  });\n  await new Promise((done, reject) => {\n    server.once(\"error\", reject);\n    server.listen(port, \"127.0.0.1\", done);\n  });\n  return {\n    url: `http://127.0.0.1:${server.address().port}/`,\n    close: () =>\n      new Promise((done, reject) =>\n        server.close((error) => (error ? reject(error) : done())),\n      ),\n  };\n}\nif (\n  process.argv[1] &&\n  resolve(process.argv[1]) === fileURLToPath(import.meta.url)\n) {\n  const app = await startPreview({ port: Number(process.env.PORT || 4174) });\n  console.log(`Preview: ${app.url}`);\n  let watcher,\n    timer,\n    building = Promise.resolve();\n  if (process.argv.includes(\"--watch\"))\n    watcher = watch(resolve(root, \"src\"), { recursive: true }, () => {\n      clearTimeout(timer);\n      timer = setTimeout(() => {\n        building = building\n          .then(() => build())\n          .then(() => console.log(\"Rebuilt. Refresh the browser.\"))\n          .catch(console.error);\n      }, 100);\n    });\n  async function close() {\n    clearTimeout(timer);\n    watcher?.close();\n    await building;\n    await app.close();\n  }\n  process.once(\"SIGINT\", close);\n  process.once(\"SIGTERM\", close);\n}\n"
    },
    {
      "path": "scripts/publish-source.mjs",
      "url": "source/files/scripts/publish-source.mjs.txt",
      "bytes": 6238,
      "sha256": "aab91c8b56afdf1526b4907911dc019e4ca38ca120d177a13853557050cee1f8",
      "content": "import { createHash } from \"node:crypto\";\nimport { lstat, mkdir, readFile, readdir, writeFile } from \"node:fs/promises\";\nimport { dirname, extname, resolve } from \"node:path\";\n\n// Only these authored inputs are public. Build output, private deployment state,\n// hidden files, dependencies, and symlinks are never traversed.\nconst textRoots = [\"src\", \"scripts\", \"tests\"];\nconst textExtensions = new Set([\n  \".html\",\n  \".css\",\n  \".js\",\n  \".mjs\",\n  \".json\",\n  \".md\",\n]);\nconst assetExtensions = new Set([\n  \".svg\",\n  \".png\",\n  \".jpg\",\n  \".jpeg\",\n  \".webp\",\n  \".avif\",\n  \".woff\",\n  \".woff2\",\n  \".mp4\",\n  \".webm\",\n]);\nconst documents = [\n  \".vercelignore\",\n  \"package.json\",\n  \"package-lock.json\",\n  \"vercel.json\",\n  \"README.md\",\n  \"ASSETS.md\",\n  \"MOTION.md\",\n  \"CAPTURES.md\",\n  \"CONCEPT-MAP.md\",\n  \"DEPLOYMENT.md\",\n];\nconst excludedDirectories = new Set([\n  \"node_modules\",\n  \"dist\",\n  \"reports\",\n  \"captures\",\n]);\n\nfunction escapeHtml(value) {\n  return value.replace(\n    /[&<>\"']/g,\n    (character) =>\n      ({\n        \"&\": \"&amp;\",\n        \"<\": \"&lt;\",\n        \">\": \"&gt;\",\n        '\"': \"&quot;\",\n        \"'\": \"&#39;\",\n      })[character],\n  );\n}\n\nasync function listFiles(root, directory, extensions) {\n  let entries;\n  try {\n    if (!(await lstat(resolve(root, directory))).isDirectory()) return [];\n    entries = await readdir(resolve(root, directory), { withFileTypes: true });\n  } catch (error) {\n    if (error.code === \"ENOENT\") return [];\n    throw error;\n  }\n  const paths = await Promise.all(\n    entries.map(async (entry) => {\n      if (entry.name.startsWith(\".\") || entry.isSymbolicLink()) return [];\n      const path = `${directory}/${entry.name}`;\n      if (entry.isDirectory()) {\n        return excludedDirectories.has(entry.name)\n          ? []\n          : listFiles(root, path, extensions);\n      }\n      return entry.isFile() && extensions.has(extname(entry.name))\n        ? [path]\n        : [];\n    }),\n  );\n  return paths.flat();\n}\n\nasync function existingDocuments(root) {\n  const paths = await Promise.all(\n    documents.map(async (path) => {\n      try {\n        return (await lstat(resolve(root, path))).isFile() ? [path] : [];\n      } catch (error) {\n        if (error.code === \"ENOENT\") return [];\n        throw error;\n      }\n    }),\n  );\n  return paths.flat();\n}\n\nfunction metadata(path, url, content) {\n  return {\n    path,\n    url,\n    bytes: content.length,\n    sha256: createHash(\"sha256\").update(content).digest(\"hex\"),\n  };\n}\n\nfunction indexPage(files, assets) {\n  const source = files\n    .map(\n      ({ path, url, content }) => `\n    <details id=\"${escapeHtml(path)}\">\n      <summary>${escapeHtml(path)}</summary>\n      <p><a href=\"../${escapeHtml(url)}\">Read raw text</a></p>\n      <pre><code>${escapeHtml(content)}</code></pre>\n    </details>`,\n    )\n    .join(\"\\n\");\n  const assetLinks = assets\n    .map(\n      ({ path, url }) =>\n        `<li><a href=\"../${escapeHtml(url)}\">${escapeHtml(path)}</a></li>`,\n    )\n    .join(\"\\n\");\n  return `<!doctype html>\n<html lang=\"en\">\n<head>\n  <meta charset=\"utf-8\">\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n  <title>DualEntry landing page — readable source</title>\n  <link rel=\"describedby\" type=\"application/json\" href=\"manifest.json\">\n  <style>body{max-width:1000px;margin:48px auto;padding:0 24px;font:16px/1.6 system-ui;color:#1d1f20;background:#fff}h1{font-weight:400;line-height:1.2}a{color:#004f5c}details{border-top:1px solid #dfe9eb;padding:16px 0}summary{cursor:pointer;overflow-wrap:anywhere}pre{overflow:auto;background:#f4f6f6;padding:20px;font-size:13px;line-height:1.55}nav{display:flex;flex-wrap:wrap;gap:20px;margin:24px 0}li{overflow-wrap:anywhere}</style>\n</head>\n<body>\n  <h1>DualEntry landing page source</h1>\n  <p>Complete authored HTML, CSS, JavaScript, build tools, tests, and local asset references. Expand a file to read it, or fetch the complete text bundle to recreate the project.</p>\n  <nav aria-label=\"Source downloads\"><a href=\"../\">Landing page</a><a href=\"manifest.json\">File manifest and SHA-256 hashes</a><a href=\"bundle.json\">All source text as JSON</a></nav>\n  <main><h2>Source files</h2>${source}<h2>Assets</h2><ul>${assetLinks}</ul></main>\n</body>\n</html>\\n`;\n}\n\nexport async function publishSource(root, destination) {\n  const paths = (\n    await Promise.all([\n      ...textRoots.map((directory) =>\n        listFiles(root, directory, textExtensions),\n      ),\n      existingDocuments(root),\n    ])\n  )\n    .flat()\n    .sort();\n  const files = await Promise.all(\n    paths.map(async (path) => {\n      const raw = await readFile(resolve(root, path));\n      const content = raw.toString(\"utf8\");\n      // Fail visibly rather than expose machine-specific source or silently redact code.\n      const localPath = new RegExp(\n        \"/(?:Users|Volumes|home)/[^\\\\s]+|[A-Za-z]:\\\\\\\\Users\\\\\\\\\",\n      );\n      if (localPath.test(content))\n        throw new Error(`Machine-specific path in public source: ${path}`);\n      const url = `source/files/${path.split(\"/\").map(encodeURIComponent).join(\"/\")}.txt`;\n      return { ...metadata(path, url, raw), content };\n    }),\n  );\n  const assetPaths = (await listFiles(root, \"assets\", assetExtensions)).sort();\n  const assets = await Promise.all(\n    assetPaths.map(async (path) =>\n      metadata(\n        path,\n        path.split(\"/\").map(encodeURIComponent).join(\"/\"),\n        await readFile(resolve(root, path)),\n      ),\n    ),\n  );\n  const manifest = {\n    version: 1,\n    files: files.map(({ content, ...entry }) => entry),\n    assets,\n  };\n  const directory = resolve(destination, \"source\");\n  await mkdir(directory, { recursive: true });\n  await Promise.all(\n    files.map(async ({ url, content }) => {\n      const output = resolve(destination, decodeURIComponent(url));\n      await mkdir(dirname(output), { recursive: true });\n      await writeFile(output, content);\n    }),\n  );\n  await Promise.all([\n    writeFile(\n      resolve(directory, \"manifest.json\"),\n      JSON.stringify(manifest, null, 2) + \"\\n\",\n    ),\n    writeFile(\n      resolve(directory, \"bundle.json\"),\n      JSON.stringify({ version: 1, files, assets }, null, 2) + \"\\n\",\n    ),\n    writeFile(resolve(directory, \"index.html\"), indexPage(files, assets)),\n  ]);\n  return manifest;\n}\n"
    },
    {
      "path": "scripts/record.mjs",
      "url": "source/files/scripts/record.mjs.txt",
      "bytes": 1619,
      "sha256": "b3a2b0685886b824e2109e32e818e815b0bc3141b060d33d0f93e12d91eb363f",
      "content": "import { chromium } from \"playwright\";\nimport { startPreview } from \"./preview.mjs\";\nimport { root } from \"./build.mjs\";\nimport { mkdir } from \"node:fs/promises\";\nprocess.chdir(root);\nawait mkdir(\"captures/current\", { recursive: true });\nconst preview = await startPreview({ port: 0 });\n(async () => {\n  let browser;\n  try {\n    browser = await chromium.launch();\n    const context = await browser.newContext({\n      viewport: { width: 390, height: 1000 },\n      recordVideo: { dir: \"reports/video\", size: { width: 390, height: 1000 } },\n    });\n    const page = await context.newPage();\n    await page.goto(preview.url);\n    await page.evaluate(() => document.fonts.ready);\n    await page.waitForTimeout(19000);\n    const video = page.video();\n    await context.close();\n    await video.saveAs(\"captures/current/mobile-task-loop.webm\");\n    const agentContext = await browser.newContext({\n      viewport: { width: 1440, height: 1000 },\n      recordVideo: {\n        dir: \"reports/video\",\n        size: { width: 1440, height: 1000 },\n      },\n    });\n    const agentPage = await agentContext.newPage();\n    await agentPage.goto(preview.url + \"#agent\");\n    await agentPage.locator(\"[data-agent-demo]\").scrollIntoViewIfNeeded();\n    await agentPage.waitForTimeout(7000);\n    const agentVideo = agentPage.video();\n    await agentContext.close();\n    await agentVideo.saveAs(\"captures/current/agent-preparation.webm\");\n    console.log(\"Mobile loop and agent preparation recorded\");\n  } finally {\n    await browser?.close();\n    await preview.close();\n  }\n})().catch((e) => {\n  console.error(e);\n  process.exitCode = 1;\n});\n"
    },
    {
      "path": "scripts/test.mjs",
      "url": "source/files/scripts/test.mjs.txt",
      "bytes": 692,
      "sha256": "f1c81431158831a51d560b339e03e9a222becbf5fcdba5b57c8a43fb1f153613",
      "content": "import { readdir } from \"node:fs/promises\";\nimport { spawnSync } from \"node:child_process\";\nimport { root } from \"./build.mjs\";\nimport { resolve } from \"node:path\";\nconst tests = (await readdir(resolve(root, \"tests\")))\n  .filter((name) => name.endsWith(\".test.mjs\"))\n  .sort();\nconst result = spawnSync(\n  process.execPath,\n  [\n    \"--test\",\n    \"--experimental-test-coverage\",\n    \"--test-coverage-include=src/scripts/**\",\n    \"--test-coverage-lines=80\",\n    \"--test-coverage-branches=80\",\n    \"--test-coverage-functions=80\",\n    ...tests.map((name) => `tests/${name}`),\n  ],\n  { cwd: root, stdio: \"inherit\" },\n);\nif (result.error) throw result.error;\nprocess.exitCode = result.status ?? 1;\n"
    },
    {
      "path": "scripts/verify.mjs",
      "url": "source/files/scripts/verify.mjs.txt",
      "bytes": 9420,
      "sha256": "072c4c9e94ff70dfac2c13f4bc742c74cd6e43bef960372ded993f48d2ef75d1",
      "content": "import { chromium } from \"playwright\";\nimport { startPreview } from \"./preview.mjs\";\nimport { root } from \"./build.mjs\";\nimport { resolve } from \"node:path\";\nimport assert from \"node:assert/strict\";\nimport * as fs from \"node:fs/promises\";\nprocess.chdir(root);\nconst preview = process.env.BASE_URL ? null : await startPreview({ port: 0 });\nconst base = process.env.BASE_URL || preview.url;\n(async () => {\n  let browser;\n  try {\n    browser = await chromium.launch();\n    const page = await browser.newPage({\n      viewport: { width: 390, height: 1000 },\n      deviceScaleFactor: 1,\n    });\n    const errors = [];\n    page.on(\"pageerror\", (e) => errors.push(e.message));\n    const sections = [\n      \"hero\",\n      \"workflow\",\n      \"video\",\n      \"selector\",\n      \"agent\",\n      \"prepared\",\n      \"context\",\n      \"progression\",\n      \"stats\",\n      \"modules\",\n      \"closing\",\n    ];\n    if (process.argv.includes(\"--capture\")) {\n      await fs.mkdir(\"captures/current\", { recursive: true });\n      for (const [label, width] of [\n        [\"desktop\", 1440],\n        [\"tablet\", 768],\n        [\"mobile\", 390],\n      ]) {\n        await page.setViewportSize({ width, height: 960 });\n        for (const section of sections) {\n          await page.goto(base + \"?capture=1&section=\" + section);\n          await page.evaluate(() => document.fonts.ready);\n          await page\n            .locator('[data-capture-section=\"' + section + '\"]')\n            .screenshot({\n              path: \"captures/current/\" + label + \"-\" + section + \".png\",\n            });\n        }\n      }\n      for (const [section, phases] of [\n        [\"hero\", [\"queued\", \"moving\", \"review\"]],\n        [\"agent\", [\"queued\", \"assigned\", \"filling\", \"review\"]],\n      ]) {\n        await page.setViewportSize({ width: 1440, height: 1300 });\n        for (const phase of phases) {\n          await page.goto(\n            base + \"?capture=1&section=\" + section + \"&phase=\" + phase,\n          );\n          await page.evaluate(() => document.fonts.ready);\n          await page\n            .locator('[data-capture-section=\"' + section + '\"]')\n            .screenshot({\n              path: \"captures/current/\" + section + \"-phase-\" + phase + \".png\",\n            });\n        }\n      }\n      await page.setViewportSize({ width: 320, height: 1100 });\n      await page.goto(base + \"?capture=1&section=hero\");\n      await page.evaluate(() => document.fonts.ready);\n      await page\n        .locator(\"[data-capture-section=hero]\")\n        .screenshot({ path: \"captures/current/small-hero.png\" });\n    }\n    const removed = [\n      \".flow-caption\",\n      \".progress-footnote\",\n      \".story-product-footer\",\n      \".prepared-entry-footer\",\n      \".context-caption\",\n      \".sel-stage-bottom\",\n      \".control-kicker\",\n      \".control-example-label\",\n      \".editorial-focus-bottom\",\n      \".agent-form-footer\",\n      \".agent-playback\",\n    ];\n    await page.goto(base + \"?capture=1\");\n    for (const selector of removed)\n      assert.equal(await page.locator(selector).count(), 0, selector);\n    assert.equal(await page.locator(\"#video-title\").count(), 1);\n    assert.equal(\n      await page.locator(\".agent-form-header [data-agent-replay]\").count(),\n      1,\n    );\n    // Real controls still work after surrounding narration has been removed.\n    await page.goto(base);\n    await page.locator(\"#agent\").scrollIntoViewIfNeeded();\n    await page.waitForFunction(\n      () =>\n        document.querySelector(\"[data-agent-demo]\").dataset.agentPhase ===\n        \"review\",\n    );\n    await page.locator(\"[data-agent-replay]\").click();\n    await page.waitForFunction(\n      () =>\n        document.querySelector(\"[data-agent-demo]\").dataset.agentPhase ===\n        \"queued\",\n    );\n    await page.waitForFunction(\n      () =>\n        document.querySelector(\"[data-agent-demo]\").dataset.agentPhase ===\n        \"review\",\n    );\n    await page.locator('[data-sel-choice=\"connections\"]').click();\n    assert.equal(\n      await page.locator(\"#selector-stage\").getAttribute(\"data-focus\"),\n      \"connections\",\n    );\n    await page.locator('[data-context-choice=\"work\"]').click();\n    assert.equal(\n      await page.locator(\"#context-demo\").getAttribute(\"data-context\"),\n      \"work\",\n    );\n    await page.locator('[data-progress-choice=\"move\"]').click();\n    assert.equal(\n      await page\n        .locator(\"[data-progress-stage]\")\n        .getAttribute(\"data-progress-stage\"),\n      \"move\",\n    );\n    const sourceManifest = await (\n      await page.request.get(base + \"source/manifest.json\")\n    ).json();\n    assert.ok(sourceManifest.files.length > 25);\n    const fullSource = await (\n      await page.request.get(base + \"source/bundle.json\")\n    ).json();\n    assert.ok(JSON.stringify(fullSource).includes(\"Your next move.\"));\n    assert.ok(\n      await page.evaluate(\n        () =>\n          document.querySelector(\".splash-actions\").getBoundingClientRect()\n            .top <\n          document.querySelector(\".splash-screen\").getBoundingClientRect().top,\n      ),\n    );\n    const widths = [\n      320, 360, 375, 390, 430, 540, 600, 680, 681, 768, 800, 801, 1024, 1440,\n    ];\n    for (const width of widths) {\n      await page.setViewportSize({ width, height: 1000 });\n      await page.goto(base + \"?capture=1\");\n      await page.evaluate(() => document.fonts.ready);\n      await page.waitForTimeout(50);\n      const result = await page.evaluate(() => ({\n        width: innerWidth,\n        scroll: document.documentElement.scrollWidth,\n        cards: [...document.querySelectorAll(\"[data-splash-card]\")].map((n) =>\n          n.getBoundingClientRect().toJSON(),\n        ),\n        slots: [...document.querySelectorAll(\"[data-splash-slot]\")].map((n) =>\n          n.getBoundingClientRect().toJSON(),\n        ),\n      }));\n      assert.ok(result.scroll <= width, \"overflow \" + width);\n      assert.equal(result.cards.length, 3);\n      for (const [i, slot] of [1, 0, 2].entries()) {\n        assert.ok(Math.abs(result.cards[i].x - result.slots[slot].x) < 1);\n        assert.ok(Math.abs(result.cards[i].y - result.slots[slot].y) < 1);\n      }\n      if (width <= 800) {\n        for (const selector of [\n          \".menu-toggle\",\n          \".header-cta\",\n\n          \".stat-source\",\n          \".site-footer nav a\",\n          \"[data-agent-replay]\",\n        ]) {\n          const height = await page\n            .locator(selector)\n            .first()\n            .evaluate((n) => n.getBoundingClientRect().height);\n          assert.ok(height >= 44, selector + \" height \" + height);\n        }\n      }\n    }\n    await page.setViewportSize({ width: 390, height: 1000 });\n    await page.goto(base);\n    await page.evaluate(() => document.fonts.ready);\n    assert.equal(await page.locator(\"[data-splash-replay]\").count(), 0);\n    assert.equal(await page.locator(\"[data-splash-announcement]\").count(), 0);\n    assert.ok(\n      !(await page.locator(\".splash\").textContent()).includes(\n        \"Keeping your books in sync\",\n      ),\n    );\n    const poses = () =>\n      page\n        .locator(\"[data-splash-card]\")\n        .evaluateAll((nodes) => nodes.map((n) => n.style.transform));\n    const initial = await poses();\n    await page.waitForFunction(\n      () =>\n        document.querySelector(\"[data-splash-demo]\").dataset.splashPhase ===\n        \"moving\",\n    );\n    await page.locator(\"[data-splash-toggle]\").click();\n    const frozen = await poses();\n    await page.waitForTimeout(450);\n    assert.deepEqual(await poses(), frozen);\n    assert.equal(\n      await page.locator(\"[data-splash-toggle]\").getAttribute(\"aria-label\"),\n      \"Resume task animation\",\n    );\n    await page.locator(\"[data-splash-toggle]\").click();\n    await page.waitForTimeout(1700);\n    assert.notDeepEqual(await poses(), initial);\n    await page.locator(\"#stats\").scrollIntoViewIfNeeded();\n    await page.waitForTimeout(100);\n    const offscreen = await poses();\n    await page.waitForTimeout(500);\n    assert.deepEqual(await poses(), offscreen);\n    await page.locator(\".splash-screen\").scrollIntoViewIfNeeded();\n    await page.emulateMedia({ reducedMotion: \"reduce\" });\n    await page.waitForTimeout(100);\n    const reduced = await poses();\n    await page.waitForTimeout(300);\n    assert.deepEqual(await poses(), reduced);\n    assert.ok(await page.locator(\"[data-splash-toggle]\").isDisabled());\n    await page.emulateMedia({ reducedMotion: \"no-preference\" });\n    await page.waitForTimeout(100);\n    assert.ok(await page.locator(\"[data-splash-toggle]\").isEnabled());\n    await page.waitForFunction(\n      (previous) =>\n        JSON.stringify(\n          [...document.querySelectorAll(\"[data-splash-card]\")].map(\n            (n) => n.style.transform,\n          ),\n        ) !== JSON.stringify(previous),\n      reduced,\n    );\n    assert.notDeepEqual(await poses(), reduced);\n    assert.deepEqual(errors, []);\n    const report = {\n      base,\n      widths,\n      cards: 3,\n      overflow: false,\n      removedLabels: true,\n      pauseResume: true,\n      offscreenPause: true,\n      reducedMotionBothDirections: true,\n      errors,\n    };\n    await fs.mkdir(\"reports\", { recursive: true });\n    await fs.writeFile(\n      \"reports/\" + (process.env.BASE_URL ? \"live\" : \"local\") + \"-browser.json\",\n      JSON.stringify(report, null, 2),\n    );\n    console.log(JSON.stringify(report));\n  } finally {\n    await browser?.close();\n    await preview?.close();\n  }\n})().catch((e) => {\n  console.error(e);\n  process.exitCode = 1;\n});\n"
    },
    {
      "path": "src/page.html",
      "url": "source/files/src/page.html.txt",
      "bytes": 6388,
      "sha256": "44ea06453cd0e8e80a67fe191e0032205a5a51d1aed5e0817e166647a9573602",
      "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n    <meta name=\"color-scheme\" content=\"light\" />\n    <meta\n      name=\"description\"\n      content=\"Bring approvals, suggested matches, and connection issues into one shared task board with DualEntry Tasks.\"\n    />\n    <link\n      rel=\"alternate\"\n      type=\"application/json\"\n      href=\"source/bundle.json\"\n      title=\"Complete page source\"\n    />\n    <title>Tasks — A clear view of what’s next | DualEntry</title>\n    <link\n      rel=\"preload\"\n      href=\"assets/lausanne-regular.woff2\"\n      as=\"font\"\n      type=\"font/woff2\"\n      crossorigin\n    />\n    <link rel=\"preload\" as=\"image\" href=\"assets/cosmos-blue-loop.webp\" />\n    <link rel=\"preload\" as=\"image\" href=\"assets/cosmos-blue-wave.webp\" />\n    <link rel=\"stylesheet\" href=\"app.css\" />\n    <script type=\"module\" src=\"scripts/main.js\"></script>\n  </head>\n  <body>\n    <a class=\"skip-link\" href=\"#main\">Skip to content</a>\n    <svg class=\"sprite\" xmlns=\"http://www.w3.org/2000/svg\" aria-hidden=\"true\">\n      <defs>\n        <symbol id=\"i-arrow\" viewBox=\"0 0 24 24\">\n          <path d=\"M4 12h15m-6-6 6 6-6 6\" />\n        </symbol>\n        <symbol id=\"i-search\" viewBox=\"0 0 24 24\">\n          <circle cx=\"10.5\" cy=\"10.5\" r=\"6.5\" />\n          <path d=\"m16 16 4 4\" />\n        </symbol>\n        <symbol id=\"i-filter\" viewBox=\"0 0 24 24\">\n          <path d=\"M3 4h18l-7 8v7l-4-2v-5L3 4Z\" />\n        </symbol>\n        <symbol id=\"i-calendar\" viewBox=\"0 0 24 24\">\n          <rect x=\"4\" y=\"5\" width=\"16\" height=\"16\" rx=\"2\" />\n          <path d=\"M8 3v4m8-4v4M4 10h16\" />\n        </symbol>\n        <symbol id=\"i-layout\" viewBox=\"0 0 24 24\">\n          <rect x=\"3\" y=\"4\" width=\"18\" height=\"16\" rx=\"2\" />\n          <path d=\"M3 9h18m-12 0v11m6-11v11\" />\n        </symbol>\n        <symbol id=\"i-list\" viewBox=\"0 0 24 24\">\n          <path d=\"M8 6h12M8 12h12M8 18h12M4 6h.01M4 12h.01M4 18h.01\" />\n        </symbol>\n        <symbol id=\"i-inbox\" viewBox=\"0 0 24 24\">\n          <rect x=\"4\" y=\"5\" width=\"16\" height=\"14\" rx=\"3\" />\n          <path d=\"m5 7 7 6 7-6\" />\n        </symbol>\n        <symbol id=\"i-spark\" viewBox=\"0 0 24 24\">\n          <path\n            d=\"m12 3 2.5 6.5L21 12l-6.5 2.5L12 21l-2.5-6.5L3 12l6.5-2.5L12 3Z\"\n          />\n        </symbol>\n        <symbol id=\"i-clock\" viewBox=\"0 0 24 24\">\n          <circle cx=\"12\" cy=\"12\" r=\"9\" />\n          <path d=\"M12 7v5l3 2\" />\n        </symbol>\n        <symbol id=\"i-more\" viewBox=\"0 0 24 24\">\n          <circle cx=\"12\" cy=\"5\" r=\"1\" />\n          <circle cx=\"12\" cy=\"12\" r=\"1\" />\n          <circle cx=\"12\" cy=\"19\" r=\"1\" />\n        </symbol>\n        <symbol id=\"i-database\" viewBox=\"0 0 24 24\">\n          <ellipse cx=\"12\" cy=\"5\" rx=\"8\" ry=\"3\" />\n          <path d=\"M4 5v14c0 4 16 4 16 0V5M4 12c0 4 16 4 16 0\" />\n        </symbol>\n        <symbol id=\"i-check\" viewBox=\"0 0 24 24\">\n          <path d=\"m5 12 4 4L19 6\" />\n        </symbol>\n        <symbol id=\"i-sync\" viewBox=\"0 0 24 24\">\n          <path\n            d=\"M20 9a8 8 0 0 0-14-3L3 9m0-6v6h6M4 15a8 8 0 0 0 14 3l3-3m0 6v-6h-6\"\n          />\n        </symbol>\n        <symbol id=\"i-play\" viewBox=\"0 0 24 24\">\n          <path d=\"m7 4 13 8-13 8V4Z\" />\n        </symbol>\n        <symbol id=\"i-chevron\" viewBox=\"0 0 24 24\">\n          <path d=\"m7 10 5 5 5-5\" />\n        </symbol>\n      </defs>\n    </svg>\n    <header class=\"site-header\">\n      <div class=\"container header-row\">\n        <a\n          class=\"logo\"\n          href=\"https://www.dualentry.com/\"\n          aria-label=\"DualEntry home\"\n          ><img src=\"assets/logo.svg\" width=\"140\" height=\"25\" alt=\"DualEntry\"\n        /></a>\n        <button\n          class=\"menu-toggle\"\n          data-menu-toggle\n          aria-expanded=\"false\"\n          aria-controls=\"site-nav\"\n          type=\"button\"\n        >\n          Menu\n          <svg class=\"icon\" aria-hidden=\"true\"><use href=\"#i-chevron\" /></svg>\n        </button>\n        <nav id=\"site-nav\" aria-label=\"Main navigation\">\n          <a href=\"#workflow\">How it works</a><a href=\"#selector\">Your tasks</a\n          ><a href=\"#progression\">Stay in control</a\n          ><a href=\"https://www.dualentry.com/customers\">Customers</a>\n        </nav>\n        <a\n          class=\"button button-small header-cta\"\n          href=\"https://www.dualentry.com/demo\"\n          >Schedule demo\n          <svg class=\"icon\" aria-hidden=\"true\"><use href=\"#i-arrow\" /></svg\n        ></a>\n      </div>\n    </header>\n    <main id=\"main\">\n      <!-- SECTIONS -->\n    </main>\n    <footer class=\"site-footer reference-footer\">\n      <div class=\"container footer-grid\">\n        <a\n          class=\"logo\"\n          href=\"https://www.dualentry.com/\"\n          aria-label=\"DualEntry home\"\n          ><img src=\"assets/logo.svg\" width=\"140\" height=\"25\" alt=\"DualEntry\"\n        /></a>\n        <nav aria-label=\"Product\">\n          <h2>Product</h2>\n          <a\n            href=\"https://www.dualentry.com/core-financials/general-ledger-software\"\n            >General Ledger</a\n          ><a\n            href=\"https://www.dualentry.com/core-financials/close-management-software\"\n            >Close Management</a\n          ><a href=\"#agent\">AI Accounting</a\n          ><a href=\"https://www.dualentry.com/pricing\">Pricing</a>\n        </nav>\n        <nav aria-label=\"Platform\">\n          <h2>Platform</h2>\n          <a href=\"#selector\">Tasks</a><a href=\"#progression\">Workflows</a\n          ><a href=\"#stats\">AI Agents</a><a href=\"#modules\">Integrations</a>\n        </nav>\n        <nav aria-label=\"Company\">\n          <h2>Company</h2>\n          <a href=\"https://www.dualentry.com/customers\">Customers</a\n          ><a href=\"https://www.dualentry.com/about-us\">About</a\n          ><a href=\"https://www.dualentry.com/careers\">Careers</a\n          ><a href=\"https://www.dualentry.com/contact\">Contact</a>\n        </nav>\n        <nav aria-label=\"Legal and source\">\n          <h2>Legal</h2>\n          <a href=\"https://www.dualentry.com/legal/privacy-policy\"\n            >Privacy Policy</a\n          ><a href=\"https://www.dualentry.com/legal/website-terms-of-use\"\n            >Website Terms</a\n          ><a href=\"https://trust.dualentry.com/\">Trust Center</a\n          ><a href=\"source/\">Page source</a>\n        </nav>\n        <small class=\"footer-copyright\">© 2026 Entry Inc.</small>\n      </div>\n    </footer>\n  </body>\n</html>\n"
    },
    {
      "path": "src/scripts/agent-state.mjs",
      "url": "source/files/src/scripts/agent-state.mjs.txt",
      "bytes": 1394,
      "sha256": "c69122753e51252a3f0694cedd154bac9b05b637110b99a23cb3118a7e19b8cb",
      "content": "const phaseTimes = Object.freeze({\n  queued: 0,\n  assigned: 800,\n  filling: 2800,\n  review: 5000,\n});\n\nexport function createAgentState(search = \"\", reduced = false) {\n  const params = new URLSearchParams(search);\n  const capture = params.get(\"capture\") === \"1\";\n  const requested = params.get(\"phase\");\n  const phase = Object.hasOwn(phaseTimes, requested) ? requested : \"review\";\n  return {\n    elapsed: reduced ? 5000 : capture ? phaseTimes[phase] : 0,\n    locked: capture || reduced,\n  };\n}\n\nexport function advanceAgent(state, milliseconds, active) {\n  if (\n    state.locked ||\n    !active ||\n    !Number.isFinite(milliseconds) ||\n    milliseconds < 0\n  )\n    return { ...state };\n  return { ...state, elapsed: Math.min(5000, state.elapsed + milliseconds) };\n}\n\nexport function replayAgent(state) {\n  return state.locked ? { ...state } : { ...state, elapsed: 0 };\n}\n\nexport function describeAgent({ elapsed }) {\n  const phase =\n    elapsed >= 5000\n      ? \"review\"\n      : elapsed >= 1700\n        ? \"filling\"\n        : elapsed >= 800\n          ? \"assigned\"\n          : \"queued\";\n  const groups =\n    elapsed >= 3800 ? 3 : elapsed >= 2800 ? 2 : elapsed >= 1700 ? 1 : 0;\n  return { phase, groups };\n}\n\nexport function eligibleAgentVisibility(\n  height,\n  intersectionHeight,\n  viewportHeight,\n) {\n  return (\n    height > 0 && intersectionHeight >= Math.min(height, viewportHeight) / 2\n  );\n}\n"
    },
    {
      "path": "src/scripts/agent.js",
      "url": "source/files/src/scripts/agent.js.txt",
      "bytes": 3772,
      "sha256": "5709a9332ee062e320339c870a7fab9fcadab0756dc352f6b26c53516d366a30",
      "content": "import {\n  createAgentState,\n  advanceAgent,\n  replayAgent,\n  describeAgent,\n  eligibleAgentVisibility,\n} from \"./agent-state.mjs\";\n\nconst labels = Object.freeze({\n  queued: [\"Waiting for an agent\", \"Ready to prepare\", \"Not started\", \"Queued\"],\n  assigned: [\n    \"Journal agent assigned\",\n    \"Preparing this task\",\n    \"Agent assigned\",\n    \"Agent assigned\",\n  ],\n  filling: [\n    \"Journal agent preparing\",\n    \"Adding entry details\",\n    \"Preparing\",\n    \"Preparing entry\",\n  ],\n  review: [\n    \"Prepared by Journal agent\",\n    \"Waiting for your review\",\n    \"Ready for review\",\n    \"Ready for review\",\n  ],\n});\n\nexport function initializeAgent(root, env = window) {\n  const media = env.matchMedia(\"(prefers-reduced-motion: reduce)\");\n  let state = createAgentState(env.location.search, media.matches);\n  let visible = false;\n  let frame = null;\n  let previousTime = null;\n  let lastRendered = \"\";\n  const replay = root.querySelector(\"[data-agent-replay]\");\n  const announcement = root.parentElement.querySelector(\n    \"[data-agent-announcement]\",\n  );\n  const fields = [...root.querySelectorAll(\"[data-agent-field]\")];\n  const slots = [\"assignment\", \"queue-note\", \"status\"].map((name) =>\n    root.querySelector(`[data-agent-${name}]`),\n  );\n\n  function render() {\n    const { phase, groups } = describeAgent(state);\n    const signature = `${phase}:${groups}:${state.locked}`;\n    if (signature === lastRendered) return;\n    lastRendered = signature;\n    root.dataset.agentPhase = phase;\n    root.dataset.agentGroups = String(groups);\n    slots.forEach((node, index) => {\n      node.textContent = labels[phase][index];\n    });\n    fields.forEach((node) => {\n      node.dataset.filled = String(Number(node.dataset.agentField) <= groups);\n    });\n    announcement.textContent = labels[phase][3];\n    replay.disabled = state.locked || phase !== \"review\";\n  }\n\n  function active() {\n    return (\n      visible && !env.document.hidden && !state.locked && state.elapsed < 5000\n    );\n  }\n  function tick(time) {\n    frame = null;\n    if (!active()) {\n      previousTime = null;\n      return;\n    }\n    state = advanceAgent(\n      state,\n      previousTime === null ? 0 : time - previousTime,\n      true,\n    );\n    previousTime = time;\n    render();\n    if (active()) frame = env.requestAnimationFrame(tick);\n  }\n  function syncPlayback() {\n    if (!active()) {\n      if (frame !== null) env.cancelAnimationFrame(frame);\n      frame = null;\n      previousTime = null;\n    } else if (frame === null) frame = env.requestAnimationFrame(tick);\n  }\n\n  const observer = new env.IntersectionObserver(\n    (entries) => {\n      const entry = entries[entries.length - 1];\n      visible =\n        entry.isIntersecting &&\n        eligibleAgentVisibility(\n          entry.boundingClientRect.height,\n          entry.intersectionRect.height,\n          env.innerHeight,\n        );\n      syncPlayback();\n    },\n    { threshold: Array.from({ length: 101 }, (_, index) => index / 100) },\n  );\n  observer.observe(root);\n  function handleReplay() {\n    state = replayAgent(state);\n    previousTime = null;\n    render();\n    syncPlayback();\n  }\n  function handleMotionChange(event) {\n    if (event.matches) {\n      state = createAgentState(env.location.search, true);\n      render();\n      syncPlayback();\n    }\n  }\n  replay.addEventListener(\"click\", handleReplay);\n  env.document.addEventListener(\"visibilitychange\", syncPlayback);\n  media.addEventListener(\"change\", handleMotionChange);\n  render();\n  return () => {\n    observer.disconnect();\n    if (frame !== null) env.cancelAnimationFrame(frame);\n    replay.removeEventListener(\"click\", handleReplay);\n    env.document.removeEventListener(\"visibilitychange\", syncPlayback);\n    media.removeEventListener(\"change\", handleMotionChange);\n  };\n}\n"
    },
    {
      "path": "src/scripts/interactions.js",
      "url": "source/files/src/scripts/interactions.js.txt",
      "bytes": 3499,
      "sha256": "daf7739cc7f37d2f9403be4c402c754ee4aeb83bb9acdc0b90a7cef3052268c9",
      "content": "import { createState, selectState } from \"./state.mjs\";\nimport { createUiBindings } from \"./ui-runtime.js\";\n\nfunction closeFilterMenu(document) {\n  const menu = document.getElementById(\"status-menu\");\n  if (!menu) return;\n  menu.open = false;\n  menu.querySelector(\"summary\").focus({ preventScroll: true });\n}\n\nfunction renderFilter(document, element, filter) {\n  element.querySelectorAll(\"[data-task-kind]\").forEach((row) => {\n    row.classList.toggle(\n      \"is-muted\",\n      filter !== \"all\" && row.dataset.taskKind !== filter,\n    );\n  });\n  const labels = {\n    all: \"All tasks\",\n    waiting: \"Waiting on you\",\n    connections: \"Connections\",\n  };\n  document.getElementById(\"filter-current-label\").textContent = labels[filter];\n  const count = element.querySelectorAll(\n    \"[data-task-kind]:not(.is-muted)\",\n  ).length;\n  document.getElementById(\"filter-result-count\").textContent =\n    `${count} tasks in focus`;\n}\n\nfunction bindSelections(document, ui) {\n  let state = createState();\n  const bind = (key, attribute, targetId) => {\n    const element = document.getElementById(targetId);\n    const buttons = [...document.querySelectorAll(`[${attribute}]`)];\n    const render = () => {\n      buttons.forEach((button) =>\n        button.setAttribute(\n          \"aria-pressed\",\n          String(button.getAttribute(attribute) === state[key]),\n        ),\n      );\n      if (!element) return;\n      element.dataset[key] = state[key];\n      if (key === \"filter\") renderFilter(document, element, state.filter);\n    };\n    render();\n    buttons.forEach((button) =>\n      ui.listen(button, \"click\", (event) => {\n        const next = selectState(state, key, button.getAttribute(attribute));\n        if (next[key] !== state[key]) {\n          state = next;\n          render();\n          ui.animate(\n            element,\n            event,\n            [\n              { opacity: 0.82, transform: \"translateY(2px)\" },\n              { opacity: 1, transform: \"translateY(0)\" },\n            ],\n            { duration: 160, easing: \"ease-out\" },\n          );\n        }\n        if (key === \"filter\") closeFilterMenu(document);\n      }),\n    );\n  };\n  bind(\"filter\", \"data-filter-choice\", \"filter-demo\");\n  bind(\"context\", \"data-context-choice\", \"context-demo\");\n}\n\nfunction bindNavigation(document, ui) {\n  const toggle = document.querySelector(\"[data-menu-toggle]\");\n  const navigation = document.getElementById(\"site-nav\");\n  if (!toggle || !navigation) return;\n  const setOpen = (open) => {\n    toggle.setAttribute(\"aria-expanded\", String(open));\n    toggle.setAttribute(\n      \"aria-label\",\n      open ? \"Close navigation\" : \"Open navigation\",\n    );\n    navigation.classList.toggle(\"is-open\", open);\n  };\n  setOpen(false);\n  ui.listen(toggle, \"click\", () =>\n    setOpen(toggle.getAttribute(\"aria-expanded\") !== \"true\"),\n  );\n  ui.listen(navigation, \"click\", (event) => {\n    if (event.target.closest(\"a\")) setOpen(false);\n  });\n  ui.listen(document, \"keydown\", (event) => {\n    if (\n      event.key !== \"Escape\" ||\n      toggle.getAttribute(\"aria-expanded\") !== \"true\"\n    )\n      return;\n    setOpen(false);\n    toggle.focus();\n  });\n}\n\nexport function initializeInteractions(document, env = window) {\n  const ui = createUiBindings(document, env);\n  bindNavigation(document, ui);\n  bindSelections(document, ui);\n  ui.listen(document, \"keydown\", (event) => {\n    if (event.key === \"Escape\" && document.getElementById(\"status-menu\")?.open)\n      closeFilterMenu(document);\n  });\n  return () => ui.dispose();\n}\n"
    },
    {
      "path": "src/scripts/main.js",
      "url": "source/files/src/scripts/main.js.txt",
      "bytes": 1470,
      "sha256": "ab4b8d4948f449783e9dc943330dc6b7704d6ff28c73f7f57d43cac273f036da",
      "content": "import { isCaptureMode, getCaptureSection } from \"./state.mjs\";\nimport { initializeInteractions } from \"./interactions.js\";\nimport { initializeFlowScenes } from \"./scenes-flow.js\";\nimport { initializeFocusScenes } from \"./scenes-focus.js\";\nimport { initializeAgent } from \"./agent.js\";\nimport { initializeSplash } from \"./splash-motion.js\";\n\n/** Capture layout is settled before any controller reads geometry or starts motion. */\nexport function applyCapture(document, search) {\n  if (isCaptureMode(search)) document.documentElement.dataset.capture = \"true\";\n  const captureSection = getCaptureSection(search);\n  if (!captureSection) return;\n  document.documentElement.dataset.isolated = \"true\";\n  document.querySelectorAll(\"[data-capture-section]\").forEach((section) => {\n    section.hidden = section.dataset.captureSection !== captureSection;\n  });\n}\n\nexport function initializePage(document, env = window) {\n  applyCapture(document, env.location.search);\n  const dispose = [\n    initializeInteractions(document, env),\n    initializeFlowScenes(document, env),\n    initializeFocusScenes(document, env),\n  ];\n  const agent = document.querySelector(\"[data-agent-demo]\");\n  const splash = document.querySelector(\"[data-splash-demo]\");\n  if (agent) dispose.push(initializeAgent(agent, env));\n  if (splash) dispose.push(initializeSplash(splash, env));\n  return () => dispose.forEach((cleanup) => cleanup());\n}\n\nif (typeof document !== \"undefined\") initializePage(document);\n"
    },
    {
      "path": "src/scripts/scenes-flow.js",
      "url": "source/files/src/scripts/scenes-flow.js.txt",
      "bytes": 4226,
      "sha256": "789354530f242b20cf0a94702feab06e8d51b1b2a1854de45f501346a56fd5a6",
      "content": "import { createUiBindings } from \"./ui-runtime.js\";\n\nfunction selectControl(root, selector, attribute, selected) {\n  root.querySelectorAll(selector).forEach((button) => {\n    button.setAttribute(\n      \"aria-pressed\",\n      String(button.dataset[attribute] === selected),\n    );\n  });\n}\n\nfunction revealColumn(root, name) {\n  const viewport = root.querySelector(\".pano-scroll\");\n  const column = root.querySelector(`.pano-col-${name}`);\n  if (!viewport || !column || viewport.scrollWidth <= viewport.clientWidth)\n    return;\n  const offset =\n    column.getBoundingClientRect().left - viewport.getBoundingClientRect().left;\n  viewport.scrollLeft += offset;\n}\n\nfunction initializeProgression(root, ui) {\n  root.querySelectorAll(\"[data-progress-choice]\").forEach((button) => {\n    ui.listen(button, \"click\", (event) => {\n      const selected = button.dataset.progressChoice;\n      if (![\"see\", \"review\", \"move\"].includes(selected)) return;\n      root.dataset.flowMotion = String(ui.allowsMotion(event));\n      root.dataset.progressStage = selected;\n      selectControl(root, \"[data-progress-choice]\", \"progressChoice\", selected);\n    });\n  });\n}\n\nfunction setPanoramaFocus(root, selected, event, ui) {\n  root.dataset.flowMotion = String(ui.allowsMotion(event));\n  root.dataset.panoFocus = selected;\n  selectControl(root, \"[data-pano-choice]\", \"panoChoice\", selected);\n  revealColumn(root, selected === \"waiting\" ? \"waiting\" : \"todo\");\n}\n\nfunction moveExample(root, event, ui) {\n  const card = root.querySelector(\"#pano-moving-task\");\n  const next = root.dataset.panoState === \"waiting\" ? \"done\" : \"waiting\";\n  const destination = root.querySelector(`[data-pano-destination=\"${next}\"]`);\n  if (!card || !destination) return;\n  const animate = ui.allowsMotion(event);\n  card.getAnimations().forEach((animation) => animation.cancel());\n  const before = card.getBoundingClientRect();\n  root.dataset.panoState = next;\n  root.dataset.flowMotion = String(animate);\n  root.dataset.panoFocus = \"all\";\n  selectControl(root, \"[data-pano-choice]\", \"panoChoice\", \"all\");\n  destination.prepend(card);\n  updatePanoramaText(root, next === \"done\");\n  revealColumn(root, next);\n  if (animate) {\n    const after = card.getBoundingClientRect();\n    const distance = Math.max(-320, Math.min(320, before.left - after.left));\n    ui.animate(\n      card,\n      event,\n      [\n        { transform: `translate(${distance}px, 4px)`, opacity: 0.65 },\n        { transform: \"translate(0, 0)\", opacity: 1 },\n      ],\n      { duration: 220, easing: \"cubic-bezier(.2,.7,.2,1)\" },\n    );\n  }\n}\n\nfunction updatePanoramaText(root, done) {\n  const values = [\n    ['[data-pano-count=\"waiting\"]', done ? \"1\" : \"2\"],\n    ['[data-pano-count=\"control\"]', done ? \"1\" : \"2\"],\n    ['[data-pano-count=\"done\"]', done ? \"2\" : \"1\"],\n    [\"[data-pano-button-label]\", done ? \"Reset\" : \"Move to Done\"],\n    [\n      \"[data-pano-task-title]\",\n      done ? \"Review complete.\" : \"Run ready for review.\",\n    ],\n    [\"[data-pano-task-badge]\", done ? \"Reviewed\" : \"Ready to review\"],\n    [\n      \"[data-pano-status]\",\n      done\n        ? \"Task moved to Done. One task still needs review.\"\n        : \"Task returned to review.\",\n    ],\n  ];\n  values.forEach(([selector, text]) => {\n    const element = root.querySelector(selector);\n    if (element) element.textContent = text;\n  });\n  const emptyState = root.querySelector(\"[data-pano-empty]\");\n  if (emptyState) emptyState.hidden = !done;\n}\n\nfunction initializePanorama(root, ui) {\n  root.querySelectorAll(\"[data-pano-choice]\").forEach((button) => {\n    ui.listen(button, \"click\", (event) => {\n      const selected = button.dataset.panoChoice;\n      if ([\"all\", \"waiting\"].includes(selected))\n        setPanoramaFocus(root, selected, event, ui);\n    });\n  });\n  ui.listen(root.querySelector(\"[data-pano-move]\"), \"click\", (event) =>\n    moveExample(root, event, ui),\n  );\n}\n\nexport function initializeFlowScenes(document, env = window) {\n  const ui = createUiBindings(document, env);\n  document\n    .querySelectorAll(\"[data-progress-stage]\")\n    .forEach((root) => initializeProgression(root, ui));\n  document\n    .querySelectorAll(\"[data-pano-state]\")\n    .forEach((root) => initializePanorama(root, ui));\n  return () => ui.dispose();\n}\n"
    },
    {
      "path": "src/scripts/scenes-focus.js",
      "url": "source/files/src/scripts/scenes-focus.js.txt",
      "bytes": 4498,
      "sha256": "a0a3c31506bde903cc98e1703558bcebee4c1d453a67dc122db8dfa0755ec0a1",
      "content": "import { createUiBindings } from \"./ui-runtime.js\";\n\n/* Deliberate, user-triggered illustration states. No timers or product connections. */\nconst focusCards = Object.freeze({\n  all: {\n    source: \"Your task queue\",\n    icon: \"i-layout\",\n    label: \"Everything, together\",\n    count: \"All tasks\",\n    title: \"A clear view of your next steps\",\n    time: \"Updated today\",\n    action: \"View tasks\",\n  },\n  approvals: {\n    source: \"Inbox\",\n    icon: \"i-inbox\",\n    label: \"Waiting on you\",\n    count: \"13 approvals\",\n    title: \"13 approvals ready for your review\",\n    time: \"2 hrs ago\",\n    action: \"View approvals\",\n  },\n  connections: {\n    source: \"USAA Bank\",\n    icon: \"i-sync\",\n    label: \"Connection needs attention\",\n    count: \"Connections\",\n    title: \"Reconnect to see recent transactions\",\n    time: \"Just now\",\n    action: \"View connection\",\n  },\n  agents: {\n    source: \"Bank Recommendations\",\n    icon: \"i-spark\",\n    label: \"Ready for review\",\n    count: \"Agent runs\",\n    title: \"Suggested matches, ready for a closer look\",\n    time: \"2 days ago\",\n    action: \"View run\",\n  },\n});\n\nconst examples = Object.freeze([\n  {\n    status: \"Pending review\",\n    source: \"Bank Recommendations\",\n    title: \"Run ready for review\",\n    action: \"Review\",\n    outcome: \"Waiting on you\",\n  },\n  {\n    status: \"Reviewed\",\n    source: \"Bank Recommendations\",\n    title: \"Recommendations reviewed\",\n    action: \"Next\",\n    outcome: \"Review complete\",\n  },\n  {\n    status: \"Pending review\",\n    source: \"Daily activity\",\n    title: \"Activity summary ready\",\n    action: \"Review\",\n    outcome: \"Waiting on you\",\n  },\n  {\n    status: \"Reviewed\",\n    source: \"Daily activity\",\n    title: \"Activity summary reviewed\",\n    action: \"Restart\",\n    outcome: \"Review complete\",\n  },\n]);\n\nexport function chooseFocus(key) {\n  return { ...focusCards[Object.hasOwn(focusCards, key) ? key : \"all\"] };\n}\n\nexport function advanceExample(step) {\n  const next =\n    Number.isInteger(step) && step >= 0 && step < examples.length\n      ? (step + 1) % examples.length\n      : 0;\n  return { ...examples[next], step: next };\n}\n\nfunction fillText(root, selector, value) {\n  const element = root.querySelector(selector);\n  if (element) element.textContent = value;\n}\n\nfunction bindFocus(document, ui) {\n  const section = document.getElementById(\"selector\");\n  if (!section) return;\n  const choices = [...section.querySelectorAll(\"[data-sel-choice]\")];\n  const stage = section.querySelector(\"#selector-stage\");\n  choices.forEach((button) =>\n    ui.listen(button, \"click\", (event) => {\n      if (button.getAttribute(\"aria-pressed\") === \"true\") return;\n      const key = button.dataset.selChoice;\n      const card = chooseFocus(key);\n      choices.forEach((choice) =>\n        choice.setAttribute(\"aria-pressed\", String(choice === button)),\n      );\n      stage.dataset.focus = key;\n      [\"source\", \"label\", \"count\", \"title\", \"time\"].forEach((field) =>\n        fillText(stage, `[data-sel-${field}]`, card[field]),\n      );\n      const action = stage.querySelector(\"[data-sel-action]\");\n      action.firstChild.textContent = `${card.action} `;\n      stage\n        .querySelector(\"[data-sel-icon]\")\n        .setAttribute(\"href\", `#${card.icon}`);\n      settleIntoPlace(ui, stage.querySelector(\".sel-main-card\"), event);\n    }),\n  );\n}\n\nfunction bindControl(document, ui) {\n  const section = document.getElementById(\"control\");\n  const button = section?.querySelector(\"[data-control-update]\");\n  if (!button) return;\n  let step = 0;\n  ui.listen(button, \"click\", (event) => {\n    const next = advanceExample(step);\n    step = next.step;\n    const frame = section.querySelector(\"#control-example\");\n    frame.dataset.reviewState =\n      next.status === \"Reviewed\" ? \"reviewed\" : \"pending\";\n    [\"source\", \"status\", \"title\", \"outcome\"].forEach((field) =>\n      fillText(section, `[data-control-${field}]`, next[field]),\n    );\n    button.firstChild.textContent = next.action;\n    settleIntoPlace(ui, section.querySelector(\".control-approval-card\"), event);\n  });\n}\n\nfunction settleIntoPlace(ui, element, event) {\n  ui.animate(\n    element,\n    event,\n    [\n      { opacity: 0.72, transform: \"translateY(4px)\" },\n      { opacity: 1, transform: \"translateY(0)\" },\n    ],\n    { duration: 200, easing: \"cubic-bezier(.2,.7,.2,1)\" },\n  );\n}\n\nexport function initializeFocusScenes(document, env = window) {\n  const ui = createUiBindings(document, env);\n  bindFocus(document, ui);\n  bindControl(document, ui);\n  return () => ui.dispose();\n}\n"
    },
    {
      "path": "src/scripts/section-order.mjs",
      "url": "source/files/src/scripts/section-order.mjs.txt",
      "bytes": 189,
      "sha256": "89922e4885e81d04a78f1cce6c9e73cf0841e3194e8c663f48ae5cb78f4b172f",
      "content": "export const sectionOrder = Object.freeze([\n  \"hero\",\n  \"workflow\",\n  \"video\",\n  \"selector\",\n  \"agent\",\n  \"prepared\",\n  \"context\",\n  \"progression\",\n  \"stats\",\n  \"modules\",\n  \"closing\",\n]);\n"
    },
    {
      "path": "src/scripts/splash-motion-state.mjs",
      "url": "source/files/src/scripts/splash-motion-state.mjs.txt",
      "bytes": 2900,
      "sha256": "2efb04e453ca09780f28711cca720ba209369dbd4b37cc2042aac70714f4c8f5",
      "content": "const LEG_DURATION = 6000;\nconst HOLD_DURATION = 3800;\nconst MOVE_DURATION = 1400;\nconst LOOP_DURATION = LEG_DURATION * 6;\nconst phaseTimes = Object.freeze({ queued: 0, moving: 4500, review: 5200 });\nconst clamp = (value) => Math.min(1, Math.max(0, value));\nconst ease = (value) => value * value * (3 - 2 * value);\nconst pairs = Object.freeze(\n  [\n    [0, 1],\n    [1, 2],\n    [0, 1],\n    [1, 2],\n    [0, 1],\n    [1, 2],\n  ].map(Object.freeze),\n);\nconst swap = (slots, pair) =>\n  slots.map((slot) =>\n    slot === pair[0] ? pair[1] : slot === pair[1] ? pair[0] : slot,\n  );\nconst arrangements = Object.freeze(\n  pairs.reduce(\n    (poses, pair) => [...poses, Object.freeze(swap(poses.at(-1), pair))],\n    [Object.freeze([0, 1, 2])],\n  ),\n);\n\nexport function createSplashState(search = \"\", reduced = false) {\n  const params = new URLSearchParams(search);\n  const capture = params.get(\"capture\") === \"1\";\n  const requested = params.get(\"phase\");\n  const phase = Object.hasOwn(phaseTimes, requested) ? requested : \"review\";\n  return {\n    elapsed: reduced ? phaseTimes.review : capture ? phaseTimes[phase] : 0,\n    capture,\n    locked: capture || reduced,\n  };\n}\n\nexport function advanceSplash(state, milliseconds, active) {\n  if (\n    state.locked ||\n    !active ||\n    !Number.isFinite(milliseconds) ||\n    milliseconds < 0\n  )\n    return { ...state };\n  return { ...state, elapsed: (state.elapsed + milliseconds) % LOOP_DURATION };\n}\n\nexport function setSplashReduced(state, reduced) {\n  return {\n    ...state,\n    elapsed: reduced ? phaseTimes.review : state.elapsed,\n    locked: state.capture || reduced,\n  };\n}\n\nexport function describeSplash({ elapsed }) {\n  const time = elapsed % LOOP_DURATION;\n  const leg = Math.floor(time / LEG_DURATION);\n  const local = time % LEG_DURATION;\n  const progress = ease(clamp((local - HOLD_DURATION) / MOVE_DURATION));\n  const from = arrangements[leg];\n  const to = arrangements[leg + 1];\n  const phase =\n    progress > 0 && progress < 1\n      ? \"moving\"\n      : time < HOLD_DURATION\n        ? \"queued\"\n        : \"review\";\n  return {\n    phase,\n    cards: from.map((slot, index) => ({\n      from: slot,\n      to: to[index],\n      progress: slot === to[index] ? 0 : progress,\n      slot: progress === 1 ? to[index] : slot,\n    })),\n  };\n}\n\nexport function splashPosition(progress, from, to, compact, direction) {\n  // The passing offset returns to exactly zero at either anchor, including the loop seam.\n  const passing =\n    progress === 0 || progress === 1 ? 0 : Math.sin(Math.PI * progress) * 6;\n  return {\n    x:\n      from.x + (to.x - from.x) * progress + (compact ? passing * direction : 0),\n    y:\n      from.y + (to.y - from.y) * progress - (compact ? 0 : passing * direction),\n  };\n}\n\nexport function splashVisible(height, intersectionHeight, viewportHeight) {\n  return (\n    height > 0 && intersectionHeight >= Math.min(height, viewportHeight) / 2\n  );\n}\n"
    },
    {
      "path": "src/scripts/splash-motion.js",
      "url": "source/files/src/scripts/splash-motion.js.txt",
      "bytes": 5408,
      "sha256": "2b372e142c4a5bdde9ba825a6a3750ca419012466dfcaec37ee022ca665ab0a1",
      "content": "import {\n  createSplashState,\n  advanceSplash,\n  setSplashReduced,\n  describeSplash,\n  splashPosition,\n  splashVisible,\n} from \"./splash-motion-state.mjs\";\n\nconst labels = Object.freeze([\"To do\", \"In progress\", \"For review\"]);\nconst setStyle = (element, property, value) => {\n  if (element.style[property] !== value) element.style[property] = value;\n};\n\nexport function initializeSplash(root, env = window) {\n  const media = env.matchMedia(\"(prefers-reduced-motion: reduce)\");\n  let state = createSplashState(env.location.search, media.matches);\n  let visible = false;\n  let userPaused = false;\n  let frame = null;\n  let previousTime = null;\n  let geometry = null;\n  let disposed = false;\n  const board = root.querySelector(\".kanban\");\n  const cards = Array.from(root.querySelectorAll(\"[data-splash-card]\"));\n  const slots = Array.from(root.querySelectorAll(\"[data-splash-slot]\"));\n  const statuses = cards.map((card) =>\n    card.querySelector(\"[data-splash-card-status]\"),\n  );\n  const toggle = root.querySelector(\"[data-splash-toggle]\");\n\n  function render() {\n    const view = describeSplash(state);\n    if (root.dataset.splashPhase !== view.phase)\n      root.dataset.splashPhase = view.phase;\n    view.cards.forEach((pose, index) => {\n      if (geometry) {\n        const position = splashPosition(\n          pose.progress,\n          geometry.anchors[pose.from],\n          geometry.anchors[pose.to],\n          geometry.compact,\n          Math.sign(pose.to - pose.from),\n        );\n        setStyle(\n          cards[index],\n          \"transform\",\n          `translate3d(${position.x}px, ${position.y}px, 0)`,\n        );\n        setStyle(\n          cards[index],\n          \"zIndex\",\n          pose.progress > 0 && pose.progress < 1\n            ? String(pose.to > pose.from ? 3 : 2)\n            : \"1\",\n        );\n      }\n      if (statuses[index] && statuses[index].textContent !== labels[pose.slot])\n        statuses[index].textContent = labels[pose.slot];\n    });\n  }\n\n  function renderControl() {\n    root.dataset.splashPaused = String(userPaused || state.locked);\n    toggle.disabled = state.locked;\n    toggle.setAttribute(\n      \"aria-label\",\n      userPaused ? \"Resume task animation\" : \"Pause task animation\",\n    );\n    toggle.setAttribute(\"aria-pressed\", String(userPaused));\n  }\n\n  function measure() {\n    if (disposed) return;\n    const width = Math.min(\n      ...slots.map((slot) => slot.getBoundingClientRect().width),\n    );\n    if (!width) return;\n    cards.forEach((card) => setStyle(card, \"width\", `${width}px`));\n    const height = `${Math.ceil(Math.max(...cards.map((card) => card.getBoundingClientRect().height)))}px`;\n    slots.forEach((slot) => setStyle(slot, \"height\", height));\n    const boardRect = board.getBoundingClientRect();\n    const anchors = slots.map((slot) => {\n      const rect = slot.getBoundingClientRect();\n      return { x: rect.left - boardRect.left, y: rect.top - boardRect.top };\n    });\n    geometry = { anchors, compact: Math.abs(anchors[0].x - anchors[1].x) < 1 };\n    root.dataset.splashCompact = String(geometry.compact);\n    render();\n  }\n\n  function active() {\n    return (\n      !disposed &&\n      visible &&\n      !env.document.hidden &&\n      !state.locked &&\n      !userPaused\n    );\n  }\n  function tick(time) {\n    frame = null;\n    if (!active()) {\n      previousTime = null;\n      return;\n    }\n    state = advanceSplash(\n      state,\n      previousTime === null ? 0 : time - previousTime,\n      true,\n    );\n    previousTime = time;\n    render();\n    frame = env.requestAnimationFrame(tick);\n  }\n  function syncPlayback() {\n    if (!active()) {\n      if (frame !== null) env.cancelAnimationFrame(frame);\n      frame = null;\n      previousTime = null;\n    } else if (frame === null) frame = env.requestAnimationFrame(tick);\n  }\n\n  const observer = new env.IntersectionObserver(\n    (entries) => {\n      const entry = entries[entries.length - 1];\n      visible =\n        entry.isIntersecting &&\n        splashVisible(\n          entry.boundingClientRect.height,\n          entry.intersectionRect.height,\n          env.innerHeight,\n        );\n      syncPlayback();\n    },\n    { threshold: Array.from({ length: 101 }, (_, index) => index / 100) },\n  );\n  const resize = new env.ResizeObserver(measure);\n  function handleToggle() {\n    if (state.locked) return;\n    userPaused = !userPaused;\n    renderControl();\n    syncPlayback();\n  }\n  function handleMotionChange(event) {\n    state = setSplashReduced(state, event.matches);\n    previousTime = null;\n    render();\n    renderControl();\n    syncPlayback();\n  }\n\n  // Three real cards share an overlay; the anchored slots reserve their full geometry.\n  board.append(...cards);\n  root.dataset.splashInitialized = \"true\";\n  measure();\n  render();\n  renderControl();\n  observer.observe(root.querySelector(\".splash-screen\"));\n  resize.observe(board);\n  env.document.fonts?.ready.then(measure);\n  toggle.addEventListener(\"click\", handleToggle);\n  env.document.addEventListener(\"visibilitychange\", syncPlayback);\n  media.addEventListener(\"change\", handleMotionChange);\n  return () => {\n    disposed = true;\n    observer.disconnect();\n    resize.disconnect();\n    if (frame !== null) env.cancelAnimationFrame(frame);\n    toggle.removeEventListener(\"click\", handleToggle);\n    env.document.removeEventListener(\"visibilitychange\", syncPlayback);\n    media.removeEventListener(\"change\", handleMotionChange);\n  };\n}\n"
    },
    {
      "path": "src/scripts/state.mjs",
      "url": "source/files/src/scripts/state.mjs.txt",
      "bytes": 788,
      "sha256": "49db3c8bb7b4181519afd93da0c697756a1b900283d7674e610dade219fd7cde",
      "content": "import { sectionOrder } from \"./section-order.mjs\";\n\nconst choices = Object.freeze({\n  filter: Object.freeze([\"all\", \"waiting\", \"connections\"]),\n  context: Object.freeze([\"source\", \"work\", \"action\"]),\n});\n\nexport function createState() {\n  return { filter: \"waiting\", context: \"source\" };\n}\n\nexport function selectState(state, key, value) {\n  const allowed = Object.hasOwn(choices, key) && choices[key].includes(value);\n  return allowed ? { ...state, [key]: value } : { ...state };\n}\n\nexport function isCaptureMode(search) {\n  return new URLSearchParams(search).get(\"capture\") === \"1\";\n}\n\nexport function getCaptureSection(search) {\n  const section = new URLSearchParams(search).get(\"section\");\n  return isCaptureMode(search) && sectionOrder.includes(section)\n    ? section\n    : null;\n}\n"
    },
    {
      "path": "src/scripts/ui-runtime.js",
      "url": "source/files/src/scripts/ui-runtime.js.txt",
      "bytes": 1390,
      "sha256": "f28cf04008e8ce19505b02b5afee26838b6057b608d6cf2d44955bb7f2f77ea6",
      "content": "/** Shared lifecycle for user-triggered UI feedback. */\nexport function createUiBindings(document, env) {\n  const media = env.matchMedia(\"(prefers-reduced-motion: reduce)\");\n  const bindings = [];\n  const animations = new Set();\n  const cancel = () => {\n    animations.forEach((animation) => animation.cancel());\n    animations.clear();\n  };\n  const listen = (target, type, callback) => {\n    if (!target) return;\n    target.addEventListener(type, callback);\n    bindings.push(() => target.removeEventListener(type, callback));\n  };\n  const allowsMotion = (event) =>\n    event.detail > 0 &&\n    document.documentElement.dataset.capture !== \"true\" &&\n    !media.matches;\n  listen(media, \"change\", () => {\n    if (media.matches) cancel();\n  });\n  return {\n    listen,\n    allowsMotion,\n    animate(element, event, frames, options) {\n      if (!element) return;\n      element.getAnimations().forEach((animation) => animation.cancel());\n      if (!allowsMotion(event)) return;\n      const animation = element.animate(frames, options);\n      animations.add(animation);\n      // Finished animations need no retained references. Cancellation also settles this promise.\n      animation.finished?.then(\n        () => animations.delete(animation),\n        () => animations.delete(animation),\n      );\n    },\n    dispose() {\n      bindings.forEach((remove) => remove());\n      cancel();\n    },\n  };\n}\n"
    },
    {
      "path": "src/sections/agent.html",
      "url": "source/files/src/sections/agent.html.txt",
      "bytes": 4909,
      "sha256": "d92cfd7032feacb9d9eef71ae33b30a06472f120d9f99fa396c82a99dba0469e",
      "content": "<section\n  class=\"section container agent-section\"\n  id=\"agent\"\n  aria-labelledby=\"agent-title\"\n  data-capture-section=\"agent\"\n>\n  <div class=\"agent-heading\">\n    <h2 id=\"agent-title\">From task to prepared entry.</h2>\n  </div>\n  <div\n    class=\"agent-stage\"\n    data-agent-demo\n    data-agent-phase=\"queued\"\n    data-agent-groups=\"0\"\n  >\n    <aside class=\"agent-queue\" aria-label=\"Example task queue\">\n      <div class=\"agent-queue-header\">\n        <span>Tasks</span><span class=\"agent-count\">1</span>\n      </div>\n      <div class=\"agent-task\">\n        <div class=\"agent-task-source\">\n          <span class=\"agent-entity\">A</span><span>Acme Inc</span>\n        </div>\n        <h3>Prepare software expense entry</h3>\n        <p>Software subscription · $1,200</p>\n        <div class=\"agent-assignment\">\n          <span class=\"agent-assignment-icon\" aria-hidden=\"true\"\n            ><svg viewBox=\"0 0 20 20\" fill=\"none\">\n              <path\n                d=\"m10 2 2.3 5.7L18 10l-5.7 2.3L10 18l-2.3-5.7L2 10l5.7-2.3L10 2Z\"\n                stroke=\"currentColor\"\n                stroke-width=\"1.3\"\n              /></svg></span\n          ><span data-agent-assignment>Waiting for an agent</span>\n        </div>\n      </div>\n      <div class=\"agent-queue-note\">\n        <span class=\"agent-note-dot\" aria-hidden=\"true\"></span\n        ><span data-agent-queue-note>Ready to prepare</span>\n      </div>\n    </aside>\n    <div class=\"agent-transfer\" aria-hidden=\"true\">\n      <span></span\n      ><svg viewBox=\"0 0 16 16\" fill=\"none\">\n        <path\n          d=\"M3 8h10m-4-4 4 4-4 4\"\n          stroke=\"currentColor\"\n          stroke-width=\"1.3\"\n          stroke-linecap=\"round\"\n          stroke-linejoin=\"round\"\n        />\n      </svg>\n    </div>\n    <div\n      class=\"agent-form\"\n      role=\"group\"\n      aria-label=\"Illustrative journal entry\"\n    >\n      <div class=\"agent-form-header\">\n        <span>Journal entry</span>\n        <div class=\"agent-form-actions\">\n          <span class=\"agent-form-status\" data-agent-status>Not started</span\n          ><button\n            class=\"agent-replay\"\n            type=\"button\"\n            data-agent-replay\n            aria-label=\"Replay journal entry preparation\"\n            title=\"Replay\"\n            disabled\n          >\n            <svg viewBox=\"0 0 16 16\" aria-hidden=\"true\" fill=\"none\">\n              <path\n                d=\"M3.2 5.5A5 5 0 1 1 3 10M3 2v4h4\"\n                stroke=\"currentColor\"\n                stroke-width=\"1.3\"\n                stroke-linecap=\"round\"\n                stroke-linejoin=\"round\"\n              />\n            </svg>\n          </button>\n        </div>\n      </div>\n      <div class=\"agent-form-body\">\n        <div class=\"agent-fields\">\n          <div class=\"agent-field\">\n            <span class=\"agent-field-label\">Entity</span>\n            <div class=\"agent-field-value\" data-agent-field=\"1\">\n              <span>Acme Inc</span>\n            </div>\n          </div>\n          <div class=\"agent-field\">\n            <span class=\"agent-field-label\">Date</span>\n            <div class=\"agent-field-value\" data-agent-field=\"1\">\n              <span>Sep 8, 2026</span>\n            </div>\n          </div>\n        </div>\n        <div\n          class=\"agent-entry-table\"\n          role=\"table\"\n          aria-label=\"Journal entry lines\"\n        >\n          <div class=\"agent-entry-row agent-entry-head\" role=\"row\">\n            <span role=\"columnheader\">Account</span\n            ><span role=\"columnheader\">Debit</span\n            ><span role=\"columnheader\">Credit</span>\n          </div>\n          <div class=\"agent-entry-row\" role=\"row\">\n            <div class=\"agent-field-value\" data-agent-field=\"2\" role=\"cell\">\n              <span>Software expense</span>\n            </div>\n            <div class=\"agent-field-value\" data-agent-field=\"2\" role=\"cell\">\n              <span>$1,200.00</span>\n            </div>\n            <div class=\"agent-field-value\" data-agent-field=\"2\" role=\"cell\">\n              <span>—</span>\n            </div>\n          </div>\n          <div class=\"agent-entry-row\" role=\"row\">\n            <div class=\"agent-field-value\" data-agent-field=\"2\" role=\"cell\">\n              <span>Accounts payable</span>\n            </div>\n            <div class=\"agent-field-value\" data-agent-field=\"2\" role=\"cell\">\n              <span>—</span>\n            </div>\n            <div class=\"agent-field-value\" data-agent-field=\"2\" role=\"cell\">\n              <span>$1,200.00</span>\n            </div>\n          </div>\n        </div>\n        <div class=\"agent-field agent-memo\">\n          <span class=\"agent-field-label\">Memo</span>\n          <div class=\"agent-field-value\" data-agent-field=\"3\">\n            <span>Software subscription</span>\n          </div>\n        </div>\n      </div>\n    </div>\n  </div>\n\n  <span\n    class=\"sr-only\"\n    data-agent-announcement\n    aria-live=\"polite\"\n    aria-atomic=\"true\"\n    >Queued</span\n  >\n</section>\n"
    },
    {
      "path": "src/sections/closing.html",
      "url": "source/files/src/sections/closing.html.txt",
      "bytes": 929,
      "sha256": "80166314f3b9007c613bc55d085a3a9f3181a1aaa9edc11efe2d3856b96d3587",
      "content": "<section\n  class=\"close-month-section\"\n  id=\"demo\"\n  aria-labelledby=\"closing-title\"\n  data-capture-section=\"closing\"\n>\n  <div class=\"container\">\n    <div class=\"close-month-panel\">\n      <p class=\"close-month-label\">Tasks · DualEntry</p>\n      <h2 id=\"closing-title\">Close all month. Approve in minutes.</h2>\n      <p class=\"close-month-description\">\n        One board from live ledger state. Nothing posts until a human does.\n      </p>\n      <div class=\"close-month-actions\">\n        <a\n          class=\"button close-month-button\"\n          href=\"https://www.dualentry.com/demo\"\n        >\n          Schedule demo\n          <svg class=\"icon\" aria-hidden=\"true\"><use href=\"#i-arrow\" /></svg>\n        </a>\n        <a class=\"text-link close-month-link\" href=\"#selector\">\n          See the board\n          <svg class=\"icon\" aria-hidden=\"true\"><use href=\"#i-arrow\" /></svg>\n        </a>\n      </div>\n    </div>\n  </div>\n</section>\n"
    },
    {
      "path": "src/sections/context.html",
      "url": "source/files/src/sections/context.html.txt",
      "bytes": 2409,
      "sha256": "a7f0f10b11ed8cdac5506121516eeaf24ea32d999a554344c0a7553b477a22db",
      "content": "<section\n  class=\"section container context-section\"\n  id=\"context\"\n  aria-labelledby=\"context-title\"\n  data-capture-section=\"context\"\n>\n  <div\n    class=\"context-panel feature-panel\"\n    id=\"context-demo\"\n    data-context=\"source\"\n    role=\"img\"\n    aria-label=\"Task card showing its source, work count, and next action\"\n  >\n    <div class=\"context-card\" aria-hidden=\"true\">\n      <div class=\"task-source\" data-part=\"source\">\n        <span class=\"avatar avatar-acme\">A</span><span>Acme Inc</span\n        ><span class=\"badge badge-lilac\">38</span\n        ><svg class=\"icon more\" aria-hidden=\"true\"><use href=\"#i-more\" /></svg>\n      </div>\n      <p class=\"task-title\" data-part=\"work\">\n        38 suggested matches across 12 accounts are ready to review.\n      </p>\n      <div class=\"task-footer\" data-part=\"action\">\n        <span class=\"timestamp\"\n          ><svg class=\"icon\" aria-hidden=\"true\"><use href=\"#i-clock\" /></svg>4\n          hrs ago</span\n        ><span class=\"mini-action\">Review</span>\n      </div>\n    </div>\n  </div>\n  <div class=\"context-copy\">\n    <h2 id=\"context-title\">\n      Everything you need<br />\n      to review.\n    </h2>\n    <div class=\"context-notes\" role=\"group\" aria-label=\"Explore task details\">\n      <button type=\"button\" data-context-choice=\"source\" aria-pressed=\"true\">\n        <span class=\"note-icon\"\n          ><svg class=\"icon\" aria-hidden=\"true\">\n            <use href=\"#i-database\" /></svg></span\n        ><span><strong>Where it came from.</strong></span\n        ><svg class=\"icon note-arrow\" aria-hidden=\"true\">\n          <use href=\"#i-arrow\" />\n        </svg></button\n      ><button type=\"button\" data-context-choice=\"work\" aria-pressed=\"false\">\n        <span class=\"note-icon\"\n          ><svg class=\"icon\" aria-hidden=\"true\">\n            <use href=\"#i-list\" /></svg></span\n        ><span><strong>What needs review.</strong></span\n        ><svg class=\"icon note-arrow\" aria-hidden=\"true\">\n          <use href=\"#i-arrow\" />\n        </svg></button\n      ><button type=\"button\" data-context-choice=\"action\" aria-pressed=\"false\">\n        <span class=\"note-icon\"\n          ><svg class=\"icon\" aria-hidden=\"true\">\n            <use href=\"#i-play\" /></svg></span\n        ><span><strong>What happens next.</strong></span\n        ><svg class=\"icon note-arrow\" aria-hidden=\"true\">\n          <use href=\"#i-arrow\" />\n        </svg>\n      </button>\n    </div>\n  </div>\n</section>\n"
    },
    {
      "path": "src/sections/hero.html",
      "url": "source/files/src/sections/hero.html.txt",
      "bytes": 12812,
      "sha256": "dda5f1d2272dab441ea23f60d76d925ea8fd22d0baf1e86e9504ecd7f564f424",
      "content": "<section\n  class=\"splash\"\n  id=\"overview\"\n  aria-labelledby=\"hero-title\"\n  data-capture-section=\"hero\"\n  data-splash-demo\n  data-splash-phase=\"review\"\n>\n  <div class=\"splash-art\" aria-hidden=\"true\"></div>\n  <div class=\"splash-overlay\" aria-hidden=\"true\"></div>\n  <div class=\"splash-copy container\">\n    <h1 id=\"hero-title\">Your next move.<br />Right here.</h1>\n    <p class=\"lead\">\n      Approvals to review. Matches to check. Connections to restore.<br />\n      One place to see what needs you.\n    </p>\n  </div>\n  <div class=\"splash-actions cta-row container\">\n    <a class=\"button\" href=\"https://www.dualentry.com/demo\"\n      >See Tasks in a demo\n      <svg class=\"icon\" aria-hidden=\"true\"><use href=\"#i-arrow\" /></svg\n    ></a>\n    <a class=\"text-link\" href=\"#video\"\n      >Explore Tasks\n      <svg class=\"icon\" aria-hidden=\"true\"><use href=\"#i-arrow\" /></svg\n    ></a>\n  </div>\n  <figure\n    class=\"splash-screen\"\n    aria-label=\"Illustrative Tasks screen showing work to do, work in progress, tasks waiting for review, and completed work. On phones, three readable task queues are arranged vertically.\"\n  >\n    <div class=\"splash-glass\" aria-hidden=\"true\">\n      <div class=\"product-window\">\n        <div class=\"product-tabs\">\n          <span>Mosaic</span><span class=\"selected\">Tasks</span\n          ><span>Agents</span><span class=\"plus\">+</span>\n        </div>\n        <div class=\"product-toolbar\">\n          <span class=\"search-art\"\n            ><svg class=\"icon\" aria-hidden=\"true\"><use href=\"#i-search\" /></svg\n            ><span>Search tasks…</span></span\n          ><span class=\"tool-art\"\n            ><svg class=\"icon\" aria-hidden=\"true\">\n              <use href=\"#i-filter\" /></svg></span\n          ><span class=\"tool-art optional-tool\"\n            ><svg class=\"icon\" aria-hidden=\"true\">\n              <use href=\"#i-calendar\" /></svg></span\n          ><span class=\"tool-art optional-tool\"\n            ><svg class=\"icon\" aria-hidden=\"true\">\n              <use href=\"#i-layout\" /></svg></span\n          ><span class=\"new-task\">New task</span>\n        </div>\n        <div class=\"kanban\">\n          <div class=\"kanban-column splash-loop-column\">\n            <div class=\"column-heading\">\n              To do<span class=\"count\"\n                ><span class=\"splash-count-desktop\">3</span\n                ><span class=\"splash-count-mobile\">1</span></span\n              >\n            </div>\n            <div class=\"splash-task-slot\" data-splash-slot=\"0\">\n              <article\n                class=\"task-card splash-moving-card\"\n                data-splash-card=\"0\"\n              >\n                <div class=\"task-source\">\n                  <span class=\"avatar avatar-inbox\"\n                    ><svg class=\"icon\" aria-hidden=\"true\">\n                      <use href=\"#i-inbox\" /></svg></span\n                  ><span>Inbox</span\n                  ><svg class=\"icon\" aria-hidden=\"true\">\n                    <use href=\"#i-more\" />\n                  </svg>\n                </div>\n                <p class=\"task-title\">13 approvals to review.</p>\n                <div class=\"task-footer\">\n                  <span class=\"splash-task-status\" data-splash-card-status\n                    >To do</span\n                  ><span class=\"mini-action\"\n                    >View\n                    <svg class=\"icon\" aria-hidden=\"true\">\n                      <use href=\"#i-arrow\" /></svg\n                  ></span>\n                </div>\n              </article>\n            </div>\n            <article class=\"task-card splash-static-card\">\n              <div class=\"task-source\">\n                <span class=\"avatar avatar-agent\"\n                  ><svg class=\"icon\" aria-hidden=\"true\">\n                    <use href=\"#i-spark\" /></svg></span\n                ><span>Anomaly Detector</span\n                ><svg class=\"icon\" aria-hidden=\"true\">\n                  <use href=\"#i-more\" />\n                </svg>\n              </div>\n              <p class=\"task-title\">3 unusual postings to check.</p>\n              <div class=\"task-footer\">\n                <span class=\"splash-task-status\">Needs attention</span\n                ><span class=\"mini-action\"\n                  >View\n                  <svg class=\"icon\" aria-hidden=\"true\">\n                    <use href=\"#i-arrow\" /></svg\n                ></span>\n              </div>\n            </article>\n            <article class=\"task-card splash-static-card\">\n              <div class=\"task-source\">\n                <span class=\"avatar avatar-agent\"\n                  ><svg class=\"icon\" aria-hidden=\"true\">\n                    <use href=\"#i-spark\" /></svg></span\n                ><span>Contracts</span\n                ><svg class=\"icon\" aria-hidden=\"true\">\n                  <use href=\"#i-more\" />\n                </svg>\n              </div>\n              <p class=\"task-title\">A new contract to review.</p>\n              <div class=\"task-footer\">\n                <span class=\"splash-task-status\">Today</span\n                ><span class=\"mini-action\"\n                  >View\n                  <svg class=\"icon\" aria-hidden=\"true\">\n                    <use href=\"#i-arrow\" /></svg\n                ></span>\n              </div>\n            </article>\n          </div>\n          <div class=\"kanban-column splash-loop-column\">\n            <div class=\"column-heading\">\n              In progress<span class=\"count\"\n                ><span class=\"splash-count-desktop\">2</span\n                ><span class=\"splash-count-mobile\">1</span></span\n              >\n            </div>\n            <div class=\"splash-task-slot\" data-splash-slot=\"1\">\n              <article\n                class=\"task-card splash-moving-card\"\n                data-splash-card=\"1\"\n              >\n                <div class=\"task-source\">\n                  <span class=\"avatar avatar-bank\"></span><span>USAA Bank</span\n                  ><svg class=\"icon\" aria-hidden=\"true\">\n                    <use href=\"#i-more\" />\n                  </svg>\n                </div>\n                <p class=\"task-title\">Reconnect your bank.</p>\n                <div class=\"task-footer\">\n                  <span class=\"splash-task-status\" data-splash-card-status\n                    >In progress</span\n                  ><span class=\"mini-action\"\n                    >View\n                    <svg class=\"icon\" aria-hidden=\"true\">\n                      <use href=\"#i-arrow\" /></svg\n                  ></span>\n                </div>\n              </article>\n            </div>\n            <article class=\"task-card splash-static-card\">\n              <div class=\"task-source\">\n                <span class=\"avatar avatar-agent\"\n                  ><svg class=\"icon\" aria-hidden=\"true\">\n                    <use href=\"#i-spark\" /></svg></span\n                ><span>Bank Recommendations</span\n                ><svg class=\"icon\" aria-hidden=\"true\">\n                  <use href=\"#i-more\" />\n                </svg>\n              </div>\n              <p class=\"task-title\">\n                Matching transactions across your accounts.\n              </p>\n              <div class=\"task-footer\">\n                <span class=\"splash-task-status\">In progress</span\n                ><span class=\"mini-action\"\n                  >View\n                  <svg class=\"icon\" aria-hidden=\"true\">\n                    <use href=\"#i-arrow\" /></svg\n                ></span>\n              </div>\n            </article>\n          </div>\n          <div class=\"kanban-column splash-loop-column\">\n            <div class=\"column-heading\">\n              For review<span class=\"count\"\n                ><span class=\"splash-count-desktop\">3</span\n                ><span class=\"splash-count-mobile\">1</span></span\n              >\n            </div>\n            <div class=\"splash-task-slot\" data-splash-slot=\"2\">\n              <article\n                class=\"task-card splash-moving-card\"\n                data-splash-card=\"2\"\n              >\n                <div class=\"task-source\">\n                  <span class=\"avatar avatar-acme\">A</span><span>Acme Inc</span\n                  ><svg class=\"icon\" aria-hidden=\"true\">\n                    <use href=\"#i-more\" />\n                  </svg>\n                </div>\n                <p class=\"task-title\">38 matches to check.</p>\n                <div class=\"task-footer\">\n                  <span class=\"splash-task-status\" data-splash-card-status\n                    >For review</span\n                  ><span class=\"mini-action\"\n                    >View\n                    <svg class=\"icon\" aria-hidden=\"true\">\n                      <use href=\"#i-arrow\" /></svg\n                  ></span>\n                </div>\n              </article>\n            </div>\n            <article class=\"task-card splash-static-card\">\n              <div class=\"task-source\">\n                <span class=\"avatar avatar-agent\"\n                  ><svg class=\"icon\" aria-hidden=\"true\">\n                    <use href=\"#i-spark\" /></svg></span\n                ><span>Journal agent</span\n                ><svg class=\"icon\" aria-hidden=\"true\">\n                  <use href=\"#i-more\" />\n                </svg>\n              </div>\n              <p class=\"task-title\">Software expense entry prepared.</p>\n              <div class=\"task-footer\">\n                <span class=\"splash-task-status\">Ready for review</span\n                ><span class=\"mini-action\"\n                  >View\n                  <svg class=\"icon\" aria-hidden=\"true\">\n                    <use href=\"#i-arrow\" /></svg\n                ></span>\n              </div>\n            </article>\n            <article class=\"task-card splash-static-card\">\n              <div class=\"task-source\">\n                <span class=\"avatar avatar-agent\"\n                  ><svg class=\"icon\" aria-hidden=\"true\">\n                    <use href=\"#i-spark\" /></svg></span\n                ><span>Daily activity</span\n                ><svg class=\"icon\" aria-hidden=\"true\">\n                  <use href=\"#i-more\" />\n                </svg>\n              </div>\n              <p class=\"task-title\">Your summary is ready.</p>\n              <div class=\"task-footer\">\n                <span class=\"splash-task-status\">For review</span\n                ><span class=\"mini-action\"\n                  >View\n                  <svg class=\"icon\" aria-hidden=\"true\">\n                    <use href=\"#i-arrow\" /></svg\n                ></span>\n              </div>\n            </article>\n          </div>\n          <div class=\"kanban-column splash-done\">\n            <div class=\"column-heading\">Done <span class=\"count\">2</span></div>\n            <article class=\"task-card splash-static-card\">\n              <div class=\"task-source\">\n                <span class=\"avatar avatar-agent\"\n                  ><svg class=\"icon\" aria-hidden=\"true\">\n                    <use href=\"#i-spark\" /></svg></span\n                ><span>Bank Recommendations</span\n                ><svg class=\"icon\" aria-hidden=\"true\">\n                  <use href=\"#i-more\" />\n                </svg>\n              </div>\n              <p class=\"task-title\">Review complete.</p>\n              <div class=\"task-footer\">\n                <span class=\"splash-task-status\">Reviewed</span\n                ><span class=\"mini-action\"\n                  >View\n                  <svg class=\"icon\" aria-hidden=\"true\">\n                    <use href=\"#i-arrow\" /></svg\n                ></span>\n              </div>\n            </article>\n            <article class=\"task-card splash-static-card\">\n              <div class=\"task-source\">\n                <span class=\"avatar avatar-bank\"></span><span>USAA Bank</span\n                ><svg class=\"icon\" aria-hidden=\"true\">\n                  <use href=\"#i-more\" />\n                </svg>\n              </div>\n              <p class=\"task-title\">Connection restored.</p>\n              <div class=\"task-footer\">\n                <span class=\"splash-task-status\">Connected</span\n                ><span class=\"mini-action\"\n                  >View\n                  <svg class=\"icon\" aria-hidden=\"true\">\n                    <use href=\"#i-arrow\" /></svg\n                ></span>\n              </div>\n            </article>\n          </div>\n        </div>\n      </div>\n    </div>\n    <button\n      class=\"splash-motion-toggle\"\n      type=\"button\"\n      aria-label=\"Pause task animation\"\n      aria-pressed=\"false\"\n      data-splash-toggle\n    >\n      <svg class=\"icon\" viewBox=\"0 0 20 20\" aria-hidden=\"true\">\n        <g class=\"splash-pause-icon\">\n          <path\n            d=\"M7 5v10M13 5v10\"\n            fill=\"none\"\n            stroke=\"currentColor\"\n            stroke-width=\"2\"\n            stroke-linecap=\"round\"\n          />\n        </g>\n        <path\n          class=\"splash-play-icon\"\n          d=\"M7 4.5 15 10l-8 5.5Z\"\n          fill=\"currentColor\"\n        />\n      </svg>\n    </button>\n  </figure>\n</section>\n"
    },
    {
      "path": "src/sections/modules.html",
      "url": "source/files/src/sections/modules.html.txt",
      "bytes": 2020,
      "sha256": "31b7b24906aed3aed444c64d368c48393ba175571ca6d435912647ce21555508",
      "content": "<section\n  class=\"modules-section\"\n  id=\"modules\"\n  aria-labelledby=\"modules-title\"\n  data-capture-section=\"modules\"\n>\n  <div class=\"container\">\n    <header class=\"modules-heading\">\n      <p class=\"modules-label\">Everything it touches</p>\n      <h2 id=\"modules-title\">One board. Live state.</h2>\n    </header>\n    <ul class=\"module-grid\" aria-label=\"Connected accounting modules\">\n      <li>\n        <svg class=\"icon\" aria-hidden=\"true\"><use href=\"#i-check\" /></svg\n        >Approval workflows\n      </li>\n      <li>\n        <svg class=\"icon\" aria-hidden=\"true\"><use href=\"#i-calendar\" /></svg\n        >Close management\n      </li>\n      <li>\n        <svg class=\"icon\" aria-hidden=\"true\"><use href=\"#i-sync\" /></svg>Bank\n        match\n      </li>\n      <li>\n        <svg class=\"icon\" aria-hidden=\"true\"><use href=\"#i-spark\" /></svg>Agents\n      </li>\n      <li>\n        <svg class=\"icon\" aria-hidden=\"true\"><use href=\"#i-list\" /></svg>Audit\n        trail\n      </li>\n      <li>\n        <svg class=\"icon\" aria-hidden=\"true\"><use href=\"#i-inbox\" /></svg\n        >Contracts\n      </li>\n      <li>\n        <svg class=\"icon\" aria-hidden=\"true\"><use href=\"#i-clock\" /></svg>Aging\n      </li>\n      <li>\n        <svg class=\"icon\" aria-hidden=\"true\"><use href=\"#i-database\" /></svg\n        >General ledger\n      </li>\n      <li>\n        <svg class=\"icon\" aria-hidden=\"true\"><use href=\"#i-layout\" /></svg\n        >Accounts payable\n      </li>\n      <li>\n        <svg class=\"icon\" aria-hidden=\"true\"><use href=\"#i-inbox\" /></svg\n        >Accounts receivable\n      </li>\n      <li>\n        <svg class=\"icon\" aria-hidden=\"true\"><use href=\"#i-calendar\" /></svg\n        >Revenue recognition\n      </li>\n      <li>\n        <svg class=\"icon\" aria-hidden=\"true\"><use href=\"#i-database\" /></svg\n        >Multi-entity\n      </li>\n    </ul>\n    <a class=\"text-link modules-demo\" href=\"https://www.dualentry.com/demo\">\n      Schedule demo\n      <svg class=\"icon\" aria-hidden=\"true\"><use href=\"#i-arrow\" /></svg>\n    </a>\n  </div>\n</section>\n"
    },
    {
      "path": "src/sections/prepared.html",
      "url": "source/files/src/sections/prepared.html.txt",
      "bytes": 1847,
      "sha256": "791a5afe6ab4e630dd0b826017722a1bc94d8e2f5414e056c51413dced3dc1bc",
      "content": "<section\n  class=\"prepared-section\"\n  id=\"prepared\"\n  aria-labelledby=\"prepared-title\"\n  data-capture-section=\"prepared\"\n>\n  <div class=\"prepared-copy\">\n    <div class=\"prepared-copy-inner\">\n      <h2 id=\"prepared-title\">\n        Every detail.<br />Ready for<br />your review.\n      </h2>\n      <p>\n        A prepared entry. A clear source.<br />The final decision stays with\n        you.\n      </p>\n      <a class=\"text-link\" href=\"#context\"\n        >Explore the details\n        <svg class=\"icon\" aria-hidden=\"true\"><use href=\"#i-arrow\" /></svg\n      ></a>\n    </div>\n  </div>\n  <div class=\"prepared-scene\">\n    <article\n      class=\"prepared-entry\"\n      aria-label=\"Illustrative prepared journal entry for Acme Inc\"\n    >\n      <header class=\"prepared-entry-header\">\n        <span\n          ><svg class=\"icon\" aria-hidden=\"true\"><use href=\"#i-database\" /></svg>\n          Journal entry</span\n        >\n        <span class=\"prepared-status\">Ready for review</span>\n      </header>\n      <div class=\"prepared-entry-body\">\n        <div class=\"prepared-entity\">\n          <span class=\"avatar avatar-acme\">A</span><span>Acme Inc</span\n          ><time datetime=\"2026-09-08\">Sep 8, 2026</time>\n        </div>\n        <h3>Software subscription</h3>\n        <p class=\"prepared-amount\">$1,200<span>.00</span></p>\n        <dl class=\"prepared-lines\">\n          <div>\n            <dt>Software expense<small>Debit</small></dt>\n            <dd>$1,200.00</dd>\n          </div>\n          <div>\n            <dt>Accounts payable<small>Credit</small></dt>\n            <dd>$1,200.00</dd>\n          </div>\n        </dl>\n        <div class=\"prepared-source\">\n          <svg class=\"icon\" aria-hidden=\"true\"><use href=\"#i-spark\" /></svg\n          ><span>Prepared by Journal agent</span><span>Draft</span>\n        </div>\n      </div>\n    </article>\n  </div>\n</section>\n"
    },
    {
      "path": "src/sections/progression.html",
      "url": "source/files/src/sections/progression.html.txt",
      "bytes": 4442,
      "sha256": "adbf231736b141de712125da652fcbfb5c62ce5913af7cd4ff159c335afed5f7",
      "content": "<section\n  class=\"section container progress-section\"\n  id=\"progression\"\n  aria-labelledby=\"progress-title\"\n  data-capture-section=\"progression\"\n  data-progress-stage=\"review\"\n>\n  <div class=\"progress-heading\">\n    <h2 id=\"progress-title\">\n      See it. Review it.<br />\n      Keep moving.\n    </h2>\n  </div>\n  <div class=\"progress-staircase\">\n    <article class=\"progress-step\" data-progress-card=\"see\">\n      <button\n        type=\"button\"\n        class=\"progress-selector\"\n        data-progress-choice=\"see\"\n        aria-pressed=\"false\"\n        aria-controls=\"progress-see-card\"\n      >\n        <span><strong>See it.</strong></span\n        ><svg class=\"icon\"><use href=\"#i-arrow\" /></svg>\n      </button>\n      <div class=\"progress-card-field\">\n        <span class=\"progress-stage-label\"\n          >To do <span class=\"flow-count\">3</span></span\n        >\n        <div class=\"task-card\" id=\"progress-see-card\">\n          <div class=\"task-source\">\n            <span class=\"avatar avatar-inbox\"\n              ><svg class=\"icon\" aria-hidden=\"true\">\n                <use href=\"#i-inbox\" /></svg></span\n            ><span>Inbox</span\n            ><svg class=\"icon more\" aria-hidden=\"true\">\n              <use href=\"#i-more\" />\n            </svg>\n          </div>\n          <p class=\"task-title\">13 approvals ready for your review.</p>\n          <div class=\"task-footer\">\n            <span class=\"timestamp\"\n              ><svg class=\"icon\" aria-hidden=\"true\"><use href=\"#i-clock\" /></svg\n              >2 hrs ago</span\n            ><span class=\"mini-action\">View</span>\n          </div>\n        </div>\n      </div>\n    </article>\n    <article class=\"progress-step\" data-progress-card=\"review\">\n      <button\n        type=\"button\"\n        class=\"progress-selector\"\n        data-progress-choice=\"review\"\n        aria-pressed=\"true\"\n        aria-controls=\"progress-review-card\"\n      >\n        <span><strong>Review it.</strong></span\n        ><svg class=\"icon\"><use href=\"#i-arrow\" /></svg>\n      </button>\n      <div class=\"progress-card-field\">\n        <span class=\"progress-stage-label\"\n          >Waiting on you\n          <span class=\"flow-count flow-count-amber\">3</span></span\n        >\n        <div class=\"task-card\" id=\"progress-review-card\">\n          <div class=\"task-source\">\n            <span class=\"avatar avatar-acme\">A</span><span>Acme Inc</span\n            ><span class=\"badge badge-lilac\">38</span\n            ><svg class=\"icon more\" aria-hidden=\"true\">\n              <use href=\"#i-more\" />\n            </svg>\n          </div>\n          <p class=\"task-title\">38 suggested matches across 12 accounts.</p>\n          <div class=\"task-footer\">\n            <span class=\"timestamp\"\n              ><svg class=\"icon\" aria-hidden=\"true\"><use href=\"#i-clock\" /></svg\n              >4 hrs ago</span\n            ><span class=\"mini-action mini-action-primary\">Review</span>\n          </div>\n        </div>\n      </div>\n    </article>\n    <article class=\"progress-step\" data-progress-card=\"move\">\n      <button\n        type=\"button\"\n        class=\"progress-selector\"\n        data-progress-choice=\"move\"\n        aria-pressed=\"false\"\n        aria-controls=\"progress-move-card\"\n      >\n        <span><strong>Keep moving.</strong></span\n        ><svg class=\"icon\"><use href=\"#i-arrow\" /></svg>\n      </button>\n      <div class=\"progress-card-field\">\n        <span class=\"progress-stage-label\"\n          >Done <span class=\"flow-count progress-count-done\">4</span></span\n        >\n        <div class=\"task-card\" id=\"progress-move-card\">\n          <div class=\"task-source\">\n            <span class=\"avatar avatar-agent\"\n              ><svg class=\"icon\" aria-hidden=\"true\">\n                <use href=\"#i-spark\" /></svg></span\n            ><span>Bank Recommendations</span\n            ><svg class=\"icon more\" aria-hidden=\"true\">\n              <use href=\"#i-more\" />\n            </svg>\n          </div>\n          <p class=\"task-title\">\n            Review complete.<br />\n            Ready for what’s next.\n          </p>\n          <div class=\"task-footer\">\n            <span class=\"timestamp\"\n              ><svg class=\"icon\" aria-hidden=\"true\"><use href=\"#i-clock\" /></svg\n              >Just now</span\n            ><span class=\"progress-reviewed\"\n              ><svg class=\"icon\" aria-hidden=\"true\"><use href=\"#i-check\" /></svg\n              >Reviewed</span\n            >\n          </div>\n        </div>\n      </div>\n    </article>\n  </div>\n</section>\n"
    },
    {
      "path": "src/sections/selector.html",
      "url": "source/files/src/sections/selector.html.txt",
      "bytes": 4296,
      "sha256": "2f271417cbf1addbd035252dd69e47c488c08ce00cf890291bfe0e4d438e88f2",
      "content": "<section\n  class=\"section container sel-section\"\n  id=\"selector\"\n  aria-labelledby=\"selector-title\"\n  data-capture-section=\"selector\"\n>\n  <div class=\"sel-copy\">\n    <h2 id=\"selector-title\">\n      Choose<br />\n      your focus.\n    </h2>\n\n    <p class=\"lead\">\n      The whole picture when you need it.<br />Just the next task when you\n      don’t.\n    </p>\n    <div class=\"sel-choices\" role=\"group\" aria-label=\"Choose a task category\">\n      <button\n        type=\"button\"\n        data-sel-choice=\"all\"\n        aria-pressed=\"false\"\n        aria-controls=\"selector-stage\"\n      >\n        <span class=\"sel-choice-icon\"\n          ><svg class=\"icon\" aria-hidden=\"true\">\n            <use href=\"#i-layout\" /></svg></span\n        >All tasks<svg class=\"icon sel-choice-arrow\" aria-hidden=\"true\">\n          <use href=\"#i-arrow\" />\n        </svg>\n      </button>\n      <button\n        type=\"button\"\n        data-sel-choice=\"approvals\"\n        aria-pressed=\"true\"\n        aria-controls=\"selector-stage\"\n      >\n        <span class=\"sel-choice-icon\"\n          ><svg class=\"icon\" aria-hidden=\"true\">\n            <use href=\"#i-check\" /></svg></span\n        >Approvals<svg class=\"icon sel-choice-arrow\" aria-hidden=\"true\">\n          <use href=\"#i-arrow\" />\n        </svg>\n      </button>\n      <button\n        type=\"button\"\n        data-sel-choice=\"connections\"\n        aria-pressed=\"false\"\n        aria-controls=\"selector-stage\"\n      >\n        <span class=\"sel-choice-icon\"\n          ><svg class=\"icon\" aria-hidden=\"true\">\n            <use href=\"#i-sync\" /></svg></span\n        >Connections<svg class=\"icon sel-choice-arrow\" aria-hidden=\"true\">\n          <use href=\"#i-arrow\" />\n        </svg>\n      </button>\n      <button\n        type=\"button\"\n        data-sel-choice=\"agents\"\n        aria-pressed=\"false\"\n        aria-controls=\"selector-stage\"\n      >\n        <span class=\"sel-choice-icon\"\n          ><svg class=\"icon\" aria-hidden=\"true\">\n            <use href=\"#i-spark\" /></svg></span\n        >Agent runs<svg class=\"icon sel-choice-arrow\" aria-hidden=\"true\">\n          <use href=\"#i-arrow\" />\n        </svg>\n      </button>\n    </div>\n  </div>\n  <div class=\"sel-stage\" id=\"selector-stage\" data-focus=\"approvals\">\n    <div class=\"sel-stage-top\">\n      <span>Tasks</span\n      ><span class=\"sel-stage-count\" data-sel-count>13 approvals</span>\n    </div>\n    <div class=\"sel-card-track\">\n      <article class=\"sel-main-card\" aria-live=\"polite\" aria-atomic=\"true\">\n        <div class=\"sel-card-source\">\n          <span class=\"sel-source-icon\"\n            ><svg class=\"icon\" aria-hidden=\"true\">\n              <use data-sel-icon href=\"#i-inbox\" /></svg></span\n          ><span data-sel-source>Inbox</span\n          ><svg class=\"icon sel-more\" aria-hidden=\"true\">\n            <use href=\"#i-more\" />\n          </svg>\n        </div>\n        <span class=\"sel-card-label\" data-sel-label>Waiting on you</span>\n        <h3 data-sel-title>13 approvals ready for your review</h3>\n\n        <div class=\"sel-card-footer\">\n          <span\n            ><svg class=\"icon\" aria-hidden=\"true\"><use href=\"#i-clock\" /></svg\n            ><span data-sel-time>2 hrs ago</span></span\n          ><span class=\"sel-art-action\" data-sel-action\n            >View approvals\n            <svg class=\"icon\" aria-hidden=\"true\"><use href=\"#i-arrow\" /></svg\n          ></span>\n        </div>\n      </article>\n      <div class=\"sel-support-card sel-support-one\" aria-hidden=\"true\">\n        <div class=\"sel-card-source\">\n          <span class=\"sel-source-icon sel-agent-icon\"\n            ><svg class=\"icon\"><use href=\"#i-spark\" /></svg></span\n          >Bank Recommendations\n        </div>\n        <p>\n          Run ready<br />\n          for review\n        </p>\n        <div class=\"sel-card-footer\">\n          <span>2 days ago</span><span class=\"sel-mini-action\">Review</span>\n        </div>\n      </div>\n      <div class=\"sel-support-card sel-support-two\" aria-hidden=\"true\">\n        <div class=\"sel-card-source\">\n          <span class=\"sel-bank-dot\"></span>USAA Bank\n        </div>\n        <p>\n          Reconnect to see<br />\n          recent transactions\n        </p>\n        <div class=\"sel-card-footer\">\n          <span>Just now</span><span class=\"sel-mini-action\">Reconnect</span>\n        </div>\n      </div>\n    </div>\n  </div>\n</section>\n"
    },
    {
      "path": "src/sections/stats.html",
      "url": "source/files/src/sections/stats.html.txt",
      "bytes": 2510,
      "sha256": "0df68e06c2f083caeb29c8e3b9f0c2b2aa2e80af116dbcec2895c03860e607dc",
      "content": "<section\n  class=\"section stats-section\"\n  id=\"stats\"\n  aria-labelledby=\"stats-title\"\n  data-capture-section=\"stats\"\n>\n  <div class=\"container\">\n    <div class=\"stats-heading\">\n      <p class=\"reference-label\">Why ledger-native</p>\n      <h2 id=\"stats-title\">Agents that reason from the books</h2>\n      <p class=\"lead\">\n        Close on autopilot. Continuous close, not a month-end crunch.\n      </p>\n    </div>\n    <div class=\"stats-grid\" aria-label=\"Published DualEntry customer results\">\n      <article class=\"stat-card stat-card-primary\">\n        <span class=\"stat-icon\" aria-hidden=\"true\"\n          ><svg class=\"icon\"><use href=\"#i-spark\" /></svg\n        ></span>\n        <p class=\"stat-number\">90<span>%</span></p>\n        <h3>Manual tasks automated</h3>\n        <div class=\"stat-meter\" aria-hidden=\"true\">\n          <span style=\"--stat-fill: 90%\"></span>\n        </div>\n        <a class=\"stat-source\" href=\"https://www.dualentry.com/customers/slash\"\n          >Slash customer story\n          <svg class=\"icon\" aria-hidden=\"true\"><use href=\"#i-arrow\" /></svg\n        ></a>\n      </article>\n      <article class=\"stat-card\">\n        <span class=\"stat-icon\" aria-hidden=\"true\"\n          ><svg class=\"icon\"><use href=\"#i-clock\" /></svg\n        ></span>\n        <p class=\"stat-number\">95<span>%</span></p>\n        <h3>Less time to close</h3>\n        <p class=\"stat-context\">\n          <span>20 days</span\n          ><svg class=\"icon\" aria-hidden=\"true\"><use href=\"#i-arrow\" /></svg\n          ><span>1 day</span>\n        </p>\n        <a\n          class=\"stat-source\"\n          href=\"https://www.dualentry.com/customers/graphite\"\n          >Graphite customer story\n          <svg class=\"icon\" aria-hidden=\"true\"><use href=\"#i-arrow\" /></svg\n        ></a>\n      </article>\n      <article class=\"stat-card\">\n        <span class=\"stat-icon\" aria-hidden=\"true\"\n          ><svg class=\"icon\"><use href=\"#i-database\" /></svg\n        ></span>\n        <p class=\"stat-number\">$0</p>\n        <h3>Implementation costs</h3>\n        <p class=\"stat-context\">Full historical data migrated</p>\n        <a\n          class=\"stat-source\"\n          href=\"https://www.dualentry.com/customers/graphite\"\n          >Graphite customer story\n          <svg class=\"icon\" aria-hidden=\"true\"><use href=\"#i-arrow\" /></svg\n        ></a>\n      </article>\n    </div>\n    <p class=\"stats-attribution\">\n      Published customer results. The 95% reduction is calculated from\n      Graphite’s 20-day to 1-day close.\n    </p>\n  </div>\n</section>\n"
    },
    {
      "path": "src/sections/video.html",
      "url": "source/files/src/sections/video.html.txt",
      "bytes": 665,
      "sha256": "23cfe5aa6e0533fa00238ff05da958c008d0aa56dcfed96468dff806cb7f0627",
      "content": "<section\n  class=\"section container video-section\"\n  id=\"video\"\n  aria-labelledby=\"video-title\"\n  data-capture-section=\"video\"\n>\n  <div\n    class=\"video-placeholder\"\n    role=\"img\"\n    aria-label=\"Video placeholder. No video has been added yet.\"\n  >\n    <span class=\"video-corner video-corner-top\" aria-hidden=\"true\"></span>\n    <span class=\"video-placeholder-icon\" aria-hidden=\"true\"\n      ><svg class=\"icon\"><use href=\"#i-play\" /></svg\n    ></span>\n    <h2 id=\"video-title\">Insert video here</h2>\n    <span class=\"video-placeholder-meta\">Product walkthrough</span>\n    <span class=\"video-corner video-corner-bottom\" aria-hidden=\"true\"></span>\n  </div>\n</section>\n"
    },
    {
      "path": "src/sections/workflow.html",
      "url": "source/files/src/sections/workflow.html.txt",
      "bytes": 5679,
      "sha256": "407a29eb46558e09e36ae1859dbf6e812b028259abb4ef043d086f72a59bd17b",
      "content": "<section\n  class=\"section container workflow-section\"\n  id=\"workflow\"\n  aria-labelledby=\"workflow-title\"\n  data-capture-section=\"workflow\"\n>\n  <header class=\"workflow-heading\">\n    <p class=\"workflow-eyebrow\">The close today</p>\n    <h2 id=\"workflow-title\">A scavenger hunt across modules</h2>\n    <p>\n      Four modules, four queues, and no single place that says what is left.\n    </p>\n  </header>\n\n  <div class=\"workflow-cards\">\n    <article class=\"workflow-card\">\n      <header class=\"workflow-card-heading\">\n        <span class=\"workflow-icon workflow-icon-teal\" aria-hidden=\"true\">\n          <svg class=\"icon\"><use href=\"#i-filter\" /></svg>\n        </span>\n        <h3>Scattered</h3>\n        <p>Every module keeps its own queue.</p>\n      </header>\n      <div\n        class=\"workflow-preview workflow-modules\"\n        aria-label=\"Separate module queues\"\n      >\n        <div class=\"workflow-module\">\n          <svg class=\"icon\" aria-hidden=\"true\"><use href=\"#i-sync\" /></svg>\n          <span>Bank match</span\n          ><span class=\"workflow-count workflow-count-amber\">38</span>\n        </div>\n        <div class=\"workflow-module\">\n          <svg class=\"icon\" aria-hidden=\"true\"><use href=\"#i-inbox\" /></svg>\n          <span>Approvals</span><span class=\"workflow-count\">13</span>\n        </div>\n        <div class=\"workflow-module\">\n          <svg class=\"icon\" aria-hidden=\"true\"><use href=\"#i-sync\" /></svg>\n          <span>Syncs</span><span class=\"workflow-count\">4</span>\n        </div>\n        <div class=\"workflow-module\">\n          <svg class=\"icon\" aria-hidden=\"true\"><use href=\"#i-list\" /></svg>\n          <span>AR aging</span\n          ><span class=\"workflow-count workflow-count-lilac\">7</span>\n        </div>\n        <div class=\"workflow-module\">\n          <svg class=\"icon\" aria-hidden=\"true\"><use href=\"#i-calendar\" /></svg>\n          <span>Close</span><span class=\"workflow-count\">9</span>\n        </div>\n        <div class=\"workflow-module\">\n          <svg class=\"icon\" aria-hidden=\"true\"><use href=\"#i-database\" /></svg>\n          <span>Contracts</span\n          ><span class=\"workflow-count workflow-count-lilac\">3</span>\n        </div>\n      </div>\n    </article>\n\n    <article class=\"workflow-card\">\n      <header class=\"workflow-card-heading\">\n        <span class=\"workflow-icon workflow-icon-lilac\" aria-hidden=\"true\">\n          <svg class=\"icon\"><use href=\"#i-layout\" /></svg>\n        </span>\n        <h3>One board</h3>\n        <p>Work arrives on its own, in one place.</p>\n      </header>\n      <div class=\"workflow-preview\" aria-label=\"Tasks collected in one board\">\n        <div class=\"workflow-queue-heading\">\n          To Do <span class=\"workflow-count\">3</span>\n        </div>\n        <ul class=\"workflow-queue\">\n          <li>\n            <span\n              class=\"workflow-source-dot workflow-source-acme\"\n              aria-hidden=\"true\"\n              >A</span\n            ><span>Bank Match: 38 auto matches</span><small>Acme Inc</small>\n          </li>\n          <li>\n            <span class=\"workflow-source-dot\" aria-hidden=\"true\"\n              ><svg class=\"icon\"><use href=\"#i-inbox\" /></svg></span\n            ><span>13 approvals ready for review</span><small>Inbox</small>\n          </li>\n          <li>\n            <span\n              class=\"workflow-source-dot workflow-source-agent\"\n              aria-hidden=\"true\"\n              ><svg class=\"icon\"><use href=\"#i-spark\" /></svg></span\n            ><span>AR aging run ready for review</span><small>Agent</small>\n          </li>\n        </ul>\n      </div>\n    </article>\n\n    <article class=\"workflow-card\">\n      <header class=\"workflow-card-heading\">\n        <span class=\"workflow-icon workflow-icon-sage\" aria-hidden=\"true\">\n          <svg class=\"icon\"><use href=\"#i-check\" /></svg>\n        </span>\n        <h3>Self-resolving</h3>\n        <p>Cards leave when the state changes.</p>\n      </header>\n      <div\n        class=\"workflow-preview\"\n        aria-label=\"Completed tasks with clear status\"\n      >\n        <div class=\"workflow-queue-heading\">\n          Done <span class=\"workflow-count workflow-count-sage\">4</span>\n        </div>\n        <ul class=\"workflow-queue\">\n          <li>\n            <span\n              class=\"workflow-source-dot workflow-source-acme\"\n              aria-hidden=\"true\"\n              >A</span\n            ><span>Bank Match: 38 auto matches</span\n            ><svg class=\"icon workflow-complete\" aria-label=\"Complete\">\n              <use href=\"#i-check\" />\n            </svg>\n          </li>\n          <li>\n            <span\n              class=\"workflow-source-dot workflow-source-bank\"\n              aria-hidden=\"true\"\n            ></span\n            ><span>Finish setup for USAA Bank</span\n            ><svg class=\"icon workflow-complete\" aria-label=\"Complete\">\n              <use href=\"#i-check\" />\n            </svg>\n          </li>\n          <li>\n            <span class=\"workflow-source-dot\" aria-hidden=\"true\"\n              ><svg class=\"icon\"><use href=\"#i-inbox\" /></svg></span\n            ><span>6 approvals ready for review</span\n            ><svg class=\"icon workflow-complete\" aria-label=\"Complete\">\n              <use href=\"#i-check\" />\n            </svg>\n          </li>\n          <li>\n            <span\n              class=\"workflow-source-dot workflow-source-agent\"\n              aria-hidden=\"true\"\n              ><svg class=\"icon\"><use href=\"#i-spark\" /></svg></span\n            ><span>Daily activity sent to the CFO</span\n            ><svg class=\"icon workflow-complete\" aria-label=\"Complete\">\n              <use href=\"#i-check\" />\n            </svg>\n          </li>\n        </ul>\n      </div>\n    </article>\n  </div>\n</section>\n"
    },
    {
      "path": "src/styles/agent.css",
      "url": "source/files/src/styles/agent.css.txt",
      "bytes": 7852,
      "sha256": "0227bc17d4b0df6583492c747bd65e1363a8426d81f5c54585fd4a7d8b44926e",
      "content": ".agent-section {\n  padding-block: 96px;\n}\n.agent-heading {\n  display: grid;\n  grid-template-columns: repeat(12, minmax(0, 1fr));\n  gap: 24px;\n  align-items: end;\n  margin-bottom: 40px;\n}\n.agent-heading h2 {\n  grid-column: span 7;\n  margin: 0;\n  max-width: 620px;\n  font-weight: 400;\n}\n\n.agent-stage {\n  display: grid;\n  grid-template-columns: minmax(220px, 4fr) 48px minmax(0, 7fr);\n  align-items: center;\n  padding: 64px 40px;\n  border: 1px solid var(--line);\n  border-radius: var(--radius);\n  background: var(--de-brand-100);\n}\n.agent-queue,\n.agent-form {\n  background: var(--white);\n  border: 1px solid var(--line);\n  border-radius: 8px;\n  overflow: hidden;\n}\n.agent-queue-header,\n.agent-form-header {\n  display: flex;\n  align-items: center;\n  justify-content: space-between;\n  gap: 12px;\n  min-height: 64px;\n  padding: 18px 24px;\n  font-size: 15px;\n  font-weight: 400;\n  border-bottom: 1px solid var(--line);\n}\n.agent-form-header {\n  padding-block: 9px;\n}\n.agent-form-actions {\n  display: flex;\n  align-items: center;\n  gap: 4px;\n  min-width: 0;\n}\n.agent-count {\n  display: grid;\n  place-items: center;\n  width: 23px;\n  height: 23px;\n  border-radius: 5px;\n  background: var(--surface);\n  color: var(--muted);\n  font-size: 12px;\n}\n.agent-task {\n  margin: 16px;\n  padding: 20px;\n  border: 1px solid var(--line);\n  border-radius: 6px;\n  transition:\n    border-color 200ms ease,\n    transform 200ms ease;\n}\n.agent-task-source {\n  display: flex;\n  align-items: center;\n  gap: 8px;\n  color: var(--muted);\n  font-size: 12px;\n}\n.agent-entity {\n  display: grid;\n  place-items: center;\n  width: 23px;\n  height: 23px;\n  border-radius: 50%;\n  color: white;\n  background: var(--ink);\n  font-size: 12px;\n}\n.agent-task h3 {\n  margin: 20px 0 10px;\n  font-size: 21px;\n  line-height: 1.3;\n  font-weight: 400;\n  letter-spacing: -0.025em;\n}\n.agent-task p {\n  margin: 0;\n  font-size: 12px;\n  color: var(--muted);\n  line-height: 1.5;\n}\n.agent-assignment {\n  display: flex;\n  align-items: center;\n  gap: 8px;\n  margin-top: 28px;\n  font-size: 12px;\n  color: var(--muted);\n}\n.agent-assignment-icon {\n  display: grid;\n  place-items: center;\n  width: 26px;\n  height: 26px;\n  background: var(--surface);\n  border-radius: 6px;\n  color: var(--teal);\n}\n.agent-assignment-icon svg {\n  width: 17px;\n  height: 17px;\n}\n.agent-queue-note {\n  display: flex;\n  align-items: center;\n  gap: 8px;\n  padding: 0 24px 20px;\n  color: var(--muted);\n  font-size: 11px;\n}\n.agent-note-dot {\n  width: 5px;\n  height: 5px;\n  border-radius: 50%;\n  background: #94a09d;\n}\n.agent-transfer {\n  display: flex;\n  align-items: center;\n  color: #8ba2a0;\n}\n.agent-transfer span {\n  flex: 1;\n  height: 1px;\n  background: currentColor;\n}\n.agent-transfer svg {\n  width: 16px;\n  height: 16px;\n  margin-left: -3px;\n}\n.agent-form-status {\n  font-size: 11px;\n  line-height: 1.4;\n  padding: 5px 8px;\n  border-radius: 4px;\n  background: var(--surface);\n  color: var(--muted);\n  white-space: nowrap;\n}\n.agent-form-body {\n  padding: 24px;\n}\n.agent-fields {\n  display: grid;\n  grid-template-columns: 1fr 1fr;\n  gap: 16px;\n}\n.agent-field-label {\n  display: block;\n  color: var(--muted);\n  font-size: 11px;\n  margin-bottom: 8px;\n}\n.agent-field-value {\n  position: relative;\n  display: flex;\n  align-items: center;\n  min-height: 40px;\n  font-size: 13px;\n  line-height: 1.3;\n}\n.agent-fields .agent-field-value,\n.agent-memo .agent-field-value {\n  border: 1px solid var(--line);\n  border-radius: 5px;\n  padding: 10px 12px;\n}\n.agent-field-value::after {\n  content: \"\";\n  display: block;\n  position: absolute;\n  left: 12px;\n  top: calc(50% - 3px);\n  width: 58%;\n  height: 6px;\n  border-radius: 2px;\n  background: var(--surface);\n  transition: opacity 200ms ease;\n}\n.agent-field-value > span {\n  visibility: hidden;\n  opacity: 0;\n  transform: translateY(3px);\n  transition:\n    opacity 200ms ease,\n    transform 200ms ease;\n}\n.agent-field-value[data-filled=\"true\"] > span {\n  visibility: visible;\n  opacity: 1;\n  transform: none;\n}\n.agent-field-value[data-filled=\"true\"]::after {\n  opacity: 0;\n}\n.agent-entry-table {\n  margin: 24px 0;\n}\n.agent-entry-row {\n  display: grid;\n  grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr) minmax(0, 1fr);\n  column-gap: 10px;\n  border-bottom: 1px solid var(--line);\n}\n.agent-entry-row > :not(:first-child) {\n  justify-content: flex-end;\n  text-align: right;\n  font-variant-numeric: tabular-nums;\n}\n.agent-entry-row .agent-field-value {\n  min-height: 54px;\n  font-size: 12px;\n}\n.agent-entry-row .agent-field-value::after {\n  left: 0;\n  width: 65%;\n}\n.agent-entry-row > :not(:first-child)::after {\n  left: auto;\n  right: 0;\n}\n.agent-entry-head {\n  padding-bottom: 10px;\n  font-size: 11px;\n  color: var(--muted);\n}\n\n[data-agent-phase=\"assigned\"] .agent-task,\n[data-agent-phase=\"filling\"] .agent-task {\n  border-color: var(--de-brand-200);\n}\n[data-agent-phase=\"assigned\"] .agent-task {\n  transform: translateY(-3px);\n}\nhtml[data-capture=\"true\"] .agent-task {\n  transform: none !important;\n}\n@media (prefers-reduced-motion: reduce) {\n  .agent-task {\n    transform: none !important;\n  }\n}\n[data-agent-phase=\"review\"] .agent-form-status {\n  background: var(--de-brand-100);\n  color: var(--teal);\n}\n\n.agent-replay {\n  display: grid;\n  place-items: center;\n  flex: none;\n  width: 44px;\n  height: 44px;\n  padding: 0;\n  color: var(--teal);\n  background: transparent;\n  border: 1px solid transparent;\n  border-radius: 5px;\n  font: inherit;\n  cursor: pointer;\n  transition: background-color 160ms ease;\n}\n.agent-replay svg {\n  width: 16px;\n  height: 16px;\n}\n.agent-replay:disabled {\n  opacity: 0.4;\n  cursor: default;\n}\n.agent-replay:focus-visible {\n  outline: 2px solid var(--teal);\n  outline-offset: 3px;\n}\n@media (hover: hover) {\n  .agent-replay:not(:disabled):hover {\n    background: var(--surface);\n  }\n}\n@media (max-width: 1000px) {\n  .agent-stage {\n    padding: 40px 24px;\n    grid-template-columns: minmax(190px, 3fr) 24px minmax(0, 5fr);\n  }\n  .agent-task {\n    padding: 16px;\n    margin: 12px;\n  }\n  .agent-heading {\n    grid-template-columns: repeat(6, minmax(0, 1fr));\n  }\n  .agent-heading h2 {\n    grid-column: span 4;\n  }\n  .agent-form-body {\n    padding: 20px;\n  }\n}\n@media (max-width: 700px) {\n  .agent-section {\n    padding-block: 64px;\n  }\n  .agent-heading {\n    display: block;\n    margin-bottom: 28px;\n  }\n  .agent-stage {\n    grid-template-columns: minmax(0, 1fr);\n    padding: 24px 16px;\n  }\n  .agent-queue-header {\n    min-height: 48px;\n    padding: 12px 20px;\n  }\n  .agent-task {\n    margin: 12px;\n    padding: 16px;\n  }\n  .agent-task h3 {\n    margin: 14px 0 8px;\n    font-size: 20px;\n  }\n  .agent-assignment {\n    margin-top: 18px;\n  }\n  .agent-queue-note {\n    padding: 0 20px 16px;\n  }\n  .agent-transfer {\n    justify-self: center;\n    width: 1px;\n    height: 32px;\n    flex-direction: column;\n  }\n  .agent-transfer span {\n    width: 1px;\n    height: auto;\n  }\n  .agent-transfer svg {\n    flex: none;\n    margin: -3px 0 0;\n    transform: rotate(90deg);\n  }\n  .agent-form-header {\n    min-height: 58px;\n    padding: 7px 8px 7px 16px;\n    gap: 4px;\n    font-size: 13px;\n  }\n  .agent-form-status {\n    font-size: 10px;\n    padding: 5px 6px;\n  }\n  .agent-form-body {\n    padding: 20px 16px;\n  }\n  .agent-entry-row {\n    column-gap: 8px;\n    grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr) minmax(0, 1fr);\n  }\n  .agent-entry-row .agent-field-value {\n    font-size: 11px;\n    min-height: 56px;\n  }\n  .agent-field-value {\n    font-size: 12px;\n  }\n  .agent-fields {\n    gap: 10px;\n  }\n  .agent-fields .agent-field-value {\n    padding: 10px 8px;\n  }\n}\n@media (prefers-reduced-motion: reduce) {\n  .agent-section *,\n  .agent-section *::after {\n    transition: none !important;\n  }\n}\nhtml[data-capture=\"true\"] .agent-section *,\nhtml[data-capture=\"true\"] .agent-section *::after {\n  transition: none !important;\n}\n\nhtml[data-capture=\"true\"] .agent-replay {\n  visibility: hidden;\n}\n"
    },
    {
      "path": "src/styles/atmosphere.css",
      "url": "source/files/src/styles/atmosphere.css.txt",
      "bytes": 5815,
      "sha256": "921e4d8ea18112a0363d0cb539d6a7fd00065531dfacf0315ced65e3518db34b",
      "content": "/* Cosmos source photographs remain intact; crops and blur use CSS. */\n.agent-stage,\n.ribbon-closing {\n  position: relative;\n  isolation: isolate;\n  overflow: hidden;\n  background: var(--de-brand-100);\n}\n.agent-stage::before,\n.ribbon-closing::before {\n  content: \"\";\n  position: absolute;\n  z-index: -1;\n  inset: -32px;\n  background: url(\"assets/cosmos-folded-glass.webp\") 50% 60% / cover;\n  filter: grayscale(1) blur(18px);\n  mix-blend-mode: luminosity;\n  opacity: 0.38;\n  pointer-events: none;\n}\n.ribbon-closing {\n  background: #edf2f2;\n}\n.ribbon-closing::before {\n  background-image: url(\"assets/cosmos-ribbed-glass.webp\");\n  opacity: 0.2;\n  filter: grayscale(1) blur(24px);\n}\n\n/* Full-bleed editorial interlude: five columns of copy, seven of product evidence. */\n.prepared-section {\n  display: grid;\n  grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);\n  min-height: min(960px, 100svh);\n  scroll-margin-top: 0;\n  background: var(--de-brand-100);\n}\n.prepared-copy {\n  display: flex;\n  align-items: center;\n  padding: 88px 48px 88px max(var(--gutter), calc((100vw - 1320px) / 2));\n}\n.prepared-copy-inner {\n  max-width: 440px;\n}\n.prepared-copy h2 {\n  color: var(--teal);\n  font-size: clamp(44px, 4.45vw, 72px);\n  line-height: 1.05;\n  letter-spacing: -0.048em;\n  text-wrap: initial;\n}\n.prepared-copy p {\n  margin-top: 32px;\n  color: var(--ink);\n  font-size: 18px;\n  line-height: 1.6;\n  text-wrap: pretty;\n}\n.prepared-copy .text-link {\n  margin-top: 36px;\n}\n.prepared-scene {\n  position: relative;\n  isolation: isolate;\n  overflow: hidden;\n  display: grid;\n  place-items: center;\n  background: var(--teal);\n  padding: 80px clamp(32px, 5vw, 96px);\n}\n.prepared-scene::before {\n  content: \"\";\n  position: absolute;\n  inset: -28px;\n  z-index: -2;\n  background: url(\"assets/cosmos-ribbed-glass.webp\") 48% 46% / cover;\n  filter: grayscale(1) blur(10px);\n  mix-blend-mode: luminosity;\n  opacity: 0.6;\n  pointer-events: none;\n}\n.prepared-scene::after {\n  content: \"\";\n  position: absolute;\n  inset: 0;\n  z-index: -1;\n  background: linear-gradient(\n    155deg,\n    #004f5c0d 10%,\n    #004f5c40 60%,\n    #004f5cd9 100%\n  );\n  pointer-events: none;\n}\n.prepared-entry {\n  width: 100%;\n  max-width: 488px;\n  min-width: 0;\n  background: var(--white);\n  border: 1px solid var(--line);\n  border-radius: 8px;\n  overflow: hidden;\n}\n.prepared-entry-header {\n  display: flex;\n  align-items: center;\n  justify-content: space-between;\n  flex-wrap: wrap;\n  gap: 12px;\n  padding: 22px 28px;\n  border-bottom: 1px solid var(--line);\n  font-size: 14px;\n}\n.prepared-entry-header > span:first-child {\n  display: inline-flex;\n  align-items: center;\n  gap: 10px;\n}\n.prepared-entry-header .icon {\n  width: 16px;\n  height: 16px;\n  color: var(--teal);\n}\n.prepared-status {\n  background: var(--de-brand-100);\n  color: var(--teal);\n  border-radius: 4px;\n  padding: 6px 8px;\n  font-size: 11px;\n  white-space: nowrap;\n}\n.prepared-entry-body {\n  padding: 28px;\n}\n.prepared-entity {\n  display: flex;\n  align-items: center;\n  gap: 8px;\n  font-size: 12px;\n  color: var(--muted);\n}\n.prepared-entity .avatar {\n  width: 22px;\n  height: 22px;\n  font-size: 12px;\n}\n.prepared-entity time {\n  margin-left: auto;\n  font-size: 11px;\n}\n.prepared-entry h3 {\n  font-size: 22px;\n  margin-top: 34px;\n}\n.prepared-amount {\n  margin-top: 14px;\n  font-size: clamp(42px, 4vw, 58px);\n  line-height: 1.1;\n  letter-spacing: -0.055em;\n  font-variant-numeric: tabular-nums;\n}\n.prepared-amount > span {\n  color: #758285;\n}\n.prepared-lines {\n  margin: 32px 0 0;\n  border-top: 1px solid var(--line);\n}\n.prepared-lines > div {\n  display: grid;\n  grid-template-columns: minmax(0, 1fr) auto;\n  align-items: center;\n  gap: 16px;\n  padding: 18px 0;\n  border-bottom: 1px solid var(--line);\n}\n.prepared-lines dt,\n.prepared-lines dd {\n  font-size: 13px;\n  margin: 0;\n}\n.prepared-lines small {\n  display: block;\n  margin-top: 5px;\n  color: var(--muted);\n  font-size: 11px;\n}\n.prepared-lines dd {\n  font-variant-numeric: tabular-nums;\n  white-space: nowrap;\n}\n.prepared-source {\n  display: flex;\n  gap: 8px;\n  align-items: center;\n  margin-top: 24px;\n  font-size: 11px;\n  color: var(--muted);\n}\n.prepared-source .icon {\n  width: 14px;\n  height: 14px;\n  color: var(--teal);\n}\n.prepared-source > span:last-child {\n  margin-left: auto;\n}\n\nhtml[data-capture=\"true\"] .prepared-section {\n  min-height: 900px;\n}\n@media (max-width: 1100px) {\n  .prepared-copy {\n    padding-right: 32px;\n  }\n  .prepared-scene {\n    padding-inline: 32px;\n  }\n  .prepared-entry-header,\n  .prepared-entry-body {\n    padding: 22px;\n  }\n}\n@media (max-width: 800px) {\n  .prepared-section {\n    grid-template-columns: 1fr;\n    min-height: auto;\n  }\n  .prepared-copy {\n    padding: 64px var(--gutter);\n  }\n  .prepared-copy-inner {\n    display: grid;\n    grid-template-columns: 1fr 1fr;\n    column-gap: 32px;\n    max-width: none;\n    width: 100%;\n    align-items: start;\n  }\n  .prepared-copy h2 {\n    font-size: 48px;\n    grid-row: span 2;\n  }\n  .prepared-copy p {\n    margin-top: 4px;\n    font-size: 17px;\n  }\n  .prepared-copy .text-link {\n    margin-top: 20px;\n    align-self: end;\n  }\n  .prepared-scene {\n    padding: 64px var(--gutter);\n  }\n  html[data-capture=\"true\"] .prepared-section {\n    min-height: auto;\n  }\n}\n@media (max-width: 540px) {\n  .prepared-copy {\n    padding-block: 48px;\n  }\n  .prepared-copy-inner {\n    display: block;\n  }\n  .prepared-copy h2 {\n    font-size: 44px;\n  }\n  .prepared-copy p {\n    margin-top: 24px;\n    font-size: 16px;\n  }\n  .prepared-copy .text-link {\n    margin-top: 22px;\n  }\n  .prepared-scene {\n    padding-block: 40px;\n  }\n  .prepared-entry-header,\n  .prepared-entry-body {\n    padding: 20px;\n  }\n  .prepared-entry h3 {\n    font-size: 20px;\n  }\n  .prepared-amount {\n    font-size: 48px;\n  }\n  .prepared-lines > div {\n    gap: 8px;\n  }\n  .prepared-source {\n    flex-wrap: wrap;\n  }\n}\n"
    },
    {
      "path": "src/styles/microfeedback.css",
      "url": "source/files/src/styles/microfeedback.css.txt",
      "bytes": 1854,
      "sha256": "db5db704db851d8b2c08cbbd3a4c750ebdcad335365a194f6bd9e3d5c8a3a7b3",
      "content": "/* Feedback belongs to controls, while product illustrations keep their geometry. */\n.button,\n.control-update-button,\n[data-agent-replay],\n.menu-toggle {\n  transition:\n    transform 180ms cubic-bezier(0.22, 0.68, 0, 1),\n    background-color 180ms ease,\n    border-color 180ms ease;\n}\n.button:active,\n.control-update-button:active,\n[data-agent-replay]:not(:disabled):active,\n.menu-toggle:active {\n  transform: scale(0.98);\n}\n.text-link .icon {\n  transition: transform 180ms cubic-bezier(0.22, 0.68, 0, 1);\n}\n.editorial-filter-menu summary > .icon:last-child {\n  transition: transform 180ms cubic-bezier(0.22, 0.68, 0, 1);\n}\n@media (hover: hover) and (pointer: fine) {\n  .text-link:hover .icon {\n    transform: translateX(4px);\n  }\n  .context-notes button .note-arrow {\n    transform: translateX(-3px);\n    transition:\n      transform 180ms ease,\n      opacity 180ms ease;\n  }\n  .context-notes button:hover .note-arrow,\n  .context-notes button[aria-pressed=\"true\"] .note-arrow {\n    transform: translateX(0);\n    opacity: 1;\n  }\n}\n@media (prefers-reduced-motion: reduce) {\n  .button,\n  .control-update-button,\n  [data-agent-replay],\n  .menu-toggle,\n  .text-link .icon,\n  .note-arrow {\n    transform: none !important;\n  }\n}\nhtml[data-capture=\"true\"]\n  :is(\n    .button,\n    .control-update-button,\n    [data-agent-replay],\n    .menu-toggle,\n    .text-link .icon,\n    .note-arrow\n  ) {\n  transform: none !important;\n}\n/* Comfortable touch targets for the actual landing-page controls. */\n@media (max-width: 800px) {\n  .logo,\n  .site-footer nav a,\n  .text-link {\n    display: inline-flex;\n    align-items: center;\n    min-height: 44px;\n  }\n  .header-cta,\n  .menu-toggle,\n  .pano-focus-control button,\n  .pano-move-button,\n  .editorial-filter-menu summary,\n  .editorial-filter-menu .filter-toolbar button,\n  .match-options button {\n    min-height: 44px;\n  }\n}\n"
    },
    {
      "path": "src/styles/page-ending.css",
      "url": "source/files/src/styles/page-ending.css.txt",
      "bytes": 3048,
      "sha256": "0681bae2b6d813d058017986f8ddf6bb75eadb28326cf90fcba11011c491b703",
      "content": "/* The page closes with a compact module index and one clear next step. */\n.modules-section {\n  padding-block: 104px 72px;\n  text-align: center;\n  background: var(--white);\n}\n\n.modules-heading {\n  margin-bottom: 36px;\n}\n\n.modules-label,\n.close-month-label {\n  margin-bottom: 14px;\n  font-size: 10px;\n  line-height: 1.5;\n  letter-spacing: 0.16em;\n  text-transform: uppercase;\n}\n\n.modules-label {\n  color: var(--muted);\n}\n\n.modules-heading h2 {\n  font-size: clamp(32px, 3.2vw, 46px);\n}\n\n.module-grid {\n  display: grid;\n  grid-template-columns: repeat(6, minmax(0, 1fr));\n  gap: 12px;\n  padding: 0;\n  margin: 0;\n  list-style: none;\n}\n\n.module-grid li {\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  gap: 8px;\n  min-height: 44px;\n  padding: 10px 12px;\n  border: 1px solid var(--line);\n  border-radius: 24px;\n  background: var(--surface);\n  color: #526569;\n  font-size: 12px;\n  line-height: 1.35;\n}\n\n.module-grid .icon {\n  width: 16px;\n  height: 16px;\n  color: var(--_v3---brand--700);\n}\n\n.modules-demo {\n  margin-top: 26px;\n  font-size: 13px;\n}\n\n.close-month-section {\n  padding-block: 80px;\n  background: linear-gradient(\n    175deg,\n    #073640 0%,\n    var(--teal) 58%,\n    var(--_v3---brand--700) 100%\n  );\n  color: var(--white);\n}\n\n.close-month-panel {\n  padding: 60px 32px;\n  border: 1px solid #ffffff24;\n  border-radius: 10px;\n  background: #a6d0d326;\n  text-align: center;\n}\n\n.close-month-label {\n  color: #d8ebedde;\n}\n\n.close-month-panel h2 {\n  font-size: clamp(34px, 3.5vw, 50px);\n  line-height: 1.12;\n}\n\n.close-month-description {\n  margin-top: 18px;\n  color: #e3eff0;\n  font-size: 16px;\n  line-height: 1.5;\n  text-wrap: pretty;\n}\n\n.close-month-actions {\n  display: flex;\n  justify-content: center;\n  align-items: center;\n  flex-wrap: wrap;\n  gap: 12px 24px;\n  margin-top: 28px;\n}\n\n.close-month-button {\n  border-color: var(--white);\n  background: var(--white);\n  color: var(--teal);\n}\n\n.close-month-link {\n  color: var(--white);\n}\n\n@media (hover: hover) and (pointer: fine) {\n  .close-month-button:hover {\n    border-color: var(--de-brand-100);\n    background: var(--de-brand-100);\n  }\n}\n\n@media (max-width: 1100px) {\n  .module-grid {\n    grid-template-columns: repeat(4, minmax(0, 1fr));\n  }\n}\n\n@media (max-width: 800px) {\n  .modules-section {\n    padding-block: 72px 48px;\n  }\n\n  .module-grid {\n    grid-template-columns: repeat(3, minmax(0, 1fr));\n    gap: 10px;\n  }\n\n  .close-month-section {\n    padding-block: 48px;\n  }\n\n  .close-month-panel {\n    padding: 48px 24px;\n  }\n}\n\n@media (max-width: 540px) {\n  .modules-heading {\n    margin-bottom: 28px;\n  }\n\n  .module-grid {\n    grid-template-columns: repeat(2, minmax(0, 1fr));\n    gap: 8px;\n  }\n\n  .module-grid li {\n    justify-content: flex-start;\n    gap: 6px;\n    padding-inline: 10px;\n    font-size: 11px;\n  }\n\n  .close-month-panel {\n    padding: 40px 20px;\n  }\n\n  .close-month-panel h2 {\n    font-size: clamp(30px, 8vw, 38px);\n  }\n\n  .close-month-description {\n    font-size: 15px;\n  }\n\n  .close-month-actions {\n    flex-direction: column;\n    gap: 8px;\n  }\n}\n"
    },
    {
      "path": "src/styles/product.css",
      "url": "source/files/src/styles/product.css.txt",
      "bytes": 9327,
      "sha256": "f945ee052b04db993122179201901de334b83dab7745b9e2f44fba9011533b25",
      "content": "/* Flat product illustrations. Real text and SVG remain crisp at capture resolution. */\n.product-window {\n  background: #fff;\n  border: 1px solid var(--line);\n  border-radius: 8px;\n  overflow: hidden;\n  font-size: 12px;\n}\n.product-tabs {\n  display: flex;\n  align-items: center;\n  gap: 10px;\n  padding: 14px 14px 8px;\n  color: #667276;\n  font-size: 12px;\n}\n.product-tabs > span {\n  padding: 7px 8px;\n  white-space: nowrap;\n}\n.product-tabs .selected {\n  background: #edf1f2;\n  border-radius: 5px;\n  color: var(--ink);\n}\n.product-tabs .plus {\n  font-size: 18px;\n  padding: 3px;\n}\n.product-toolbar {\n  display: flex;\n  align-items: center;\n  gap: 6px;\n  padding: 8px 12px 14px;\n  border-bottom: 1px solid var(--line);\n}\n.search-art {\n  min-width: 0;\n  display: flex;\n  align-items: center;\n  gap: 7px;\n  flex: 1;\n  border: 1px solid #dce4e6;\n  border-radius: 3px;\n  height: 30px;\n  padding: 0 8px;\n  color: #859095;\n}\n.search-art .icon {\n  width: 12px;\n  height: 12px;\n}\n.search-art span {\n  white-space: nowrap;\n  overflow: hidden;\n}\n.tool-art {\n  display: grid;\n  place-items: center;\n  width: 29px;\n  height: 30px;\n  border: 1px solid #dce4e6;\n  color: #718086;\n  border-radius: 3px;\n}\n.tool-art .icon {\n  width: 14px;\n  height: 14px;\n}\n.new-task {\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  white-space: nowrap;\n  height: 30px;\n  padding-inline: 10px;\n  border-radius: 3px;\n  background: var(--teal);\n  color: white;\n  font-size: 11px;\n}\n.kanban {\n  display: grid;\n  grid-template-columns: repeat(3, minmax(0, 1fr));\n  background: #fafcfc;\n}\n.kanban-column {\n  padding: 0 10px 14px;\n  border-right: 1px solid var(--line);\n  min-width: 0;\n}\n.kanban-column:last-child {\n  border-right: 0;\n}\n.column-heading {\n  display: flex;\n  align-items: center;\n  gap: 7px;\n  font-size: 12px;\n  white-space: nowrap;\n  padding: 14px 0;\n}\n.count,\n.badge {\n  display: inline-flex;\n  align-items: center;\n  justify-content: center;\n  font-variant-numeric: tabular-nums;\n  font-size: 11px;\n  background: #e5ecee;\n  color: #386470;\n  padding: 3px 5px;\n  min-width: 19px;\n  border-radius: 4px;\n}\n.count-amber {\n  color: #946b3c;\n  background: #f9f0e5;\n}\n.badge-lilac {\n  background: #f0ecfa;\n  color: #655293;\n}\n.task-card {\n  background: white;\n  border: 1px solid #dce4e6;\n  border-radius: 7px;\n  padding: 12px;\n  margin-bottom: 10px;\n  min-width: 0;\n}\n.task-source {\n  display: flex;\n  align-items: center;\n  gap: 7px;\n  font-size: 10px;\n  color: #667276;\n  min-height: 20px;\n}\n.task-source > span:not(.avatar):not(.badge) {\n  min-width: 0;\n}\n.avatar {\n  display: inline-flex;\n  align-items: center;\n  justify-content: center;\n  width: 17px;\n  height: 17px;\n  border-radius: 50%;\n  flex-shrink: 0;\n  font-size: 10px;\n}\n.avatar-acme {\n  color: white;\n  background: #222626;\n}\n.avatar-bank {\n  background: #24428e;\n}\n.avatar-inbox {\n  background: #e7eff1;\n  color: #426f7a;\n}\n.avatar-agent {\n  background: #f0ecfc;\n  color: #675298;\n}\n.avatar .icon {\n  width: 10px;\n  height: 10px;\n}\n.more {\n  margin-left: auto;\n  width: 12px;\n  height: 14px;\n  color: #7c898d;\n}\n.task-title {\n  margin: 16px 0 20px;\n  font-size: 14px;\n  line-height: 1.4;\n  letter-spacing: -0.015em;\n}\n.task-footer {\n  display: flex;\n  align-items: center;\n  gap: 6px;\n  flex-wrap: wrap;\n}\n.timestamp {\n  display: inline-flex;\n  align-items: center;\n  gap: 4px;\n  font-size: 10px;\n  color: #839095;\n  white-space: nowrap;\n}\n.timestamp .icon {\n  width: 12px;\n  height: 12px;\n}\n.task-footer .timestamp {\n  margin-right: auto;\n}\n.mini-action {\n  display: inline-flex;\n  align-items: center;\n  justify-content: center;\n  font-size: 10px;\n  white-space: nowrap;\n  padding: 5px 7px;\n  background: #edf0f1;\n  color: #566266;\n  border-radius: 4px;\n}\n.mini-action-primary {\n  background: var(--teal);\n  color: white;\n}\n.quiet-state {\n  display: flex;\n  align-items: center;\n  gap: 8px;\n  color: #8a9699;\n  font-size: 10px;\n  padding: 20px 6px;\n  line-height: 1.4;\n}\n.quiet-state .icon {\n  width: 14px;\n}\n.filter-panel {\n  padding: 20px;\n}\n.filter-toolbar {\n  display: flex;\n  gap: 6px;\n  padding: 0 0 20px;\n  align-items: center;\n}\n.filter-toolbar button {\n  display: flex;\n  align-items: center;\n  gap: 7px;\n  border: 1px solid transparent;\n  border-radius: 5px;\n  padding: 8px 12px;\n  min-height: 38px;\n  background: transparent;\n  color: #6e7b80;\n  font-size: 12px;\n  white-space: nowrap;\n  transition:\n    color 160ms,\n    border-color 160ms,\n    background 160ms;\n}\n.filter-toolbar button[aria-pressed=\"true\"] {\n  background: white;\n  border-color: #cbd9dd;\n  color: var(--ink);\n}\n.focus-row {\n  display: grid;\n  grid-template-columns: 128px minmax(0, 1fr) 62px 62px;\n  gap: 10px;\n  align-items: center;\n  padding: 18px 12px;\n  border: 1px solid var(--line);\n  border-radius: 6px;\n  background: white;\n  margin-bottom: 8px;\n  transition: opacity 180ms;\n}\n.focus-source {\n  display: flex;\n  align-items: center;\n  gap: 7px;\n  color: #637075;\n  font-size: 10px;\n}\n.focus-title {\n  font-size: 12px;\n  line-height: 1.45;\n}\n.focus-row .timestamp {\n  font-size: 9px;\n}\n.focus-row .timestamp .icon {\n  display: none;\n}\n.focus-row.is-muted {\n  opacity: 0.34;\n}\n.panel-bottom {\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  gap: 8px;\n  color: #7b888c;\n  font-size: 11px;\n  padding-top: 16px;\n}\n.panel-bottom .icon {\n  width: 12px;\n  height: 12px;\n}\n.queue-list {\n  padding: 8px;\n  border: 1px solid var(--line);\n  background: white;\n  border-radius: 8px;\n  width: 100%;\n}\n.queue-list > div {\n  display: flex;\n  align-items: center;\n  gap: 12px;\n  padding: 12px 10px;\n  font-size: 14px;\n  border: 1px solid var(--line);\n  border-radius: 5px;\n  margin-bottom: 7px;\n}\n.queue-list > div:last-child {\n  margin: 0;\n}\n.queue-list .icon {\n  width: 16px;\n  height: 16px;\n  color: #748388;\n}\n.queue-list .count {\n  margin-left: auto;\n}\n.step-task {\n  width: 100%;\n  max-width: 290px;\n}\n.step-task .task-card {\n  padding: 18px;\n}\n.step-task .task-source {\n  font-size: 12px;\n}\n.step-task .task-title {\n  font-size: 18px;\n}\n.step-task .timestamp {\n  font-size: 11px;\n}\n.step-task .mini-action {\n  font-size: 11px;\n}\n.context-card {\n  background: white;\n  padding: 28px;\n  border: 1px solid #dce4e6;\n  border-radius: 9px;\n  position: relative;\n}\n.context-card .task-source {\n  font-size: 15px;\n  gap: 10px;\n}\n.context-card .avatar {\n  width: 24px;\n  height: 24px;\n  font-size: 14px;\n}\n.context-card .badge {\n  font-size: 14px;\n}\n.context-card .task-title {\n  font-size: 25px;\n  margin: 32px 0 36px;\n  line-height: 1.4;\n  letter-spacing: -0.025em;\n}\n.context-card .timestamp {\n  font-size: 13px;\n}\n.context-card .mini-action {\n  font-size: 14px;\n  padding: 8px 14px;\n}\n.context-card [data-part] {\n  position: relative;\n}\n.context-card [data-part]::before {\n  content: \"\";\n  position: absolute;\n  inset: -8px;\n  border-radius: 5px;\n  border: 1px solid #7cabb333;\n  opacity: 0;\n  transition: opacity 160ms;\n  pointer-events: none;\n}\n#context-demo[data-context=\"source\"] [data-part=\"source\"]::before,\n#context-demo[data-context=\"work\"] [data-part=\"work\"]::before,\n#context-demo[data-context=\"action\"] [data-part=\"action\"]::before {\n  opacity: 1;\n}\n\n@media (max-width: 1100px) {\n  .focus-row {\n    grid-template-columns: 100px minmax(0, 1fr) 55px;\n    padding-inline: 10px;\n  }\n  .focus-row > .timestamp {\n    display: none;\n  }\n}\n@media (max-width: 800px) {\n  .focus-row {\n    grid-template-columns: 120px minmax(0, 1fr) 65px;\n  }\n  .focus-title {\n    font-size: 13px;\n  }\n  .focus-source {\n    font-size: 11px;\n  }\n  .step-task .task-card {\n    padding: 12px;\n  }\n  .step-task .task-title {\n    font-size: 14px;\n  }\n  .step-task .task-source {\n    font-size: 10px;\n  }\n  .step-task .task-footer {\n    gap: 8px;\n  }\n  .step-task .timestamp {\n    font-size: 9px;\n  }\n  .queue-list > div {\n    font-size: 11px;\n    gap: 6px;\n    padding: 12px 6px;\n  }\n  .queue-list .icon {\n    width: 13px;\n  }\n  .context-card {\n    max-width: 460px;\n    width: 100%;\n    margin-inline: auto;\n  }\n  .context-card .task-title {\n    font-size: 25px;\n  }\n}\n@media (max-width: 540px) {\n  .filter-panel {\n    padding: 12px;\n  }\n  .filter-toolbar {\n    gap: 4px;\n    padding-bottom: 12px;\n  }\n  .filter-toolbar button {\n    padding: 7px 8px;\n    font-size: 10px;\n  }\n  .filter-toolbar .count {\n    min-width: 14px;\n    font-size: 9px;\n    padding: 2px 4px;\n  }\n  .focus-row {\n    grid-template-columns: 1fr 58px;\n    gap: 7px 10px;\n    padding: 13px 10px;\n  }\n  .focus-source {\n    grid-column: 1;\n  }\n  .focus-title {\n    grid-column: 1;\n    font-size: 12px;\n  }\n  .focus-row .mini-action {\n    grid-column: 2;\n    grid-row: 1 / 3;\n    justify-self: end;\n  }\n  .focus-row.is-muted {\n    opacity: 0.34;\n  }\n  .step-task .task-card {\n    padding: 20px;\n  }\n  .step-task .task-title {\n    font-size: 19px;\n  }\n  .step-task .task-source {\n    font-size: 12px;\n  }\n  .step-task .timestamp {\n    font-size: 11px;\n  }\n  .queue-list {\n    max-width: 290px;\n  }\n  .queue-list > div {\n    font-size: 15px;\n    padding: 13px 10px;\n    gap: 12px;\n  }\n  .queue-list .icon {\n    width: 16px;\n  }\n  .context-card {\n    padding: 22px;\n  }\n  .context-card .task-source {\n    font-size: 13px;\n    gap: 8px;\n  }\n  .context-card .task-title {\n    font-size: 21px;\n    margin-block: 28px;\n  }\n  .context-card .timestamp {\n    font-size: 11px;\n  }\n  .context-card .mini-action {\n    font-size: 12px;\n  }\n}\n"
    },
    {
      "path": "src/styles/reference-layout.css",
      "url": "source/files/src/styles/reference-layout.css.txt",
      "bytes": 6371,
      "sha256": "68614463c2cc006f2d243084e19dd61ab14a857d03e57235866210dcb6635076",
      "content": "/* Reference page rhythm. Product sections keep their own scoped responsive rules. */\n.container {\n  max-width: 1160px;\n}\n.splash {\n  padding-top: 64px;\n  padding-bottom: 64px;\n}\n.splash-screen {\n  max-width: 1080px;\n  margin-top: 38px;\n}\n.splash-actions {\n  margin-top: 24px;\n}\n.splash-actions .text-link {\n  color: #edf5f7;\n}\n.splash-actions .text-link:hover {\n  color: #fff;\n}\n.section {\n  padding-block: 88px;\n}\n.reference-label {\n  color: var(--muted);\n  font-size: 11px;\n  letter-spacing: 0.12em;\n  text-transform: uppercase;\n  margin-bottom: 14px;\n}\n.sel-copy > .lead {\n  font-size: 16px;\n  line-height: 1.55;\n  margin-top: 22px;\n  margin-bottom: 28px;\n}\n.prepared-copy {\n  padding-left: max(var(--gutter), calc((100vw - 1160px) / 2));\n}\n.video-section {\n  padding-top: 0;\n  padding-bottom: 48px;\n}\n.video-placeholder {\n  width: 100%;\n  min-width: 0;\n  position: relative;\n  display: flex;\n  flex-direction: column;\n  align-items: center;\n  justify-content: center;\n  aspect-ratio: 16/7;\n  min-height: 240px;\n  border: 1px solid var(--line);\n  border-radius: 10px;\n  background: linear-gradient(135deg, #edf2f1, var(--de-brand-100));\n  color: var(--teal);\n}\n.video-placeholder-icon {\n  display: grid;\n  place-items: center;\n  width: 64px;\n  height: 64px;\n  border: 1px solid #004f5c26;\n  border-radius: 50%;\n  background: #ffffffad;\n  margin-bottom: 20px;\n}\n.video-placeholder-icon .icon {\n  width: 23px;\n  height: 23px;\n  margin-left: 3px;\n}\n.video-placeholder h2 {\n  font-size: 24px;\n  letter-spacing: -0.025em;\n}\n.video-placeholder-meta {\n  margin-top: 10px;\n  font-size: 13px;\n  color: var(--muted);\n}\n.video-corner {\n  position: absolute;\n  width: 24px;\n  height: 24px;\n  border-color: #004f5c30;\n  border-style: solid;\n}\n.video-corner-top {\n  left: 24px;\n  top: 24px;\n  border-width: 1px 0 0 1px;\n}\n.video-corner-bottom {\n  right: 24px;\n  bottom: 24px;\n  border-width: 0 1px 1px 0;\n}\n.stats-section {\n  background: linear-gradient(180deg, #f4f7f6, #fff);\n  border-block: 1px solid var(--line);\n}\n.stats-heading {\n  margin-bottom: 38px;\n}\n.stats-heading h2 {\n  max-width: 900px;\n}\n.stats-heading .lead {\n  margin-top: 16px;\n  font-size: 17px;\n}\n.stats-grid {\n  display: grid;\n  grid-template-columns: repeat(3, minmax(0, 1fr));\n  gap: 24px;\n}\n.stat-card {\n  min-width: 0;\n  padding: 32px;\n  border: 1px solid var(--line);\n  border-radius: 8px;\n  background: var(--white);\n  display: flex;\n  flex-direction: column;\n  align-items: flex-start;\n}\n.stat-card-primary {\n  background: var(--teal);\n  color: white;\n  border-color: var(--teal);\n}\n.stat-icon {\n  display: grid;\n  place-items: center;\n  width: 36px;\n  height: 36px;\n  background: var(--de-brand-100);\n  color: var(--teal);\n  border-radius: 7px;\n}\n.stat-card-primary .stat-icon {\n  color: white;\n  background: #ffffff1a;\n}\n.stat-number {\n  margin-top: 34px;\n  margin-bottom: 16px;\n  font-size: clamp(64px, 6.5vw, 92px);\n  font-weight: 400;\n  letter-spacing: -0.055em;\n  line-height: 1;\n  font-variant-numeric: tabular-nums;\n}\n.stat-number > span {\n  font-size: 0.6em;\n  margin-left: 3px;\n}\n.stat-card h3 {\n  font-size: 19px;\n  line-height: 1.35;\n  letter-spacing: -0.02em;\n}\n.stat-context {\n  display: flex;\n  align-items: center;\n  gap: 14px;\n  color: var(--muted);\n  font-size: 13px;\n  min-height: 34px;\n  margin-top: 16px;\n}\n.stat-context .icon {\n  width: 15px;\n  height: 15px;\n  color: var(--teal);\n}\n.stat-meter {\n  width: 100%;\n  height: 4px;\n  margin-top: 32px;\n  margin-bottom: 14px;\n  background: #ffffff25;\n  border-radius: 2px;\n}\n.stat-meter span {\n  display: block;\n  width: var(--stat-fill);\n  height: 100%;\n  background: #bfd3d6;\n  border-radius: inherit;\n}\n.stat-source {\n  display: flex;\n  align-items: center;\n  justify-content: space-between;\n  gap: 14px;\n  width: 100%;\n  margin-top: 26px;\n  padding-top: 22px;\n  border-top: 1px solid var(--line);\n  font-size: 12px;\n  color: var(--teal);\n  min-height: 44px;\n}\n.stat-source .icon {\n  width: 16px;\n  height: 16px;\n  transition: transform 180ms ease;\n}\n.stat-card-primary .stat-source {\n  color: white;\n  border-color: #ffffff26;\n}\n.stat-source:hover .icon {\n  transform: translateX(3px);\n}\n.stats-attribution {\n  margin-top: 18px;\n  font-size: 11px;\n  color: var(--muted);\n  line-height: 1.5;\n}\n.reference-footer {\n  margin: 0;\n  max-width: none;\n  width: 100%;\n  background: #171b1c;\n  color: #e8edec;\n  padding: 64px 0 36px;\n}\n.footer-grid {\n  display: grid;\n  grid-template-columns: 1.4fr repeat(4, 1fr);\n  gap: 40px;\n  align-items: start;\n}\n.reference-footer .logo img {\n  filter: brightness(0) invert(1);\n}\n.reference-footer nav {\n  margin: 0;\n  justify-self: start;\n  text-align: left;\n  display: flex;\n  flex-direction: column;\n  align-items: flex-start;\n  gap: 12px;\n}\n.reference-footer nav h2 {\n  font-size: 10px;\n  letter-spacing: 0.1em;\n  text-transform: uppercase;\n  margin-bottom: 6px;\n  color: #a7b8ba;\n}\n.reference-footer nav a {\n  font-size: 12px;\n  line-height: 1.5;\n  color: #c5d0d1;\n}\n.reference-footer nav a:hover {\n  color: white;\n}\n.footer-copyright {\n  grid-column: 1/-1;\n  margin-top: 24px;\n  font-size: 11px;\n  color: #99a9aa;\n}\n@media (max-width: 1000px) {\n  .stat-card {\n    padding: 24px;\n  }\n  .stat-card h3 {\n    font-size: 17px;\n  }\n  .footer-grid {\n    gap: 24px;\n  }\n}\n@media (max-width: 760px) {\n  .section {\n    padding-block: 64px;\n  }\n  .splash {\n    padding-top: 36px;\n    padding-bottom: 36px;\n  }\n  .splash-screen {\n    margin-top: 28px;\n  }\n  .splash-actions {\n    gap: 12px;\n    margin-top: 24px;\n  }\n  .video-section {\n    padding-top: 0;\n    padding-bottom: 24px;\n  }\n  .video-placeholder {\n    aspect-ratio: 16/10;\n  }\n  .stats-grid {\n    grid-template-columns: 1fr;\n    gap: 16px;\n  }\n  .stat-card {\n    padding: 28px;\n  }\n  .stat-number {\n    font-size: 76px;\n    margin-top: 24px;\n  }\n  .stat-source {\n    margin-top: 22px;\n  }\n  .footer-grid {\n    grid-template-columns: repeat(2, minmax(0, 1fr));\n    gap: 32px 24px;\n  }\n  .reference-footer .logo {\n    grid-column: 1/-1;\n  }\n  .reference-footer nav {\n    gap: 0;\n  }\n  .reference-footer nav a {\n    min-height: 44px;\n    display: flex;\n    align-items: center;\n  }\n  .reference-footer {\n    padding-top: 48px;\n  }\n  .prepared-copy {\n    padding-left: var(--gutter);\n  }\n}\n@media (prefers-reduced-motion: reduce) {\n  .stat-source .icon {\n    transition: none;\n  }\n}\nhtml[data-capture=\"true\"] .stat-source .icon {\n  transition: none;\n}\n"
    },
    {
      "path": "src/styles/scenes-flow.css",
      "url": "source/files/src/styles/scenes-flow.css.txt",
      "bytes": 11726,
      "sha256": "bf220c0d7faa152aab8af4f6d66d828fd279b3d7f27f493bcf41d40f7c8a5ad8",
      "content": "/* Source, task, and board occupy fixed grid tracks with edge-to-edge connectors. */\n.flow-heading {\n  max-width: 850px;\n}\n.flow-bridge {\n  display: grid;\n  grid-template-columns: repeat(12, minmax(0, 1fr));\n  gap: 24px;\n  align-items: center;\n}\n.flow-sources {\n  grid-column: span 4;\n  padding: 24px;\n  border: 1px solid var(--line);\n  border-radius: 8px;\n  background: white;\n  position: relative;\n  min-width: 0;\n}\n.flow-panel-kicker {\n  display: block;\n  font-size: 13px;\n  color: var(--muted);\n  margin-bottom: 24px;\n}\n.flow-source-list {\n  display: grid;\n  gap: 8px;\n}\n.flow-source-list > div {\n  display: flex;\n  align-items: center;\n  gap: 8px;\n  padding: 12px 0;\n  border-bottom: 1px solid var(--line);\n  font-size: 12px;\n}\n.flow-source-list > div:last-child {\n  border: 0;\n}\n.flow-source-list > div > .icon {\n  width: 16px;\n  height: 16px;\n  color: var(--muted);\n  flex-shrink: 0;\n}\n.flow-count {\n  display: inline-flex;\n  align-items: center;\n  justify-content: center;\n  min-width: 23px;\n  padding: 3px 6px;\n  font-size: 12px;\n  font-weight: 400;\n  border-radius: 4px;\n  background: var(--de-brand-100);\n  color: var(--teal);\n  font-variant-numeric: tabular-nums;\n}\n.flow-source-list .flow-count {\n  margin-left: auto;\n}\n.flow-count-amber {\n  background: #f7eee1;\n  color: #966b36;\n}\n.flow-count-indigo {\n  background: var(--de-indigo-100);\n  color: #60548d;\n}\n.flow-count-neutral {\n  background: var(--surface);\n  color: var(--muted);\n}\n.flow-inbox-card {\n  grid-column: span 4;\n  padding: 24px;\n  margin: 0;\n  min-width: 0;\n  position: relative;\n  border-color: var(--line);\n}\n.flow-sources::after,\n.flow-inbox-card::after {\n  content: \"\";\n  position: absolute;\n  left: 100%;\n  top: 50%;\n  width: 25px;\n  height: 1px;\n  background: #b9c9cc;\n}\n.flow-inbox-card .task-source {\n  font-size: 12px;\n}\n.flow-inbox-card .avatar {\n  width: 23px;\n  height: 23px;\n}\n.flow-inbox-card .task-title {\n  font-size: 23px;\n  font-weight: 400;\n  line-height: 1.35;\n  margin: 28px 0 32px;\n}\n.flow-inbox-card .timestamp {\n  font-size: 10px;\n}\n.flow-inbox-card .mini-action {\n  padding: 8px 10px;\n  gap: 8px;\n  font-size: 11px;\n}\n.flow-inbox-card .mini-action .icon {\n  width: 13px;\n  height: 13px;\n}\n.flow-board-field {\n  grid-column: span 4;\n  min-width: 0;\n  padding: 16px;\n  border-radius: 8px;\n  border: 1px solid var(--line);\n  background: var(--surface);\n}\n.flow-board {\n  background: white;\n  border: 1px solid var(--line);\n  border-radius: 6px;\n  overflow: hidden;\n}\n.flow-board-nav {\n  display: flex;\n  align-items: center;\n  gap: 14px;\n  padding: 16px;\n  font-size: 12px;\n  color: var(--muted);\n}\n.flow-board-nav strong {\n  font-weight: 400;\n  margin-right: auto;\n  color: var(--ink);\n}\n.flow-board-nav .icon {\n  width: 13px;\n  height: 13px;\n}\n.flow-board-toolbar {\n  display: flex;\n  align-items: center;\n  justify-content: space-between;\n  border-block: 1px solid var(--line);\n  padding: 12px;\n  font-size: 11px;\n}\n.flow-board-columns {\n  display: grid;\n  gap: 10px;\n  padding: 12px;\n  background: var(--surface);\n}\n.flow-board-columns .task-card {\n  min-height: 152px;\n  padding: 14px;\n  margin: 0;\n  display: flex;\n  flex-direction: column;\n}\n.flow-board-columns .task-source {\n  font-size: 10px;\n  gap: 6px;\n}\n.flow-board-columns .avatar {\n  width: 18px;\n  height: 18px;\n  flex-shrink: 0;\n}\n.flow-board-columns .task-title {\n  font-size: 15px;\n  line-height: 1.4;\n  margin: 18px 0;\n}\n.flow-board-columns .task-footer {\n  margin-top: auto;\n  gap: 6px;\n}\n.flow-board-columns .timestamp,\n.flow-board-columns .mini-action {\n  font-size: 10px;\n}\n\n/* The wide frame keeps the surrounding workflow visible, without 3D decoration. */\n.pano-heading {\n  display: flex;\n  justify-content: space-between;\n  align-items: flex-end;\n  gap: 48px;\n  margin-bottom: 44px;\n}\n\n.pano-controls {\n  display: flex;\n  justify-content: space-between;\n  align-items: center;\n  gap: 20px;\n  margin-bottom: 20px;\n}\n.pano-focus-control {\n  display: inline-flex;\n  background: var(--surface);\n  border: 1px solid var(--line);\n  border-radius: 6px;\n  padding: 4px;\n  gap: 4px;\n}\n.pano-focus-control button {\n  display: flex;\n  align-items: center;\n  gap: 8px;\n  min-height: 38px;\n  border: 1px solid transparent;\n  border-radius: 4px;\n  background: transparent;\n  color: var(--muted);\n  font-size: 12px;\n  padding: 7px 12px;\n}\n.pano-focus-control button[aria-pressed=\"true\"] {\n  background: white;\n  border-color: var(--line);\n  color: var(--ink);\n}\n.pano-focus-control .flow-count {\n  font-size: 10px;\n  min-width: 18px;\n}\n.pano-move-button {\n  display: inline-flex;\n  align-items: center;\n  gap: 12px;\n  border: 0;\n  background: transparent;\n  color: var(--teal);\n  min-height: 44px;\n  font-size: 12px;\n  padding: 8px 0;\n}\n.pano-move-button .icon {\n  width: 16px;\n  height: 16px;\n}\n.pano-scroll {\n  overflow-x: auto;\n  overflow-y: hidden;\n  border: 1px solid var(--line);\n  border-radius: 9px;\n  background: var(--surface);\n  scrollbar-width: thin;\n  scrollbar-color: #bed0d4 transparent;\n  scroll-snap-type: x proximity;\n}\n.pano-scroll:focus-visible {\n  outline: 2px solid var(--teal);\n  outline-offset: 5px;\n}\n.pano-board {\n  display: grid;\n  grid-template-columns: 1fr 1fr 1.35fr 1fr;\n  min-width: 1040px;\n  min-height: 550px;\n}\n.pano-column {\n  min-width: 0;\n  padding: 22px 14px 32px;\n  border-right: 1px solid var(--line);\n  scroll-snap-align: start;\n}\n.pano-column:last-child {\n  border-right: 0;\n}\n.pano-column h3 {\n  display: flex;\n  align-items: center;\n  gap: 9px;\n  font-size: 15px;\n  letter-spacing: -0.015em;\n  padding: 0 2px 23px;\n}\n.pano-col-waiting {\n  background: var(--surface);\n}\n.pano-col-done {\n  background: var(--surface);\n}\n.pano-card-stack {\n  display: grid;\n  gap: 12px;\n}\n.pano-card-stack .task-card {\n  margin: 0;\n  padding: 17px 15px;\n}\n.pano-card-stack .task-source {\n  font-size: 11px;\n}\n.pano-card-stack .task-title {\n  font-size: 16px;\n  margin: 20px 0 22px;\n}\n.pano-card-stack .mini-action {\n  font-size: 11px;\n}\n.pano-card-stack .timestamp {\n  font-size: 10px;\n}\n.pano-moving-card {\n  border-color: #8bb9c3;\n  position: relative;\n}\n.pano-moving-card::before {\n  position: absolute;\n  content: \"\";\n  left: -1px;\n  top: 20px;\n  bottom: 20px;\n  width: 3px;\n  background: var(--teal);\n  border-radius: 0 3px 3px 0;\n}\n.pano-task-detail {\n  display: flex;\n  gap: 6px;\n  margin: -7px 0 25px;\n  flex-wrap: wrap;\n}\n.pano-task-detail > span {\n  background: var(--de-indigo-100);\n  color: #695990;\n  font-size: 10px;\n  padding: 4px 6px;\n  border-radius: 3px;\n}\n.pano-completed-card {\n  border-color: #d9e3dc;\n}\n.pano-empty-state {\n  display: flex;\n  align-items: center;\n  gap: 7px;\n  font-size: 11px;\n  padding: 22px 8px;\n  color: #57776f;\n}\n.pano-empty-state .icon {\n  width: 14px;\n  height: 14px;\n}\n[data-pano-focus=\"waiting\"]\n  .pano-column:not(.pano-col-waiting)\n  .pano-card-stack {\n  opacity: 0.42;\n}\n[data-pano-state=\"done\"] .pano-moving-card {\n  border-color: #8db5a7;\n}\n[data-pano-state=\"done\"] .pano-moving-card::before {\n  background: #527e6e;\n}\n[data-pano-state=\"done\"] [data-pano-task-badge] {\n  background: #e8f2ec;\n  color: #46715e;\n}\n\n/* Equal stages share card and footer baselines; selection does not move the grid. */\n.progress-heading {\n  display: grid;\n  grid-template-columns: 1.4fr 1fr;\n  gap: 48px;\n  align-items: end;\n}\n\n.progress-staircase {\n  display: grid;\n  grid-template-columns: repeat(3, minmax(0, 1fr));\n  gap: 24px;\n  margin-top: 48px;\n}\n.progress-step {\n  min-width: 0;\n  display: flex;\n  flex-direction: column;\n}\n.progress-selector {\n  display: flex;\n  align-items: flex-start;\n  gap: 12px;\n  width: 100%;\n  text-align: left;\n  border: 0;\n  background: transparent;\n  padding: 0 0 20px;\n  color: var(--ink);\n  min-height: 48px;\n}\n\n.progress-selector strong {\n  display: block;\n  font-weight: 400;\n  font-size: 23px;\n  letter-spacing: -0.035em;\n  margin-bottom: 8px;\n}\n\n.progress-selector > .icon {\n  width: 15px;\n  height: 15px;\n  margin: 6px 0 0 auto;\n  opacity: 0.25;\n  flex-shrink: 0;\n}\n.progress-selector[aria-pressed=\"true\"] > .icon {\n  opacity: 1;\n  color: var(--teal);\n}\n.progress-card-field {\n  background: var(--surface);\n  border: 1px solid var(--line);\n  border-radius: 8px;\n  padding: 20px;\n  flex: 1;\n  display: flex;\n  flex-direction: column;\n}\n.progress-stage-label {\n  display: flex;\n  align-items: center;\n  gap: 9px;\n  font-size: 12px;\n  padding-bottom: 20px;\n}\n.progress-card-field .task-card {\n  padding: 20px;\n  margin: 0;\n  min-height: 230px;\n  display: flex;\n  flex-direction: column;\n  flex: 1;\n}\n.progress-card-field .task-source {\n  font-size: 11px;\n}\n.progress-card-field .task-title {\n  font-size: 20px;\n  font-weight: 400;\n  line-height: 1.35;\n  margin: 26px 0;\n}\n.progress-card-field .task-footer {\n  margin-top: auto;\n}\n.progress-card-field .mini-action {\n  font-size: 11px;\n}\n.progress-reviewed {\n  display: inline-flex;\n  align-items: center;\n  gap: 4px;\n  padding: 5px 7px;\n  border-radius: 4px;\n  background: #eaf3ec;\n  color: #496e59;\n  font-size: 10px;\n}\n.progress-reviewed .icon {\n  width: 12px;\n  height: 12px;\n}\n.progress-count-done {\n  background: #e8f2ec;\n  color: #46715e;\n}\n[data-progress-stage=\"see\"] [data-progress-card=\"see\"] .task-card,\n[data-progress-stage=\"review\"] [data-progress-card=\"review\"] .task-card,\n[data-progress-stage=\"move\"] [data-progress-card=\"move\"] .task-card {\n  border-color: var(--teal);\n}\n\n[data-flow-motion=\"true\"] .pano-card-stack {\n  transition: opacity 180ms ease;\n}\n[data-flow-motion=\"true\"] .progress-card-field .task-card {\n  transition: border-color 180ms ease;\n}\n[data-flow-motion=\"true\"] .progress-selector > .icon {\n  transition: opacity 160ms ease;\n}\n@media (max-width: 1100px) {\n  .flow-sources,\n  .flow-inbox-card {\n    padding: 20px;\n  }\n  .flow-board-field {\n    padding: 12px;\n  }\n  .flow-inbox-card .task-title {\n    font-size: 21px;\n  }\n  .progress-card-field {\n    padding: 14px;\n  }\n  .progress-card-field .task-card {\n    padding: 16px;\n  }\n  .progress-card-field .task-title {\n    font-size: 18px;\n  }\n}\n@media (max-width: 800px) {\n  .flow-bridge {\n    grid-template-columns: repeat(6, minmax(0, 1fr));\n    gap: 32px 24px;\n  }\n  .flow-sources,\n  .flow-inbox-card,\n  .flow-board-field {\n    grid-column: 2 / 6;\n  }\n  .flow-sources::after,\n  .flow-inbox-card::after {\n    left: 50%;\n    top: 100%;\n    width: 1px;\n    height: 33px;\n  }\n  .flow-source-list > div {\n    font-size: 13px;\n  }\n  .flow-inbox-card .task-title {\n    font-size: 24px;\n  }\n  .flow-board-columns .task-source {\n    font-size: 12px;\n  }\n  .flow-board-columns .task-title {\n    font-size: 18px;\n  }\n\n  .pano-heading {\n    gap: 24px;\n    align-items: flex-start;\n    flex-direction: column;\n  }\n\n  .progress-heading {\n    grid-template-columns: 1fr;\n    gap: 24px;\n  }\n  .progress-staircase {\n    grid-template-columns: 1fr;\n    gap: 28px;\n  }\n  .progress-selector {\n    min-height: 0;\n  }\n  .progress-card-field .task-card {\n    min-height: 205px;\n  }\n}\n@media (max-width: 540px) {\n  .flow-bridge {\n    grid-template-columns: 1fr;\n  }\n  .flow-sources,\n  .flow-inbox-card,\n  .flow-board-field {\n    grid-column: 1;\n  }\n\n  .pano-heading {\n    margin-bottom: 28px;\n  }\n  .pano-controls {\n    align-items: flex-start;\n    flex-direction: column;\n    gap: 10px;\n  }\n  .pano-focus-control button {\n    min-height: 36px;\n    padding-inline: 10px;\n  }\n  .pano-move-button {\n    font-size: 12px;\n    padding-block: 4px;\n    min-height: 36px;\n  }\n  .pano-board {\n    min-width: 1110px;\n    grid-template-columns: 260px 260px 320px 270px;\n    min-height: 510px;\n  }\n  .pano-column {\n    padding: 20px 12px;\n  }\n\n  .progress-staircase {\n    margin-top: 32px;\n  }\n  .progress-card-field {\n    padding: 20px;\n  }\n  .progress-card-field .task-card {\n    padding: 20px;\n  }\n  .progress-card-field .task-title {\n    font-size: 21px;\n  }\n}\n"
    },
    {
      "path": "src/styles/scenes-focus.css",
      "url": "source/files/src/styles/scenes-focus.css.txt",
      "bytes": 14686,
      "sha256": "385775c31dad16c08a6eb61c53d48d27927795e829f532a50dd6a85d28652080",
      "content": "/* Focus, handoff, and closing scenes. The figures are live HTML, never raster mockups. */\n.sel-section {\n  display: grid;\n  grid-template-columns: repeat(12, minmax(0, 1fr));\n  gap: 24px;\n  align-items: center;\n}\n.sel-copy {\n  grid-column: span 4;\n}\n\n.sel-choices {\n  display: grid;\n  gap: 7px;\n  margin-top: 34px;\n}\n.sel-choices button {\n  display: flex;\n  align-items: center;\n  gap: 14px;\n  width: 100%;\n  min-height: 66px;\n  padding: 10px 16px;\n  border: 0;\n  border-left: 3px solid transparent;\n  border-radius: 5px;\n  background: transparent;\n  color: var(--muted);\n  text-align: left;\n  font-size: 18px;\n}\n.sel-choices button[aria-pressed=\"true\"] {\n  background: var(--de-brand-100, #dfe9eb);\n  border-left-color: var(--teal);\n  color: var(--teal);\n}\n.sel-choice-icon {\n  width: 34px;\n  height: 34px;\n  border-radius: 6px;\n  display: grid;\n  place-items: center;\n  background: var(--surface);\n  color: var(--teal);\n  flex-shrink: 0;\n}\n.sel-choices button[aria-pressed=\"true\"] .sel-choice-icon {\n  background: white;\n}\n.sel-choice-arrow {\n  width: 17px;\n  margin-left: auto;\n  opacity: 0.55;\n}\n.sel-choices button[aria-pressed=\"true\"] .sel-choice-arrow {\n  opacity: 1;\n}\n.sel-stage {\n  grid-column: span 8;\n  min-width: 0;\n  background: var(--surface);\n  border: 1px solid var(--line);\n  border-radius: 8px;\n  padding: 24px;\n  display: flex;\n  flex-direction: column;\n  gap: 24px;\n}\n.sel-stage-top {\n  display: flex;\n  align-items: center;\n  justify-content: space-between;\n  gap: 16px;\n  font-size: 12px;\n  color: var(--muted);\n}\n.sel-stage-count {\n  font-size: 11px;\n  padding: 6px 9px;\n  border: 1px solid var(--line);\n  border-radius: 4px;\n  white-space: nowrap;\n}\n.sel-card-track {\n  display: grid;\n  grid-template-columns: repeat(2, minmax(0, 1fr));\n  gap: 24px;\n}\n.sel-main-card {\n  grid-column: 1 / -1;\n  min-width: 0;\n  min-height: 280px;\n  padding: 24px;\n  border: 1px solid var(--line);\n  border-radius: 6px;\n  background: white;\n  display: flex;\n  flex-direction: column;\n}\n.sel-card-source {\n  display: flex;\n  align-items: center;\n  gap: 10px;\n  font-size: 13px;\n  color: #596a70;\n}\n.sel-source-icon {\n  display: inline-grid;\n  place-items: center;\n  width: 28px;\n  height: 28px;\n  background: var(--de-brand-100, #dfe9eb);\n  border-radius: 7px;\n  color: var(--teal);\n  flex-shrink: 0;\n}\n.sel-source-icon .icon {\n  width: 16px;\n  height: 16px;\n}\n.sel-agent-icon {\n  background: var(--de-indigo-100, #f0ecfc);\n  color: #6856a0;\n}\n.sel-more {\n  margin-left: auto;\n  width: 14px;\n  height: 18px;\n  color: var(--muted);\n}\n.sel-card-label {\n  font-size: 10px;\n  letter-spacing: 0.04em;\n  color: var(--teal);\n  margin-top: 33px;\n}\n.sel-main-card h3 {\n  font-size: 28px;\n  font-weight: 400;\n  line-height: 1.25;\n  letter-spacing: -0.035em;\n  margin-top: 10px;\n  min-height: 70px;\n  text-wrap: pretty;\n}\n\n.sel-card-footer {\n  display: flex;\n  align-items: center;\n  justify-content: space-between;\n  gap: 10px;\n  font-size: 10px;\n  color: var(--muted);\n  margin-top: auto;\n  padding-top: 28px;\n}\n.sel-card-footer > span:first-child {\n  display: flex;\n  align-items: center;\n  gap: 4px;\n}\n.sel-card-footer .icon {\n  width: 13px;\n  height: 13px;\n}\n.sel-art-action {\n  display: flex;\n  align-items: center;\n  gap: 7px;\n  background: var(--teal);\n  border-radius: 4px;\n  color: white;\n  padding: 9px 10px;\n  font-size: 10px;\n  white-space: nowrap;\n}\n.sel-support-card {\n  min-width: 0;\n  padding: 20px;\n  border: 1px solid var(--line);\n  border-radius: 6px;\n  background: white;\n  min-height: 220px;\n  display: flex;\n  flex-direction: column;\n}\n.sel-support-card .sel-card-source {\n  font-size: 11px;\n  gap: 7px;\n}\n.sel-support-card .sel-source-icon {\n  width: 23px;\n  height: 23px;\n}\n.sel-support-card p {\n  font-size: 18px;\n  line-height: 1.4;\n  letter-spacing: -0.02em;\n  margin-top: 24px;\n  font-weight: 400;\n}\n.sel-mini-action {\n  background: var(--de-brand-100, #dfe9eb);\n  color: var(--teal);\n  border-radius: 4px;\n  padding: 7px 9px;\n}\n.sel-bank-dot {\n  display: inline-block;\n  width: 21px;\n  height: 21px;\n  border-radius: 50%;\n  background: #294797;\n  flex-shrink: 0;\n}\n\n.control-heading {\n  display: flex;\n  justify-content: space-between;\n  align-items: flex-end;\n  gap: 36px;\n  margin-bottom: 50px;\n}\n\n.control-composition {\n  display: grid;\n  grid-template-columns: minmax(0, 1fr) 32px minmax(0, 1.4fr) 32px minmax(\n      0,\n      0.9fr\n    );\n  align-items: center;\n}\n.control-source-block {\n  background: white;\n  padding: 24px;\n  border: 1px solid var(--line);\n  border-radius: 8px;\n  min-width: 0;\n}\n.control-connector {\n  height: 1px;\n  width: 100%;\n  background: #b9c9cc;\n}\n\n.control-source-item {\n  display: flex;\n  align-items: center;\n  gap: 10px;\n  padding: 18px 0;\n  border-bottom: 1px solid var(--line);\n}\n.control-source-item:last-child {\n  border-bottom: 0;\n  padding-bottom: 6px;\n}\n.control-letter {\n  width: 23px;\n  height: 23px;\n  display: inline-grid;\n  place-items: center;\n  background: var(--ink);\n  color: white;\n  border-radius: 50%;\n  font-size: 12px;\n  flex-shrink: 0;\n}\n.control-source-glyph {\n  display: grid;\n  place-items: center;\n  color: var(--teal);\n  width: 23px;\n}\n.control-source-glyph .icon {\n  width: 19px;\n}\n.control-source-item strong {\n  font-weight: 400;\n  font-size: 14px;\n}\n.control-source-item p {\n  font-size: 12px;\n  margin-top: 7px;\n  color: var(--muted);\n  line-height: 1.4;\n}\n.control-source-count {\n  margin-left: auto;\n  background: white;\n  border-radius: 4px;\n  padding: 5px;\n  font-size: 11px;\n  color: var(--teal);\n}\n.control-source-arrow {\n  margin-left: auto;\n  width: 14px;\n  color: var(--teal);\n}\n.control-decision-block {\n  background: var(--surface);\n  padding: 24px;\n  border: 1px solid var(--line);\n  border-radius: 8px;\n  min-width: 0;\n}\n\n.control-approval-card {\n  border: 1px solid var(--line);\n  padding: 24px;\n  border-radius: 6px;\n  background: white;\n  min-height: 260px;\n  display: flex;\n  flex-direction: column;\n}\n.control-review-status {\n  align-self: flex-start;\n  display: inline-block;\n  padding: 5px 7px;\n  border-radius: 4px;\n  font-size: 10px;\n  background: var(--de-indigo-100, #f0ecfc);\n  color: #655687;\n  margin-top: 25px;\n}\n.control-approval-card h3 {\n  font-size: 25px;\n  font-weight: 400;\n  line-height: 1.3;\n  margin-top: 11px;\n  min-height: 65px;\n  text-wrap: pretty;\n}\n\n.control-decision-footer {\n  display: flex;\n  align-items: center;\n  gap: 12px;\n  margin-top: auto;\n  padding-top: 25px;\n}\n.control-owner {\n  display: flex;\n  align-items: center;\n  gap: 9px;\n  font-size: 10px;\n  color: var(--muted);\n}\n.control-owner > span {\n  font-size: 10px;\n  color: var(--muted);\n  border-left: 1px solid var(--line);\n  padding-left: 9px;\n}\n.control-complete-icon {\n  opacity: 0;\n  width: 16px;\n  margin-left: auto;\n  color: var(--teal);\n}\n.control-update-row {\n  display: flex;\n  flex-direction: column;\n  align-items: flex-start;\n  gap: 16px;\n  margin-top: 20px;\n}\n\n.control-update-button {\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  gap: 8px;\n  font-size: 12px;\n  color: var(--teal);\n  background: white;\n  border: 1px solid var(--line);\n  border-radius: 5px;\n  padding: 10px 12px;\n  min-height: 44px;\n  white-space: nowrap;\n}\n.control-update-button .icon {\n  width: 14px;\n  height: 14px;\n}\n.control-outcome-block {\n  padding: 24px;\n  background: white;\n  border: 1px solid var(--line);\n  border-radius: 8px;\n  min-width: 0;\n}\n.control-outcome-row {\n  display: flex;\n  gap: 11px;\n  align-items: center;\n}\n.control-outcome-row strong {\n  font-size: 15px;\n  font-weight: 400;\n}\n\n.control-outcome-dot {\n  display: block;\n  width: 7px;\n  height: 7px;\n  background: var(--teal);\n  border-radius: 50%;\n  flex-shrink: 0;\n}\n.control-outcome-row > .icon {\n  margin-left: auto;\n  color: var(--teal);\n  width: 16px;\n  opacity: 0.35;\n}\n.control-composition:has([data-review-state=\"reviewed\"])\n  .control-outcome-row\n  > .icon,\n[data-review-state=\"reviewed\"] .control-complete-icon {\n  opacity: 1;\n}\n[data-review-state=\"reviewed\"] .control-review-status {\n  background: var(--de-brand-100, #dfe9eb);\n  color: var(--teal);\n}\n.ribbon-closing {\n  text-align: center;\n  overflow: hidden;\n  margin-top: 24px;\n  border-top: 1px solid var(--line);\n  padding: 48px 24px;\n  background: var(--de-brand-100);\n  border-radius: 8px;\n}\n.ribbon-closing-copy {\n  padding: 72px 16px;\n}\n.ribbon-closing-copy h2 {\n  font-size: clamp(40px, 4.2vw, 62px);\n}\n\n.ribbon-closing-copy .button {\n  margin-top: 30px;\n}\n.ribbon-track {\n  display: grid;\n  grid-template-columns: repeat(4, minmax(0, 1fr));\n  gap: 24px;\n  text-align: left;\n  align-items: stretch;\n}\n.ribbon-card {\n  min-width: 0;\n  min-height: 206px;\n  padding: 20px;\n  border: 1px solid var(--line);\n  background: white;\n  border-radius: 6px;\n  display: flex;\n  flex-direction: column;\n}\n.ribbon-source {\n  display: flex;\n  align-items: center;\n  gap: 8px;\n  font-size: 11px;\n  color: var(--muted);\n}\n.ribbon-source .sel-source-icon {\n  width: 23px;\n  height: 23px;\n  border-radius: 5px;\n}\n.ribbon-source .sel-source-icon .icon {\n  width: 13px;\n  height: 13px;\n}\n.ribbon-source .control-letter,\n.ribbon-source .sel-bank-dot {\n  width: 19px;\n  height: 19px;\n  font-size: 10px;\n}\n.ribbon-count {\n  background: var(--de-indigo-100, #f0ecfc);\n  color: #645387;\n  border-radius: 4px;\n  padding: 3px 5px;\n  font-size: 10px;\n  margin-left: 2px;\n}\n.ribbon-card p {\n  font-size: 17px;\n  font-weight: 400;\n  line-height: 1.4;\n  letter-spacing: -0.015em;\n  margin-top: 20px;\n  min-height: 47px;\n}\n.ribbon-foot {\n  display: flex;\n  align-items: center;\n  justify-content: space-between;\n  gap: 8px;\n  margin-top: auto;\n  padding-top: 20px;\n  color: var(--muted);\n  font-size: 10px;\n}\n.ribbon-foot > span {\n  background: var(--surface);\n  color: #53686e;\n  padding: 5px 7px;\n  border-radius: 4px;\n}\n.ribbon-foot .icon {\n  width: 13px;\n  height: 13px;\n  color: var(--teal);\n}\n\n@media (hover: hover) and (pointer: fine) {\n  .sel-choices button:hover {\n    color: var(--teal);\n  }\n  .sel-choices button,\n  .control-update-button {\n    transition:\n      background 180ms ease,\n      color 180ms ease;\n  }\n  .control-update-button:hover {\n    background: var(--de-brand-100);\n  }\n}\n@media (max-width: 1100px) {\n  .sel-stage {\n    padding: 20px;\n  }\n  .sel-card-track {\n    gap: 20px;\n  }\n  .sel-support-card {\n    padding: 16px;\n  }\n  .sel-support-card .sel-card-source {\n    font-size: 10px;\n  }\n  .sel-support-card p {\n    font-size: 17px;\n  }\n  .control-composition {\n    grid-template-columns: minmax(0, 1fr) 24px minmax(0, 1.4fr) 24px minmax(\n        0,\n        0.9fr\n      );\n  }\n  .control-source-block,\n  .control-decision-block,\n  .control-outcome-block {\n    padding: 16px;\n  }\n  .control-approval-card {\n    padding: 18px;\n  }\n  .control-approval-card h3 {\n    font-size: 22px;\n  }\n  .control-source-count,\n  .control-source-arrow {\n    display: none;\n  }\n  .control-source-item {\n    gap: 8px;\n  }\n  .control-source-item strong {\n    font-size: 12px;\n  }\n  .control-source-item p {\n    font-size: 11px;\n  }\n  .control-outcome-row {\n    align-items: flex-start;\n  }\n  .control-outcome-dot {\n    margin-top: 7px;\n  }\n  .control-outcome-row > .icon {\n    display: none;\n  }\n  .ribbon-track {\n    grid-template-columns: repeat(2, minmax(0, 1fr));\n  }\n  .ribbon-track > .ribbon-card:nth-child(n + 3) {\n    display: none;\n  }\n}\n@media (max-width: 800px) {\n  .sel-section {\n    grid-template-columns: repeat(6, minmax(0, 1fr));\n  }\n  .sel-copy,\n  .sel-stage {\n    grid-column: 1 / -1;\n  }\n  .sel-copy h2 br {\n    display: none;\n  }\n\n  .sel-choices {\n    grid-template-columns: repeat(4, minmax(0, 1fr));\n    gap: 6px;\n    margin-top: 25px;\n  }\n  .sel-choices button {\n    min-height: 52px;\n    font-size: 12px;\n    justify-content: center;\n    padding: 8px;\n    gap: 6px;\n    border-left: 0;\n    border-bottom: 2px solid transparent;\n  }\n  .sel-choices button[aria-pressed=\"true\"] {\n    border-bottom-color: var(--teal);\n  }\n  .sel-choice-icon {\n    width: 25px;\n    height: 25px;\n    background: transparent;\n  }\n  .sel-choice-icon .icon {\n    width: 16px;\n    height: 16px;\n  }\n  .sel-choice-arrow {\n    display: none;\n  }\n  .sel-support-card {\n    padding: 20px;\n  }\n  .sel-support-card .sel-card-source {\n    font-size: 11px;\n  }\n  .control-heading {\n    display: block;\n    margin-bottom: 32px;\n  }\n\n  .control-composition {\n    display: grid;\n    grid-template-columns: repeat(6, minmax(0, 1fr));\n    gap: 0 24px;\n  }\n  .control-source-block,\n  .control-decision-block,\n  .control-outcome-block {\n    grid-column: 2 / 6;\n    padding: 24px;\n  }\n  .control-connector {\n    grid-column: 2 / 6;\n    justify-self: center;\n    height: 32px;\n    width: 1px;\n  }\n  .control-approval-card {\n    padding: 24px;\n  }\n  .control-source-item strong {\n    font-size: 14px;\n  }\n  .control-source-item p {\n    font-size: 12px;\n  }\n  .control-source-count,\n  .control-source-arrow {\n    display: inline-flex;\n  }\n  .control-approval-card h3 {\n    font-size: 25px;\n  }\n  .control-outcome-row > .icon {\n    display: block;\n  }\n}\n@media (max-width: 540px) {\n  .sel-section {\n    grid-template-columns: 1fr;\n  }\n  .sel-choices {\n    grid-template-columns: repeat(2, minmax(0, 1fr));\n    gap: 5px;\n  }\n  .sel-choices button {\n    justify-content: flex-start;\n    font-size: 13px;\n    padding-inline: 10px;\n  }\n  .sel-stage {\n    padding: 16px;\n    gap: 20px;\n  }\n  .sel-stage-top {\n    font-size: 11px;\n    gap: 8px;\n  }\n  .sel-stage-count {\n    font-size: 10px;\n  }\n  .sel-card-track {\n    grid-template-columns: 1fr;\n    gap: 16px;\n  }\n  .sel-main-card {\n    padding: 20px;\n    min-height: 320px;\n  }\n  .sel-main-card h3 {\n    font-size: 24px;\n    min-height: 120px;\n  }\n\n  .sel-card-source {\n    font-size: 11px;\n  }\n  .sel-card-label {\n    margin-top: 26px;\n  }\n  .sel-card-footer {\n    font-size: 10px;\n  }\n  .sel-support-card {\n    min-height: 190px;\n  }\n  .sel-support-card p br {\n    display: none;\n  }\n\n  .control-composition {\n    grid-template-columns: 1fr;\n  }\n  .control-source-block,\n  .control-decision-block,\n  .control-outcome-block,\n  .control-connector {\n    grid-column: 1;\n  }\n  .control-source-block,\n  .control-decision-block,\n  .control-outcome-block {\n    padding: 20px;\n  }\n  .control-approval-card {\n    padding: 20px;\n    min-height: 260px;\n  }\n  .control-update-button {\n    width: 100%;\n  }\n  .ribbon-closing {\n    padding: 24px 16px;\n  }\n  .ribbon-track {\n    grid-template-columns: 1fr;\n  }\n  .ribbon-track > .ribbon-card:nth-child(n + 2) {\n    display: none;\n  }\n  .ribbon-card {\n    min-height: 190px;\n  }\n  .ribbon-closing-copy {\n    padding: 48px 0;\n  }\n  .ribbon-closing-copy h2 {\n    font-size: 38px;\n  }\n  .ribbon-closing-copy h2 br {\n    display: none;\n  }\n\n  .ribbon-closing-copy .button {\n    font-size: 14px;\n  }\n}\n"
    },
    {
      "path": "src/styles/splash-motion.css",
      "url": "source/files/src/styles/splash-motion.css.txt",
      "bytes": 4231,
      "sha256": "51890e50ef868bea426c2b7998aacb4bd192106252c1a6b24980004c95c74288",
      "content": "/* Three stable slots keep the board still while its tasks exchange places. */\n.splash-screen {\n  position: relative;\n}\n.splash .kanban {\n  position: relative;\n}\n.splash-task-slot {\n  min-height: 146px;\n  margin-bottom: 12px;\n}\n.splash-task-slot > .task-card {\n  margin: 0;\n}\n.splash[data-splash-initialized] .splash-moving-card {\n  position: absolute;\n  top: 0;\n  left: 0;\n  margin: 0;\n  z-index: 2;\n}\n.splash .splash-moving-card {\n  background: #fff;\n}\n.splash .task-source > .icon:last-child {\n  width: 12px;\n  height: 12px;\n  margin-left: auto;\n  color: var(--muted);\n}\n.splash .mini-action {\n  display: inline-flex;\n  align-items: center;\n  gap: 5px;\n}\n.splash .mini-action .icon {\n  width: 12px;\n  height: 12px;\n}\n.splash-task-status {\n  color: var(--muted);\n}\n.splash-count-mobile {\n  display: none;\n}\n.splash-motion-toggle {\n  position: absolute;\n  right: 26px;\n  top: 23px;\n  display: grid;\n  place-items: center;\n  width: 32px;\n  height: 32px;\n  padding: 0;\n  border: 1px solid var(--line);\n  border-radius: 5px;\n  background: #fff;\n  color: var(--teal);\n  cursor: pointer;\n  transition: background-color 180ms ease;\n}\n.splash-motion-toggle .icon {\n  width: 16px;\n  height: 16px;\n}\n.splash-motion-toggle:hover {\n  background: var(--de-brand-100);\n}\n.splash-motion-toggle:focus-visible {\n  outline: 2px solid var(--teal);\n  outline-offset: 3px;\n}\n.splash-motion-toggle:disabled {\n  opacity: 0.45;\n  cursor: default;\n}\n.splash-play-icon {\n  display: none;\n}\n.splash[data-splash-paused=\"true\"] .splash-pause-icon {\n  display: none;\n}\n.splash[data-splash-paused=\"true\"] .splash-play-icon {\n  display: block;\n}\n.splash .product-tabs {\n  padding-right: 64px;\n}\n@media (max-width: 800px) and (min-width: 681px) {\n  .splash .kanban-column {\n    padding-inline: 10px;\n  }\n  .splash .task-card {\n    padding: 12px;\n  }\n  .splash .task-title {\n    font-size: 14px;\n  }\n  .splash .task-source {\n    font-size: 10px;\n  }\n  .splash .task-footer {\n    flex-wrap: wrap;\n    gap: 10px;\n  }\n  .splash .column-heading {\n    font-size: 12px;\n    gap: 6px;\n  }\n}\n@media (max-width: 680px) {\n  .splash {\n    padding-top: 32px;\n    padding-bottom: 36px;\n  }\n  .splash h1 {\n    font-size: clamp(38px, 10.8vw, 48px);\n  }\n  .splash-copy .lead {\n    font-size: 15px;\n    line-height: 1.5;\n    margin-top: 18px;\n    max-width: 350px;\n  }\n  .splash-screen {\n    margin-top: 24px;\n  }\n  .splash .kanban {\n    grid-template-columns: 1fr;\n    gap: 0;\n    padding: 2px 10px 10px;\n  }\n  .splash .kanban-column.splash-loop-column {\n    display: block;\n    border: 0;\n    padding: 0;\n  }\n  .splash .splash-static-card,\n  .splash .splash-done {\n    display: none;\n  }\n  .splash .column-heading {\n    padding: 10px 4px 7px;\n    font-size: 11px;\n    line-height: 1.2;\n    min-height: 0;\n    gap: 6px;\n  }\n  .splash .count {\n    padding: 2px 5px;\n    font-size: 10px;\n  }\n  .splash-count-desktop {\n    display: none;\n  }\n  .splash-count-mobile {\n    display: inline;\n  }\n  .splash-task-slot {\n    min-height: 103px;\n    margin-bottom: 3px;\n  }\n  .splash .splash-moving-card {\n    padding: 11px 13px;\n    border-radius: 6px;\n  }\n  .splash .splash-moving-card .task-source {\n    font-size: 11px;\n    gap: 6px;\n  }\n  .splash .splash-moving-card .avatar {\n    width: 16px;\n    height: 16px;\n    font-size: 10px;\n  }\n  .splash .splash-moving-card .task-title {\n    font-size: 16px;\n    line-height: 1.3;\n    margin: 8px 0 10px;\n  }\n  .splash .splash-moving-card .task-footer {\n    font-size: 10px;\n  }\n  .splash .splash-moving-card .mini-action {\n    font-size: 10px;\n    padding: 3px 6px;\n  }\n  .splash-motion-toggle {\n    width: 44px;\n    height: 44px;\n    top: 9px;\n    right: 13px;\n  }\n  .splash .product-tabs {\n    padding-top: 10px;\n    padding-bottom: 4px;\n  }\n  .splash .product-toolbar {\n    padding-top: 8px;\n    padding-bottom: 10px;\n  }\n  .splash-actions {\n    margin-top: 22px;\n    gap: 12px;\n  }\n  .splash-actions .button {\n    min-height: 44px;\n    font-size: 13px;\n    gap: 10px;\n    padding: 10px 13px;\n  }\n  .splash-actions .text-link {\n    font-size: 13px;\n    gap: 8px;\n  }\n}\n@media (prefers-reduced-motion: reduce) {\n  .splash-motion-toggle {\n    transition: none;\n  }\n}\nhtml[data-capture=\"true\"] .splash-motion-toggle {\n  visibility: hidden;\n}\n"
    },
    {
      "path": "src/styles/splash.css",
      "url": "source/files/src/styles/splash.css.txt",
      "bytes": 5406,
      "sha256": "cb381b0ddc4065d81db70f92e43bcc38feb2a178fe6ae7796de3ee58f2aaf1f4",
      "content": "/* A dark blue editorial splash; the product and remaining page stay light. */\n:root {\n  --splash-navy: #08283e;\n  --splash-top: #092b42;\n}\n.site-header {\n  position: relative;\n  z-index: 4;\n  background: var(--splash-top);\n  color: white;\n  border-color: #ffffff24;\n}\n.site-header .logo img {\n  filter: brightness(0) invert(1);\n}\n.site-header #site-nav {\n  color: #e0ebf0;\n}\n.site-header #site-nav a:hover {\n  color: white;\n}\n.site-header .header-cta {\n  background: white;\n  border-color: white;\n  color: var(--teal);\n}\n.site-header .header-cta:hover {\n  background: #e5eef1;\n  border-color: #e5eef1;\n}\n.site-header .menu-toggle {\n  color: white;\n  background: transparent;\n}\n.site-header :focus-visible {\n  outline-color: #b9e8f5;\n}\n.splash {\n  position: relative;\n  isolation: isolate;\n  overflow: hidden;\n  padding: 76px 0 72px;\n  background: var(--splash-navy);\n}\n.splash-art,\n.splash-overlay {\n  position: absolute;\n  inset: 0;\n  z-index: -1;\n  pointer-events: none;\n}\n.splash-art {\n  overflow: hidden;\n}\n.splash-art::before,\n.splash-art::after {\n  content: \"\";\n  position: absolute;\n  inset-block: -8px;\n  filter: blur(2px);\n}\n.splash-art::before {\n  width: 70%;\n  right: -9%;\n  background: url(\"assets/cosmos-blue-loop.webp\") 50% 45% / cover no-repeat;\n}\n.splash-art::after {\n  width: 55%;\n  left: -7%;\n  background: url(\"assets/cosmos-blue-wave.webp\") 52% 40% / cover no-repeat;\n  opacity: 0.82;\n  mask-image: linear-gradient(90deg, #000 70%, transparent);\n}\n.splash-overlay {\n  background: linear-gradient(\n    180deg,\n    #092b42f5 0%,\n    #092b42d9 13%,\n    #06344d94 32%,\n    #004f5c30 52%,\n    #b8d8e054 76%,\n    #ffffff 100%\n  );\n}\n.splash-copy {\n  text-align: center;\n  color: white;\n}\n.splash h1 {\n  font-size: clamp(48px, 5vw, 72px);\n  line-height: 1.04;\n  letter-spacing: -0.055em;\n  font-weight: 400;\n}\n.splash-copy .lead {\n  max-width: 660px;\n  margin: 26px auto 0;\n  color: #e4eef4;\n  font-size: 19px;\n  line-height: 1.55;\n}\n.splash-screen {\n  width: min(1200px, calc(100% - var(--gutter) * 2));\n  margin: 44px auto 0;\n}\n.splash-glass {\n  padding: 10px;\n  border: 1px solid #ffffff88;\n  border-radius: 17px;\n  background: #ffffff2e;\n  box-shadow:\n    inset 0 1px 0 #ffffff7a,\n    0 24px 64px #072b4333;\n  backdrop-filter: blur(8px);\n  -webkit-backdrop-filter: blur(8px);\n}\n.splash .product-window {\n  border-radius: 9px;\n  border-color: #ffffffbb;\n  background: #f8fbfc;\n}\n.splash .product-tabs {\n  padding: 12px 18px 6px;\n  font-size: 13px;\n}\n.splash .product-toolbar {\n  padding: 10px 18px 14px;\n}\n.splash .search-art,\n.splash .tool-art,\n.splash .new-task {\n  height: 33px;\n}\n.splash .kanban {\n  grid-template-columns: repeat(4, minmax(0, 1fr));\n  background: #f7fafb;\n}\n.splash .kanban-column {\n  padding: 0 12px 6px;\n}\n.splash .column-heading {\n  font-size: 14px;\n  padding: 18px 0;\n}\n.splash .task-card {\n  padding: 14px;\n  margin-bottom: 12px;\n}\n.splash .task-source {\n  font-size: 11px;\n  gap: 6px;\n}\n.splash .task-title {\n  font-size: 15px;\n  line-height: 1.4;\n  margin: 18px 0 22px;\n}\n.splash .task-footer {\n  font-size: 11px;\n  justify-content: space-between;\n}\n.splash .timestamp {\n  font-size: 11px;\n}\n.splash .mini-action {\n  font-size: 11px;\n  padding: 6px 8px;\n}\n.splash-actions {\n  justify-content: center;\n  margin-top: 30px;\n  gap: 14px 28px;\n}\n.splash-actions .button {\n  background: white;\n  border-color: #d2e3e8;\n  color: var(--teal);\n  box-shadow: 0 3px 12px #08283e08;\n}\n.splash-actions .button:hover {\n  background: #f2f7f8;\n}\n.splash-actions .text-link {\n  color: var(--teal);\n}\n@media (max-width: 1100px) {\n  .splash .kanban {\n    grid-template-columns: repeat(3, minmax(0, 1fr));\n  }\n  .splash .splash-done {\n    display: none;\n  }\n  .splash .kanban-column:nth-child(3) {\n    border-right: 0;\n  }\n}\n@media (max-width: 800px) {\n  .site-header #site-nav.is-open {\n    background: var(--splash-top);\n    border-bottom-color: #ffffff24;\n  }\n  .splash {\n    padding-top: 56px;\n    padding-bottom: 56px;\n  }\n  .splash h1 {\n    font-size: 58px;\n  }\n  .splash-copy .lead {\n    font-size: 18px;\n    max-width: 550px;\n  }\n  .splash-copy .lead br {\n    display: none;\n  }\n  .splash-screen {\n    margin-top: 36px;\n  }\n  .splash-art::before {\n    width: 110%;\n    right: -35%;\n  }\n  .splash-art::after {\n    width: 85%;\n    left: -32%;\n  }\n}\n@media (max-width: 540px) {\n  .splash {\n    padding-top: 48px;\n    padding-bottom: 48px;\n  }\n  .splash h1 {\n    font-size: clamp(40px, 11vw, 52px);\n  }\n  .splash-copy .lead {\n    font-size: 17px;\n    margin-top: 22px;\n  }\n  .splash-screen {\n    width: calc(100% - 32px);\n    margin-top: 30px;\n  }\n  .splash-glass {\n    padding: 7px;\n    border-radius: 13px;\n  }\n  .splash .product-tabs {\n    padding-inline: 10px;\n    font-size: 12px;\n    gap: 3px;\n  }\n  .splash .product-toolbar {\n    padding-inline: 10px;\n    gap: 6px;\n  }\n  .splash .optional-tool {\n    display: none;\n  }\n  .splash .kanban-column {\n    padding-inline: 12px;\n  }\n  .splash .task-source {\n    font-size: 12px;\n  }\n  .splash .task-title {\n    font-size: 17px;\n    margin-block: 16px 20px;\n  }\n  .splash .task-footer,\n  .splash .timestamp,\n  .splash .mini-action {\n    font-size: 12px;\n  }\n  .splash-art::before {\n    width: 160%;\n    right: -66%;\n  }\n  .splash-art::after {\n    width: 120%;\n    left: -60%;\n  }\n  .splash-actions {\n    gap: 10px 18px;\n    margin-top: 26px;\n  }\n  .splash-actions .button {\n    font-size: 14px;\n    padding-inline: 16px;\n  }\n}\n"
    },
    {
      "path": "src/styles/styles.css",
      "url": "source/files/src/styles/styles.css.txt",
      "bytes": 10927,
      "sha256": "8ae08518d543ae62a540cbc9bb61c0178564dad22160e501595cdb890b6b7040",
      "content": "@font-face {\n  font-family: Lausanne;\n  src: url(\"assets/lausanne-regular.woff2\") format(\"woff2\");\n  font-style: normal;\n  font-weight: 400;\n  font-display: swap;\n}\n@font-face {\n  font-family: Lausanne;\n  src: url(\"assets/lausanne-medium.woff2\") format(\"woff2\");\n  font-style: normal;\n  font-weight: 500;\n  font-display: swap;\n}\n:root {\n  color-scheme: light;\n  --grid-gap: 24px;\n  --grid-columns: 12;\n  --gutter: clamp(24px, 4.45vw, 80px);\n  font-family: Lausanne, Arial, sans-serif;\n  color: var(--ink);\n  background: var(--white);\n  font-synthesis: none;\n  -webkit-font-smoothing: antialiased;\n}\n* {\n  box-sizing: border-box;\n}\nbody {\n  margin: 0;\n}\n[hidden] {\n  display: none !important;\n}\nbutton,\ninput {\n  font: inherit;\n}\na {\n  color: inherit;\n  text-decoration: none;\n}\nbutton,\na {\n  -webkit-tap-highlight-color: transparent;\n}\nbutton {\n  cursor: pointer;\n}\nbutton:focus-visible,\na:focus-visible {\n  outline: 2px solid #206570;\n  outline-offset: 5px;\n}\nbutton:disabled {\n  cursor: default;\n}\nfigure,\np {\n  margin: 0;\n}\nh1,\nh2,\nh3 {\n  margin: 0;\n  font-weight: 400;\n  text-wrap: balance;\n}\nh1 {\n  font-size: clamp(44px, 4.8vw, 68px);\n  line-height: 1.06;\n  letter-spacing: -0.05em;\n}\nh2 {\n  font-size: clamp(34px, 3.25vw, 48px);\n  line-height: 1.1;\n  letter-spacing: -0.045em;\n}\nh3 {\n  font-size: 22px;\n  line-height: 1.2;\n  letter-spacing: -0.025em;\n}\n.icon {\n  width: 20px;\n  height: 20px;\n  fill: none;\n  stroke: currentColor;\n  stroke-width: 1.6;\n  stroke-linecap: round;\n  stroke-linejoin: round;\n  flex-shrink: 0;\n}\n.sprite {\n  position: absolute;\n  width: 0;\n  height: 0;\n  overflow: hidden;\n}\n.container {\n  width: min(100% - var(--gutter) * 2, 1320px);\n  margin-inline: auto;\n}\n.section {\n  padding-block: 100px;\n  scroll-margin-top: 30px;\n}\n.lead {\n  font-size: clamp(18px, 1.5vw, 22px);\n  line-height: 1.5;\n  color: var(--muted);\n  text-wrap: pretty;\n}\n.button {\n  display: inline-flex;\n  min-height: 48px;\n  align-items: center;\n  justify-content: center;\n  gap: 16px;\n  border: 1px solid var(--teal);\n  background: var(--teal);\n  color: white;\n  border-radius: 5px;\n  font-size: 15px;\n  padding: 12px 20px;\n  white-space: nowrap;\n  transition:\n    background 160ms,\n    border-color 160ms;\n}\n.button:hover {\n  background: #206570;\n  border-color: #206570;\n}\n.button .icon,\n.text-link .icon {\n  width: 18px;\n  height: 18px;\n  transition: transform 160ms;\n}\n@media (hover: hover) and (pointer: fine) {\n  .button:hover .icon,\n  .text-link:hover .icon {\n    transform: translateX(3px);\n  }\n}\n.button-small {\n  min-height: 38px;\n  padding: 8px 14px;\n  font-size: 13px;\n}\n.text-link {\n  display: inline-flex;\n  min-height: 44px;\n  align-items: center;\n  gap: 10px;\n  color: var(--teal);\n  font-size: 15px;\n}\n.cta-row {\n  display: flex;\n  flex-wrap: wrap;\n  align-items: center;\n  gap: 12px 24px;\n}\n.logo {\n  display: inline-flex;\n  flex-shrink: 0;\n}\n.logo img {\n  display: block;\n  width: 126px;\n  height: auto;\n  filter: brightness(0);\n}\n.site-header {\n  border-bottom: 1px solid var(--line);\n}\n.header-row {\n  display: flex;\n  align-items: center;\n  min-height: 80px;\n  gap: 48px;\n}\n#site-nav {\n  display: flex;\n  gap: 28px;\n  margin-left: auto;\n  font-size: 13px;\n  color: #4f595c;\n}\n#site-nav a {\n  padding: 12px 0;\n}\n#site-nav a:hover {\n  color: var(--teal);\n}\n.menu-toggle {\n  display: none;\n}\n.section-heading {\n  margin-bottom: 40px;\n}\n\n.section-heading.centered {\n  text-align: center;\n  margin-bottom: 48px;\n}\n.feature-panel {\n  background: var(--surface);\n  border: 1px solid var(--line);\n  border-radius: var(--radius);\n  min-width: 0;\n}\n.split-section {\n  display: grid;\n  grid-template-columns: 0.85fr 1.65fr;\n  gap: 64px;\n  align-items: center;\n}\n.section-copy .lead {\n  margin-top: 24px;\n  max-width: 340px;\n}\n.section-copy .text-link {\n  margin-top: 24px;\n}\n.steps-grid {\n  display: grid;\n  grid-template-columns: repeat(3, minmax(0, 1fr));\n  gap: 24px;\n}\n.step-panel {\n  display: flex;\n  flex-direction: column;\n  padding: 24px;\n}\n.step-art {\n  min-height: 290px;\n  display: flex;\n  align-items: center;\n  justify-content: center;\n}\n.step-caption {\n  padding: 16px 4px 8px;\n}\n.step-number {\n  font-size: 11px;\n  color: #778285;\n  display: block;\n  margin-bottom: 16px;\n}\n.step-caption h3 {\n  font-size: 26px;\n}\n.step-caption p {\n  font-size: 17px;\n  color: var(--muted);\n  line-height: 1.45;\n  margin-top: 10px;\n}\n.context-section {\n  display: grid;\n  grid-template-columns: 1.05fr 1fr;\n  align-items: center;\n  gap: 72px;\n}\n.context-panel {\n  min-height: 550px;\n  padding: 48px;\n  display: flex;\n  flex-direction: column;\n  justify-content: center;\n}\n.context-copy h2 {\n  margin-bottom: 32px;\n}\n.context-notes {\n  display: grid;\n  gap: 10px;\n}\n.context-notes button {\n  display: flex;\n  align-items: center;\n  gap: 18px;\n  text-align: left;\n  border: 1px solid transparent;\n  background: white;\n  border-radius: 8px;\n  padding: 16px 12px;\n  color: var(--ink);\n  transition: background 160ms;\n}\n.context-notes button:hover {\n  background: #f6f8f8;\n}\n.note-icon {\n  height: 42px;\n  width: 42px;\n  display: grid;\n  place-items: center;\n  background: #f0f4f4;\n  border-radius: 8px;\n  flex-shrink: 0;\n}\n.note-icon .icon {\n  width: 22px;\n  height: 22px;\n}\n.context-notes strong {\n  display: block;\n  font-size: 20px;\n  font-weight: 400;\n  margin: 0;\n  letter-spacing: -0.025em;\n}\n\n.note-arrow {\n  margin: 0 0 0 auto;\n  opacity: 0;\n  width: 16px;\n  color: var(--teal);\n  transition: opacity 160ms;\n}\n.context-notes button[aria-pressed=\"true\"] .note-arrow {\n  opacity: 1;\n}\n.context-notes button[aria-pressed=\"true\"] .note-icon {\n  background: #e6eeee;\n  color: var(--teal);\n}\n.heading-split {\n  display: flex;\n  justify-content: space-between;\n  align-items: flex-end;\n  gap: 32px;\n}\n.heading-split > p {\n  padding-bottom: 6px;\n  max-width: 320px;\n}\n.closing {\n  border-top: 1px solid var(--line);\n  margin-top: 64px;\n  text-align: center;\n  padding-block: 104px 112px;\n}\n.closing h2 {\n  font-size: clamp(40px, 4vw, 58px);\n}\n.closing .button {\n  margin-top: 32px;\n}\n.site-footer {\n  display: flex;\n  align-items: center;\n  border-top: 1px solid var(--line);\n  gap: 36px;\n  min-height: 112px;\n  font-size: 12px;\n  color: var(--muted);\n}\n.site-footer nav {\n  display: flex;\n  gap: 24px;\n  margin-left: auto;\n}\n.site-footer a:hover {\n  color: var(--teal);\n}\n.skip-link {\n  position: absolute;\n  left: 16px;\n  top: -80px;\n  padding: 12px;\n  background: white;\n  z-index: 10;\n}\n.skip-link:focus {\n  top: 12px;\n}\n@media (max-width: 1100px) {\n  .header-row {\n    gap: 24px;\n  }\n  #site-nav {\n    gap: 20px;\n  }\n  .split-section {\n    gap: 32px;\n    grid-template-columns: 0.85fr 1.5fr;\n  }\n  .context-section {\n    gap: 36px;\n  }\n  .context-panel {\n    padding: 32px;\n  }\n  .step-panel {\n    padding: 18px;\n  }\n  .step-art {\n    min-height: 250px;\n  }\n}\n@media (max-width: 800px) {\n  :root {\n    --grid-columns: 6;\n  }\n  .section {\n    padding-block: 64px;\n  }\n  .header-row {\n    min-height: 72px;\n  }\n  #site-nav {\n    display: none;\n  }\n  .header-cta {\n    margin-left: auto;\n  }\n  .menu-toggle {\n    display: inline-flex;\n    align-items: center;\n    gap: 4px;\n    border: 0;\n    padding: 10px 0;\n    background: white;\n    font-size: 13px;\n    order: 3;\n  }\n  .menu-toggle .icon {\n    width: 14px;\n  }\n  #site-nav.is-open {\n    position: absolute;\n    top: 72px;\n    left: 0;\n    right: 0;\n    display: grid;\n    gap: 0;\n    padding: 16px var(--gutter);\n    background: white;\n    border-bottom: 1px solid var(--line);\n    z-index: 5;\n  }\n  .split-section {\n    grid-template-columns: 1fr;\n    gap: 32px;\n  }\n  .section-copy .lead {\n    max-width: 520px;\n  }\n  .section-copy h2 br {\n    display: none;\n  }\n  .section-copy .text-link {\n    margin-top: 16px;\n  }\n  .steps-grid {\n    gap: 14px;\n  }\n  .step-panel {\n    padding: 16px;\n  }\n  .step-art {\n    min-height: 250px;\n  }\n  .step-caption h3 {\n    font-size: 21px;\n  }\n  .step-caption p {\n    font-size: 15px;\n  }\n  .context-section {\n    grid-template-columns: 1fr;\n    gap: 36px;\n  }\n  .context-panel {\n    min-height: 380px;\n    order: 2;\n    padding: 48px;\n  }\n  .context-copy h2 br {\n    display: none;\n  }\n  .context-notes {\n    grid-template-columns: repeat(3, 1fr);\n    gap: 8px;\n  }\n  .context-notes button {\n    flex-direction: column;\n    padding: 12px 8px;\n  }\n  .context-notes strong {\n    font-size: 17px;\n  }\n\n  .note-arrow {\n    display: none;\n  }\n  .heading-split {\n    align-items: flex-start;\n    flex-direction: column;\n    gap: 8px;\n  }\n  .heading-split > p {\n    max-width: 450px;\n  }\n  .closing {\n    margin-top: 40px;\n    padding-block: 72px;\n  }\n  .site-footer {\n    flex-wrap: wrap;\n    gap: 24px;\n    padding-block: 32px;\n  }\n}\n@media (max-width: 540px) {\n  :root {\n    --gutter: 22px;\n    --grid-columns: 1;\n  }\n  h1 {\n    font-size: 44px;\n  }\n  h2 {\n    font-size: 34px;\n  }\n  .section {\n    padding-block: 48px;\n  }\n  .header-row {\n    gap: 16px;\n    min-height: 68px;\n  }\n  .logo img {\n    width: 112px;\n  }\n  .header-cta {\n    font-size: 11px;\n    padding: 8px 10px;\n    min-height: 34px;\n  }\n  .header-cta .icon {\n    display: none;\n  }\n  #site-nav.is-open {\n    top: 68px;\n  }\n  .section-heading {\n    margin-bottom: 28px;\n  }\n  .steps-grid {\n    grid-template-columns: 1fr;\n    gap: 16px;\n  }\n  .step-panel {\n    padding: 24px;\n  }\n  .step-art {\n    min-height: 230px;\n  }\n  .step-caption h3 {\n    font-size: 26px;\n  }\n  .step-caption p {\n    font-size: 17px;\n  }\n  .context-panel {\n    padding: 24px;\n    min-height: 350px;\n  }\n  .context-notes {\n    grid-template-columns: 1fr;\n  }\n  .context-notes button {\n    flex-direction: row;\n    gap: 16px;\n  }\n  .context-notes strong {\n    font-size: 19px;\n  }\n\n  .site-footer nav {\n    gap: 18px;\n    margin-left: auto;\n  }\n  .site-footer > span {\n    width: 100%;\n  }\n  .closing {\n    padding-block: 64px;\n    margin-top: 24px;\n  }\n  .closing h2 {\n    font-size: 40px;\n  }\n}\n@media (max-width: 360px) {\n  .header-row {\n    gap: 10px;\n  }\n  .header-row .logo img {\n    width: 96px;\n  }\n  .menu-toggle {\n    font-size: 12px;\n  }\n}\n@media (prefers-reduced-motion: reduce) {\n  *,\n  *::before,\n  *::after {\n    animation: none !important;\n    transition: none !important;\n    scroll-behavior: auto !important;\n  }\n}\nhtml[data-capture=\"true\"] *,\nhtml[data-capture=\"true\"] *::before,\nhtml[data-capture=\"true\"] *::after {\n  animation: none !important;\n  transition: none !important;\n  caret-color: transparent !important;\n}\nhtml[data-isolated=\"true\"] .site-header,\nhtml[data-isolated=\"true\"] .site-footer,\nhtml[data-isolated=\"true\"] .skip-link {\n  display: none;\n}\nhtml[data-isolated=\"true\"] .closing,\nhtml[data-isolated=\"true\"] .ribbon-closing {\n  margin-top: 0;\n  border-top: 0;\n}\n@media print {\n  .section {\n    break-inside: avoid;\n  }\n  .site-header,\n  .site-footer {\n    position: static;\n  }\n}\n\n.sr-only {\n  position: absolute;\n  width: 1px;\n  height: 1px;\n  padding: 0;\n  margin: -1px;\n  overflow: hidden;\n  clip-path: inset(50%);\n  white-space: nowrap;\n  border: 0;\n}\n"
    },
    {
      "path": "src/styles/tokens.css",
      "url": "source/files/src/styles/tokens.css.txt",
      "bytes": 1363,
      "sha256": "5a30d5d720e5daf09b3cde7a90c31020e35b5f40ee04e6eb9a81e5df2e63f145",
      "content": "/* Public DualEntry marketing CSS, verified 2026-09-08.\n   Semantic aliases below preserve source values; this is not a private library export. */\n:root {\n  --_v3---text-on-light--primary: #1d1f20;\n  --_v3---text-on-light--secondary: #1d1f20a6;\n  --_v3---background--secondary: #f5f6f6;\n  --_v3---background--tertiary: #f1f2f2;\n  --_v3---border-on-light--primary: #e4ebec;\n  --_v3---brand--100: #dfe9eb;\n  --_v3---brand--200: #bfd3d6;\n  --_v3---brand--700: #206570;\n  --_v3---brand--800: #004f5c;\n  --base-color-accent--cyan-100: #ebfcff;\n  --base-color-accent--cyan-300: #c0f2fa;\n  --base-color-accent--indigo-300: #bfa2ff;\n  --base-color-accent--indigo-300-30: #bfa2ff4d;\n  --de-brand-100: var(--_v3---brand--100);\n  --de-brand-200: var(--_v3---brand--200);\n  --de-cyan-100: var(--base-color-accent--cyan-100);\n  --de-cyan-300: var(--base-color-accent--cyan-300);\n  --de-indigo-100: #f0ecfc; /* Public Tasks prototype source token. */\n  --de-lavender-block: var(--base-color-accent--indigo-300-30);\n  --ink: var(--_v3---text-on-light--primary);\n  --muted: var(--_v3---text-on-light--secondary);\n  --teal: var(--_v3---brand--800);\n  --surface: var(--_v3---background--secondary);\n  --line: var(--_v3---border-on-light--primary);\n  --white: #fff;\n  --radius: 8px;\n  --motion-fast: 160ms;\n  --motion-scene: 240ms;\n  --ease-enter: cubic-bezier(0.32, 0.72, 0, 1);\n}\n"
    },
    {
      "path": "src/styles/workflow-cards.css",
      "url": "source/files/src/styles/workflow-cards.css.txt",
      "bytes": 4671,
      "sha256": "bd8fd7f88a09b23a521dcb5e5007b2e5f507f849edb8453c23d575312cc009d0",
      "content": "/* The close today: three aligned, readable illustrations of the same workflow. */\n.workflow-heading {\n  display: grid;\n  gap: 16px;\n  margin-bottom: 36px;\n}\n.workflow-heading h2 {\n  font-size: clamp(28px, 2.8vw, 40px);\n}\n.workflow-heading > p:last-child {\n  color: var(--muted);\n  font-size: 16px;\n  line-height: 1.5;\n}\n.workflow-eyebrow {\n  color: var(--muted);\n  font-size: 11px;\n  letter-spacing: 0.12em;\n  text-transform: uppercase;\n}\n.workflow-cards {\n  display: grid;\n  grid-template-columns: repeat(3, minmax(0, 1fr));\n  gap: 24px;\n}\n.workflow-card {\n  display: grid;\n  grid-template-rows: auto 1fr;\n  min-width: 0;\n  padding: 24px;\n  border: 1px solid var(--line);\n  border-radius: var(--radius);\n  background: var(--surface);\n}\n.workflow-card-heading {\n  display: grid;\n  justify-items: start;\n  gap: 10px;\n  margin-bottom: 24px;\n}\n.workflow-card-heading h3 {\n  font-size: 20px;\n  line-height: 1.25;\n}\n.workflow-card-heading p {\n  min-height: 40px;\n  color: var(--muted);\n  font-size: 14px;\n  line-height: 1.45;\n}\n.workflow-icon {\n  display: grid;\n  place-items: center;\n  width: 36px;\n  height: 36px;\n  margin-bottom: 4px;\n  border-radius: 7px;\n}\n.workflow-icon .icon {\n  width: 19px;\n  height: 19px;\n}\n.workflow-icon-teal {\n  color: var(--teal);\n  background: var(--de-brand-100);\n}\n.workflow-icon-lilac {\n  color: #71629b;\n  background: var(--de-indigo-100);\n}\n.workflow-icon-sage {\n  color: #456c55;\n  background: #e8efe9;\n}\n.workflow-preview {\n  min-width: 0;\n  min-height: 188px;\n  padding: 14px;\n  background: var(--white);\n  border: 1px solid var(--line);\n  border-radius: 6px;\n}\n.workflow-modules {\n  display: grid;\n  grid-template-columns: repeat(2, minmax(0, 1fr));\n  align-content: start;\n  gap: 10px 8px;\n  padding-block: 20px;\n}\n.workflow-module {\n  display: flex;\n  align-items: center;\n  gap: 5px;\n  min-width: 0;\n  min-height: 36px;\n  padding: 6px;\n  border: 1px solid var(--line);\n  border-radius: 4px;\n  font-size: 11px;\n}\n.workflow-module > .icon {\n  width: 12px;\n  height: 12px;\n  color: #6b848b;\n}\n.workflow-module > span:first-of-type {\n  white-space: nowrap;\n}\n.workflow-module .workflow-count {\n  margin-left: auto;\n}\n.workflow-count {\n  display: inline-grid;\n  place-items: center;\n  min-width: 18px;\n  height: 18px;\n  padding: 0 4px;\n  background: var(--de-brand-100);\n  border-radius: 3px;\n  color: var(--teal);\n  font-size: 10px;\n  font-variant-numeric: tabular-nums;\n}\n.workflow-count-amber {\n  color: #8b6031;\n  background: #f7ede0;\n}\n.workflow-count-lilac {\n  color: #71629b;\n  background: var(--de-indigo-100);\n}\n.workflow-count-sage {\n  color: #456c55;\n  background: #e8efe9;\n}\n.workflow-queue-heading {\n  display: flex;\n  align-items: center;\n  gap: 8px;\n  padding-bottom: 12px;\n  font-size: 11px;\n}\n.workflow-queue {\n  display: grid;\n  gap: 0;\n  padding: 0;\n  margin: 0;\n  list-style: none;\n}\n.workflow-queue li {\n  display: flex;\n  align-items: center;\n  gap: 7px;\n  min-height: 32px;\n  border-top: 1px solid #f1f3f3;\n  font-size: 11px;\n  line-height: 1.35;\n}\n.workflow-queue li > span:nth-child(2) {\n  flex: 1;\n}\n.workflow-queue small {\n  color: #879395;\n  font-size: 9px;\n  white-space: nowrap;\n}\n.workflow-source-dot {\n  display: grid;\n  place-items: center;\n  flex: 0 0 15px;\n  width: 15px;\n  height: 15px;\n  background: var(--de-brand-100);\n  color: var(--teal);\n  border-radius: 50%;\n  font-size: 9px;\n}\n.workflow-source-dot .icon {\n  width: 10px;\n  height: 10px;\n}\n.workflow-source-acme {\n  background: #27302f;\n  color: white;\n}\n.workflow-source-agent {\n  background: var(--de-indigo-100);\n  color: #71629b;\n}\n.workflow-source-bank {\n  background: #2e4993;\n}\n.workflow-complete {\n  width: 12px;\n  height: 12px;\n  color: #63806d;\n}\n@media (max-width: 1100px) and (min-width: 761px) {\n  .workflow-cards {\n    gap: 16px;\n  }\n  .workflow-card {\n    padding: 16px;\n  }\n  .workflow-preview {\n    padding: 10px;\n  }\n  .workflow-modules {\n    grid-template-columns: 1fr;\n    gap: 5px;\n  }\n  .workflow-module {\n    min-height: 26px;\n  }\n  .workflow-queue small {\n    display: none;\n  }\n}\n@media (max-width: 760px) {\n  .workflow-cards {\n    grid-template-columns: 1fr;\n    gap: 16px;\n  }\n  .workflow-card {\n    padding: 24px;\n  }\n  .workflow-card-heading p {\n    min-height: 0;\n  }\n  .workflow-preview {\n    min-height: 180px;\n  }\n  .workflow-module,\n  .workflow-queue li {\n    font-size: 12px;\n  }\n  .workflow-queue small {\n    font-size: 10px;\n  }\n}\n@media (max-width: 380px) {\n  .workflow-card {\n    padding: 18px;\n  }\n  .workflow-preview {\n    padding: 10px;\n  }\n  .workflow-module {\n    gap: 4px;\n    font-size: 10px;\n  }\n  .workflow-queue li {\n    font-size: 11px;\n  }\n  .workflow-queue small {\n    display: none;\n  }\n}\n"
    },
    {
      "path": "tests/agent-controller.test.mjs",
      "url": "source/files/tests/agent-controller.test.mjs.txt",
      "bytes": 5147,
      "sha256": "b3f96d714f384686e89a97208205bc599d701c7c8478922047927bb53094678c",
      "content": "import test from \"node:test\";\nimport assert from \"node:assert/strict\";\nimport { initializeAgent } from \"../src/scripts/agent.js\";\n\nfunction eventTarget(extra = {}) {\n  const listeners = new Map();\n  return {\n    ...extra,\n    addEventListener: (key, fn) => listeners.set(key, fn),\n    removeEventListener: (key) => listeners.delete(key),\n    emit: (key, event = {}) => listeners.get(key)?.(event),\n  };\n}\n\nfunction fixture(search = \"\", reduced = false) {\n  let intersection;\n  let serial = 0;\n  let disconnected = false;\n  const frames = new Map();\n  const replay = eventTarget({ disabled: false });\n  const announcement = { textContent: \"\" };\n  const fields = [1, 1, 2, 2, 2, 2, 2, 2, 3].map((group) => ({\n    dataset: { agentField: String(group) },\n  }));\n  const slots = new Map(\n    [\"assignment\", \"queue-note\", \"status\"].map((name) => [\n      `[data-agent-${name}]`,\n      { textContent: \"\" },\n    ]),\n  );\n  const root = {\n    dataset: {},\n    parentElement: {\n      querySelector: (selector) =>\n        selector === \"[data-agent-replay]\" ? replay : announcement,\n    },\n    querySelector: (selector) =>\n      selector === \"[data-agent-replay]\" ? replay : slots.get(selector),\n    querySelectorAll: () => fields,\n  };\n  const media = eventTarget({ matches: reduced });\n  const document = eventTarget({ hidden: false });\n  const env = {\n    location: { search },\n    innerHeight: 800,\n    document,\n    matchMedia: () => media,\n    requestAnimationFrame: (callback) => {\n      frames.set(++serial, callback);\n      return serial;\n    },\n    cancelAnimationFrame: (id) => frames.delete(id),\n    IntersectionObserver: class {\n      constructor(callback) {\n        intersection = callback;\n      }\n      observe() {}\n      disconnect() {\n        disconnected = true;\n      }\n    },\n  };\n  const dispose = initializeAgent(root, env);\n  return {\n    root,\n    replay,\n    announcement,\n    fields,\n    slots,\n    media,\n    document,\n    dispose,\n    frames: () => frames.size,\n    disconnected: () => disconnected,\n    visible(height = 600, shown = 600) {\n      intersection([\n        {\n          isIntersecting: shown > 0,\n          boundingClientRect: { height },\n          intersectionRect: { height: shown },\n        },\n      ]);\n    },\n    tick(time) {\n      const item = frames.entries().next().value;\n      if (item) {\n        frames.delete(item[0]);\n        item[1](time);\n      }\n    },\n  };\n}\n\ntest(\"controller renders grouped fields once, pauses offscreen/hidden, and replays\", () => {\n  const app = fixture();\n  assert.equal(app.root.dataset.agentPhase, \"queued\");\n  assert.equal(app.frames(), 0);\n  assert.ok(app.fields.every((field) => field.dataset.filled === \"false\"));\n  app.visible();\n  app.tick(0);\n  app.tick(800);\n  assert.equal(app.root.dataset.agentPhase, \"assigned\");\n  app.visible(600, 200);\n  assert.equal(app.frames(), 0);\n  app.tick(9000);\n  app.visible();\n  app.tick(10000);\n  app.tick(10900);\n  assert.equal(app.root.dataset.agentPhase, \"filling\");\n  assert.equal(\n    app.fields.filter((field) => field.dataset.filled === \"true\").length,\n    2,\n  );\n  app.document.hidden = true;\n  app.document.emit(\"visibilitychange\");\n  assert.equal(app.frames(), 0);\n  app.document.hidden = false;\n  app.document.emit(\"visibilitychange\");\n  app.tick(50000);\n  app.tick(51100);\n  assert.equal(\n    app.fields.filter((field) => field.dataset.filled === \"true\").length,\n    8,\n  );\n  app.tick(52100);\n  assert.ok(app.fields.every((field) => field.dataset.filled === \"true\"));\n  app.tick(53300);\n  assert.equal(app.root.dataset.agentPhase, \"review\");\n  assert.equal(app.frames(), 0);\n  assert.equal(app.replay.disabled, false);\n  app.visible(600, 0);\n  app.visible();\n  assert.equal(\n    app.frames(),\n    0,\n    \"completed animation does not restart on reentry\",\n  );\n  app.replay.emit(\"click\");\n  assert.equal(app.root.dataset.agentPhase, \"queued\");\n  assert.equal(app.frames(), 1);\n  app.dispose();\n  assert.equal(app.frames(), 0);\n  assert.equal(app.disconnected(), true);\n});\n\ntest(\"capture states remain fixed and replay cannot trigger animation\", () => {\n  for (const phase of [\"queued\", \"assigned\", \"filling\", \"review\"]) {\n    const app = fixture(`?capture=1&phase=${phase}`);\n    app.visible();\n    app.replay.emit(\"click\");\n    app.tick(10000);\n    assert.equal(app.root.dataset.agentPhase, phase);\n    assert.equal(app.frames(), 0);\n    assert.equal(app.replay.disabled, true);\n    app.dispose();\n  }\n});\n\ntest(\"reduced motion is settled on load and when preference changes during playback\", () => {\n  const reduced = fixture(\"\", true);\n  assert.equal(reduced.root.dataset.agentPhase, \"review\");\n  reduced.visible();\n  assert.equal(reduced.frames(), 0);\n  reduced.dispose();\n  const app = fixture();\n  app.visible(1100, 399);\n  assert.equal(app.frames(), 0);\n  app.visible(1100, 400);\n  app.tick(0);\n  app.tick(1800);\n  app.media.emit(\"change\", { matches: false });\n  assert.equal(app.root.dataset.agentPhase, \"filling\");\n  app.media.emit(\"change\", { matches: true });\n  assert.equal(app.root.dataset.agentPhase, \"review\");\n  assert.equal(app.frames(), 0);\n  assert.equal(app.replay.disabled, true);\n  app.dispose();\n});\n"
    },
    {
      "path": "tests/agent-state.test.mjs",
      "url": "source/files/tests/agent-state.test.mjs.txt",
      "bytes": 2876,
      "sha256": "61b591e6dcf0f0aaf3800f21ed11166e6a4300e5a38fa02b997bd08f3ea22c9e",
      "content": "import test from \"node:test\";\nimport assert from \"node:assert/strict\";\nimport {\n  createAgentState,\n  advanceAgent,\n  replayAgent,\n  describeAgent,\n  eligibleAgentVisibility,\n} from \"../src/scripts/agent-state.mjs\";\n\ntest(\"agent progresses through grouped fields and stops at review\", () => {\n  const queued = createAgentState(\"\");\n  assert.equal(describeAgent(queued).phase, \"queued\");\n  const assigned = advanceAgent(queued, 800, true);\n  assert.equal(describeAgent(assigned).phase, \"assigned\");\n  const filling = advanceAgent(assigned, 900, true);\n  assert.equal(describeAgent(filling).phase, \"filling\");\n  assert.equal(describeAgent(filling).groups, 1);\n  assert.equal(describeAgent(advanceAgent(filling, 1100, true)).groups, 2);\n  assert.equal(describeAgent(advanceAgent(filling, 2100, true)).groups, 3);\n  const done = advanceAgent(filling, 9999, true);\n  assert.deepEqual(describeAgent(done), { phase: \"review\", groups: 3 });\n  assert.equal(done.elapsed, 5000);\n  assert.deepEqual(advanceAgent(done, 500, true), done);\n  assert.equal(queued.elapsed, 0);\n});\n\ntest(\"offscreen and hidden states do not consume elapsed time; replay resets\", () => {\n  const running = advanceAgent(createAgentState(\"\"), 1700, true);\n  assert.deepEqual(advanceAgent(running, 3000, false), running);\n  assert.deepEqual(advanceAgent(running, -1, true), running);\n  assert.deepEqual(advanceAgent(running, NaN, true), running);\n  assert.deepEqual(advanceAgent(running, Infinity, true), running);\n  assert.equal(replayAgent(running).elapsed, 0);\n});\n\ntest(\"capture accepts deterministic phases, ignores invalid phases and cannot replay\", () => {\n  for (const phase of [\"queued\", \"assigned\", \"filling\", \"review\"]) {\n    const state = createAgentState(\"?capture=1&phase=\" + phase);\n    assert.equal(describeAgent(state).phase, phase);\n    assert.deepEqual(advanceAgent(state, 9000, true), state);\n    assert.deepEqual(replayAgent(state), state);\n  }\n  assert.equal(\n    describeAgent(createAgentState(\"?capture=1&phase=bad\")).phase,\n    \"review\",\n  );\n  assert.equal(describeAgent(createAgentState(\"?capture=1\")).phase, \"review\");\n  assert.equal(\n    describeAgent(createAgentState(\"?phase=review\")).phase,\n    \"queued\",\n  );\n});\n\ntest(\"reduced motion is a settled review even when capture phase is specified\", () => {\n  const state = createAgentState(\"?capture=1&phase=queued\", true);\n  assert.equal(describeAgent(state).phase, \"review\");\n  assert.deepEqual(replayAgent(state), state);\n});\n\ntest(\"visibility threshold is half the stage or viewport for tall mobile layouts\", () => {\n  assert.equal(eligibleAgentVisibility(600, 299, 900), false);\n  assert.equal(eligibleAgentVisibility(600, 300, 900), true);\n  assert.equal(eligibleAgentVisibility(1100, 400, 800), true);\n  assert.equal(eligibleAgentVisibility(1100, 399, 800), false);\n  assert.equal(eligibleAgentVisibility(0, 0, 800), false);\n});\n"
    },
    {
      "path": "tests/build.test.mjs",
      "url": "source/files/tests/build.test.mjs.txt",
      "bytes": 2348,
      "sha256": "f4cb850165331d1877b21662625a8f3d8fac2948211b6fd2c23d9eb3601a80f6",
      "content": "import { mkdtemp, rm } from \"node:fs/promises\";\nimport { tmpdir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\nimport { build } from \"../scripts/build.mjs\";\nimport test from \"node:test\";\nimport assert from \"node:assert/strict\";\nimport { readFile, readdir } from \"node:fs/promises\";\nimport { fileURLToPath } from \"node:url\";\n\nconst root = fileURLToPath(new URL(\"../\", import.meta.url));\ntest(\"production output contains every composed section and only runtime assets\", async (t) => {\n  const output = await mkdtemp(join(tmpdir(), \"dualentry-build-\"));\n  t.after(() => rm(output, { recursive: true, force: true }));\n  const generated = pathToFileURL(output + \"/\");\n  await build(output);\n  const html = await readFile(new URL(\"index.html\", generated), \"utf8\");\n  const sections = [...html.matchAll(/data-capture-section=\"([^\"]+)\"/g)].map(\n    (x) => x[1],\n  );\n  assert.deepEqual(sections, [\n    \"hero\",\n    \"workflow\",\n    \"video\",\n    \"selector\",\n    \"agent\",\n    \"prepared\",\n    \"context\",\n    \"progression\",\n    \"stats\",\n    \"modules\",\n    \"closing\",\n  ]);\n  assert.ok(!html.includes('class=\"eyebrow\"'));\n  assert.ok(!html.includes(\"data-view-choice\"));\n  assert.ok(!html.includes(\"data-step-choice\"));\n  const ids = [...html.matchAll(/\\sid=\"([^\"]+)\"/g)].map((x) => x[1]);\n  assert.equal(\n    new Set(ids).size,\n    ids.length,\n    \"IDs must be unique after composition\",\n  );\n  for (const match of html.matchAll(/(?:src|href)=\"([^\"#]+)\"/g)) {\n    if (!match[1].startsWith(\"http\"))\n      await readFile(\n        new URL(\n          match[1].endsWith(\"/\") ? match[1] + \"index.html\" : match[1],\n          generated,\n        ),\n      );\n  }\n  const files = await readdir(generated);\n  for (const unwanted of [\n    \"sections\",\n    \"tests\",\n    \"captures\",\n    \"README.md\",\n    \".vercel\",\n  ])\n    assert.ok(!files.includes(unwanted));\n  assert.ok(!html.includes(\"<!-- SECTIONS -->\"));\n  for (const file of files.filter((name) => name.endsWith(\".css\"))) {\n    const css = await readFile(new URL(file, generated), \"utf8\");\n    assert.equal(\n      (css.match(/\\/\\*/g) || []).length,\n      (css.match(/\\*\\//g) || []).length,\n      `${file} has unbalanced comments`,\n    );\n    assert.ok(\n      !css.replace(/\\/\\*[\\s\\S]*?\\*\\//g, \"\").includes(\"/*\"),\n      `${file} has an unterminated comment`,\n    );\n  }\n});\n"
    },
    {
      "path": "tests/focus-scenes.test.mjs",
      "url": "source/files/tests/focus-scenes.test.mjs.txt",
      "bytes": 6652,
      "sha256": "6701cc4848185b5e4116d6971fc07436d8e296d43f89e458b747a99d75e91575",
      "content": "import test from \"node:test\";\nimport assert from \"node:assert/strict\";\nimport {\n  chooseFocus,\n  advanceExample,\n  initializeFocusScenes,\n} from \"../src/scripts/scenes-focus.js\";\n\ntest(\"focus has distinct meaningful task content for every supported selection\", () => {\n  const cards = [\"all\", \"approvals\", \"connections\", \"agents\"].map(chooseFocus);\n  assert.equal(new Set(cards.map((card) => card.title)).size, 4);\n  assert.ok(cards.every((card) => card.title && card.source && card.action));\n});\ntest(\"unknown focus safely falls back to all tasks without modifying existing data\", () => {\n  const first = chooseFocus(\"all\");\n  assert.deepEqual(chooseFocus(\"__proto__\"), first);\n  assert.notEqual(chooseFocus(\"all\"), first);\n});\ntest(\"example explicitly cycles pending, reviewed, and a new pending example\", () => {\n  const first = advanceExample(0);\n  assert.equal(first.step, 1);\n  assert.equal(first.status, \"Reviewed\");\n  const second = advanceExample(first.step);\n  assert.equal(second.step, 2);\n  assert.equal(second.status, \"Pending review\");\n  assert.notEqual(second.title, first.title);\n  assert.equal(advanceExample(3).step, 0);\n});\ntest(\"invalid update state recovers to first example\", () => {\n  assert.equal(advanceExample(NaN).step, 0);\n  assert.equal(advanceExample(-2).step, 0);\n  assert.equal(advanceExample(\"1\").step, 0);\n});\n\nfunction element(queries = {}) {\n  return {\n    dataset: {},\n    attributes: {},\n    textContent: \"\",\n    firstChild: { textContent: \"\" },\n    events: {},\n    animations: [],\n    querySelector(selector) {\n      return queries[selector] ?? null;\n    },\n    querySelectorAll(selector) {\n      return queries[selector] ?? [];\n    },\n    setAttribute(key, value) {\n      this.attributes[key] = value;\n    },\n    getAttribute(key) {\n      return this.attributes[key];\n    },\n    addEventListener(key, callback) {\n      this.events[key] = callback;\n    },\n    removeEventListener(key) {\n      delete this.events[key];\n    },\n    animate(frames, options) {\n      this.animations.push({ frames, options });\n      return { cancel() {} };\n    },\n    getAnimations() {\n      return [{ cancel() {} }];\n    },\n  };\n}\n\nfunction illustrationFixture() {\n  const choices = [\"all\", \"approvals\", \"connections\", \"agents\"].map((key) => {\n    const button = element();\n    button.dataset.selChoice = key;\n    button.attributes[\"aria-pressed\"] = String(key === \"approvals\");\n    return button;\n  });\n  const stageFields = Object.fromEntries(\n    [\"source\", \"label\", \"count\", \"title\", \"time\", \"action\", \"icon\"].map(\n      (field) => [`[data-sel-${field}]`, element()],\n    ),\n  );\n  const mainCard = element();\n  const stage = element({ ...stageFields, \".sel-main-card\": mainCard });\n  const selector = element({\n    \"[data-sel-choice]\": choices,\n    \"#selector-stage\": stage,\n  });\n  const controlFields = Object.fromEntries(\n    [\"source\", \"status\", \"title\", \"outcome\"].map((field) => [\n      `[data-control-${field}]`,\n      element(),\n    ]),\n  );\n  const update = element();\n  const approvalCard = element();\n  const controlFrame = element();\n  const control = element({\n    ...controlFields,\n    \"[data-control-update]\": update,\n    \"#control-example\": controlFrame,\n    \".control-approval-card\": approvalCard,\n  });\n  const document = {\n    documentElement: { dataset: {} },\n    getElementById: (id) => ({ selector, control })[id],\n  };\n  return {\n    document,\n    choices,\n    stage,\n    stageFields,\n    mainCard,\n    controlFrame,\n    controlFields,\n    update,\n    approvalCard,\n  };\n}\n\ntest(\"bound selection updates accessible state, task content, and only pointer motion\", async () => {\n  const fixture = illustrationFixture();\n  const originalDocument = globalThis.document;\n  const originalMatch = globalThis.matchMedia;\n  let reducedMotion = false;\n  globalThis.document = fixture.document;\n  globalThis.matchMedia = () => ({\n    get matches() {\n      return reducedMotion;\n    },\n    addEventListener() {},\n    removeEventListener() {},\n  });\n  try {\n    const dispose = initializeFocusScenes(fixture.document, {\n      matchMedia: globalThis.matchMedia,\n    });\n    fixture.choices[2].events.click({ detail: 1 });\n    assert.equal(fixture.choices[2].attributes[\"aria-pressed\"], \"true\");\n    assert.equal(fixture.choices[1].attributes[\"aria-pressed\"], \"false\");\n    assert.equal(\n      fixture.stageFields[\"[data-sel-title]\"].textContent,\n      \"Reconnect to see recent transactions\",\n    );\n    assert.equal(\n      fixture.stageFields[\"[data-sel-icon]\"].attributes.href,\n      \"#i-sync\",\n    );\n    assert.equal(fixture.mainCard.animations.length, 1);\n    fixture.choices[2].events.click({ detail: 1 });\n    assert.equal(\n      fixture.mainCard.animations.length,\n      1,\n      \"selecting the same category does not replay motion\",\n    );\n    fixture.choices[3].events.click({ detail: 0 });\n    assert.equal(fixture.stage.dataset.focus, \"agents\");\n    assert.equal(\n      fixture.mainCard.animations.length,\n      1,\n      \"keyboard activation settles immediately\",\n    );\n    fixture.document.documentElement.dataset.capture = \"true\";\n    fixture.choices[0].events.click({ detail: 1 });\n    assert.equal(\n      fixture.mainCard.animations.length,\n      1,\n      \"capture mode suppresses motion\",\n    );\n    fixture.document.documentElement.dataset.capture = \"false\";\n    reducedMotion = true;\n    fixture.choices[1].events.click({ detail: 1 });\n    assert.equal(\n      fixture.mainCard.animations.length,\n      1,\n      \"reduced motion suppresses motion\",\n    );\n    fixture.update.events.click({ detail: 0 });\n    assert.equal(fixture.controlFrame.dataset.reviewState, \"reviewed\");\n    assert.equal(\n      fixture.controlFields[\"[data-control-status]\"].textContent,\n      \"Reviewed\",\n    );\n    assert.equal(fixture.update.firstChild.textContent, \"Next\");\n    fixture.update.events.click({ detail: 1 });\n    assert.equal(fixture.controlFrame.dataset.reviewState, \"pending\");\n    assert.equal(\n      fixture.controlFields[\"[data-control-source]\"].textContent,\n      \"Daily activity\",\n    );\n    assert.equal(fixture.approvalCard.animations.length, 0);\n    reducedMotion = false;\n    fixture.update.events.click({ detail: 1 });\n    assert.equal(fixture.approvalCard.animations.length, 1);\n    fixture.update.events.click({ detail: 1 });\n    assert.equal(\n      fixture.controlFields[\"[data-control-source]\"].textContent,\n      \"Bank Recommendations\",\n    );\n    dispose();\n    assert.equal(fixture.update.events.click, undefined);\n    assert.ok(fixture.choices.every((button) => !button.events.click));\n  } finally {\n    globalThis.document = originalDocument;\n    globalThis.matchMedia = originalMatch;\n  }\n});\n"
    },
    {
      "path": "tests/portability.test.mjs",
      "url": "source/files/tests/portability.test.mjs.txt",
      "bytes": 1629,
      "sha256": "d2b0d49d50056b0b1b63bbd8da3aaf840a7bf79bbc7c270c2ad7dc888424c722",
      "content": "import { mkdtemp, rm } from \"node:fs/promises\";\nimport { tmpdir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\nimport { build } from \"../scripts/build.mjs\";\nimport test from \"node:test\";\nimport assert from \"node:assert/strict\";\nimport { readFile, readdir } from \"node:fs/promises\";\nconst root = new URL(\"../\", import.meta.url);\ntest(\"portable build isolates runtime output and preserves authored source\", async (t) => {\n  const before = await readFile(new URL(\"src/page.html\", root), \"utf8\");\n  const output = await mkdtemp(join(tmpdir(), \"dualentry-build-\"));\n  t.after(() => rm(output, { recursive: true, force: true }));\n  const generated = pathToFileURL(output + \"/\");\n  await build(output);\n  assert.equal(await readFile(new URL(\"src/page.html\", root), \"utf8\"), before);\n  const html = await readFile(new URL(\"index.html\", generated), \"utf8\");\n  assert.equal((html.match(/rel=\"stylesheet\"/g) || []).length, 1);\n  assert.equal((html.match(/<script /g) || []).length, 1);\n  assert.ok(html.includes(\"scripts/main.js\"));\n  for (const text of [\n    \"Less searching.\",\n    \"One connected workflow.\",\n    \"The source. The work. The next step.\",\n    \"Example workflow ·\",\n    \"Stay focused.\",\n    \"01 / Work comes together\",\n  ])\n    assert.ok(!html.includes(text), text);\n  for (const path of [\n    \"src\",\n    \"tests\",\n    \"captures\",\n    \"node_modules\",\n    \"package.json\",\n    \".vercel\",\n    \"build.mjs\",\n  ])\n    assert.ok(!(await readdir(generated)).includes(path));\n  assert.ok(html.includes('data-capture-section=\"video\"'));\n  assert.ok(html.includes('id=\"video-title\"'));\n});\n"
    },
    {
      "path": "tests/reference-layout.test.mjs",
      "url": "source/files/tests/reference-layout.test.mjs.txt",
      "bytes": 1271,
      "sha256": "06346c6983904964ee9841c736fca4c8d1d56d7425922b9ff020cce25164c5d8",
      "content": "import test from \"node:test\";\nimport assert from \"node:assert/strict\";\nimport { readFile } from \"node:fs/promises\";\nimport { sectionOrder } from \"../src/scripts/section-order.mjs\";\nconst read = (name) =>\n  readFile(\n    new URL(\"../src/sections/\" + name + \".html\", import.meta.url),\n    \"utf8\",\n  );\ntest(\"reference layout keeps the requested sequence and puts hero actions above its board\", async () => {\n  assert.deepEqual(sectionOrder, [\n    \"hero\",\n    \"workflow\",\n    \"video\",\n    \"selector\",\n    \"agent\",\n    \"prepared\",\n    \"context\",\n    \"progression\",\n    \"stats\",\n    \"modules\",\n    \"closing\",\n  ]);\n  const hero = await read(\"hero\");\n  assert.ok(hero.indexOf(\"splash-actions\") < hero.indexOf(\"splash-screen\"));\n  const video = await read(\"video\");\n  assert.ok(video.includes(\"Insert video here\"));\n  assert.ok(!video.includes(\"<iframe\"));\n  const stats = await read(\"stats\");\n  for (const value of [\n    \"90\",\n    \"95\",\n    \"$0\",\n    \"/customers/slash\",\n    \"/customers/graphite\",\n  ])\n    assert.ok(stats.includes(value));\n  assert.ok(!stats.includes(\"task-card\"));\n  const workflow = await read(\"workflow\");\n  for (const text of [\n    \"A scavenger hunt across modules\",\n    \"Scattered\",\n    \"Self-resolving\",\n  ])\n    assert.ok(workflow.includes(text));\n});\n"
    },
    {
      "path": "tests/runtime-controllers.test.mjs",
      "url": "source/files/tests/runtime-controllers.test.mjs.txt",
      "bytes": 9249,
      "sha256": "b5b344d5d53fb2745a4c21da98445ed8964b9f5374f80028e1ef36366a6365b6",
      "content": "import test from \"node:test\";\nimport assert from \"node:assert/strict\";\nimport { initializeInteractions } from \"../src/scripts/interactions.js\";\nimport { initializeFlowScenes } from \"../src/scripts/scenes-flow.js\";\nimport { applyCapture, initializePage } from \"../src/scripts/main.js\";\n\nfunction node(queries = {}) {\n  const listeners = new Map();\n  const classes = new Set();\n  return {\n    dataset: {},\n    attributes: {},\n    queries,\n    animations: [],\n    textContent: \"\",\n    focused: false,\n    classList: {\n      toggle(key, on) {\n        if (on) classes.add(key);\n        else classes.delete(key);\n      },\n      contains: (key) => classes.has(key),\n    },\n    querySelector(selector) {\n      return this.queries[selector] ?? null;\n    },\n    querySelectorAll(selector) {\n      return this.queries[selector] ?? [];\n    },\n    getElementById(id) {\n      return this.queries[id] ?? null;\n    },\n    getAttribute(key) {\n      return this.attributes[key];\n    },\n    setAttribute(key, value) {\n      this.attributes[key] = value;\n    },\n    addEventListener(key, fn) {\n      listeners.set(key, [...(listeners.get(key) ?? []), fn]);\n    },\n    removeEventListener(key, fn) {\n      listeners.set(\n        key,\n        (listeners.get(key) ?? []).filter((item) => item !== fn),\n      );\n    },\n    emit(key, event = {}) {\n      (listeners.get(key) ?? []).forEach((fn) => fn(event));\n    },\n    listenerCount() {\n      return [...listeners.values()].reduce(\n        (sum, list) => sum + list.length,\n        0,\n      );\n    },\n    focus() {\n      this.focused = true;\n    },\n    getAnimations() {\n      return this.animations;\n    },\n    animate() {\n      const item = {\n        cancelled: false,\n        cancel() {\n          this.cancelled = true;\n        },\n        finished: Promise.resolve(),\n      };\n      this.animations.push(item);\n      return item;\n    },\n    getBoundingClientRect() {\n      return { left: 0, top: 0, width: 200, height: 120 };\n    },\n    prepend(card) {\n      this.card = card;\n    },\n  };\n}\nfunction environment(document, search = \"\") {\n  const media = node();\n  media.matches = false;\n  document.documentElement = { dataset: {} };\n  return { document, location: { search }, matchMedia: () => media, media };\n}\nfunction button(attribute, value) {\n  const item = node();\n  item.setAttribute(attribute, value);\n  return item;\n}\n\ntest(\"filter, context, and navigation retain keyboard state and detach listeners\", () => {\n  const filterButtons = [\"all\", \"waiting\", \"connections\"].map((value) =>\n    button(\"data-filter-choice\", value),\n  );\n  const contextButtons = [\"source\", \"work\", \"action\"].map((value) =>\n    button(\"data-context-choice\", value),\n  );\n  const rows = [\"waiting\", \"connections\", \"waiting\"].map((kind) => {\n    const item = node();\n    item.dataset.taskKind = kind;\n    return item;\n  });\n  const filter = node({ \"[data-task-kind]\": rows });\n  filter.querySelectorAll = (selector) =>\n    selector.endsWith(\":not(.is-muted)\")\n      ? rows.filter((row) => !row.classList.contains(\"is-muted\"))\n      : rows;\n  const summary = node();\n  const menu = node({ summary });\n  const toggle = node();\n  const nav = node();\n  const context = node();\n  const label = node();\n  const count = node();\n  const document = node({\n    \"[data-filter-choice]\": filterButtons,\n    \"[data-context-choice]\": contextButtons,\n    \"filter-demo\": filter,\n    \"context-demo\": context,\n    \"filter-current-label\": label,\n    \"filter-result-count\": count,\n    \"status-menu\": menu,\n    \"[data-menu-toggle]\": toggle,\n    \"site-nav\": nav,\n  });\n  const env = environment(document);\n  const dispose = initializeInteractions(document, env);\n  assert.equal(filter.dataset.filter, \"waiting\");\n  filterButtons[0].emit(\"click\", { detail: 0 });\n  filterButtons[1].emit(\"click\", { detail: 1 });\n  assert.equal(count.textContent, \"2 tasks in focus\");\n  assert.equal(label.textContent, \"Waiting on you\");\n  assert.equal(filter.animations.length, 1);\n  assert.equal(summary.focused, true);\n  menu.open = true;\n  filterButtons[1].emit(\"click\", { detail: 1 });\n  assert.equal(menu.open, false);\n  contextButtons[1].emit(\"click\", { detail: 0 });\n  assert.equal(context.dataset.context, \"work\");\n  assert.equal(context.animations.length, 0);\n  toggle.emit(\"click\");\n  assert.equal(toggle.getAttribute(\"aria-expanded\"), \"true\");\n  document.emit(\"keydown\", { key: \"x\" });\n  assert.equal(nav.classList.contains(\"is-open\"), true);\n  document.emit(\"keydown\", { key: \"Escape\" });\n  assert.equal(toggle.focused, true);\n  toggle.emit(\"click\");\n  nav.emit(\"click\", { target: { closest: () => null } });\n  assert.equal(toggle.getAttribute(\"aria-expanded\"), \"true\");\n  nav.emit(\"click\", { target: { closest: () => ({}) } });\n  assert.equal(toggle.getAttribute(\"aria-expanded\"), \"false\");\n  menu.open = true;\n  document.emit(\"keydown\", { key: \"Escape\" });\n  assert.equal(menu.open, false);\n  env.media.matches = true;\n  env.media.emit(\"change\");\n  assert.equal(filter.animations[0].cancelled, true);\n  filterButtons[2].emit(\"click\", { detail: 1 });\n  assert.equal(filter.animations.length, 1);\n  dispose();\n  assert.equal(document.listenerCount(), 0);\n  assert.ok(\n    [...filterButtons, ...contextButtons, toggle, nav].every(\n      (item) => item.listenerCount() === 0,\n    ),\n  );\n});\n\ntest(\"panorama moves, resets, announces status, and cleans up; progression stays selectable\", () => {\n  const controls = [\"all\", \"waiting\", \"invalid\"].map((value) => {\n    const item = node();\n    item.dataset.panoChoice = value;\n    return item;\n  });\n  const progressButtons = [\"see\", \"review\", \"move\", \"invalid\"].map((value) => {\n    const item = node();\n    item.dataset.progressChoice = value;\n    return item;\n  });\n  const progress = node({ \"[data-progress-choice]\": progressButtons });\n  const move = node();\n  const card = node();\n  const done = node();\n  const waiting = node();\n  const viewport = node();\n  viewport.scrollWidth = 800;\n  viewport.clientWidth = 200;\n  viewport.scrollLeft = 0;\n  const column = node();\n  column.getBoundingClientRect = () => ({ left: 250 });\n  const fields = Object.fromEntries(\n    [\n      '[data-pano-count=\"waiting\"]',\n      '[data-pano-count=\"control\"]',\n      '[data-pano-count=\"done\"]',\n      \"[data-pano-button-label]\",\n      \"[data-pano-task-title]\",\n      \"[data-pano-task-badge]\",\n      \"[data-pano-status]\",\n      \"[data-pano-empty]\",\n    ].map((key) => [key, node()]),\n  );\n  const panorama = node({\n    ...fields,\n    \"[data-pano-choice]\": controls,\n    \"[data-pano-move]\": move,\n    \"#pano-moving-task\": card,\n    '[data-pano-destination=\"done\"]': done,\n    '[data-pano-destination=\"waiting\"]': waiting,\n    \".pano-scroll\": viewport,\n    \".pano-col-done\": column,\n    \".pano-col-waiting\": column,\n    \".pano-col-todo\": column,\n  });\n  panorama.dataset.panoState = \"waiting\";\n  const document = node({\n    \"[data-progress-stage]\": [progress],\n    \"[data-pano-state]\": [panorama],\n  });\n  const env = environment(document);\n  const dispose = initializeFlowScenes(document, env);\n  controls[1].emit(\"click\", { detail: 1 });\n  assert.equal(panorama.dataset.panoFocus, \"waiting\");\n  controls[2].emit(\"click\", { detail: 1 });\n  assert.equal(panorama.dataset.panoFocus, \"waiting\");\n  move.emit(\"click\", { detail: 1 });\n  assert.equal(done.card, card);\n  assert.equal(panorama.dataset.panoState, \"done\");\n  assert.equal(fields['[data-pano-count=\"done\"]'].textContent, \"2\");\n  assert.match(fields[\"[data-pano-status]\"].textContent, /moved to Done/);\n  assert.equal(card.animations.length, 1);\n  move.emit(\"click\", { detail: 0 });\n  assert.equal(waiting.card, card);\n  assert.equal(fields[\"[data-pano-empty]\"].hidden, true);\n  assert.equal(card.animations.length, 1);\n  progressButtons[1].emit(\"click\", { detail: 0 });\n  assert.equal(progress.dataset.progressStage, \"review\");\n  assert.equal(progress.dataset.flowMotion, \"false\");\n  progressButtons[3].emit(\"click\", { detail: 1 });\n  assert.equal(progress.dataset.progressStage, \"review\");\n  document.documentElement.dataset.capture = \"true\";\n  progressButtons[2].emit(\"click\", { detail: 1 });\n  assert.equal(progress.dataset.flowMotion, \"false\");\n  viewport.scrollWidth = 100;\n  controls[0].emit(\"click\", { detail: 1 });\n  panorama.queries[\"#pano-moving-task\"] = null;\n  move.emit(\"click\", { detail: 1 });\n  dispose();\n  assert.equal(move.listenerCount(), 0);\n  assert.ok(\n    [...controls, ...progressButtons].every(\n      (item) => item.listenerCount() === 0,\n    ),\n  );\n});\n\ntest(\"capture is applied before optional scenes initialize and an empty page disposes safely\", () => {\n  const hero = node();\n  hero.dataset.captureSection = \"hero\";\n  const agent = node();\n  agent.dataset.captureSection = \"agent\";\n  const document = node({ \"[data-capture-section]\": [hero, agent] });\n  const env = environment(document, \"?capture=1&section=agent\");\n  const dispose = initializePage(document, env);\n  assert.equal(document.documentElement.dataset.capture, \"true\");\n  assert.equal(hero.hidden, true);\n  assert.equal(agent.hidden, false);\n  dispose();\n  assert.equal(document.listenerCount(), 0);\n  assert.equal(env.media.listenerCount(), 0);\n  const ordinary = node();\n  environment(ordinary);\n  applyCapture(ordinary, \"\");\n  assert.deepEqual(ordinary.documentElement.dataset, {});\n});\n"
    },
    {
      "path": "tests/source-export.test.mjs",
      "url": "source/files/tests/source-export.test.mjs.txt",
      "bytes": 3679,
      "sha256": "de1b9f18d78bcdea33bb1fffcf0b03c8183a187ac984bd0e3cf29474b4513e0c",
      "content": "import assert from \"node:assert/strict\";\nimport { createHash } from \"node:crypto\";\nimport {\n  mkdir,\n  mkdtemp,\n  readFile,\n  rm,\n  symlink,\n  writeFile,\n} from \"node:fs/promises\";\nimport { tmpdir } from \"node:os\";\nimport { join } from \"node:path\";\nimport test from \"node:test\";\nimport { publishSource } from \"../scripts/publish-source.mjs\";\n\nasync function fixture(t) {\n  const root = await mkdtemp(join(tmpdir(), \"source-export-\"));\n  t.after(() => rm(root, { recursive: true, force: true }));\n  for (const folder of [\"src\", \"scripts\", \"tests\", \"assets\", \".vercel\", \"dist\"])\n    await mkdir(join(root, folder));\n  await writeFile(\n    join(root, \"src/page.html\"),\n    '<main title=\"example\">Hello & goodbye</main>',\n  );\n  await writeFile(\n    join(root, \"scripts/build.mjs\"),\n    \"export const build = true;\\n\",\n  );\n  await writeFile(join(root, \"tests/example.test.mjs\"), \"// Portable test\\n\");\n  await writeFile(join(root, \"assets/logo.svg\"), \"<svg></svg>\");\n  await writeFile(join(root, \"package.json\"), '{\"private\":true}');\n  await writeFile(join(root, \"README.md\"), \"# Setup\\n\");\n  await writeFile(join(root, \".env\"), \"PRIVATE=never-export\");\n  await writeFile(join(root, \".vercel/project.json\"), \"private-project\");\n  await writeFile(join(root, \"src/.env\"), \"PRIVATE=never-export\");\n  await writeFile(join(root, \"dist/old.js\"), \"old-output\");\n  return root;\n}\n\ntest(\"source publication exposes portable text and local asset hashes only\", async (t) => {\n  const root = await fixture(t);\n  await symlink(join(root, \".env\"), join(root, \"src/linked.js\"));\n  const destination = join(root, \"dist\");\n  await publishSource(root, destination);\n  const manifest = JSON.parse(\n    await readFile(join(destination, \"source/manifest.json\")),\n  );\n  const bundle = JSON.parse(\n    await readFile(join(destination, \"source/bundle.json\")),\n  );\n  assert.equal(manifest.version, 1);\n  assert.deepEqual(\n    manifest.files.map(({ path }) => path),\n    [\n      \"README.md\",\n      \"package.json\",\n      \"scripts/build.mjs\",\n      \"src/page.html\",\n      \"tests/example.test.mjs\",\n    ],\n  );\n  for (const entry of manifest.files) {\n    const raw = await readFile(join(destination, entry.url));\n    assert.equal(entry.bytes, raw.length);\n    assert.equal(entry.sha256, createHash(\"sha256\").update(raw).digest(\"hex\"));\n    assert.equal(\n      bundle.files.find(({ path }) => path === entry.path).content,\n      raw.toString(\"utf8\"),\n    );\n  }\n  assert.equal(manifest.assets[0].url, \"assets/logo.svg\");\n  assert.deepEqual(bundle.assets, manifest.assets);\n  const index = await readFile(join(destination, \"source/index.html\"), \"utf8\");\n  assert.ok(index.includes(\"&lt;main title=&quot;example&quot;&gt;\"));\n  assert.ok(index.includes(\"Hello &amp; goodbye\"));\n  assert.ok(!index.includes(\"<main title=\"));\n  for (const secret of [\"never-export\", \"private-project\", \"old-output\", root])\n    assert.ok(!JSON.stringify(bundle).includes(secret));\n});\n\ntest(\"source publication refuses machine-specific paths in publishable text\", async (t) => {\n  const root = await fixture(t);\n  await writeFile(\n    join(root, \"src/local.js\"),\n    `const file = '${\"/\" + \"Users/\"}someone/private';`,\n  );\n  await assert.rejects(\n    publishSource(root, join(root, \"dist\")),\n    /machine-specific path.*src\\/local.js/i,\n  );\n});\n\ntest(\"allowlisted roots cannot follow a symlink into private files\", async (t) => {\n  const root = await fixture(t);\n  await rm(join(root, \"scripts\"), { recursive: true });\n  await symlink(join(root, \".vercel\"), join(root, \"scripts\"));\n  const manifest = await publishSource(root, join(root, \"dist\"));\n  assert.ok(!manifest.files.some(({ path }) => path.startsWith(\"scripts/\")));\n});\n"
    },
    {
      "path": "tests/splash-motion-controller.test.mjs",
      "url": "source/files/tests/splash-motion-controller.test.mjs.txt",
      "bytes": 7172,
      "sha256": "84a68ec96362e8f6c2edc2d0e801ae03a9b6dcc92cb99da54ea678a4b43d2415",
      "content": "import test from \"node:test\";\nimport assert from \"node:assert/strict\";\nimport { initializeSplash } from \"../src/scripts/splash-motion.js\";\n\nfunction target(extra = {}) {\n  const listeners = new Map();\n  return {\n    ...extra,\n    addEventListener: (name, fn) => listeners.set(name, fn),\n    removeEventListener: (name) => listeners.delete(name),\n    emit: (name, event = {}) => listeners.get(name)?.(event),\n  };\n}\n\nfunction fixture(search = \"\", reduced = false, compact = false) {\n  let intersection, resize;\n  let serial = 0;\n  const frames = new Map();\n  const rect = (x, y, width, height) => ({\n    x,\n    y,\n    left: x,\n    top: y,\n    width,\n    height,\n  });\n  const node = (bounds) => ({\n    bounds,\n    style: {},\n    textContent: \"\",\n    getBoundingClientRect() {\n      return this.bounds;\n    },\n  });\n  const board = {\n    ...node(rect(100, 100, 1000, 600)),\n    append(...children) {\n      this.children = children;\n    },\n  };\n  const slots = Array.from({ length: 3 }, (_, index) =>\n    node(\n      rect(\n        compact ? 112 : 120 + index * 300,\n        compact ? 124 + index * 180 : 154,\n        compact ? 290 : 250,\n        140,\n      ),\n    ),\n  );\n  const statuses = Array.from({ length: 3 }, () => node());\n  const cards = statuses.map((status, index) => ({\n    ...node(rect(0, 0, 250, 140 + index * 5)),\n    querySelector: () => status,\n  }));\n  const attributes = new Map();\n  const toggle = target({\n    disabled: false,\n    setAttribute: (name, value) => attributes.set(name, value),\n  });\n  const nodes = new Map([\n    [\".kanban\", board],\n    [\".splash-screen\", node()],\n    [\"[data-splash-toggle]\", toggle],\n  ]);\n  const root = {\n    dataset: {},\n    querySelector: (selector) => nodes.get(selector),\n    querySelectorAll: (selector) =>\n      selector === \"[data-splash-card]\" ? cards : slots,\n  };\n  const media = target({ matches: reduced });\n  const document = target({ hidden: false });\n  const env = {\n    location: { search },\n    innerHeight: 800,\n    document,\n    matchMedia: () => media,\n    requestAnimationFrame: (callback) => {\n      frames.set(++serial, callback);\n      return serial;\n    },\n    cancelAnimationFrame: (id) => frames.delete(id),\n    IntersectionObserver: class {\n      constructor(callback) {\n        intersection = callback;\n      }\n      observe() {}\n      disconnect() {}\n    },\n    ResizeObserver: class {\n      constructor(callback) {\n        resize = callback;\n      }\n      observe() {}\n      disconnect() {}\n    },\n  };\n  const dispose = initializeSplash(root, env);\n  return {\n    root,\n    cards,\n    slots,\n    statuses,\n    toggle,\n    attributes,\n    media,\n    document,\n    dispose,\n    frames: () => frames.size,\n    visible(shown = 600) {\n      intersection([\n        {\n          isIntersecting: shown > 0,\n          boundingClientRect: { height: 600 },\n          intersectionRect: { height: shown },\n        },\n      ]);\n    },\n    tick(time) {\n      const item = frames.entries().next().value;\n      if (item) {\n        frames.delete(item[0]);\n        item[1](time);\n      }\n    },\n    resize: () => resize(),\n  };\n}\n\ntest(\"all cards loop continuously, pause offscreen or hidden, and resume without skipped time\", () => {\n  const app = fixture();\n  assert.equal(app.root.dataset.splashPhase, \"queued\");\n  assert.equal(app.frames(), 0);\n  assert.equal(app.cards[0].style.transform, \"translate3d(20px, 54px, 0)\");\n  assert.deepEqual(\n    app.slots.map((slot) => slot.style.height),\n    [\"150px\", \"150px\", \"150px\"],\n  );\n  app.visible();\n  app.tick(0);\n  app.tick(4500);\n  assert.equal(app.root.dataset.splashPhase, \"moving\");\n  const pose = app.cards.map((card) => card.style.transform);\n  app.visible(100);\n  app.tick(10000);\n  assert.equal(app.frames(), 0);\n  assert.deepEqual(\n    app.cards.map((card) => card.style.transform),\n    pose,\n  );\n  app.visible();\n  app.tick(11000);\n  assert.deepEqual(\n    app.cards.map((card) => card.style.transform),\n    pose,\n  );\n  app.document.hidden = true;\n  app.document.emit(\"visibilitychange\");\n  assert.equal(app.frames(), 0);\n  app.document.hidden = false;\n  app.document.emit(\"visibilitychange\");\n  app.tick(50000);\n  app.tick(50700);\n  assert.equal(app.root.dataset.splashPhase, \"review\");\n  assert.equal(app.cards[0].style.transform, \"translate3d(320px, 54px, 0)\");\n  assert.deepEqual(\n    app.statuses.map((status) => status.textContent),\n    [\"In progress\", \"To do\", \"For review\"],\n  );\n  assert.equal(app.frames(), 1);\n  app.tick(81500);\n  assert.equal(app.cards[0].style.transform, \"translate3d(20px, 54px, 0)\");\n  assert.equal(app.frames(), 1);\n  app.dispose();\n  assert.equal(app.frames(), 0);\n});\n\ntest(\"phone cards move between real vertical anchors and remeasure after width changes\", () => {\n  const app = fixture(\"\", false, true);\n  assert.equal(app.root.dataset.splashCompact, \"true\");\n  assert.equal(app.cards[0].style.transform, \"translate3d(12px, 24px, 0)\");\n  app.visible();\n  app.tick(0);\n  app.tick(4500);\n  assert.equal(app.cards[0].style.transform, \"translate3d(18px, 114px, 0)\");\n  app.slots.forEach((slot) => {\n    slot.bounds = { ...slot.bounds, width: 250 };\n  });\n  app.resize();\n  assert.equal(app.cards[0].style.width, \"250px\");\n  app.tick(5200);\n  assert.equal(app.cards[0].style.transform, \"translate3d(12px, 204px, 0)\");\n  assert.equal(app.cards[1].style.transform, \"translate3d(12px, 24px, 0)\");\n  app.dispose();\n});\n\ntest(\"capture and reduced motion lock playback, and switching motion preference back resumes\", () => {\n  for (const phase of [\"queued\", \"moving\", \"review\"]) {\n    const app = fixture(`?capture=1&section=hero&phase=${phase}`);\n    app.visible();\n    app.toggle.emit(\"click\");\n    app.tick(9999);\n    assert.equal(app.root.dataset.splashPhase, phase);\n    assert.equal(app.frames(), 0);\n    assert.equal(app.toggle.disabled, true);\n    app.media.emit(\"change\", { matches: false });\n    assert.equal(app.frames(), 0);\n    app.dispose();\n  }\n  const app = fixture(\"\", true);\n  assert.equal(app.root.dataset.splashPhase, \"review\");\n  app.visible();\n  assert.equal(app.frames(), 0);\n  app.media.emit(\"change\", { matches: false });\n  assert.equal(app.frames(), 1);\n  assert.equal(app.toggle.disabled, false);\n  app.tick(0);\n  app.tick(5000);\n  app.media.emit(\"change\", { matches: true });\n  assert.equal(app.root.dataset.splashPhase, \"review\");\n  assert.equal(app.frames(), 0);\n  assert.equal(app.toggle.disabled, true);\n  app.dispose();\n});\n\ntest(\"accessible pause control freezes in place and preserves user pause across visibility changes\", () => {\n  const app = fixture();\n  app.visible();\n  app.tick(0);\n  app.tick(4500);\n  const pose = app.cards[0].style.transform;\n  app.toggle.emit(\"click\");\n  assert.equal(app.frames(), 0);\n  assert.equal(app.attributes.get(\"aria-label\"), \"Resume task animation\");\n  assert.equal(app.attributes.get(\"aria-pressed\"), \"true\");\n  app.visible(0);\n  app.visible();\n  assert.equal(app.frames(), 0);\n  app.toggle.emit(\"click\");\n  assert.equal(app.attributes.get(\"aria-label\"), \"Pause task animation\");\n  app.tick(20000);\n  assert.equal(app.cards[0].style.transform, pose);\n  app.tick(20700);\n  assert.notEqual(app.cards[0].style.transform, pose);\n  app.dispose();\n});\n"
    },
    {
      "path": "tests/splash-motion-state.test.mjs",
      "url": "source/files/tests/splash-motion-state.test.mjs.txt",
      "bytes": 3442,
      "sha256": "8a2e26d1351f32aaff6c99d793b7eec7e1e8d2206426b89cb718ae6830859080",
      "content": "import test from \"node:test\";\nimport assert from \"node:assert/strict\";\nimport {\n  createSplashState,\n  advanceSplash,\n  setSplashReduced,\n  describeSplash,\n  splashPosition,\n  splashVisible,\n} from \"../src/scripts/splash-motion-state.mjs\";\n\ntest(\"six adjacent swaps return every card to its initial slot without a loop boundary jump\", () => {\n  const initial = Object.freeze(createSplashState());\n  for (let leg = 0; leg < 6; leg++) {\n    const held = describeSplash(\n      advanceSplash(initial, leg * 6000 + 3700, true),\n    );\n    const flight = describeSplash(\n      advanceSplash(initial, leg * 6000 + 4500, true),\n    );\n    const settled = describeSplash(\n      advanceSplash(initial, leg * 6000 + 5300, true),\n    );\n    assert.equal(held.cards.filter((card) => card.progress !== 0).length, 0);\n    assert.equal(\n      flight.cards.filter((card) => card.progress > 0 && card.progress < 1)\n        .length,\n      2,\n    );\n    assert.equal(flight.phase, \"moving\");\n    assert.equal(new Set(settled.cards.map((card) => card.slot)).size, 3);\n    const next = describeSplash(advanceSplash(initial, (leg + 1) * 6000, true));\n    assert.deepEqual(\n      settled.cards.map((card) => card.slot),\n      next.cards.map((card) => card.slot),\n    );\n  }\n  assert.deepEqual(\n    describeSplash(advanceSplash(initial, 36000, true)),\n    describeSplash(initial),\n  );\n  assert.equal(advanceSplash(initial, 36000 * 12 + 1234, true).elapsed, 1234);\n  assert.equal(initial.elapsed, 0);\n});\n\ntest(\"capture phases freeze, unknown phase settles, and reduced motion can resume only outside capture\", () => {\n  for (const phase of [\"queued\", \"moving\", \"review\"]) {\n    const state = createSplashState(`?capture=1&phase=${phase}`);\n    assert.equal(describeSplash(state).phase, phase);\n    assert.deepEqual(advanceSplash(state, 9999, true), state);\n    assert.equal(setSplashReduced(state, false).locked, true);\n  }\n  assert.equal(\n    describeSplash(createSplashState(\"?capture=1&phase=bad\")).phase,\n    \"review\",\n  );\n  assert.equal(describeSplash(createSplashState(\"?capture=1\")).phase, \"review\");\n  assert.equal(\n    describeSplash(createSplashState(\"?phase=review\")).phase,\n    \"queued\",\n  );\n  const reduced = setSplashReduced(createSplashState(), true);\n  assert.equal(describeSplash(reduced).phase, \"review\");\n  assert.equal(reduced.locked, true);\n  assert.equal(setSplashReduced(reduced, false).locked, false);\n});\n\ntest(\"hidden or invalid elapsed time cannot advance playback\", () => {\n  const state = createSplashState();\n  for (const time of [-1, Infinity, NaN])\n    assert.deepEqual(advanceSplash(state, time, true), state);\n  assert.deepEqual(advanceSplash(state, 5000, false), state);\n  assert.equal(splashVisible(800, 300, 600), true);\n  assert.equal(splashVisible(800, 299, 600), false);\n  assert.equal(splashVisible(0, 0, 600), false);\n});\n\ntest(\"actual desktop and vertical phone anchors share exact endpoints and bounded passing movement\", () => {\n  for (const [from, to, compact] of [\n    [{ x: 20, y: 170 }, { x: 620, y: 54 }, false],\n    [{ x: 12, y: 24 }, { x: 12, y: 224 }, true],\n  ]) {\n    assert.deepEqual(splashPosition(0, from, to, compact, 1), from);\n    assert.deepEqual(splashPosition(1, from, to, compact, -1), to);\n    const midway = splashPosition(0.5, from, to, compact, 1);\n    assert.equal(midway.x, (from.x + to.x) / 2 + (compact ? 6 : 0));\n    assert.equal(midway.y, (from.y + to.y) / 2 - (compact ? 0 : 6));\n  }\n});\n"
    },
    {
      "path": "tests/state.test.mjs",
      "url": "source/files/tests/state.test.mjs.txt",
      "bytes": 2169,
      "sha256": "bda80b37d7b1ada90a8855f6a78cf9fc43c444b737370c572a41cb75ff95b712",
      "content": "import test from \"node:test\";\nimport assert from \"node:assert/strict\";\nimport {\n  createState,\n  selectState,\n  isCaptureMode,\n  getCaptureSection,\n} from \"../src/scripts/state.mjs\";\n\ntest(\"initial product illustrations remain ready for image capture\", () => {\n  assert.deepEqual(createState(), {\n    filter: \"waiting\",\n    context: \"source\",\n  });\n  assert.notEqual(createState(), createState());\n});\n\ntest(\"selections return a new state without changing other illustrations\", () => {\n  const original = Object.freeze(createState());\n  for (const [key, values] of Object.entries({\n    filter: [\"all\", \"waiting\", \"connections\"],\n    context: [\"source\", \"work\", \"action\"],\n  })) {\n    for (const value of values) {\n      const next = selectState(original, key, value);\n      assert.deepEqual(next, { ...original, [key]: value });\n      assert.notEqual(next, original);\n    }\n  }\n  assert.equal(original.filter, \"waiting\");\n});\n\ntest(\"unknown keys and unsupported values cannot enter product state\", () => {\n  const original = createState();\n  for (const [key, value] of [\n    [\"view\", \"grid\"],\n    [\"filter\", \"review\"],\n    [\"step\", \"3\"],\n    [\"constructor\", \"bad\"],\n    [\"__proto__\", \"bad\"],\n  ]) {\n    assert.deepEqual(selectState(original, key, value), original);\n  }\n});\n\ntest(\"only the explicit capture flag enables a still presentation\", () => {\n  assert.equal(isCaptureMode(\"?capture=1\"), true);\n  for (const query of [\"\", \"?capture=0\", \"?capture=true\", \"?other=1\"]) {\n    assert.equal(isCaptureMode(query), false);\n  }\n});\n\ntest(\"isolated capture only accepts known sections with explicit capture mode\", () => {\n  for (const section of [\n    \"hero\",\n    \"workflow\",\n    \"video\",\n    \"selector\",\n    \"agent\",\n    \"prepared\",\n    \"context\",\n    \"progression\",\n    \"stats\",\n    \"modules\",\n    \"closing\",\n  ]) {\n    assert.equal(getCaptureSection(`?capture=1&section=${section}`), section);\n  }\n  for (const search of [\n    \"\",\n    \"?section=hero\",\n    \"?capture=0&section=hero\",\n    \"?capture=1\",\n    \"?capture=1&section=unknown\",\n    \"?capture=1&section=views\",\n    \"?capture=1&section=recurring\",\n  ]) {\n    assert.equal(getCaptureSection(search), null);\n  }\n});\n"
    },
    {
      "path": "vercel.json",
      "url": "source/files/vercel.json.txt",
      "bytes": 220,
      "sha256": "9e3b78479bd03b3f7fd8c14a1d7792adb2644ff4fac4b8932de2582e770f9b3b",
      "content": "{\"framework\":null,\"buildCommand\":\"npm run build\",\"outputDirectory\":\"dist\",\"headers\":[{\"source\":\"/assets/(.*)\",\"headers\":[{\"key\":\"Cache-Control\",\"value\":\"public, max-age=86400\"}]}],\"name\":\"dualentry-landing\",\"version\":2}\n"
    }
  ],
  "assets": [
    {
      "path": "assets/cosmos-blue-loop.webp",
      "url": "assets/cosmos-blue-loop.webp",
      "bytes": 78590,
      "sha256": "3dae9c468be7018a44c7919bf0cfc8b7ae29f570d56e1170fd230bbd02c83a9c"
    },
    {
      "path": "assets/cosmos-blue-wave.webp",
      "url": "assets/cosmos-blue-wave.webp",
      "bytes": 100310,
      "sha256": "3aff10ca8b638eb7af152a12e74a843633ce0a8ffa96f2aa75b1bf072890e340"
    },
    {
      "path": "assets/cosmos-folded-glass.webp",
      "url": "assets/cosmos-folded-glass.webp",
      "bytes": 40326,
      "sha256": "cbbd74a36e59b5dfec72c1473165e602d02f56e51428dfea15de1fc19e47c339"
    },
    {
      "path": "assets/cosmos-ribbed-glass.webp",
      "url": "assets/cosmos-ribbed-glass.webp",
      "bytes": 110444,
      "sha256": "5e649ab0d727ad9d1a21924d5e449736b441ec2b8726e578ee58fd33f90eccd4"
    },
    {
      "path": "assets/lausanne-medium.woff2",
      "url": "assets/lausanne-medium.woff2",
      "bytes": 30900,
      "sha256": "88925c18d2d0288d2d37acc586efd78e9387f191599e86755760947024e9e613"
    },
    {
      "path": "assets/lausanne-regular.woff2",
      "url": "assets/lausanne-regular.woff2",
      "bytes": 30952,
      "sha256": "3edff1ede4f95fec11b4ad510397682faac14c622267b92fe314f6860f6eba12"
    },
    {
      "path": "assets/logo.svg",
      "url": "assets/logo.svg",
      "bytes": 3281,
      "sha256": "ec5db72abd800a25248d9b4e581c8a06d0fff5d643590f81b7afe8f1258aeb16"
    }
  ]
}
