Add landing screen as the app's entry point

Introduce a simple, show-don't-tell entry screen that lowers the "what
counts as a protocol" barrier and frames the activity as a short journey:

- Lead line "Examine the protocols around you" over a rotating, cross-fading
  list of deliberately diverse examples (traffic, code, kitchens, ritual,
  governance, play)
- Prominent "Begin" CTA above a three-step path: Describe / Understand / Share
- "About the Bicorder" link opens the existing help modal

Shown on first arrival; returning users with a reading in progress skip
straight to the diagnostic (computed synchronously, no flash). Remove the
now-redundant inline description from the focused flow.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Nathan Schneider
2026-06-30 17:37:42 -06:00
parent fd556d967f
commit c571bf1c01
2 changed files with 247 additions and 6 deletions
+31 -6
View File
@@ -9,6 +9,7 @@
import FormRecommendation from './components/FormRecommendation.svelte';
import AnalysisTransitionBanner from './components/AnalysisTransitionBanner.svelte';
import HamburgerMenu from './components/HamburgerMenu.svelte';
import Landing from './components/Landing.svelte';
import { BicorderClassifier } from './bicorder-classifier';
// Load bicorder data and model from build-time constants
@@ -30,6 +31,32 @@
let refreshKey = 0; // Used to force component refresh in focused mode
let isHelpOpen = false;
// Show the landing screen on first arrival. Returning users who already have
// a reading in progress skip straight to the diagnostic. Computed
// synchronously (not in onMount) so the landing never flashes for them.
function hasReadingInProgress(): boolean {
if (typeof localStorage === 'undefined') return false;
try {
const saved = localStorage.getItem('bicorder-state');
if (!saved) return false;
const s = JSON.parse(saved);
const hasProtocol = !!s?.metadata?.protocol;
const hasValue = s?.diagnostic?.some(
(set: any) => set?.gradients?.some((g: any) => g?.value !== null && g?.value !== undefined)
);
return hasProtocol || hasValue;
} catch {
return false;
}
}
let started = hasReadingInProgress();
function startReading() {
started = true;
currentScreen = 0;
}
// Screen types
type Screen =
| { type: 'metadata' }
@@ -432,6 +459,9 @@
<HelpModal bind:isOpen={isHelpOpen} />
{#if !started}
<Landing on:begin={startReading} on:about={openHelp} />
{:else}
<main>
<div class="header">
<div class="header-left">
@@ -519,12 +549,6 @@
{:else}
<!-- FOCUSED MODE: Show one screen at a time -->
{#if currentScreen === 0}
<div class="description">
<p>A diagnostic tool for the study of protocols</p>
</div>
{/if}
<div class="focused-container">
{#if currentScreenData.type === 'metadata'}
<div class="focused-screen">
@@ -679,6 +703,7 @@
</div>
{/if}
</main>
{/if}
<style>
main {