failproofai 0.0.11-beta.8 → 0.0.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.next/standalone/.next/BUILD_ID +1 -1
- package/.next/standalone/.next/app-path-routes-manifest.json +1 -0
- package/.next/standalone/.next/build-manifest.json +6 -6
- package/.next/standalone/.next/prerender-manifest.json +3 -3
- package/.next/standalone/.next/required-server-files.json +1 -1
- package/.next/standalone/.next/routes-manifest.json +6 -0
- package/.next/standalone/.next/server/app/_global-error/page/build-manifest.json +3 -3
- package/.next/standalone/.next/server/app/_global-error/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/_global-error/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/_global-error.html +1 -1
- package/.next/standalone/.next/server/app/_global-error.rsc +7 -7
- package/.next/standalone/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +7 -7
- package/.next/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_not-found/page/build-manifest.json +3 -3
- package/.next/standalone/.next/server/app/_not-found/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/_not-found/page.js +2 -2
- package/.next/standalone/.next/server/app/_not-found/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/_not-found.html +1 -1
- package/.next/standalone/.next/server/app/_not-found.rsc +15 -15
- package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +15 -15
- package/.next/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +4 -4
- package/.next/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +10 -10
- package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/api/audit/invite/route/app-paths-manifest.json +3 -0
- package/.next/standalone/.next/server/app/api/audit/invite/route/build-manifest.json +9 -0
- package/.next/standalone/.next/server/app/api/audit/invite/route/server-reference-manifest.json +4 -0
- package/.next/standalone/.next/server/app/api/audit/invite/route.js +7 -0
- package/.next/standalone/.next/server/app/api/audit/invite/route.js.map +5 -0
- package/.next/standalone/.next/server/app/api/audit/invite/route.js.nft.json +1 -0
- package/.next/standalone/.next/server/app/api/audit/invite/route_client-reference-manifest.js +3 -0
- package/.next/standalone/.next/server/app/api/audit/run/route.js +1 -1
- package/.next/standalone/.next/server/app/api/audit/run/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/auth/login-request/route.js +1 -1
- package/.next/standalone/.next/server/app/api/auth/login-request/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/auth/login-verify/route.js +2 -2
- package/.next/standalone/.next/server/app/api/auth/login-verify/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/auth/logout/route.js +2 -2
- package/.next/standalone/.next/server/app/api/auth/logout/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/auth/reminder/route.js +2 -2
- package/.next/standalone/.next/server/app/api/auth/reminder/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/auth/status/route.js +2 -2
- package/.next/standalone/.next/server/app/api/auth/status/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/download/[project]/[session]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/audit/page/build-manifest.json +3 -3
- package/.next/standalone/.next/server/app/audit/page/server-reference-manifest.json +2 -2
- package/.next/standalone/.next/server/app/audit/page.js +2 -2
- package/.next/standalone/.next/server/app/audit/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/audit/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/index.html +1 -1
- package/.next/standalone/.next/server/app/index.rsc +15 -15
- package/.next/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/index.segments/_full.segment.rsc +15 -15
- package/.next/standalone/.next/server/app/index.segments/_head.segment.rsc +4 -4
- package/.next/standalone/.next/server/app/index.segments/_index.segment.rsc +10 -10
- package/.next/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/page/build-manifest.json +3 -3
- package/.next/standalone/.next/server/app/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/page.js +2 -2
- package/.next/standalone/.next/server/app/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/policies/page/build-manifest.json +3 -3
- package/.next/standalone/.next/server/app/policies/page/server-reference-manifest.json +8 -8
- package/.next/standalone/.next/server/app/policies/page.js +2 -2
- package/.next/standalone/.next/server/app/policies/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/policies/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/project/[name]/page/build-manifest.json +3 -3
- package/.next/standalone/.next/server/app/project/[name]/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/project/[name]/page.js +3 -3
- package/.next/standalone/.next/server/app/project/[name]/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/project/[name]/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/build-manifest.json +3 -3
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/react-loadable-manifest.json +2 -2
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/server-reference-manifest.json +2 -2
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page.js +3 -3
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/projects/page/build-manifest.json +3 -3
- package/.next/standalone/.next/server/app/projects/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/projects/page.js +3 -3
- package/.next/standalone/.next/server/app/projects/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/projects/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app-paths-manifest.json +1 -0
- package/.next/standalone/.next/server/chunks/[externals]__1_g_b3t._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0dwpg-h._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0lnenda._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__13i_sva._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1_mqemn._.js +1 -1
- package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_audit_invite_route_actions_0-2n5sy.js +3 -0
- package/.next/standalone/.next/server/chunks/node_modules_0-tu4ot._.js +3 -0
- package/.next/standalone/.next/server/chunks/node_modules_0ttxbz7._.js +3 -0
- package/.next/standalone/.next/server/chunks/node_modules_1bnh1y0._.js +3 -0
- package/.next/standalone/.next/server/chunks/node_modules_1epycqa._.js +3 -0
- package/.next/standalone/.next/server/chunks/node_modules_1wpdcgo._.js +3 -0
- package/.next/standalone/.next/server/chunks/node_modules_next_dist_esm_build_templates_app-route_17k9e3w.js +3 -3
- package/.next/standalone/.next/server/chunks/node_modules_posthog-node_dist_entrypoints_index_node_mjs_01r25oi._.js +1 -1
- package/.next/standalone/.next/server/chunks/node_modules_posthog-node_dist_entrypoints_index_node_mjs_09z9-p7._.js +1 -1
- package/.next/standalone/.next/server/chunks/package_json_[json]_cjs_1nxcc4v._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__1d4gx_t._.js → [root-of-the-server]__00uwqi6._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0808sha._.js +4 -0
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__1cd25c7._.js → [root-of-the-server]__0e4-6d8._.js} +3 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0ehe24g._.js +4 -0
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__1-scthx._.js → [root-of-the-server]__0f62vu9._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0g253ve._.js +4 -0
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0l13qf2._.js → [root-of-the-server]__0k65l27._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__15i0juc._.js → [root-of-the-server]__0kjb_s4._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0vxf0_g._.js +4 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__12mcauo._.js +4 -0
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0989_dx._.js → [root-of-the-server]__1e-x7j4._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1mt35_w._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1pcxxwg._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1uvfwgr._.js +4 -0
- package/.next/standalone/.next/server/chunks/ssr/_05whahf._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_0il3fl1._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/app_audit__components_audit-dashboard_tsx_0p9ud47._.js +49 -21
- package/.next/standalone/.next/server/chunks/ssr/app_global-error_tsx_1kp6l3x._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/app_policies_hooks-client_tsx_19dqvpc._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/node_modules_html-to-image_es_index_0ihmbv4.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/node_modules_html-to-image_es_index_1ao30b1.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/node_modules_posthog-node_dist_entrypoints_index_node_mjs_11bnuzn._.js +1 -1
- package/.next/standalone/.next/server/middleware-build-manifest.js +6 -6
- package/.next/standalone/.next/server/pages/404.html +1 -1
- package/.next/standalone/.next/server/pages/500.html +1 -1
- package/.next/standalone/.next/server/server-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/server-reference-manifest.json +10 -10
- package/.next/standalone/.next/static/chunks/{0d49wc5zca0u1.js → 02fywjt0by40a.js} +1 -1
- package/.next/standalone/.next/static/chunks/0f7d7hnbh4djs.js +1 -0
- package/.next/standalone/.next/static/chunks/0h7auy7hzjyhw.js +1 -0
- package/.next/standalone/.next/static/chunks/0xdx2ehtbdoeg.js +1 -0
- package/.next/standalone/.next/static/chunks/{1nd1e30h8s_mc.js → 1-a5rvq67k7ed.js} +1 -1
- package/.next/standalone/.next/static/chunks/{1m2yj97j7f_km.js → 15csyj1_rf0-w.js} +1 -1
- package/.next/standalone/.next/static/chunks/1o0xa47736gi9.css +2 -0
- package/.next/standalone/.next/static/chunks/24cv31x607n7k.js +1 -0
- package/.next/standalone/.next/static/chunks/{3w8d8k_dca5rp.js → 2h0dkzyy0vocp.js} +1 -1
- package/.next/standalone/.next/static/chunks/2n_s8v1ae38_a.js +69 -0
- package/.next/standalone/.next/static/chunks/2y-jmvrjxz60x.js +6 -0
- package/.next/standalone/.next/static/chunks/{24z-bgbisv379.js → 3eik_d9qrvoft.js} +1 -1
- package/.next/standalone/.next/static/chunks/3i27c3hcriawq.css +1 -0
- package/.next/standalone/.next/static/chunks/{0j969hb6nujdf.js → 3v61675vr6jav.js} +1 -1
- package/.next/standalone/.next/static/chunks/3zkg2s2vzxc3d.js +1 -0
- package/.next/standalone/.next/static/chunks/{turbopack-00qy7zfa7m--m.js → turbopack-3lrm4f20fz89b.js} +1 -1
- package/.next/standalone/app/api/audit/invite/route.ts +192 -0
- package/.next/standalone/app/api/audit/run/route.ts +35 -0
- package/.next/standalone/app/api/auth/login-request/route.ts +2 -2
- package/.next/standalone/app/api/auth/login-verify/route.ts +10 -2
- package/.next/standalone/app/audit/_components/audit-dashboard.tsx +39 -63
- package/.next/standalone/app/audit/_components/audit-poster.tsx +326 -0
- package/.next/standalone/app/audit/_components/auth-dialog.tsx +23 -49
- package/.next/standalone/app/audit/_components/come-back-better-section.tsx +336 -0
- package/.next/standalone/app/audit/_components/how-to-improve-section.tsx +187 -0
- package/.next/standalone/app/audit/_components/invite-dialog.tsx +230 -0
- package/.next/standalone/app/audit/_components/quirks-section.tsx +75 -0
- package/.next/standalone/app/audit/_components/share-templates.ts +63 -32
- package/.next/standalone/app/audit/_components/sigil.tsx +9 -66
- package/.next/standalone/app/audit/_components/strengths-section.tsx +20 -32
- package/.next/standalone/app/audit/audit-styles.css +778 -1786
- package/.next/standalone/app/components/sessions-list.tsx +77 -80
- package/.next/standalone/app/globals.css +241 -34
- package/.next/standalone/app/layout.tsx +1 -10
- package/.next/standalone/app/policies/hooks-client.tsx +45 -28
- package/.next/standalone/app/project/[name]/page.tsx +23 -79
- package/.next/standalone/app/projects/page.tsx +14 -23
- package/.next/standalone/assets/audit/poster-styles.css +1 -1
- package/.next/standalone/assets/audit/styles.css +11 -11
- package/.next/standalone/components/navbar.tsx +2 -37
- package/.next/standalone/components/reach-developers.tsx +10 -25
- package/.next/standalone/lib/auth/api-server-client.ts +28 -0
- package/.next/standalone/lib/client-telemetry.ts +4 -0
- package/.next/standalone/node_modules/@next/env/package.json +2 -2
- package/.next/standalone/node_modules/next/dist/build/swc/index.js +1 -1
- package/.next/standalone/node_modules/next/dist/compiled/next-server/pages-turbo.runtime.prod.js +1 -1
- package/.next/standalone/node_modules/next/dist/lib/patch-incorrect-lockfile.js +3 -3
- package/.next/standalone/node_modules/next/dist/server/config.js +1 -1
- package/.next/standalone/node_modules/next/dist/server/dev/hot-reloader-turbopack.js +2 -2
- package/.next/standalone/node_modules/next/dist/server/dev/hot-reloader-webpack.js +1 -1
- package/.next/standalone/node_modules/next/dist/server/lib/app-info-log.js +1 -1
- package/.next/standalone/node_modules/next/dist/server/lib/start-server.js +1 -1
- package/.next/standalone/node_modules/next/dist/shared/lib/errors/canary-only-config-error.js +1 -1
- package/.next/standalone/node_modules/next/dist/telemetry/anonymous-meta.js +1 -1
- package/.next/standalone/node_modules/next/dist/telemetry/events/swc-load-failure.js +1 -1
- package/.next/standalone/node_modules/next/dist/telemetry/events/version.js +2 -2
- package/.next/standalone/node_modules/next/package.json +15 -15
- package/.next/standalone/package.json +19 -14
- package/.next/standalone/server.js +1 -1
- package/README.md +2 -2
- package/bin/failproofai.mjs +24 -5
- package/dist/cli.mjs +2328 -381
- package/lib/auth/api-server-client.ts +28 -0
- package/lib/client-telemetry.ts +4 -0
- package/package.json +19 -14
- package/scripts/launch.ts +30 -4
- package/scripts/postinstall.mjs +10 -1
- package/scripts/skew-log-filter.ts +46 -0
- package/scripts/validate-mdx.ts +139 -0
- package/src/audit/cli.ts +330 -0
- package/src/audit/open-browser.ts +69 -0
- package/src/audit/social-proof.ts +34 -0
- package/src/auth/cli.ts +16 -13
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__07tgnzi._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0oeun7z._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__12pit4m._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__13ra2jq._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1b9z5-i._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1ixjiy8._.js +0 -3
- package/.next/standalone/.next/server/chunks/_1-1804f._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__00jkjmt._.js +0 -4
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__013du6r._.js +0 -4
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0e85wxv._.js +0 -4
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0gfxvb1._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1hlrq6y._.js +0 -4
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1ihxdo5._.js +0 -4
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1vvfde2._.js +0 -4
- package/.next/standalone/.next/server/chunks/ssr/node_modules_html2canvas_dist_html2canvas_esm_1k58rb_.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/node_modules_html2canvas_dist_html2canvas_esm_1n-0xws.js +0 -3
- package/.next/standalone/.next/static/chunks/09ueq8s1as8xs.css +0 -2
- package/.next/standalone/.next/static/chunks/0qassxjx1ef04.js +0 -1
- package/.next/standalone/.next/static/chunks/0qxb5czqxe-vu.js +0 -1
- package/.next/standalone/.next/static/chunks/1dh06515j265n.js +0 -41
- package/.next/standalone/.next/static/chunks/29gs4efgi3hme.js +0 -6
- package/.next/standalone/.next/static/chunks/2mni177pnjx6u.js +0 -1
- package/.next/standalone/.next/static/chunks/2so39wg7mjbi7.js +0 -1
- package/.next/standalone/.next/static/chunks/3gti1qdk5epqn.js +0 -1
- package/.next/standalone/.next/static/chunks/3wycox197ouus.css +0 -1
- package/.next/standalone/app/audit/_components/findings-section.tsx +0 -135
- package/.next/standalone/app/audit/_components/identity-section.tsx +0 -126
- package/.next/standalone/app/audit/_components/policies-section.tsx +0 -194
- package/.next/standalone/app/audit/_components/return-section.tsx +0 -416
- package/.next/standalone/app/audit/_components/score-section.tsx +0 -179
- package/.next/standalone/app/audit/_components/share-dock.tsx +0 -265
- package/.next/standalone/app/audit/_components/show-off-cta.tsx +0 -135
- /package/.next/standalone/.next/static/{CVv2A0hMd24t0c0x3V-W_ → P_MIRSeoE296wkbE-Icin}/_buildManifest.js +0 -0
- /package/.next/standalone/.next/static/{CVv2A0hMd24t0c0x3V-W_ → P_MIRSeoE296wkbE-Icin}/_clientMiddlewareManifest.js +0 -0
- /package/.next/standalone/.next/static/{CVv2A0hMd24t0c0x3V-W_ → P_MIRSeoE296wkbE-Icin}/_ssgManifest.js +0 -0
|
@@ -1 +0,0 @@
|
|
|
1
|
-
.scanline-overlay{pointer-events:none;z-index:9999;mix-blend-mode:overlay;background:repeating-linear-gradient(#fff0 0 2px,#ffffff05 2px 3px);position:fixed;inset:0}.empty-section,.running-section{padding-top:80px;padding-bottom:96px}.empty-panel,.running-panel{background:repeating-linear-gradient(0deg, #e4587d06 0 1px, transparent 1px 16px), repeating-linear-gradient(90deg, #66d1b506 0 1px, transparent 1px 16px), var(--bg-2);flex-direction:column;padding:48px 56px;display:flex}.empty-glyph{text-align:center;align-self:center;margin-bottom:28px}.empty-glyph-grid{border:1px solid var(--line-2);background:var(--bg);box-shadow:6px 6px 0 0 var(--accent-pink-shadow);grid-template-rows:repeat(6,14px);grid-template-columns:repeat(6,14px);gap:3px;margin:0 auto 14px;padding:16px;display:grid}.empty-glyph-grid .px{background:0 0}.empty-glyph-grid .px.on{background:var(--accent-pink)}.empty-glyph-label{font-family:var(--font-mono);letter-spacing:.22em;text-transform:uppercase;color:var(--dim);font-size:11px}.empty-headline{font-family:var(--font-display);letter-spacing:.1em;text-transform:lowercase;color:var(--ink);text-shadow:3px 3px 0 var(--accent-pink-shadow);text-wrap:balance;text-align:center;margin:0 0 16px;font-size:clamp(32px,4.6vw,48px);line-height:1.05}.empty-sub{font-family:var(--font-mono);color:var(--ink-2);text-align:center;max-width:580px;margin:0 auto 32px;font-size:14px;line-height:1.65}.empty-actions{flex-direction:column;align-items:center;gap:12px;display:flex}.empty-cta{letter-spacing:.08em;padding:12px 24px;font-size:14px;text-decoration:none}.empty-meta{font-family:var(--font-mono);letter-spacing:.15em;text-transform:uppercase;color:var(--dim);font-size:11px}.running-panel{padding:36px 40px}.running-header{border-bottom:1px dashed var(--line);font-family:var(--font-mono);align-items:center;gap:10px;margin-bottom:22px;padding-bottom:18px;font-size:13px;display:flex}.running-prompt{color:var(--accent-green)}.running-cmd{color:var(--ink);letter-spacing:.02em}.running-cursor{color:var(--accent-pink);margin-left:4px;animation:.9s steps(2,end) infinite cursor-blink}@keyframes cursor-blink{50%{opacity:0}}.running-stages{flex-direction:column;margin:0 0 28px;padding:0;list-style:none;display:flex}.running-stage{border-bottom:1px dashed var(--line);font-family:var(--font-mono);grid-template-columns:28px 1fr auto;align-items:start;gap:14px;padding:12px 0;display:grid}.running-stage:last-child{border-bottom:none}.running-marker{font-family:var(--font-mono);letter-spacing:-1px;margin-top:1px;font-size:12px}.running-stage.queued{color:var(--dim)}.running-stage.queued .running-marker{color:var(--line-2)}.running-stage.active{color:var(--ink)}.running-stage.active .running-marker{color:var(--accent-pink)}.running-stage.done{color:var(--ink-2)}.running-stage.done .running-marker{color:var(--accent-green)}.running-stage.done .running-stage-label{text-decoration:line-through;-webkit-text-decoration-color:var(--line-2);text-decoration-color:var(--line-2)}.running-stage-label{letter-spacing:.04em;font-size:13px}.running-stage-detail{color:var(--ink-2);letter-spacing:.02em;margin-top:4px;font-size:11px}.running-stage-spin{font-family:var(--font-mono);color:var(--accent-pink);align-self:center;font-size:16px;animation:.7s steps(4,end) infinite spin-step}@keyframes spin-step{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.running-bar-label{font-family:var(--font-mono);letter-spacing:.22em;text-transform:uppercase;color:var(--ink-2);justify-content:space-between;margin-bottom:8px;font-size:10px;display:flex}.running-bar-track{background:var(--bg);border:1px solid var(--line);height:6px;position:relative;overflow:hidden}.running-bar-fill{background:linear-gradient(90deg, var(--accent-pink) 0%, #e89aaf 100%);height:100%;transition:width .6s cubic-bezier(.22,1,.36,1);position:relative}.running-bar-fill:after{content:"";background:linear-gradient(90deg,#0000 0% 40%,#ffffff59 50%,#0000 60% 100%);animation:1.6s linear infinite bar-shine;position:absolute;inset:0}@keyframes bar-shine{0%{transform:translate(-100%)}to{transform:translate(100%)}}.running-foot{font-family:var(--font-mono);letter-spacing:.05em;color:var(--dim);text-align:center;margin-top:22px;font-size:11px}@media (max-width:720px){.empty-panel,.running-panel{padding:32px 24px}}.report{width:100%;max-width:clamp(720px,92vw,1480px);margin:0 auto;padding:0 clamp(20px,3vw,48px)}.section{border-bottom:1px solid var(--line);padding:64px 0;position:relative}.section:last-child{border-bottom:none}.section-mast{flex-wrap:wrap;justify-content:space-between;align-items:baseline;gap:24px;margin-bottom:28px;display:flex}.section-label{font-family:var(--font-mono);letter-spacing:.2em;text-transform:uppercase;color:var(--accent-green);align-items:baseline;gap:10px;font-size:11px;display:inline-flex}.section-label .glyph{color:var(--accent-pink);letter-spacing:-2px}.section-meta{font-family:var(--font-mono);letter-spacing:.18em;text-transform:uppercase;color:var(--dim);font-size:11px}.section-meta .g{color:var(--accent-green)}.section-meta .p{color:var(--accent-pink)}.section-h{font-family:var(--font-display);letter-spacing:.11em;color:var(--ink);text-transform:lowercase;text-wrap:balance;margin:0 0 18px;font-size:clamp(28px,4vw,44px);font-weight:400;line-height:1.05}.identity{padding:80px 0 96px;position:relative}.archetype-frame{border:1px solid var(--line-2);background:repeating-linear-gradient(0deg, #e4587d06 0 1px, transparent 1px 16px), repeating-linear-gradient(90deg, #66d1b506 0 1px, transparent 1px 16px), var(--bg-2);max-width:1320px;box-shadow:8px 8px 0 0 var(--accent-pink-shadow);margin-left:auto;margin-right:auto;padding:56px 56px 48px;position:relative}.archetype-frame .corner{font-family:var(--font-mono);color:var(--accent-pink);opacity:.6;letter-spacing:.1em;font-size:11px;position:absolute}.archetype-frame .corner.tl{top:8px;left:12px}.archetype-frame .corner.tr{top:8px;right:12px}.archetype-frame .corner.bl{bottom:8px;left:12px}.archetype-frame .corner.br{bottom:8px;right:12px}.arch-mast{border-bottom:1px dashed var(--line);flex-wrap:wrap;justify-content:space-between;align-items:center;gap:24px;margin-bottom:32px;padding-bottom:22px;display:flex}.arch-mast-left{flex-direction:column;gap:8px;display:flex}.arch-eyebrow{font-family:var(--font-mono);letter-spacing:.22em;text-transform:uppercase;color:var(--accent-green);font-size:11px}.arch-eyebrow .ix{color:var(--accent-pink)}.arch-target{font-family:var(--font-mono);color:var(--ink-2);letter-spacing:.05em;font-size:12px}.arch-target .slash{color:var(--dim);margin:0 6px}.arch-target .live{color:var(--accent-green);letter-spacing:.2em;text-transform:uppercase;align-items:center;gap:6px;margin-left:10px;font-size:10px;display:inline-flex}.arch-target .dot-live{background:var(--accent-green);width:7px;height:7px;animation:1.6s ease-in-out infinite pulseDot;display:inline-block;box-shadow:0 0 8px #66d1b599}@keyframes pulseDot{0%,to{opacity:1;transform:scale(1)}50%{opacity:.4;transform:scale(.85)}}@media (prefers-reduced-motion:reduce){.arch-target .dot-live{animation:none}}.arch-counter{font-family:var(--font-mono);letter-spacing:.18em;text-transform:uppercase;color:var(--dim);text-align:right;font-size:11px}.arch-counter .of{color:var(--ink-2)}.arch-body{grid-template-columns:1.7fr 1fr;align-items:center;gap:56px;display:grid}.arch-name{font-family:var(--font-display);letter-spacing:.08em;text-transform:lowercase;color:var(--ink);text-wrap:balance;text-shadow:4px 4px 0 var(--accent-pink-shadow);margin:0 0 16px;font-size:clamp(56px,10vw,124px);line-height:.95}.arch-tagline{font-family:var(--font-mono);color:var(--ink-2);text-wrap:pretty;max-width:580px;margin:0 0 28px;font-size:16px;line-height:1.5}.arch-desc{font-family:var(--font-mono);color:var(--ink);text-wrap:pretty;max-width:580px;margin:0 0 28px;font-size:13px;line-height:1.65}.arch-secondary{border:1px dashed var(--line-2);font-family:var(--font-mono);letter-spacing:.15em;text-transform:uppercase;color:var(--ink-2);align-items:center;gap:10px;margin-bottom:24px;padding:6px 12px;font-size:11px;display:inline-flex}.arch-secondary .with{color:var(--dim)}.arch-secondary .name{color:var(--accent-pink)}.arch-keywords{font-family:var(--font-display);letter-spacing:.11em;text-transform:lowercase;flex-wrap:wrap;align-items:baseline;gap:16px;padding:18px 0 4px;font-size:clamp(20px,2.4vw,28px);line-height:1.1;display:flex}.arch-keywords .kw{color:var(--ink)}.arch-keywords .kw:first-child{color:var(--accent-green)}.arch-keywords .kw:nth-child(3){color:var(--ink)}.arch-keywords .kw:nth-child(5){color:var(--accent-pink)}.arch-keywords .kw-sep{color:var(--dim);font-family:var(--font-mono);letter-spacing:0;font-size:18px}.signature-block{background:var(--bg);border:1px solid var(--line);font-family:var(--font-mono);white-space:pre;max-width:580px;padding:18px 20px;font-size:13px;line-height:1.75;position:relative;overflow-x:auto}.signature-block:before{content:"";border-top:1px solid var(--accent-pink);border-left:1px solid var(--accent-pink);width:8px;height:8px;position:absolute;top:-1px;left:-1px}.signature-block:after{content:"";border-bottom:1px solid var(--accent-pink);border-right:1px solid var(--accent-pink);width:8px;height:8px;position:absolute;bottom:-1px;right:-1px}.sig-line{color:var(--ink);display:block}.sig-line .arrow{color:var(--accent-green);margin-right:6px}.sig-line .comment{color:var(--dim)}.sig-line .err{color:var(--accent-pink)}.arch-meta-grid{border-top:1px dashed var(--line);grid-template-columns:1fr 1fr;gap:24px;margin-top:28px;padding-top:22px;display:grid}.arch-meta-item .label{font-family:var(--font-mono);letter-spacing:.22em;text-transform:uppercase;color:var(--accent-green);margin-bottom:8px;font-size:10px;display:block}.arch-meta-item .label.p{color:var(--accent-pink)}.arch-meta-item .body{font-family:var(--font-mono);color:var(--ink-2);font-size:12px;line-height:1.55}.arch-closing{font-family:var(--font-display);letter-spacing:.11em;color:var(--accent-pink);text-transform:lowercase;border-top:1px dashed var(--line);margin-top:28px;padding-top:22px;font-size:22px}.sigil-wrap{flex-direction:column;justify-self:center;align-items:center;display:flex}.sigil-plate{background: repeating-linear-gradient(0deg, #e4587d0a 0 1px, transparent 1px 12px), repeating-linear-gradient(90deg, #66d1b50a 0 1px, transparent 1px 12px), var(--bg);border:1px solid var(--line-2);box-shadow:8px 8px 0 0 var(--accent-pink-shadow), 16px 16px 0 0 #0000008c;padding:18px 22px;position:relative}.sigil-mark{width:10px;height:10px;color:var(--accent-pink);opacity:.75;pointer-events:none;position:absolute}.sigil-mark:before,.sigil-mark:after{content:"";background:currentColor;position:absolute}.sigil-mark:before{height:1px;top:50%;left:0;right:0}.sigil-mark:after{width:1px;top:0;bottom:0;left:50%}.sigil-mark.tl{top:6px;left:6px}.sigil-mark.tr{top:6px;right:6px}.sigil-mark.bl{bottom:6px;left:6px}.sigil-mark.br{bottom:6px;right:6px}.sigil-strip{font-family:var(--font-mono);letter-spacing:.22em;text-transform:uppercase;color:var(--dim);justify-content:space-between;align-items:baseline;font-size:10px;display:flex}.sigil-strip--top{border-bottom:1px dashed var(--line);margin-bottom:14px;padding-bottom:10px}.sigil-strip--bot{border-top:1px dashed var(--line);margin-top:14px;padding-top:10px}.sigil-ix{color:var(--accent-pink)}.sigil-coord,.sigil-strip-key{color:var(--dim)}.sigil-strip-val{color:var(--accent-green)}.sigil{background:var(--bg-2);border:1px dashed var(--line);grid-template-rows:repeat(8,20px);grid-template-columns:repeat(8,20px);gap:2px;margin:0 auto;padding:12px;display:grid}.sigil-wrap[data-bare=true] .sigil{background:var(--bg);border:1px solid var(--line-2);box-shadow:6px 6px 0 0 var(--accent-pink-shadow)}.sigil .px{opacity:0;animation:.28s cubic-bezier(.22,1,.36,1) forwards sigil-cell-in;animation-delay:calc((var(--cx,0) + var(--cy,0)) * 22ms);background:0 0}.sigil .px.on{background:var(--ink)}.sigil .px.p{background:var(--accent-pink);box-shadow:0 0 4px #e4587d73}.sigil .px.g{background:var(--accent-green);box-shadow:0 0 4px #66d1b559}.sigil .px.d{background:var(--dim)}@keyframes sigil-cell-in{0%{opacity:0;transform:scale(.4)}to{opacity:1;transform:scale(1)}}@media (prefers-reduced-motion:reduce){.sigil .px{opacity:1;animation:none;transform:none}}.archetype-frame.capturing{min-width:1080px;max-width:1180px;box-shadow:none;padding:52px 52px 44px}.archetype-frame.capturing .arch-name{text-shadow:none;letter-spacing:.06em;margin:0 0 24px;font-size:88px;line-height:1}.archetype-frame.capturing .arch-tagline{max-width:560px;margin:0 0 32px;font-size:16px}.archetype-frame.capturing .arch-secondary{margin-bottom:32px}.archetype-frame.capturing .arch-keywords{letter-spacing:.09em;gap:14px;max-width:560px;padding:16px 0 12px;font-size:24px}.archetype-frame.capturing .arch-body{grid-template-columns:minmax(0,1.6fr) minmax(220px,1fr);align-items:start;gap:56px}.archetype-frame.capturing .arch-meta-grid{gap:28px;margin-top:32px;padding-top:26px}.archetype-frame.capturing .arch-closing{margin-top:32px;padding-top:26px;font-size:22px}.archetype-frame.capturing .sigil-wrap{place-self:center;padding-top:0;position:static}.archetype-frame.capturing .sigil-plate{box-shadow:8px 8px 0 0 var(--accent-pink-shadow)}.archetype-frame.capturing .sigil{box-shadow:none}.archetype-frame.capturing .sigil .px{opacity:1;animation:none;transform:none}.identity-share-grid{border-top:1px dashed var(--line);grid-template-columns:repeat(3,1fr);gap:12px;margin-top:22px;padding-top:18px;display:grid}@media (max-width:720px){.identity-share-grid{grid-template-columns:1fr}}.share-btn{background:var(--bg);border:1px solid var(--line-2);border-right:2px solid var(--accent-pink-soft);color:var(--ink);font-family:var(--font-mono);text-align:left;cursor:pointer;grid-template-columns:44px 1fr auto;align-items:center;gap:14px;padding:12px 18px;transition:border-color .16s cubic-bezier(.22,1,.36,1),background-color .16s cubic-bezier(.22,1,.36,1),box-shadow .16s cubic-bezier(.22,1,.36,1),transform .16s cubic-bezier(.22,1,.36,1);display:grid;position:relative}.share-btn:hover{border-color:var(--accent-pink);background:var(--accent-pink-bg);box-shadow:4px 4px 0 0 var(--accent-pink-shadow);transform:translate(-1px,-1px)}.share-btn:active{box-shadow:0 0 0 0 var(--accent-pink-shadow);transform:translate(2px,2px)}.share-btn:disabled{opacity:.55;cursor:not-allowed;border-right-color:var(--line)}.share-btn:disabled:hover{background:var(--bg);border-color:var(--line-2);border-right-color:var(--line);box-shadow:none;transform:none}.share-btn-mark{width:44px;height:44px;font-family:var(--font-mono);border:1px solid var(--line-2);background:linear-gradient(to right, var(--accent-pink) 0 6px, transparent 6px) top left/100% 1px no-repeat, linear-gradient(to bottom, var(--accent-pink) 0 6px, transparent 6px) top left/1px 100% no-repeat, linear-gradient(to left, var(--accent-pink) 0 6px, transparent 6px) bottom right/100% 1px no-repeat, linear-gradient(to top, var(--accent-pink) 0 6px, transparent 6px) bottom right/1px 100% no-repeat, var(--bg-2);color:var(--ink);place-items:center;font-size:22px;font-weight:700;line-height:1;display:grid}.share-btn-mark--x{color:#fff;background-color:#000}.share-btn-mark--li{color:#fff;background-color:#0a66c2;background-image:none}.share-btn-mark--dl{color:var(--accent-pink)}.share-btn-body{flex-direction:column;gap:2px;min-width:0;display:flex}.share-btn-eyebrow{letter-spacing:.22em;text-transform:uppercase;color:var(--accent-green);font-size:10px}.share-btn-label{letter-spacing:.05em;color:var(--ink);text-overflow:ellipsis;white-space:nowrap;font-size:13px;font-weight:500;overflow:hidden}.share-btn-arrow{font-family:var(--font-mono);color:var(--accent-pink);opacity:.7;font-size:18px;transition:opacity .16s cubic-bezier(.22,1,.36,1),transform .16s cubic-bezier(.22,1,.36,1)}.share-btn:hover .share-btn-arrow{opacity:1;transform:translate(2px)}@media (prefers-reduced-motion:reduce){.share-btn,.share-btn-arrow{transition:none}.share-btn:hover{transform:none}}.archetype-frame.capturing .identity-share-grid{display:none}.strengths-grid{border:1px solid var(--line-2);background:var(--bg-2);gap:0;display:grid}.strength-row{border-bottom:1px solid var(--line);grid-template-columns:56px 1fr auto;align-items:start;gap:16px;padding:22px 24px;transition:background .12s;display:grid}.strength-row:last-child{border-bottom:none}.strength-row:hover{background:#66d1b508}.strength-check{border:1px solid var(--accent-green);background:var(--accent-green-bg);width:32px;height:32px;color:var(--accent-green);font-family:var(--font-mono);place-items:center;font-size:14px;font-weight:600;display:grid}.strength-body{flex-direction:column;gap:6px;display:flex}.strength-headline{font-family:var(--font-mono);color:var(--ink);letter-spacing:.01em;font-size:14px;font-weight:500}.strength-detail{font-family:var(--font-mono);color:var(--ink-2);letter-spacing:.01em;font-size:12px;line-height:1.55}.strength-metric{font-family:var(--font-display);letter-spacing:.06em;text-transform:lowercase;color:var(--accent-green);text-align:right;white-space:nowrap;font-size:26px;line-height:1}.strength-metric .unit{font-family:var(--font-mono);letter-spacing:.18em;text-transform:uppercase;color:var(--dim);margin-top:4px;font-size:10px;display:block}.strengths-footer{font-family:var(--font-mono);color:var(--ink-2);letter-spacing:.02em;margin-top:18px;padding-left:4px;font-size:12px}.score-share-card{background:repeating-linear-gradient(0deg, #e4587d08 0 1px, transparent 1px 16px), repeating-linear-gradient(90deg, #e4587d08 0 1px, transparent 1px 16px), var(--bg-2);padding:22px 24px 20px}.score-card-header{font-family:var(--font-mono);letter-spacing:.18em;text-transform:uppercase;color:var(--ink-2);margin-bottom:16px;font-size:10px}.ss-label{font-family:var(--font-mono);letter-spacing:.22em;text-transform:uppercase;color:var(--accent-green);margin-bottom:14px;font-size:10px}.ss-score-row{align-items:baseline;gap:10px;margin:0 0 10px;display:flex}.ss-score{font-family:var(--font-display);letter-spacing:.04em;color:var(--accent-pink);text-shadow:4px 4px 0 var(--accent-pink-shadow);font-size:clamp(52px,7vw,76px);line-height:.9}.ss-score.g-S,.ss-score.g-A{color:var(--accent-green);text-shadow:4px 4px 0 var(--accent-green-shadow)}.ss-score.g-B{color:#d3e1a8;text-shadow:4px 4px #6f7e45}.ss-score-of{font-family:var(--font-mono);color:var(--dim);letter-spacing:.08em;font-size:18px}.ss-tier-row{align-items:center;gap:12px;margin-bottom:16px;display:flex}.ss-tier-badge{font-family:var(--font-mono);letter-spacing:.18em;text-transform:uppercase;border:1px solid var(--accent-pink);background:var(--accent-pink-bg);color:var(--accent-pink);padding:5px 10px;font-size:11px}.ss-tier-badge.g-S,.ss-tier-badge.g-A{border-color:var(--accent-green);background:var(--accent-green-bg);color:var(--accent-green)}.ss-tier-badge.g-B{color:#d3e1a8;background:#d3e1a81a;border-color:#d3e1a8}.ss-arch{font-family:var(--font-mono);color:var(--ink-2);letter-spacing:.06em;font-size:12px}.ss-progress-label{font-family:var(--font-mono);letter-spacing:.06em;justify-content:space-between;margin-bottom:6px;font-size:11px;display:flex}.ss-progress-track{background:var(--bg);border:1px solid var(--line);height:10px;margin-bottom:6px;position:relative;overflow:visible}.ss-progress-fill{background:linear-gradient(90deg, var(--accent-pink) 0%, #f472b6 60%, #a78bfa 100%);height:100%}.ss-progress-tick{background:var(--line-2);pointer-events:none;width:1px;position:absolute;top:-4px;bottom:-4px}.ss-grade-stops{height:16px;margin-bottom:16px;position:relative}.ss-grade-stop{font-family:var(--font-mono);letter-spacing:.12em;text-transform:uppercase;color:var(--dim);font-size:9px;position:absolute;top:0;transform:translate(-50%)}.ss-grade-stop.active{color:var(--accent-pink);font-weight:700}.ss-stats{grid-template-columns:repeat(3,1fr);gap:8px;margin-bottom:16px;display:grid}.ss-stat{border:1px solid var(--line-2);background:var(--bg);text-align:left;padding:10px 12px}.ss-stat-n{font-family:var(--font-display);letter-spacing:.04em;margin-bottom:6px;font-size:24px;line-height:1}.ss-stat-l{font-family:var(--font-mono);letter-spacing:.2em;text-transform:uppercase;color:var(--dim);font-size:9px;line-height:1.4}.ss-policy-label{font-family:var(--font-mono);letter-spacing:.22em;text-transform:uppercase;color:var(--ink-2);border-top:1px dashed var(--line);margin-top:14px;margin-bottom:10px;padding-top:14px;font-size:10px}.ss-policy-chips{flex-wrap:wrap;gap:6px;display:flex}.ss-chip{border:1px solid var(--line-2);background:var(--bg);font-family:var(--font-mono);color:var(--ink-2);border-radius:0;align-items:center;gap:6px;padding:4px 10px;font-size:11px;display:inline-flex}.ss-chip .dot{background:var(--dim);border-radius:0;width:5px;height:5px}.ss-chip.missing{color:var(--accent-pink);background:#e4587d0f;border-color:#e4587d99}.ss-chip.missing .dot{background:var(--accent-pink)}.ss-chip.enabled{color:var(--accent-green);background:#66d1b50d;border-color:#66d1b580}.ss-chip.enabled .dot{background:var(--accent-green)}.ss-templates{flex-direction:column;gap:10px;margin-bottom:16px;display:flex}.ss-template{border:1px solid var(--line-2);background:var(--bg);padding:14px 16px}.ss-template-head{font-family:var(--font-mono);letter-spacing:.2em;text-transform:uppercase;color:var(--ink-2);align-items:center;gap:8px;margin-bottom:8px;font-size:10px;display:inline-flex}.ss-template-head .dot{background:var(--accent-pink);border-radius:50%;width:6px;height:6px}.ss-template-body{font-family:var(--font-mono);color:var(--ink-2);margin:0;font-size:12.5px;line-height:1.55}.ss-actions{flex-direction:column;gap:8px;display:flex}.ss-action-btn{border:1px solid var(--line-2);color:var(--ink);text-align:left;font-family:var(--font-mono);cursor:pointer;background:0 0;grid-template-columns:28px 1fr;align-items:center;gap:12px;padding:10px 14px;font-size:12px;text-decoration:none;transition:all .12s;display:grid}.ss-action-btn:hover{border-color:var(--accent-pink);background:var(--accent-pink-bg);color:var(--accent-pink)}.ss-action-btn:disabled{opacity:.55;cursor:wait}.ss-action-glyph{border:1px solid var(--ink-2);width:24px;height:24px;font-family:var(--font-mono);text-transform:uppercase;color:var(--ink-2);place-items:center;font-size:11px;display:grid}.ss-action-btn:hover .ss-action-glyph{border-color:var(--accent-pink);color:var(--accent-pink)}.ss-action-text{flex-direction:column;display:flex}.ss-action-title{font-family:var(--font-mono);letter-spacing:.04em;color:var(--ink);font-size:13px}.ss-action-btn:hover .ss-action-title{color:var(--accent-pink)}.ss-action-sub{font-family:var(--font-mono);letter-spacing:.05em;color:var(--dim);margin-top:2px;font-size:10px}.ss-foot{border-top:1px dashed var(--line);font-family:var(--font-mono);color:var(--ink-2);flex-wrap:wrap;justify-content:space-between;gap:16px;margin-top:26px;padding-top:18px;font-size:11px;display:flex}.ss-foot-link{color:var(--accent-green);text-decoration:none}.ss-foot-link:hover{text-underline-offset:3px;text-decoration:underline}@media (max-width:880px){.score-share-card{padding:16px}}.findings-list{flex-direction:column;gap:20px;display:flex}.finding{border:1px solid var(--line-2);background:var(--bg-2);position:relative}.finding:before{content:"";border-top:1px solid var(--accent-pink);border-left:1px solid var(--accent-pink);width:8px;height:8px;position:absolute;top:-1px;left:-1px}.finding-head{border-bottom:1px solid var(--line);grid-template-columns:auto 1fr auto;align-items:center;gap:18px;padding:20px 24px;display:grid}.finding-num{font-family:var(--font-mono);color:var(--accent-pink);letter-spacing:.12em;font-size:13px;font-weight:600}.finding-title{font-family:var(--font-display);letter-spacing:.11em;color:var(--ink);text-transform:lowercase;font-size:22px}.finding-count{font-family:var(--font-display);letter-spacing:.04em;color:var(--accent-pink);text-transform:lowercase;align-items:baseline;gap:6px;font-size:36px;line-height:1;display:flex}.finding-count .label{font-family:var(--font-mono);letter-spacing:.22em;text-transform:uppercase;color:var(--dim);font-size:10px}.finding-meta{font-family:var(--font-mono);letter-spacing:.05em;color:var(--ink-2);border-bottom:1px solid var(--line);background:#00000026;flex-wrap:wrap;gap:16px;padding:12px 24px;font-size:11px;display:flex}.finding-meta .policy{color:var(--accent-green)}.finding-meta .sep{color:var(--dim)}.finding-body{grid-template-columns:1fr 1fr;gap:0;display:grid}.finding-block{border-right:1px solid var(--line);border-bottom:1px solid var(--line);flex-direction:column;gap:10px;padding:22px 24px;display:flex}.finding-block:nth-child(2n){border-right:none}.finding-block:nth-last-child(-n+2){border-bottom:none}.fb-label{font-family:var(--font-mono);letter-spacing:.22em;text-transform:uppercase;color:var(--accent-green);font-size:10px}.fb-label.cost{color:var(--amber)}.fb-label.fix{color:var(--accent-pink)}.fb-body{font-family:var(--font-mono);color:var(--ink-2);font-size:13px;line-height:1.65}.fb-body .pk{color:var(--accent-pink)}.fb-body .g{color:var(--accent-green)}.fb-body .a{color:var(--amber)}.fb-body code{background:var(--bg);border:1px solid var(--line);color:var(--accent-green);padding:1px 6px;font-size:12px}.fb-evidence{font-family:var(--font-mono);background:var(--bg);border:1px solid var(--line);white-space:pre;color:var(--ink);padding:12px 14px;font-size:12px;line-height:1.65;overflow-x:auto}.fb-evidence .arrow{color:var(--accent-green)}.fb-evidence .err{color:var(--accent-pink)}.fb-evidence .comment{color:var(--dim)}.fb-fix{background:var(--bg);border:1px solid var(--line);font-family:var(--font-mono);padding:14px;font-size:12px}.fb-fix .slug{background:var(--accent-pink-bg);color:var(--accent-pink);border:1px solid var(--accent-pink);letter-spacing:.15em;text-transform:uppercase;margin-bottom:10px;padding:2px 8px;font-size:10px;display:inline-block}.fb-fix .cmd{color:var(--accent-green);border-top:1px dashed var(--line);margin-top:12px;padding-top:10px;font-size:12px;display:block}.fb-fix .cmd .prompt{color:var(--dim);margin-right:6px}.showoff{border-bottom:1px solid var(--line);margin-bottom:0;padding:0 0 32px;scroll-margin-top:80px}.showoff-cta{border:1px solid var(--line-2);background:repeating-linear-gradient(0deg, #e4587d06 0 1px, transparent 1px 16px), repeating-linear-gradient(90deg, #e4587d06 0 1px, transparent 1px 16px), var(--bg-2);color:var(--ink);grid-template-columns:auto 1fr auto;align-items:center;gap:32px;padding:28px 32px;text-decoration:none;transition:border-color .12s,background .12s;display:grid;position:relative}.showoff-cta:hover{border-color:var(--ink-2);background:repeating-linear-gradient(0deg, #e4587d0a 0 1px, transparent 1px 16px), repeating-linear-gradient(90deg, #e4587d0a 0 1px, transparent 1px 16px), var(--bg-3)}.showoff-cta:before{content:"";border-top:1px solid var(--accent-pink);border-left:1px solid var(--accent-pink);width:10px;height:10px;position:absolute;top:-1px;left:-1px}.showoff-cta:after{content:"";border-bottom:1px solid var(--accent-pink);border-right:1px solid var(--accent-pink);width:10px;height:10px;position:absolute;bottom:-1px;right:-1px}.showoff-glyph{transform-origin:50%;margin:-40px -28px;display:block;transform:scale(.55)}.showoff-glyph .sigil-wrap[data-bare=true] .sigil{box-shadow:4px 4px 0 0 var(--accent-pink-shadow)}.showoff-glyph .sigil-label{display:none}.showoff-copy{flex-direction:column;gap:6px;min-width:0;display:flex}.showoff-label{font-family:var(--font-mono);letter-spacing:.22em;text-transform:uppercase;color:var(--accent-green);font-size:11px}.showoff-headline{font-family:var(--font-display);letter-spacing:.11em;text-transform:lowercase;color:var(--ink);text-shadow:3px 3px 0 var(--accent-pink-shadow);font-size:clamp(28px,3.4vw,40px);line-height:1.05}.showoff-sub{font-family:var(--font-mono);color:var(--ink-2);max-width:520px;font-size:13px;line-height:1.55}.showoff-action{border:1px solid var(--accent-pink);background:var(--accent-pink-bg);color:var(--accent-pink);font-family:var(--font-mono);letter-spacing:.22em;text-transform:uppercase;white-space:nowrap;flex-direction:column;align-items:center;gap:8px;padding:16px 24px;font-size:11px;display:inline-flex}.showoff-arrow{font-family:var(--font-display);letter-spacing:0;color:var(--accent-pink);font-size:36px;line-height:1}@media (max-width:800px){.showoff-cta{grid-template-columns:1fr;gap:18px;padding:24px 20px}.showoff-glyph{transform-origin:0 0;margin:0;transform:scale(.6)}.showoff-action{flex-direction:row;justify-content:center;width:100%}}.policy-callout{border:1px solid var(--accent-green);background:var(--accent-green-bg);font-family:var(--font-mono);letter-spacing:.02em;color:var(--ink);box-shadow:4px 4px 0 0 var(--accent-green-shadow);align-items:baseline;gap:12px;margin-bottom:28px;padding:12px 18px;font-size:13px;display:inline-flex}.policy-callout .arrow{color:var(--accent-green);margin:0 4px}.policy-callout .new-score{font-family:var(--font-display);letter-spacing:.08em;color:var(--accent-green);font-size:22px}.policy-callout .new-tier{color:var(--accent-green);font-weight:600}.policies-grid{grid-template-columns:repeat(2,1fr);gap:16px;display:grid}.policy-card{border:1px solid var(--line-2);background:var(--bg-2);flex-direction:column;gap:10px;padding:20px 22px;transition:all .12s;display:flex;position:relative}.policy-card:before{content:"";background:var(--accent-pink);opacity:.7;width:3px;height:100%;position:absolute;top:0;left:0}.policy-card:hover{background:var(--bg-3)}.policy-card .head{border-bottom:1px dashed var(--line);justify-content:space-between;align-items:baseline;gap:12px;margin-bottom:4px;padding-bottom:10px;display:flex}.policy-name{font-family:var(--font-display);letter-spacing:.11em;color:var(--ink);text-transform:lowercase;font-size:18px}.policy-slug{font-family:var(--font-mono);letter-spacing:.12em;color:var(--dim);text-transform:uppercase;font-size:10px}.policy-desc{font-family:var(--font-mono);color:var(--ink-2);font-size:12px;line-height:1.6}.policy-impact{font-family:var(--font-mono);color:var(--accent-green);letter-spacing:.01em;border-top:1px dashed var(--line);margin-top:auto;padding-top:10px;font-size:12px}.policy-impact .check{margin-right:6px}.policy-install{font-family:var(--font-mono);background:var(--bg);border:1px solid var(--line);color:var(--accent-green);align-items:center;gap:8px;margin-top:4px;padding:8px 10px;font-size:11px;display:flex}.policy-install .prompt{color:var(--dim)}.policy-install .copy{color:var(--dim);cursor:pointer;letter-spacing:.15em;text-transform:uppercase;margin-left:auto;font-size:10px;transition:color .12s}.policy-install .copy:hover{color:var(--accent-pink)}.share-grid{grid-template-columns:1fr 1fr;align-items:start;gap:32px;display:grid}.share-card{border:1px solid var(--accent-pink);background:repeating-linear-gradient(0deg, #e4587d05 0 1px, transparent 1px 16px), repeating-linear-gradient(90deg, #e4587d05 0 1px, transparent 1px 16px), var(--bg-2);box-shadow:8px 8px 0 0 var(--accent-pink-shadow);padding:32px;position:relative}.share-card .stamp-tl,.share-card .stamp-br{font-family:var(--font-mono);letter-spacing:.2em;text-transform:uppercase;color:var(--accent-pink);opacity:.55;font-size:9px;position:absolute}.share-card .stamp-tl{top:8px;left:12px}.share-card .stamp-br{bottom:8px;right:12px}.share-brand{align-items:center;gap:10px;margin-bottom:28px;display:flex}.share-brand .glyph{color:var(--accent-pink);font-family:var(--font-mono);letter-spacing:-2px;font-size:14px;font-weight:700}.share-brand .name{font-family:var(--font-display);letter-spacing:.11em;text-transform:lowercase;color:var(--ink);font-size:14px}.share-brand .sep{color:var(--dim);font-size:11px}.share-brand .meta{font-family:var(--font-mono);letter-spacing:.18em;text-transform:uppercase;color:var(--dim);font-size:10px}.share-project{font-family:var(--font-mono);letter-spacing:.05em;color:var(--ink-2);margin-bottom:20px;font-size:12px}.share-archetype{font-family:var(--font-display);letter-spacing:.08em;text-transform:lowercase;color:var(--ink);text-shadow:3px 3px 0 var(--accent-pink-shadow);text-wrap:balance;margin:0 0 12px;font-size:clamp(36px,5vw,56px);line-height:1}.share-rule{background:var(--accent-pink);width:56px;height:2px;margin:16px 0 20px}.share-tagline{font-family:var(--font-mono);color:var(--ink-2);text-wrap:pretty;margin-bottom:32px;font-size:14px;line-height:1.45}.share-score-row{font-family:var(--font-mono);letter-spacing:.05em;border-top:1px dashed var(--line);align-items:center;gap:14px;padding-top:22px;font-size:14px;display:flex}.share-score-row .tier{font-family:var(--font-display);letter-spacing:.08em;color:var(--accent-pink);text-transform:uppercase;font-size:22px}.share-score-row .sep{color:var(--dim)}.share-score-row .num{color:var(--ink)}.share-score-row .rank{color:var(--ink-2)}.share-url{font-family:var(--font-mono);letter-spacing:.18em;text-transform:uppercase;color:var(--accent-green);margin-top:22px;font-size:11px}.share-actions{flex-direction:column;gap:16px;display:flex}.tweet-tabs{border:1px solid var(--line-2);gap:0;display:flex}.tweet-tab{font-family:var(--font-mono);letter-spacing:.15em;text-transform:uppercase;color:var(--ink-2);border-right:1px solid var(--line);background:var(--bg-2);flex:1;padding:10px 14px;font-size:11px;transition:all .12s}.tweet-tab:last-child{border-right:none}.tweet-tab:hover{color:var(--ink)}.tweet-tab.is-active{color:var(--accent-pink);background:var(--accent-pink-bg)}.tweet-preview{background:var(--bg-2);border:1px solid var(--line-2);font-family:var(--font-mono);color:var(--ink);white-space:pre-wrap;min-height:200px;padding:20px 22px;font-size:13px;line-height:1.65;position:relative}.tweet-preview .url,.tweet-preview .arch{color:var(--accent-pink)}.tweet-meta{font-family:var(--font-mono);letter-spacing:.18em;text-transform:uppercase;color:var(--dim);justify-content:space-between;font-size:10px;display:flex}.tweet-meta .count.over{color:var(--accent-pink)}.share-buttons{flex-wrap:wrap;gap:12px;display:flex}.share-btn{font-family:var(--font-mono);letter-spacing:.04em;border:1px solid var(--accent-pink);color:var(--accent-pink);box-shadow:4px 4px 0 0 var(--accent-pink-shadow);background:0 0;align-items:center;gap:10px;padding:14px 20px;font-size:13px;transition:all .12s;display:inline-flex}.share-btn:hover{background:var(--accent-pink);color:var(--bg);box-shadow:2px 2px 0 0 var(--accent-pink-shadow);transform:translate(2px,2px)}.share-btn.alt{border-color:var(--line-2);color:var(--ink);box-shadow:4px 4px #1a1a20}.share-btn.alt:hover{border-color:var(--ink);color:var(--ink);background:#ffffff0a;box-shadow:2px 2px #1a1a20}.share-btn .arrow{color:var(--accent-green)}.share-btn:hover .arrow{color:var(--bg)}.return-hook{border:1px solid var(--line-2);background:var(--bg-2);margin-top:64px;padding:40px 48px;position:relative}.return-hook:before,.return-hook:after{content:"";width:8px;height:8px;position:absolute}.return-hook:before{border-top:1px solid var(--accent-green);border-left:1px solid var(--accent-green);top:-1px;left:-1px}.return-hook:after{border-bottom:1px solid var(--accent-green);border-right:1px solid var(--accent-green);bottom:-1px;right:-1px}.return-hook .label{font-family:var(--font-mono);letter-spacing:.22em;text-transform:uppercase;color:var(--accent-green);margin-bottom:12px;font-size:11px}.return-hook h3{font-family:var(--font-display);letter-spacing:.11em;text-transform:lowercase;color:var(--ink);margin:0 0 16px;font-size:clamp(28px,3.6vw,40px);font-weight:400;line-height:1.1}.return-hook p{font-family:var(--font-mono);color:var(--ink-2);max-width:600px;margin:0 0 8px;font-size:13px;line-height:1.7}.return-actions{flex-wrap:wrap;align-items:center;gap:12px;margin-top:28px;display:flex}.return-status{border:1px solid var(--accent-pink);background:repeating-linear-gradient(0deg, #e4587d08 0 1px, transparent 1px 16px), repeating-linear-gradient(90deg, #e4587d08 0 1px, transparent 1px 16px), var(--bg-2);margin-top:24px;padding:18px 20px}.return-status .rs-row{font-family:var(--font-mono);color:var(--ink-2);align-items:center;gap:12px;margin:6px 0;font-size:13px;display:flex}.return-status .rs-row-primary{color:var(--ink);letter-spacing:.02em;font-size:15px}.return-status .rs-strong{color:var(--accent-pink)}.return-status .rs-email{color:var(--accent-green)}.rs-dot{flex-shrink:0;width:8px;height:8px;display:inline-block}.rs-dot-pink{background:var(--accent-pink);animation:1.6s ease-in-out infinite pulseDot;box-shadow:0 0 8px #e4587d8c}.rs-dot-green{background:var(--accent-green);box-shadow:0 0 6px #66d1b58c}.rs-clear{font-family:var(--font-mono);letter-spacing:.1em;color:var(--dim);cursor:pointer;text-underline-offset:3px;background:0 0;border:none;padding:4px 0;font-size:11px;text-decoration:underline;transition:color .12s}.rs-clear:hover:not(:disabled){color:var(--accent-pink)}.rs-clear:disabled{opacity:.5;cursor:not-allowed}.report-footer{border-top:1px solid var(--line);background:var(--bg);text-align:center;font-family:var(--font-mono);letter-spacing:.15em;text-transform:uppercase;color:var(--dim);padding:48px 32px 24px;font-size:11px}.report-footer--fixed{z-index:10;padding:16px 32px;position:fixed;bottom:0;left:0;right:0}.report-footer .brand-mark{color:var(--accent-pink);font-family:var(--font-mono);letter-spacing:-2px;margin-right:6px;font-size:14px;font-weight:700}.auth-dialog-backdrop{z-index:10000;-webkit-backdrop-filter:blur(6px);background:radial-gradient(1000px 700px at 30% 20%,#e4587d14 0%,#0000 60%),#08080ac7;place-items:center;padding:32px 16px;animation:.14s ease-out authFadeIn;display:grid;position:fixed;inset:0}@keyframes authFadeIn{0%{opacity:0}to{opacity:1}}.auth-dialog{border:1px solid var(--accent-pink);background:repeating-linear-gradient(0deg, #e4587d08 0 1px, transparent 1px 16px), repeating-linear-gradient(90deg, #e4587d08 0 1px, transparent 1px 16px), var(--bg-2);width:100%;max-width:460px;box-shadow:8px 8px 0 0 var(--accent-pink-shadow);font-family:var(--font-mono);color:var(--ink);padding:32px 32px 28px;animation:.16s ease-out authPop;position:relative}@keyframes authPop{0%{opacity:0;transform:translateY(8px)scale(.985)}to{opacity:1;transform:translateY(0)scale(1)}}.auth-dialog .corner{font-family:var(--font-mono);color:var(--accent-pink);opacity:.85;font-size:14px;line-height:1;position:absolute}.auth-dialog .corner.tl{top:6px;left:8px}.auth-dialog .corner.tr{top:6px;right:8px}.auth-dialog .corner.bl{bottom:6px;left:8px}.auth-dialog .corner.br{bottom:6px;right:8px}.auth-close{font-family:var(--font-mono);letter-spacing:.15em;text-transform:uppercase;color:var(--dim);cursor:pointer;background:0 0;border:none;padding:4px 6px;font-size:11px;transition:color .12s;position:absolute;top:12px;right:14px}.auth-close:hover{color:var(--accent-pink)}.auth-close:disabled{color:var(--line-2);cursor:not-allowed}.auth-label{font-family:var(--font-mono);letter-spacing:.22em;text-transform:uppercase;color:var(--accent-green);margin-bottom:14px;font-size:11px}.auth-headline{font-family:var(--font-display);letter-spacing:.09em;text-transform:lowercase;color:var(--ink);text-shadow:3px 3px 0 var(--accent-pink-shadow);text-wrap:balance;margin:0 0 12px;font-size:clamp(26px,3.6vw,34px);line-height:1.1}.auth-sub{font-family:var(--font-mono);color:var(--ink-2);margin:0 0 22px;font-size:13px;line-height:1.65}.auth-sub .auth-email{color:var(--accent-pink)}.auth-sub .auth-ok{color:var(--accent-green);margin-right:6px}.auth-form{flex-direction:column;gap:10px;display:flex}.auth-field-label{font-family:var(--font-mono);letter-spacing:.22em;text-transform:uppercase;color:var(--accent-green);font-size:10px}.auth-input{background:var(--bg);border:1px solid var(--line-2);width:100%;color:var(--ink);font-family:var(--font-mono);letter-spacing:.03em;outline:none;padding:11px 14px;font-size:14px;transition:border-color .12s,box-shadow .12s}.auth-input:focus{border-color:var(--accent-pink);box-shadow:0 0 0 1px var(--accent-pink-soft)}.auth-input:disabled{opacity:.55;cursor:not-allowed}.auth-input-code{letter-spacing:.5em;text-align:center;font-variant-numeric:tabular-nums;font-size:18px}.auth-input::placeholder{color:var(--dim)}.auth-error{font-family:var(--font-mono);color:var(--accent-pink);background:var(--accent-pink-bg);border:1px solid var(--accent-pink);letter-spacing:.02em;border-left-width:3px;margin-top:4px;padding:8px 12px;font-size:12px}.auth-actions{flex-wrap:wrap;gap:10px;margin-top:14px;display:flex}.auth-btn{font-family:var(--font-mono);letter-spacing:.06em;border:1px solid var(--line-2);color:var(--ink);cursor:pointer;background:0 0;align-items:center;gap:8px;padding:10px 16px;font-size:12px;transition:all .12s;display:inline-flex}.auth-btn:hover:not(:disabled){border-color:var(--ink);background:#ffffff0a}.auth-btn:disabled{opacity:.45;cursor:not-allowed}.auth-btn.primary{border-color:var(--accent-pink);color:var(--accent-pink);box-shadow:4px 4px 0 0 var(--accent-pink-shadow)}.auth-btn.primary:hover:not(:disabled){background:var(--accent-pink);color:var(--bg);box-shadow:2px 2px 0 0 var(--accent-pink-shadow);transform:translate(2px,2px)}.auth-back{font-family:var(--font-mono);letter-spacing:.1em;color:var(--dim);cursor:pointer;background:0 0;border:none;align-self:flex-start;margin-top:4px;padding:6px 0;font-size:11px;transition:color .12s}.auth-back:hover:not(:disabled){color:var(--ink-2)}.auth-back:disabled{opacity:.45;cursor:not-allowed}@media (max-width:520px){.auth-dialog{padding:26px 22px 22px}.auth-actions{flex-direction:column;align-items:stretch}.auth-btn{justify-content:center}}.auth-status-pill{border:1px dashed var(--line-2);font-family:var(--font-mono);letter-spacing:.1em;color:var(--ink-2);align-items:center;gap:8px;margin-top:16px;padding:6px 10px;font-size:11px;display:inline-flex}.auth-status-pill .dot{background:var(--accent-green);width:7px;height:7px;display:inline-block;box-shadow:0 0 6px #66d1b58c}.auth-status-pill .email{color:var(--accent-green)}@media (max-width:960px){.report{padding:0 20px}.archetype-frame{padding:32px 24px}.arch-body{grid-template-columns:1fr;gap:32px}.arch-meta-grid,.score-grid{grid-template-columns:1fr;gap:16px}.finding-body{grid-template-columns:1fr}.finding-block{border-right:none!important}.policies-grid,.share-grid{grid-template-columns:1fr}.strength-row{grid-template-columns:40px 1fr}.strength-metric{text-align:left;grid-column:2;margin-top:6px}.return-hook{padding:28px 24px}}@media (prefers-reduced-motion:reduce){.running-cursor,.running-stage-spin,.running-bar-fill:after,.auth-status-pill .dot{animation:none}.running-bar-fill{transition:none}}.share-dock{z-index:40;background:var(--bg-2);border:1px solid var(--line-2);width:300px;box-shadow:8px 8px 0 0 var(--accent-pink-shadow), 16px 16px 0 0 #00000080;animation:.32s cubic-bezier(.22,1,.36,1) share-dock-in;position:fixed;bottom:clamp(16px,2.5vw,32px);right:clamp(16px,2.5vw,32px)}.share-dock:before,.share-dock:after{content:"";width:10px;height:10px;position:absolute}.share-dock:before{border-top:1px solid var(--accent-pink);border-left:1px solid var(--accent-pink);top:-1px;left:-1px}.share-dock:after{border-bottom:1px solid var(--accent-pink);border-right:1px solid var(--accent-pink);bottom:-1px;right:-1px}@keyframes share-dock-in{0%{opacity:0;transform:translate(8px,8px)}to{opacity:1;transform:translate(0)}}.share-dock-head{border-bottom:1px dashed var(--line);justify-content:space-between;align-items:center;padding:12px 16px;display:flex}.share-dock-eyebrow{font-family:var(--font-mono);letter-spacing:.22em;text-transform:uppercase;color:var(--accent-green);font-size:10px}.share-dock-eyebrow>span{color:var(--accent-pink);letter-spacing:-2px;margin-right:8px}.share-dock-caret{border:1px solid var(--line-2);width:24px;height:24px;color:var(--ink-2);font-family:var(--font-mono);cursor:pointer;background:0 0;place-items:center;font-size:11px;transition:color .14s cubic-bezier(.22,1,.36,1),border-color .14s cubic-bezier(.22,1,.36,1);display:grid}.share-dock-caret:hover{color:var(--accent-pink);border-color:var(--accent-pink)}.share-dock-stack{flex-direction:column;gap:8px;padding:14px 14px 10px;display:flex}.share-dock-stack .share-btn{width:100%}.share-dock-foot{border-top:1px dashed var(--line);font-family:var(--font-mono);letter-spacing:.18em;text-transform:uppercase;color:var(--dim);text-align:center;padding:10px 16px 12px;font-size:10px}.share-dock-foot>span{color:var(--accent-pink);margin-right:6px}.share-dock-fab{z-index:40;background:var(--accent-pink);width:56px;height:56px;color:var(--bg);border:1px solid var(--accent-pink);box-shadow:6px 6px 0 0 var(--accent-pink-shadow);font-family:var(--font-mono);cursor:pointer;place-items:center;font-size:22px;font-weight:700;transition:transform .16s cubic-bezier(.22,1,.36,1),box-shadow .16s cubic-bezier(.22,1,.36,1);animation:.32s cubic-bezier(.22,1,.36,1) share-dock-in;display:grid;position:fixed;bottom:clamp(16px,2.5vw,32px);right:clamp(16px,2.5vw,32px)}.share-dock-fab:hover{box-shadow:9px 9px 0 0 var(--accent-pink-shadow);transform:translate(-2px,-2px)}.share-dock-fab:active{box-shadow:0 0 0 0 var(--accent-pink-shadow);transform:translate(2px,2px)}@media (max-width:760px){.share-dock,.share-dock-fab{display:none}}@media (prefers-reduced-motion:reduce){.share-dock,.share-dock-fab{animation:none}.share-dock-fab,.share-dock-caret{transition:none}}.audit-progress-strip{z-index:60;background:var(--bg-2);border-bottom:1px solid var(--accent-pink);box-shadow:0 4px 0 0 var(--accent-pink-shadow);font-family:var(--font-mono);animation:.22s cubic-bezier(.22,1,.36,1) audit-progress-slide-in;position:sticky;top:0;left:0;right:0}.audit-progress-strip--failed{border-bottom-color:var(--accent-pink);background:linear-gradient(to right, var(--accent-pink-bg), var(--bg-2))}.audit-progress-strip__inner{justify-content:space-between;align-items:center;gap:16px;max-width:1480px;margin:0 auto;padding:12px clamp(20px,3vw,48px);display:flex;position:relative}.audit-progress-strip__label{color:var(--ink);letter-spacing:.06em;text-transform:lowercase;align-items:center;gap:10px;font-size:12px;display:inline-flex}.audit-progress-strip--failed .audit-progress-strip__label{color:var(--accent-pink)}.audit-progress-strip__elapsed{font-variant-numeric:tabular-nums;color:var(--accent-pink);letter-spacing:.08em;font-size:12px}.audit-progress-strip__spinner{border:1.5px solid var(--accent-pink);background:0 0;border-top-color:#0000;border-radius:50%;width:9px;height:9px;animation:.8s linear infinite audit-progress-spin}.audit-progress-strip__x{border:1px solid var(--accent-pink);width:14px;height:14px;color:var(--accent-pink);justify-content:center;align-items:center;font-size:11px;line-height:1;display:inline-flex}.audit-progress-strip__dismiss{border:1px solid var(--line-2);color:var(--ink-2);font-family:var(--font-mono);text-transform:lowercase;letter-spacing:.06em;cursor:pointer;background:0 0;padding:5px 10px;font-size:11px;transition:border-color .14s,color .14s}.audit-progress-strip__dismiss:hover{border-color:var(--accent-pink);color:var(--accent-pink)}.audit-progress-strip__pulse{background:linear-gradient(90deg, transparent 0%, var(--accent-pink) 20%, var(--accent-pink) 80%, transparent 100%);transform-origin:0;height:1px;animation:2.4s cubic-bezier(.55,.1,.45,.9) infinite audit-progress-pulse;position:absolute;bottom:-1px;left:0;right:0}@keyframes audit-progress-spin{to{transform:rotate(360deg)}}@keyframes audit-progress-pulse{0%{opacity:.4;transform:scaleX(0)translate(0%)}50%{opacity:1;transform:scaleX(.6)translate(20%)}to{opacity:.2;transform:scaleX(0)translate(100%)}}@keyframes audit-progress-slide-in{0%{opacity:0;transform:translateY(-100%)}to{opacity:1;transform:translateY(0)}}@media (prefers-reduced-motion:reduce){.audit-progress-strip{animation:none}.audit-progress-strip__spinner{border-top-color:var(--accent-pink);animation:none}.audit-progress-strip__pulse{opacity:.4;animation:none;transform:scaleX(.4)translate(30%)}}
|
|
@@ -1,135 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Section 04 — FINDINGS. "your agent has some quirks."
|
|
5
|
-
*
|
|
6
|
-
* Per-finding cards with four blocks: what happened / what this costs /
|
|
7
|
-
* evidence sample / the fix. Data sourced from `src/audit/findings.ts`.
|
|
8
|
-
*/
|
|
9
|
-
import React, { useState } from "react";
|
|
10
|
-
import type { FindingCard } from "@/src/audit/findings";
|
|
11
|
-
import { usePostHog } from "@/contexts/PostHogContext";
|
|
12
|
-
|
|
13
|
-
interface Props {
|
|
14
|
-
findings: FindingCard[];
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export function FindingsSection({ findings }: Props) {
|
|
18
|
-
if (findings.length === 0) return null;
|
|
19
|
-
|
|
20
|
-
return (
|
|
21
|
-
<section className="section" data-screen-label="04 Findings">
|
|
22
|
-
<div className="section-mast">
|
|
23
|
-
<div className="section-label">
|
|
24
|
-
<span className="glyph">━━</span> findings{" "}
|
|
25
|
-
<span style={{ color: "var(--dim)" }}>·</span> ranked by impact
|
|
26
|
-
</div>
|
|
27
|
-
<div className="section-meta">
|
|
28
|
-
<span className="p">●</span> {findings.length} detector{findings.length === 1 ? "" : "s"} triggered
|
|
29
|
-
</div>
|
|
30
|
-
</div>
|
|
31
|
-
<h2 className="section-h">your agent has some quirks.</h2>
|
|
32
|
-
|
|
33
|
-
<div className="findings-list">
|
|
34
|
-
{findings.map((f) => <Finding key={f.sourceSlug} f={f} />)}
|
|
35
|
-
</div>
|
|
36
|
-
</section>
|
|
37
|
-
);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
function Finding({ f }: { f: FindingCard }) {
|
|
41
|
-
const { capture } = usePostHog();
|
|
42
|
-
const [copied, setCopied] = useState(false);
|
|
43
|
-
|
|
44
|
-
const handleCopy = async (e: React.MouseEvent) => {
|
|
45
|
-
e.stopPropagation();
|
|
46
|
-
try {
|
|
47
|
-
await navigator.clipboard.writeText(f.fix.install);
|
|
48
|
-
setCopied(true);
|
|
49
|
-
capture("audit_copy_clicked", {
|
|
50
|
-
source: "findings_section",
|
|
51
|
-
item_type: "single_policy_install_command",
|
|
52
|
-
policy_name: f.fix.slug,
|
|
53
|
-
finding_slug: f.sourceSlug,
|
|
54
|
-
});
|
|
55
|
-
setTimeout(() => setCopied(false), 1500);
|
|
56
|
-
} catch { /* ignore */ }
|
|
57
|
-
};
|
|
58
|
-
|
|
59
|
-
return (
|
|
60
|
-
<article className="finding">
|
|
61
|
-
<header className="finding-head">
|
|
62
|
-
<div className="finding-num">№{f.num}</div>
|
|
63
|
-
<div className="finding-title">{f.title}</div>
|
|
64
|
-
<div className="finding-count">
|
|
65
|
-
{f.count}×
|
|
66
|
-
<span className="label">occurrences</span>
|
|
67
|
-
</div>
|
|
68
|
-
</header>
|
|
69
|
-
<div className="finding-meta">
|
|
70
|
-
<span>
|
|
71
|
-
<span style={{ color: "var(--dim)" }}>policy</span>{" "}
|
|
72
|
-
<span className="policy">{f.policy}</span>
|
|
73
|
-
</span>
|
|
74
|
-
<span className="sep">·</span>
|
|
75
|
-
<span>{f.projects} {f.projects === 1 ? "project" : "projects"}</span>
|
|
76
|
-
<span className="sep">·</span>
|
|
77
|
-
<span>last seen {f.lastSeen}</span>
|
|
78
|
-
{f.alreadyEnabled && (
|
|
79
|
-
<>
|
|
80
|
-
<span className="sep">·</span>
|
|
81
|
-
<span style={{ color: "var(--accent-green)" }}>enforced</span>
|
|
82
|
-
</>
|
|
83
|
-
)}
|
|
84
|
-
</div>
|
|
85
|
-
<div className="finding-body">
|
|
86
|
-
<div className="finding-block">
|
|
87
|
-
<div className="fb-label">what happened</div>
|
|
88
|
-
<div className="fb-body">{f.body}</div>
|
|
89
|
-
</div>
|
|
90
|
-
<div className="finding-block">
|
|
91
|
-
<div className="fb-label cost">what this costs</div>
|
|
92
|
-
<div className="fb-body">{f.cost}</div>
|
|
93
|
-
</div>
|
|
94
|
-
<div className="finding-block">
|
|
95
|
-
<div className="fb-label">evidence · sample</div>
|
|
96
|
-
<div className="fb-evidence">
|
|
97
|
-
{f.evidence.map((e, i) => {
|
|
98
|
-
if (e.kind === "comment") {
|
|
99
|
-
return <div key={i} className="comment">{e.text}</div>;
|
|
100
|
-
}
|
|
101
|
-
if (e.kind === "err") {
|
|
102
|
-
return <div key={i} className="err">{e.text}</div>;
|
|
103
|
-
}
|
|
104
|
-
return (
|
|
105
|
-
<div key={i}>
|
|
106
|
-
<span className="arrow">→ </span>
|
|
107
|
-
<span>{e.text}</span>
|
|
108
|
-
</div>
|
|
109
|
-
);
|
|
110
|
-
})}
|
|
111
|
-
</div>
|
|
112
|
-
</div>
|
|
113
|
-
<div className="finding-block">
|
|
114
|
-
<div className="fb-label fix">the fix</div>
|
|
115
|
-
<div className="fb-fix">
|
|
116
|
-
<span className="slug">{f.fix.slug}</span>
|
|
117
|
-
<div style={{ color: "var(--ink-2)" }}>{f.fix.desc}</div>
|
|
118
|
-
{f.fix.alsoCoveredBy && (
|
|
119
|
-
<div style={{ color: "var(--dim)", fontSize: 11, marginTop: 4 }}>
|
|
120
|
-
also covered by{" "}
|
|
121
|
-
<span style={{ color: "var(--accent-green)" }}>{f.fix.alsoCoveredBy}</span>
|
|
122
|
-
</div>
|
|
123
|
-
)}
|
|
124
|
-
<code className="cmd" onClick={handleCopy} style={{ cursor: "pointer" }}>
|
|
125
|
-
<span className="prompt">$</span>{f.fix.install}{" "}
|
|
126
|
-
<span style={{ color: "var(--dim)", marginLeft: 8, fontSize: 10, letterSpacing: "0.15em", textTransform: "uppercase" }}>
|
|
127
|
-
{copied ? "copied" : "click to copy"}
|
|
128
|
-
</span>
|
|
129
|
-
</code>
|
|
130
|
-
</div>
|
|
131
|
-
</div>
|
|
132
|
-
</div>
|
|
133
|
-
</article>
|
|
134
|
-
);
|
|
135
|
-
}
|
|
@@ -1,126 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Section 01 — IDENTITY. The hero. Big archetype name with hard-offset
|
|
5
|
-
* stamp shadow, sigil to the right, keywords strip, "common in / primary
|
|
6
|
-
* risk" meta grid, and the closing one-liner.
|
|
7
|
-
*
|
|
8
|
-
* Layout uses the ported `.archetype-frame` / `.arch-mast` / `.arch-body`
|
|
9
|
-
* classes from audit-styles.css. Data sources from `src/audit/archetypes.ts`.
|
|
10
|
-
*
|
|
11
|
-
* The variant copy (tagline / keywords / common / risk / closing) is
|
|
12
|
-
* picked deterministically from a multi-variant catalog using the `seed`
|
|
13
|
-
* prop — typically the inferred project name. Same seed → same persona
|
|
14
|
-
* blurb across renders; different seeds → different copy. So two users
|
|
15
|
-
* who both land on "the optimist" see different language for it.
|
|
16
|
-
*
|
|
17
|
-
* Exposes a `frameRef` forwarded onto the `.archetype-frame` element so
|
|
18
|
-
* the ShowOff "make poster" action can capture it via html2canvas.
|
|
19
|
-
*/
|
|
20
|
-
import React, { forwardRef, useMemo } from "react";
|
|
21
|
-
import { ARCHETYPES, pickArchetypeVariant, type ArchetypeKey } from "@/src/audit/archetypes";
|
|
22
|
-
import { type Grade } from "@/src/audit/scoring";
|
|
23
|
-
import { Sigil } from "./sigil";
|
|
24
|
-
|
|
25
|
-
interface Props {
|
|
26
|
-
archetypeKey: ArchetypeKey;
|
|
27
|
-
secondaryKey: ArchetypeKey;
|
|
28
|
-
toolCalls: number;
|
|
29
|
-
sessions: number;
|
|
30
|
-
/** "30d", "7d", etc. shown in the target line; "all time" otherwise. */
|
|
31
|
-
window: string;
|
|
32
|
-
/** Stable seed for variant selection (project name is the natural fit). */
|
|
33
|
-
seed: string;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export const IdentitySection = forwardRef<HTMLDivElement, Props>(function IdentitySection(
|
|
37
|
-
{ archetypeKey, secondaryKey, toolCalls, sessions, window, seed }: Props,
|
|
38
|
-
frameRef,
|
|
39
|
-
) {
|
|
40
|
-
// `pickArchetypeVariant` re-hashes the seed string via djb2 + 4 mix
|
|
41
|
-
// passes per axis. Deterministic over (archetypeKey, seed) so memoize.
|
|
42
|
-
const archetype = useMemo(
|
|
43
|
-
() => pickArchetypeVariant(archetypeKey, seed),
|
|
44
|
-
[archetypeKey, seed],
|
|
45
|
-
);
|
|
46
|
-
const secondary = secondaryKey !== archetypeKey ? ARCHETYPES[secondaryKey] : null;
|
|
47
|
-
|
|
48
|
-
return (
|
|
49
|
-
<section className="identity" data-screen-label="01 Identity">
|
|
50
|
-
<div className="archetype-frame" ref={frameRef}>
|
|
51
|
-
<span className="corner tl">┌ identity</span>
|
|
52
|
-
<span className="corner tr">v1.0 ┐</span>
|
|
53
|
-
<span className="corner bl">└ № {archetype.index} / 08</span>
|
|
54
|
-
<span className="corner br">archetype ┘</span>
|
|
55
|
-
|
|
56
|
-
<div className="arch-mast">
|
|
57
|
-
<div className="arch-mast-left">
|
|
58
|
-
<div className="arch-eyebrow">
|
|
59
|
-
━━ identity <span className="ix">·</span> your agent's archetype
|
|
60
|
-
</div>
|
|
61
|
-
<div className="arch-target">
|
|
62
|
-
detected from{" "}
|
|
63
|
-
<span style={{ color: "var(--ink)" }}>{toolCalls.toLocaleString()}</span>
|
|
64
|
-
{" "}tool calls
|
|
65
|
-
<span className="slash">/</span>
|
|
66
|
-
<span style={{ color: "var(--ink)" }}>{sessions}</span>
|
|
67
|
-
{" "}sessions
|
|
68
|
-
<span className="slash">/</span>
|
|
69
|
-
<span style={{ color: "var(--ink)" }}>{window}</span>
|
|
70
|
-
<span className="live">
|
|
71
|
-
<span className="dot-live"></span>live
|
|
72
|
-
</span>
|
|
73
|
-
</div>
|
|
74
|
-
</div>
|
|
75
|
-
<div className="arch-counter">
|
|
76
|
-
<div>
|
|
77
|
-
№ {archetype.index}<span className="of"> of 08</span>
|
|
78
|
-
</div>
|
|
79
|
-
<div style={{ color: "var(--ink-2)", marginTop: 4 }}>archetype</div>
|
|
80
|
-
</div>
|
|
81
|
-
</div>
|
|
82
|
-
|
|
83
|
-
<div className="arch-body">
|
|
84
|
-
<div>
|
|
85
|
-
<h1 className="arch-name">{archetype.name}</h1>
|
|
86
|
-
<p className="arch-tagline">{archetype.tagline}</p>
|
|
87
|
-
|
|
88
|
-
{secondary && (
|
|
89
|
-
<div className="arch-secondary">
|
|
90
|
-
<span className="with">with</span>
|
|
91
|
-
<span className="name">{secondary.name.replace("the ", "")}</span>
|
|
92
|
-
<span className="with">tendencies</span>
|
|
93
|
-
</div>
|
|
94
|
-
)}
|
|
95
|
-
|
|
96
|
-
<div className="arch-keywords">
|
|
97
|
-
{archetype.keywords.map((k, i) => (
|
|
98
|
-
<React.Fragment key={k}>
|
|
99
|
-
<span className="kw">{k}</span>
|
|
100
|
-
{i < archetype.keywords.length - 1 && (
|
|
101
|
-
<span className="kw-sep">·</span>
|
|
102
|
-
)}
|
|
103
|
-
</React.Fragment>
|
|
104
|
-
))}
|
|
105
|
-
</div>
|
|
106
|
-
|
|
107
|
-
<div className="arch-meta-grid">
|
|
108
|
-
<div className="arch-meta-item">
|
|
109
|
-
<span className="label">common in</span>
|
|
110
|
-
<span className="body">{archetype.common}</span>
|
|
111
|
-
</div>
|
|
112
|
-
<div className="arch-meta-item">
|
|
113
|
-
<span className="label p">primary risk</span>
|
|
114
|
-
<span className="body">{archetype.risk}</span>
|
|
115
|
-
</div>
|
|
116
|
-
</div>
|
|
117
|
-
|
|
118
|
-
<div className="arch-closing">— {archetype.closing}</div>
|
|
119
|
-
</div>
|
|
120
|
-
|
|
121
|
-
<Sigil archetypeKey={archetypeKey} />
|
|
122
|
-
</div>
|
|
123
|
-
</div>
|
|
124
|
-
</section>
|
|
125
|
-
);
|
|
126
|
-
});
|
|
@@ -1,194 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Section 05 — PRESCRIBED POLICIES. "enable these. close the gap."
|
|
5
|
-
*
|
|
6
|
-
* Grid of unenabled-builtin cards with install commands + projected
|
|
7
|
-
* score uplift callout.
|
|
8
|
-
*
|
|
9
|
-
* Sources two layers of "hits":
|
|
10
|
-
* 1. Unenabled builtin policies that fired on their own
|
|
11
|
-
* 2. Audit detectors → mapped via DETECTOR_TO_POLICY in findings.ts.
|
|
12
|
-
* The detector's hits get attributed to its primary policy so the
|
|
13
|
-
* report frames everything as failproofai-coverable.
|
|
14
|
-
*
|
|
15
|
-
* Same policy can collect hits from multiple sources; we sum them and
|
|
16
|
-
* render one card per policy.
|
|
17
|
-
*/
|
|
18
|
-
import React, { useMemo, useState } from "react";
|
|
19
|
-
import type { AuditResult } from "@/src/audit/types";
|
|
20
|
-
import { type Grade, tierName } from "@/src/audit/scoring";
|
|
21
|
-
import { usePostHog } from "@/contexts/PostHogContext";
|
|
22
|
-
|
|
23
|
-
interface Props {
|
|
24
|
-
result: AuditResult;
|
|
25
|
-
projected: number;
|
|
26
|
-
projectedGrade: Grade;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
// Mirror of DETECTOR_TO_POLICY in findings.ts. Could re-export but keep
|
|
30
|
-
// the dependency tree shallow — both modules are stable.
|
|
31
|
-
const DETECTOR_TO_PRIMARY_POLICY: Record<string, string> = {
|
|
32
|
-
"redundant-cd-cwd": "warn-repeated-tool-calls",
|
|
33
|
-
"prefer-edit-over-read-cat": "block-read-outside-cwd",
|
|
34
|
-
"prefer-edit-over-sed-awk": "warn-repeated-tool-calls",
|
|
35
|
-
"prefer-write-over-heredoc": "block-env-files",
|
|
36
|
-
"sleep-polling-loop": "warn-background-process",
|
|
37
|
-
"find-from-root": "block-read-outside-cwd",
|
|
38
|
-
"git-commit-no-verify": "warn-git-amend",
|
|
39
|
-
"reread-after-edit": "warn-repeated-tool-calls",
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
const POLICY_DESC: Record<string, string> = {
|
|
43
|
-
"warn-repeated-tool-calls": "warns when the same tool is called 3+ times with identical parameters — catches the loops before they spiral.",
|
|
44
|
-
"block-read-outside-cwd": "denies any file read whose absolute path falls outside the project root, including symlinks.",
|
|
45
|
-
"block-env-files": "blocks reads and writes of `.env` files at the tool layer.",
|
|
46
|
-
"block-secrets-write": "blocks writes to .pem, id_rsa, credentials.json, and other secret-key files.",
|
|
47
|
-
"warn-background-process": "warns before starting nohup / & / screen / tmux / disown processes that get forgotten about.",
|
|
48
|
-
"warn-git-amend": "warns before amending git commits — dangerous-commit-flag class.",
|
|
49
|
-
"require-ci-green-before-stop": "requires CI checks to pass on HEAD before the agent declares the task done.",
|
|
50
|
-
};
|
|
51
|
-
|
|
52
|
-
function shortName(name: string): string {
|
|
53
|
-
const slash = name.indexOf("/");
|
|
54
|
-
return slash >= 0 ? name.slice(slash + 1) : name;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
interface PolicyCard {
|
|
58
|
-
name: string; // short slug
|
|
59
|
-
desc: string; // displayTitle (low-res) or impact
|
|
60
|
-
catches: string; // "would have caught X occurrences..." copy
|
|
61
|
-
hits: number;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
function buildPolicyCards(result: AuditResult): PolicyCard[] {
|
|
65
|
-
const enabledSet = new Set(result.enabledBuiltinNames ?? []);
|
|
66
|
-
// policyName → aggregated counts
|
|
67
|
-
const buckets = new Map<string, { hits: number; projects: number; sources: Set<string> }>();
|
|
68
|
-
|
|
69
|
-
for (const row of result.results) {
|
|
70
|
-
if (row.hits === 0) continue;
|
|
71
|
-
|
|
72
|
-
let target: string;
|
|
73
|
-
let isFromDetector = false;
|
|
74
|
-
if (row.source === "audit-detector") {
|
|
75
|
-
const mapped = DETECTOR_TO_PRIMARY_POLICY[shortName(row.name)];
|
|
76
|
-
if (!mapped) continue;
|
|
77
|
-
target = mapped;
|
|
78
|
-
isFromDetector = true;
|
|
79
|
-
} else if (row.source === "builtin" && !row.enabledInConfig) {
|
|
80
|
-
target = shortName(row.name);
|
|
81
|
-
} else {
|
|
82
|
-
continue; // already-enabled builtins don't need to be prescribed
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
// Skip if the target policy is already in the user's enabled set
|
|
86
|
-
// (detector hits would land there in production already).
|
|
87
|
-
if (enabledSet.has(target)) continue;
|
|
88
|
-
|
|
89
|
-
const bucket = buckets.get(target) ?? { hits: 0, projects: 0, sources: new Set() };
|
|
90
|
-
bucket.hits += row.hits;
|
|
91
|
-
bucket.projects = Math.max(bucket.projects, row.projects);
|
|
92
|
-
bucket.sources.add(isFromDetector ? shortName(row.name) : "self");
|
|
93
|
-
buckets.set(target, bucket);
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
return [...buckets.entries()]
|
|
97
|
-
.sort((a, b) => b[1].hits - a[1].hits)
|
|
98
|
-
.map(([name, b]) => {
|
|
99
|
-
const viaList = [...b.sources].filter((s) => s !== "self");
|
|
100
|
-
const viaCopy = viaList.length > 0
|
|
101
|
-
? ` (via ${viaList.join(", ")})`
|
|
102
|
-
: "";
|
|
103
|
-
const catches = `would have caught ${b.hits} occurrence${b.hits === 1 ? "" : "s"} across ${b.projects} project${b.projects === 1 ? "" : "s"}${viaCopy}.`;
|
|
104
|
-
return {
|
|
105
|
-
name,
|
|
106
|
-
desc: POLICY_DESC[name] ?? "enable this builtin policy to close the gap.",
|
|
107
|
-
catches,
|
|
108
|
-
hits: b.hits,
|
|
109
|
-
};
|
|
110
|
-
});
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
export function PoliciesSection({ result, projected, projectedGrade }: Props) {
|
|
114
|
-
// Builds a Map+Set aggregation + sort over result.results — non-trivial.
|
|
115
|
-
// Memoize so unrelated parent re-renders don't recompute every frame.
|
|
116
|
-
const policies = useMemo(() => buildPolicyCards(result), [result]);
|
|
117
|
-
|
|
118
|
-
if (policies.length === 0) return null;
|
|
119
|
-
|
|
120
|
-
return (
|
|
121
|
-
<section className="section" data-screen-label="05 Policies">
|
|
122
|
-
<div className="section-mast">
|
|
123
|
-
<div className="section-label">
|
|
124
|
-
<span className="glyph">━━</span> policies{" "}
|
|
125
|
-
<span style={{ color: "var(--dim)" }}>·</span> prescribed
|
|
126
|
-
</div>
|
|
127
|
-
<div className="section-meta">
|
|
128
|
-
{policies.length} polic{policies.length === 1 ? "y" : "ies"}{" "}
|
|
129
|
-
<span style={{ color: "var(--dim)" }}>·</span>{" "}
|
|
130
|
-
<span className="g">covers your slipping-through hits</span>
|
|
131
|
-
</div>
|
|
132
|
-
</div>
|
|
133
|
-
<h2 className="section-h">enable these. close the gap.</h2>
|
|
134
|
-
|
|
135
|
-
<div className="policy-callout">
|
|
136
|
-
<span>
|
|
137
|
-
enable all {policies.length === 1 ? "one" : policies.length}
|
|
138
|
-
</span>
|
|
139
|
-
<span className="arrow">→</span>
|
|
140
|
-
<span>projected score</span>
|
|
141
|
-
<span className="new-score">{projected}</span>
|
|
142
|
-
<span style={{ color: "var(--dim)" }}>·</span>
|
|
143
|
-
<span className="new-tier">{tierName(projectedGrade)}</span>
|
|
144
|
-
</div>
|
|
145
|
-
|
|
146
|
-
<div className="policies-grid">
|
|
147
|
-
{policies.map((p, i) => (
|
|
148
|
-
<PolicyTile key={p.name} policy={p} idx={i} />
|
|
149
|
-
))}
|
|
150
|
-
</div>
|
|
151
|
-
</section>
|
|
152
|
-
);
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
function PolicyTile({ policy, idx }: { policy: PolicyCard; idx: number }) {
|
|
156
|
-
const { capture } = usePostHog();
|
|
157
|
-
const [copied, setCopied] = useState(false);
|
|
158
|
-
const install = `failproof policy add ${policy.name}`;
|
|
159
|
-
|
|
160
|
-
const handleCopy = async (e: React.MouseEvent) => {
|
|
161
|
-
e.stopPropagation();
|
|
162
|
-
try {
|
|
163
|
-
await navigator.clipboard.writeText(install);
|
|
164
|
-
setCopied(true);
|
|
165
|
-
capture("audit_copy_clicked", {
|
|
166
|
-
source: "policies_section",
|
|
167
|
-
item_type: "single_policy_install_command",
|
|
168
|
-
policy_name: policy.name,
|
|
169
|
-
policy_rank: idx + 1,
|
|
170
|
-
});
|
|
171
|
-
setTimeout(() => setCopied(false), 1500);
|
|
172
|
-
} catch { /* ignore */ }
|
|
173
|
-
};
|
|
174
|
-
|
|
175
|
-
return (
|
|
176
|
-
<article className="policy-card">
|
|
177
|
-
<div className="head">
|
|
178
|
-
<div className="policy-name">{policy.name}</div>
|
|
179
|
-
<div className="policy-slug">№{String(idx + 1).padStart(2, "0")}</div>
|
|
180
|
-
</div>
|
|
181
|
-
<div className="policy-desc">{policy.desc}</div>
|
|
182
|
-
<div className="policy-impact">
|
|
183
|
-
<span className="check">✓</span>{policy.catches}
|
|
184
|
-
</div>
|
|
185
|
-
<div className="policy-install">
|
|
186
|
-
<span className="prompt">$</span>
|
|
187
|
-
<span>{install}</span>
|
|
188
|
-
<span className="copy" onClick={handleCopy}>
|
|
189
|
-
{copied ? "copied" : "copy"}
|
|
190
|
-
</span>
|
|
191
|
-
</div>
|
|
192
|
-
</article>
|
|
193
|
-
);
|
|
194
|
-
}
|