@tokenoftrust/storefront-runner 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +58 -0
- package/README.md +40 -0
- package/apps/storefront/.dev.vars.example +41 -0
- package/apps/storefront/.env.example +24 -0
- package/apps/storefront/astro.config.mjs +245 -0
- package/apps/storefront/env.d.ts +155 -0
- package/apps/storefront/lib/ensure-preview-reconcile-secret.sh +31 -0
- package/apps/storefront/lib/resolve-cf-token.sh +48 -0
- package/apps/storefront/lib/resolve-tot-credentials.sh +69 -0
- package/apps/storefront/migrations/0000_baseline.sql +54 -0
- package/apps/storefront/migrations/0001_products_fts.sql +9 -0
- package/apps/storefront/migrations/README.md +54 -0
- package/apps/storefront/migrations/meta/0000_snapshot.json +347 -0
- package/apps/storefront/migrations/meta/0001_snapshot.json +347 -0
- package/apps/storefront/migrations/meta/_journal.json +20 -0
- package/apps/storefront/package.json +41 -0
- package/apps/storefront/public/brand/northwind-logo-dark.svg +4 -0
- package/apps/storefront/public/brand/northwind-logo-light.svg +4 -0
- package/apps/storefront/public/brand/northwind-og.svg +13 -0
- package/apps/storefront/public/favicon.svg +5 -0
- package/apps/storefront/public/js/dashboard-team.js +147 -0
- package/apps/storefront/public/js/dashboard-vendor-search.js +115 -0
- package/apps/storefront/src/components/Badge.astro +34 -0
- package/apps/storefront/src/components/Breadcrumbs.astro +45 -0
- package/apps/storefront/src/components/CollectionCard.astro +56 -0
- package/apps/storefront/src/components/EmptyState.astro +35 -0
- package/apps/storefront/src/components/Img.astro +68 -0
- package/apps/storefront/src/components/ProductCard.astro +228 -0
- package/apps/storefront/src/components/Section.astro +39 -0
- package/apps/storefront/src/components/Seo.astro +70 -0
- package/apps/storefront/src/components/WidgetFrame.astro +34 -0
- package/apps/storefront/src/components/auth/AuthBadge.astro +44 -0
- package/apps/storefront/src/components/chrome/AnnouncementBar.astro +108 -0
- package/apps/storefront/src/components/chrome/MegaMenu.astro +26 -0
- package/apps/storefront/src/components/chrome/NavDropdown.astro +116 -0
- package/apps/storefront/src/components/chrome/SiteFooter.astro +181 -0
- package/apps/storefront/src/components/chrome/SiteHeader.astro +181 -0
- package/apps/storefront/src/components/chrome/UtilityNav.astro +79 -0
- package/apps/storefront/src/components/commerce/FoxyLoader.astro +23 -0
- package/apps/storefront/src/components/commerce/PriceDisplay.astro +91 -0
- package/apps/storefront/src/components/commerce/ProductCarousel.astro +197 -0
- package/apps/storefront/src/components/commerce/ProductGrid.astro +75 -0
- package/apps/storefront/src/components/commerce/RatingStars.astro +58 -0
- package/apps/storefront/src/components/compliance/NicotineWarning.astro +33 -0
- package/apps/storefront/src/components/home/Hero.astro +164 -0
- package/apps/storefront/src/components/islands/AgeGate.tsx +105 -0
- package/apps/storefront/src/components/islands/ImageGallery.tsx +237 -0
- package/apps/storefront/src/components/islands/IsolatedAgeGate.tsx +73 -0
- package/apps/storefront/src/components/islands/MobileNav.tsx +239 -0
- package/apps/storefront/src/components/islands/QuickView.tsx +138 -0
- package/apps/storefront/src/components/islands/RecentlyViewed.tsx +122 -0
- package/apps/storefront/src/components/islands/SavedList.tsx +99 -0
- package/apps/storefront/src/components/islands/SearchTypeahead.tsx +248 -0
- package/apps/storefront/src/components/islands/VariantSelector.tsx +378 -0
- package/apps/storefront/src/components/marketing/CardGrid.astro +72 -0
- package/apps/storefront/src/components/marketing/CodeSample.astro +20 -0
- package/apps/storefront/src/components/marketing/CtaBand.astro +24 -0
- package/apps/storefront/src/components/marketing/Faq.astro +37 -0
- package/apps/storefront/src/components/marketing/Integrations.astro +63 -0
- package/apps/storefront/src/components/marketing/MarketingBlocks.astro +53 -0
- package/apps/storefront/src/components/marketing/MarketingCtas.astro +48 -0
- package/apps/storefront/src/components/marketing/MarketingHero.astro +72 -0
- package/apps/storefront/src/components/marketing/ProofStrip.astro +37 -0
- package/apps/storefront/src/components/marketing/SplitCompare.astro +53 -0
- package/apps/storefront/src/components/marketing/Steps.astro +36 -0
- package/apps/storefront/src/components/marketing/Testimonials.astro +38 -0
- package/apps/storefront/src/components/marketing/TrustBar.astro +22 -0
- package/apps/storefront/src/components/nav/Footer.astro +148 -0
- package/apps/storefront/src/components/nav/Header.astro +190 -0
- package/apps/storefront/src/components/plp/ActiveFilters.astro +79 -0
- package/apps/storefront/src/components/plp/FacetSidebar.astro +146 -0
- package/apps/storefront/src/components/plp/Pagination.astro +99 -0
- package/apps/storefront/src/components/plp/SortSelect.astro +64 -0
- package/apps/storefront/src/config/devTenants.ts +16 -0
- package/apps/storefront/src/config/kvTenantResolver.ts +87 -0
- package/apps/storefront/src/config/resolver.ts +46 -0
- package/apps/storefront/src/config/tenants.ts +193 -0
- package/apps/storefront/src/layouts/Layout.astro +303 -0
- package/apps/storefront/src/lib/analytics/index.ts +47 -0
- package/apps/storefront/src/lib/auth/brokerAssertion.ts +136 -0
- package/apps/storefront/src/lib/auth/devAuth.ts +90 -0
- package/apps/storefront/src/lib/auth/gatePage.ts +81 -0
- package/apps/storefront/src/lib/auth/identityToken.ts +341 -0
- package/apps/storefront/src/lib/auth/loginGate.ts +107 -0
- package/apps/storefront/src/lib/auth/route.ts +146 -0
- package/apps/storefront/src/lib/auth/session.ts +203 -0
- package/apps/storefront/src/lib/auth/totAccessClient.ts +503 -0
- package/apps/storefront/src/lib/basePath.ts +41 -0
- package/apps/storefront/src/lib/cfImage.ts +55 -0
- package/apps/storefront/src/lib/chrome/model.ts +65 -0
- package/apps/storefront/src/lib/colors.ts +97 -0
- package/apps/storefront/src/lib/content-edit/client.ts +230 -0
- package/apps/storefront/src/lib/content-edit/index.ts +14 -0
- package/apps/storefront/src/lib/content-edit/route.ts +25 -0
- package/apps/storefront/src/lib/content-edit/types.ts +19 -0
- package/apps/storefront/src/lib/cspStaticHashes.ts +24 -0
- package/apps/storefront/src/lib/d1/catalog.ts +289 -0
- package/apps/storefront/src/lib/dashboard/staffAdmission.ts +43 -0
- package/apps/storefront/src/lib/dashboard/staffVendorAccess.ts +449 -0
- package/apps/storefront/src/lib/dashboard/tenantSelection.ts +136 -0
- package/apps/storefront/src/lib/dashboard/vendorQuery.ts +61 -0
- package/apps/storefront/src/lib/demoGate.ts +113 -0
- package/apps/storefront/src/lib/dev/ai-widget-client.js +127 -0
- package/apps/storefront/src/lib/dev/cliSignInCode.ts +132 -0
- package/apps/storefront/src/lib/diag/redact.ts +20 -0
- package/apps/storefront/src/lib/edgeCache.ts +128 -0
- package/apps/storefront/src/lib/email/magicLinkInviteEmail.ts +62 -0
- package/apps/storefront/src/lib/env.ts +60 -0
- package/apps/storefront/src/lib/fixtures/sampleProducts.ts +130 -0
- package/apps/storefront/src/lib/format.ts +29 -0
- package/apps/storefront/src/lib/foxyCommerce.ts +49 -0
- package/apps/storefront/src/lib/imageAttrs.ts +55 -0
- package/apps/storefront/src/lib/jsonld.ts +136 -0
- package/apps/storefront/src/lib/maintenance.ts +71 -0
- package/apps/storefront/src/lib/memoryKv.ts +32 -0
- package/apps/storefront/src/lib/messaging/messagesClient.ts +143 -0
- package/apps/storefront/src/lib/placeholder.ts +99 -0
- package/apps/storefront/src/lib/previewReload.ts +125 -0
- package/apps/storefront/src/lib/rawMarketingHtml.ts +133 -0
- package/apps/storefront/src/lib/search/index.ts +74 -0
- package/apps/storefront/src/lib/sections.ts +129 -0
- package/apps/storefront/src/lib/securityHeaders.ts +31 -0
- package/apps/storefront/src/lib/storyblok/content-model.ts +289 -0
- package/apps/storefront/src/lib/storyblok/provider.ts +524 -0
- package/apps/storefront/src/lib/tenantRouting.ts +91 -0
- package/apps/storefront/src/lib/tot/ToTClient.ts +177 -0
- package/apps/storefront/src/lib/tot/d1Client.ts +62 -0
- package/apps/storefront/src/lib/tot/query.ts +187 -0
- package/apps/storefront/src/lib/tot/totClientInterface.ts +30 -0
- package/apps/storefront/src/lib/url.ts +119 -0
- package/apps/storefront/src/lib/wishlist.ts +63 -0
- package/apps/storefront/src/middleware/index.ts +413 -0
- package/apps/storefront/src/pages/404.astro +61 -0
- package/apps/storefront/src/pages/[...slug].astro +90 -0
- package/apps/storefront/src/pages/api/auth/logout.ts +21 -0
- package/apps/storefront/src/pages/api/auth/magic-exchange.ts +107 -0
- package/apps/storefront/src/pages/api/auth/send.ts +85 -0
- package/apps/storefront/src/pages/api/auth/verify.ts +135 -0
- package/apps/storefront/src/pages/api/cache-purge.ts +44 -0
- package/apps/storefront/src/pages/api/content-edit/ai-edit.ts +64 -0
- package/apps/storefront/src/pages/api/csp-report.ts +25 -0
- package/apps/storefront/src/pages/api/dashboard/enter-vendor.ts +124 -0
- package/apps/storefront/src/pages/api/dashboard/vendor-search.ts +120 -0
- package/apps/storefront/src/pages/api/dev/cli-signin-code.ts +44 -0
- package/apps/storefront/src/pages/api/newsletter.ts +104 -0
- package/apps/storefront/src/pages/api/request-access.ts +172 -0
- package/apps/storefront/src/pages/auth/login.astro +149 -0
- package/apps/storefront/src/pages/auth/magic.astro +105 -0
- package/apps/storefront/src/pages/capabilities.astro +292 -0
- package/apps/storefront/src/pages/collections/[handle].astro +154 -0
- package/apps/storefront/src/pages/collections/index.astro +59 -0
- package/apps/storefront/src/pages/dashboard/[appDomain]/index.astro +100 -0
- package/apps/storefront/src/pages/dashboard/[appDomain]/team.astro +154 -0
- package/apps/storefront/src/pages/dashboard/index.astro +160 -0
- package/apps/storefront/src/pages/dev.astro +653 -0
- package/apps/storefront/src/pages/index.astro +290 -0
- package/apps/storefront/src/pages/llms.txt.ts +92 -0
- package/apps/storefront/src/pages/products/[handle].astro +443 -0
- package/apps/storefront/src/pages/robots.txt.ts +24 -0
- package/apps/storefront/src/pages/saved.astro +35 -0
- package/apps/storefront/src/pages/search.astro +150 -0
- package/apps/storefront/src/pages/sitemap.xml.ts +78 -0
- package/apps/storefront/src/pages/style-guide/[tenant]/[theme].astro +646 -0
- package/apps/storefront/src/pages/style-guide/[tenant]/index.astro +85 -0
- package/apps/storefront/src/pages/style-guide/index.astro +94 -0
- package/apps/storefront/src/pages/tenants/[id]/[...path].ts +57 -0
- package/apps/storefront/src/styles/global.css +277 -0
- package/apps/storefront/src/themes/reference.ts +61 -0
- package/apps/storefront/src/themes/schema.ts +111 -0
- package/apps/storefront/src/themes/tenants/index.ts +51 -0
- package/apps/storefront/tsconfig.json +16 -0
- package/apps/storefront/vitest.config.ts +22 -0
- package/apps/storefront/wrangler.toml +175 -0
- package/package.json +23 -0
- package/packages/public-runtime/LICENSE +58 -0
- package/packages/public-runtime/package.json +22 -0
- package/packages/public-runtime/src/binary-path.ts +68 -0
- package/packages/public-runtime/src/capabilities.ts +89 -0
- package/packages/public-runtime/src/catalog-api.ts +81 -0
- package/packages/public-runtime/src/catalog-d1.ts +192 -0
- package/packages/public-runtime/src/csp.ts +109 -0
- package/packages/public-runtime/src/customization-preview.ts +197 -0
- package/packages/public-runtime/src/customization-reconcile.ts +63 -0
- package/packages/public-runtime/src/customization-runtime.ts +157 -0
- package/packages/public-runtime/src/customization-scripts.ts +64 -0
- package/packages/public-runtime/src/customization-versioning.ts +95 -0
- package/packages/public-runtime/src/foxy.ts +184 -0
- package/packages/public-runtime/src/index.ts +30 -0
- package/packages/public-runtime/src/product.ts +159 -0
- package/packages/public-runtime/src/search.ts +45 -0
- package/packages/public-runtime/src/tenant-assets.ts +444 -0
- package/packages/public-runtime/src/tenant.ts +243 -0
- package/packages/public-runtime/tsconfig.json +8 -0
- package/packages/public-runtime/vitest.config.ts +8 -0
- package/pnpm-workspace.yaml +7 -0
- package/scripts/build/copy-tenant-assets.mjs +69 -0
- package/scripts/tot-dev.mjs +439 -0
- package/tenants/bigdvapor/content/blog.json +52 -0
- package/tenants/bigdvapor/content/chrome.html +149 -0
- package/tenants/bigdvapor/content/chrome.json +47 -0
- package/tenants/bigdvapor/content/home.html +463 -0
- package/tenants/bigdvapor/content/home.json +73 -0
- package/tenants/bigdvapor/content/pages/about.json +5 -0
- package/tenants/bigdvapor/content/pages/privacy.json +6 -0
- package/tenants/bigdvapor/content/pages/shipping-returns.json +6 -0
- package/tenants/bigdvapor/content/pages-html/blogs/news.html +86 -0
- package/tenants/bigdvapor/content/pages-html/pages/about-us.html +106 -0
- package/tenants/bigdvapor/content/pages-html/pages/contact-us.html +61 -0
- package/tenants/bigdvapor/content/pages-html/pages/privacy-policy.html +72 -0
- package/tenants/bigdvapor/content/pages-html/pages/shipping-returns.html +172 -0
- package/tenants/bigdvapor/content/themes/bigd-navy.json +109 -0
- package/tenants/bigdvapor/public/img/brands/adjust-vape-disposable.png +0 -0
- package/tenants/bigdvapor/public/img/brands/again-vape-disposable.png +0 -0
- package/tenants/bigdvapor/public/img/brands/al-fakher-vape-disposable.png +0 -0
- package/tenants/bigdvapor/public/img/brands/arro-vape-disposable.png +0 -0
- package/tenants/bigdvapor/public/img/brands/cookies-vape-disposable.png +0 -0
- package/tenants/bigdvapor/public/img/brands/core-vape-disposable.png +0 -0
- package/tenants/bigdvapor/public/img/brands/cyclone-vape-disposable.png +0 -0
- package/tenants/bigdvapor/public/img/brands/dinner-lady-vape-disposable.png +0 -0
- package/tenants/bigdvapor/public/img/brands/extre-bar-vape-disposable.png +0 -0
- package/tenants/bigdvapor/public/img/brands/fifty-bar-vape-disposable.jpg +0 -0
- package/tenants/bigdvapor/public/img/brands/firerose-vape-disposable.jpg +0 -0
- package/tenants/bigdvapor/public/img/brands/flavor-beast-vape-disposable.jpg +0 -0
- package/tenants/bigdvapor/public/img/brands/foger-vape-disposable.png +0 -0
- package/tenants/bigdvapor/public/img/brands/kk-energy-vape-disposable.png +0 -0
- package/tenants/bigdvapor/public/img/brands/kumi-vape-disposable.png +0 -0
- package/tenants/bigdvapor/public/img/brands/lost-vape-dispoable.png +0 -0
- package/tenants/bigdvapor/public/img/brands/melo-labs-vape-disposable.png +0 -0
- package/tenants/bigdvapor/public/img/brands/mixo-vape-disposable.webp +0 -0
- package/tenants/bigdvapor/public/img/brands/one-tank-vape-disposable.jpg +0 -0
- package/tenants/bigdvapor/public/img/brands/oxbar-vape-disposable.webp +0 -0
- package/tenants/bigdvapor/public/img/brands/pillow-talk-vape-disposable.jpg +0 -0
- package/tenants/bigdvapor/public/img/brands/pod-king-vape-disposable.jpg +0 -0
- package/tenants/bigdvapor/public/img/brands/raz-vape-disposable.png +0 -0
- package/tenants/bigdvapor/public/img/hero-texas.jpg +0 -0
- package/tenants/bigdvapor/public/img/og.jpg +0 -0
- package/tenants/bigdvapor/public/img/pages/AdobeStock_202106312_web.jpg +0 -0
- package/tenants/bigdvapor/public/img/pages/CREW_web.jpg +0 -0
- package/tenants/bigdvapor/public/img/pages/Hero-Image.jpg +0 -0
- package/tenants/bigdvapor/public/img/tiles/adjust.png +0 -0
- package/tenants/bigdvapor/public/img/tiles/again.png +0 -0
- package/tenants/bigdvapor/public/img/tiles/al-fakher.png +0 -0
- package/tenants/bigdvapor/public/img/tiles/arro.png +0 -0
- package/tenants/bigdvapor/public/img/tiles/cookies.png +0 -0
- package/tenants/bigdvapor/public/img/tiles/core.png +0 -0
- package/tenants/bigdvapor/public/img/tiles/cyclone.png +0 -0
- package/tenants/bigdvapor/public/img/tiles/disposables.svg +23 -0
- package/tenants/bigdvapor/public/logo-wordmark.png +0 -0
- package/tenants/bigdvapor/public/pages/home.css +118 -0
- package/tenants/bigdvapor/public/pages/mkt.css +185 -0
- package/tenants/bigdvapor/public/pages/page.css +148 -0
- package/tenants/bigdvapor/public/themes/bigd-navy.css +73 -0
- package/tenants/bigdvapor/theme.json +12 -0
- package/tenants/giantvapes/content/chrome.html +152 -0
- package/tenants/giantvapes/content/chrome.json +94 -0
- package/tenants/giantvapes/content/home.html +194 -0
- package/tenants/giantvapes/content/home.json +50 -0
- package/tenants/giantvapes/content/pages/about.json +10 -0
- package/tenants/giantvapes/content/pages/privacy.json +6 -0
- package/tenants/giantvapes/content/pages/shipping-returns.json +6 -0
- package/tenants/giantvapes/content/pages-html/blogs/news.html +68 -0
- package/tenants/giantvapes/content/pages-html/pages/about-us.html +95 -0
- package/tenants/giantvapes/content/pages-html/pages/contact-us.html +68 -0
- package/tenants/giantvapes/content/pages-html/pages/privacy-policy.html +65 -0
- package/tenants/giantvapes/content/pages-html/pages/shipping-returns.html +77 -0
- package/tenants/giantvapes/content/themes/giant-navy.json +73 -0
- package/tenants/giantvapes/public/img/hero-suicide-bunny.jpg +0 -0
- package/tenants/giantvapes/public/img/hero.webp +0 -0
- package/tenants/giantvapes/public/img/og.jpg +0 -0
- package/tenants/giantvapes/public/logo-wordmark.png +0 -0
- package/tenants/giantvapes/public/pages/home.css +120 -0
- package/tenants/giantvapes/public/pages/mkt.css +185 -0
- package/tenants/giantvapes/public/pages/page.css +155 -0
- package/tenants/giantvapes/public/themes/giant-navy.css +76 -0
- package/tenants/giantvapes/theme.json +39 -0
- package/tenants/home/content/chrome.json +11 -0
- package/tenants/home/content/home.html +304 -0
- package/tenants/home/content/home.json +13 -0
- package/tenants/home/public/js/storefront.js +210 -0
- package/tenants/home/public/logo-wordmark.png +0 -0
- package/tenants/home/public/pages/storefront.css +212 -0
- package/tenants/home/theme.json +6 -0
- package/tenants/tokenoftrust/.tot/config.json +9 -0
- package/tenants/tokenoftrust/content/chrome.json +55 -0
- package/tenants/tokenoftrust/content/home.html +723 -0
- package/tenants/tokenoftrust/content/home.json +233 -0
- package/tenants/tokenoftrust/content/pages-html/careers.html +231 -0
- package/tenants/tokenoftrust/content/pages-html/company.html +275 -0
- package/tenants/tokenoftrust/content/pages-html/contact/contact-sales.html +188 -0
- package/tenants/tokenoftrust/content/pages-html/contact/startup-apply.html +206 -0
- package/tenants/tokenoftrust/content/pages-html/contact.html +178 -0
- package/tenants/tokenoftrust/content/pages-html/industries/adult-content-age-verification.html +286 -0
- package/tenants/tokenoftrust/content/pages-html/industries/cannabis.html +277 -0
- package/tenants/tokenoftrust/content/pages-html/pact-act-pricing.html +289 -0
- package/tenants/tokenoftrust/content/pages-html/pricing.html +483 -0
- package/tenants/tokenoftrust/content/pages-html/product/age-assurance/age-estimation.html +278 -0
- package/tenants/tokenoftrust/content/pages-html/product/age-assurance/age-gate.html +279 -0
- package/tenants/tokenoftrust/content/pages-html/product/age-assurance/age-verification.html +265 -0
- package/tenants/tokenoftrust/content/pages-html/product/age-assurance.html +173 -0
- package/tenants/tokenoftrust/content/pages-html/product/compliance/aml.html +214 -0
- package/tenants/tokenoftrust/content/pages-html/product/compliance/pact-act.html +226 -0
- package/tenants/tokenoftrust/content/pages-html/product/fraud-prevention.html +254 -0
- package/tenants/tokenoftrust/content/pages-html/product/social-profile-verification.html +212 -0
- package/tenants/tokenoftrust/content/pages-html/product/tax/excise-tax.html +213 -0
- package/tenants/tokenoftrust/content/pages-html/product/verification/aml.html +259 -0
- package/tenants/tokenoftrust/content/pages-html/product/verification/biometric-selfie.html +305 -0
- package/tenants/tokenoftrust/content/pages-html/product/verification/coverage.html +254 -0
- package/tenants/tokenoftrust/content/pages-html/product/verification/document-verification.html +306 -0
- package/tenants/tokenoftrust/content/pages-html/product/verification/electronic-identity-verification.html +304 -0
- package/tenants/tokenoftrust/content/pages-html/product/verification/government-id-verification.html +308 -0
- package/tenants/tokenoftrust/content/pages-html/product/verification.html +183 -0
- package/tenants/tokenoftrust/content/pages-html/product.html +228 -0
- package/tenants/tokenoftrust/content/pages-html/resources/integrations/bigcommerce-integration.html +220 -0
- package/tenants/tokenoftrust/content/pages-html/resources/integrations/shopify-integration.html +221 -0
- package/tenants/tokenoftrust/content/pages-html/resources/integrations/wordpress.html +220 -0
- package/tenants/tokenoftrust/content/pages-html/resources/integrations.html +172 -0
- package/tenants/tokenoftrust/content/pages-html/resources/refer-a-friend-program.html +317 -0
- package/tenants/tokenoftrust/content/pages-html/resources.html +177 -0
- package/tenants/tokenoftrust/content/pages-html/reviews.html +273 -0
- package/tenants/tokenoftrust/content/pages-html/solutions.html +292 -0
- package/tenants/tokenoftrust/content/pages-html/vlp-alcohol.html +289 -0
- package/tenants/tokenoftrust/content/pages-html/vlp-cigars-and-tobacco.html +286 -0
- package/tenants/tokenoftrust/content/pages-html/vlp-firearm-accessories.html +267 -0
- package/tenants/tokenoftrust/content/pages-html/vlp-peptides.html +273 -0
- package/tenants/tokenoftrust/content/themes/tot-navy.json +88 -0
- package/tenants/tokenoftrust/public/favicon.png +0 -0
- package/tenants/tokenoftrust/public/logo-icon.png +0 -0
- package/tenants/tokenoftrust/public/logo-wordmark.png +0 -0
- package/tenants/tokenoftrust/public/pages/company.css +108 -0
- package/tenants/tokenoftrust/public/pages/home.css +457 -0
- package/tenants/tokenoftrust/public/pages/mkt.css +482 -0
- package/tenants/tokenoftrust/public/pages/pricing.css +214 -0
- package/tenants/tokenoftrust/public/pages/solutions.css +66 -0
- package/tenants/tokenoftrust/public/themes/tot-navy-1.0.0.css +136 -0
- package/tenants/tokenoftrust/public/themes/tot-navy.css +358 -0
- package/tenants/tokenoftrust/theme.json +31 -0
- package/tsconfig.base.json +20 -0
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
/* Storefront early-access landing — interactions + analytics.
|
|
2
|
+
* Served at /tenants/home/js/storefront.js (mirrored from tenants/home/public/).
|
|
3
|
+
*
|
|
4
|
+
* ---- tot20 analytics: public reportAnalytics endpoint --------------------
|
|
5
|
+
* GET /reportAnalytics/{origin}/{pluginVersion}/{subject}/{action}?...
|
|
6
|
+
* origin=totcom => anonymous marketing path (user_id null, device-id based).
|
|
7
|
+
* apiKeyNotRequired + allowCORs, so we fire a fire-and-forget GET beacon.
|
|
8
|
+
*
|
|
9
|
+
* Beacon transport is an Image() GET on purpose: the storefront CSP is
|
|
10
|
+
* `img-src https:` (allowed) but `connect-src 'self'` (a cross-origin fetch to
|
|
11
|
+
* qa.tokenoftrust.com would be BLOCKED). An <img> GET sidesteps connect-src.
|
|
12
|
+
*
|
|
13
|
+
* Detail rides in utm_content/utm_campaign (the endpoint's eventProperties).
|
|
14
|
+
* Events use subject=cust and are shaped onto two EXISTING registered wildcards
|
|
15
|
+
* in tot20's analytics schema (analyticEvents.json), so they validate (HTTP 200)
|
|
16
|
+
* with no schema change:
|
|
17
|
+
* - views → cust_viewed_totcom_page_* (the anonymous tokenoftrust.com convention)
|
|
18
|
+
* - clicks → cust_clicked_btn_*
|
|
19
|
+
* ------------------------------------------------------------------------- */
|
|
20
|
+
(function () {
|
|
21
|
+
const BASE = "https://qa.tokenoftrust.com/api"; // tot20 public API (qa; swap for prod)
|
|
22
|
+
const ORIGIN = "totcom", PLUGIN = "1.0", SUBJECT = "cust", APP_DOMAIN = "tokenoftrust.com";
|
|
23
|
+
|
|
24
|
+
function deviceId() {
|
|
25
|
+
try {
|
|
26
|
+
const k = "ampDeviceId";
|
|
27
|
+
let v = localStorage.getItem(k);
|
|
28
|
+
if (!v) { v = (crypto.randomUUID ? crypto.randomUUID() : String(Date.now()) + Math.random()); localStorage.setItem(k, v); }
|
|
29
|
+
return v;
|
|
30
|
+
} catch (e) { return "anon"; }
|
|
31
|
+
}
|
|
32
|
+
function track(action, detail, campaign) {
|
|
33
|
+
try {
|
|
34
|
+
const qs = new URLSearchParams({
|
|
35
|
+
appDomain: APP_DOMAIN, ampDeviceId: deviceId(),
|
|
36
|
+
title: document.title, referrer: document.referrer || "",
|
|
37
|
+
lang: navigator.language || "", screen_w: String(screen.width), screen_h: String(screen.height)
|
|
38
|
+
});
|
|
39
|
+
if (detail) qs.set("utm_content", detail);
|
|
40
|
+
qs.set("utm_campaign", campaign || "storefront_early_access");
|
|
41
|
+
qs.set("utm_source", "storefront-landing"); qs.set("utm_medium", "web");
|
|
42
|
+
const url = BASE + "/reportAnalytics/" + ORIGIN + "/" + PLUGIN + "/" + SUBJECT + "/" + encodeURIComponent(action) + "?" + qs.toString();
|
|
43
|
+
// Image() GET beacon — allowed by img-src https:; a fetch would hit connect-src 'self'.
|
|
44
|
+
new Image().src = url;
|
|
45
|
+
} catch (e) { /* fire-and-forget */ }
|
|
46
|
+
}
|
|
47
|
+
window.__totTrack = track;
|
|
48
|
+
|
|
49
|
+
// 1) page view
|
|
50
|
+
track("viewed_totcom_page_storefront_early_access");
|
|
51
|
+
|
|
52
|
+
// 2) every click on a labeled control (captures all CTAs, nav, deck links, login)
|
|
53
|
+
document.addEventListener("click", function (e) {
|
|
54
|
+
const el = e.target.closest("[data-ev]");
|
|
55
|
+
if (el) { const l = el.getAttribute("data-ev"); track("clicked_btn_" + l, l); }
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
// 3) section visibility (which parts of the page people actually reach)
|
|
59
|
+
if ("IntersectionObserver" in window) {
|
|
60
|
+
const seen = {};
|
|
61
|
+
const io = new IntersectionObserver(function (entries) {
|
|
62
|
+
entries.forEach(function (en) {
|
|
63
|
+
const name = en.target.getAttribute("data-section");
|
|
64
|
+
if (en.isIntersecting && !seen[name]) { seen[name] = 1; track("viewed_totcom_page_section_" + name, name); }
|
|
65
|
+
});
|
|
66
|
+
}, { threshold: .4 });
|
|
67
|
+
document.querySelectorAll("[data-section]").forEach(function (s) { io.observe(s); });
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// 4) scroll depth
|
|
71
|
+
const marks = [25, 50, 75, 100], hit = {};
|
|
72
|
+
window.addEventListener("scroll", function () {
|
|
73
|
+
const sc = document.documentElement, pct = Math.round((sc.scrollTop + window.innerHeight) / sc.scrollHeight * 100);
|
|
74
|
+
marks.forEach(function (m) { if (pct >= m && !hit[m]) { hit[m] = 1; track("viewed_totcom_page_scroll_" + m, String(m)); } });
|
|
75
|
+
}, { passive: true });
|
|
76
|
+
|
|
77
|
+
// 5) comparison expand/collapse
|
|
78
|
+
document.querySelectorAll(".cmp .top").forEach(function (btn) {
|
|
79
|
+
btn.addEventListener("click", function () {
|
|
80
|
+
const card = btn.closest(".cmp"), open = card.getAttribute("aria-expanded") === "true";
|
|
81
|
+
card.setAttribute("aria-expanded", open ? "false" : "true");
|
|
82
|
+
btn.setAttribute("aria-expanded", open ? "false" : "true");
|
|
83
|
+
// (analytics for the open already fired via data-ev on the button)
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
// 6) persona tabs
|
|
88
|
+
const tabs = document.querySelectorAll(".seg [data-persona]");
|
|
89
|
+
const panels = document.querySelectorAll(".ppanel");
|
|
90
|
+
tabs.forEach(function (tab) {
|
|
91
|
+
tab.addEventListener("click", function () {
|
|
92
|
+
const who = tab.getAttribute("data-persona");
|
|
93
|
+
tabs.forEach(function (t) { t.setAttribute("aria-selected", t === tab ? "true" : "false"); });
|
|
94
|
+
panels.forEach(function (p) { p.classList.toggle("on", p.getAttribute("data-panel") === who); });
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
// 7) time on page (sent on leave)
|
|
99
|
+
const start = Date.now();
|
|
100
|
+
window.addEventListener("pagehide", function () {
|
|
101
|
+
track("viewed_totcom_page_exit", String(Math.round((Date.now() - start) / 1000)));
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
// ---- request-access modal --------------------------------------------------
|
|
105
|
+
// Board address the mailto: fallback targets (mirrors the server route's
|
|
106
|
+
// recipient). Kept in sync with apps/storefront/src/pages/api/request-access.ts.
|
|
107
|
+
const BOARD_EMAIL = "darrin84+l6gajmvvoo1x4edew5qs@boards.trello.com";
|
|
108
|
+
const modal = document.getElementById("ra-modal");
|
|
109
|
+
const form = modal && modal.querySelector("form.ra");
|
|
110
|
+
|
|
111
|
+
function openModal(source) {
|
|
112
|
+
if (!modal) return;
|
|
113
|
+
modal.classList.remove("done");
|
|
114
|
+
if (form) form.classList.remove("has-error");
|
|
115
|
+
modal.classList.add("on");
|
|
116
|
+
document.body.style.overflow = "hidden";
|
|
117
|
+
track("clicked_btn_request_access_open", source || "unknown");
|
|
118
|
+
const first = modal.querySelector("input[name=email]");
|
|
119
|
+
if (first) setTimeout(function () { first.focus(); }, 40);
|
|
120
|
+
}
|
|
121
|
+
function closeModal() {
|
|
122
|
+
if (!modal) return;
|
|
123
|
+
modal.classList.remove("on");
|
|
124
|
+
document.body.style.overflow = "";
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// Any element pointing at #request opens the modal instead of jumping.
|
|
128
|
+
document.querySelectorAll('a[href="#request"]').forEach(function (a) {
|
|
129
|
+
a.addEventListener("click", function (e) {
|
|
130
|
+
e.preventDefault();
|
|
131
|
+
openModal(a.getAttribute("data-ev") || "cta");
|
|
132
|
+
});
|
|
133
|
+
});
|
|
134
|
+
if (modal) {
|
|
135
|
+
modal.querySelectorAll("[data-close]").forEach(function (el) {
|
|
136
|
+
el.addEventListener("click", closeModal);
|
|
137
|
+
});
|
|
138
|
+
document.addEventListener("keydown", function (e) {
|
|
139
|
+
if (e.key === "Escape" && modal.classList.contains("on")) closeModal();
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
function mailtoFallback(fields) {
|
|
144
|
+
const lines = [
|
|
145
|
+
"First name: " + fields.firstName,
|
|
146
|
+
"Last name: " + fields.lastName,
|
|
147
|
+
"Email: " + fields.email,
|
|
148
|
+
fields.phone ? "Phone: " + fields.phone : null,
|
|
149
|
+
fields.details ? "\nDetails:\n" + fields.details : null,
|
|
150
|
+
].filter(Boolean).join("\n");
|
|
151
|
+
const subject = "Early-access request — " + fields.firstName + " " + fields.lastName;
|
|
152
|
+
return "mailto:" + BOARD_EMAIL + "?subject=" + encodeURIComponent(subject) + "&body=" + encodeURIComponent(lines);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
if (form) {
|
|
156
|
+
form.addEventListener("submit", async function (e) {
|
|
157
|
+
e.preventDefault();
|
|
158
|
+
form.classList.remove("has-error");
|
|
159
|
+
const fd = new FormData(form);
|
|
160
|
+
const fields = {
|
|
161
|
+
email: String(fd.get("email") || "").trim(),
|
|
162
|
+
firstName: String(fd.get("firstName") || "").trim(),
|
|
163
|
+
lastName: String(fd.get("lastName") || "").trim(),
|
|
164
|
+
phone: String(fd.get("phone") || "").trim(),
|
|
165
|
+
details: String(fd.get("details") || "").trim(),
|
|
166
|
+
};
|
|
167
|
+
track("clicked_btn_request_access_submit", fields.email ? "with_email" : "no_email");
|
|
168
|
+
|
|
169
|
+
const btn = form.querySelector("button[type=submit]");
|
|
170
|
+
const label = btn ? btn.textContent : "";
|
|
171
|
+
if (btn) { btn.disabled = true; btn.textContent = "Sending…"; }
|
|
172
|
+
|
|
173
|
+
try {
|
|
174
|
+
const res = await fetch("/api/request-access", {
|
|
175
|
+
method: "POST",
|
|
176
|
+
headers: { "content-type": "application/json", accept: "application/json" },
|
|
177
|
+
body: JSON.stringify(fields),
|
|
178
|
+
});
|
|
179
|
+
const data = await res.json().catch(function () { return {}; });
|
|
180
|
+
if (res.ok && data && data.ok) {
|
|
181
|
+
// If the endpoint couldn't send server-side yet, it hands back a
|
|
182
|
+
// mailto: so the request is never dropped on the floor.
|
|
183
|
+
if (data.fallback === "mailto") {
|
|
184
|
+
window.location.href = data.mailto || mailtoFallback(fields);
|
|
185
|
+
}
|
|
186
|
+
modal.classList.add("done");
|
|
187
|
+
} else {
|
|
188
|
+
throw new Error((data && data.error) || "send_failed");
|
|
189
|
+
}
|
|
190
|
+
} catch (err) {
|
|
191
|
+
// Never a dead form: offer the mailto: as a client-side last resort.
|
|
192
|
+
// Built with DOM methods (no innerHTML) so field values can't inject markup.
|
|
193
|
+
form.classList.add("has-error");
|
|
194
|
+
const errEl = form.querySelector(".err");
|
|
195
|
+
if (errEl) {
|
|
196
|
+
errEl.textContent = "Something went wrong. ";
|
|
197
|
+
const link = document.createElement("a");
|
|
198
|
+
link.href = mailtoFallback(fields);
|
|
199
|
+
link.style.color = "inherit";
|
|
200
|
+
link.style.textDecoration = "underline";
|
|
201
|
+
link.textContent = "Email us directly";
|
|
202
|
+
errEl.appendChild(link);
|
|
203
|
+
errEl.appendChild(document.createTextNode(" and we'll take it from there."));
|
|
204
|
+
}
|
|
205
|
+
} finally {
|
|
206
|
+
if (btn) { btn.disabled = false; btn.textContent = label; }
|
|
207
|
+
}
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
})();
|
|
Binary file
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
/* Storefront by Token of Trust — early-access landing page.
|
|
2
|
+
* Ported from the approved prototype; served at /tenants/home/pages/storefront.css
|
|
3
|
+
* (mirrored from tenants/home/public/ by scripts/build/copy-tenant-assets.mjs).
|
|
4
|
+
* Sub-brand: Storefront lockup + teal→blue gradient on the tokenoftrust.com light theme. */
|
|
5
|
+
:root{
|
|
6
|
+
--navy:#10294b; --navy-2:#173763; --ink:#1b2a40; --muted:#4d5a70;
|
|
7
|
+
--cream:#faf8f4; --card:#fff; --line:#e6e2d9; --line-cool:#dfe6ee;
|
|
8
|
+
--teal:#0d9391; --teal-ink:#0b6360; --coral:#bf3d2c; --green:#1d9e5f; --gold:#8a6012;
|
|
9
|
+
--grad:linear-gradient(115deg,#0d9391,#3b82c4);
|
|
10
|
+
--r:20px; --r-sm:13px; --shadow:0 18px 50px rgba(16,41,75,.13); --shadow-soft:0 8px 24px rgba(27,42,64,.07);
|
|
11
|
+
--sans:"Inter",-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif;
|
|
12
|
+
--display:"Plus Jakarta Sans",var(--sans); --mono:"JetBrains Mono",ui-monospace,Menlo,monospace;
|
|
13
|
+
}
|
|
14
|
+
*{box-sizing:border-box;margin:0;padding:0}
|
|
15
|
+
body{font-family:var(--sans);background:var(--cream);color:var(--ink);line-height:1.6;-webkit-font-smoothing:antialiased}
|
|
16
|
+
.wrap{max-width:1200px;margin:0 auto;padding:0 40px}
|
|
17
|
+
a{color:inherit;text-decoration:none}
|
|
18
|
+
h1,h2,h3{font-family:var(--display);letter-spacing:-.02em;color:var(--navy)}
|
|
19
|
+
.grad{background:var(--grad);-webkit-background-clip:text;background-clip:text;color:transparent}
|
|
20
|
+
.btn{display:inline-flex;align-items:center;gap:9px;font-family:var(--display);font-weight:700;font-size:.94rem;
|
|
21
|
+
padding:12px 22px;border-radius:12px;border:0;cursor:pointer;transition:transform .15s,box-shadow .15s;color:inherit}
|
|
22
|
+
.btn:hover{transform:translateY(-2px)}
|
|
23
|
+
.btn-grad{background:var(--grad);color:#fff;box-shadow:0 10px 24px rgba(13,147,145,.32)}
|
|
24
|
+
.btn-grad:hover{box-shadow:0 14px 30px rgba(13,147,145,.4)}
|
|
25
|
+
.btn-line{background:#fff;color:var(--navy);border:1.5px solid var(--line-cool)}
|
|
26
|
+
.btn-line:hover{border-color:var(--navy)}
|
|
27
|
+
.arrow{transition:transform .2s}
|
|
28
|
+
.btn:hover .arrow{transform:translateX(3px)}
|
|
29
|
+
.kicker{font-size:.8rem;font-weight:800;letter-spacing:.14em;text-transform:uppercase;color:var(--teal-ink)}
|
|
30
|
+
|
|
31
|
+
/* header */
|
|
32
|
+
header{position:sticky;top:0;z-index:50;border-bottom:1px solid var(--line);background:rgba(250,248,244,.85);backdrop-filter:blur(12px)}
|
|
33
|
+
.nav{display:flex;align-items:center;justify-content:space-between;height:76px}
|
|
34
|
+
.lockup{display:flex;align-items:center;gap:12px}
|
|
35
|
+
.lockup img{height:30px;display:block}
|
|
36
|
+
.lockup .div{width:1px;height:22px;background:var(--line-cool)}
|
|
37
|
+
.lockup .prod{font-family:var(--display);font-weight:600;font-size:.95rem;letter-spacing:-.01em}
|
|
38
|
+
.nav-links{display:flex;gap:28px}
|
|
39
|
+
.nav-links a{font-size:.92rem;font-weight:500;color:var(--muted)}
|
|
40
|
+
.nav-links a:hover{color:var(--navy)}
|
|
41
|
+
.nav-right{display:flex;align-items:center;gap:20px}
|
|
42
|
+
.login{font-size:.92rem;font-weight:600;color:var(--muted)}
|
|
43
|
+
.login:hover{color:var(--navy)}
|
|
44
|
+
|
|
45
|
+
/* hero */
|
|
46
|
+
.hero{position:relative;overflow:hidden}
|
|
47
|
+
.blob{position:absolute;border-radius:50%;filter:blur(70px);opacity:.5;z-index:0;pointer-events:none}
|
|
48
|
+
.b1{width:520px;height:520px;background:radial-gradient(circle,#9fe4dd,transparent 70%);top:-160px;right:-120px}
|
|
49
|
+
.b2{width:440px;height:440px;background:radial-gradient(circle,#bcd6f5,transparent 70%);top:120px;right:220px;opacity:.4}
|
|
50
|
+
.hero-grid{position:relative;z-index:1;display:grid;grid-template-columns:1.02fr .98fr;gap:56px;align-items:center;padding:70px 0 84px}
|
|
51
|
+
.eyebrow{display:inline-flex;align-items:center;gap:10px;background:#fff;border:1px solid var(--line);
|
|
52
|
+
border-radius:999px;padding:8px 16px;font-size:.82rem;font-weight:700;color:var(--navy);box-shadow:var(--shadow-soft)}
|
|
53
|
+
.eyebrow .dot{position:relative;width:8px;height:8px;border-radius:50%;background:var(--green)}
|
|
54
|
+
.eyebrow .dot::after{content:"";position:absolute;inset:0;border-radius:50%;background:var(--green);animation:pulse 2.2s infinite}
|
|
55
|
+
@keyframes pulse{0%{transform:scale(1);opacity:.6}100%{transform:scale(2.8);opacity:0}}
|
|
56
|
+
h1{font-weight:800;font-size:3.35rem;line-height:1.07;margin:22px 0 20px}
|
|
57
|
+
.lede{font-size:1.17rem;color:var(--muted);max-width:40ch;margin-bottom:14px}
|
|
58
|
+
.lede b{color:var(--ink);font-weight:600}
|
|
59
|
+
.hero-ctas{display:flex;gap:13px;margin:28px 0 26px}
|
|
60
|
+
.cues{display:flex;flex-direction:column;gap:9px}
|
|
61
|
+
.cues span{display:flex;align-items:center;gap:10px;font-size:.95rem;font-weight:500;color:var(--ink)}
|
|
62
|
+
.cues .tk{width:20px;height:20px;border-radius:50%;background:rgba(13,147,145,.12);display:inline-flex;align-items:center;justify-content:center;flex:none}
|
|
63
|
+
.cues .tk svg{width:12px;height:12px;color:var(--teal)}
|
|
64
|
+
|
|
65
|
+
/* console (from A) */
|
|
66
|
+
.console{background:var(--card);border:1px solid var(--line);border-radius:var(--r);box-shadow:var(--shadow);overflow:hidden}
|
|
67
|
+
.c-head{display:flex;align-items:center;justify-content:space-between;padding:15px 20px;border-bottom:1px solid var(--line);background:linear-gradient(180deg,#fbfcfe,#fff)}
|
|
68
|
+
.c-head .url{font-family:var(--mono);font-size:.82rem;color:var(--navy);display:flex;align-items:center;gap:9px}
|
|
69
|
+
.c-live{display:inline-flex;align-items:center;gap:7px;font-size:.76rem;font-weight:700;color:var(--green);background:rgba(29,158,95,.1);padding:5px 11px;border-radius:999px}
|
|
70
|
+
.c-live i{width:7px;height:7px;border-radius:50%;background:var(--green);animation:blip 1.8s infinite}
|
|
71
|
+
@keyframes blip{0%{box-shadow:0 0 0 0 rgba(29,158,95,.5)}70%{box-shadow:0 0 0 7px rgba(29,158,95,0)}100%{box-shadow:0 0 0 0 rgba(29,158,95,0)}}
|
|
72
|
+
.c-body{padding:8px 8px 12px}
|
|
73
|
+
.crow{display:flex;align-items:center;gap:13px;padding:13px 14px;border-radius:11px}
|
|
74
|
+
.crow .ic{width:26px;height:26px;border-radius:8px;background:rgba(13,147,145,.12);display:inline-flex;align-items:center;justify-content:center;flex:none}
|
|
75
|
+
.crow .ic svg{width:15px;height:15px;color:var(--teal)}
|
|
76
|
+
.crow .lab{font-weight:600;font-size:.95rem;color:var(--ink)}
|
|
77
|
+
.crow .val{margin-left:auto;font-family:var(--mono);font-size:.82rem;color:var(--muted)}
|
|
78
|
+
.crow .val b{color:var(--green);font-weight:500}
|
|
79
|
+
.crow.killed{opacity:.5}
|
|
80
|
+
.crow.killed .ic{background:rgba(191,61,44,.1)}.crow.killed .ic svg{color:var(--coral)}
|
|
81
|
+
.crow.killed .lab{text-decoration:line-through;text-decoration-color:rgba(191,61,44,.55);color:var(--muted)}
|
|
82
|
+
.crow.killed .val{color:var(--coral)}
|
|
83
|
+
.c-foot{margin:6px 10px 4px;padding:12px 14px;border-top:1px dashed var(--line-cool);display:flex;align-items:center;gap:10px;font-size:.86rem;color:var(--muted)}
|
|
84
|
+
.c-foot b{color:var(--navy);font-weight:700}
|
|
85
|
+
.migbadge{margin-left:auto;font-family:var(--mono);font-size:.74rem;color:var(--teal-ink);background:rgba(13,147,145,.1);padding:4px 9px;border-radius:7px}
|
|
86
|
+
|
|
87
|
+
/* fear band */
|
|
88
|
+
.fear{background:var(--navy);color:#e7eef8}
|
|
89
|
+
.fear .wrap{display:grid;grid-template-columns:auto 1fr;gap:36px;align-items:center;padding:44px 40px}
|
|
90
|
+
.fear .big{font-family:var(--display);font-weight:800;font-size:3.6rem;line-height:1;color:#fff;letter-spacing:-.03em}
|
|
91
|
+
.fear .big .u{color:#ff9d8e}
|
|
92
|
+
.fear h2{color:#fff;font-size:1.5rem;margin-bottom:8px}
|
|
93
|
+
.fear p{color:#aebfd6;max-width:62ch;font-size:1rem}
|
|
94
|
+
.fear .src{font-family:var(--mono);font-size:.74rem;color:#7d92b3;margin-top:10px}
|
|
95
|
+
|
|
96
|
+
/* generic section */
|
|
97
|
+
section.blk{padding:78px 0}
|
|
98
|
+
.center{text-align:center}
|
|
99
|
+
.center .section-lede{margin-inline:auto}
|
|
100
|
+
h2.big2{font-size:2.15rem;line-height:1.12;margin:12px 0 12px}
|
|
101
|
+
.section-lede{color:var(--muted);max-width:60ch;font-size:1.06rem}
|
|
102
|
+
|
|
103
|
+
/* pillars */
|
|
104
|
+
.pillars{display:grid;grid-template-columns:repeat(3,1fr);gap:20px;margin-top:40px}
|
|
105
|
+
.pillar{background:#fff;border:1px solid var(--line);border-radius:var(--r);padding:24px;box-shadow:var(--shadow-soft)}
|
|
106
|
+
.pillar .pic{width:44px;height:44px;border-radius:12px;background:rgba(13,147,145,.1);display:inline-flex;align-items:center;justify-content:center;margin-bottom:16px}
|
|
107
|
+
.pillar .pic svg{width:23px;height:23px;color:var(--teal)}
|
|
108
|
+
.pillar h3{font-size:1.18rem;margin-bottom:8px}
|
|
109
|
+
.pillar p{color:var(--muted);font-size:.96rem}
|
|
110
|
+
.pillar .tag{display:inline-block;margin-top:14px;font-family:var(--mono);font-size:.74rem;color:var(--teal-ink);background:rgba(13,147,145,.09);padding:5px 10px;border-radius:7px}
|
|
111
|
+
|
|
112
|
+
/* comparison */
|
|
113
|
+
.cmp-wrap{background:#fff}
|
|
114
|
+
.cmp-cards{display:grid;grid-template-columns:repeat(3,1fr);gap:16px;margin-top:36px}
|
|
115
|
+
.cmp{border:1px solid var(--line);border-radius:var(--r);overflow:hidden;background:#fff;transition:box-shadow .2s}
|
|
116
|
+
.cmp:hover{box-shadow:var(--shadow-soft)}
|
|
117
|
+
.cmp .top{width:100%;text-align:left;background:none;border:0;cursor:pointer;padding:20px 22px;display:flex;align-items:center;gap:14px;font:inherit}
|
|
118
|
+
.cmp .logo{width:38px;height:38px;border-radius:10px;display:inline-flex;align-items:center;justify-content:center;font-family:var(--display);font-weight:800;color:#fff;font-size:1.05rem;flex:none}
|
|
119
|
+
.cmp .tt{flex:1}
|
|
120
|
+
.cmp .tt .nm{display:block;font-family:var(--display);font-weight:700;font-size:1.06rem;color:var(--navy)}
|
|
121
|
+
.cmp .tt .sub{display:block;font-size:.86rem;color:var(--muted);margin-top:2px}
|
|
122
|
+
.cmp .chev{width:20px;height:20px;color:var(--muted);transition:transform .25s;flex:none}
|
|
123
|
+
.cmp[aria-expanded="true"] .chev{transform:rotate(180deg)}
|
|
124
|
+
.cmp .panel{display:none;padding:0 22px 22px;border-top:1px solid var(--line)}
|
|
125
|
+
.cmp[aria-expanded="true"] .panel{display:block;animation:fade .3s ease}
|
|
126
|
+
@keyframes fade{from{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:none}}
|
|
127
|
+
.cmp .row2{padding-top:16px}
|
|
128
|
+
.cmp .row2 .h{display:flex;align-items:center;gap:8px;font-family:var(--display);font-weight:700;font-size:.82rem;text-transform:uppercase;letter-spacing:.06em;margin-bottom:8px}
|
|
129
|
+
.cmp .them .h{color:var(--coral)}
|
|
130
|
+
.cmp .us .h{color:var(--teal-ink)}
|
|
131
|
+
.cmp .row2 p{font-size:.92rem;color:var(--muted);line-height:1.55}
|
|
132
|
+
.cmp .row2 p b{color:var(--ink);font-weight:600}
|
|
133
|
+
.cmp .us{margin-top:16px;padding-top:16px;border-top:1px dashed var(--line-cool)}
|
|
134
|
+
|
|
135
|
+
/* persona */
|
|
136
|
+
.persona-wrap{background:linear-gradient(180deg,#f4f1ea,#faf8f4)}
|
|
137
|
+
.seg{display:inline-flex;background:#fff;border:1px solid var(--line);border-radius:14px;padding:5px;gap:4px;margin:28px 0 8px;box-shadow:var(--shadow-soft)}
|
|
138
|
+
.seg button{font-family:var(--display);font-weight:700;font-size:.95rem;color:var(--muted);background:none;border:0;padding:11px 20px;border-radius:10px;cursor:pointer;transition:.18s}
|
|
139
|
+
.seg button[aria-selected="true"]{background:var(--grad);color:#fff;box-shadow:0 6px 16px rgba(13,147,145,.28)}
|
|
140
|
+
.ppanel{display:none;margin-top:26px;background:#fff;border:1px solid var(--line);border-radius:var(--r);box-shadow:var(--shadow);overflow:hidden}
|
|
141
|
+
.ppanel.on{display:grid;grid-template-columns:.9fr 1.1fr}
|
|
142
|
+
.ppanel .lft{padding:34px;border-right:1px solid var(--line);background:linear-gradient(180deg,#fbfcfe,#fff)}
|
|
143
|
+
.ppanel .lft .who{font-family:var(--mono);font-size:.76rem;letter-spacing:.1em;text-transform:uppercase;color:var(--teal-ink);font-weight:600}
|
|
144
|
+
.ppanel .lft h3{font-size:1.7rem;line-height:1.12;margin:12px 0 12px}
|
|
145
|
+
.ppanel .lft p{color:var(--muted);font-size:1rem;margin-bottom:20px}
|
|
146
|
+
.ppanel .deck{display:inline-flex;align-items:center;gap:8px;font-family:var(--display);font-weight:700;font-size:.9rem;color:var(--teal-ink)}
|
|
147
|
+
.ppanel .deck:hover{color:var(--navy)}
|
|
148
|
+
.ppanel .rgt{padding:30px 34px;display:flex;flex-direction:column;gap:16px}
|
|
149
|
+
.ben{display:flex;gap:13px}
|
|
150
|
+
.ben .bic{width:28px;height:28px;border-radius:8px;background:rgba(13,147,145,.12);display:inline-flex;align-items:center;justify-content:center;flex:none}
|
|
151
|
+
.ben .bic svg{width:15px;height:15px;color:var(--teal)}
|
|
152
|
+
.ben .bt{font-family:var(--display);font-weight:700;font-size:.98rem;color:var(--navy)}
|
|
153
|
+
.ben .bd{font-size:.9rem;color:var(--muted)}
|
|
154
|
+
|
|
155
|
+
/* final cta */
|
|
156
|
+
.final{padding:20px 0 88px}
|
|
157
|
+
.cta-band{background:var(--navy);border-radius:26px;padding:56px 40px;text-align:center;position:relative;overflow:hidden}
|
|
158
|
+
.cta-band .cb{position:absolute;width:360px;height:360px;border-radius:50%;filter:blur(80px);opacity:.35}
|
|
159
|
+
.cta-band .cb1{background:#0d9391;top:-120px;left:-60px}.cta-band .cb2{background:#3b82c4;bottom:-140px;right:-40px}
|
|
160
|
+
.cta-band .kicker{color:#7fe3d6;position:relative}
|
|
161
|
+
.cta-band h2{color:#fff;font-size:2.2rem;margin:12px 0 12px;position:relative}
|
|
162
|
+
.cta-band p{color:#aebfd6;max-width:56ch;margin:0 auto 26px;position:relative}
|
|
163
|
+
.cta-band .hero-ctas{justify-content:center;position:relative}
|
|
164
|
+
.btn-white{background:#fff;color:var(--navy)}
|
|
165
|
+
|
|
166
|
+
/* built strip / footer */
|
|
167
|
+
.strip{border-top:1px solid var(--line);border-bottom:1px solid var(--line);background:#fff}
|
|
168
|
+
.strip .wrap{display:flex;align-items:center;justify-content:space-between;padding:20px 40px;gap:24px;flex-wrap:wrap}
|
|
169
|
+
.strip .built{display:flex;align-items:center;gap:14px;font-size:.88rem;color:var(--muted);flex-wrap:wrap}
|
|
170
|
+
.strip .built .k{font-weight:700;color:var(--navy);font-size:.78rem;letter-spacing:.08em;text-transform:uppercase}
|
|
171
|
+
.strip .built .tag{font-weight:600;color:var(--ink)}
|
|
172
|
+
.strip .built .sep{color:var(--line-cool)}
|
|
173
|
+
.strip .repl{font-size:.85rem;color:var(--muted)}.strip .repl b{color:var(--navy);font-weight:700}
|
|
174
|
+
footer.foot{padding:40px 0;color:var(--muted);font-size:.85rem;text-align:center;background:#f4f1ea}
|
|
175
|
+
|
|
176
|
+
/* request-access modal */
|
|
177
|
+
.modal{position:fixed;inset:0;z-index:100;display:none;align-items:center;justify-content:center;padding:24px}
|
|
178
|
+
.modal.on{display:flex}
|
|
179
|
+
.modal .ov{position:absolute;inset:0;background:rgba(16,41,75,.5);backdrop-filter:blur(3px)}
|
|
180
|
+
.modal .dlg{position:relative;z-index:1;background:#fff;border-radius:var(--r);box-shadow:var(--shadow);width:100%;max-width:520px;max-height:92vh;overflow:auto;animation:fade .25s ease}
|
|
181
|
+
.modal .dlg-head{display:flex;align-items:flex-start;justify-content:space-between;gap:16px;padding:28px 30px 6px}
|
|
182
|
+
.modal .dlg-head h3{font-size:1.5rem;line-height:1.15}
|
|
183
|
+
.modal .dlg-head p{color:var(--muted);font-size:.95rem;margin-top:6px}
|
|
184
|
+
.modal .x{background:none;border:0;cursor:pointer;color:var(--muted);width:34px;height:34px;border-radius:9px;display:inline-flex;align-items:center;justify-content:center;flex:none}
|
|
185
|
+
.modal .x:hover{background:var(--cream);color:var(--navy)}
|
|
186
|
+
.modal .x svg{width:20px;height:20px}
|
|
187
|
+
form.ra{padding:14px 30px 30px;display:flex;flex-direction:column;gap:14px}
|
|
188
|
+
form.ra .fld{display:flex;flex-direction:column;gap:6px}
|
|
189
|
+
form.ra .row{display:grid;grid-template-columns:1fr 1fr;gap:14px}
|
|
190
|
+
form.ra label{font-family:var(--display);font-weight:700;font-size:.82rem;color:var(--navy)}
|
|
191
|
+
form.ra label .opt{font-family:var(--sans);font-weight:500;color:var(--muted);text-transform:none;letter-spacing:0}
|
|
192
|
+
form.ra input,form.ra textarea{font:inherit;font-size:.95rem;color:var(--ink);background:#fff;border:1.5px solid var(--line-cool);
|
|
193
|
+
border-radius:10px;padding:11px 13px;transition:border-color .15s}
|
|
194
|
+
form.ra input:focus,form.ra textarea:focus{outline:none;border-color:var(--teal)}
|
|
195
|
+
form.ra textarea{resize:vertical;min-height:78px}
|
|
196
|
+
form.ra .btn-grad{justify-content:center;margin-top:4px}
|
|
197
|
+
form.ra .err{display:none;color:var(--coral);font-size:.9rem;font-weight:600}
|
|
198
|
+
form.ra.has-error .err{display:block}
|
|
199
|
+
.ra-done{display:none;padding:34px 30px 40px;text-align:center}
|
|
200
|
+
.modal.done form.ra{display:none}
|
|
201
|
+
.modal.done .ra-done{display:block}
|
|
202
|
+
.ra-done .tick{width:56px;height:56px;border-radius:50%;background:rgba(29,158,95,.12);display:inline-flex;align-items:center;justify-content:center;margin-bottom:16px}
|
|
203
|
+
.ra-done .tick svg{width:30px;height:30px;color:var(--green)}
|
|
204
|
+
.ra-done h3{font-size:1.5rem;margin-bottom:8px}
|
|
205
|
+
.ra-done p{color:var(--muted);font-size:1rem;max-width:34ch;margin:0 auto 18px}
|
|
206
|
+
|
|
207
|
+
@media (max-width:900px){
|
|
208
|
+
.hero-grid{grid-template-columns:1fr;gap:40px}.pillars,.cmp-cards{grid-template-columns:1fr}
|
|
209
|
+
.ppanel.on{grid-template-columns:1fr}.ppanel .lft{border-right:0;border-bottom:1px solid var(--line)}
|
|
210
|
+
.fear .wrap{grid-template-columns:1fr;gap:16px}h1{font-size:2.5rem}
|
|
211
|
+
form.ra .row{grid-template-columns:1fr}
|
|
212
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
{
|
|
2
|
+
"tenant": "tokenoftrust",
|
|
3
|
+
"scope": "tokenoftrust.com",
|
|
4
|
+
"mappings": [
|
|
5
|
+
{ "workspace": "theme.json", "repo": "tenants/tokenoftrust/theme.json", "kind": "file" },
|
|
6
|
+
{ "workspace": "content/", "repo": "tenants/tokenoftrust/content/", "kind": "tree" },
|
|
7
|
+
{ "workspace": "public/", "repo": "tenants/tokenoftrust/public/", "kind": "tree" }
|
|
8
|
+
]
|
|
9
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
{
|
|
2
|
+
"nav": [
|
|
3
|
+
{ "label": "Platform", "href": "/#platform" },
|
|
4
|
+
{ "label": "Industries", "href": "/#industries" },
|
|
5
|
+
{ "label": "Resources", "href": "https://help.tokenoftrust.com" },
|
|
6
|
+
{ "label": "Pricing", "href": "https://tokenoftrust.com/pricing/" },
|
|
7
|
+
{ "label": "Login", "href": "https://app.tokenoftrust.com" }
|
|
8
|
+
],
|
|
9
|
+
"headerCtas": [
|
|
10
|
+
{ "label": "Book Demo", "href": "https://tokenoftrust.com/contact/", "variant": "secondary" },
|
|
11
|
+
{ "label": "Start For Free", "href": "https://app.tokenoftrust.com", "variant": "primary" }
|
|
12
|
+
],
|
|
13
|
+
"footer": {
|
|
14
|
+
"tagline": "Customer verification and compliance for regulated ecommerce. 200+ countries. We will never sell your data.",
|
|
15
|
+
"legal": "GDPR · CCPA · PIPEDA compliant. 256-bit SSL. We will never sell your data.",
|
|
16
|
+
"columns": [
|
|
17
|
+
{
|
|
18
|
+
"title": "Platform",
|
|
19
|
+
"links": [
|
|
20
|
+
{ "label": "Identity Verification", "href": "/#platform" },
|
|
21
|
+
{ "label": "Age Assurance", "href": "/#platform" },
|
|
22
|
+
{ "label": "Fraud Prevention", "href": "/#platform" },
|
|
23
|
+
{ "label": "Compliance Evidence", "href": "/#platform" },
|
|
24
|
+
{ "label": "AML · PACT Act · Tax", "href": "/#platform" }
|
|
25
|
+
]
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
"title": "Industries",
|
|
29
|
+
"links": [
|
|
30
|
+
{ "label": "Alcohol", "href": "/#industries" },
|
|
31
|
+
{ "label": "Tobacco & Vape", "href": "/#industries" },
|
|
32
|
+
{ "label": "Age-Restricted Goods", "href": "/#industries" },
|
|
33
|
+
{ "label": "Marketplaces", "href": "/#industries" }
|
|
34
|
+
]
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
"title": "Company",
|
|
38
|
+
"links": [
|
|
39
|
+
{ "label": "Pricing", "href": "https://tokenoftrust.com/pricing/" },
|
|
40
|
+
{ "label": "Contact Sales", "href": "https://tokenoftrust.com/contact/" },
|
|
41
|
+
{ "label": "Resources", "href": "https://help.tokenoftrust.com" },
|
|
42
|
+
{ "label": "Login", "href": "https://app.tokenoftrust.com" }
|
|
43
|
+
]
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
"title": "Legal",
|
|
47
|
+
"links": [
|
|
48
|
+
{ "label": "Privacy Policy", "href": "https://tokenoftrust.com/privacy/" },
|
|
49
|
+
{ "label": "Terms", "href": "https://tokenoftrust.com/terms/" }
|
|
50
|
+
]
|
|
51
|
+
}
|
|
52
|
+
],
|
|
53
|
+
"social": []
|
|
54
|
+
}
|
|
55
|
+
}
|