<script>
	import favicon from '$lib/assets/favicon.svg';
	import { browser } from '$app/environment';
	import { page } from '$app/stores'; // current route, used to hide the count pill on /archive
	import GlobalCountPill from '$lib/components/GlobalCountPill.svelte';

	let { children } = $props();

	// --- one-time opening ritual ---------------------------------------
	// `ritualMounted` controls whether the overlay exists in the DOM at all.
	// Starting it at `false` means SSR renders nothing (avoiding a flash of
	// the overlay on every page before we've even checked localStorage),
	// and it only ever becomes `true` in the browser, once, for first-time
	// visitors.
	let ritualMounted = $state(false);
	// `ritualVisible` drives the CSS opacity transition (fade in/out).
	// Toggling this class is what actually animates the overlay; the timers
	// below just flip it true -> false at the right moments.
	let ritualVisible = $state(false);

	$effect(() => {
		if (!browser) return; // localStorage doesn't exist during SSR

		// the flag that marks "this device has already seen the ritual"
		const hasVisited = localStorage.getItem('overheard_has_visited');
		if (hasVisited) return; // not the first visit - never mount the overlay

		// Mark the device as visited immediately (rather than after the
		// animation finishes). If we waited until the end, a user who closes
		// the tab partway through the ritual would see it again on their
		// next visit - setting the flag up front guarantees "only once ever".
		localStorage.setItem('overheard_has_visited', 'true');

		ritualMounted = true;

		// Fade-in timing: wait one animation frame so the overlay first
		// paints at opacity 0 (its initial CSS state), then flip
		// `ritualVisible` to true so the opacity transition to 1 actually
		// animates instead of snapping straight to visible.
		const fadeInFrame = requestAnimationFrame(() => {
			ritualVisible = true;
		});

		// Total sequence ~5s: 1.2s fade in + 2.6s hold + 1.2s fade out.
		const fadeInMs = 1200;
		const holdMs = 2600;
		const fadeOutMs = 1200;

		// After the fade-in finishes and the hold completes, start fading out.
		const fadeOutTimer = setTimeout(() => {
			ritualVisible = false;
		}, fadeInMs + holdMs);

		// Once the fade-out transition has finished, unmount the overlay
		// entirely (rather than just leaving it hidden via CSS/opacity:0).
		// A hidden-but-present full-screen element would still sit in the
		// DOM at a high z-index and could intercept clicks/taps meant for
		// the map underneath, so we remove it completely once it's invisible.
		const removeTimer = setTimeout(() => {
			ritualMounted = false;
		}, fadeInMs + holdMs + fadeOutMs);

		// cleanup if the component is destroyed mid-sequence
		return () => {
			cancelAnimationFrame(fadeInFrame);
			clearTimeout(fadeOutTimer);
			clearTimeout(removeTimer);
		};
	});
</script>

<svelte:head>
	<link rel="icon" href={favicon} />
</svelte:head>

<!-- Map/geolocation in {@render children()} starts loading immediately and
     in parallel - this overlay just sits on top of it visually, it doesn't
     block or delay anything underneath. -->
{@render children()}

<!-- global "memory counter" pill, top-right on every page EXCEPT /archive and
     /stampbook - both are the user's own private views (their messages, their
     earned stamps), so the global "everyone, everywhere" count would feel out
     of place there (see GlobalCountPill.svelte for the pill itself). -->
{#if $page.url.pathname !== '/archive' && $page.url.pathname !== '/stampbook'}
	<GlobalCountPill />
{/if}

<!-- one-time opening ritual overlay, first-ever visit only -->
{#if ritualMounted}
	<div class="ritual-overlay" class:visible={ritualVisible} aria-hidden="true">
		<p class="ritual-text">Some things are only true if you're standing here.</p>
	</div>
{/if}

<!-- ===================================================================
     GLOBAL TEXTURE OVERLAY (start)
     A subtle parchment/paper grain over the ENTIRE app (was previously
     just over the map - moved here per request). pointer-events: none
     so it never blocks clicks/taps anywhere in the UI.
     TO REMOVE: delete this <div> and the ".global-texture-overlay" CSS
     block below - nothing else depends on either.
     =================================================================== -->
<div class="global-texture-overlay" aria-hidden="true"></div>
<!-- GLOBAL TEXTURE OVERLAY (end) -->

<style>
	/* full-screen opening ritual overlay - soft cream background matching
	   the app's pastel palette, sits above everything while it's visible */
	.ritual-overlay {
		position: fixed;
		inset: 0;
		background: #f9f7f4;
		display: flex;
		align-items: center;
		justify-content: center;
		z-index: 1000;
		/* starts invisible; .visible below fades it in/out over 1.2s.
		   the same transition is reused for fade-out since both are just
		   opacity changes between 0 and 1 */
		opacity: 0;
		transition: opacity 1.2s ease;
	}

	.ritual-overlay.visible {
		opacity: 1;
	}

	.ritual-text {
		/* same serif used for the loading/error text in +page.svelte, for a
		   calm, contemplative feel */
		font-family: Georgia, 'Times New Roman', Times, serif;
		font-size: 1.15rem;
		color: #555; /* muted dark grey, not pure black */
		letter-spacing: 0.08em;
		text-align: center;
		line-height: 1.6;
		margin: 0;
		padding: 0 2rem;
	}

	@media (min-width: 768px) {
		.ritual-text {
			font-size: 1.35rem;
		}
	}

	/* =================================================================
	   GLOBAL TEXTURE OVERLAY (start) - see matching comment in the
	   markup above for removal instructions.
	   - position: fixed + inset: 0 covers the full viewport, regardless
	     of scroll position, on every page.
	   - z-index: 2000 sits above the opening ritual (1000) and every
	     other UI element (all of which use z-index 200 or less) - this
	     is intentional, since the texture is purely decorative and
	     pointer-events: none means it never intercepts input even when
	     it's the topmost element.
	   - mix-blend-mode: multiply + opacity: 0.08 + the warm #ecdfc4
	     background-color gently "ages" whatever's underneath (map,
	     white panels, sheets) without hiding any content. opacity
	     back down to 0.08 - the stronger feColorMatrix/tile-size
	     values below (tuned while testing at 0.10) keep the grain
	     from disappearing entirely at this lower opacity.
	   - background-image is the same inline SVG <feTurbulence> +
	     <feColorMatrix> grain used previously on just the map.
	     feColorMatrix scale 3.5 / offset -1.6 and background-size
	     110px give the grain a faint but present texture even at
	     0.08 opacity. */
	.global-texture-overlay {
		position: fixed;
		inset: 0;
		z-index: 2000;
		pointer-events: none;
		opacity: 0.08;
		mix-blend-mode: multiply;
		background-color: #ecdfc4;
		background-image:
			url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='220' height='220'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch' result='noise'/%3E%3CfeColorMatrix in='noise' type='matrix' values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3.5 -1.6'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
		background-size: 110px 110px;
		background-repeat: repeat;
	}
	/* GLOBAL TEXTURE OVERLAY (end) */
</style>
