+ For AI agents: a documentation index is available at /llms.txt — markdown versions of all pages
+ are available by appending .md to any URL path.
+
+
diff --git a/docs/.vitepress/theme/index.ts b/docs/.vitepress/theme/index.ts
new file mode 100644
index 0000000..b594544
--- /dev/null
+++ b/docs/.vitepress/theme/index.ts
@@ -0,0 +1,7 @@
+import DefaultTheme from 'vitepress/theme';
+import HomeLayout from './HomeLayout.vue';
+
+export default {
+ extends: DefaultTheme,
+ Layout: HomeLayout,
+};
diff --git a/docs/about.md b/docs/about.md
new file mode 100644
index 0000000..97b1e68
--- /dev/null
+++ b/docs/about.md
@@ -0,0 +1,72 @@
+# About AFDocs
+
+
+
+
+AFDocs is an open-source tool that tests documentation sites against the [Agent-Friendly Documentation Spec](https://agentdocsspec.com). The spec defines what makes documentation accessible to AI coding agents, based on observed behavior across real agent platforms. AFDocs automates those observations into 22 checks that produce a score and actionable fix suggestions.
+
+
+
+
+
+
+
+
+## The Agent-Friendly Documentation Spec
+
+The [Agent-Friendly Documentation Spec](https://agentdocsspec.com) is the foundation for everything AFDocs checks. It documents:
+
+- How agents actually discover, fetch, and consume documentation
+- What fails in practice (truncation, empty SPA shells, auth gates, broken redirects)
+- What works (llms.txt, markdown availability, content negotiation, proper status codes)
+- Specific agent behaviors observed across Claude Code, Cursor, GitHub Copilot, OpenAI Codex, Gemini CLI, and others
+
+The spec is maintained at [github.com/agent-ecosystem/agent-docs-spec](https://github.com/agent-ecosystem/agent-docs-spec) and is open for contributions.
+
+AFDocs implements spec v0.3.0 (2026-03-31).
+
+## Status
+
+AFDocs is in early development (0.x). Check IDs, CLI flags, and output formats may change between minor versions. The tool is usable today, but don't build automation against specific output details until 1.0.
+
+## Contributing
+
+AFDocs is developed at [github.com/agent-ecosystem/afdocs](https://github.com/agent-ecosystem/afdocs). Issues, bug reports, and pull requests are welcome.
+
+If you've tested AFDocs against your docs site and found a check that doesn't accurately reflect agent behavior, or a failure mode that isn't covered, that's especially valuable feedback. The checks are based on observed behavior, and more observations make them better.
+
+## License
+
+MIT
+
+
diff --git a/docs/agent-score-calculation.md b/docs/agent-score-calculation.md
new file mode 100644
index 0000000..bed91f0
--- /dev/null
+++ b/docs/agent-score-calculation.md
@@ -0,0 +1,201 @@
+# Score Calculation
+
+The Agent Score is a weighted average of 22 check results, adjusted for interaction effects between checks. This page covers the mechanics: how checks are weighted, how multi-page results are scored proportionally, and how the system handles cases where checks influence each other.
+
+Each check corresponds to a section of the [Agent-Friendly Documentation Spec](https://agentdocsspec.com), which documents what the check measures and the observed agent behaviors that motivated it. For what each check measures, see the [Checks Reference](/checks/).
+
+## The formula
+
+```
+score = (sum of check scores) / (sum of weights for non-skipped checks) × 100
+```
+
+Each check earns a proportion of its weight based on its result:
+
+- **Pass**: Full weight
+- **Warn**: Partial weight (see [warn coefficients](#warn-coefficients) below)
+- **Fail**: Zero
+- **Skip**: Excluded from both the numerator and denominator
+
+The score is rounded to the nearest integer and mapped to a [letter grade](/what-is-agent-score#letter-grades).
+
+## Check weights by category
+
+Every check is assigned a weight tier based on its observed impact on agent workflows:
+
+- **Critical (10 pts)**: Agents cannot function without this. Failure means zero content, zero navigation, or zero access.
+- **High (7 pts)**: Directly limits agent effectiveness. Failure means truncation, dead ends, or agents stuck on a worse path.
+- **Medium (4 pts)**: Significant but not blocking. Failure degrades quality or misses an opportunity.
+- **Low (2 pts)**: Refinements. Failure is a missed best practice, not an agent-blocking issue.
+
+### Content Discoverability
+
+| Check | Weight |
+| ------------------------- | ------------- |
+| `llms-txt-exists` | Critical (10) |
+| `llms-txt-valid` | Medium (4) |
+| `llms-txt-size` | High (7) |
+| `llms-txt-links-resolve` | High (7) |
+| `llms-txt-links-markdown` | High (7) |
+| `llms-txt-directive` | High (7) |
+
+### Markdown Availability
+
+| Check | Weight |
+| ---------------------- | ---------- |
+| `markdown-url-support` | High (7) |
+| `content-negotiation` | Medium (4) |
+
+### Page Size and Truncation Risk
+
+| Check | Weight |
+| ------------------------ | ------------- |
+| `rendering-strategy` | Critical (10) |
+| `page-size-markdown` | High (7) |
+| `page-size-html` | High (7) |
+| `content-start-position` | Medium (4) |
+
+### Content Structure
+
+| Check | Weight |
+| ------------------------------ | ---------- |
+| `tabbed-content-serialization` | Medium (4) |
+| `section-header-quality` | Low (2) |
+| `markdown-code-fence-validity` | Medium (4) |
+
+### URL Stability and Redirects
+
+| Check | Weight |
+| ------------------- | ---------- |
+| `http-status-codes` | High (7) |
+| `redirect-behavior` | Medium (4) |
+
+### Observability and Content Health
+
+| Check | Weight |
+| ------------------------- | ---------- |
+| `llms-txt-freshness` | Medium (4) |
+| `markdown-content-parity` | Medium (4) |
+| `cache-header-hygiene` | Low (2) |
+
+### Authentication and Access
+
+| Check | Weight |
+| ------------------------- | ------------- |
+| `auth-gate-detection` | Critical (10) |
+| `auth-alternative-access` | Medium (4) |
+
+## Proportional scoring
+
+Checks that test multiple pages use proportional scoring. If `page-size-html` tests 50 pages and 3 exceed the threshold, the check scores ~94% of its weight rather than failing outright. This reflects reality: a site where a few pages are oversized is very different from one where nearly all are.
+
+### Multi-page checks (proportional)
+
+These checks sample pages from your site and score based on the pass rate across those pages:
+
+| Check | What's measured per page |
+| ------------------------------ | ----------------------------------------------------------- |
+| `rendering-strategy` | Whether the page is server-rendered or an SPA shell |
+| `page-size-html` | Whether the HTML-to-text conversion fits within size limits |
+| `page-size-markdown` | Whether the markdown version fits within size limits |
+| `content-start-position` | How far into the response actual content begins |
+| `content-negotiation` | Whether the server returns markdown for this page |
+| `markdown-url-support` | Whether the `.md` URL variant returns markdown |
+| `http-status-codes` | Whether a fabricated bad URL returns a proper 404 |
+| `redirect-behavior` | Whether redirects use standard HTTP methods |
+| `auth-gate-detection` | Whether the page is publicly accessible |
+| `llms-txt-directive` | Whether the page includes a directive pointing to llms.txt |
+| `tabbed-content-serialization` | Whether tabbed content creates oversized output |
+| `section-header-quality` | Whether tab section headers include variant context |
+| `markdown-code-fence-validity` | Whether code fences are properly closed |
+| `markdown-content-parity` | Whether markdown and HTML versions match |
+| `cache-header-hygiene` | Whether cache headers allow timely updates |
+| `auth-alternative-access` | Whether auth-gated pages have alternative access paths |
+
+### Single-resource checks (all-or-nothing)
+
+These checks test a single site-wide resource and produce one pass, warn, or fail result:
+
+| Check | What's tested |
+| ------------------------- | ------------------------------------------------------ |
+| `llms-txt-exists` | Whether an llms.txt file exists at candidate locations |
+| `llms-txt-valid` | Whether the llms.txt follows the standard structure |
+| `llms-txt-size` | Whether the llms.txt fits within agent context limits |
+| `llms-txt-links-resolve` | Whether links in the llms.txt return 200 |
+| `llms-txt-links-markdown` | Whether llms.txt links point to markdown content |
+| `llms-txt-freshness` | Whether the llms.txt reflects the current site state |
+
+Note that the llms.txt link checks (`llms-txt-links-resolve`, `llms-txt-links-markdown`) do test multiple URLs, but they test the links _within_ the llms.txt file rather than sampling pages from the site. Their result is a single pass/warn/fail based on the overall resolution or markdown rate.
+
+## Warn coefficients
+
+A warning is not a binary "half credit." Different warnings represent different degrees of degradation, and the score reflects this.
+
+| Coefficient | Meaning | Checks |
+| ----------- | ---------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| **0.75** | Content substantively intact | `llms-txt-valid`, `content-negotiation`, `llms-txt-links-resolve`, `llms-txt-freshness`, `markdown-content-parity` |
+| **0.60** | Partial coverage or platform-dependent | `llms-txt-directive`, `redirect-behavior` |
+| **0.50** | Genuine functional degradation | `llms-txt-exists`, `llms-txt-size`, `rendering-strategy`, `markdown-url-support`, `page-size-markdown`, `page-size-html`, `content-start-position`, `tabbed-content-serialization`, `section-header-quality`, `cache-header-hygiene`, `auth-gate-detection`, `auth-alternative-access` |
+| **0.25** | Actively steering agents to a worse path | `llms-txt-links-markdown` (markdown exists but llms.txt links to HTML) |
+
+Two checks have no warn state and are strictly pass/fail: `http-status-codes` and `markdown-code-fence-validity`.
+
+## Score caps
+
+Some problems are severe enough that no amount of other passing checks should compensate. When AFDocs detects a critical issue, we cap the score regardless of how well everything else performs.
+
+| Condition | Cap | Why |
+| ------------------------------------------------------------------------------------- | ------ | ------------------------------------------------------ |
+| `llms-txt-exists` fails | 59 (D) | Agents lose their primary navigation mechanism. |
+| `rendering-strategy`: 75%+ SPA shells | 39 (F) | Most content is invisible to agents. |
+| `rendering-strategy`: 50%+ SPA shells | 59 (D) | Significant content is invisible. |
+| `auth-gate-detection`: 75%+ pages gated | 39 (F) | Most documentation is inaccessible. |
+| `auth-gate-detection`: 50%+ pages gated | 59 (D) | Significant documentation is inaccessible. |
+| [No viable path](/interaction-diagnostics#no-viable-path-to-content) diagnostic fires | 39 (F) | Agents have no effective way to access content at all. |
+
+When multiple caps apply, the lowest one wins.
+
+## Cluster coefficients
+
+Some checks only matter if agents can actually reach the content they measure. If agents can't discover your markdown path, measuring markdown quality is pointless. The score handles this through cluster coefficients that scale both a check's score and its weight proportionally.
+
+### Discovery coefficient
+
+**Affects**: `page-size-markdown`, `markdown-code-fence-validity`, `markdown-content-parity`
+
+These checks measure markdown path quality. But if agents can't discover that path, the quality is irrelevant.
+
+| Condition | Coefficient | Why |
+| --------------------------- | ----------- | --------------------------------------------------------------- |
+| Content negotiation passes | 1.0 | Agents that request it get markdown automatically. |
+| llms.txt directive passes | 0.8 | Effective, but agents sometimes ignore the directive. |
+| llms.txt links use .md URLs | 0.5 | Agents must find llms.txt first, then follow .md links. |
+| None of the above | 0.0 | Agents won't find the markdown path. Check excluded from score. |
+
+If multiple conditions are met, the highest coefficient applies.
+
+Note that `markdown-url-support` is intentionally excluded from this coefficient. It measures whether the capability exists, not the quality of an established path. A site should get credit for serving markdown; the discovery coefficient only applies to downstream quality checks.
+
+### HTML path coefficient
+
+**Affects**: `page-size-html`, `content-start-position`, `tabbed-content-serialization`, `section-header-quality`
+
+If pages are SPA shells, measuring HTML quality is meaningless. This coefficient equals the `rendering-strategy` check's pass proportion: if 90% of pages render correctly, these checks count for 90% of their weight.
+
+### Index truncation coefficient
+
+**Affects**: `llms-txt-links-resolve`, `llms-txt-valid`, `llms-txt-freshness`, `llms-txt-links-markdown`
+
+If your llms.txt is truncated, agents only see part of the index. Measuring the quality of the invisible portion doesn't reflect real agent experience.
+
+| Condition | Coefficient |
+| -------------------------------- | ---------------------------------------------------------- |
+| `llms-txt-size` passes | 1.0 |
+| `llms-txt-size` warns (50K–100K) | 0.8 |
+| `llms-txt-size` fails (>100K) | Proportional to visible fraction (e.g., a 200K file ≈ 0.5) |
+
+### How coefficients combine
+
+When a check is subject to multiple coefficients, they multiply. Both the check's score and its weight in the denominator are scaled by the same combined coefficient, so a discounted check contributes proportionally less to the overall score rather than dragging it down.
+
+In the current scoring version, the three coefficient groups apply to disjoint sets of checks, so no check actually has more than one coefficient.
diff --git a/docs/checks/authentication.md b/docs/checks/authentication.md
new file mode 100644
index 0000000..bee0bb0
--- /dev/null
+++ b/docs/checks/authentication.md
@@ -0,0 +1,102 @@
+# Authentication and Access
+
+Whether agents can reach your documentation at all. Documentation that returns login pages, 401/403 responses, or SSO redirects is completely invisible to agents. These checks identify the problem and look for alternative access paths.
+
+## auth-gate-detection
+
+Whether documentation pages require authentication to access content.
+
+| | |
+| ---------- | -------------------------------------------------------------------------- |
+| **Weight** | Critical (10) |
+| **Spec** | [auth-gate-detection](https://agentdocsspec.com/spec/#auth-gate-detection) |
+
+### Why it matters
+
+Auth-gated documentation is the most absolute barrier for agents. When agents encounter a login page or 401 response, they fall back on potentially outdated training data or seek secondary sources that may not reflect your official documentation or best practices. Competitors with ungated docs provide a better agent experience for their users.
+
+### Results
+
+| Result | Condition |
+| ------ | ------------------------------------------------------------------------------ |
+| Pass | Documentation pages return content without authentication |
+| Warn | Some pages are accessible while others require authentication (partial gating) |
+| Fail | All or most documentation pages require authentication |
+
+AFDocs detects several forms of auth gating:
+
+- **HTTP status codes**: 401 (Unauthorized) and 403 (Forbidden) responses.
+- **SSO redirects**: Redirects to known SSO providers including Okta, Auth0, Microsoft login, Google Accounts, and Salesforce, plus common SSO subdomain patterns (`sso.`, `idp.`, `auth.`, `login.`).
+- **Soft auth gates**: Pages returning 200 but containing login form indicators: password input fields, page titles starting with "sign in" or "log in", or forms with SAML/OAuth/OpenID action URLs.
+
+### How to fix
+
+**If this check warns**, some of your docs are gated while others are public. This is common for products with tiered documentation. Consider ungating reference docs and API guides, which are the pages agents need most.
+
+**If this check fails**, all or most docs require authentication. Consider:
+
+- Ungating public API references and integration guides
+- Providing a public `llms.txt` with links to whatever content can be public
+- Shipping documentation with your SDK
+- Providing an MCP server for authenticated access
+
+The [Agent-Friendly Documentation Spec](https://agentdocsspec.com/spec) covers options for making private docs agent-accessible, ordered by implementation effort.
+
+### Score impact
+
+This is a Critical check with two score caps:
+
+- At 50%+ pages gated, the score is [capped at D (59)](/agent-score-calculation#score-caps).
+- At 75%+ pages gated, the score is [capped at F (39)](/agent-score-calculation#score-caps).
+
+---
+
+## auth-alternative-access
+
+Whether auth-gated sites provide alternative access paths agents can use.
+
+| | |
+| -------------- | ---------------------------------------------------------------------------------- |
+| **Weight** | Medium (4) |
+| **Depends on** | `auth-gate-detection` (warn or fail) |
+| **Spec** | [auth-alternative-access](https://agentdocsspec.com/spec/#auth-alternative-access) |
+
+### Why it matters
+
+Sites that must gate their primary documentation can still serve agents through secondary channels. This check gives credit for agent access even when the main docs require login. It only runs when `auth-gate-detection` returns warn or fail; if your docs are public, this check is skipped.
+
+### Results
+
+| Result | Condition |
+| ------ | ------------------------------------------------------------------------------------------ |
+| Pass | At least one alternative access path detected |
+| Warn | Partial alternative access (e.g., public `llms.txt` covers only a subset of gated content) |
+| Fail | No alternative access paths detected |
+
+### What the check detects
+
+AFDocs automatically detects three forms of alternative access:
+
+- **Public `llms.txt`**: Even if underlying docs are gated, a public `llms.txt` gives agents a navigational index.
+- **Public markdown**: Pages that serve markdown via `.md` URLs or content negotiation without requiring authentication.
+- **Partially accessible pages**: Some documentation pages are publicly accessible while others are gated.
+
+Some alternative access paths can't be detected automatically: bundled SDK documentation, CLI-based doc commands, and MCP servers. These are noted in the check output as requiring manual verification.
+
+### Other alternative access options
+
+If the check fails, these are additional approaches worth considering (even though AFDocs can't detect them):
+
+- **Bundled documentation**: Ship docs in your package/SDK so agents can access them locally.
+- **CLI-based doc access**: Provide a CLI command that works with the developer's existing authentication (e.g., `yourproduct docs search "topic"`).
+- **MCP server**: Expose documentation through tool calls with server-side authentication.
+
+If you provide any of these, document them on a public page (a setup guide, README, or your `llms.txt` itself) so agents have a chance of discovering the alternative path. An undiscoverable alternative isn't much better than no alternative.
+
+Because AFDocs can't detect these manual paths, you won't get score credit for them even if they're in place. If that's your situation, consider [defining a custom config](/improve-your-score#step-3-work-through-fixes-iteratively) that excludes `auth-alternative-access` so your score reflects the checks you can actually act on.
+
+### How to fix
+
+**If this check fails**, no alternative access paths were detected for your auth-gated content. The lowest-effort option is usually providing a public `llms.txt` that lists whatever documentation can be made available without authentication. See the [Agent-Friendly Documentation Spec](https://agentdocsspec.com/spec) for the full range of options.
+
+**If this check warns**, you have partial alternative access. Expand coverage to include more of the gated documentation, or add additional access paths.
diff --git a/docs/checks/content-discoverability.md b/docs/checks/content-discoverability.md
new file mode 100644
index 0000000..546b5b3
--- /dev/null
+++ b/docs/checks/content-discoverability.md
@@ -0,0 +1,223 @@
+# Content Discoverability
+
+How agents find and navigate your documentation. This category covers `llms.txt`: whether it exists, whether agents can parse it, whether the links work, and whether agents visiting individual pages know it's there.
+
+These six checks carry the most combined weight of any category. Without discoverability, everything else is less useful.
+
+## llms-txt-exists
+
+Whether your site has an `llms.txt` file at a discoverable location.
+
+| | |
+| ---------- | ------------------------------------------------------------------ |
+| **Weight** | Critical (10) |
+| **Spec** | [llms-txt-exists](https://agentdocsspec.com/spec/#llms-txt-exists) |
+
+### Why it matters
+
+`llms.txt` is the most effective navigation mechanism observed for agents. When agents find one, or are intentionally pointed to it, this gives agents the ability to navigate a documentation site. Without it, agents resort to guessing URLs from training data. They do _not_ read your navigation structure, and in cases where agent platforms automatically convert HTML to markdown before providing it to agents, they literally can't _see_ your navigation structure.
+
+### Results
+
+| Result | Condition |
+| ------ | ------------------------------------------------------------------------- |
+| Pass | `llms.txt` found at one or more candidate locations, returning 200 |
+| Warn | Reachable only via a cross-host redirect (some agents don't follow these) |
+| Fail | Not found at any candidate location |
+
+### Candidate locations
+
+AFDocs checks up to three URLs, depending on the URL you pass:
+
+| Candidate | Example |
+| ------------------------ | ---------------------------------------------------------------------------- |
+| `{baseUrl}/llms.txt` | `https://example.com/docs/llms.txt` (if you pass `https://example.com/docs`) |
+| `{origin}/llms.txt` | `https://example.com/llms.txt` |
+| `{origin}/docs/llms.txt` | `https://example.com/docs/llms.txt` |
+
+Duplicates are removed, so in practice fewer URLs may be checked (e.g., if your `baseUrl` is `https://example.com/docs`, the first and third rows produce the same URL).
+
+If any of these redirect cross-host (e.g., `example.com` redirects to `docs.example.com`), AFDocs also probes `{redirected_origin}/llms.txt` as a fallback.
+
+If your `llms.txt` lives at a location not covered by these candidates, AFDocs won't find it. You can either move it to one of the candidate locations or [open an issue](https://github.com/agent-ecosystem/afdocs/issues) to suggest expanding the candidate list.
+
+### How to fix
+
+**If this check fails**, create an `llms.txt` at one of the candidate locations above. The file should contain an H1 title, a blockquote summary, and markdown links to your key documentation pages. See the [llms.txt specification](https://llmstxt.org/) for the format.
+
+This is the single highest-impact improvement for agent access to your docs. It also unblocks five dependent checks that are currently skipped.
+
+**If this check warns**, your `llms.txt` is only reachable via a cross-host redirect. Serve it directly from the same host as your documentation, or add a same-host redirect.
+
+### Score impact
+
+If this check fails, the score is [capped at D (59)](/agent-score-calculation#score-caps) regardless of everything else.
+
+---
+
+## llms-txt-valid
+
+Whether your `llms.txt` follows the [llmstxt.org](https://llmstxt.org/) structure so agents can parse it reliably.
+
+| | |
+| -------------- | ---------------------------------------------------------------- |
+| **Weight** | Medium (4) |
+| **Depends on** | `llms-txt-exists` |
+| **Spec** | [llms-txt-valid](https://agentdocsspec.com/spec/#llms-txt-valid) |
+
+### Why it matters
+
+A well-structured `llms.txt` gives agents a reliable map of the documentation. Inconsistent implementations reduce its value, though even a non-standard file with useful links is better than nothing.
+
+### Results
+
+| Result | Condition |
+| ------ | ------------------------------------------------------------------------------------------------------------ |
+| Pass | Follows the proposed structure: H1 title, blockquote summary, heading-delimited sections with markdown links |
+| Warn | Contains parseable markdown links but doesn't follow the proposed structure |
+| Fail | Exists but contains no parseable links or is empty |
+
+### How to fix
+
+**If this check warns**, add an H1 title as the first line and a blockquote summary (lines starting with `>`) to improve agent parsing.
+
+**If this check fails**, add links in `[name](url): description` format under heading-delimited sections.
+
+---
+
+## llms-txt-size
+
+Whether your `llms.txt` fits within agent context windows.
+
+| | |
+| -------------- | -------------------------------------------------------------- |
+| **Weight** | High (7) |
+| **Depends on** | `llms-txt-exists` |
+| **Spec** | [llms-txt-size](https://agentdocsspec.com/spec/#llms-txt-size) |
+
+### Why it matters
+
+An `llms.txt` that exceeds truncation limits defeats its purpose. Some agent platforms see only the first 50K-100K characters; links, structure, and content beyond that point are invisible. This is arguably worse than the truncation problem affecting documentation pages, because `llms.txt` is supposed to be the solution to navigation.
+
+### Results
+
+| Result | Condition |
+| ------ | ------------------------------------------------------------------------ |
+| Pass | Under 50,000 characters |
+| Warn | 50,000-100,000 characters (fits within some agent platforms but not all) |
+| Fail | Over 100,000 characters (likely truncated by major agent platforms) |
+
+### How to fix
+
+**If this check warns**, keep an eye on it. If your `llms.txt` grows further, split it before it crosses the 100K threshold.
+
+**If this check fails**, split into a root `llms.txt` that links to section-level files, each under 50,000 characters. For example, a root index might link to `/api/llms.txt`, `/guides/llms.txt`, and `/reference/llms.txt`.
+
+### Score impact
+
+When `llms.txt` is oversized, the [index truncation coefficient](/agent-score-calculation#index-truncation-coefficient) discounts the value of downstream checks that measure the quality of content agents can't see.
+
+---
+
+## llms-txt-links-resolve
+
+Whether the URLs listed in your `llms.txt` actually work.
+
+| | |
+| -------------- | -------------------------------------------------------------------------------- |
+| **Weight** | High (7) |
+| **Depends on** | `llms-txt-exists` |
+| **Spec** | [llms-txt-links-resolve](https://agentdocsspec.com/spec/#llms-txt-links-resolve) |
+
+### Why it matters
+
+A stale `llms.txt` with broken links is worse than no `llms.txt` at all. It sends agents down dead ends with high confidence, because agents treat `llms.txt` as an authoritative source. Broken links are often pages that were renamed or removed without updating `llms.txt`.
+
+### Results
+
+| Result | Condition |
+| ------ | ------------------------------ |
+| Pass | All links resolve (return 200) |
+| Warn | Over 90% of links resolve |
+| Fail | Under 90% of links resolve |
+
+### How to fix
+
+Run with `--verbose` to see which specific links are broken. These are usually pages that were renamed or removed. Either update the links in `llms.txt` or remove entries for pages that no longer exist.
+
+The best long-term fix is generating `llms.txt` at build time so it stays in sync automatically.
+
+---
+
+## llms-txt-links-markdown
+
+Whether the URLs in your `llms.txt` point to markdown content rather than HTML.
+
+| | |
+| -------------- | ---------------------------------------------------------------------------------- |
+| **Weight** | High (7) |
+| **Depends on** | `llms-txt-exists` |
+| **Spec** | [llms-txt-links-markdown](https://agentdocsspec.com/spec/#llms-txt-links-markdown) |
+
+### Why it matters
+
+Markdown is more useful for agents than HTML. It omits the unnecessary tokens introduced by HTML in the page, and gives the agents clear content in an easy-to-parse format. An `llms.txt` pointing to HTML misses the opportunity to deliver content in the most agent-friendly format. Agents don't discover `.md` URL variants on their own; they follow whatever link `llms.txt` gives them.
+
+### Results
+
+| Result | Condition |
+| ------ | --------------------------------------------------------------------------------------------- |
+| Pass | All or most links point to markdown content |
+| Warn | Links point to HTML, but markdown versions are available (detected by testing `.md` variants) |
+| Fail | Links point to HTML and no markdown alternatives detected |
+
+### How to fix
+
+**If this check warns**, your site serves markdown but your `llms.txt` links to the HTML versions. Update the links to use `.md` URLs. This is usually a find-and-replace.
+
+**If this check fails**, your `llms.txt` links to HTML and no markdown is available. See [Markdown Availability](/checks/markdown-availability) for how to serve markdown.
+
+### Score impact
+
+A warning on this check carries a bigger penalty in scoring because it means markdown exists but agents are being actively steered away from it.
+
+---
+
+## llms-txt-directive
+
+Whether your documentation pages tell agents where to find `llms.txt`.
+
+| | |
+| ---------- | ------------------------------------------------------------------------ |
+| **Weight** | High (7) |
+| **Spec** | [llms-txt-directive](https://agentdocsspec.com/spec/#llms-txt-directive) |
+
+### Why it matters
+
+Agents don't know to look for `llms.txt` by default. When they land on an individual documentation page, they have no way to discover that a navigation index exists unless the page tells them. A blockquote directive near the top of each page is the agent equivalent of a "You Are Here" marker.
+
+In practice, agents that see the directive can follow it and use the index to navigate. In testing, Anthropic's Claude Code documentation used this pattern, and it worked reliably for Claude agents. However, agents are non-deterministic, and platforms implement functionality in different ways, so efficacy may vary across agents. This is more of a suggestion than a guarantee.
+
+### Results
+
+| Result | Condition |
+| ------ | -------------------------------------------------------------------------- |
+| Pass | Directive found on all or nearly all documentation pages, near the top |
+| Warn | Found on some pages but missing from others, or buried past 50% of content |
+| Fail | Not detected on any tested page |
+
+### How to fix
+
+Add a blockquote near the top of each documentation page pointing to your `llms.txt`. For example:
+
+```markdown
+> For the complete documentation index, see [llms.txt](/llms.txt)
+```
+
+The URL in the directive should match wherever you placed your `llms.txt`. If it's at `/docs/llms.txt`, use that path instead.
+
+This can typically be added through your docs platform's page template or layout component. It can be visually hidden with CSS while remaining accessible to agents, as long as it's in the server-rendered HTML (not injected by client-side JavaScript).
+
+### Score impact
+
+This check is one of the signals used by the [discovery coefficient](/agent-score-calculation#discovery-coefficient). If neither this check nor content negotiation passes, downstream markdown quality checks are discounted because agents can't find the markdown path.
diff --git a/docs/checks/content-structure.md b/docs/checks/content-structure.md
new file mode 100644
index 0000000..c6ba684
--- /dev/null
+++ b/docs/checks/content-structure.md
@@ -0,0 +1,92 @@
+# Content Structure
+
+Whether page content is structured in ways agents can consume. These checks cover patterns that are great for humans but problematic for agents: tabbed interfaces that serialize into massive documents, generic headers that lose context when tabs are flattened, and code fences that corrupt everything after them when left unclosed.
+
+The checks in this section focus on structural patterns that have measurable impact on agents: serialization behavior, header disambiguation, and code fence integrity. How you organize your content (page granularity, information architecture, what to include) is a separate question that we don't yet have enough empirical data to score.
+
+## tabbed-content-serialization
+
+Whether tabbed UI components create oversized output when serialized.
+
+| | |
+| ---------- | -------------------------------------------------------------------------------------------- |
+| **Weight** | Medium (4) |
+| **Spec** | [tabbed-content-serialization](https://agentdocsspec.com/spec/#tabbed-content-serialization) |
+
+### Why it matters
+
+Tabbed content is great for humans but can create truncation-based discoverability issues for agents. A tutorial showing the same steps in 11 language variants serializes into a single massive document in the HTML source. The agent sees only the first few variants before hitting truncation limits; everything past that point is invisible. Asking for a specific variant (like Python) doesn't help if that variant is beyond the truncation point.
+
+### Results
+
+| Result | Condition |
+| ------ | ------------------------------------------------------------------- |
+| Pass | No tabbed content, or serialized content is under 50,000 characters |
+| Warn | Serialized tabbed content is 50,000-100,000 characters |
+| Fail | Serialized tabbed content exceeds 100,000 characters |
+
+### How to fix
+
+If tabbed content creates oversized output, consider these approaches:
+
+- **Separate pages**: Break each variant into its own page (e.g., `/quickstart/python`, `/quickstart/node`). Each page is self-contained and fits within limits.
+- **Query parameters**: Provide a mechanism for agents to request a specific variant (e.g., `?lang=python`), returning only that variant's content.
+
+---
+
+## section-header-quality
+
+Whether headers in tabbed sections include enough context to be meaningful without the surrounding UI.
+
+| | |
+| -------------- | -------------------------------------------------------------------------------- |
+| **Weight** | Low (2) |
+| **Depends on** | `tabbed-content-serialization` |
+| **Spec** | [section-header-quality](https://agentdocsspec.com/spec/#section-header-quality) |
+
+### Why it matters
+
+When agents see serialized tabbed content, headers are the only way to tell which section applies to which context. Generic headers like "Step 1" repeated across Python, Node, and Go variants are indistinguishable in the serialized output. Headers like "Step 1 (Python/PyMongo)" preserve the filtering context agents need.
+
+### Results
+
+| Result | Condition |
+| ------ | ---------------------------------------------------------------------------------------------------- |
+| Pass | 25% or fewer of headers within tabbed sections are generic (repeated without distinguishing context) |
+| Warn | 25-50% of headers are generic across variants |
+| Fail | Over 50% generic, or identical header sets repeated across tab groups with no variant context |
+
+### How to fix
+
+Add variant context to headers in tabbed sections. For example, change "Step 1" to "Step 1 (Python)" or "Installation (npm)". This change benefits agents without affecting the human reading experience because the tab UI already provides the variant context visually.
+
+---
+
+## markdown-code-fence-validity
+
+Whether markdown content has properly closed code fences.
+
+| | |
+| -------------- | -------------------------------------------------------------------------------------------- |
+| **Weight** | Medium (4) |
+| **Depends on** | `markdown-url-support` or `content-negotiation` |
+| **Spec** | [markdown-code-fence-validity](https://agentdocsspec.com/spec/#markdown-code-fence-validity) |
+
+### Why it matters
+
+An unclosed code fence causes everything after it to be interpreted as code rather than prose. The agent sees the rest of the document as literal content to reproduce, not natural language instructions to follow. An early unclosed fence means the agent loses the entire rest of the page's meaning.
+
+Per CommonMark, a backtick fence (` ``` `) can only be closed by another backtick fence of equal or greater length. A tilde fence (`~~~`) closing a backtick-opened fence leaves the backtick fence unclosed.
+
+### Results
+
+| Result | Condition |
+| ------ | ------------------------------------------ |
+| Pass | All code fences properly opened and closed |
+| Fail | One or more unclosed code fences detected |
+
+This check has no warn state; it's strictly pass/fail.
+
+### How to fix
+
+Run with `--verbose` to see which pages have unclosed fences. Ensure every opening ` ``` ` or `~~~` has a matching closing delimiter of the same type and equal or greater length. Pay particular attention to nested code examples (code blocks inside code blocks) which are the most common source of fence mismatches.
diff --git a/docs/checks/index.md b/docs/checks/index.md
new file mode 100644
index 0000000..dd620e6
--- /dev/null
+++ b/docs/checks/index.md
@@ -0,0 +1,51 @@
+# Checks Reference
+
+AFDocs runs 22 checks across 7 categories. Each check implements a section of the [Agent-Friendly Documentation Spec](https://agentdocsspec.com/spec), which documents the observed agent behaviors and failure modes that motivated the check.
+
+## Categories
+
+| Category | Checks | What it covers |
+| ---------------------------------------------------------- | ------ | -------------------------------------------------------------------- |
+| [Content Discoverability](/checks/content-discoverability) | 6 | Whether agents can find and navigate your documentation via llms.txt |
+| [Markdown Availability](/checks/markdown-availability) | 2 | Whether agents can get documentation as markdown instead of HTML |
+| [Page Size and Truncation Risk](/checks/page-size) | 4 | Whether agents can process your pages without losing content |
+| [Content Structure](/checks/content-structure) | 3 | Whether page content is structured in ways agents can consume |
+| [URL Stability and Redirects](/checks/url-stability) | 2 | Whether documentation URLs behave predictably for agents |
+| [Observability and Content Health](/checks/observability) | 3 | Whether agent-facing resources stay accurate over time |
+| [Authentication and Access](/checks/authentication) | 2 | Whether agents can reach your documentation at all |
+
+## How to read check results
+
+Each check produces one of four results:
+
+- **Pass**: The check passed. Your site meets the spec recommendation.
+- **Warn**: Partial success. Something works but could be better; the scorecard includes a specific suggestion.
+- **Fail**: The check failed. Agents are affected. The scorecard includes a fix suggestion.
+- **Skip**: A dependency didn't pass, so this check couldn't run. The dependency already carries the penalty.
+
+For checks that test multiple pages (like `page-size-html` or `rendering-strategy`), results are proportional. If 3 out of 50 pages fail, the check scores ~94% of its weight rather than failing outright. See [Proportional scoring](/agent-score-calculation#proportional-scoring) for details.
+
+## Check dependencies
+
+Some checks depend on others. If a dependency doesn't pass, the dependent check is skipped.
+
+- `llms-txt-valid`, `llms-txt-size`, `llms-txt-links-resolve`, `llms-txt-links-markdown` require `llms-txt-exists`
+- `page-size-markdown` requires `markdown-url-support` or `content-negotiation`
+- `section-header-quality` requires `tabbed-content-serialization`
+- `markdown-code-fence-validity` requires `markdown-url-support` or `content-negotiation`
+- `llms-txt-freshness` requires `llms-txt-exists`
+- `markdown-content-parity` requires `markdown-url-support` or `content-negotiation`
+- `auth-alternative-access` requires `auth-gate-detection` (warn or fail)
+
+When running a subset of checks with `--checks`, include the dependencies in your list. AFDocs handles execution order automatically, but it can only run checks you've asked for. If you pass `--checks llms-txt-valid` without including `llms-txt-exists`, the dependency won't run, so `llms-txt-valid` gets skipped.
+
+## Weight tiers
+
+Every check is assigned a weight based on its observed impact on agent workflows. Weights determine how much each check contributes to the overall score.
+
+- **Critical (10 pts)**: Agents cannot function without this.
+- **High (7 pts)**: Directly limits agent effectiveness.
+- **Medium (4 pts)**: Significant but not blocking.
+- **Low (2 pts)**: Refinements and best practices.
+
+See [Score Calculation](/agent-score-calculation) for the full scoring mechanics.
diff --git a/docs/checks/markdown-availability.md b/docs/checks/markdown-availability.md
new file mode 100644
index 0000000..a7302a1
--- /dev/null
+++ b/docs/checks/markdown-availability.md
@@ -0,0 +1,73 @@
+# Markdown Availability
+
+Whether agents can get documentation as markdown instead of HTML. Agents work more effectively and efficiently with markdown: it's smaller, cleaner, and avoids the lossy HTML-to-markdown conversion that many agent web fetch pipelines apply. But agents don't discover markdown support on their own. Your docs must signal it.
+
+## markdown-url-support
+
+Whether appending `.md` to a documentation URL returns valid markdown.
+
+| | |
+| ---------- | ---------------------------------------------------------------------------- |
+| **Weight** | High (7) |
+| **Spec** | [markdown-url-support](https://agentdocsspec.com/spec/#markdown-url-support) |
+
+### Why it matters
+
+Sites serving markdown directly bypass the entire HTML-to-markdown conversion pipeline, which is lossy and unpredictable across agent platforms. This is the core format capability agents look for when directed to it via `llms.txt` links or a page directive.
+
+Some docs platforms support this natively. VitePress, for example, serves markdown at `.md` URLs out of the box.
+
+### Results
+
+| Result | Condition |
+| ------ | ------------------------------------------------ |
+| Pass | `.md` URLs return valid markdown with 200 status |
+| Warn | Some pages support `.md` but not consistently |
+| Fail | `.md` URLs return errors or HTML |
+
+### How to fix
+
+Configure your docs platform to serve `.md` variants for all documentation pages. The implementation depends on your platform:
+
+- **VitePress**: Works out of the box; `.md` URLs serve the raw source files.
+- **Other static generators**: You may need to copy source markdown files into the build output directory, or configure the server to serve them alongside the HTML.
+- **Server-rendered platforms**: Add a route that serves the markdown source when the `.md` extension is requested.
+
+### Dependencies
+
+`page-size-markdown`, `markdown-code-fence-validity`, and `markdown-content-parity` all require either this check or `content-negotiation` to pass. If neither passes, those downstream checks are skipped.
+
+---
+
+## content-negotiation
+
+Whether your server returns markdown when agents send `Accept: text/markdown`.
+
+| | |
+| ---------- | -------------------------------------------------------------------------- |
+| **Weight** | Medium (4) |
+| **Spec** | [content-negotiation](https://agentdocsspec.com/spec/#content-negotiation) |
+
+### Why it matters
+
+Some agents, including Claude Code and Cursor, send `Accept: text/markdown` as their preferred content type. If your server honors this, agents get clean markdown automatically without needing to know about `.md` URL patterns. This is the most transparent form of markdown delivery because it requires no changes to agent behavior.
+
+Most agents don't request markdown this way, but those that do benefit significantly.
+
+### Results
+
+| Result | Condition |
+| ------ | --------------------------------------------------------------------------- |
+| Pass | Server returns markdown with `Content-Type: text/markdown` |
+| Warn | Server returns markdown content but with an incorrect `Content-Type` header |
+| Fail | Server ignores the `Accept` header and returns HTML |
+
+### How to fix
+
+**If this check warns**, your server returns markdown content but doesn't set the `Content-Type` header correctly. Set the response `Content-Type` to `text/markdown` when the `Accept` header requests it.
+
+**If this check fails**, configure your server to honor content negotiation. This requires server-side support: when a request includes `Accept: text/markdown`, serve the markdown source instead of the HTML page.
+
+### Score impact
+
+Content negotiation passing sets the [discovery coefficient](/agent-score-calculation#discovery-coefficient) to 1.0 for downstream markdown quality checks, because agents that request markdown get it automatically with no decision involved.
diff --git a/docs/checks/observability.md b/docs/checks/observability.md
new file mode 100644
index 0000000..cdd513f
--- /dev/null
+++ b/docs/checks/observability.md
@@ -0,0 +1,96 @@
+# Observability and Content Health
+
+Whether agent-facing resources stay accurate over time. Getting `llms.txt` and markdown support working is the hard part; keeping them working is a different problem. These checks catch the silent failures: a stale index, drifting content between formats, and cache headers that delay updates.
+
+## llms-txt-freshness
+
+Whether your `llms.txt` reflects the current state of your documentation site.
+
+| | |
+| -------------- | ------------------------------------------------------------------------ |
+| **Weight** | Medium (4) |
+| **Depends on** | `llms-txt-exists` |
+| **Spec** | [llms-txt-freshness](https://agentdocsspec.com/spec/#llms-txt-freshness) |
+
+### Why it matters
+
+An `llms.txt` that was accurate at launch but never updated is a silent failure. New pages won't appear in the index, deleted pages send agents to 404s, and renamed pages produce redirect chains. Unlike `llms-txt-links-resolve` (which catches broken links), this check catches missing coverage: pages that exist on your site but aren't listed in `llms.txt`.
+
+### Results
+
+Based on coverage of your site's documentation pages (excluding non-docs pages like blog posts, pricing, login):
+
+| Result | Condition |
+| ------ | --------------------------------------------------------------- |
+| Pass | `llms.txt` covers 95% or more of the site's documentation pages |
+| Warn | 80-95% coverage (some live pages missing from the index) |
+| Fail | Under 80% coverage (missing large documentation sections) |
+
+### How to fix
+
+**If this check warns or fails**, regenerate `llms.txt` from your sitemap or build pipeline. The best long-term fix is generating `llms.txt` at build time, so every deployment automatically includes an up-to-date index. Run with `--verbose` to see which pages are missing.
+
+---
+
+## markdown-content-parity
+
+Whether markdown and HTML versions of pages contain the same content.
+
+| | |
+| -------------- | ---------------------------------------------------------------------------------- |
+| **Weight** | Medium (4) |
+| **Depends on** | `markdown-url-support` or `content-negotiation` |
+| **Spec** | [markdown-content-parity](https://agentdocsspec.com/spec/#markdown-content-parity) |
+
+### Why it matters
+
+When markdown is generated separately from HTML (not served directly from source), the two can drift. A site updates its HTML but forgets to regenerate the markdown, leaving agents with outdated instructions or code examples. Or a build pipeline that generates markdown misses some of the content. This is particularly insidious because agents receiving the markdown version have no signal that content is missing or outdated, and humans typically don't look at both page formats to spot discrepancies.
+
+### Results
+
+Based on the percentage of HTML content segments missing from the markdown version, after normalization:
+
+| Result | Condition |
+| ------ | --------------------------------------------------------------------------------------------- |
+| Pass | Under 5% of content segments missing |
+| Warn | 5-20% missing (minor differences like formatting or navigation elements) |
+| Fail | 20% or more missing (substantive differences like missing sections or outdated code examples) |
+
+### How to fix
+
+**If this check warns**, review the differences for formatting variations. Minor parity issues (navigation elements present in one format but not the other) may be acceptable.
+
+**If this check fails**, your markdown and HTML versions have substantive content differences. Regenerate markdown from source, or fix the build pipeline to keep both formats in sync. The most reliable approach is serving markdown directly from the same source files used to generate HTML, rather than maintaining two separate outputs.
+
+---
+
+## cache-header-hygiene
+
+Whether cache headers on `llms.txt` and markdown endpoints allow timely updates.
+
+| | |
+| ---------- | ---------------------------------------------------------------------------- |
+| **Weight** | Low (2) |
+| **Spec** | [cache-header-hygiene](https://agentdocsspec.com/spec/#cache-header-hygiene) |
+
+### Why it matters
+
+Aggressive caching means that after you update `llms.txt` or markdown content, agents and CDNs continue serving the stale version for hours or days. Conversely, missing cache headers lead to ambiguous behavior where CDN providers apply their own defaults.
+
+This isn't only a CDN concern. Some agents appear to cache fetched content locally or through a server proxy, using cache headers to decide whether to re-fetch a page or serve a stored copy. In testing, agents have been observed returning stale content for pages they previously fetched, even after the source was updated. The exact mechanism varies by agent platform, but the practical effect is the same: long cache lifetimes delay how quickly agents see your changes.
+
+For small, infrequently fetched resources like `llms.txt`, short cache lifetimes with revalidation headers are appropriate.
+
+### Results
+
+| Result | Condition |
+| ------ | ------------------------------------------------------------------------------------------- |
+| Pass | `max-age` under 3600, or uses `must-revalidate` with `ETag`/`Last-Modified` |
+| Warn | Moderate caching (1-24 hours) that could delay updates |
+| Fail | Aggressive caching (over 24 hours) with no revalidation, or no cache-related headers at all |
+
+Responses that lack `Cache-Control`/`Expires` but include `ETag` or `Last-Modified` pass, because they enable conditional revalidation.
+
+### How to fix
+
+Set reasonable cache lifetimes on `.md` and `.txt` files. A `max-age` of 300-3600 seconds (5 minutes to 1 hour) with `must-revalidate` is a good default. Include `ETag` or `Last-Modified` headers so clients can conditionally revalidate without re-downloading unchanged content.
diff --git a/docs/checks/page-size.md b/docs/checks/page-size.md
new file mode 100644
index 0000000..7c3024b
--- /dev/null
+++ b/docs/checks/page-size.md
@@ -0,0 +1,143 @@
+# Page Size and Truncation Risk
+
+Whether agents can process your pages without losing content. Agent platforms have diverse truncation limits, from 5K characters on some platforms to over 100K on others. Pages that exceed these limits are silently truncated: the agent sees the beginning of the page and loses the rest.
+
+This category also covers the related problem of pages that technically fit within limits but waste most of that budget on boilerplate (inline CSS, JavaScript, navigation chrome) instead of documentation content.
+
+## rendering-strategy
+
+Whether pages contain server-rendered content or are empty client-side application shells.
+
+| | |
+| ---------- | ------------------------------------------------------------------------ |
+| **Weight** | Critical (10) |
+| **Spec** | [rendering-strategy](https://agentdocsspec.com/spec/#rendering-strategy) |
+
+### Why it matters
+
+Many agents fetch pages using HTTP libraries that don't execute JavaScript. When a site relies on client-side rendering, agents receive an empty shell with framework boilerplate but none of the documentation content. This isn't a truncation problem; it's a zero-content problem.
+
+The rendering strategy is a property of the framework and its configuration, not the content. Sites using Next.js, for example, can be fully agent-accessible (like react.dev) or deliver empty shells, depending on whether server-side rendering is enabled.
+
+### Results
+
+| Result | Condition |
+| ------ | --------------------------------------------------------------------------------------------------------- |
+| Pass | Pages contain substantive server-rendered content (headings, prose, code blocks) |
+| Warn | Some content present but sparse (possible partial hydration or lazy loading) |
+| Fail | SPA shell detected (framework markers like `id="__next"`, minimal visible text, no page-specific content) |
+
+### How to fix
+
+**If this check warns**, verify that key content is present in the server-rendered HTML response. Some pages may use component-level client rendering or lazy loading for specific sections.
+
+**If this check fails**, enable server-side rendering or static site generation in your docs platform. This is typically a configuration change, not a code rewrite.
+
+### Score impact
+
+This is a Critical check with two score caps:
+
+- At 50%+ SPA shells, the score is [capped at D (59)](/agent-score-calculation#score-caps).
+- At 75%+ SPA shells, the score is [capped at F (39)](/agent-score-calculation#score-caps).
+
+The `rendering-strategy` pass rate also drives the [HTML path coefficient](/agent-score-calculation#html-path-coefficient). If 90% of pages render correctly, HTML quality checks (`page-size-html`, `content-start-position`, `tabbed-content-serialization`, `section-header-quality`) count for 90% of their weight.
+
+---
+
+## page-size-markdown
+
+Character count when documentation is served as markdown.
+
+| | |
+| -------------- | ------------------------------------------------------------------------ |
+| **Weight** | High (7) |
+| **Depends on** | `markdown-url-support` or `content-negotiation` |
+| **Spec** | [page-size-markdown](https://agentdocsspec.com/spec/#page-size-markdown) |
+
+### Why it matters
+
+This is the best-case scenario for agent consumption. Markdown size directly corresponds to what the model sees, with no conversion overhead. If the markdown version fits within limits, agents that can request it get full, untruncated content.
+
+### Results
+
+| Result | Condition |
+| ------ | ---------------------------------------------------------------------------- |
+| Pass | Under 50,000 characters |
+| Warn | 50,000-100,000 characters (fits within some platforms but may exceed others) |
+| Fail | Over 100,000 characters (truncated by all major agent platforms) |
+
+### How to fix
+
+**If pages are too large**, break them into smaller pages or restructure serialized tabbed content. See [tabbed-content-serialization](/checks/content-structure#tabbed-content-serialization) for guidance on the most common source of oversized pages.
+
+---
+
+## page-size-html
+
+Character count of the HTML response and the post-conversion size when converted to markdown.
+
+| | |
+| ---------- | ---------------------------------------------------------------- |
+| **Weight** | High (7) |
+| **Spec** | [page-size-html](https://agentdocsspec.com/spec/#page-size-html) |
+
+### Why it matters
+
+Many agents receive HTML, either because they don't request markdown or because the server doesn't support delivering markdown when requested. When agents receive HTML, the page size that matters isn't the raw HTML; it's how large the page is after the agent's platform converts it to text. Pages with a lot of inline CSS and JavaScript may be less likely to convert cleanly to text; the version of the page that the agent "sees" may still contain a lot of inline CSS and JavaScript. This can push the actual documentation content past agent truncation limits.
+
+AFDocs measures both the raw HTML size and the post-conversion size, and scores based on the conversion result. See [content-start-position](#content-start-position) below for more on how boilerplate affects what agents see.
+
+### Results
+
+Based on post-conversion character count:
+
+| Result | Condition |
+| ------ | ------------------------- |
+| Pass | Under 50,000 characters |
+| Warn | 50,000-100,000 characters |
+| Fail | Over 100,000 characters |
+
+The output also reports the conversion ratio. A page that converts from 505KB HTML to 12KB markdown has 98% boilerplate, meaning only 2% of the HTML was documentation content.
+
+### How to fix
+
+**If pages convert to too many characters**, the fix depends on where the bloat comes from:
+
+- **Inline CSS/JS**: Move styles and scripts to external files. This is the most common cause of high boilerplate percentages.
+- **Large pages**: Break long reference pages into smaller sections.
+- **Tabbed content**: See [tabbed-content-serialization](/checks/content-structure#tabbed-content-serialization).
+
+**If you also serve markdown**, this check matters less for agents that can request it. But most agents (4 of 6 tested) still fetch HTML, so the HTML path remains important.
+
+---
+
+## content-start-position
+
+How far into the response actual documentation content begins.
+
+| | |
+| ---------- | -------------------------------------------------------------------------------- |
+| **Weight** | Medium (4) |
+| **Spec** | [content-start-position](https://agentdocsspec.com/spec/#content-start-position) |
+
+### Why it matters
+
+When agents convert HTML to text, they don't always strip out the non-content parts of the page. Inline CSS and JavaScript can end up mixed in with your documentation from the agent's perspective. If enough of this boilerplate appears before your actual content, the agent may never see your documentation at all because it hits truncation limits first.
+
+In observed cases, actual content didn't start until 87% through the converted page: 441,000 characters of styling code before the first paragraph of actual documentation. The agent reported seeing a documentation page _about_ CSS instead of the actual documentation content.
+
+### Results
+
+Based on where content begins in the converted output:
+
+| Result | Condition |
+| ------ | ----------------------------------- |
+| Pass | Content starts within the first 10% |
+| Warn | Content starts between 10-50% |
+| Fail | Content starts after 50% |
+
+### How to fix
+
+**If this check warns or fails**, move inline CSS and JavaScript to external files. This is the most effective fix because external resources aren't included when agents process the page.
+
+If your platform inlines critical CSS, check whether you can reduce the amount. Navigation chrome, theme variables, and third-party widget styles all contribute to the boilerplate before content.
diff --git a/docs/checks/url-stability.md b/docs/checks/url-stability.md
new file mode 100644
index 0000000..d6ec9dc
--- /dev/null
+++ b/docs/checks/url-stability.md
@@ -0,0 +1,72 @@
+# URL Stability and Redirects
+
+Whether documentation URLs behave predictably for agents. Agents retrieve URLs from training data and `llms.txt`. When those URLs don't resolve cleanly, the agent either silently consumes the wrong content or fails to reach the page at all.
+
+## http-status-codes
+
+Whether error pages return correct HTTP status codes.
+
+| | |
+| ---------- | ---------------------------------------------------------------------- |
+| **Weight** | High (7) |
+| **Spec** | [http-status-codes](https://agentdocsspec.com/spec/#http-status-codes) |
+
+### Why it matters
+
+In empirical testing, soft 404s (pages returning 200 with "page not found" content) performed _worse_ than real 404s for agents. When an agent sees a 200 response, it trusts the content and tries to extract information from whatever is on the page. With a soft 404, that means the agent tries to use the error page content as if it were documentation. A clean 404 tells the agent to try a different approach.
+
+### Results
+
+| Result | Condition |
+| ------ | -------------------------------------------------- |
+| Pass | Fabricated bad URLs return proper 4xx status codes |
+| Fail | Bad URLs return 200 (soft 404) |
+
+This check has no warn state; it's strictly pass/fail.
+
+AFDocs tests this by generating non-existent URLs based on your site's URL structure and checking whether the server returns 404 or 200.
+
+### How to fix
+
+Configure your server or hosting platform to return a 404 status code for pages that don't exist. Most docs platforms handle this correctly by default; the common exception is single-page applications that serve the shell HTML for all routes and handle 404s client-side.
+
+### What about serving helpful content on missing pages?
+
+It's tempting to serve something useful when an agent requests a page that doesn't exist. For example, you might return your `llms.txt` as a fallback, or a "did you mean?" page with links to related content. This seems like an elegant solution to agents hallucinating URLs.
+
+The problem is the status code, not the content. If you serve a helpful fallback with a 200 status, the agent doesn't know the page it asked for doesn't exist. It trusts the 200 and tries to extract an answer from whatever you returned. If that's your `llms.txt`, the agent may try to answer a specific question using your table of contents. In testing, this performed worse than a clean 404 because the agent confidently uses the wrong content instead of recognizing its mistake and trying a different approach.
+
+The good news is that HTTP lets you do both: **return a 404 status code with a helpful response body.** Agents that check status codes will know the page doesn't exist; agents that read the body anyway get something useful. This is the best of both worlds.
+
+A more interesting long-term approach: if you notice agents consistently requesting pages that don't exist (the same hallucinated URL appearing repeatedly in your 404 logs), consider creating content at that URL. Agents hallucinate URLs based on patterns in their training data, and if many agents expect a page to exist, there may be a real content gap worth filling.
+
+---
+
+## redirect-behavior
+
+Whether redirects use standard HTTP methods and stay on the same host.
+
+| | |
+| ---------- | ---------------------------------------------------------------------- |
+| **Weight** | Medium (4) |
+| **Spec** | [redirect-behavior](https://agentdocsspec.com/spec/#redirect-behavior) |
+
+### Why it matters
+
+Same-host redirects (where the path changes but the host stays the same) work transparently because HTTP clients follow them automatically. Cross-host redirects are a known failure point: some agents, including Claude Code, don't automatically follow them as a security measure against open redirects. JavaScript-based redirects don't work at all because agents don't execute JavaScript.
+
+Agents often retrieve URLs from training data, which may point to old paths. Redirects from old paths to new ones are expected and fine, as long as they're same-host HTTP redirects.
+
+### Results
+
+| Result | Condition |
+| ------ | --------------------------------------------------------------------------------------- |
+| Pass | All redirects are same-host HTTP redirects (301/302) |
+| Warn | Cross-host HTTP redirects present (agents may or may not follow, depending on platform) |
+| Fail | JavaScript-based redirects detected |
+
+### How to fix
+
+**If this check warns**, you have cross-host HTTP redirects. Where possible, use same-host redirects or update URLs to point directly to the final destination. Common causes: migrating docs from one subdomain to another, or CDN configurations that redirect between `www` and non-`www`.
+
+**If this check fails**, JavaScript-based redirects were detected. Replace them with HTTP 301/302 redirects. Agents don't execute JavaScript and will never follow these.
diff --git a/docs/ci-integration.md b/docs/ci-integration.md
new file mode 100644
index 0000000..0ac49ef
--- /dev/null
+++ b/docs/ci-integration.md
@@ -0,0 +1,189 @@
+# CI Integration
+
+AFDocs includes vitest helpers so you can add agent-friendliness checks to your CI pipeline. Checks run as tests: each check is its own test case, so you can see exactly what passed, warned, failed, or was skipped.
+
+## Quick setup
+
+Install AFDocs and vitest as dev dependencies:
+
+```bash
+npm install -D afdocs vitest
+```
+
+### Config file
+
+Create `agent-docs.config.yml` in your project root:
+
+```yaml
+url: https://docs.example.com
+```
+
+The helpers look for this file starting from `process.cwd()` and walking up the directory tree.
+
+### Test file
+
+Create `agent-docs.test.ts`:
+
+```ts
+import { describeAgentDocsPerCheck } from 'afdocs/helpers';
+
+describeAgentDocsPerCheck();
+```
+
+### Run it
+
+```bash
+npx vitest run agent-docs.test.ts
+```
+
+Each check appears as its own test in the output:
+
+```
+ ✓ Agent-Friendly Documentation > llms-txt-exists
+ ✓ Agent-Friendly Documentation > llms-txt-valid
+ ✓ Agent-Friendly Documentation > llms-txt-size
+ × Agent-Friendly Documentation > markdown-url-support
+ ↓ Agent-Friendly Documentation > page-size-markdown
+```
+
+Checks that fail cause the test to fail. Checks that warn still pass (they're informational). Checks skipped due to unmet dependencies show as skipped.
+
+## Running a subset of checks
+
+If certain checks don't apply to your site (for example, you don't serve markdown), limit which checks run in the config:
+
+```yaml
+url: https://docs.example.com
+checks:
+ - llms-txt-exists
+ - llms-txt-valid
+ - llms-txt-size
+ - http-status-codes
+ - auth-gate-detection
+```
+
+Checks not in the list show as skipped in the test output.
+
+## Config options
+
+```yaml
+url: https://docs.example.com
+
+# Optional: run only specific checks (omit to run all 22)
+# checks:
+# - llms-txt-exists
+# - llms-txt-valid
+# - llms-txt-size
+
+# Optional: tune sampling behavior
+# options:
+# maxLinksToTest: 50
+# samplingStrategy: deterministic
+```
+
+### Config resolution
+
+The helpers look for `agent-docs.config.yml` (or `.yaml`) starting from `process.cwd()` and walking up the directory tree. You can also pass an explicit directory:
+
+```ts
+describeAgentDocsPerCheck(__dirname);
+```
+
+## Summary helper
+
+If you don't need per-check granularity, `describeAgentDocs` provides a simpler two-test suite (one to run checks, one to assert no failures):
+
+```ts
+import { describeAgentDocs } from 'afdocs/helpers';
+
+describeAgentDocs();
+```
+
+## Direct imports
+
+For full control, use the programmatic API directly:
+
+```ts
+import { createContext, getCheck } from 'afdocs';
+import { describe, it, expect } from 'vitest';
+
+describe('agent-friendliness', () => {
+ it('has a valid llms.txt', async () => {
+ const ctx = createContext('https://docs.example.com');
+ const check = getCheck('llms-txt-exists')!;
+ const result = await check.run(ctx);
+ expect(result.status).toBe('pass');
+ });
+});
+```
+
+## GitHub Actions
+
+Add a workflow file at `.github/workflows/agent-docs.yml`:
+
+```yaml
+name: Agent-Friendly Docs
+
+on:
+ push:
+ branches: [main]
+ pull_request:
+ branches: [main]
+
+jobs:
+ agent-docs-check:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v6
+
+ - uses: actions/setup-node@v6
+ with:
+ node-version: 22
+
+ - run: npm install
+
+ - name: Run agent-friendly docs checks
+ run: npx vitest run agent-docs.test.ts
+ timeout-minutes: 5
+```
+
+### Add a test script
+
+Alternatively, add a script to your `package.json`:
+
+```json
+{
+ "scripts": {
+ "test:agent-docs": "vitest run agent-docs.test.ts"
+ }
+}
+```
+
+Then reference it in the workflow:
+
+```yaml
+- name: Run agent-friendly docs checks
+ run: npm run test:agent-docs
+```
+
+## Other CI providers
+
+The GitHub Actions workflow is just Node.js setup + `npm install` + running the test. The same steps work on any CI provider. The test exits with code 0 if all checks pass (or warn) and code 1 if any check fails.
+
+## Organizing files
+
+If you prefer to keep test files out of your project root, move `agent-docs.config.yml` and `agent-docs.test.ts` into a subdirectory (e.g., `tests/`). Update the test file to tell AFDocs where to find the config:
+
+```ts
+import { describeAgentDocsPerCheck } from 'afdocs/helpers';
+
+describeAgentDocsPerCheck(__dirname);
+```
+
+## Timeouts
+
+The helpers set a 120-second timeout on the check run automatically. No vitest timeout configuration is needed.
+
+## Ready-to-copy example
+
+The [`examples/`](https://github.com/agent-ecosystem/afdocs/tree/main/examples) directory in the AFDocs repo contains a complete, ready-to-copy setup with all the files from this page, including the GitHub Actions workflow.
diff --git a/docs/generate_agent_md b/docs/generate_agent_md
new file mode 100755
index 0000000..90df402
--- /dev/null
+++ b/docs/generate_agent_md
@@ -0,0 +1,167 @@
+#!/usr/bin/env node
+//
+// Generates agent-facing markdown versions of all docs pages.
+// Called after vitepress build.
+//
+// For each source .md file:
+// - VitePress home layout frontmatter is converted to markdown
+// (hero name/text/tagline/actions and features)
+// - Other frontmatter (title, outline, etc.) is stripped
+// -
+
+## Get your score
+
+```bash
+npx afdocs check https://docs.example.com --format scorecard
+```
+
+The scorecard shows category breakdowns, system-level diagnostics, and per-check results with fix suggestions. Run with `--verbose --fixes` for detail on which specific pages have issues.
diff --git a/docs/interaction-diagnostics.md b/docs/interaction-diagnostics.md
new file mode 100644
index 0000000..91ae2bc
--- /dev/null
+++ b/docs/interaction-diagnostics.md
@@ -0,0 +1,65 @@
+# Interaction Diagnostics
+
+Some problems only become visible when you look at multiple checks together. The scorecard surfaces these as **interaction diagnostics**: system-level findings that emerge from combinations of check results.
+
+These diagnostics appear in the "Interaction Diagnostics" section of the `--format scorecard` output and as entries in the `diagnostics` array of the scoring API response.
+
+## Markdown support is undiscoverable
+
+**Triggers when** your site serves markdown at `.md` URLs, but none of the discovery mechanisms exist: no content negotiation, no llms.txt directive on pages, and no `.md` links in llms.txt.
+
+**What it means**: You've done the work to support markdown, but agents have no way to find out. They'll default to the HTML path every time. In observed agent behavior, agents do not independently discover `.md` URL variants; they need to be told.
+
+**What to do**: Add a [directive](/checks/content-discoverability#llms-txt-directive) on your docs pages pointing to llms.txt, or implement [content negotiation](/checks/markdown-availability#content-negotiation) for `Accept: text/markdown`. Either change makes your existing markdown support visible to agents.
+
+**Score impact**: Markdown quality checks (`page-size-markdown`, `markdown-code-fence-validity`, `markdown-content-parity`) are excluded from the score entirely when this diagnostic fires, because their results don't reflect real agent experience.
+
+## Truncated index
+
+**Triggers when** your llms.txt exists but exceeds agent context limits (the `llms-txt-size` check warns or fails).
+
+**What it means**: Agents see roughly the first 50K–100K characters of your llms.txt. Everything beyond that point (links, structure, descriptions) is invisible to agents. Quality checks on the truncated portion are discounted in the score.
+
+**What to do**: Split into a root llms.txt that links to section-level llms.txt files, each under 50,000 characters. The [llms-txt-size check](/checks/content-discoverability#llms-txt-size) details the thresholds.
+
+**Score impact**: The index truncation coefficient scales down `llms-txt-links-resolve`, `llms-txt-valid`, `llms-txt-freshness`, and `llms-txt-links-markdown` proportionally. A file that's twice the limit counts those checks at roughly half weight.
+
+## SPA shells invalidate HTML path
+
+**Triggers when** more than 25% of sampled pages use client-side rendering (the `rendering-strategy` check warns or fails).
+
+**What it means**: When humans visit the page in a browser, JavaScript loads the content. Agents don't visit a page in a browser, so they never see the content, only the shell. Page size and content structure scores for the HTML path are discounted because they're partially measuring shells, not actual content.
+
+**What to do**: Enable server-side rendering or static generation for documentation pages. If only specific page templates use client-side content loading, target those templates. The [rendering-strategy check](/checks/page-size#rendering-strategy) explains how AFDocs detects SPA shells.
+
+**Score impact**: The HTML path coefficient scales `page-size-html`, `content-start-position`, `tabbed-content-serialization`, and `section-header-quality` in proportion to the fraction of pages that render correctly. If 60% of pages are SPA shells, these checks count for 40% of their weight. At 50%+ SPA shells, the overall score is also [capped at D or F](/agent-score-calculation#score-caps).
+
+## No viable path to content
+
+**Triggers when** there's no working llms.txt (missing or nearly all links broken), no server-rendered HTML, and no discoverable markdown path.
+
+**What it means**: Agents have no effective way to access your documentation. They will fall back on training data or secondary sources, both of which may be inaccurate or outdated.
+
+**What to do**: If your site uses client-side rendering, enable server-side rendering. The second highest-impact action is creating an llms.txt at your site root with working links, ideally pointing to markdown pages. See [Improve Your Score](/improve-your-score) for a prioritized fix list.
+
+**Score impact**: Caps the overall score at 39 (F).
+
+## Auth-gated with no alternative
+
+**Triggers when** all documentation requires authentication and no alternative access paths exist (the `auth-gate-detection` check fails and `auth-alternative-access` also fails).
+
+**What it means**: Agents that encounter your docs will hit a login wall and fall back on training data or secondary sources.
+
+**What to do**: Consider providing a public llms.txt with links to ungated content, removing auth gates from API references and integration guides, or shipping documentation with your SDK. The [auth-alternative-access check](/checks/authentication#auth-alternative-access) covers the options.
+
+**Score impact**: Caps the overall score. If 75%+ of pages are gated with no alternatives, the cap is 39 (F). At 50%+, it's 59 (D).
+
+## Pages exceed size limits with no markdown escape
+
+**Triggers when** HTML pages exceed agent truncation limits and there's no discoverable markdown path that could offer smaller representations.
+
+**What it means**: Agents will silently receive truncated content on oversized pages, with no alternative path to the full content. This is particularly common on sites that inline large amounts of CSS and JavaScript.
+
+**What to do**: Either reduce HTML page sizes (break large pages into smaller ones, move inline CSS/JS to external files) or provide markdown versions and make them discoverable via content negotiation or llms.txt links. See [Page Size checks](/checks/page-size) for the specific thresholds.
+
+**Score impact**: No direct score cap, but the combination of failing page-size checks with no markdown alternative typically results in low category scores for both Page Size and Markdown Availability.
diff --git a/docs/logos/afdoc_logo_dark.svg b/docs/logos/afdoc_logo_dark.svg
new file mode 100644
index 0000000..19fb894
--- /dev/null
+++ b/docs/logos/afdoc_logo_dark.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/docs/logos/afdoc_logo_light.svg b/docs/logos/afdoc_logo_light.svg
new file mode 100644
index 0000000..6a0185c
--- /dev/null
+++ b/docs/logos/afdoc_logo_light.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/docs/package-lock.json b/docs/package-lock.json
new file mode 100644
index 0000000..4397dbc
--- /dev/null
+++ b/docs/package-lock.json
@@ -0,0 +1,2516 @@
+{
+ "name": "afdocs-docs",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "afdocs-docs",
+ "devDependencies": {
+ "vitepress": "^1.6.3"
+ }
+ },
+ "node_modules/@algolia/abtesting": {
+ "version": "1.16.1",
+ "resolved": "https://registry.npmjs.org/@algolia/abtesting/-/abtesting-1.16.1.tgz",
+ "integrity": "sha512-Xxk4l00pYI+jE0PNw8y0MvsQWh5278WRtZQav8/BMMi3HKi2xmeuqe11WJ3y8/6nuBHdv39w76OpJb09TMfAVQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@algolia/client-common": "5.50.1",
+ "@algolia/requester-browser-xhr": "5.50.1",
+ "@algolia/requester-fetch": "5.50.1",
+ "@algolia/requester-node-http": "5.50.1"
+ },
+ "engines": {
+ "node": ">= 14.0.0"
+ }
+ },
+ "node_modules/@algolia/autocomplete-core": {
+ "version": "1.17.7",
+ "resolved": "https://registry.npmjs.org/@algolia/autocomplete-core/-/autocomplete-core-1.17.7.tgz",
+ "integrity": "sha512-BjiPOW6ks90UKl7TwMv7oNQMnzU+t/wk9mgIDi6b1tXpUek7MW0lbNOUHpvam9pe3lVCf4xPFT+lK7s+e+fs7Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@algolia/autocomplete-plugin-algolia-insights": "1.17.7",
+ "@algolia/autocomplete-shared": "1.17.7"
+ }
+ },
+ "node_modules/@algolia/autocomplete-plugin-algolia-insights": {
+ "version": "1.17.7",
+ "resolved": "https://registry.npmjs.org/@algolia/autocomplete-plugin-algolia-insights/-/autocomplete-plugin-algolia-insights-1.17.7.tgz",
+ "integrity": "sha512-Jca5Ude6yUOuyzjnz57og7Et3aXjbwCSDf/8onLHSQgw1qW3ALl9mrMWaXb5FmPVkV3EtkD2F/+NkT6VHyPu9A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@algolia/autocomplete-shared": "1.17.7"
+ },
+ "peerDependencies": {
+ "search-insights": ">= 1 < 3"
+ }
+ },
+ "node_modules/@algolia/autocomplete-preset-algolia": {
+ "version": "1.17.7",
+ "resolved": "https://registry.npmjs.org/@algolia/autocomplete-preset-algolia/-/autocomplete-preset-algolia-1.17.7.tgz",
+ "integrity": "sha512-ggOQ950+nwbWROq2MOCIL71RE0DdQZsceqrg32UqnhDz8FlO9rL8ONHNsI2R1MH0tkgVIDKI/D0sMiUchsFdWA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@algolia/autocomplete-shared": "1.17.7"
+ },
+ "peerDependencies": {
+ "@algolia/client-search": ">= 4.9.1 < 6",
+ "algoliasearch": ">= 4.9.1 < 6"
+ }
+ },
+ "node_modules/@algolia/autocomplete-shared": {
+ "version": "1.17.7",
+ "resolved": "https://registry.npmjs.org/@algolia/autocomplete-shared/-/autocomplete-shared-1.17.7.tgz",
+ "integrity": "sha512-o/1Vurr42U/qskRSuhBH+VKxMvkkUVTLU6WZQr+L5lGZZLYWyhdzWjW0iGXY7EkwRTjBqvN2EsR81yCTGV/kmg==",
+ "dev": true,
+ "license": "MIT",
+ "peerDependencies": {
+ "@algolia/client-search": ">= 4.9.1 < 6",
+ "algoliasearch": ">= 4.9.1 < 6"
+ }
+ },
+ "node_modules/@algolia/client-abtesting": {
+ "version": "5.50.1",
+ "resolved": "https://registry.npmjs.org/@algolia/client-abtesting/-/client-abtesting-5.50.1.tgz",
+ "integrity": "sha512-4peZlPXMwTOey9q1rQKMdCnwZb/E95/1e+7KujXpLLSh0FawJzg//U2NM+r4AiJy4+naT2MTBhj0K30yshnVTA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@algolia/client-common": "5.50.1",
+ "@algolia/requester-browser-xhr": "5.50.1",
+ "@algolia/requester-fetch": "5.50.1",
+ "@algolia/requester-node-http": "5.50.1"
+ },
+ "engines": {
+ "node": ">= 14.0.0"
+ }
+ },
+ "node_modules/@algolia/client-analytics": {
+ "version": "5.50.1",
+ "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-5.50.1.tgz",
+ "integrity": "sha512-i+aWHHG8NZvGFHtPeMZkxL2Loc6Fm7iaRo15lYSMx8gFL+at9vgdWxhka7mD1fqxkrxXsQstUBCIsSY8FvkEOw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@algolia/client-common": "5.50.1",
+ "@algolia/requester-browser-xhr": "5.50.1",
+ "@algolia/requester-fetch": "5.50.1",
+ "@algolia/requester-node-http": "5.50.1"
+ },
+ "engines": {
+ "node": ">= 14.0.0"
+ }
+ },
+ "node_modules/@algolia/client-common": {
+ "version": "5.50.1",
+ "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-5.50.1.tgz",
+ "integrity": "sha512-Hw52Fwapyk/7hMSV/fI4+s3H9MGZEUcRh4VphyXLAk2oLYdndVUkc6KBi0zwHSzwPAr+ZBwFPe2x6naUt9mZGw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 14.0.0"
+ }
+ },
+ "node_modules/@algolia/client-insights": {
+ "version": "5.50.1",
+ "resolved": "https://registry.npmjs.org/@algolia/client-insights/-/client-insights-5.50.1.tgz",
+ "integrity": "sha512-Bn/wtwhJ7p1OD/6pY+Zzn+zlu2N/SJnH46md/PAbvqIzmjVuwjNwD4y0vV5Ov8naeukXdd7UU9v550+v8+mtlg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@algolia/client-common": "5.50.1",
+ "@algolia/requester-browser-xhr": "5.50.1",
+ "@algolia/requester-fetch": "5.50.1",
+ "@algolia/requester-node-http": "5.50.1"
+ },
+ "engines": {
+ "node": ">= 14.0.0"
+ }
+ },
+ "node_modules/@algolia/client-personalization": {
+ "version": "5.50.1",
+ "resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-5.50.1.tgz",
+ "integrity": "sha512-0V4Tu0RWR8YxkgI9EPVOZHGE4K5pEIhkLNN0CTkP/rnPsqaaSQpNMYW3/mGWdiKOWbX0iVmwLB9QESk3H0jS5g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@algolia/client-common": "5.50.1",
+ "@algolia/requester-browser-xhr": "5.50.1",
+ "@algolia/requester-fetch": "5.50.1",
+ "@algolia/requester-node-http": "5.50.1"
+ },
+ "engines": {
+ "node": ">= 14.0.0"
+ }
+ },
+ "node_modules/@algolia/client-query-suggestions": {
+ "version": "5.50.1",
+ "resolved": "https://registry.npmjs.org/@algolia/client-query-suggestions/-/client-query-suggestions-5.50.1.tgz",
+ "integrity": "sha512-jofcWNYMXJDDr87Z2eivlWY6o71Zn7F7aOvQCXSDAo9QTlyf7BhXEsZymLUvF0O1yU9Q9wvrjAWn8uVHYnAvgw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@algolia/client-common": "5.50.1",
+ "@algolia/requester-browser-xhr": "5.50.1",
+ "@algolia/requester-fetch": "5.50.1",
+ "@algolia/requester-node-http": "5.50.1"
+ },
+ "engines": {
+ "node": ">= 14.0.0"
+ }
+ },
+ "node_modules/@algolia/client-search": {
+ "version": "5.50.1",
+ "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-5.50.1.tgz",
+ "integrity": "sha512-OteRb8WubcmEvU0YlMJwCXs3Q6xrdkb0v50/qZBJP1TF0CvujFZQM++9BjEkTER/Jr9wbPHvjSFKnbMta0b4dQ==",
+ "dev": true,
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@algolia/client-common": "5.50.1",
+ "@algolia/requester-browser-xhr": "5.50.1",
+ "@algolia/requester-fetch": "5.50.1",
+ "@algolia/requester-node-http": "5.50.1"
+ },
+ "engines": {
+ "node": ">= 14.0.0"
+ }
+ },
+ "node_modules/@algolia/ingestion": {
+ "version": "1.50.1",
+ "resolved": "https://registry.npmjs.org/@algolia/ingestion/-/ingestion-1.50.1.tgz",
+ "integrity": "sha512-0GmfSgDQK6oiIVXnJvGxtNFOfosBspRTR7csCOYCTL1P8QtxX2vDCIKwTM7xdSAEbJaZ43QlWg25q0Qdsndz8Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@algolia/client-common": "5.50.1",
+ "@algolia/requester-browser-xhr": "5.50.1",
+ "@algolia/requester-fetch": "5.50.1",
+ "@algolia/requester-node-http": "5.50.1"
+ },
+ "engines": {
+ "node": ">= 14.0.0"
+ }
+ },
+ "node_modules/@algolia/monitoring": {
+ "version": "1.50.1",
+ "resolved": "https://registry.npmjs.org/@algolia/monitoring/-/monitoring-1.50.1.tgz",
+ "integrity": "sha512-ySuigKEe4YjYV3si8NVk9BHQpFj/1B+ON7DhhvTvbrZJseHQQloxzq0yHwKmznSdlO6C956fx4pcfOKkZClsyg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@algolia/client-common": "5.50.1",
+ "@algolia/requester-browser-xhr": "5.50.1",
+ "@algolia/requester-fetch": "5.50.1",
+ "@algolia/requester-node-http": "5.50.1"
+ },
+ "engines": {
+ "node": ">= 14.0.0"
+ }
+ },
+ "node_modules/@algolia/recommend": {
+ "version": "5.50.1",
+ "resolved": "https://registry.npmjs.org/@algolia/recommend/-/recommend-5.50.1.tgz",
+ "integrity": "sha512-Cp8T/B0gVmjFlzzp6eP47hwKh5FGyeqQp1N48/ANDdvdiQkPqLyFHQVDwLBH0LddfIPQE+yqmZIgmKc82haF4A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@algolia/client-common": "5.50.1",
+ "@algolia/requester-browser-xhr": "5.50.1",
+ "@algolia/requester-fetch": "5.50.1",
+ "@algolia/requester-node-http": "5.50.1"
+ },
+ "engines": {
+ "node": ">= 14.0.0"
+ }
+ },
+ "node_modules/@algolia/requester-browser-xhr": {
+ "version": "5.50.1",
+ "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-5.50.1.tgz",
+ "integrity": "sha512-XKdGGLikfrlK66ZSXh/vWcXZZ8Vg3byDFbJD8pwEvN1FoBRGxhxya476IY2ohoTymLa4qB5LBRlIa+2TLHx3Uw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@algolia/client-common": "5.50.1"
+ },
+ "engines": {
+ "node": ">= 14.0.0"
+ }
+ },
+ "node_modules/@algolia/requester-fetch": {
+ "version": "5.50.1",
+ "resolved": "https://registry.npmjs.org/@algolia/requester-fetch/-/requester-fetch-5.50.1.tgz",
+ "integrity": "sha512-mBAU6WyVsDwhHyGM+nodt1/oebHxgvuLlOAoMGbj/1i6LygDHZWDgL1t5JEs37x9Aywv7ZGhqbM1GsfZ54sU6g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@algolia/client-common": "5.50.1"
+ },
+ "engines": {
+ "node": ">= 14.0.0"
+ }
+ },
+ "node_modules/@algolia/requester-node-http": {
+ "version": "5.50.1",
+ "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-5.50.1.tgz",
+ "integrity": "sha512-qmo1LXrNKLHvJE6mdQbLnsZAoZvj7VyF2ft4xmbSGWI2WWm87fx/CjUX4kEExt4y0a6T6nEts6ofpUfH5TEE1A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@algolia/client-common": "5.50.1"
+ },
+ "engines": {
+ "node": ">= 14.0.0"
+ }
+ },
+ "node_modules/@babel/helper-string-parser": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz",
+ "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-validator-identifier": {
+ "version": "7.28.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz",
+ "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/parser": {
+ "version": "7.29.2",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.2.tgz",
+ "integrity": "sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.29.0"
+ },
+ "bin": {
+ "parser": "bin/babel-parser.js"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@babel/types": {
+ "version": "7.29.0",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz",
+ "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-string-parser": "^7.27.1",
+ "@babel/helper-validator-identifier": "^7.28.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@docsearch/css": {
+ "version": "3.8.2",
+ "resolved": "https://registry.npmjs.org/@docsearch/css/-/css-3.8.2.tgz",
+ "integrity": "sha512-y05ayQFyUmCXze79+56v/4HpycYF3uFqB78pLPrSV5ZKAlDuIAAJNhaRi8tTdRNXh05yxX/TyNnzD6LwSM89vQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@docsearch/js": {
+ "version": "3.8.2",
+ "resolved": "https://registry.npmjs.org/@docsearch/js/-/js-3.8.2.tgz",
+ "integrity": "sha512-Q5wY66qHn0SwA7Taa0aDbHiJvaFJLOJyHmooQ7y8hlwwQLQ/5WwCcoX0g7ii04Qi2DJlHsd0XXzJ8Ypw9+9YmQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@docsearch/react": "3.8.2",
+ "preact": "^10.0.0"
+ }
+ },
+ "node_modules/@docsearch/react": {
+ "version": "3.8.2",
+ "resolved": "https://registry.npmjs.org/@docsearch/react/-/react-3.8.2.tgz",
+ "integrity": "sha512-xCRrJQlTt8N9GU0DG4ptwHRkfnSnD/YpdeaXe02iKfqs97TkZJv60yE+1eq/tjPcVnTW8dP5qLP7itifFVV5eg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@algolia/autocomplete-core": "1.17.7",
+ "@algolia/autocomplete-preset-algolia": "1.17.7",
+ "@docsearch/css": "3.8.2",
+ "algoliasearch": "^5.14.2"
+ },
+ "peerDependencies": {
+ "@types/react": ">= 16.8.0 < 19.0.0",
+ "react": ">= 16.8.0 < 19.0.0",
+ "react-dom": ">= 16.8.0 < 19.0.0",
+ "search-insights": ">= 1 < 3"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "react": {
+ "optional": true
+ },
+ "react-dom": {
+ "optional": true
+ },
+ "search-insights": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@esbuild/aix-ppc64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz",
+ "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "aix"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/android-arm": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz",
+ "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/android-arm64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz",
+ "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/android-x64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz",
+ "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/darwin-arm64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz",
+ "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/darwin-x64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz",
+ "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/freebsd-arm64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz",
+ "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/freebsd-x64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz",
+ "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-arm": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz",
+ "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-arm64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz",
+ "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-ia32": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz",
+ "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-loong64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz",
+ "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==",
+ "cpu": [
+ "loong64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-mips64el": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz",
+ "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==",
+ "cpu": [
+ "mips64el"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-ppc64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz",
+ "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-riscv64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz",
+ "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-s390x": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz",
+ "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-x64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz",
+ "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/netbsd-x64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz",
+ "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/openbsd-x64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz",
+ "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/sunos-x64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz",
+ "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "sunos"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/win32-arm64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz",
+ "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/win32-ia32": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz",
+ "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/win32-x64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz",
+ "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@iconify-json/simple-icons": {
+ "version": "1.2.76",
+ "resolved": "https://registry.npmjs.org/@iconify-json/simple-icons/-/simple-icons-1.2.76.tgz",
+ "integrity": "sha512-lLRlA8yaf+1L5VCPRvR9lynoSklsddKHEylchmZJKdj/q2xVQ1ZAEJ8SCQlv9cbgtMefnlyM98U+8Si2aoFZPA==",
+ "dev": true,
+ "license": "CC0-1.0",
+ "dependencies": {
+ "@iconify/types": "*"
+ }
+ },
+ "node_modules/@iconify/types": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/@iconify/types/-/types-2.0.0.tgz",
+ "integrity": "sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@jridgewell/sourcemap-codec": {
+ "version": "1.5.5",
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
+ "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@rollup/rollup-android-arm-eabi": {
+ "version": "4.60.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.60.1.tgz",
+ "integrity": "sha512-d6FinEBLdIiK+1uACUttJKfgZREXrF0Qc2SmLII7W2AD8FfiZ9Wjd+rD/iRuf5s5dWrr1GgwXCvPqOuDquOowA==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ]
+ },
+ "node_modules/@rollup/rollup-android-arm64": {
+ "version": "4.60.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.60.1.tgz",
+ "integrity": "sha512-YjG/EwIDvvYI1YvYbHvDz/BYHtkY4ygUIXHnTdLhG+hKIQFBiosfWiACWortsKPKU/+dUwQQCKQM3qrDe8c9BA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ]
+ },
+ "node_modules/@rollup/rollup-darwin-arm64": {
+ "version": "4.60.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.60.1.tgz",
+ "integrity": "sha512-mjCpF7GmkRtSJwon+Rq1N8+pI+8l7w5g9Z3vWj4T7abguC4Czwi3Yu/pFaLvA3TTeMVjnu3ctigusqWUfjZzvw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/@rollup/rollup-darwin-x64": {
+ "version": "4.60.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.60.1.tgz",
+ "integrity": "sha512-haZ7hJ1JT4e9hqkoT9R/19XW2QKqjfJVv+i5AGg57S+nLk9lQnJ1F/eZloRO3o9Scy9CM3wQ9l+dkXtcBgN5Ew==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/@rollup/rollup-freebsd-arm64": {
+ "version": "4.60.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.60.1.tgz",
+ "integrity": "sha512-czw90wpQq3ZsAVBlinZjAYTKduOjTywlG7fEeWKUA7oCmpA8xdTkxZZlwNJKWqILlq0wehoZcJYfBvOyhPTQ6w==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ]
+ },
+ "node_modules/@rollup/rollup-freebsd-x64": {
+ "version": "4.60.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.60.1.tgz",
+ "integrity": "sha512-KVB2rqsxTHuBtfOeySEyzEOB7ltlB/ux38iu2rBQzkjbwRVlkhAGIEDiiYnO2kFOkJp+Z7pUXKyrRRFuFUKt+g==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm-gnueabihf": {
+ "version": "4.60.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.60.1.tgz",
+ "integrity": "sha512-L+34Qqil+v5uC0zEubW7uByo78WOCIrBvci69E7sFASRl0X7b/MB6Cqd1lky/CtcSVTydWa2WZwFuWexjS5o6g==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm-musleabihf": {
+ "version": "4.60.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.60.1.tgz",
+ "integrity": "sha512-n83O8rt4v34hgFzlkb1ycniJh7IR5RCIqt6mz1VRJD6pmhRi0CXdmfnLu9dIUS6buzh60IvACM842Ffb3xd6Gg==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm64-gnu": {
+ "version": "4.60.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.60.1.tgz",
+ "integrity": "sha512-Nql7sTeAzhTAja3QXeAI48+/+GjBJ+QmAH13snn0AJSNL50JsDqotyudHyMbO2RbJkskbMbFJfIJKWA6R1LCJQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm64-musl": {
+ "version": "4.60.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.60.1.tgz",
+ "integrity": "sha512-+pUymDhd0ys9GcKZPPWlFiZ67sTWV5UU6zOJat02M1+PiuSGDziyRuI/pPue3hoUwm2uGfxdL+trT6Z9rxnlMA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-loong64-gnu": {
+ "version": "4.60.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.60.1.tgz",
+ "integrity": "sha512-VSvgvQeIcsEvY4bKDHEDWcpW4Yw7BtlKG1GUT4FzBUlEKQK0rWHYBqQt6Fm2taXS+1bXvJT6kICu5ZwqKCnvlQ==",
+ "cpu": [
+ "loong64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-loong64-musl": {
+ "version": "4.60.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.60.1.tgz",
+ "integrity": "sha512-4LqhUomJqwe641gsPp6xLfhqWMbQV04KtPp7/dIp0nzPxAkNY1AbwL5W0MQpcalLYk07vaW9Kp1PBhdpZYYcEw==",
+ "cpu": [
+ "loong64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-ppc64-gnu": {
+ "version": "4.60.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.60.1.tgz",
+ "integrity": "sha512-tLQQ9aPvkBxOc/EUT6j3pyeMD6Hb8QF2BTBnCQWP/uu1lhc9AIrIjKnLYMEroIz/JvtGYgI9dF3AxHZNaEH0rw==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-ppc64-musl": {
+ "version": "4.60.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.60.1.tgz",
+ "integrity": "sha512-RMxFhJwc9fSXP6PqmAz4cbv3kAyvD1etJFjTx4ONqFP9DkTkXsAMU4v3Vyc5BgzC+anz7nS/9tp4obsKfqkDHg==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-riscv64-gnu": {
+ "version": "4.60.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.60.1.tgz",
+ "integrity": "sha512-QKgFl+Yc1eEk6MmOBfRHYF6lTxiiiV3/z/BRrbSiW2I7AFTXoBFvdMEyglohPj//2mZS4hDOqeB0H1ACh3sBbg==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-riscv64-musl": {
+ "version": "4.60.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.60.1.tgz",
+ "integrity": "sha512-RAjXjP/8c6ZtzatZcA1RaQr6O1TRhzC+adn8YZDnChliZHviqIjmvFwHcxi4JKPSDAt6Uhf/7vqcBzQJy0PDJg==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-s390x-gnu": {
+ "version": "4.60.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.60.1.tgz",
+ "integrity": "sha512-wcuocpaOlaL1COBYiA89O6yfjlp3RwKDeTIA0hM7OpmhR1Bjo9j31G1uQVpDlTvwxGn2nQs65fBFL5UFd76FcQ==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-x64-gnu": {
+ "version": "4.60.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.60.1.tgz",
+ "integrity": "sha512-77PpsFQUCOiZR9+LQEFg9GClyfkNXj1MP6wRnzYs0EeWbPcHs02AXu4xuUbM1zhwn3wqaizle3AEYg5aeoohhg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-x64-musl": {
+ "version": "4.60.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.60.1.tgz",
+ "integrity": "sha512-5cIATbk5vynAjqqmyBjlciMJl1+R/CwX9oLk/EyiFXDWd95KpHdrOJT//rnUl4cUcskrd0jCCw3wpZnhIHdD9w==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-openbsd-x64": {
+ "version": "4.60.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.60.1.tgz",
+ "integrity": "sha512-cl0w09WsCi17mcmWqqglez9Gk8isgeWvoUZ3WiJFYSR3zjBQc2J5/ihSjpl+VLjPqjQ/1hJRcqBfLjssREQILw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openbsd"
+ ]
+ },
+ "node_modules/@rollup/rollup-openharmony-arm64": {
+ "version": "4.60.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.60.1.tgz",
+ "integrity": "sha512-4Cv23ZrONRbNtbZa37mLSueXUCtN7MXccChtKpUnQNgF010rjrjfHx3QxkS2PI7LqGT5xXyYs1a7LbzAwT0iCA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openharmony"
+ ]
+ },
+ "node_modules/@rollup/rollup-win32-arm64-msvc": {
+ "version": "4.60.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.60.1.tgz",
+ "integrity": "sha512-i1okWYkA4FJICtr7KpYzFpRTHgy5jdDbZiWfvny21iIKky5YExiDXP+zbXzm3dUcFpkEeYNHgQ5fuG236JPq0g==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@rollup/rollup-win32-ia32-msvc": {
+ "version": "4.60.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.60.1.tgz",
+ "integrity": "sha512-u09m3CuwLzShA0EYKMNiFgcjjzwqtUMLmuCJLeZWjjOYA3IT2Di09KaxGBTP9xVztWyIWjVdsB2E9goMjZvTQg==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@rollup/rollup-win32-x64-gnu": {
+ "version": "4.60.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.60.1.tgz",
+ "integrity": "sha512-k+600V9Zl1CM7eZxJgMyTUzmrmhB/0XZnF4pRypKAlAgxmedUA+1v9R+XOFv56W4SlHEzfeMtzujLJD22Uz5zg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@rollup/rollup-win32-x64-msvc": {
+ "version": "4.60.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.60.1.tgz",
+ "integrity": "sha512-lWMnixq/QzxyhTV6NjQJ4SFo1J6PvOX8vUx5Wb4bBPsEb+8xZ89Bz6kOXpfXj9ak9AHTQVQzlgzBEc1SyM27xQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@shikijs/core": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-2.5.0.tgz",
+ "integrity": "sha512-uu/8RExTKtavlpH7XqnVYBrfBkUc20ngXiX9NSrBhOVZYv/7XQRKUyhtkeflY5QsxC0GbJThCerruZfsUaSldg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@shikijs/engine-javascript": "2.5.0",
+ "@shikijs/engine-oniguruma": "2.5.0",
+ "@shikijs/types": "2.5.0",
+ "@shikijs/vscode-textmate": "^10.0.2",
+ "@types/hast": "^3.0.4",
+ "hast-util-to-html": "^9.0.4"
+ }
+ },
+ "node_modules/@shikijs/engine-javascript": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-2.5.0.tgz",
+ "integrity": "sha512-VjnOpnQf8WuCEZtNUdjjwGUbtAVKuZkVQ/5cHy/tojVVRIRtlWMYVjyWhxOmIq05AlSOv72z7hRNRGVBgQOl0w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@shikijs/types": "2.5.0",
+ "@shikijs/vscode-textmate": "^10.0.2",
+ "oniguruma-to-es": "^3.1.0"
+ }
+ },
+ "node_modules/@shikijs/engine-oniguruma": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-2.5.0.tgz",
+ "integrity": "sha512-pGd1wRATzbo/uatrCIILlAdFVKdxImWJGQ5rFiB5VZi2ve5xj3Ax9jny8QvkaV93btQEwR/rSz5ERFpC5mKNIw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@shikijs/types": "2.5.0",
+ "@shikijs/vscode-textmate": "^10.0.2"
+ }
+ },
+ "node_modules/@shikijs/langs": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-2.5.0.tgz",
+ "integrity": "sha512-Qfrrt5OsNH5R+5tJ/3uYBBZv3SuGmnRPejV9IlIbFH3HTGLDlkqgHymAlzklVmKBjAaVmkPkyikAV/sQ1wSL+w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@shikijs/types": "2.5.0"
+ }
+ },
+ "node_modules/@shikijs/themes": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-2.5.0.tgz",
+ "integrity": "sha512-wGrk+R8tJnO0VMzmUExHR+QdSaPUl/NKs+a4cQQRWyoc3YFbUzuLEi/KWK1hj+8BfHRKm2jNhhJck1dfstJpiw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@shikijs/types": "2.5.0"
+ }
+ },
+ "node_modules/@shikijs/transformers": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/@shikijs/transformers/-/transformers-2.5.0.tgz",
+ "integrity": "sha512-SI494W5X60CaUwgi8u4q4m4s3YAFSxln3tzNjOSYqq54wlVgz0/NbbXEb3mdLbqMBztcmS7bVTaEd2w0qMmfeg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@shikijs/core": "2.5.0",
+ "@shikijs/types": "2.5.0"
+ }
+ },
+ "node_modules/@shikijs/types": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-2.5.0.tgz",
+ "integrity": "sha512-ygl5yhxki9ZLNuNpPitBWvcy9fsSKKaRuO4BAlMyagszQidxcpLAr0qiW/q43DtSIDxO6hEbtYLiFZNXO/hdGw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@shikijs/vscode-textmate": "^10.0.2",
+ "@types/hast": "^3.0.4"
+ }
+ },
+ "node_modules/@shikijs/vscode-textmate": {
+ "version": "10.0.2",
+ "resolved": "https://registry.npmjs.org/@shikijs/vscode-textmate/-/vscode-textmate-10.0.2.tgz",
+ "integrity": "sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/estree": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
+ "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/hast": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz",
+ "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "*"
+ }
+ },
+ "node_modules/@types/linkify-it": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-5.0.0.tgz",
+ "integrity": "sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/markdown-it": {
+ "version": "14.1.2",
+ "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-14.1.2.tgz",
+ "integrity": "sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/linkify-it": "^5",
+ "@types/mdurl": "^2"
+ }
+ },
+ "node_modules/@types/mdast": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz",
+ "integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "*"
+ }
+ },
+ "node_modules/@types/mdurl": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-2.0.0.tgz",
+ "integrity": "sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/unist": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz",
+ "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/web-bluetooth": {
+ "version": "0.0.21",
+ "resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.21.tgz",
+ "integrity": "sha512-oIQLCGWtcFZy2JW77j9k8nHzAOpqMHLQejDA48XXMWH6tjCQHz5RCFz1bzsmROyL6PUm+LLnUiI4BCn221inxA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@ungap/structured-clone": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz",
+ "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/@vitejs/plugin-vue": {
+ "version": "5.2.4",
+ "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-5.2.4.tgz",
+ "integrity": "sha512-7Yx/SXSOcQq5HiiV3orevHUFn+pmMB4cgbEkDYgnkUWb0WfeQ/wa2yFv6D5ICiCQOVpjA7vYDXrC7AGO8yjDHA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^18.0.0 || >=20.0.0"
+ },
+ "peerDependencies": {
+ "vite": "^5.0.0 || ^6.0.0",
+ "vue": "^3.2.25"
+ }
+ },
+ "node_modules/@vue/compiler-core": {
+ "version": "3.5.32",
+ "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.32.tgz",
+ "integrity": "sha512-4x74Tbtqnda8s/NSD6e1Dr5p1c8HdMU5RWSjMSUzb8RTcUQqevDCxVAitcLBKT+ie3o0Dl9crc/S/opJM7qBGQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/parser": "^7.29.2",
+ "@vue/shared": "3.5.32",
+ "entities": "^7.0.1",
+ "estree-walker": "^2.0.2",
+ "source-map-js": "^1.2.1"
+ }
+ },
+ "node_modules/@vue/compiler-dom": {
+ "version": "3.5.32",
+ "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.32.tgz",
+ "integrity": "sha512-ybHAu70NtiEI1fvAUz3oXZqkUYEe5J98GjMDpTGl5iHb0T15wQYLR4wE3h9xfuTNA+Cm2f4czfe8B4s+CCH57Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@vue/compiler-core": "3.5.32",
+ "@vue/shared": "3.5.32"
+ }
+ },
+ "node_modules/@vue/compiler-sfc": {
+ "version": "3.5.32",
+ "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.32.tgz",
+ "integrity": "sha512-8UYUYo71cP/0YHMO814TRZlPuUUw3oifHuMR7Wp9SNoRSrxRQnhMLNlCeaODNn6kNTJsjFoQ/kqIj4qGvya4Xg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/parser": "^7.29.2",
+ "@vue/compiler-core": "3.5.32",
+ "@vue/compiler-dom": "3.5.32",
+ "@vue/compiler-ssr": "3.5.32",
+ "@vue/shared": "3.5.32",
+ "estree-walker": "^2.0.2",
+ "magic-string": "^0.30.21",
+ "postcss": "^8.5.8",
+ "source-map-js": "^1.2.1"
+ }
+ },
+ "node_modules/@vue/compiler-ssr": {
+ "version": "3.5.32",
+ "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.32.tgz",
+ "integrity": "sha512-Gp4gTs22T3DgRotZ8aA/6m2jMR+GMztvBXUBEUOYOcST+giyGWJ4WvFd7QLHBkzTxkfOt8IELKNdpzITLbA2rw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@vue/compiler-dom": "3.5.32",
+ "@vue/shared": "3.5.32"
+ }
+ },
+ "node_modules/@vue/devtools-api": {
+ "version": "7.7.9",
+ "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-7.7.9.tgz",
+ "integrity": "sha512-kIE8wvwlcZ6TJTbNeU2HQNtaxLx3a84aotTITUuL/4bzfPxzajGBOoqjMhwZJ8L9qFYDU/lAYMEEm11dnZOD6g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@vue/devtools-kit": "^7.7.9"
+ }
+ },
+ "node_modules/@vue/devtools-kit": {
+ "version": "7.7.9",
+ "resolved": "https://registry.npmjs.org/@vue/devtools-kit/-/devtools-kit-7.7.9.tgz",
+ "integrity": "sha512-PyQ6odHSgiDVd4hnTP+aDk2X4gl2HmLDfiyEnn3/oV+ckFDuswRs4IbBT7vacMuGdwY/XemxBoh302ctbsptuA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@vue/devtools-shared": "^7.7.9",
+ "birpc": "^2.3.0",
+ "hookable": "^5.5.3",
+ "mitt": "^3.0.1",
+ "perfect-debounce": "^1.0.0",
+ "speakingurl": "^14.0.1",
+ "superjson": "^2.2.2"
+ }
+ },
+ "node_modules/@vue/devtools-shared": {
+ "version": "7.7.9",
+ "resolved": "https://registry.npmjs.org/@vue/devtools-shared/-/devtools-shared-7.7.9.tgz",
+ "integrity": "sha512-iWAb0v2WYf0QWmxCGy0seZNDPdO3Sp5+u78ORnyeonS6MT4PC7VPrryX2BpMJrwlDeaZ6BD4vP4XKjK0SZqaeA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "rfdc": "^1.4.1"
+ }
+ },
+ "node_modules/@vue/reactivity": {
+ "version": "3.5.32",
+ "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.32.tgz",
+ "integrity": "sha512-/ORasxSGvZ6MN5gc+uE364SxFdJ0+WqVG0CENXaGW58TOCdrAW76WWaplDtECeS1qphvtBZtR+3/o1g1zL4xPQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@vue/shared": "3.5.32"
+ }
+ },
+ "node_modules/@vue/runtime-core": {
+ "version": "3.5.32",
+ "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.32.tgz",
+ "integrity": "sha512-pDrXCejn4UpFDFmMd27AcJEbHaLemaE5o4pbb7sLk79SRIhc6/t34BQA7SGNgYtbMnvbF/HHOftYBgFJtUoJUQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@vue/reactivity": "3.5.32",
+ "@vue/shared": "3.5.32"
+ }
+ },
+ "node_modules/@vue/runtime-dom": {
+ "version": "3.5.32",
+ "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.32.tgz",
+ "integrity": "sha512-1CDVv7tv/IV13V8Nip1k/aaObVbWqRlVCVezTwx3K07p7Vxossp5JU1dcPNhJk3w347gonIUT9jQOGutyJrSVQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@vue/reactivity": "3.5.32",
+ "@vue/runtime-core": "3.5.32",
+ "@vue/shared": "3.5.32",
+ "csstype": "^3.2.3"
+ }
+ },
+ "node_modules/@vue/server-renderer": {
+ "version": "3.5.32",
+ "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.32.tgz",
+ "integrity": "sha512-IOjm2+JQwRFS7W28HNuJeXQle9KdZbODFY7hFGVtnnghF51ta20EWAZJHX+zLGtsHhaU6uC9BGPV52KVpYryMQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@vue/compiler-ssr": "3.5.32",
+ "@vue/shared": "3.5.32"
+ },
+ "peerDependencies": {
+ "vue": "3.5.32"
+ }
+ },
+ "node_modules/@vue/shared": {
+ "version": "3.5.32",
+ "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.32.tgz",
+ "integrity": "sha512-ksNyrmRQzWJJ8n3cRDuSF7zNNontuJg1YHnmWRJd2AMu8Ij2bqwiiri2lH5rHtYPZjj4STkNcgcmiQqlOjiYGg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@vueuse/core": {
+ "version": "12.8.2",
+ "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-12.8.2.tgz",
+ "integrity": "sha512-HbvCmZdzAu3VGi/pWYm5Ut+Kd9mn1ZHnn4L5G8kOQTPs/IwIAmJoBrmYk2ckLArgMXZj0AW3n5CAejLUO+PhdQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/web-bluetooth": "^0.0.21",
+ "@vueuse/metadata": "12.8.2",
+ "@vueuse/shared": "12.8.2",
+ "vue": "^3.5.13"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/antfu"
+ }
+ },
+ "node_modules/@vueuse/integrations": {
+ "version": "12.8.2",
+ "resolved": "https://registry.npmjs.org/@vueuse/integrations/-/integrations-12.8.2.tgz",
+ "integrity": "sha512-fbGYivgK5uBTRt7p5F3zy6VrETlV9RtZjBqd1/HxGdjdckBgBM4ugP8LHpjolqTj14TXTxSK1ZfgPbHYyGuH7g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@vueuse/core": "12.8.2",
+ "@vueuse/shared": "12.8.2",
+ "vue": "^3.5.13"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/antfu"
+ },
+ "peerDependencies": {
+ "async-validator": "^4",
+ "axios": "^1",
+ "change-case": "^5",
+ "drauu": "^0.4",
+ "focus-trap": "^7",
+ "fuse.js": "^7",
+ "idb-keyval": "^6",
+ "jwt-decode": "^4",
+ "nprogress": "^0.2",
+ "qrcode": "^1.5",
+ "sortablejs": "^1",
+ "universal-cookie": "^7"
+ },
+ "peerDependenciesMeta": {
+ "async-validator": {
+ "optional": true
+ },
+ "axios": {
+ "optional": true
+ },
+ "change-case": {
+ "optional": true
+ },
+ "drauu": {
+ "optional": true
+ },
+ "focus-trap": {
+ "optional": true
+ },
+ "fuse.js": {
+ "optional": true
+ },
+ "idb-keyval": {
+ "optional": true
+ },
+ "jwt-decode": {
+ "optional": true
+ },
+ "nprogress": {
+ "optional": true
+ },
+ "qrcode": {
+ "optional": true
+ },
+ "sortablejs": {
+ "optional": true
+ },
+ "universal-cookie": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@vueuse/metadata": {
+ "version": "12.8.2",
+ "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-12.8.2.tgz",
+ "integrity": "sha512-rAyLGEuoBJ/Il5AmFHiziCPdQzRt88VxR+Y/A/QhJ1EWtWqPBBAxTAFaSkviwEuOEZNtW8pvkPgoCZQ+HxqW1A==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/antfu"
+ }
+ },
+ "node_modules/@vueuse/shared": {
+ "version": "12.8.2",
+ "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-12.8.2.tgz",
+ "integrity": "sha512-dznP38YzxZoNloI0qpEfpkms8knDtaoQ6Y/sfS0L7Yki4zh40LFHEhur0odJC6xTHG5dxWVPiUWBXn+wCG2s5w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "vue": "^3.5.13"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/antfu"
+ }
+ },
+ "node_modules/algoliasearch": {
+ "version": "5.50.1",
+ "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-5.50.1.tgz",
+ "integrity": "sha512-/bwdue1/8LWELn/DBalGRfuLsXBLXULJo/yOeavJtDu8rBwxIzC6/Rz9Jg19S21VkJvRuZO1k8CZXBMS73mYbA==",
+ "dev": true,
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@algolia/abtesting": "1.16.1",
+ "@algolia/client-abtesting": "5.50.1",
+ "@algolia/client-analytics": "5.50.1",
+ "@algolia/client-common": "5.50.1",
+ "@algolia/client-insights": "5.50.1",
+ "@algolia/client-personalization": "5.50.1",
+ "@algolia/client-query-suggestions": "5.50.1",
+ "@algolia/client-search": "5.50.1",
+ "@algolia/ingestion": "1.50.1",
+ "@algolia/monitoring": "1.50.1",
+ "@algolia/recommend": "5.50.1",
+ "@algolia/requester-browser-xhr": "5.50.1",
+ "@algolia/requester-fetch": "5.50.1",
+ "@algolia/requester-node-http": "5.50.1"
+ },
+ "engines": {
+ "node": ">= 14.0.0"
+ }
+ },
+ "node_modules/birpc": {
+ "version": "2.9.0",
+ "resolved": "https://registry.npmjs.org/birpc/-/birpc-2.9.0.tgz",
+ "integrity": "sha512-KrayHS5pBi69Xi9JmvoqrIgYGDkD6mcSe/i6YKi3w5kekCLzrX4+nawcXqrj2tIp50Kw/mT/s3p+GVK0A0sKxw==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/antfu"
+ }
+ },
+ "node_modules/ccount": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz",
+ "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/character-entities-html4": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-2.1.0.tgz",
+ "integrity": "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/character-entities-legacy": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz",
+ "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/comma-separated-tokens": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz",
+ "integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/copy-anything": {
+ "version": "4.0.5",
+ "resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-4.0.5.tgz",
+ "integrity": "sha512-7Vv6asjS4gMOuILabD3l739tsaxFQmC+a7pLZm02zyvs8p977bL3zEgq3yDk5rn9B0PbYgIv++jmHcuUab4RhA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-what": "^5.2.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/mesqueeb"
+ }
+ },
+ "node_modules/csstype": {
+ "version": "3.2.3",
+ "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz",
+ "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/dequal": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz",
+ "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/devlop": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz",
+ "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "dequal": "^2.0.0"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/emoji-regex-xs": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex-xs/-/emoji-regex-xs-1.0.0.tgz",
+ "integrity": "sha512-LRlerrMYoIDrT6jgpeZ2YYl/L8EulRTt5hQcYjy5AInh7HWXKimpqx68aknBFpGL2+/IcogTcaydJEgaTmOpDg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/entities": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/entities/-/entities-7.0.1.tgz",
+ "integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=0.12"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/entities?sponsor=1"
+ }
+ },
+ "node_modules/esbuild": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz",
+ "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==",
+ "dev": true,
+ "hasInstallScript": true,
+ "license": "MIT",
+ "bin": {
+ "esbuild": "bin/esbuild"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "optionalDependencies": {
+ "@esbuild/aix-ppc64": "0.21.5",
+ "@esbuild/android-arm": "0.21.5",
+ "@esbuild/android-arm64": "0.21.5",
+ "@esbuild/android-x64": "0.21.5",
+ "@esbuild/darwin-arm64": "0.21.5",
+ "@esbuild/darwin-x64": "0.21.5",
+ "@esbuild/freebsd-arm64": "0.21.5",
+ "@esbuild/freebsd-x64": "0.21.5",
+ "@esbuild/linux-arm": "0.21.5",
+ "@esbuild/linux-arm64": "0.21.5",
+ "@esbuild/linux-ia32": "0.21.5",
+ "@esbuild/linux-loong64": "0.21.5",
+ "@esbuild/linux-mips64el": "0.21.5",
+ "@esbuild/linux-ppc64": "0.21.5",
+ "@esbuild/linux-riscv64": "0.21.5",
+ "@esbuild/linux-s390x": "0.21.5",
+ "@esbuild/linux-x64": "0.21.5",
+ "@esbuild/netbsd-x64": "0.21.5",
+ "@esbuild/openbsd-x64": "0.21.5",
+ "@esbuild/sunos-x64": "0.21.5",
+ "@esbuild/win32-arm64": "0.21.5",
+ "@esbuild/win32-ia32": "0.21.5",
+ "@esbuild/win32-x64": "0.21.5"
+ }
+ },
+ "node_modules/estree-walker": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
+ "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/focus-trap": {
+ "version": "7.8.0",
+ "resolved": "https://registry.npmjs.org/focus-trap/-/focus-trap-7.8.0.tgz",
+ "integrity": "sha512-/yNdlIkpWbM0ptxno3ONTuf+2g318kh2ez3KSeZN5dZ8YC6AAmgeWz+GasYYiBJPFaYcSAPeu4GfhUaChzIJXA==",
+ "dev": true,
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "tabbable": "^6.4.0"
+ }
+ },
+ "node_modules/fsevents": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
+ "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
+ "dev": true,
+ "hasInstallScript": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+ }
+ },
+ "node_modules/hast-util-to-html": {
+ "version": "9.0.5",
+ "resolved": "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-9.0.5.tgz",
+ "integrity": "sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/hast": "^3.0.0",
+ "@types/unist": "^3.0.0",
+ "ccount": "^2.0.0",
+ "comma-separated-tokens": "^2.0.0",
+ "hast-util-whitespace": "^3.0.0",
+ "html-void-elements": "^3.0.0",
+ "mdast-util-to-hast": "^13.0.0",
+ "property-information": "^7.0.0",
+ "space-separated-tokens": "^2.0.0",
+ "stringify-entities": "^4.0.0",
+ "zwitch": "^2.0.4"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/hast-util-whitespace": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz",
+ "integrity": "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/hast": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/hookable": {
+ "version": "5.5.3",
+ "resolved": "https://registry.npmjs.org/hookable/-/hookable-5.5.3.tgz",
+ "integrity": "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/html-void-elements": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-3.0.0.tgz",
+ "integrity": "sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/is-what": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/is-what/-/is-what-5.5.0.tgz",
+ "integrity": "sha512-oG7cgbmg5kLYae2N5IVd3jm2s+vldjxJzK1pcu9LfpGuQ93MQSzo0okvRna+7y5ifrD+20FE8FvjusyGaz14fw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/mesqueeb"
+ }
+ },
+ "node_modules/magic-string": {
+ "version": "0.30.21",
+ "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz",
+ "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/sourcemap-codec": "^1.5.5"
+ }
+ },
+ "node_modules/mark.js": {
+ "version": "8.11.1",
+ "resolved": "https://registry.npmjs.org/mark.js/-/mark.js-8.11.1.tgz",
+ "integrity": "sha512-1I+1qpDt4idfgLQG+BNWmrqku+7/2bi5nLf4YwF8y8zXvmfiTBY3PV3ZibfrjBueCByROpuBjLLFCajqkgYoLQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/mdast-util-to-hast": {
+ "version": "13.2.1",
+ "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.1.tgz",
+ "integrity": "sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/hast": "^3.0.0",
+ "@types/mdast": "^4.0.0",
+ "@ungap/structured-clone": "^1.0.0",
+ "devlop": "^1.0.0",
+ "micromark-util-sanitize-uri": "^2.0.0",
+ "trim-lines": "^3.0.0",
+ "unist-util-position": "^5.0.0",
+ "unist-util-visit": "^5.0.0",
+ "vfile": "^6.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/micromark-util-character": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz",
+ "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "micromark-util-symbol": "^2.0.0",
+ "micromark-util-types": "^2.0.0"
+ }
+ },
+ "node_modules/micromark-util-encode": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.1.tgz",
+ "integrity": "sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/micromark-util-sanitize-uri": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.1.tgz",
+ "integrity": "sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "micromark-util-character": "^2.0.0",
+ "micromark-util-encode": "^2.0.0",
+ "micromark-util-symbol": "^2.0.0"
+ }
+ },
+ "node_modules/micromark-util-symbol": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz",
+ "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/micromark-util-types": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.2.tgz",
+ "integrity": "sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/minisearch": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/minisearch/-/minisearch-7.2.0.tgz",
+ "integrity": "sha512-dqT2XBYUOZOiC5t2HRnwADjhNS2cecp9u+TJRiJ1Qp/f5qjkeT5APcGPjHw+bz89Ms8Jp+cG4AlE+QZ/QnDglg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/mitt": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz",
+ "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/nanoid": {
+ "version": "3.3.11",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
+ "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "bin": {
+ "nanoid": "bin/nanoid.cjs"
+ },
+ "engines": {
+ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
+ }
+ },
+ "node_modules/oniguruma-to-es": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/oniguruma-to-es/-/oniguruma-to-es-3.1.1.tgz",
+ "integrity": "sha512-bUH8SDvPkH3ho3dvwJwfonjlQ4R80vjyvrU8YpxuROddv55vAEJrTuCuCVUhhsHbtlD9tGGbaNApGQckXhS8iQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "emoji-regex-xs": "^1.0.0",
+ "regex": "^6.0.1",
+ "regex-recursion": "^6.0.2"
+ }
+ },
+ "node_modules/perfect-debounce": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-1.0.0.tgz",
+ "integrity": "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/picocolors": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
+ "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/postcss": {
+ "version": "8.5.8",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.8.tgz",
+ "integrity": "sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/postcss"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "nanoid": "^3.3.11",
+ "picocolors": "^1.1.1",
+ "source-map-js": "^1.2.1"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14"
+ }
+ },
+ "node_modules/preact": {
+ "version": "10.29.1",
+ "resolved": "https://registry.npmjs.org/preact/-/preact-10.29.1.tgz",
+ "integrity": "sha512-gQCLc/vWroE8lIpleXtdJhTFDogTdZG9AjMUpVkDf2iTCNwYNWA+u16dL41TqUDJO4gm2IgrcMv3uTpjd4Pwmg==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/preact"
+ }
+ },
+ "node_modules/property-information": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/property-information/-/property-information-7.1.0.tgz",
+ "integrity": "sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/regex": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/regex/-/regex-6.1.0.tgz",
+ "integrity": "sha512-6VwtthbV4o/7+OaAF9I5L5V3llLEsoPyq9P1JVXkedTP33c7MfCG0/5NOPcSJn0TzXcG9YUrR0gQSWioew3LDg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "regex-utilities": "^2.3.0"
+ }
+ },
+ "node_modules/regex-recursion": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/regex-recursion/-/regex-recursion-6.0.2.tgz",
+ "integrity": "sha512-0YCaSCq2VRIebiaUviZNs0cBz1kg5kVS2UKUfNIx8YVs1cN3AV7NTctO5FOKBA+UT2BPJIWZauYHPqJODG50cg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "regex-utilities": "^2.3.0"
+ }
+ },
+ "node_modules/regex-utilities": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/regex-utilities/-/regex-utilities-2.3.0.tgz",
+ "integrity": "sha512-8VhliFJAWRaUiVvREIiW2NXXTmHs4vMNnSzuJVhscgmGav3g9VDxLrQndI3dZZVVdp0ZO/5v0xmX516/7M9cng==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/rfdc": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz",
+ "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/rollup": {
+ "version": "4.60.1",
+ "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.60.1.tgz",
+ "integrity": "sha512-VmtB2rFU/GroZ4oL8+ZqXgSA38O6GR8KSIvWmEFv63pQ0G6KaBH9s07PO8XTXP4vI+3UJUEypOfjkGfmSBBR0w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree": "1.0.8"
+ },
+ "bin": {
+ "rollup": "dist/bin/rollup"
+ },
+ "engines": {
+ "node": ">=18.0.0",
+ "npm": ">=8.0.0"
+ },
+ "optionalDependencies": {
+ "@rollup/rollup-android-arm-eabi": "4.60.1",
+ "@rollup/rollup-android-arm64": "4.60.1",
+ "@rollup/rollup-darwin-arm64": "4.60.1",
+ "@rollup/rollup-darwin-x64": "4.60.1",
+ "@rollup/rollup-freebsd-arm64": "4.60.1",
+ "@rollup/rollup-freebsd-x64": "4.60.1",
+ "@rollup/rollup-linux-arm-gnueabihf": "4.60.1",
+ "@rollup/rollup-linux-arm-musleabihf": "4.60.1",
+ "@rollup/rollup-linux-arm64-gnu": "4.60.1",
+ "@rollup/rollup-linux-arm64-musl": "4.60.1",
+ "@rollup/rollup-linux-loong64-gnu": "4.60.1",
+ "@rollup/rollup-linux-loong64-musl": "4.60.1",
+ "@rollup/rollup-linux-ppc64-gnu": "4.60.1",
+ "@rollup/rollup-linux-ppc64-musl": "4.60.1",
+ "@rollup/rollup-linux-riscv64-gnu": "4.60.1",
+ "@rollup/rollup-linux-riscv64-musl": "4.60.1",
+ "@rollup/rollup-linux-s390x-gnu": "4.60.1",
+ "@rollup/rollup-linux-x64-gnu": "4.60.1",
+ "@rollup/rollup-linux-x64-musl": "4.60.1",
+ "@rollup/rollup-openbsd-x64": "4.60.1",
+ "@rollup/rollup-openharmony-arm64": "4.60.1",
+ "@rollup/rollup-win32-arm64-msvc": "4.60.1",
+ "@rollup/rollup-win32-ia32-msvc": "4.60.1",
+ "@rollup/rollup-win32-x64-gnu": "4.60.1",
+ "@rollup/rollup-win32-x64-msvc": "4.60.1",
+ "fsevents": "~2.3.2"
+ }
+ },
+ "node_modules/search-insights": {
+ "version": "2.17.3",
+ "resolved": "https://registry.npmjs.org/search-insights/-/search-insights-2.17.3.tgz",
+ "integrity": "sha512-RQPdCYTa8A68uM2jwxoY842xDhvx3E5LFL1LxvxCNMev4o5mLuokczhzjAgGwUZBAmOKZknArSxLKmXtIi2AxQ==",
+ "dev": true,
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/shiki": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/shiki/-/shiki-2.5.0.tgz",
+ "integrity": "sha512-mI//trrsaiCIPsja5CNfsyNOqgAZUb6VpJA+340toL42UpzQlXpwRV9nch69X6gaUxrr9kaOOa6e3y3uAkGFxQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@shikijs/core": "2.5.0",
+ "@shikijs/engine-javascript": "2.5.0",
+ "@shikijs/engine-oniguruma": "2.5.0",
+ "@shikijs/langs": "2.5.0",
+ "@shikijs/themes": "2.5.0",
+ "@shikijs/types": "2.5.0",
+ "@shikijs/vscode-textmate": "^10.0.2",
+ "@types/hast": "^3.0.4"
+ }
+ },
+ "node_modules/source-map-js": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
+ "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/space-separated-tokens": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz",
+ "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/speakingurl": {
+ "version": "14.0.1",
+ "resolved": "https://registry.npmjs.org/speakingurl/-/speakingurl-14.0.1.tgz",
+ "integrity": "sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/stringify-entities": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz",
+ "integrity": "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "character-entities-html4": "^2.0.0",
+ "character-entities-legacy": "^3.0.0"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/superjson": {
+ "version": "2.2.6",
+ "resolved": "https://registry.npmjs.org/superjson/-/superjson-2.2.6.tgz",
+ "integrity": "sha512-H+ue8Zo4vJmV2nRjpx86P35lzwDT3nItnIsocgumgr0hHMQ+ZGq5vrERg9kJBo5AWGmxZDhzDo+WVIJqkB0cGA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "copy-anything": "^4"
+ },
+ "engines": {
+ "node": ">=16"
+ }
+ },
+ "node_modules/tabbable": {
+ "version": "6.4.0",
+ "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.4.0.tgz",
+ "integrity": "sha512-05PUHKSNE8ou2dwIxTngl4EzcnsCDZGJ/iCLtDflR/SHB/ny14rXc+qU5P4mG9JkusiV7EivzY9Mhm55AzAvCg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/trim-lines": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz",
+ "integrity": "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/unist-util-is": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.1.tgz",
+ "integrity": "sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/unist-util-position": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-5.0.0.tgz",
+ "integrity": "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/unist-util-stringify-position": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz",
+ "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/unist-util-visit": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.1.0.tgz",
+ "integrity": "sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "^3.0.0",
+ "unist-util-is": "^6.0.0",
+ "unist-util-visit-parents": "^6.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/unist-util-visit-parents": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.2.tgz",
+ "integrity": "sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "^3.0.0",
+ "unist-util-is": "^6.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/vfile": {
+ "version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz",
+ "integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "^3.0.0",
+ "vfile-message": "^4.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/vfile-message": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.3.tgz",
+ "integrity": "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "^3.0.0",
+ "unist-util-stringify-position": "^4.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/vite": {
+ "version": "5.4.21",
+ "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.21.tgz",
+ "integrity": "sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==",
+ "dev": true,
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "esbuild": "^0.21.3",
+ "postcss": "^8.4.43",
+ "rollup": "^4.20.0"
+ },
+ "bin": {
+ "vite": "bin/vite.js"
+ },
+ "engines": {
+ "node": "^18.0.0 || >=20.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/vitejs/vite?sponsor=1"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.3"
+ },
+ "peerDependencies": {
+ "@types/node": "^18.0.0 || >=20.0.0",
+ "less": "*",
+ "lightningcss": "^1.21.0",
+ "sass": "*",
+ "sass-embedded": "*",
+ "stylus": "*",
+ "sugarss": "*",
+ "terser": "^5.4.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/node": {
+ "optional": true
+ },
+ "less": {
+ "optional": true
+ },
+ "lightningcss": {
+ "optional": true
+ },
+ "sass": {
+ "optional": true
+ },
+ "sass-embedded": {
+ "optional": true
+ },
+ "stylus": {
+ "optional": true
+ },
+ "sugarss": {
+ "optional": true
+ },
+ "terser": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/vitepress": {
+ "version": "1.6.4",
+ "resolved": "https://registry.npmjs.org/vitepress/-/vitepress-1.6.4.tgz",
+ "integrity": "sha512-+2ym1/+0VVrbhNyRoFFesVvBvHAVMZMK0rw60E3X/5349M1GuVdKeazuksqopEdvkKwKGs21Q729jX81/bkBJg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@docsearch/css": "3.8.2",
+ "@docsearch/js": "3.8.2",
+ "@iconify-json/simple-icons": "^1.2.21",
+ "@shikijs/core": "^2.1.0",
+ "@shikijs/transformers": "^2.1.0",
+ "@shikijs/types": "^2.1.0",
+ "@types/markdown-it": "^14.1.2",
+ "@vitejs/plugin-vue": "^5.2.1",
+ "@vue/devtools-api": "^7.7.0",
+ "@vue/shared": "^3.5.13",
+ "@vueuse/core": "^12.4.0",
+ "@vueuse/integrations": "^12.4.0",
+ "focus-trap": "^7.6.4",
+ "mark.js": "8.11.1",
+ "minisearch": "^7.1.1",
+ "shiki": "^2.1.0",
+ "vite": "^5.4.14",
+ "vue": "^3.5.13"
+ },
+ "bin": {
+ "vitepress": "bin/vitepress.js"
+ },
+ "peerDependencies": {
+ "markdown-it-mathjax3": "^4",
+ "postcss": "^8"
+ },
+ "peerDependenciesMeta": {
+ "markdown-it-mathjax3": {
+ "optional": true
+ },
+ "postcss": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/vue": {
+ "version": "3.5.32",
+ "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.32.tgz",
+ "integrity": "sha512-vM4z4Q9tTafVfMAK7IVzmxg34rSzTFMyIe0UUEijUCkn9+23lj0WRfA83dg7eQZIUlgOSGrkViIaCfqSAUXsMw==",
+ "dev": true,
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@vue/compiler-dom": "3.5.32",
+ "@vue/compiler-sfc": "3.5.32",
+ "@vue/runtime-dom": "3.5.32",
+ "@vue/server-renderer": "3.5.32",
+ "@vue/shared": "3.5.32"
+ },
+ "peerDependencies": {
+ "typescript": "*"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/zwitch": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz",
+ "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ }
+ }
+}
diff --git a/docs/package.json b/docs/package.json
new file mode 100644
index 0000000..d85eeaa
--- /dev/null
+++ b/docs/package.json
@@ -0,0 +1,13 @@
+{
+ "name": "afdocs-docs",
+ "private": true,
+ "type": "module",
+ "scripts": {
+ "dev": "vitepress dev",
+ "build": "./generate_llms_txt && vitepress build && ./generate_agent_md",
+ "preview": "vitepress preview"
+ },
+ "devDependencies": {
+ "vitepress": "^1.6.3"
+ }
+}
diff --git a/docs/public/.htaccess b/docs/public/.htaccess
new file mode 100644
index 0000000..a9ff08e
--- /dev/null
+++ b/docs/public/.htaccess
@@ -0,0 +1,57 @@
+# Prevent Apache's MultiViews from serving index.html when index.md is requested
+Options -MultiViews
+
+RewriteEngine On
+
+# --- Agent signal tracking ---
+# Routes requests likely from agents through a PHP shim that logs
+# full request headers before serving the file. Three triggers:
+#
+# 1. Content negotiation: Accept header requests text/markdown
+# 2. Direct .md requests: explicit markdown URL
+# 3. llms.txt requests: agent discovery file
+
+# 1. Content negotiation — directory with index.md
+RewriteCond %{HTTP_ACCEPT} text/markdown
+RewriteCond %{REQUEST_FILENAME} -d
+RewriteCond %{REQUEST_FILENAME}/index.md -f
+RewriteRule ^(.*)$ /log-agent-signal.php?path=$1/index.md&trigger=content-negotiation [L,QSA]
+
+# 1. Content negotiation — file with .md equivalent
+RewriteCond %{HTTP_ACCEPT} text/markdown
+RewriteCond %{REQUEST_FILENAME}.md -f
+RewriteRule ^(.*)$ /log-agent-signal.php?path=$1.md&trigger=content-negotiation [L,QSA]
+
+# 2. Direct .md file requests
+RewriteCond %{REQUEST_URI} \.md$
+RewriteCond %{REQUEST_FILENAME} -f
+RewriteRule ^(.*)$ /log-agent-signal.php?path=$1&trigger=direct-md [L,QSA]
+
+# 3. llms.txt requests
+RewriteRule ^llms\.txt$ /log-agent-signal.php?path=llms.txt&trigger=llms-txt [L,QSA]
+
+# VitePress flat HTML: serve /page.html when /page or /page/ is requested.
+# VitePress builds non-index pages as flat .html files (quick-start.html),
+# not directories (quick-start/index.html). This rule maps trailing-slash
+# URLs to their .html counterparts so the directive check can fetch them.
+RewriteCond %{REQUEST_FILENAME} !-f
+RewriteCond %{REQUEST_FILENAME} !-d
+RewriteRule ^(.*?)/?$ /$1.html [L]
+
+# Serve .md files with the correct content type
+AddType text/markdown .md
+
+# Cache headers for agent-facing resources
+# The PHP shim serves .md and .txt files; set cache headers on its responses
+# so Dreamhost's proxy doesn't add its default max-age=172800
+
+ Header set Cache-Control "max-age=3600, must-revalidate"
+
+
+
+ Header set Cache-Control "max-age=3600, must-revalidate"
+
+
+
+ Header set Cache-Control "max-age=3600, must-revalidate"
+
diff --git a/docs/public/favicons/android-icon-144x144.png b/docs/public/favicons/android-icon-144x144.png
new file mode 100644
index 0000000..48d37fc
Binary files /dev/null and b/docs/public/favicons/android-icon-144x144.png differ
diff --git a/docs/public/favicons/android-icon-192x192.png b/docs/public/favicons/android-icon-192x192.png
new file mode 100644
index 0000000..92288e9
Binary files /dev/null and b/docs/public/favicons/android-icon-192x192.png differ
diff --git a/docs/public/favicons/android-icon-36x36.png b/docs/public/favicons/android-icon-36x36.png
new file mode 100644
index 0000000..54f39fa
Binary files /dev/null and b/docs/public/favicons/android-icon-36x36.png differ
diff --git a/docs/public/favicons/android-icon-48x48.png b/docs/public/favicons/android-icon-48x48.png
new file mode 100644
index 0000000..adc0971
Binary files /dev/null and b/docs/public/favicons/android-icon-48x48.png differ
diff --git a/docs/public/favicons/android-icon-72x72.png b/docs/public/favicons/android-icon-72x72.png
new file mode 100644
index 0000000..dca4e5e
Binary files /dev/null and b/docs/public/favicons/android-icon-72x72.png differ
diff --git a/docs/public/favicons/android-icon-96x96.png b/docs/public/favicons/android-icon-96x96.png
new file mode 100644
index 0000000..5468a86
Binary files /dev/null and b/docs/public/favicons/android-icon-96x96.png differ
diff --git a/docs/public/favicons/apple-icon-114x114.png b/docs/public/favicons/apple-icon-114x114.png
new file mode 100644
index 0000000..cab13d2
Binary files /dev/null and b/docs/public/favicons/apple-icon-114x114.png differ
diff --git a/docs/public/favicons/apple-icon-120x120.png b/docs/public/favicons/apple-icon-120x120.png
new file mode 100644
index 0000000..f35f885
Binary files /dev/null and b/docs/public/favicons/apple-icon-120x120.png differ
diff --git a/docs/public/favicons/apple-icon-144x144.png b/docs/public/favicons/apple-icon-144x144.png
new file mode 100644
index 0000000..b738419
Binary files /dev/null and b/docs/public/favicons/apple-icon-144x144.png differ
diff --git a/docs/public/favicons/apple-icon-152x152.png b/docs/public/favicons/apple-icon-152x152.png
new file mode 100644
index 0000000..bd51897
Binary files /dev/null and b/docs/public/favicons/apple-icon-152x152.png differ
diff --git a/docs/public/favicons/apple-icon-180x180.png b/docs/public/favicons/apple-icon-180x180.png
new file mode 100644
index 0000000..8cf82ff
Binary files /dev/null and b/docs/public/favicons/apple-icon-180x180.png differ
diff --git a/docs/public/favicons/apple-icon-57x57.png b/docs/public/favicons/apple-icon-57x57.png
new file mode 100644
index 0000000..485c7ab
Binary files /dev/null and b/docs/public/favicons/apple-icon-57x57.png differ
diff --git a/docs/public/favicons/apple-icon-60x60.png b/docs/public/favicons/apple-icon-60x60.png
new file mode 100644
index 0000000..ce79ce6
Binary files /dev/null and b/docs/public/favicons/apple-icon-60x60.png differ
diff --git a/docs/public/favicons/apple-icon-72x72.png b/docs/public/favicons/apple-icon-72x72.png
new file mode 100644
index 0000000..dca4e5e
Binary files /dev/null and b/docs/public/favicons/apple-icon-72x72.png differ
diff --git a/docs/public/favicons/apple-icon-76x76.png b/docs/public/favicons/apple-icon-76x76.png
new file mode 100644
index 0000000..49ef41d
Binary files /dev/null and b/docs/public/favicons/apple-icon-76x76.png differ
diff --git a/docs/public/favicons/apple-icon-precomposed.png b/docs/public/favicons/apple-icon-precomposed.png
new file mode 100644
index 0000000..b3830b9
Binary files /dev/null and b/docs/public/favicons/apple-icon-precomposed.png differ
diff --git a/docs/public/favicons/apple-icon.png b/docs/public/favicons/apple-icon.png
new file mode 100644
index 0000000..b3830b9
Binary files /dev/null and b/docs/public/favicons/apple-icon.png differ
diff --git a/docs/public/favicons/browserconfig.xml b/docs/public/favicons/browserconfig.xml
new file mode 100644
index 0000000..7d453d3
--- /dev/null
+++ b/docs/public/favicons/browserconfig.xml
@@ -0,0 +1,2 @@
+
+#ffffff
diff --git a/docs/public/favicons/favicon-16x16.png b/docs/public/favicons/favicon-16x16.png
new file mode 100644
index 0000000..32f4f67
Binary files /dev/null and b/docs/public/favicons/favicon-16x16.png differ
diff --git a/docs/public/favicons/favicon-32x32.png b/docs/public/favicons/favicon-32x32.png
new file mode 100644
index 0000000..ec60c37
Binary files /dev/null and b/docs/public/favicons/favicon-32x32.png differ
diff --git a/docs/public/favicons/favicon-96x96.png b/docs/public/favicons/favicon-96x96.png
new file mode 100644
index 0000000..257028f
Binary files /dev/null and b/docs/public/favicons/favicon-96x96.png differ
diff --git a/docs/public/favicons/favicon.ico b/docs/public/favicons/favicon.ico
new file mode 100644
index 0000000..07a6f6b
Binary files /dev/null and b/docs/public/favicons/favicon.ico differ
diff --git a/docs/public/favicons/ms-icon-144x144.png b/docs/public/favicons/ms-icon-144x144.png
new file mode 100644
index 0000000..b738419
Binary files /dev/null and b/docs/public/favicons/ms-icon-144x144.png differ
diff --git a/docs/public/favicons/ms-icon-150x150.png b/docs/public/favicons/ms-icon-150x150.png
new file mode 100644
index 0000000..14c172b
Binary files /dev/null and b/docs/public/favicons/ms-icon-150x150.png differ
diff --git a/docs/public/favicons/ms-icon-310x310.png b/docs/public/favicons/ms-icon-310x310.png
new file mode 100644
index 0000000..48744f1
Binary files /dev/null and b/docs/public/favicons/ms-icon-310x310.png differ
diff --git a/docs/public/favicons/ms-icon-70x70.png b/docs/public/favicons/ms-icon-70x70.png
new file mode 100644
index 0000000..931fda5
Binary files /dev/null and b/docs/public/favicons/ms-icon-70x70.png differ
diff --git a/docs/public/llms.txt b/docs/public/llms.txt
new file mode 100644
index 0000000..5887f8a
--- /dev/null
+++ b/docs/public/llms.txt
@@ -0,0 +1,41 @@
+# AFDocs
+
+> Test your documentation site against the Agent-Friendly Documentation Spec. AFDocs runs 22 checks across 7 categories to measure how well AI coding agents can discover, navigate, and consume your docs.
+
+## The Score
+
+- [What Is the Agent Score?](https://afdocs.dev/what-is-agent-score.md)
+- [Why Agent-Friendliness Matters](https://afdocs.dev/why-agent-friendliness-matters.md)
+- [Score Calculation](https://afdocs.dev/agent-score-calculation.md)
+- [Interaction Diagnostics](https://afdocs.dev/interaction-diagnostics.md)
+
+## Get Started
+
+- [Quick Start](https://afdocs.dev/quick-start.md)
+- [Run Locally](https://afdocs.dev/run-locally.md)
+- [Improve Your Score](https://afdocs.dev/improve-your-score.md)
+- [CI Integration](https://afdocs.dev/ci-integration.md)
+
+## Checks Reference
+
+- [Checks Overview](https://afdocs.dev/checks/index.md)
+- [Content Discoverability](https://afdocs.dev/checks/content-discoverability.md): llms.txt existence, validity, size, link resolution, markdown links, directive
+- [Markdown Availability](https://afdocs.dev/checks/markdown-availability.md): .md URL support, content negotiation
+- [Page Size](https://afdocs.dev/checks/page-size.md): rendering strategy, HTML/markdown size, content start position
+- [Content Structure](https://afdocs.dev/checks/content-structure.md): tabbed content serialization, header quality, code fence validity
+- [URL Stability](https://afdocs.dev/checks/url-stability.md): HTTP status codes, redirect behavior
+- [Observability](https://afdocs.dev/checks/observability.md): llms.txt freshness, markdown content parity, cache headers
+- [Authentication](https://afdocs.dev/checks/authentication.md): auth gate detection, alternative access paths
+
+## API Reference
+
+- [API Reference Overview](https://afdocs.dev/reference/index.md)
+- [CLI Reference](https://afdocs.dev/reference/cli.md): flags, output formats, sampling strategies
+- [Programmatic API](https://afdocs.dev/reference/programmatic-api.md): TypeScript API for running checks
+- [Scoring API](https://afdocs.dev/reference/scoring-api.md): computing scores from check results
+- [Config File](https://afdocs.dev/reference/config-file.md): agent-docs.config.yml format and options
+
+## About
+
+- [About AFDocs](https://afdocs.dev/about.md)
+- [AFDocs Home](https://afdocs.dev/index.md)
diff --git a/docs/public/log-agent-signal.php b/docs/public/log-agent-signal.php
new file mode 100644
index 0000000..7f63350
--- /dev/null
+++ b/docs/public/log-agent-signal.php
@@ -0,0 +1,98 @@
+ /home/user)
+$homeDir = dirname($_SERVER['DOCUMENT_ROOT'] ?? '');
+$config = @include($homeDir . '/agent-signal-config.php');
+$logDir = ($config['log_dir'] ?? null);
+
+if ($logDir) {
+ if (!is_dir($logDir)) {
+ @mkdir($logDir, 0750, true);
+ }
+
+ // Rate-limit direct-md: log at most once per IP per 60 seconds.
+ // Content-negotiation and llms-txt are rare, high-value signals
+ // that are always logged.
+ $shouldLog = true;
+ if ($trigger === 'direct-md') {
+ $rateLimitDir = $logDir . '/rate-limit';
+ if (!is_dir($rateLimitDir)) {
+ @mkdir($rateLimitDir, 0750, true);
+ }
+ $ip = $_SERVER['REMOTE_ADDR'] ?? 'unknown';
+ $tokenFile = $rateLimitDir . '/' . md5($ip);
+ if (file_exists($tokenFile) && (time() - filemtime($tokenFile)) < 60) {
+ $shouldLog = false;
+ } else {
+ @touch($tokenFile);
+ }
+ }
+
+ if ($shouldLog) {
+ // Collect all request headers
+ $allHeaders = getallheaders() ?: [];
+
+ // Build a JSON log entry for rich, parseable data
+ $entry = [
+ 'timestamp' => gmdate('Y-m-d\TH:i:s\Z'),
+ 'domain' => $_SERVER['HTTP_HOST'] ?? '-',
+ 'ip' => $_SERVER['REMOTE_ADDR'] ?? '-',
+ 'method' => $_SERVER['REQUEST_METHOD'] ?? '-',
+ 'path' => $path,
+ 'trigger' => $trigger,
+ 'headers' => $allHeaders,
+ ];
+
+ @file_put_contents(
+ $logDir . '/agent-signals-' . gmdate('Y-m-d') . '.jsonl',
+ json_encode($entry, JSON_UNESCAPED_SLASHES) . "\n",
+ FILE_APPEND | LOCK_EX
+ );
+ }
+}
+
+// Serve the file — remove any server-level cache headers first
+header_remove('Cache-Control');
+header_remove('Expires');
+header('Content-Type: ' . $contentType . '; charset=utf-8');
+header('Cache-Control: max-age=3600, must-revalidate');
+readfile($file);
diff --git a/docs/public/logos/afdoc_logo_dark.svg b/docs/public/logos/afdoc_logo_dark.svg
new file mode 100644
index 0000000..19fb894
--- /dev/null
+++ b/docs/public/logos/afdoc_logo_dark.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/docs/public/logos/afdoc_logo_light.svg b/docs/public/logos/afdoc_logo_light.svg
new file mode 100644
index 0000000..6a0185c
--- /dev/null
+++ b/docs/public/logos/afdoc_logo_light.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/docs/quick-start.md b/docs/quick-start.md
new file mode 100644
index 0000000..8edb85b
--- /dev/null
+++ b/docs/quick-start.md
@@ -0,0 +1,149 @@
+# Quick Start
+
+## Requirements
+
+Node.js 22 or later.
+
+## Run your first check
+
+No install needed. Point AFDocs at your documentation site:
+
+```bash
+npx afdocs check https://docs.example.com --format scorecard
+```
+
+This discovers pages from your site (via llms.txt, sitemap, or both), samples up to 50, runs all 22 checks, and produces a scorecard with your overall score, per-category breakdowns, and fix suggestions:
+
+```
+Agent-Friendly Docs Scorecard
+==============================
+
+ Overall Score: 72 / 100 (C)
+
+ Category Scores:
+ Content Discoverability 72 / 100 (C)
+ Markdown Availability 60 / 100 (C)
+ Page Size and Truncation Risk 45 / 100 (D)
+ ...
+
+ Interaction Diagnostics:
+ [!] Markdown support is undiscoverable
+ Your site serves markdown at .md URLs, but agents have no way to
+ discover this. ...
+
+ Check Results:
+ Content Discoverability
+ PASS llms-txt-exists llms.txt found at /llms.txt
+ WARN llms-txt-size llms.txt is 65,000 characters
+ FAIL llms-txt-directive No directive detected on any tested page
+ Fix: Add a blockquote near the top of each page ...
+```
+
+To understand what the score means and how it's calculated, see [What Is the Agent Score?](/what-is-agent-score).
+
+## See what's wrong and how to fix it
+
+### Get your score
+
+The scorecard shown above is the best starting point. It gives you the overall score, per-category breakdowns, [interaction diagnostics](/interaction-diagnostics), and fix suggestions for every failing check, all in one view:
+
+```bash
+npx afdocs check https://docs.example.com --format scorecard
+```
+
+### Dig into per-page details
+
+When you're ready to fix specific issues, switch to the text format with `--verbose` and `--fixes`. This tells you exactly which pages have problems and what to do about them:
+
+```bash
+npx afdocs check https://docs.example.com --verbose --fixes
+```
+
+The scorecard tells you _what's wrong_. The verbose text output tells you _where_.
+
+### Get machine-readable output
+
+For scripting and automation, use JSON output. Add `--score` to include scoring data and fix suggestions:
+
+```bash
+npx afdocs check https://docs.example.com --format json --score
+```
+
+## Run specific checks
+
+If you're working on a particular issue, you don't need to run all 22 checks every time. Pass a comma-separated list of check IDs:
+
+```bash
+npx afdocs check https://docs.example.com --checks llms-txt-exists,llms-txt-valid,llms-txt-size
+```
+
+Some checks depend on others. For example, `llms-txt-valid` requires `llms-txt-exists` to pass first; if you run `llms-txt-valid` alone, it will skip. When running a subset, include the dependencies too.
+
+See the [Checks Reference](/checks/) for the full list of check IDs and dependencies.
+
+## Check a specific page
+
+Skip page discovery entirely and check just one URL with `--sampling none`:
+
+```bash
+npx afdocs check https://docs.example.com/api/auth --sampling none
+```
+
+You can combine this with `--checks` to run a single check against a single page:
+
+```bash
+npx afdocs check https://docs.example.com/api/auth --sampling none --checks rendering-strategy
+```
+
+## Get consistent results between runs
+
+By default, AFDocs randomly samples pages, so results can vary between runs. For reproducible results (useful when verifying a fix), use deterministic sampling:
+
+```bash
+npx afdocs check https://docs.example.com --sampling deterministic
+```
+
+This sorts discovered URLs alphabetically and picks an even spread, producing the same sample every time as long as your site's URL set is stable.
+
+## Tune request behavior
+
+AFDocs is designed to be a good citizen. It enforces delays between requests and caps concurrent connections. If you need to adjust these:
+
+```bash
+# Slower, gentler requests (for rate-limited servers)
+npx afdocs check https://docs.example.com --request-delay 500 --max-concurrency 1
+
+# Faster runs (for your own infrastructure)
+npx afdocs check https://docs.example.com --request-delay 50 --max-concurrency 10
+
+# Sample fewer pages for a quicker check
+npx afdocs check https://docs.example.com --max-links 10
+```
+
+For the full list of flags, see the [CLI Reference](/reference/cli).
+
+## Exit codes
+
+AFDocs exits with `0` if all checks pass or warn, and `1` if any check fails. This makes it usable in CI pipelines and shell scripts. See [CI Integration](/ci-integration) for full setup.
+
+## Installing
+
+`npx` downloads and runs AFDocs on demand, which is fine for getting started and one-off checks. If you run it regularly, you can install it for faster startup:
+
+```bash
+# Global install — puts `afdocs` on your PATH
+npm install -g afdocs
+afdocs check https://docs.example.com
+
+# Project dev dependency — for CI and test suites
+npm install -D afdocs
+```
+
+For CI integration with vitest helpers, see [CI Integration](/ci-integration).
+
+## Next steps
+
+- [Improve Your Score](/improve-your-score) — a prioritized workflow for fixing what the checks found
+- [Run Locally](/run-locally) — iterate against a local dev server
+- [CI Integration](/ci-integration) — add checks to your CI pipeline
+- [Checks Reference](/checks/) — what each check measures and why
diff --git a/docs/reference/cli.md b/docs/reference/cli.md
new file mode 100644
index 0000000..0120dcc
--- /dev/null
+++ b/docs/reference/cli.md
@@ -0,0 +1,147 @@
+# CLI Reference
+
+## Install
+
+```bash
+# Run without installing (recommended for getting started)
+npx afdocs check https://docs.example.com
+
+# Install globally
+npm install -g afdocs
+
+# Install as a project dev dependency
+npm install -D afdocs
+```
+
+Requires Node.js 22 or later.
+
+## Commands
+
+### `afdocs check `
+
+Run agent-friendly documentation checks against a URL.
+
+```bash
+afdocs check https://docs.example.com
+```
+
+The URL can be a site root or a specific page. When pointing to a site root, `afdocs` discovers pages via `llms.txt` and sitemap, then samples a subset to check. When pointing to a specific page with `--sampling none`, it skips discovery and checks just that page.
+
+## Options
+
+### Output
+
+| Flag | Default | Description |
+| ----------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
+| `-f, --format ` | `text` | Output format: `text`, `json`, or `scorecard` |
+| `-v, --verbose` | | Show per-page details for checks with issues |
+| `--fixes` | | Show per-check fix suggestions for warn/fail checks (only needed for `text` format; the other two formats include fix suggestions automatically) |
+| `--score` | | Include scoring data in JSON output (only usable with `json` output format) |
+
+**Which format to use:**
+
+- **`text`** is the default. Shows per-check pass/warn/fail/skip results. Add `--verbose` for per-page details and `--fixes` for fix suggestions. Useful when iterating on individual check fixes.
+- **`scorecard`** includes the overall score, per-category scores, interaction diagnostics, and fix suggestions for every failing check. This is the best starting point for understanding your site's agent-friendliness.
+- **`json`** produces machine-readable output for scripting and automation. Add `--score` to include scoring data and fix suggestions.
+
+### Config file
+
+| Flag | Default | Description |
+| ----------------- | ------- | -------------------------------------------- |
+| `--config ` | | Path to a config file (skips auto-discovery) |
+
+Without `--config`, the CLI looks for `agent-docs.config.yml` (or `.yaml`) starting from the current directory and walking up the tree. Config values serve as defaults; any CLI flags you pass override them.
+
+```bash
+# Auto-discover config (typical usage)
+afdocs check --format scorecard
+
+# Use an explicit config file
+afdocs check --config agent-docs.local.yml --format scorecard
+```
+
+See [Config File](/reference/config-file) for the full config format.
+
+### Check selection
+
+| Flag | Default | Description |
+| -------------------- | ------- | ---------------------------------------- |
+| `-c, --checks ` | all | Comma-separated list of check IDs to run |
+
+```bash
+# Run only llms.txt checks
+afdocs check https://docs.example.com --checks llms-txt-exists,llms-txt-valid,llms-txt-size
+```
+
+Some checks depend on others. If you include a check without its dependency, the dependent check will be skipped. See [Check dependencies](/checks/#check-dependencies) for the full list.
+
+### Sampling
+
+| Flag | Default | Description |
+| ----------------------- | -------- | ----------------------------------------------------------- |
+| `--sampling ` | `random` | URL sampling strategy: `random`, `deterministic`, or `none` |
+| `--max-links ` | `50` | Maximum number of pages to sample |
+
+**Sampling strategies:**
+
+- **`random`**: Shuffle discovered URLs and take the first N. Fast and broad, but results vary between runs. Useful for spot-checking pages across a large corpus.
+- **`deterministic`**: Sort discovered URLs alphabetically and pick an even spread. Produces the same sample on repeated runs as long as the URL set is stable. Useful for CI or when verifying a fix.
+- **`none`**: Skip discovery entirely. Only check the URL you pass on the command line.
+
+```bash
+# Reproducible results
+afdocs check https://docs.example.com --sampling deterministic
+
+# Check a single page
+afdocs check https://docs.example.com/api/auth --sampling none
+
+# Sample fewer pages for a quicker run
+afdocs check https://docs.example.com --max-links 10
+
+# Sample more pages for better representation across a large corpus
+afdocs check https://docs.example.com --max-links 100
+```
+
+### Request behavior
+
+| Flag | Default | Description |
+| ----------------------- | ------- | -------------------------------------- |
+| `--max-concurrency ` | `3` | Maximum concurrent HTTP requests |
+| `--request-delay ` | `200` | Delay between requests in milliseconds |
+
+AFDocs enforces delays between requests and caps concurrent connections to avoid overloading your server. Adjust these if you need gentler or faster runs:
+
+```bash
+# Slower, gentler (for rate-limited servers)
+afdocs check https://docs.example.com --request-delay 500 --max-concurrency 1
+
+# Faster (for your own infrastructure)
+afdocs check https://docs.example.com --request-delay 50 --max-concurrency 10
+```
+
+### Size thresholds
+
+| Flag | Default | Description |
+| ---------------------- | -------- | -------------------------------------- |
+| `--pass-threshold ` | `50000` | Page size pass threshold in characters |
+| `--fail-threshold ` | `100000` | Page size fail threshold in characters |
+
+These thresholds apply to `page-size-html`, `page-size-markdown`, and `tabbed-content-serialization`. Pages under the pass threshold pass; pages between the two thresholds warn; pages over the fail threshold fail.
+
+The defaults (50K pass, 100K fail) reflect observed agent truncation limits. You generally don't need to change these unless you have specific knowledge of your users' agent platforms.
+
+## Exit codes
+
+| Code | Meaning |
+| ---- | --------------------------- |
+| `0` | All checks passed or warned |
+| `1` | One or more checks failed |
+
+This makes AFDocs usable in CI pipelines and shell scripts. A warning does not cause a non-zero exit. See [CI Integration](/ci-integration) for full setup.
+
+## Global flags
+
+| Flag | Description |
+| ----------- | ------------------------ |
+| `--version` | Print the version number |
+| `--help` | Print help information |
diff --git a/docs/reference/config-file.md b/docs/reference/config-file.md
new file mode 100644
index 0000000..8489d5c
--- /dev/null
+++ b/docs/reference/config-file.md
@@ -0,0 +1,87 @@
+# Config File
+
+The `agent-docs.config.yml` file lets you define a reusable configuration for running `afdocs` checks. It works with both the CLI and the [vitest test helpers](/ci-integration).
+
+## Format
+
+```yaml
+# Required: the URL to check
+url: https://docs.example.com
+
+# Optional: run only specific checks
+checks:
+ - llms-txt-exists
+ - llms-txt-valid
+ - llms-txt-size
+ - llms-txt-links-resolve
+ - rendering-strategy
+ - page-size-html
+ - http-status-codes
+ - auth-gate-detection
+
+# Optional: override default options
+options:
+ maxLinksToTest: 20
+ samplingStrategy: deterministic
+ maxConcurrency: 5
+ requestDelay: 100
+ thresholds:
+ pass: 50000
+ fail: 100000
+```
+
+## Fields
+
+### `url` (required)
+
+The documentation site URL to check. This is the only required field.
+
+### `checks` (optional)
+
+A list of check IDs to run. If omitted, all 22 checks run. Use this to focus on checks that are actionable for your platform. See the [Checks Reference](/checks/) for the full list of check IDs.
+
+This is particularly useful when your docs platform doesn't support certain capabilities. For example, if you can't serve markdown, exclude the markdown-related checks so your score reflects what you can control. See [Improve Your Score](/improve-your-score#step-3-work-through-fixes-iteratively) for more on this approach.
+
+### `options` (optional)
+
+Override default runner options. All fields are optional:
+
+| Field | Default | Description |
+| ------------------ | -------- | ---------------------------------------------------- |
+| `maxLinksToTest` | `50` | Maximum number of pages to sample |
+| `samplingStrategy` | `random` | `random`, `deterministic`, or `none` |
+| `maxConcurrency` | `3` | Maximum concurrent HTTP requests |
+| `requestDelay` | `200` | Delay between requests in milliseconds |
+| `requestTimeout` | `30000` | Timeout for individual HTTP requests in milliseconds |
+| `thresholds.pass` | `50000` | Page size pass threshold in characters |
+| `thresholds.fail` | `100000` | Page size fail threshold in characters |
+
+## Config resolution
+
+The config loader searches for `agent-docs.config.yml` (or `.yaml`) starting from the current working directory and walking up the directory tree, similar to how ESLint and Prettier find their config files. This means the config works whether you're running the CLI from your project root or running a test file from a subdirectory.
+
+For the vitest helpers, you can also pass an explicit directory:
+
+```ts
+import { describeAgentDocsPerCheck } from 'afdocs/helpers';
+
+describeAgentDocsPerCheck(__dirname);
+```
+
+## Multiple configs
+
+You might maintain separate configs for different contexts (local development, staging, production). Use `--config` to select one at runtime:
+
+```bash
+afdocs check --config agent-docs.local.yml
+afdocs check --config agent-docs.staging.yml
+```
+
+A common pattern: point `agent-docs.config.yml` at your production URL (CI auto-discovers this), and override just the URL on the command line when running locally:
+
+```bash
+# Production config is auto-discovered; URL is overridden for local dev
+afdocs check http://localhost:3000
+```
+
+CLI flags always take precedence over config values.
diff --git a/docs/reference/index.md b/docs/reference/index.md
new file mode 100644
index 0000000..8dc25a9
--- /dev/null
+++ b/docs/reference/index.md
@@ -0,0 +1,6 @@
+# API Reference
+
+- [CLI](/reference/cli) — command-line flags, output formats, sampling strategies
+- [Programmatic API](/reference/programmatic-api) — TypeScript API for running checks
+- [Scoring API](/reference/scoring-api) — computing scores from check results
+- [Config File](/reference/config-file) — `agent-docs.config.yml` format and options
diff --git a/docs/reference/programmatic-api.md b/docs/reference/programmatic-api.md
new file mode 100644
index 0000000..4873bc3
--- /dev/null
+++ b/docs/reference/programmatic-api.md
@@ -0,0 +1,96 @@
+# Programmatic API
+
+AFDocs exports its check runner and utilities as a TypeScript API, so you can integrate agent-friendliness checks into your own tools and workflows.
+
+## Run all checks
+
+```ts
+import { runChecks } from 'afdocs';
+
+const report = await runChecks('https://docs.example.com');
+
+console.log(report.summary);
+// { total: 22, pass: 15, warn: 3, fail: 2, skip: 2, error: 0 }
+
+for (const result of report.results) {
+ console.log(`${result.id}: ${result.status} — ${result.message}`);
+}
+```
+
+`runChecks` returns a `ReportResult` containing:
+
+- `url` — the URL that was checked
+- `timestamp` — when the check ran
+- `results` — array of `CheckResult` objects (one per check)
+- `summary` — counts by status (pass, warn, fail, skip, error)
+
+## Run with options
+
+Pass a second argument to configure sampling, concurrency, and thresholds:
+
+```ts
+import { runChecks } from 'afdocs';
+
+const report = await runChecks('https://docs.example.com', {
+ checkIds: ['llms-txt-exists', 'llms-txt-valid', 'llms-txt-size'],
+ samplingStrategy: 'deterministic',
+ maxLinksToTest: 20,
+ maxConcurrency: 5,
+ requestDelay: 100,
+ thresholds: {
+ pass: 50000,
+ fail: 100000,
+ },
+});
+```
+
+All options are optional. The defaults match the CLI defaults.
+
+## Run a single check
+
+For more control, create a context and run individual checks:
+
+```ts
+import { createContext, getCheck } from 'afdocs';
+
+const ctx = createContext('https://docs.example.com');
+const check = getCheck('llms-txt-exists')!;
+const result = await check.run(ctx);
+
+console.log(result.status); // 'pass', 'warn', 'fail', or 'skip'
+console.log(result.message);
+```
+
+`createContext` sets up the shared state (HTTP client, page cache, previous results) that checks use. If you run multiple checks against the same context, later checks can access the results of earlier ones through `ctx.previousResults`, which is how check dependencies work.
+
+## List available checks
+
+```ts
+import { getAllChecks, getChecksSorted } from 'afdocs';
+
+// All checks as a Map
+const all = getAllChecks();
+
+// Checks in dependency-safe execution order
+const sorted = getChecksSorted();
+for (const check of sorted) {
+ console.log(`${check.id} (${check.category}): ${check.description}`);
+}
+```
+
+## Types
+
+The main types you'll work with:
+
+```ts
+import type {
+ CheckResult,
+ CheckStatus, // 'pass' | 'warn' | 'fail' | 'skip' | 'error'
+ ReportResult,
+ RunnerOptions,
+ CheckOptions,
+ AgentDocsConfig,
+} from 'afdocs';
+```
+
+See the [Scoring API](/reference/scoring-api) for scoring-related types.
diff --git a/docs/reference/scoring-api.md b/docs/reference/scoring-api.md
new file mode 100644
index 0000000..f97ff5c
--- /dev/null
+++ b/docs/reference/scoring-api.md
@@ -0,0 +1,72 @@
+# Scoring API
+
+The scoring module is available as a pure function for programmatic consumers. It takes a `ReportResult` from `runChecks` and returns a standalone `ScoreResult` with the overall score, per-category breakdowns, interaction diagnostics, and fix suggestions.
+
+## Compute a score
+
+```ts
+import { runChecks, computeScore } from 'afdocs';
+
+const report = await runChecks('https://docs.example.com');
+const score = computeScore(report);
+
+console.log(score.overall); // 72
+console.log(score.grade); // 'C'
+console.log(score.categoryScores); // { 'content-discoverability': { score: 80, grade: 'B' }, ... }
+console.log(score.diagnostics); // [{ id: 'markdown-undiscoverable', severity: 'warning', ... }]
+console.log(score.resolutions); // { 'llms-txt-directive': 'Add a blockquote near the top...' }
+```
+
+`computeScore` is a pure function. It does not modify the report or make any network requests. Composition is the consumer's responsibility: the CLI formatters compose `runChecks` and `computeScore`; external consumers call them separately.
+
+## Import from the subpath
+
+You can also import from the dedicated scoring subpath:
+
+```ts
+import { computeScore } from 'afdocs/scoring';
+```
+
+This is the same function; the subpath is provided for consumers who want a narrower import.
+
+## ScoreResult
+
+`computeScore` returns a `ScoreResult` with these fields:
+
+| Field | Type | Description |
+| ---------------- | ------------------------------- | ------------------------------------------------------------------------- |
+| `overall` | `number` | The overall score (0-100) |
+| `grade` | `Grade` | Letter grade (`A+`, `A`, `B`, `C`, `D`, `F`) |
+| `categoryScores` | `Record` | Per-category score and grade |
+| `checkScores` | `Record` | Per-check scoring details (weight, coefficient, proportion, earned score) |
+| `diagnostics` | `Diagnostic[]` | Interaction diagnostics that fired |
+| `caps` | `ScoreCap[]` | Score caps that were applied |
+| `resolutions` | `Record` | Fix suggestions keyed by check ID |
+
+## Grade conversion
+
+If you need to convert a numeric score to a letter grade independently:
+
+```ts
+import { toGrade } from 'afdocs';
+
+toGrade(92); // 'A'
+toGrade(100); // 'A+'
+toGrade(55); // 'F'
+```
+
+## Types
+
+```ts
+import type {
+ ScoreResult,
+ CheckScore,
+ CategoryScore,
+ ScoreCap,
+ Diagnostic,
+ DiagnosticSeverity, // 'info' | 'warning' | 'critical'
+ Grade, // 'A+' | 'A' | 'B' | 'C' | 'D' | 'F'
+} from 'afdocs';
+```
+
+For how the score is calculated (weights, coefficients, caps, proportional scoring), see [Score Calculation](/agent-score-calculation).
diff --git a/docs/run-locally.md b/docs/run-locally.md
new file mode 100644
index 0000000..d5aa252
--- /dev/null
+++ b/docs/run-locally.md
@@ -0,0 +1,92 @@
+# Run Locally
+
+You can run AFDocs against a local development server to iterate on fixes without deploying. This is the fastest way to work through the [Improve Your Score](/improve-your-score) workflow.
+
+## Basic setup
+
+Start your docs site locally, then point AFDocs at it:
+
+```bash
+# In one terminal, start your dev server
+npm run dev
+# → http://localhost:3000
+
+# In another terminal, run checks
+npx afdocs check http://localhost:3000
+```
+
+## Single-page mode
+
+When working on a specific page, skip discovery and check just that page:
+
+```bash
+npx afdocs check http://localhost:3000/api/auth --sampling none
+```
+
+This is much faster than a full site check because it skips page discovery and only makes requests for the one URL.
+
+## Run specific checks
+
+If you're fixing a particular issue, run only the relevant checks:
+
+```bash
+# Just page size checks
+npx afdocs check http://localhost:3000 --checks page-size-html,content-start-position
+
+# Just llms.txt checks
+npx afdocs check http://localhost:3000 --checks llms-txt-exists,llms-txt-valid,llms-txt-size
+
+# Single page, single check
+npx afdocs check http://localhost:3000/api/auth --sampling none --checks rendering-strategy
+```
+
+## Use a config file
+
+For repeated local runs, create an `agent-docs.config.yml` pointing to localhost:
+
+```yaml
+url: http://localhost:3000
+
+# Optional: run only specific checks
+# checks:
+# - llms-txt-exists
+# - llms-txt-valid
+# - rendering-strategy
+
+# Optional: tune sampling
+# options:
+# maxLinksToTest: 20
+# samplingStrategy: deterministic
+```
+
+Then run checks without specifying the URL each time:
+
+```bash
+npx afdocs check --format scorecard
+```
+
+By default, the CLI looks for `agent-docs.config.yml` in the current directory (or any parent directory). You can also pass an explicit config path with `--config`:
+
+```bash
+npx afdocs check --config agent-docs.local.yml --format scorecard
+```
+
+This lets you maintain separate configs for different contexts (local development, staging, production) and choose the right one at runtime. It's the same config format used by the [vitest test helpers](/ci-integration). Any CLI flags you pass override the config values.
+
+## Local vs. production differences
+
+Some checks may behave differently against a local server:
+
+- **Redirects**: Your production CDN or hosting provider may add redirects (e.g., trailing slash normalization, www redirects) that your local server doesn't. The `redirect-behavior` check may pass locally but warn or fail in production.
+- **Cache headers**: Local dev servers typically don't set cache headers. The `cache-header-hygiene` check will likely fail locally. This is expected; check it against production instead.
+- **Auth gating**: If your production site has authentication, your local server probably doesn't. The `auth-gate-detection` check will pass locally but may fail in production. This represents a real agent failure mode; if an agent can't access your documentation without logging in, an agent can't access your documentation.
+- **Hot reload injection**: Some dev servers inject hot-reload scripts into the page HTML. This can affect `page-size-html` and `content-start-position` results. Build and serve the production output locally (e.g., `npm run build && npm run preview`) for accurate size measurements.
+- **llms.txt**: If your llms.txt is generated at build time, it won't exist on the dev server. Either generate it first or skip the llms.txt checks locally.
+
+For the most accurate results, build the production output and serve it with a local static server:
+
+```bash
+npm run build
+npx serve dist # or however your site serves its build output
+npx afdocs check http://localhost:3000
+```
diff --git a/docs/what-is-agent-score.md b/docs/what-is-agent-score.md
new file mode 100644
index 0000000..758c38c
--- /dev/null
+++ b/docs/what-is-agent-score.md
@@ -0,0 +1,90 @@
+# What Is the Agent Score?
+
+The Agent Score is a 0–100 rating of how well AI coding agents can discover, navigate, and consume your documentation site. You can get your score with [AFDocs](https://www.npmjs.com/package/afdocs), which runs 22 automated checks based on the [Agent-Friendly Documentation Spec](https://agentdocsspec.com) and maps the results to a letter grade.
+
+The AI coding agents that regularly consume your documentation while helping developers perform tasks include:
+
+- Claude Code
+- Codex
+- Cursor
+- Gemini CLI
+- GitHub Copilot
+- Windsurf
+
+And more.
+
+This is a distinct audience from LLM and AI answer engine crawlers, and they need different things from your documentation.
+
+## Why agent-friendliness matters
+
+When agents can't use your docs, they fall back on training data (which may be outdated) or look for content elsewhere. That means developers get bad answers, your support costs go up, and competitors with more agent-friendly docs gain an advantage.
+
+A good Agent Score means agents can reach your content, read it in a useful format, and navigate it reliably. That creates better outcomes for developers using those agents.
+
+For the full business case, including how agents fail on documentation, the concrete impact, and how to make the case internally, see [Why Agent-Friendliness Matters](/why-agent-friendliness-matters).
+
+## What the score measures
+
+The 22 checks cover seven categories:
+
+| Category | What it tests |
+| ---------------------------------------------------------- | -------------------------------------------------------------------------------------------------- |
+| [Content Discoverability](/checks/content-discoverability) | Can agents find your docs? Do you have an `llms.txt`? Do pages tell agents where to look? |
+| [Markdown Availability](/checks/markdown-availability) | Can agents get content in markdown (their preferred format) via `.md` URLs or content negotiation? |
+| [Page Size](/checks/page-size) | Will agents hit truncation limits? Are pages server-rendered, or do agents get empty SPA shells? |
+| [Content Structure](/checks/content-structure) | Do tabbed UI components blow up page size? Are code fences properly closed? |
+| [URL Stability](/checks/url-stability) | Do error pages return real 404s? Do redirects use standard HTTP methods? |
+| [Observability](/checks/observability) | Is your `llms.txt` fresh? Do markdown and HTML versions match? Are cache headers reasonable? |
+| [Authentication](/checks/authentication) | Can agents reach your docs at all, or is everything behind a login wall? |
+
+Not all checks carry equal weight. Authentication failures and missing `llms.txt` are critical, while cache header issues are refinements. The scoring system accounts for this with [weight tiers](/agent-score-calculation#check-weights-by-category) and [score caps](/agent-score-calculation#score-caps) that prevent high scores when fundamental problems exist.
+
+## Letter grades
+
+| Grade | Score | What it means |
+| ------ | ----- | ---------------------------------------------------------------------------- |
+| **A+** | 100 | Every check passes. Agents can fully navigate and consume your docs. |
+| **A** | 90–99 | Excellent. Agents can use your documentation with minimal friction. |
+| **B** | 80–89 | Good. Minor improvements possible; most content is accessible to agents. |
+| **C** | 70–79 | Functional but with notable gaps. Some content is inaccessible or degraded. |
+| **D** | 60–69 | Significant barriers. Agents struggle to use your documentation effectively. |
+| **F** | 0–59 | Agents likely cannot use your documentation in a meaningful way. |
+
+## What the scorecard looks like
+
+The score is part of a larger scorecard that includes per-category breakdowns, system-level diagnostics that emerge from combinations of check results, and individual check results with fix suggestions:
+
+```
+Agent-Friendly Docs Scorecard
+==============================
+
+ Overall Score: 72 / 100 (C)
+
+ Category Scores:
+ Content Discoverability 72 / 100 (C)
+ Markdown Availability 60 / 100 (C)
+ Page Size and Truncation Risk 45 / 100 (D)
+ ...
+
+ Interaction Diagnostics:
+ [!] Markdown support is undiscoverable
+ Your site serves markdown at .md URLs, but agents have no way to
+ discover this. ...
+
+ Check Results:
+ Content Discoverability
+ PASS llms-txt-exists llms.txt found at /llms.txt
+ WARN llms-txt-size llms.txt is 65,000 characters
+ FAIL llms-txt-directive No directive detected on any tested page
+ Fix: Add a blockquote near the top of each page ...
+```
+
+The [Interaction Diagnostics](/interaction-diagnostics) section covers amplification effects between checks. When some check failures compound, the agent impact is more pronounced than individual check failures imply. This includes things like having markdown support that agents can't discover, or page sizes that exceed limits with no alternate format available.
+
+## What to do with your score
+
+If you already have a score and want to improve it, the [Improve Your Score](/improve-your-score) guide walks you through the highest-impact fixes in priority order.
+
+If you want to understand the math behind the number, [Score Calculation](/agent-score-calculation) covers the weights, proportional scoring, and interaction effects that produce the final score.
+
+If you want to run it yourself, [Quick Start](/quick-start) has you up and running in one command.
diff --git a/docs/why-agent-friendliness-matters.md b/docs/why-agent-friendliness-matters.md
new file mode 100644
index 0000000..dd5119d
--- /dev/null
+++ b/docs/why-agent-friendliness-matters.md
@@ -0,0 +1,80 @@
+# Why Agent-Friendliness Matters
+
+AI coding agents are a new and fast-growing audience for your documentation. Millions of developers use tools like Claude Code, Cursor, GitHub Copilot, Windsurf, Codex, and Gemini CLI daily. Those tools read your docs on the developers' behalf. When a developer asks an agent to integrate your API, debug an issue, or follow a migration guide, the agent fetches and reads your documentation pages in real time.
+
+This is a distinct audience from LLM training crawlers or AI answer engines. Coding agents need to read specific pages, right now, and produce working code from what they find. If they can't, the developer gets a bad result and your product takes the hit.
+
+## How agents fail on documentation
+
+Agents don't read docs the way humans do. They can't scroll past a navigation bar, mentally filter out boilerplate, or click through a login flow. When your docs aren't set up for agents, here's what actually happens:
+
+- **Client-side rendering**: Agents fetch the page and get an empty JavaScript shell with no content. This is the most common complete failure mode, and it affects every docs site built on a single-page app framework without server-side rendering.
+- **Truncation**: Agents have context limits. A page with 200K characters of inline CSS, JavaScript, and navigation markup before the actual content starts means the agent may never reach the documentation text. Even if it does, the content may be cut off. Different agent platforms implement different solutions for this problem, and each platform has different failure modes.
+- **No discovery path**: Agents don't guess that your site supports `.md` URLs. Only some of them try `Accept: text/markdown` headers to get clean markdown content. Without an `llms.txt` or a directive on pages, agents have no way to find a markdown content path even if one exists.
+- **Broken navigation**: Cross-host redirects, JavaScript redirects, and soft 404s (pages that return HTTP 200 with an error message) all break agent workflows. Agents trust HTTP status codes and follow standard redirects. Anything else is a dead end.
+- **Auth walls**: If your docs require authentication, agents can't log in. The entire site is invisible to them.
+
+When your docs _are_ agent-friendly, none of this is visible. The agent fetches clean markdown, navigates via llms.txt, and produces working integration code on the first try. The developer never thinks about your docs at all, which is the goal.
+
+## The invisible problem
+
+When a documentation page has a typo, someone files a bug. When an agent can't read a documentation page, nobody files anything. The developer gets a bad answer from the agent, blames the agent (or your product), and moves on. There's no feedback loop.
+
+This means agent-accessibility problems can persist for months without anyone on your team knowing. Your docs could be perfectly written and completely invisible to the tools that millions of developers rely on.
+
+The Agent Score gives you visibility into this blind spot. It tests your site the way agents actually access it and tells you what they see (or don't see).
+
+## Business impact
+
+When agents can't use your documentation effectively, the result impacts your bottom line:
+
+### Increased support costs
+
+Agents that can't read your docs produce incorrect code. Developers hit errors, open support tickets, and file bug reports that trace back to bad agent output rather than actual bugs in your product. Your support team spends time debugging problems that good documentation would have prevented.
+
+### Customer churn and revenue impact
+
+Developers increasingly choose tools based on how well they work with AI agents. If integrating your product is painful because agents can't read your docs, developers will choose a competitor with docs that agents can actually use. This is a new competitive angle that most companies aren't tracking yet.
+
+### Wasted documentation investment
+
+You've invested in writing, maintaining, and hosting documentation. If agents can't access it, that investment is partially wasted for a growing segment of your audience. The content exists; it's just locked behind technical barriers that have real fixes.
+
+### Reputational damage
+
+When an agent writes bad code using your product, the developer's first instinct is often "this API is hard to use" or "the docs are bad," not "the agent couldn't read the docs." Poor agent-friendliness degrades your product's reputation even when the product and its documentation is excellent.
+
+## The effort has an outsized impact
+
+The highest-impact fixes for agent-friendliness are typically configuration changes, not documentation rewrites:
+
+| Fix | Impact | Typical effort |
+| ------------------------------------ | ----------------- | -------------------------------------------------------------------------------- |
+| Add an `llms.txt` file | Critical (10 pts) | A few hours for initial creation; minutes to maintain if generated at build time |
+| Enable server-side rendering | Critical (10 pts) | A configuration flag on many docs platforms |
+| Serve markdown at `.md` URLs | High (7 pts) | Platform-dependent; some support it natively, others need a server config change |
+| Add an `llms.txt` directive to pages | High (7 pts) | A one-line addition to your page template |
+| Fix broken `llms.txt` links | High (7 pts) | Find and fix broken links with `afdocs check --verbose` |
+| Point `llms.txt` links to markdown | High (7 pts) | Find-and-replace in your `llms.txt` |
+
+Your documentation site may move from an F to a B or higher in a single sprint. The [Improve Your Score](/improve-your-score) guide walks through these fixes in priority order.
+
+## A new competitive angle
+
+When a developer asks an agent to "help me integrate Product A's API" and "help me integrate Product B's API", the agent will produce better code for whichever product has more agent-friendly documentation. The developer may not even realize why one integration went smoothly and the other didn't.
+
+Companies that optimize their docs for agents early will have a compounding advantage as agent usage grows. Companies that don't will gradually lose developer mindshare to competitors whose documentation agents can actually read.
+
+This isn't hypothetical. Agent usage among developers has grown rapidly through 2025 and into 2026, and the agents that read documentation (Claude Code, Cursor, Copilot, etc.) are among the most widely adopted developer tools in history. The documentation you ship today is already being read by agents, whether or not you've optimized for it. In early April 2026, documentation platform provider Mintlify [shared a statistic](https://www.linkedin.com/posts/handotdev_last-month-i-shared-that-ai-agents-account-activity-7445500425610420225-Bs6M):
+
+> Claude Code and Cursor account for nearly half of all views to documentation sites.
+
+## Making the case internally
+
+If you need to justify prioritizing agent-friendliness to leadership, here are the key points:
+
+1. **It's measurable.** Run `npx afdocs check https://your-docs-site.com --format scorecard` and you have a concrete before-and-after metric. See [Quick Start](/quick-start) for setup.
+2. **The fixes may be small.** Most high-impact improvements are configuration changes, not content changes. See the [effort table above](#the-effort-has-an-outsized-impact). The effort size varies depending on your documentation platform.
+3. **The problem is invisible without measurement.** You won't get bug reports about this. The Agent Score is the feedback loop.
+4. **It's competitive.** If your competitors' docs are agent-friendly and yours aren't, agents will produce better code for their products.
+5. **It protects your docs investment.** You've already written the content. Agent-friendliness makes sure it reaches this growing audience.
diff --git a/package.json b/package.json
index 3632c1b..0c9ab9e 100644
--- a/package.json
+++ b/package.json
@@ -34,7 +34,10 @@
"format": "prettier --write .",
"format:check": "prettier --check .",
"prepare": "husky",
- "prepublishOnly": "npm run lint && npm test && npm run build"
+ "prepublishOnly": "npm run lint && npm test && npm run build",
+ "docs:dev": "npm run dev --prefix docs",
+ "docs:build": "npm run build --prefix docs",
+ "docs:preview": "npm run preview --prefix docs"
},
"lint-staged": {
"*.{ts,js,mjs}": [
@@ -67,7 +70,7 @@
"bugs": {
"url": "https://github.com/agent-ecosystem/afdocs/issues"
},
- "homepage": "https://github.com/agent-ecosystem/afdocs",
+ "homepage": "https://afdocs.dev",
"license": "MIT",
"engines": {
"node": ">=22"