Expand public site content and operator guides

This commit is contained in:
axiomlogicnexus 2026-07-01 03:37:13 +00:00
parent ad7404d482
commit 951c927ffb
18 changed files with 1359 additions and 53 deletions

View file

@ -26,6 +26,15 @@ claims over the same capability.
- the public website may be widened as a professional operator/distribution
manual, but that still does not authorize it to claim ownership over the
native simulator job
- the public website should now also say this plainly in operator-facing terms:
the web version is intentionally narrower and materially less powerful for
actual simulator work than the downloadable
- the web version remains justified because it owns account/auth, release
posture, pricing, notices, support-safe onboarding, and browser-to-desktop
handoff without turning the simulator into a storefront or identity shell
- the downloadable remains the main product because it owns package-validated
training behavior, replay/coaching execution, higher-dimensional runtime
families, and the current serious control/runtime evidence
## Refactor toolchain

View file

@ -57,6 +57,18 @@ The website is therefore not superfluous, but it is intentionally inferior for
the core simulator job. Public and manual wording must keep that distinction
explicit.
Concrete interpretation rule:
- the browser version is for public docs, pricing, release posture, notices,
support-safe onboarding, protected account state, and browser-to-desktop
handoff
- the browser version is not the place to overclaim package-validated
training behavior, higher-dimensional packaged execution, low-latency native
input authority, or finished XR/controller runtime ownership
- the downloadable remains the materially more powerful product surface because
it owns the simulator itself, the higher-dimensional family maps, packaged
proof, and the current serious training workflows
The current first-party website also doubles as a bounded public-facing
operator manual:

View file

@ -1,6 +1,6 @@
# HyperTwist Operator Manual
Last updated: 2026-06-30
Last updated: 2026-07-01
## Purpose
@ -76,6 +76,32 @@ That narrower browser boundary is intentional. It keeps access, release,
billing, pairing, and legal-distribution work inspectable outside the simulator
while keeping the real training runtime easier to trust.
### What you do not get if you stay browser-only
If you stay only on the website, you do not get the main simulator value:
- the real classic-cube practice loop
- recognition, correction closure, and solve-guidance execution
- replay, coaching, analytics, and local leaderboard continuity
- dedicated `Magic120Cell` or `MagicCube5D` packaged-family runtime execution
- the native diagnostics that prove higher-dimensional session, scene,
persistence-boundary, and state-semantics ownership
In short:
- the browser version is useful, but it is intentionally weaker than the
downloadable for actual training and serious study
- the downloadable remains the primary product because it is where the current
simulator authority really lives
### What the browser version is still excellent for
- public docs, help-center, and route-atlas reading
- pricing, launch-status, and release-note review
- account access and protected entitlement posture
- protected notices and corresponding-source follow-through
- browser-to-desktop pairing and rollout-safe support coordination
## Browser access and account posture
The browser lane is intentionally narrower than the simulator.
@ -232,6 +258,19 @@ The desktop runtime is the current product center for:
This is the current truthful desktop-first posture. Do not collapse it into a
generic browser simulator claim.
## Current puzzle and workflow lineup
These are the main study lanes the downloadable already owns today:
- classic-cube practice and timing
- recognition, reconstruction, and solve guidance
- replay, coaching, analytics, and operator diagnostics
- `Magic120Cell` packaged runtime
- `MagicCube5D` packaged runtime
- `MagicTile` embedded-browser runtime posture inside Unreal
The website can explain every one of these. The website does not execute them.
## Control and settings truth
Current shipped desktop control truth includes:
@ -351,6 +390,15 @@ Use the desktop runtime when you need:
- higher-dimensional execution
- native diagnostics or runtime-adjacent operator work
Current public route guidance:
- `/browser` explains why the web version exists and why it stays narrower than
the downloadable
- `/help` acts as the knowledge-base style route for onboarding, controls,
troubleshooting, and rollout-safe product questions
- `/contact` is the direct human lane when the next best move is no longer a
manual page
## Release, download, and distribution posture
HyperTwist is digitally delivered through browser account access and desktop

View file

@ -3,6 +3,9 @@
<url>
<loc>https://hypertwist.app/</loc>
</url>
<url>
<loc>https://hypertwist.app/browser</loc>
</url>
<url>
<loc>https://hypertwist.app/features</loc>
</url>
@ -12,6 +15,9 @@
<url>
<loc>https://hypertwist.app/resources</loc>
</url>
<url>
<loc>https://hypertwist.app/help</loc>
</url>
<url>
<loc>https://hypertwist.app/getting-started</loc>
</url>
@ -24,6 +30,9 @@
<url>
<loc>https://hypertwist.app/support</loc>
</url>
<url>
<loc>https://hypertwist.app/contact</loc>
</url>
<url>
<loc>https://hypertwist.app/changelog</loc>
</url>

View file

@ -59,7 +59,7 @@ describe('App bootstrap', () => {
render(<App />)
expect(await screen.findByText('HyperTwist turns cube practice into a real operator-grade training stack.')).toBeTruthy()
expect(await screen.findByText('From first solves to 120-cell, HyperTwist keeps the real simulator in the downloadable.')).toBeTruthy()
await waitFor(() => {
expect(window.location.pathname).toBe('/')
})

View file

@ -158,7 +158,25 @@ describe('AppRouteTree', () => {
expect(screen.getByText('Loading HyperTwist...')).toBeTruthy()
expect(screen.getByText('Public release shell')).toBeTruthy()
expect(screen.getByText(/public product story, current launch posture, and browser-versus-desktop authority map/i)).toBeTruthy()
expect(await screen.findByText('HyperTwist turns cube practice into a real operator-grade training stack.')).toBeTruthy()
expect(await screen.findByText('From first solves to 120-cell, HyperTwist keeps the real simulator in the downloadable.')).toBeTruthy()
})
it('renders the browser-guide page through the real public route tree', async () => {
renderRoute('/browser')
expect(screen.getByText('Browser access guide')).toBeTruthy()
expect(screen.getByText('Web version posture')).toBeTruthy()
expect(screen.getByText(/browser-versus-downloadable boundary, protected dashboard handoff, and the current web-lane purpose/i)).toBeTruthy()
expect(await screen.findByText('The browser version exists to support the downloadable, not replace it.')).toBeTruthy()
})
it('renders the help-center page through the real public route tree', async () => {
renderRoute('/help')
expect(screen.getByText('Help center')).toBeTruthy()
expect(screen.getByText('Operator knowledge base')).toBeTruthy()
expect(screen.getByText(/onboarding, control truth, browser-to-desktop guidance, and rollout-safe troubleshooting/i)).toBeTruthy()
expect(await screen.findByText('Production-grade help for the routes, runtime, and rollout you actually have.')).toBeTruthy()
})
it('renders the pricing page through the real public route tree', async () => {

View file

@ -10,10 +10,13 @@ describe('offline operator manual', () => {
expect(manual).toContain('## Why the website stays and where it is intentionally weaker')
expect(manual).toContain('### What the browser does not claim')
expect(manual).toContain('### What you do not get if you stay browser-only')
expect(manual).toContain('## First-session verification checklist')
expect(manual).toContain('## Issue reporting checklist')
expect(manual).toContain('desktop-hosted native OpenXR/controller widening is `No-Go`')
expect(manual).toContain('`Magic120Cell`')
expect(manual).toContain('/app/downloads')
expect(manual).toContain('/browser')
expect(manual).toContain('/help')
})
})

View file

@ -114,11 +114,14 @@ vi.mock('../site-config', () => ({
import {
AboutPage,
BrowserExperiencePage,
ChangelogPage,
ContactPage,
DocsPage,
DownloadPage,
FeaturesPage,
GettingStartedPage,
HelpCenterPage,
HomeLanding,
LaunchStatusPage,
OpenSourceNoticesPage,
@ -1074,6 +1077,82 @@ describe('public marketing pages', () => {
expect(screen.getByText('Runtime and training issues')).toBeTruthy()
})
it('renders the new browser, help, and contact guidance routes with the expected public-manual boundary language', () => {
mockGetAuthHealth.mockResolvedValue({
ok: true,
service: 'hypertwist-auth-server',
supertokens: {
configured: true,
reachable: true,
ready: true,
apiVersion: '5.4',
error: null,
oauth: {
github: false,
google: false,
},
},
fallback: {
enabled: true,
active: false,
reason: null,
},
billing: {
statePath: '/var/lib/hypertwist/auth/hypertwist-billing-state.json',
processedEventCount: 0,
pricePlanMapConfigured: false,
productPlanMapConfigured: false,
webhookSecretConfigured: false,
},
runtime: {
mode: 'mixed',
public_origin_ready: true,
cookie_secure: true,
api_domain: 'https://hypertwist.app',
website_domain: 'https://hypertwist.app',
warnings: [],
errors: [],
},
})
mockGetReleaseManifest.mockResolvedValue({
ok: true,
manifest: {
generated_at: '2026-06-22T12:00:00.000Z',
support_email: 'hello@hypertwist.app',
public_docs_url: 'https://docs.hypertwist.app',
release_notes_url: 'https://notes.hypertwist.app',
corresponding_source_url: 'https://hypertwist.app/open-source/source.zip',
open_source_repo_url: 'https://github.com/hypertwist/hypertwist',
viewer: {
authenticated: false,
canDownload: false,
plan: null,
role: null,
accessStatus: null,
},
platforms: [],
},
})
const browserView = renderWithProviders(<BrowserExperiencePage />, ['/browser'])
expect(within(browserView.container).getByText('What the browser version is genuinely for')).toBeTruthy()
expect(within(browserView.container).getByText('Why the downloadable remains much more powerful')).toBeTruthy()
expect(within(browserView.container).getByText('How the browser and downloadable work together')).toBeTruthy()
expect(within(browserView.container).getByText('The browser version exists to support the downloadable, not replace it.')).toBeTruthy()
const helpView = renderWithProviders(<HelpCenterPage />, ['/help'])
expect(within(helpView.container).getByText('What this help center covers')).toBeTruthy()
expect(within(helpView.container).getByText('Pick the right help lane')).toBeTruthy()
expect(within(helpView.container).getByText('Current controls and device posture')).toBeTruthy()
expect(within(helpView.container).getByText('Need escalation instead of guidance?')).toBeTruthy()
const contactView = renderWithProviders(<ContactPage />, ['/contact'])
expect(within(contactView.container).getByText('Contact lanes')).toBeTruthy()
expect(within(contactView.container).getByText('Primary contact route')).toBeTruthy()
expect(within(contactView.container).getByText('What to include in your message')).toBeTruthy()
expect(within(contactView.container).getByText('How HyperTwist classifies escalations')).toBeTruthy()
})
it('surfaces current packaged desktop proof on the public resources page', () => {
mockGetAuthHealth.mockResolvedValue({
ok: true,
@ -1712,7 +1791,8 @@ describe('public marketing pages', () => {
renderWithProviders(<ChangelogPage />, ['/changelog'])
expect(screen.getByText('Latest changes')).toBeTruthy()
expect(screen.getByText('Recent release packets')).toBeTruthy()
expect(screen.getByText('Detailed chronological feed')).toBeTruthy()
expect(screen.getAllByText('June 24, 2026').length).toBeGreaterThan(0)
expect(screen.getByText('Signed-in operator shell now mirrors the native control roster')).toBeTruthy()
expect(screen.getByText('Native selector-recall diagnostics hardened and revalidated')).toBeTruthy()

View file

@ -19,9 +19,10 @@ describe('public route registry', () => {
it('exposes the intended primary navigation and footer surfaces', () => {
expect(marketingNavLinks).toEqual([
{ to: '/', label: 'Home' },
{ to: '/browser', label: 'Browser' },
{ to: '/features', label: 'Features' },
{ to: '/about', label: 'About' },
{ to: '/resources', label: 'Resources' },
{ to: '/help', label: 'Help Center' },
{ to: '/pricing', label: 'Pricing' },
{ to: '/download', label: 'Download' },
])
@ -30,11 +31,17 @@ describe('public route registry', () => {
to: '/open-source-notices',
label: 'Open Source Notices',
})
expect(footerLinks).toContainEqual({
to: '/contact',
label: 'Contact',
})
})
it('keeps auth routes out of crawlable sitemap posture', () => {
expect(crawlablePublicRoutes.map((route) => route.path)).not.toContain('/login')
expect(crawlablePublicRoutes.map((route) => route.path)).not.toContain('/register')
expect(crawlablePublicRoutes.map((route) => route.path)).toContain('/browser')
expect(crawlablePublicRoutes.map((route) => route.path)).toContain('/help')
expect(crawlablePublicRoutes.map((route) => route.path)).toContain('/getting-started')
expect(crawlablePublicRoutes.map((route) => route.path)).toContain('/launch-status')
})
@ -62,7 +69,9 @@ describe('public route registry', () => {
const xml = buildPublicSitemapXml()
expect(xml).toContain('<loc>https://hypertwist.app/</loc>')
expect(xml).toContain('<loc>https://hypertwist.app/browser</loc>')
expect(xml).toContain('<loc>https://hypertwist.app/features</loc>')
expect(xml).toContain('<loc>https://hypertwist.app/help</loc>')
expect(xml).toContain('<loc>https://hypertwist.app/getting-started</loc>')
expect(xml).toContain('<loc>https://hypertwist.app/launch-status</loc>')
expect(xml).not.toContain('/login')

View file

@ -16,6 +16,21 @@ export function MarketingShell({
children: React.ReactNode
}) {
const { isAuthenticated } = usePlatformAuth()
const footerLookup = new Map(footerLinks.map((link) => [link.to, link]))
const footerGroups = [
{
title: 'Product',
routes: ['/', '/browser', '/features', '/about', '/resources', '/help', '/docs'],
},
{
title: 'Access',
routes: ['/pricing', '/download', '/getting-started', '/launch-status', '/support', '/contact', '/changelog'],
},
{
title: 'Policy',
routes: ['/open-source-notices', '/privacy', '/terms', '/shipping-payment'],
},
] as const
return (
<div className="site-shell">
@ -26,7 +41,7 @@ export function MarketingShell({
alt="HyperTwist"
className="brand-mark__image"
/>
<span>
<span className="brand-mark__copy">
<strong>{brandConfig.brandName}</strong>
<small>{brandConfig.tagline}</small>
</span>
@ -66,12 +81,33 @@ export function MarketingShell({
<div className="site-footer__brand">
<strong>{brandConfig.brandName}</strong>
<p>{brandConfig.tagline}</p>
</div>
<div className="site-footer__links">
{footerLinks.map((link) => (
<Link key={link.to} to={link.to}>
{link.label}
<p className="site-footer__contact">
Contact: <a href={brandConfig.contact.emailHref}>{brandConfig.contact.email}</a>
</p>
<div className="button-row top-gap">
<Link className="button button--primary" to="/download">
Get desktop app
</Link>
<Link className="button button--ghost" to={isAuthenticated ? '/app' : '/login'}>
{isAuthenticated ? 'Account dashboard' : 'Account access'}
</Link>
</div>
</div>
<div className="site-footer__grid">
{footerGroups.map((group) => (
<div key={group.title} className="site-footer__group">
<p className="eyebrow">{group.title}</p>
<div className="site-footer__links">
{group.routes
.map((route) => footerLookup.get(route))
.filter((link): link is { to: string; label: string } => Boolean(link))
.map((link) => (
<Link key={link.to} to={link.to}>
{link.label}
</Link>
))}
</div>
</div>
))}
</div>
<p className="site-footer__note">

View file

@ -6,10 +6,11 @@ import { OperationalStatusCallout } from '../components/ui/OperationalStatusCall
import { ProductSurfaceMatrix } from '../components/ui/ProductSurfaceMatrix'
import { PublicLaunchStatus } from '../components/ui/PublicLaunchStatus'
import { ReleaseValidationSummary } from '../components/ui/ReleaseValidationSummary'
import { paddleReadyDescription } from '../site-config'
import { brandConfig, paddleReadyDescription } from '../site-config'
import { buildReleaseMetadataItems, resolveReleaseCommerceView } from '../release-manifest'
import { buildLoginPath, buildProtectedDownloadPath, buildSupportPath } from '../site-routes'
import {
browserLimitCards,
desktopFirstLaunchCards,
desktopDownloadSteps,
desktopReleaseSignals,
@ -21,6 +22,7 @@ import {
operatorManualTracks,
privacyBoundaryCards,
productSurfaceMatrixRows,
puzzleCatalogCards,
releaseRolloutChecklist,
runtimeControlGuideCards,
supportEscalationCards,
@ -102,6 +104,12 @@ export function PricingPage() {
</div>
</Section>
<BulletCardSection
title="Why plan access starts on the web but training stays in the downloadable"
description="Pricing should explain the product boundary directly instead of letting buyers infer it from scattered support notes."
cards={browserLimitCards}
/>
<Section title="Launch posture">
<PublicLaunchStatus />
</Section>
@ -134,6 +142,12 @@ export function PricingPage() {
description="Plans only make sense if the public pricing lane also says what the entitled desktop software is for once it is installed."
/>
<BulletCardSection
title="What those plans unlock in practice"
description="Commercial copy is stronger when it points at the concrete simulator lanes the downloadable already owns."
cards={puzzleCatalogCards}
/>
<HigherDimensionalRuntimeGuideSection
title="Higher-dimensional families behind the plans"
description="This keeps commercial copy tied to the real runtime families the desktop product already owns instead of leaving serious capability buried elsewhere in the manual."
@ -179,6 +193,17 @@ export function PricingPage() {
Public pricing, checkout, and download pages are distribution surfaces. Before external launch,
keep their legal footer and open-source notices link live and ensure the corresponding-source URL is configured for any downloadable build containing MPL-covered material.
</p>
<div className="button-row top-gap">
<Link className="button button--ghost" to="/browser">
Open browser guide
</Link>
<Link className="button button--ghost" to="/help">
Open help center
</Link>
<Link className="button button--primary" to="/contact">
Contact HyperTwist
</Link>
</div>
</article>
</Section>
</MarketingShell>
@ -291,6 +316,26 @@ export function DownloadPage() {
</div>
</Section>
<Section
title="Need the web-version explanation before you install?"
description="The download lane should still link back to the public routes that explain what the browser shell is for and how the protected handoff works."
>
<div className="feature-band">
<Link to="/browser" className="feature-band__card feature-band__card--link">
<h3>Browser guide</h3>
<p>Read why HyperTwist keeps the web version, what it does well, and where it is intentionally weaker than the downloadable.</p>
</Link>
<Link to="/help" className="feature-band__card feature-band__card--link">
<h3>Help center</h3>
<p>Open practical onboarding, controls, and rollout-safe troubleshooting guidance before or after the first install.</p>
</Link>
<Link to="/contact" className="feature-band__card feature-band__card--link">
<h3>Contact</h3>
<p>Open the human contact lane when the next move is support, rollout coordination, or pricing follow-through.</p>
</Link>
</div>
</Section>
<SimulatorManualSection
title="What the installed runtime already owns"
description="Download posture is stronger when the page also explains the real software lane operators receive after the package handoff."
@ -559,6 +604,22 @@ export function OpenSourceNoticesPage() {
<DownloadableOperatorManualSection
description="The legal/distribution lane now also keeps the offline operator manual reachable so corresponding-source, rollout, download, and native-runtime boundary guidance can travel together."
/>
<Section title="Questions about notices or redistribution?">
<article className="callout">
<p>
Contact <a href={brandConfig.contact.emailHref}>{brandConfig.contact.email}</a> when the next question is redistribution, corresponding-source follow-through, or release-surface notice posture rather than simulator behavior.
</p>
<div className="button-row top-gap">
<Link className="button button--ghost" to="/support?topic=launch-readiness">
Open launch support
</Link>
<Link className="button button--primary" to="/contact">
Open contact route
</Link>
</div>
</article>
</Section>
</MarketingShell>
</>
)
@ -660,6 +721,22 @@ export function PrivacyPage() {
))}
</div>
</Section>
<Section title="Privacy contact and policy help">
<article className="callout">
<p>
For browser-account, billing, release-access, or policy questions, contact <a href={brandConfig.contact.emailHref}>{brandConfig.contact.email}</a> and include whether the concern is public, protected, or native-runtime context.
</p>
<div className="button-row top-gap">
<Link className="button button--ghost" to="/help">
Open help center
</Link>
<Link className="button button--primary" to="/contact">
Open contact route
</Link>
</div>
</article>
</Section>
</MarketingShell>
</>
)
@ -760,6 +837,22 @@ export function TermsPage() {
))}
</div>
</Section>
<Section title="Access, redistribution, or compliance contact">
<article className="callout">
<p>
Terms questions that affect billing, protected release access, or redistribution should go to <a href={brandConfig.contact.emailHref}>{brandConfig.contact.email}</a> with the exact public or protected route and the current build or release context.
</p>
<div className="button-row top-gap">
<Link className="button button--ghost" to="/support?topic=studio-rollout">
Open rollout support
</Link>
<Link className="button button--primary" to="/contact">
Open contact route
</Link>
</div>
</article>
</Section>
</MarketingShell>
</>
)
@ -937,6 +1030,25 @@ export function ShippingPaymentPage() {
<DownloadableOperatorManualSection
description="The delivery lane also keeps the offline operator manual attached so first-session setup, rollout posture, higher-dimensional runtime guidance, and browser-versus-desktop truth can accompany the purchase and download path."
/>
<Section title="Need billing, rollout, or plan help?">
<article className="callout">
<p>
Write to <a href={brandConfig.contact.emailHref}>{brandConfig.contact.email}</a> for operator provisioning, studio rollout, payment posture, or release-surface billing questions.
</p>
<div className="button-row top-gap">
<Link className="button button--ghost" to="/pricing">
Reopen pricing
</Link>
<Link className="button button--ghost" to="/help">
Open help center
</Link>
<Link className="button button--primary" to="/contact">
Open contact route
</Link>
</div>
</article>
</Section>
</MarketingShell>
</>
)

View file

@ -0,0 +1,365 @@
import { Globe, Headset, LifeBuoy, Mail, MonitorSmartphone, ShieldCheck } from 'lucide-react'
import { Link } from 'react-router-dom'
import { MarketingShell } from '../components/layout/MarketingShell'
import { SiteMetadata } from '../components/seo/SiteMetadata'
import { brandConfig } from '../site-config'
import {
browserLimitCards,
browserPurposeCards,
browserWorkflowTracks,
contactChannelCards,
helpCenterCards,
issueReportingChecklistCards,
supportEscalationCards,
supportFaqs,
} from '../site-data'
import {
BrowserAuthMethodsSection,
BrowserDesktopDecisionFaqSection,
BrowserDesktopRealitySection,
BulletCardSection,
DeliverySurfaceResponsibilitiesGrid,
FaqCardSection,
HigherDimensionalRuntimeGuideSection,
InputAndDevicePostureSection,
OperatorDesktopQuickstartSection,
PublicPackagedDesktopProofSection,
PublicReleaseDecisionGuideSection,
ReleaseAuthorityBundleSection,
Section,
StepCardSection,
SupportTopicDirectorySection,
SurfaceChoiceGuideSection,
supportTopicDirectory,
usePublicReleaseManifestView,
} from './public-page-helpers'
export function BrowserExperiencePage() {
const { releaseManifest, windowsValidationPlatform } = usePublicReleaseManifestView('public-browser')
return (
<>
<SiteMetadata
title="HyperTwist browser access"
description="Learn what the HyperTwist browser experience is for, why it remains intentionally narrower than the downloadable, and when to move into the desktop runtime."
canonicalPath="/browser"
/>
<MarketingShell
eyebrow="Web version and protected browser shell"
title="The browser version exists to support the downloadable, not replace it."
lede="HyperTwist keeps a real browser experience because account access, pricing, release posture, notices, pairing, and operator support should stay outside the simulator. That does make the browser version narrower and less powerful for training work, and this page says exactly how."
>
<Section
title="Start with the right expectation"
description="This is the shortest honest description of the web version: useful, production-relevant, and intentionally weaker than the downloadable for the core simulator job."
>
<div className="feature-band">
<article className="feature-band__card">
<Globe size={22} />
<h3>The browser is the public and protected operator shell</h3>
<p>Use it for docs, pricing, release posture, account access, notices, and browser-to-desktop pairing.</p>
</article>
<article className="feature-band__card">
<MonitorSmartphone size={22} />
<h3>The downloadable is the actual simulator</h3>
<p>Use the desktop runtime for recognition, replay, coaching, higher-dimensional families, and packaged proof.</p>
</article>
<article className="feature-band__card">
<Headset size={22} />
<h3>The current XR boundary is still explicit</h3>
<p>The browser does not hide the fact that finished OpenXR/controller completion still remains a separate native packet.</p>
</article>
</div>
<div className="button-row top-gap">
<Link className="button button--primary" to="/download">
Open desktop download
</Link>
<Link className="button button--ghost" to="/app">
Open protected dashboard
</Link>
<Link className="button button--ghost" to="/help">
Open help center
</Link>
</div>
</Section>
<BulletCardSection
title="What the browser version is genuinely for"
description="This is the browser lane at its strongest: account-aware operator and distribution work around the simulator."
cards={browserPurposeCards}
/>
<BulletCardSection
title="Why the downloadable remains much more powerful"
description="This is the direct statement the public site should not bury: the web version is intentionally narrower and materially less capable for simulator execution."
cards={browserLimitCards}
/>
<StepCardSection
title="How the browser and downloadable work together"
description="Use this lane when a buyer, operator, or studio wants the real sequence instead of generic browser-versus-native rhetoric."
cards={browserWorkflowTracks}
/>
<BrowserDesktopRealitySection
title="What stays on the website and what stays in the downloadable"
description="The browser shell remains valuable because it stays on its own side of the product boundary instead of quietly absorbing simulator claims it cannot prove."
/>
<BrowserDesktopDecisionFaqSection
description="These are the direct questions people ask as soon as they realize HyperTwist has both a website and a downloadable."
/>
<BrowserAuthMethodsSection
description="The browser lane is easier to understand when the real sign-in posture is visible next to the release, support, and download decisions it controls."
/>
<Section
title="What changes after you install the desktop build"
description="The browser remains part of the product after installation, but the center of gravity moves into the downloadable immediately."
>
<DeliverySurfaceResponsibilitiesGrid />
</Section>
<OperatorDesktopQuickstartSection title="First downloadable session after the browser handoff" />
<SupportTopicDirectorySection
title="Need a browser or handoff answer fast?"
description="These routes keep the next operator move explicit when the web version raises a launch, access, or rollout question."
topics={supportTopicDirectory}
selectedTopicKey="operator-access"
/>
<SurfaceChoiceGuideSection description="The browser page should also tell people exactly where to go next: public for evaluation, protected for account-aware release work, and desktop for the actual simulator." />
<PublicReleaseDecisionGuideSection
releaseManifest={releaseManifest}
description="This keeps the web-version story operationally useful too: the next honest move might be protected downloads, pricing, notices, or browser-account continuity."
/>
<PublicPackagedDesktopProofSection
platform={windowsValidationPlatform}
actions={[
{ to: '/download', label: 'Open download center' },
{ to: '/changelog', label: 'Review release notes' },
]}
/>
<ReleaseAuthorityBundleSection
releaseManifest={releaseManifest}
description="The browser lane is part of the release story, so this page keeps docs, release notes, source, notices, and support contact bundled with the downloadable handoff."
/>
</MarketingShell>
</>
)
}
export function HelpCenterPage() {
const { releaseManifest, windowsValidationPlatform } = usePublicReleaseManifestView('public-help')
return (
<>
<SiteMetadata
title="HyperTwist help center"
description="Use the HyperTwist help center for onboarding, controls, higher-dimensional runtime guidance, browser-to-desktop handoff help, and rollout-safe troubleshooting."
canonicalPath="/help"
/>
<MarketingShell
eyebrow="Help center"
title="Production-grade help for the routes, runtime, and rollout you actually have."
lede="The help center is where HyperTwist answers practical questions before they become support tickets: how the browser handoff works, how the downloadable should behave on first launch, what controls are real today, and how to escalate when the next step is genuinely human."
>
<BulletCardSection
title="What this help center covers"
description="These are the main categories the public site should answer directly instead of forcing operators into support for everything."
cards={helpCenterCards}
/>
<SupportTopicDirectorySection
title="Pick the right help lane"
description="These cards keep account, rollout, release, and runtime questions separated before escalation begins."
topics={supportTopicDirectory}
/>
<OperatorDesktopQuickstartSection
title="First-session help"
description="If the question is 'what should I actually do first?', this is the shortest truthful answer."
/>
<InputAndDevicePostureSection
title="Current controls and device posture"
description="The help center should say plainly what is real today and what still remains outside the current native XR/controller completion lane."
/>
<HigherDimensionalRuntimeGuideSection
title="Higher-dimensional runtime help"
description="This guide keeps the serious family lanes accessible to public readers without pretending they run in the browser."
/>
<BulletCardSection
title="Issue-report packet"
description="When self-service stops being enough, these prompts keep issue reports high-signal and surface-aware."
cards={issueReportingChecklistCards}
/>
<FaqCardSection
title="Common operator questions"
description="These public-safe answers should settle the most common browser, download, controls, and scope questions quickly."
cards={supportFaqs}
/>
<BrowserDesktopRealitySection
title="Why help still separates browser from downloadable"
description="Good help is clearer when it mirrors the live product topology instead of flattening everything into one vague app."
/>
<Section
title="Need escalation instead of guidance?"
description="Move into the human lane when the question has already become account, package, runtime, or rollout blocking."
>
<div className="feature-band">
<Link to="/support" className="feature-band__card feature-band__card--link">
<LifeBuoy size={22} />
<h3>Open support</h3>
<p>Use the escalation route when the next job is launch recovery, entitlement review, or runtime issue routing.</p>
</Link>
<Link to="/contact" className="feature-band__card feature-band__card--link">
<Mail size={22} />
<h3>Open contact page</h3>
<p>Use the direct contact lane when you already know you need a human response rather than another manual page.</p>
</Link>
</div>
</Section>
<SurfaceChoiceGuideSection description="The help center is best when it still says where the answer lives: public for guidance, protected for account-aware release work, and desktop for simulator execution." />
<PublicReleaseDecisionGuideSection
releaseManifest={releaseManifest}
description="Help gets stronger when it also tells operators the next honest move instead of stopping at explanation alone."
/>
<PublicPackagedDesktopProofSection
platform={windowsValidationPlatform}
actions={[
{ to: '/download', label: 'Open download center' },
{ to: '/support', label: 'Open support' },
]}
/>
<ReleaseAuthorityBundleSection
releaseManifest={releaseManifest}
description="The help center should still carry the same docs, release notes, notices, and support bundle as the rest of the public manual so operators can act on what they just learned."
/>
</MarketingShell>
</>
)
}
export function ContactPage() {
const { releaseManifest, windowsValidationPlatform } = usePublicReleaseManifestView('public-contact')
return (
<>
<SiteMetadata
title="Contact HyperTwist"
description="Contact HyperTwist for operator support, desktop rollout help, download issues, pricing questions, and notices or release follow-through."
canonicalPath="/contact"
/>
<MarketingShell
eyebrow="Contact"
title="Contact the team with the right packet the first time."
lede={`Write to ${brandConfig.contact.email} when the next step is genuinely human: access problems, rollout questions, runtime issue packets, pricing follow-through, or legal-distribution contact.`}
>
<BulletCardSection
title="Contact lanes"
description="The public site should make the human lanes explicit too, not only the self-service documentation."
cards={contactChannelCards}
/>
<Section
title="Primary contact route"
description="HyperTwist keeps one direct contact path visible, but the fastest answer still depends on naming the right surface and packet."
>
<article className="callout">
<p>
Email <a href={brandConfig.contact.emailHref}>{brandConfig.contact.email}</a> with the route,
platform, plan posture, and whether the question is public, protected, or native runtime work.
</p>
<p>
The clearer the surface ownership is up front, the faster HyperTwist can separate account, package, runtime, and rollout questions.
</p>
<div className="button-row top-gap">
<a className="button button--primary" href={brandConfig.contact.emailHref}>
Email HyperTwist
</a>
<Link className="button button--ghost" to="/support">
Open support routes
</Link>
</div>
</article>
</Section>
<SupportTopicDirectorySection
title="Choose the right escalation lane"
description="These topic cards help you attach the message to the real account, rollout, or simulator surface before you send it."
topics={supportTopicDirectory}
/>
<BulletCardSection
title="What to include in your message"
description="This is the compact packet shape that makes replies faster and reduces back-and-forth."
cards={issueReportingChecklistCards}
/>
<BulletCardSection
title="How HyperTwist classifies escalations"
description="These distinctions matter because a release/access failure and a simulator bug are not the same problem even when they occur in one session."
cards={supportEscalationCards}
/>
<BrowserDesktopRealitySection
title="Why contact still depends on the browser-versus-downloadable split"
description="The contact lane should reflect the real product topology too: account and release issues stay in the browser family, while simulator issues stay attached to the downloadable."
/>
<Section
title="Launch and release context"
description="Contact and support are safer when they stay anchored to current package proof and public launch posture."
>
<div className="feature-band">
<article className="feature-band__card">
<ShieldCheck size={22} />
<h3>Release posture stays visible</h3>
<p>Use current launch status and packaged proof before reporting a rollout or release concern.</p>
</article>
<article className="feature-band__card">
<MonitorSmartphone size={22} />
<h3>The downloadable remains the runtime authority</h3>
<p>Runtime issue reports should name the exact simulator family and build, not only the website route that led there.</p>
</article>
</div>
</Section>
<SurfaceChoiceGuideSection description="This page should still point operators to the right next surface too: public for context, protected for account-aware release work, and desktop for actual simulator confirmation." />
<PublicReleaseDecisionGuideSection
releaseManifest={releaseManifest}
description="If direct contact is not actually the next best move, these cards keep the lower-friction public and protected routes visible too."
/>
<PublicPackagedDesktopProofSection
platform={windowsValidationPlatform}
actions={[
{ to: '/download', label: 'Open download center' },
{ to: '/launch-status', label: 'Open launch status' },
]}
/>
<ReleaseAuthorityBundleSection
releaseManifest={releaseManifest}
description="Contact pages are stronger when they still carry the same docs, release notes, corresponding-source, notices, and support references that frame the actual problem."
/>
</MarketingShell>
</>
)
}

View file

@ -8,6 +8,8 @@ import { ProductSurfaceMatrix } from '../components/ui/ProductSurfaceMatrix'
import { brandConfig } from '../site-config'
import {
advancedOperatorAdjunctTracks,
audienceFitCards,
browserLimitCards,
capabilityPillars,
changelogEntries,
companyNarrative,
@ -22,7 +24,9 @@ import {
issueReportingChecklistCards,
operatorManualTracks,
operatorPlaybooks,
puzzleCatalogCards,
publicDocumentationPrinciples,
releasePacketCards,
releaseRolloutChecklist,
productSurfaceMatrixRows,
releaseStoryCards,
@ -73,32 +77,33 @@ export function HomeLanding() {
canonicalPath="/"
/>
<MarketingShell
eyebrow="Desktop-first training. Browser-first operator access."
title="HyperTwist turns cube practice into a real operator-grade training stack."
lede="Recognition, replay, coaching, analytics, higher-dimensional runtime ownership, public distribution, and browser-based account access all live under one honest product story."
eyebrow="Desktop-first simulator. Browser-first access and rollout."
title="From first solves to 120-cell, HyperTwist keeps the real simulator in the downloadable."
lede="The website is a real product surface for account access, pricing, release posture, legal follow-through, and operator help. The downloadable is the much more powerful runtime for recognition, replay, coaching, higher-dimensional execution, and package-validated training."
>
<section className="hero-panel">
<div className="hero-grid">
<div className="hero-copy">
<p>
HyperTwist is a native training environment for classic cube, higher-dimensional
families, browser-assisted recognition, replay explanation, and desktop packaging.
The public site is intentionally honest: the desktop runtime is real, the browser
account/dashboard is real, and the optional full-browser simulator path remains spec-only.
HyperTwist is a native training environment for classic cube practice, recognition
and correction closure, replay explanation, coaching, higher-dimensional puzzle
families, and serious packaged study sessions. The web lane is intentionally narrower:
it owns access, documentation, release posture, support, and pairing so the
downloadable can stay focused on the simulator itself.
</p>
<div className="button-row">
<Link className="button button--primary" to="/download">
Download desktop app
</Link>
<Link className="button button--ghost" to="/browser">
Why keep the web version?
</Link>
<Link className="button button--ghost" to="/help">
Open help center
</Link>
<Link className="button button--ghost" to="/app">
Open operator dashboard
</Link>
<Link className="button button--ghost" to="/getting-started">
Open getting started
</Link>
<Link className="button button--ghost" to="/features">
Explore feature atlas
</Link>
</div>
</div>
<div className="hero-visual-card">
@ -108,8 +113,13 @@ export function HomeLanding() {
className="hero-visual-card__image"
/>
<p className="hero-visual-card__caption">
Browser account shell outside the simulator. Native Unreal runtime inside the simulator.
Browser shell for access, rollout, and support. Native Unreal runtime for the simulator.
</p>
<ul className="list top-gap">
<li>Use the web for pricing, docs, release notes, notices, and protected downloads.</li>
<li>Use the downloadable for real cube-state workflows, higher-dimensional maps, and diagnostics.</li>
<li>Read XR/controller widening honestly as a separate native completion packet, not as a finished browser or desktop claim today.</li>
</ul>
</div>
</div>
<div className="metric-grid">
@ -129,6 +139,12 @@ export function HomeLanding() {
<PublicLaunchStatus title="Public website and release posture" />
</Section>
<BulletCardSection
title="Why the downloadable remains the main product"
description="The homepage should answer this immediately instead of leaving it hidden inside support or legal copy."
cards={browserLimitCards}
/>
<BrowserDesktopRealitySection />
<BrowserDesktopDecisionFaqSection
@ -149,6 +165,12 @@ export function HomeLanding() {
</div>
</Section>
<BulletCardSection
title="Puzzle families and study lanes"
description="HyperTwist is broader than one timer or one browser widget. These are the concrete practice and puzzle lanes the product already owns."
cards={puzzleCatalogCards}
/>
<Section
title="Capability pillars"
description="The page structure keeps HyperTwist's public shell disciplined around real runtime authority instead of mixing product narrative, rollout status, and simulator claims together."
@ -163,6 +185,12 @@ export function HomeLanding() {
</div>
</Section>
<BulletCardSection
title="Who HyperTwist is for"
description="The browser and downloadable work together differently depending on whether the next job is practice, rollout, or higher-dimensional study."
cards={audienceFitCards}
/>
<Section
title="Roadmap-honest posture"
description="Important boundaries stay visible instead of being blurred into vague marketing claims."
@ -293,7 +321,7 @@ export function AboutPage() {
<MarketingShell
eyebrow="Why HyperTwist exists"
title="A training stack serious enough for higher-dimensional cubing."
lede="HyperTwist exists because cubers deserve one coherent system for physical recognition, explanation, practice, replay, analytics, and hyper puzzle ownership."
lede="HyperTwist exists because cubers deserve one coherent system for physical recognition, explanation, practice, replay, analytics, serious higher-dimensional runtime ownership, and an operator shell that does not blur account access with simulator execution."
>
<Section title="Mission">
<div className="card">
@ -336,6 +364,18 @@ export function AboutPage() {
</div>
</Section>
<BulletCardSection
title="What you can actually train today"
description="The public narrative is stronger when it names the concrete puzzle and workflow families the downloadable already owns."
cards={puzzleCatalogCards}
/>
<BulletCardSection
title="Who the product is built for"
description="HyperTwist is not one flat audience product. The browser shell and downloadable serve different needs across these groups."
cards={audienceFitCards}
/>
<Section
title="How a real HyperTwist session unfolds"
description="The product story is strongest when the public site explains the genuine operator path instead of flattening browser access and simulator use into one vague promise."
@ -473,11 +513,21 @@ export function ResourcesPage() {
<Section title="Direct routes">
<div className="feature-band">
<Link to="/browser" className="feature-band__card feature-band__card--link">
<ExternalLink size={22} />
<h3>Browser guide</h3>
<p>The public explanation of what the web version is for, what it is weaker at, and when to move into the downloadable.</p>
</Link>
<Link to="/features" className="feature-band__card feature-band__card--link">
<Boxes size={22} />
<h3>Feature atlas</h3>
<p>One public page for current capability, surface boundaries, and release posture.</p>
</Link>
<Link to="/help" className="feature-band__card feature-band__card--link">
<MonitorCog size={22} />
<h3>Help center</h3>
<p>Knowledge-base style guidance for onboarding, controls, release handoff, and rollout-safe troubleshooting.</p>
</Link>
<Link to="/getting-started" className="feature-band__card feature-band__card--link">
<MonitorCog size={22} />
<h3>Getting started</h3>
@ -498,6 +548,11 @@ export function ResourcesPage() {
<h3>Support</h3>
<p>Contact, rollout questions, and account/download help.</p>
</Link>
<Link to="/contact" className="feature-band__card feature-band__card--link">
<Landmark size={22} />
<h3>Contact</h3>
<p>The direct operator contact route for access, runtime, rollout, pricing, and notice follow-through.</p>
</Link>
<Link to="/changelog" className="feature-band__card feature-band__card--link">
<Sparkles size={22} />
<h3>Release notes</h3>
@ -564,6 +619,12 @@ export function ResourcesPage() {
cards={advancedOperatorAdjunctTracks}
/>
<BulletCardSection
title="Puzzle families and training lanes"
description="Resources should also expose the actual study surfaces the downloadable already owns instead of only the broader manual taxonomy."
cards={puzzleCatalogCards}
/>
<HigherDimensionalRuntimeGuideSection
title="Higher-dimensional runtime guide"
description="These public-safe cards explain which higher-dimensional family lanes are already real and what runtime posture each one actually uses."
@ -768,10 +829,33 @@ export function DocsPage() {
<MarketingShell
eyebrow="Documentation posture"
title="HyperTwist documentation stays capability-accurate."
lede="The public docs surface points users to product-safe truth: feature registry discipline, roadmap honesty, release notes, and distribution/legal guidance."
lede="The public docs surface now functions as a real product manual: current feature truth, browser-versus-downloadable boundaries, first-session guidance, control truth, higher-dimensional runtime posture, and release-safe distribution guidance."
>
<PrincipleCardSection title="Public documentation lanes" cards={publicDocumentationPrinciples} />
<Section
title="Manual entry points"
description="The docs surface is now only one part of the public manual family. These entry points help operators choose the right reading depth quickly."
>
<div className="feature-band">
<Link to="/browser" className="feature-band__card feature-band__card--link">
<MonitorCog size={22} />
<h3>Browser guide</h3>
<p>Open the public explanation of the web version, protected dashboard, and downloadable boundary.</p>
</Link>
<Link to="/help" className="feature-band__card feature-band__card--link">
<BookOpenText size={22} />
<h3>Help center</h3>
<p>Open the practical troubleshooting and onboarding lane when the next job is not full manual study.</p>
</Link>
<Link to="/contact" className="feature-band__card feature-band__card--link">
<ExternalLink size={22} />
<h3>Contact</h3>
<p>Open the direct human contact route when the next best move is escalation instead of more reading.</p>
</Link>
</div>
</Section>
<PublicManualRouteAtlasSection
title="Documentation and route atlas"
description="The manual is easier to use when it also says which public route owns which question, so operators do not have to infer structure from navigation labels alone."
@ -922,7 +1006,7 @@ export function SupportPage() {
<MarketingShell
eyebrow="Operator help"
title="Support for rollout, downloads, pricing, and browser-to-desktop access."
lede="Support is focused on helping operators understand what the browser shell does, what the desktop build does, and how the two connect."
lede="Support is focused on getting operators unstuck without flattening the product topology: browser and release issues stay browser-side, simulator issues stay attached to the downloadable, and rollout or legal questions stay distinct from both."
>
{selectedSupportTopic ? (
<Section title="Selected help lane">
@ -978,6 +1062,14 @@ export function SupportPage() {
Email <a href={brandConfig.contact.emailHref}>{brandConfig.contact.email}</a> for account activation,
release enablement, pricing configuration, or deployment help.
</p>
<div className="button-row top-gap">
<Link className="button button--ghost" to="/help">
Open help center
</Link>
<Link className="button button--primary" to="/contact">
Open contact route
</Link>
</div>
</article>
</Section>
@ -1113,10 +1205,33 @@ export function ChangelogPage() {
/>
<MarketingShell
eyebrow="Release notes"
title="Recent public-facing HyperTwist changes."
lede="This page focuses on user-visible posture changes: browser operator access, package hardening, diagnostics, and distribution readiness."
title="Release notes you can actually use for rollout."
lede="This page now combines grouped release packets with the chronological feed so operators can understand what changed in the browser shell, what changed in the downloadable, and what changed in the release or legal lane without reading raw roadmap archaeology."
>
<Section
title="Recent release packets"
description="These grouped cards are the higher-signal public version of the release story: what changed, where it changed, and why it matters operationally."
>
<div className="timeline">
{releasePacketCards.map((entry) => (
<article key={`${entry.date}-${entry.version}`} className="timeline-entry">
<p className="timeline-entry__date">{entry.date}</p>
<p className="status-pill status-pill--info">{entry.category}</p>
<h3>{entry.version}</h3>
<ul className="list top-gap">
{entry.notes.map((note) => (
<li key={note}>{note}</li>
))}
</ul>
</article>
))}
</div>
</Section>
<Section
title="Detailed chronological feed"
description="The detailed feed keeps route-by-route and surface-by-surface chronology visible once you need the finer-grained public history."
>
<Section title="Latest changes">
<div className="timeline">
{changelogEntries.map((entry) => (
<article key={`${entry.date}-${entry.title}`} className="timeline-entry">

View file

@ -2,3 +2,4 @@ export * from './public-pages-marketing'
export * from './public-pages-features'
export * from './public-pages-commerce'
export * from './public-pages-launch'
export * from './public-pages-guides'

View file

@ -9,6 +9,16 @@
"footer": false,
"crawlable": true
},
{
"path": "/browser",
"label": "Browser",
"loaderTitle": "Browser access guide",
"loaderEyebrow": "Web version posture",
"loaderDescription": "Loading the browser-versus-downloadable boundary, protected dashboard handoff, and the current web-lane purpose.",
"nav": true,
"footer": true,
"crawlable": true
},
{
"path": "/features",
"label": "Features",
@ -35,6 +45,16 @@
"loaderTitle": "Resources",
"loaderEyebrow": "Public reference portal",
"loaderDescription": "Loading rollout-safe resources, simulator guidance, and current higher-dimensional operator references.",
"nav": false,
"footer": true,
"crawlable": true
},
{
"path": "/help",
"label": "Help Center",
"loaderTitle": "Help center",
"loaderEyebrow": "Operator knowledge base",
"loaderDescription": "Loading onboarding, control truth, browser-to-desktop guidance, and rollout-safe troubleshooting.",
"nav": true,
"footer": true,
"crawlable": true
@ -66,7 +86,7 @@
"loaderEyebrow": "Public manual",
"loaderDescription": "Loading the feature-registry-backed manual, rollout doctrine, and browser-versus-desktop usage guide.",
"nav": false,
"footer": false,
"footer": true,
"crawlable": true
},
{
@ -76,7 +96,17 @@
"loaderEyebrow": "Operator help lane",
"loaderDescription": "Loading rollout guidance, account and entitlement help, and browser-to-desktop escalation routes.",
"nav": false,
"footer": false,
"footer": true,
"crawlable": true
},
{
"path": "/contact",
"label": "Contact",
"loaderTitle": "Contact HyperTwist",
"loaderEyebrow": "Human help lane",
"loaderDescription": "Loading operator contact paths, escalation packets, and release-aware support follow-through.",
"nav": false,
"footer": true,
"crawlable": true
},
{
@ -86,7 +116,7 @@
"loaderEyebrow": "Public release history",
"loaderDescription": "Loading recent browser, package, control-boundary, and rollout changes from the active shipping lane.",
"nav": false,
"footer": false,
"footer": true,
"crawlable": true
},
{

View file

@ -4,13 +4,16 @@ import { GeneralPageLoader } from '../components/ui/Skeletons'
import { publicRouteRegistry, type PublicRouteDefinition } from '../public-route-registry'
const HomeLanding = lazy(() => import('../pages/public-pages-marketing').then((m) => ({ default: m.HomeLanding })))
const BrowserExperiencePage = lazy(() => import('../pages/public-pages-guides').then((m) => ({ default: m.BrowserExperiencePage })))
const FeaturesPage = lazy(() => import('../pages/public-pages-features').then((m) => ({ default: m.FeaturesPage })))
const AboutPage = lazy(() => import('../pages/public-pages-marketing').then((m) => ({ default: m.AboutPage })))
const ResourcesPage = lazy(() => import('../pages/public-pages-marketing').then((m) => ({ default: m.ResourcesPage })))
const HelpCenterPage = lazy(() => import('../pages/public-pages-guides').then((m) => ({ default: m.HelpCenterPage })))
const GettingStartedPage = lazy(() => import('../pages/public-pages-marketing').then((m) => ({ default: m.GettingStartedPage })))
const LaunchStatusPage = lazy(() => import('../pages/public-pages-launch').then((m) => ({ default: m.LaunchStatusPage })))
const DocsPage = lazy(() => import('../pages/public-pages-marketing').then((m) => ({ default: m.DocsPage })))
const SupportPage = lazy(() => import('../pages/public-pages-marketing').then((m) => ({ default: m.SupportPage })))
const ContactPage = lazy(() => import('../pages/public-pages-guides').then((m) => ({ default: m.ContactPage })))
const ChangelogPage = lazy(() => import('../pages/public-pages-marketing').then((m) => ({ default: m.ChangelogPage })))
const PricingPage = lazy(() => import('../pages/public-pages-commerce').then((m) => ({ default: m.PricingPage })))
const DownloadPage = lazy(() => import('../pages/public-pages-commerce').then((m) => ({ default: m.DownloadPage })))
@ -23,13 +26,16 @@ const RegisterPage = lazy(() => import('../pages/auth-pages').then((m) => ({ def
const publicRouteElements: Record<string, ReactNode> = {
'/': <HomeLanding />,
'/browser': <BrowserExperiencePage />,
'/features': <FeaturesPage />,
'/about': <AboutPage />,
'/resources': <ResourcesPage />,
'/help': <HelpCenterPage />,
'/getting-started': <GettingStartedPage />,
'/launch-status': <LaunchStatusPage />,
'/docs': <DocsPage />,
'/support': <SupportPage />,
'/contact': <ContactPage />,
'/changelog': <ChangelogPage />,
'/pricing': <PricingPage />,
'/download': <DownloadPage />,

View file

@ -930,8 +930,10 @@ export const resourceCollections = [
title: 'Product truth',
items: [
'Feature registry-backed descriptions only',
'Dedicated browser guide for the public web-version-versus-downloadable boundary',
'Dedicated getting-started route for the first real browser-to-desktop operator journey',
'Dedicated launch-status route for the canonical preview-versus-launch authority surface',
'Dedicated help-center route for product-safe onboarding and troubleshooting',
'Public feature atlas for the real browser-versus-desktop product split',
'Roadmap-honest separation between shipped and retained capability',
'Release notes that surface what actually landed',
@ -983,12 +985,257 @@ export const resourceCollections = [
items: [
'Auth fallback posture and mixed-mode recovery guidance',
'Release-authority fallback without raw package-delivery overclaim',
'Direct contact route for operator, rollout, pricing, and legal follow-through questions',
'Account, package, runtime, and compliance issue separation',
'Operator-safe next steps when browser authority is degraded',
],
},
] as const
export const browserPurposeCards = [
{
title: 'Use the browser for access, release, and rollout posture',
description: 'The browser lane owns the work that should stay inspectable outside the simulator.',
bullets: [
'Open public pages for product research, pricing, release notes, legal notices, and launch-readiness posture.',
'Use the protected browser dashboard for sign-in, entitlement, billing, protected downloads, and desktop-link pairing.',
'Keep rollout, purchase, and legal-follow-through work on the web so the simulator is not forced to become a storefront or auth shell.',
],
},
{
title: 'Use the browser for product-safe guidance and onboarding',
description: 'The web version is strong when the job is explanation, orientation, or operator coordination rather than simulator execution.',
bullets: [
'Use the public docs, help, resources, and support routes as the current operator manual and rollout guide.',
'Review first-launch guidance, control truth, package proof, and support lanes before deeper deployment or training work.',
'Use the browser shell when a studio or buyer needs to understand what is real today without opening the native runtime first.',
],
},
{
title: 'Use the browser after install when account state changes',
description: 'The browser remains part of the product after the desktop runtime is installed, but for bounded reasons.',
bullets: [
'Return to the browser for account changes, plan changes, desktop-link refresh, protected notices, release-manifest review, and support escalation.',
'Keep browser issues separated from native runtime issues so support can diagnose the correct surface quickly.',
'Treat the browser as the operator and distribution shell around the downloadable simulator, not as a hidden second simulator.',
],
},
] as const
export const browserLimitCards = [
{
title: 'What the browser version does not currently do',
description: 'The web lane is intentionally narrower and materially less powerful for the core simulator job.',
bullets: [
'It does not own package-validated training behavior, replay execution, or the higher-dimensional packaged family maps.',
'It does not own low-latency native input, device/runtime integration, or the dedicated Unreal session and scene surfaces that power the downloadable.',
'It does not own finished OpenXR/controller runtime behavior, user-facing rebinding, or packaged controller validation.',
],
},
{
title: 'Why the downloadable is the primary product',
description: 'The downloadable stays primary because that is where the serious simulator work actually lives.',
bullets: [
'The desktop runtime owns recognition, correction closure, replay, coaching, analytics, and genuine session continuity.',
'It owns the current dedicated `Magic120Cell` and `MagicCube5D` runtime-state, projection, persistence, and training-map execution lanes.',
'It is also the current authority for packaged proof, native diagnostics, control roster truth, and serious study sessions.',
],
},
{
title: 'When browser-only use is still worthwhile',
description: 'The website is not superfluous just because it is narrower.',
bullets: [
'Use it for product evaluation, account access, protected release posture, billing, notices, help, and launch-readiness review.',
'Use it when a team needs product-safe explanation, public references, or rollout coordination without opening the simulator.',
'Use it as the bounded bridge into the desktop runtime rather than as a lesser substitute for the simulator itself.',
],
},
] as const
export const browserWorkflowTracks = [
{
title: '1. Start on the web before you install anything',
description: 'The first job is understanding release posture and choosing the right operator path.',
steps: [
'Review launch status, pricing, and download posture on the public site.',
'Open docs, help, or resources if the team still needs rollout-safe explanation of the product topology.',
'Choose the correct platform and plan posture before you cross into the protected browser shell.',
],
},
{
title: '2. Use the protected browser shell for account-aware follow-through',
description: 'The browser becomes stronger after sign-in, but still stays bounded to account and release work.',
steps: [
'Sign in, review account and entitlement posture, and generate a desktop-link token when needed.',
'Use protected downloads and notices instead of expecting anonymous public pages to expose raw delivery authority.',
'Keep the browser focused on release, billing, pairing, and rollout posture rather than simulator execution.',
],
},
{
title: '3. Hand off to the downloadable for the real simulator',
description: 'The browser flow succeeds when it leads cleanly into the desktop runtime instead of pretending to replace it.',
steps: [
'Install the package-validated desktop build and complete the bounded browser-to-desktop handoff.',
'Use the desktop runtime for actual training, higher-dimensional work, replay, and diagnostics.',
'Return to the browser later only when account, notices, rollout, or support context becomes the next real concern.',
],
},
] as const
export const puzzleCatalogCards = [
{
title: 'Classic-cube practice and timing',
description: 'The downloadable already owns the current day-to-day solving lane for serious training use.',
bullets: [
'Classic timer, scramble, hints, mode switching, voice shortcuts, and replay-aware practice already ship.',
'The public control truth is literal today: the shipped `classic-wca-keyboard/v1` profile plus click/touch, orbit, zoom, hint, and hold-to-talk behavior.',
'This is the fastest way to verify that a fresh install matches the current public product story.',
],
},
{
title: 'Recognition, reconstruction, and solve guidance',
description: 'HyperTwist already treats physical-cube intake and correction closure as real first-party product work.',
bullets: [
'Use the desktop runtime for bounded capture, browser-assisted recognition, manual correction closure, and solve-guidance readout.',
'The browser shell helps operators reach this workflow, but the actual reconstruction authority stays in the native runtime.',
'This keeps physical practice and analytical follow-through inside one coherent training system.',
],
},
{
title: 'Replay, coaching, and analytics',
description: 'The downloadable also owns session review, training continuity, and operator-facing evidence.',
bullets: [
'Replay capture, coaching review, local leaderboard persistence, diagnostics, and operator evidence already ship.',
'These surfaces are part of the native runtime, not detached browser widgets pretending to be simulator parity.',
'This is one of the clearest reasons the downloadable remains much more powerful than the web lane.',
],
},
{
title: 'Magic120Cell packaged runtime',
description: 'HyperTwist already owns a real dedicated higher-dimensional family lane in the downloadable.',
bullets: [
'The desktop runtime owns live `Magic120Cell` session surfaces, scene surfaces, symmetry/focus posture, and persisted selector continuity.',
'Operators can inspect session, interactive-scene, persistence-boundary, and state-semantics ownership directly in native diagnostics.',
'This lane is described on the public site, but it is only executed in the downloadable runtime.',
],
},
{
title: 'MagicCube5D packaged runtime',
description: 'The downloadable already carries real 5D runtime ownership instead of just broad capability claims.',
bullets: [
'Use the dedicated `MagicCube5D` map for projection-distance, stereo, focus, and face-visibility study inside the native runtime.',
'Native diagnostics already expose the owning session, interactive-scene, persistence, and state-semantics seams for this family too.',
'The browser can document and coordinate this lane, but it does not replace the downloadable that executes it.',
],
},
{
title: 'MagicTile embedded-browser lane',
description: 'HyperTwist also carries a bounded non-Euclidean lane, but it is still intentionally hosted inside the desktop product.',
bullets: [
'The current live `MagicTile` posture runs through the embedded browser host inside Unreal rather than through the public website.',
'State bridge, scramble normalization, and timer continuity are already first-party owned around that host posture.',
'Native renderer widening remains an explicit gate, so the public product story stays honest about where this lane currently lives.',
],
},
] as const
export const audienceFitCards = [
{
title: 'New solvers',
description: 'The product already supports a guided early-training lane instead of only expert tooling.',
bullets: [
'Use classic timing, hints, solve guidance, and replay-backed review to build confidence from the start.',
'The website can explain the first-session path before the downloadable takes over for the real practice loop.',
],
},
{
title: 'Serious daily trainers',
description: 'This is the current core audience for the desktop runtime.',
bullets: [
'Recognition, replay, coaching, diagnostics, and continuity are already designed to support repeated deliberate practice.',
'The browser lane stays useful around that work for release posture, account access, and support-safe coordination.',
],
},
{
title: 'Hypercubers and topology-focused learners',
description: 'HyperTwist is already unusual in that it treats higher-dimensional work as a real shipping lane.',
bullets: [
'Dedicated `Magic120Cell`, `MagicCube5D`, and bounded `MagicTile` posture are public, truthful, and source-backed today.',
'The downloadable remains essential here because the higher-dimensional runtime ownership is not a browser claim.',
],
},
{
title: 'Studios, educators, and rollout owners',
description: 'The website matters most for teams that need distribution, launch, and support posture before training sessions begin.',
bullets: [
'Pricing, notices, support, launch status, docs, help, and browser-to-desktop handoff are deliberate operator surfaces.',
'This is the strongest reason the browser lane is still worth keeping even though the downloadable remains the main product.',
],
},
] as const
export const helpCenterCards = [
{
title: 'Account, access, and protected downloads',
description: 'Use the help center when the next task is getting into the right browser or release lane safely.',
bullets: [
'Choose the right public route, preserve the requested platform through sign-in, and use the protected dashboard for entitlement-aware delivery.',
'Keep sign-in, release, and desktop-link questions attached to the browser shell instead of flattening them into simulator bugs.',
],
},
{
title: 'First launch and desktop verification',
description: 'The help center should also explain what a good first packaged session looks like.',
bullets: [
'Verify package proof, release notes, the shipped control roster, and the classic-cube lane before broader rollout.',
'Confirm the higher-dimensional family you plan to use instead of inferring readiness from broad marketing copy alone.',
],
},
{
title: 'Controls, settings, and current XR truth',
description: 'The current input story is strong, but it is bounded and should be taught honestly.',
bullets: [
'Keyboard, mouse, touch, camera, immersive settings, selector continuity, and dedicated-family view ownership are already real.',
'The current desktop-hosted OpenXR/controller widening boundary remains explicit No-Go until dedicated runtime owners, rebinding ownership, and Windows packaged controller proof all exist together.',
],
},
{
title: 'Rollout, pricing, notices, and release follow-through',
description: 'Help is not only for runtime bugs. It is also for distribution-safe operation.',
bullets: [
'Use pricing, launch status, notices, and corresponding-source guidance together when a team is evaluating public rollout.',
'Keep commercial, legal, release, and simulator questions separated so operators can move faster with less confusion.',
],
},
] as const
export const contactChannelCards = [
{
title: 'Operator support',
description: 'Use this when a real user session is blocked by account, entitlement, or rollout issues.',
bullets: [
`Contact ${brandConfig.contact.email} for access, release enablement, desktop-link pairing trouble, or protected browser-lane follow-through.`,
'Include the exact route, plan posture, requested platform, and whether the failure is public, protected, or native.',
],
},
{
title: 'Runtime issue reporting',
description: 'Use this when the downloadable itself behaves unexpectedly.',
bullets: [
'Name the affected lane: classic cube, recognition, replay/coaching, `Magic120Cell`, `MagicCube5D`, or `MagicTile`.',
'Include build/channel context, control posture, and whether the issue is a real shipped regression or a still-explicit unfinished XR/controller expectation.',
],
},
{
title: 'Studio rollout and commercial contact',
description: 'Use this when the question is deployment, pricing, or broader rollout readiness rather than one operator session.',
bullets: [
'Bundle plan, platform, launch posture, notices, and release expectations together so commercial follow-through stays attached to real package and legal truth.',
'Use this lane for production-oriented training programs, deployment review, and release-safe distribution planning.',
],
},
] as const
export const publicManualRouteAtlasCards = [
{
title: 'Home',
@ -1000,6 +1247,16 @@ export const publicManualRouteAtlasCards = [
'Points operators toward getting started, pricing, download, and the protected dashboard without overclaiming browser parity.',
],
},
{
title: 'Browser access guide',
route: '/browser',
description: 'Open this route when you need the cleanest public explanation of what the web version is for, why it is intentionally narrower, and when to move into the downloadable.',
bullets: [
'Explains the browser shell as a real operator/distribution surface instead of a half-promised simulator.',
'Shows what the browser version does well, what it deliberately does not do, and why the downloadable remains the primary product.',
'Keeps account, protected dashboard, and desktop handoff decisions visible in one place.',
],
},
{
title: 'Feature atlas',
route: '/features',
@ -1040,6 +1297,16 @@ export const publicManualRouteAtlasCards = [
'Acts as the shortest handoff-friendly onboarding surface on the public site.',
],
},
{
title: 'Help Center',
route: '/help',
description: 'Open this route when you need product-safe troubleshooting, onboarding guidance, control truth, or rollout-safe answers before escalating into support.',
bullets: [
'Collects first-launch, controls, browser-to-desktop handoff, and release-surface guidance into one knowledge-base style route.',
'Separates help-center guidance from direct support escalation so operators can self-serve first without losing product truth.',
'Connects questions back to docs, support, download, and the protected dashboard when a live next step exists.',
],
},
{
title: 'Launch status',
route: '/launch-status',
@ -1070,6 +1337,16 @@ export const publicManualRouteAtlasCards = [
'Mirrors the same browser-versus-desktop split so support does not soften product truth.',
],
},
{
title: 'Contact',
route: '/contact',
description: 'Open this route when a human contact path, escalation expectation, or issue-report packet is the next real step.',
bullets: [
'Provides the direct operator contact lane alongside what information to include for faster diagnosis.',
'Keeps runtime, rollout, account, and legal/commercial contacts separated instead of flattening them together.',
'Links back to support topics, download posture, and public/protected route ownership as needed.',
],
},
{
title: 'Pricing',
route: '/pricing',
@ -1142,6 +1419,69 @@ export const publicManualRouteAtlasCards = [
},
] as const
export const releasePacketCards = [
{
date: 'June 30, 2026',
version: 'Public manual deepening packet',
category: 'Website, onboarding, and operator documentation',
notes: [
'Broadened the public and offline operator manual so the website now explains concrete desktop workflows, controls, higher-dimensional families, and release follow-through instead of only broad topology prose.',
'Made the browser-versus-desktop split explicit on the highest-traffic public routes so teams no longer have to infer why the downloadable remains the primary simulator.',
'Kept the current XR/controller boundary visible while strengthening what the public site can honestly claim today.',
],
},
{
date: 'June 29, 2026',
version: 'Validation and package-proof refresh',
category: 'Release integrity and package evidence',
notes: [
'Revalidated the exact-source browser surface and refreshed the packaged higher-dimensional proof so public release pages stay attached to current native evidence.',
'Reran owned source and browser validation without widening product scope and kept the live preview lane green.',
'Preserved the rule that native package proof, browser release posture, and legal-distribution follow-through move together.',
],
},
{
date: 'June 28, 2026',
version: 'Native diagnostics truth packet',
category: 'Controls, settings, and higher-dimensional ownership',
notes: [
'Tightened native control, settings, continuity, and active-scene diagnostics so operators can see the exact higher-dimensional ownership seams that are live today.',
'Improved public and protected manual language to reflect those stronger native proofs instead of leaving them buried inside internal diagnostics only.',
'Strengthened the public route atlas so operators can navigate documentation, help, release, and legal surfaces as one coherent product shell.',
],
},
{
date: 'June 27, 2026',
version: 'Launch-authority and onboarding packet',
category: 'Public routes, protected routes, and browser shell startup',
notes: [
'Added dedicated public launch-status and getting-started routes plus stronger protected launch authority so rollout truth stopped depending on scattered callouts.',
'Improved browser auth behavior, startup loading posture, and public/protected route continuity without implying browser simulator parity.',
'Turned the first real desktop-session path into a clearer public manual route instead of burying it across unrelated pages.',
],
},
{
date: 'June 24 to June 25, 2026',
version: 'Native XR-boundary and control-roster packet',
category: 'Desktop control truth and public honesty',
notes: [
'Promoted the literal shipped control roster, settings ownership, and higher-dimensional state seams into stable native/operator surfaces.',
'Kept the desktop-hosted OpenXR/controller widening decision explicit, including the reopen requirements for dedicated runtime owners, rebinding ownership, and Windows packaged controller validation.',
'Mirrored that truth into the public manual, pricing, download, and support surfaces so the website cannot overclaim what the downloadable has not yet finished.',
],
},
{
date: 'June 18 to June 23, 2026',
version: 'Packaging, browser shell, and MagicTile hardening packet',
category: 'Phase 10 package integrity plus bounded browser/runtime expansion',
notes: [
'Closed package and integration hardening while keeping the embedded browser shell, release notes, and packaged-proof story aligned.',
'Hardened MagicTile behavior proof without reopening native renderer widening and preserved the browser-host decision as the current honest shipping posture.',
'Expanded the public site into a bounded operator/distribution surface around the downloadable rather than a replacement for it.',
],
},
] as const
export const changelogEntries = [
{
date: 'June 30, 2026',

View file

@ -94,12 +94,20 @@ img {
align-items: center;
justify-content: space-between;
gap: 1.5rem;
padding: 1.25rem clamp(1rem, 3vw, 2.25rem);
border-bottom: 1px solid var(--ht-border);
padding: 1.35rem clamp(1rem, 3vw, 2.5rem);
border: 1px solid rgba(255, 255, 255, 0.04);
backdrop-filter: blur(18px);
background: rgba(8, 12, 22, 0.42);
background:
radial-gradient(circle at top, rgba(84, 203, 255, 0.08), transparent 46%),
linear-gradient(180deg, rgba(8, 12, 22, 0.82), rgba(10, 16, 30, 0.72));
position: sticky;
top: 0;
margin: 0.75rem auto 0;
width: min(1260px, calc(100vw - 2rem));
border-radius: 1.6rem;
box-shadow:
inset 0 1px 0 rgba(255, 255, 255, 0.04),
0 22px 60px rgba(0, 0, 0, 0.22);
}
.brand-mark {
@ -111,10 +119,15 @@ img {
.brand-mark__image,
.app-sidebar__brand-image {
width: 3rem;
height: 3rem;
width: 5.4rem;
height: 5.4rem;
object-fit: contain;
filter: drop-shadow(0 0 18px rgba(84, 203, 255, 0.2));
filter: drop-shadow(0 0 30px rgba(84, 203, 255, 0.24));
}
.brand-mark__copy {
display: grid;
gap: 0.2rem;
}
.brand-mark strong,
@ -122,6 +135,8 @@ img {
display: block;
font-family: var(--font-display);
letter-spacing: 0.02em;
font-size: clamp(1.35rem, 2vw, 1.7rem);
line-height: 0.96;
}
.brand-mark small,
@ -132,6 +147,11 @@ img {
color: var(--ht-muted);
}
.brand-mark small {
font-size: 0.98rem;
max-width: 29rem;
}
.site-nav,
.site-header__actions,
.button-row,
@ -152,6 +172,11 @@ img {
justify-content: center;
}
.site-header__actions {
flex-wrap: wrap;
justify-content: flex-end;
}
.button-row {
flex-wrap: wrap;
}
@ -165,6 +190,7 @@ img {
padding: 0.7rem 0.95rem;
border-radius: 999px;
color: var(--ht-muted);
font-weight: 600;
transition: 160ms ease;
}
@ -182,12 +208,13 @@ img {
justify-content: center;
gap: 0.5rem;
min-height: 2.8rem;
padding: 0.8rem 1.1rem;
padding: 0.82rem 1.18rem;
border-radius: 999px;
border: 1px solid transparent;
font-weight: 700;
letter-spacing: 0.01em;
cursor: pointer;
transition: transform 160ms ease, background 160ms ease, border-color 160ms ease, color 160ms ease;
transition: transform 160ms ease, background 160ms ease, border-color 160ms ease, color 160ms ease, box-shadow 160ms ease;
}
.button:hover {
@ -197,10 +224,11 @@ img {
.button--primary {
background: linear-gradient(120deg, var(--ht-amber), #ffc788);
color: #09111d;
box-shadow: 0 14px 34px rgba(247, 178, 103, 0.24);
}
.button--ghost {
background: rgba(255, 255, 255, 0.02);
background: rgba(255, 255, 255, 0.04);
border-color: var(--ht-border);
color: var(--ht-text);
}
@ -217,13 +245,35 @@ img {
}
.page-main {
width: min(1180px, calc(100vw - 2rem));
width: min(1260px, calc(100vw - 2rem));
margin: 0 auto;
padding-bottom: 4rem;
}
.page-hero {
padding: clamp(2.25rem, 6vw, 5rem) 0 1.5rem;
position: relative;
overflow: hidden;
margin-top: 1rem;
padding: clamp(2.25rem, 6vw, 4.6rem) clamp(1.2rem, 3vw, 2.2rem) 1.75rem;
border: 1px solid var(--ht-border);
border-radius: 2rem;
background:
radial-gradient(circle at top, rgba(84, 203, 255, 0.14), transparent 42%),
radial-gradient(circle at 82% 18%, rgba(247, 178, 103, 0.12), transparent 28%),
linear-gradient(180deg, rgba(10, 16, 30, 0.88), rgba(7, 11, 20, 0.78));
box-shadow:
inset 0 1px 0 rgba(255, 255, 255, 0.05),
0 32px 90px rgba(0, 0, 0, 0.2);
}
.page-hero::before {
content: "";
position: absolute;
inset: 0;
pointer-events: none;
background:
linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.08), transparent);
mask-image: linear-gradient(180deg, rgba(255,255,255,0.5), transparent 72%);
}
.eyebrow {
@ -258,6 +308,13 @@ img {
word-break: break-word;
}
.page-hero__lede {
position: relative;
z-index: 1;
max-width: 60rem;
font-size: clamp(1rem, 1.3vw, 1.16rem);
}
.hero-panel,
.page-section,
.site-footer,
@ -273,18 +330,26 @@ img {
border: 1px solid var(--ht-border);
background: var(--ht-surface);
border-radius: 1.5rem;
box-shadow: 0 24px 90px rgba(0, 0, 0, 0.15);
box-shadow:
inset 0 1px 0 rgba(255, 255, 255, 0.04),
0 24px 90px rgba(0, 0, 0, 0.15);
backdrop-filter: blur(18px);
}
.hero-panel {
position: relative;
overflow: hidden;
padding: clamp(1.25rem, 3vw, 2rem);
background:
radial-gradient(circle at top left, rgba(84, 203, 255, 0.12), transparent 32%),
radial-gradient(circle at bottom right, rgba(247, 178, 103, 0.1), transparent 28%),
var(--ht-surface);
}
.hero-grid {
display: grid;
grid-template-columns: minmax(0, 1.35fr) minmax(300px, 0.85fr);
gap: 1.5rem;
gap: 1.8rem;
align-items: center;
}
@ -294,6 +359,8 @@ img {
}
.hero-visual-card {
position: relative;
overflow: hidden;
padding: 1.2rem;
background:
radial-gradient(circle at top, rgba(84, 203, 255, 0.18), transparent 42%),
@ -319,6 +386,9 @@ img {
.metric-card {
flex: 1 1 210px;
padding: 1rem 1.1rem;
background:
linear-gradient(180deg, rgba(255, 255, 255, 0.03), rgba(255, 255, 255, 0.01)),
rgba(10, 16, 30, 0.58);
}
.metric-card strong {
@ -333,7 +403,7 @@ img {
.page-section {
margin-top: 1.4rem;
padding: clamp(1.25rem, 3vw, 1.85rem);
padding: clamp(1.3rem, 3vw, 1.95rem);
}
.section-heading {
@ -346,6 +416,7 @@ img {
.timeline-entry h3 {
margin: 0;
font-family: var(--font-display);
line-height: 1.04;
}
.card-grid,
@ -368,6 +439,17 @@ img {
.callout,
.timeline-entry {
padding: 1.15rem;
transition: transform 180ms ease, border-color 180ms ease, box-shadow 180ms ease;
}
.card:hover,
.callout:hover,
.timeline-entry:hover {
transform: translateY(-2px);
border-color: rgba(247, 178, 103, 0.26);
box-shadow:
inset 0 1px 0 rgba(255, 255, 255, 0.04),
0 28px 84px rgba(0, 0, 0, 0.18);
}
.card--selected {
@ -455,7 +537,9 @@ img {
padding: 1.2rem;
border: 1px solid var(--ht-border);
border-radius: 1.3rem;
background: rgba(10, 16, 30, 0.56);
background:
linear-gradient(180deg, rgba(255, 255, 255, 0.02), transparent 24%),
rgba(10, 16, 30, 0.56);
}
.feature-band__card--link {
@ -510,6 +594,9 @@ img {
.timeline-entry {
border-left: 4px solid var(--ht-amber);
background:
linear-gradient(180deg, rgba(247, 178, 103, 0.04), transparent 26%),
var(--ht-surface);
}
.timeline-entry__date {
@ -520,15 +607,31 @@ img {
}
.site-footer {
width: min(1180px, calc(100vw - 2rem));
width: min(1260px, calc(100vw - 2rem));
margin: 1rem auto 2rem;
padding: 1.2rem;
padding: 1.35rem;
display: grid;
gap: 0.9rem;
gap: 1.1rem;
}
.site-footer__grid {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: 1rem;
}
.site-footer__group {
display: grid;
gap: 0.7rem;
}
.site-footer__links {
flex-wrap: wrap;
flex-direction: column;
}
.site-footer__contact {
color: var(--ht-text);
}
.site-footer__note {
@ -816,6 +919,10 @@ code {
.app-main-shell {
padding: 0 0.8rem 0.8rem;
}
.site-footer__grid {
grid-template-columns: 1fr;
}
}
@media (max-width: 720px) {
@ -827,6 +934,7 @@ code {
.site-header {
padding-inline: 0.8rem;
border-radius: 1.25rem;
}
.page-main {
@ -840,6 +948,11 @@ code {
flex-direction: column;
}
.brand-mark__image {
width: 4.4rem;
height: 4.4rem;
}
.button-row > * {
width: 100%;
}