{"release_id":"01a1c502-4ad1-0000-ec62-adc54d3c69aa","chunk_id":"01a1c502-4cf8-7952-b996-efd7bd5b223e","file":"60.FsW_gtxe.mjs","mappings":"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","names":["query","$.state","sort","PREF_KEY","activeTags","$.proxy","media","onMount","saved","$.set","t","ALBUM_TAGS","savedMedia","MEDIA_PREF_KEY","isAlbumMedia","hasTasteSignal","mediaCounts","$.derived","$$props","a","matchesMedia","selectMedia","m","shown","PAGE","trackAlbumMediaFilter","availableTags","TAGS_SHOWN","tagsOpen","rankedTags","unlocks","albums","$.get","x","y","shownTags","i","moreTags","toggleTag","active","trackAlbumTagFilter","tasteWeights","w","tasteTotal","tasteScore","score","filtered","asked","q","parseMediaQuery","sorted","b","visible","creatorCount","photoCount","hottest","SORT_OPTIONS","sortMenuOpen","sortMenuEl","sortLabel","o","selectSort","value","railEl","fadeLeft","fadeRight","isDesktop","updateRailFades","el","railMaskStyle","activeMode","mq","onMq","e","onDocClick","onKey","scrollToBrowse","main","$.first_child","fragment","div","section","div_1","div_2","a_1","$.child","div_3","span","span_1","span_2","span_3","span_4","span_5","section_1","root_1","div_4","$.sibling","album","div_5","root_2","AlbumRichCard","node_1","$.reset","$$value","$.template_effect","$.set_style","$.event","$$render","consequent","section_2","node","div_6","div_7","input","$.remove_input_defaults","AlbumMediaSwitch","node_2","div_8","button","span_6","svg","node_3","div_9","root_3","button_1","root_4","text_4","svg_1","root_5","$.append","$$anchor","consequent_1","$.set_attribute","$.set_text","$.delegated","consequent_2","div_10","root_6","$.each","node_6","button_2","root_7","text_5","$.set_class","$0","ALBUM_TAG_LABELS","button_3","root_8","text_6","button_4","root_9","consequent_3","consequent_4","button_5","root_10","consequent_5","consequent_6","div_11","node_5","node_9","div_12","root_12","button_6","span_7","consequent_7","p","root_13","consequent_8","section_3","div_13","AlbumHubChips","node_12","ALBUM_HUBS_BY_SIZE","section_4","div_14","step","div_15","root_14","span_8","h3","p_1","text_8","text_9","text_10","Footer","node_13","text"],"sources":["../../../../../../src/routes/albums/+page.svelte"],"sourcesContent":["<script lang=\"ts\">\n\timport { onMount } from 'svelte';\n\timport { activeMode } from '$lib/stores/activeMode';\n\timport AlbumRichCard from '$lib/components/album/AlbumRichCard.svelte';\n\timport { ALBUM_TAGS, ALBUM_TAG_LABELS, type AlbumTag } from '$lib/types/album-tags';\n\timport { trackAlbumMediaFilter, trackAlbumTagFilter } from '$lib/analytics';\n\timport {\n\t\tisAlbumMedia,\n\t\tmatchesMedia,\n\t\tMEDIA_PREF_KEY,\n\t\tparseMediaQuery,\n\t\ttype AlbumMedia\n\t} from '$lib/album-media';\n\timport AlbumMediaSwitch from '$lib/components/album/AlbumMediaSwitch.svelte';\n\timport Footer from '$lib/components/Footer.svelte';\n\timport { ALBUM_HUBS_BY_SIZE } from '$lib/album-hubs';\n\timport AlbumHubChips from '$lib/components/album/AlbumHubChips.svelte';\n\timport type { PageData } from './$types';\n\n\tlet { data }: { data: PageData } = $props();\n\n\tlet query = $state('');\n\tlet sort = $state<'foryou' | 'new' | 'popular' | 'price'>('new');\n\n\t// Tag filter — OR semantics (any selected tag matches): the catalog is\n\t// small, AND would empty out instantly. Chips only render for tags that\n\t// actually have inventory, so a chip can never produce an empty grid on\n\t// its own. Selection persists so a returning visitor lands pre-filtered.\n\tconst PREF_KEY = 'rmd_album_tags';\n\tlet activeTags = $state<AlbumTag[]>([]);\n\t// RAT-621: photos or videos, from what's in the album; kept like the chips.\n\tlet media = $state<AlbumMedia>('all');\n\tonMount(() => {\n\t\ttry {\n\t\t\tconst saved = JSON.parse(localStorage.getItem(PREF_KEY) ?? '[]');\n\t\t\tif (Array.isArray(saved)) activeTags = saved.filter((t) => ALBUM_TAGS.includes(t));\n\t\t\tconst savedMedia = localStorage.getItem(MEDIA_PREF_KEY);\n\t\t\tif (isAlbumMedia(savedMedia)) media = savedMedia;\n\t\t} catch {\n\t\t\t/* localStorage unavailable — chips still work, nothing persists */\n\t\t}\n\t\tif (hasTasteSignal) sort = 'foryou';\n\t});\n\tconst mediaCounts = $derived({\n\t\tall: data.items.length,\n\t\tvideos: data.items.filter((a) => matchesMedia(a, 'videos')).length,\n\t\tphotos: data.items.filter((a) => matchesMedia(a, 'photos')).length\n\t});\n\tfunction selectMedia(m: AlbumMedia) {\n\t\tif (m === media) return;\n\t\tmedia = m;\n\t\tshown = PAGE;\n\t\ttry {\n\t\t\tlocalStorage.setItem(MEDIA_PREF_KEY, m);\n\t\t} catch {\n\t\t\t/* ignore */\n\t\t}\n\t\ttrackAlbumMediaFilter(m, 'albums');\n\t}\n\tconst availableTags = $derived(\n\t\tALBUM_TAGS.filter((t) => data.items.some((a) => a.tags.includes(t)))\n\t);\n\t// The chips, most bought first: unlocks across the albums wearing the tag,\n\t// album count breaking ties. Six show; the rest open in place, and a chip\n\t// the viewer has on stays in view either way.\n\tconst TAGS_SHOWN = 6;\n\tlet tagsOpen = $state(false);\n\tconst rankedTags = $derived.by(() => {\n\t\tconst unlocks = new Map<string, number>();\n\t\tconst albums = new Map<string, number>();\n\t\tfor (const a of data.items)\n\t\t\tfor (const t of a.tags) {\n\t\t\t\tunlocks.set(t, (unlocks.get(t) ?? 0) + a.unlockCount);\n\t\t\t\talbums.set(t, (albums.get(t) ?? 0) + 1);\n\t\t\t}\n\t\treturn [...availableTags].sort(\n\t\t\t(x, y) =>\n\t\t\t\t(unlocks.get(y) ?? 0) - (unlocks.get(x) ?? 0) || (albums.get(y) ?? 0) - (albums.get(x) ?? 0)\n\t\t);\n\t});\n\tconst shownTags = $derived(\n\t\ttagsOpen ? rankedTags : rankedTags.filter((t, i) => i < TAGS_SHOWN || activeTags.includes(t))\n\t);\n\tconst moreTags = $derived(rankedTags.length - shownTags.length);\n\tfunction toggleTag(t: AlbumTag) {\n\t\tconst active = !activeTags.includes(t);\n\t\tactiveTags = active ? [...activeTags, t] : activeTags.filter((x) => x !== t);\n\t\tshown = PAGE;\n\t\ttry {\n\t\t\tlocalStorage.setItem(PREF_KEY, JSON.stringify(activeTags));\n\t\t} catch {\n\t\t\t/* ignore */\n\t\t}\n\t\ttrackAlbumTagFilter(t, active, 'chips');\n\t}\n\n\t// \"for you\" — client-side taste score: the chips the viewer picked (strong)\n\t// plus the tag profile of albums they've already unlocked (weaker). Only\n\t// offered/defaulted when there's any signal; otherwise 'new' stands.\n\tconst tasteWeights = $derived.by(() => {\n\t\tconst w = new Map<string, number>();\n\t\tfor (const a of data.items)\n\t\t\tif (a.unlocked && !a.isOwner) for (const t of a.tags) w.set(t, (w.get(t) ?? 0) + 1);\n\t\treturn w;\n\t});\n\tconst tasteTotal = $derived([...tasteWeights.values()].reduce((x, y) => x + y, 0));\n\tfunction tasteScore(a: (typeof data.items)[number]): number {\n\t\tlet score = 0;\n\t\tfor (const t of a.tags) {\n\t\t\tif (activeTags.includes(t as AlbumTag)) score += 2;\n\t\t\tif (tasteTotal > 0) score += (tasteWeights.get(t) ?? 0) / tasteTotal;\n\t\t}\n\t\treturn score;\n\t}\n\tconst hasTasteSignal = $derived(activeTags.length > 0 || tasteTotal > 0);\n\n\n\tconst filtered = $derived.by(() => {\n\t\t// \"hairy videos\": \"hairy\" in albums with clips (album-media.ts)\n\t\tconst { media: asked, text: q } = parseMediaQuery(query);\n\t\tconst list = data.items.filter((a) => {\n\t\t\tif (!matchesMedia(a, media) || !matchesMedia(a, asked)) return false;\n\t\t\tif (activeTags.length > 0 && !activeTags.some((t) => a.tags.includes(t))) return false;\n\t\t\tif (!q) return true;\n\t\t\treturn (\n\t\t\t\ta.title.toLowerCase().includes(q) ||\n\t\t\t\t(a.creator.nickname ?? '').toLowerCase().includes(q)\n\t\t\t);\n\t\t});\n\t\t// Server hands the payload back newest-first, so 'new' keeps that order.\n\t\tconst sorted = [...list];\n\t\tif (sort === 'popular') sorted.sort((a, b) => b.unlockCount - a.unlockCount);\n\t\telse if (sort === 'price') sorted.sort((a, b) => a.priceTokens - b.priceTokens);\n\t\t// stable sort: equal taste scores keep the server's newest-first order\n\t\telse if (sort === 'foryou') sorted.sort((a, b) => tasteScore(b) - tasteScore(a));\n\t\treturn sorted;\n\t});\n\n\t// Browse grid is paginated client-side: show 12 at a time so the page never\n\t// renders the whole catalog at once. \"load more\" reveals the next 12.\n\tconst PAGE = 12;\n\tlet shown = $state(PAGE);\n\tconst visible = $derived(filtered.slice(0, shown));\n\n\tconst creatorCount = $derived(data.stats.creators);\n\tconst photoCount = $derived(data.stats.photos);\n\n\t// Most-unlocked across the WHOLE catalog (server-ranked in `data.hottest`) —\n\t// not just the newest slice `data.items` holds, otherwise a popular older set\n\t// would be missed from the spotlight.\n\tconst hottest = $derived(data.hottest);\n\n\t// Sort dropdown — same compact pill style as roleplay's control bar.\n\ttype SortKey = 'foryou' | 'new' | 'popular' | 'price';\n\tconst SORT_OPTIONS: { value: SortKey; label: string }[] = [\n\t\t{ value: 'foryou', label: 'for you' },\n\t\t{ value: 'new', label: 'newest' },\n\t\t{ value: 'popular', label: 'most unlocked' },\n\t\t{ value: 'price', label: 'price' }\n\t];\n\tlet sortMenuOpen = $state(false);\n\tlet sortMenuEl = $state<HTMLDivElement>();\n\tconst sortLabel = $derived(SORT_OPTIONS.find((o) => o.value === sort)?.label ?? 'newest');\n\tfunction selectSort(value: SortKey) {\n\t\tsort = value;\n\t\tsortMenuOpen = false;\n\t}\n\n\t// Scroll-aware edge fades on the hottest rail: the left fade only appears once\n\t// you've scrolled past the start (so the first card sits crisp at rest), the\n\t// right fade only while there's more to scroll. No fade at all if it all fits.\n\tlet railEl = $state<HTMLDivElement>();\n\tlet fadeLeft = $state(false);\n\tlet fadeRight = $state(false);\n\t// Edge fades are a desktop-only flourish — on mobile they just chop the cards\n\t// and make the touch-scroll feel cramped, so we drop the mask entirely there.\n\tlet isDesktop = $state(false);\n\tfunction updateRailFades() {\n\t\tconst el = railEl;\n\t\tif (!el) return;\n\t\tfadeLeft = el.scrollLeft > 4;\n\t\tfadeRight = el.scrollLeft < el.scrollWidth - el.clientWidth - 4;\n\t}\n\tconst railMaskStyle = $derived(\n\t\tisDesktop\n\t\t\t? `-webkit-mask-image: linear-gradient(to right, ${fadeLeft ? 'transparent' : '#000'}, #000 3rem, #000 calc(100% - 3rem), ${fadeRight ? 'transparent' : '#000'}); mask-image: linear-gradient(to right, ${fadeLeft ? 'transparent' : '#000'}, #000 3rem, #000 calc(100% - 3rem), ${fadeRight ? 'transparent' : '#000'});`\n\t\t\t: ''\n\t);\n\n\tonMount(() => {\n\t\tactiveMode.set('albums');\n\t\tconst mq = window.matchMedia('(min-width: 768px)');\n\t\tisDesktop = mq.matches;\n\t\tconst onMq = (e: MediaQueryListEvent) => {\n\t\t\tisDesktop = e.matches;\n\t\t};\n\t\tmq.addEventListener('change', onMq);\n\t\tupdateRailFades();\n\t\tconst onDocClick = (e: MouseEvent) => {\n\t\t\tconst t = e.target as Node;\n\t\t\tif (sortMenuOpen && sortMenuEl && !sortMenuEl.contains(t)) sortMenuOpen = false;\n\t\t};\n\t\tconst onKey = (e: KeyboardEvent) => {\n\t\t\tif (e.key === 'Escape') sortMenuOpen = false;\n\t\t};\n\t\tdocument.addEventListener('click', onDocClick);\n\t\tdocument.addEventListener('keydown', onKey);\n\t\twindow.addEventListener('resize', updateRailFades);\n\t\treturn () => {\n\t\t\tactiveMode.set(null);\n\t\t\tmq.removeEventListener('change', onMq);\n\t\t\tdocument.removeEventListener('click', onDocClick);\n\t\t\tdocument.removeEventListener('keydown', onKey);\n\t\t\twindow.removeEventListener('resize', updateRailFades);\n\t\t};\n\t});\n\n\t// Hero CTA → smooth-scroll to the grid (no navigation, no setTimeout).\n\tfunction scrollToBrowse(e: MouseEvent) {\n\t\te.preventDefault();\n\t\tdocument.getElementById('albums-browse')?.scrollIntoView({ behavior: 'smooth', block: 'start' });\n\t}\n</script>\n\n<main class=\"relative overflow-hidden pt-20 pb-16 md:pt-24\">\n\t<div\n\t\tclass=\"pointer-events-none absolute inset-0 bg-[linear-gradient(rgba(255,255,255,.005)_1px,transparent_1px),linear-gradient(90deg,rgba(255,255,255,.005)_1px,transparent_1px)] bg-[size:60px_60px]\"\n\t></div>\n\n\t<div class=\"relative mx-auto w-full max-w-5xl px-5 md:px-0\">\n\t\t<!-- HERO -->\n\t\t<section class=\"max-w-3xl\">\n\t\t\t<h1\n\t\t\t\tclass=\"mt-3 font-display text-[clamp(2.2rem,6vw,4rem)] leading-[0.92] font-bold tracking-[-0.02em]\"\n\t\t\t>\n\t\t\t\talbums, straight<br /><span class=\"text-fuchsia\">from the source.</span>\n\t\t\t</h1>\n\t\t\t<p class=\"mt-4 max-w-md text-sm leading-relaxed text-muted\">\n\t\t\t\t<span class=\"font-semibold text-text\">real creators</span>,\n\t\t\t\t<span class=\"font-semibold text-text\">full sets</span> — unlock the ones worth it.\n\t\t\t</p>\n\t\t\t<div class=\"mt-6 flex flex-wrap items-center gap-x-6 gap-y-4\">\n\t\t\t\t<div class=\"flex w-full flex-col gap-3 sm:w-auto sm:flex-row sm:items-center\">\n\t\t\t\t\t<a\n\t\t\t\t\t\thref=\"#albums-browse\"\n\t\t\t\t\t\tonclick={scrollToBrowse}\n\t\t\t\t\t\tclass=\"inline-flex w-full items-center justify-center gap-2 rounded-xl bg-fuchsia px-7 py-3.5 font-display text-[15px] font-bold tracking-tight text-white no-underline transition-colors hover:bg-fuchsia-dark sm:w-auto\"\n\t\t\t\t\t>\n\t\t\t\t\t\tbrowse albums\n\t\t\t\t\t\t<svg class=\"h-4 w-4\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" aria-hidden=\"true\">\n\t\t\t\t\t\t\t<path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"m6 9 6 6 6-6\" />\n\t\t\t\t\t\t</svg>\n\t\t\t\t\t</a>\n\t\t\t\t\t<a\n\t\t\t\t\t\thref=\"/album\"\n\t\t\t\t\t\tclass=\"inline-flex w-full items-center justify-center rounded-xl border border-border bg-surface px-7 py-3.5 font-display text-[15px] font-bold tracking-tight text-text no-underline transition-colors hover:border-white/20 sm:w-auto\"\n\t\t\t\t\t\t>+ start an album</a\n\t\t\t\t\t>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"flex items-center gap-5 font-mono text-[10px] tracking-[0.14em] text-muted uppercase\">\n\t\t\t\t\t<span><span class=\"text-text\">{data.stats.albums}</span> albums</span>\n\t\t\t\t\t<span><span class=\"text-text\">{creatorCount}</span> creators</span>\n\t\t\t\t\t<span><span class=\"text-text\">{photoCount}</span> photos</span>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<a\n\t\t\t\thref=\"/sell-nudes\"\n\t\t\t\tclass=\"mt-6 inline-block text-sm font-semibold text-muted no-underline transition-colors hover:text-text\"\n\t\t\t\t>selling your own pics? how it works →</a\n\t\t\t>\n\t\t</section>\n\n\t\t<!-- HOTTEST (Steam-style ranked spotlight) -->\n\t\t{#if data.items.length >= 4}\n\t\t\t<section class=\"mt-12 md:mt-16\">\n\t\t\t\t<div class=\"mb-4 flex items-center gap-2\">\n\t\t\t\t\t<svg\n\t\t\t\t\t\tclass=\"flame h-5 w-5 text-fuchsia\"\n\t\t\t\t\t\tviewBox=\"0 0 24 24\"\n\t\t\t\t\t\tfill=\"currentColor\"\n\t\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t>\n\t\t\t\t\t\t<path\n\t\t\t\t\t\t\td=\"M12 2c.5 3-1.5 4.5-3 6.5C7.5 10.5 6 12.4 6 15a6 6 0 0 0 12 0c0-2-1-3.7-2-5-.5 1-1.3 1.6-2.2 1.7C15 9 14 5.5 12 2z\"\n\t\t\t\t\t\t/>\n\t\t\t\t\t</svg>\n\t\t\t\t\t<h2 class=\"font-display text-2xl font-bold tracking-tight\">hottest right now</h2>\n\t\t\t\t</div>\n\t\t\t\t<div\n\t\t\t\t\tbind:this={railEl}\n\t\t\t\t\tonscroll={updateRailFades}\n\t\t\t\t\tstyle={railMaskStyle}\n\t\t\t\t\tclass=\"-mx-5 flex gap-4 overflow-x-auto px-5 pb-2 [-ms-overflow-style:none] [scrollbar-width:none] md:mx-0 md:px-0 [&::-webkit-scrollbar]:hidden\"\n\t\t\t\t>\n\t\t\t\t\t{#each hottest as album (album.id)}\n\t\t\t\t\t\t<div class=\"w-[230px] shrink-0\">\n\t\t\t\t\t\t\t<AlbumRichCard {album} surface=\"browse\" />\n\t\t\t\t\t\t</div>\n\t\t\t\t\t{/each}\n\t\t\t\t</div>\n\t\t\t</section>\n\t\t{/if}\n\n\t\t<!-- BROWSE -->\n\t\t<section id=\"albums-browse\" class=\"mt-14 scroll-mt-24 md:mt-20\">\n\t\t\t<div class=\"mb-5\">\n\t\t\t\t<h2 class=\"font-display text-2xl font-bold tracking-tight\">browse all</h2>\n\t\t\t\t<p class=\"mt-1 text-sm text-muted\">every set someone was bold enough to publish.</p>\n\t\t\t</div>\n\n\t\t\t<!-- compact control bar: search grows; sort is a matching pill dropdown -->\n\t\t\t<div class=\"mb-6 flex flex-wrap items-center gap-2 sm:gap-3\">\n\t\t\t\t<!-- search -->\n\t\t\t\t<div class=\"relative min-w-0 basis-full sm:flex-1 sm:basis-0\">\n\t\t\t\t\t<svg\n\t\t\t\t\t\tclass=\"pointer-events-none absolute top-1/2 left-3.5 h-4 w-4 -translate-y-1/2 text-muted\"\n\t\t\t\t\t\tviewBox=\"0 0 24 24\"\n\t\t\t\t\t\tfill=\"none\"\n\t\t\t\t\t\tstroke=\"currentColor\"\n\t\t\t\t\t\tstroke-width=\"2\"\n\t\t\t\t\t>\n\t\t\t\t\t\t<circle cx=\"11\" cy=\"11\" r=\"7\" /><path d=\"m21 21-4.3-4.3\" />\n\t\t\t\t\t</svg>\n\t\t\t\t\t<input\n\t\t\t\t\t\ttype=\"search\"\n\t\t\t\t\t\tbind:value={query}\n\t\t\t\t\t\tplaceholder=\"search albums, creators, videos…\"\n\t\t\t\t\t\tclass=\"w-full rounded-xl border border-border bg-surface py-2.5 pr-4 pl-10 text-sm text-text placeholder:text-muted focus:border-fuchsia focus:outline-none\"\n\t\t\t\t\t/>\n\t\t\t\t</div>\n\n\t\t\t\t<AlbumMediaSwitch\n\t\t\t\t\tvalue={media}\n\t\t\t\t\tcounts={mediaCounts}\n\t\t\t\t\tonchange={selectMedia}\n\t\t\t\t\tclass=\"min-w-0 flex-1 sm:flex-none\"\n\t\t\t\t/>\n\n\t\t\t\t<!-- sort -->\n\t\t\t\t<div class=\"relative flex-none\" bind:this={sortMenuEl}>\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tonclick={() => (sortMenuOpen = !sortMenuOpen)}\n\t\t\t\t\t\taria-haspopup=\"listbox\"\n\t\t\t\t\t\taria-expanded={sortMenuOpen}\n\t\t\t\t\t\tclass=\"flex w-full items-center justify-between gap-1.5 rounded-xl border border-border bg-surface px-3 py-2.5 text-[13px] font-semibold text-text transition-colors hover:border-white/20 focus:outline-none sm:w-auto\"\n\t\t\t\t\t>\n\t\t\t\t\t\t<span class=\"flex items-center gap-1.5\">\n\t\t\t\t\t\t\t<svg\n\t\t\t\t\t\t\t\tclass=\"h-3.5 w-3.5 text-muted\"\n\t\t\t\t\t\t\t\tviewBox=\"0 0 24 24\"\n\t\t\t\t\t\t\t\tfill=\"none\"\n\t\t\t\t\t\t\t\tstroke=\"currentColor\"\n\t\t\t\t\t\t\t\tstroke-width=\"2\"\n\t\t\t\t\t\t\t\t><path\n\t\t\t\t\t\t\t\t\tstroke-linecap=\"round\"\n\t\t\t\t\t\t\t\t\tstroke-linejoin=\"round\"\n\t\t\t\t\t\t\t\t\td=\"M7 16V4M7 4L4 7M7 4l3 3M17 8v12M17 20l3-3M17 20l-3-3\"\n\t\t\t\t\t\t\t\t/></svg\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{sortLabel}\n\t\t\t\t\t\t</span>\n\t\t\t\t\t\t<svg\n\t\t\t\t\t\t\tclass=\"h-3.5 w-3.5 text-muted transition-transform {sortMenuOpen ? 'rotate-180' : ''}\"\n\t\t\t\t\t\t\tviewBox=\"0 0 24 24\"\n\t\t\t\t\t\t\tfill=\"none\"\n\t\t\t\t\t\t\tstroke=\"currentColor\"\n\t\t\t\t\t\t\tstroke-width=\"2\"\n\t\t\t\t\t\t\t><path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"m6 9 6 6 6-6\" /></svg\n\t\t\t\t\t\t>\n\t\t\t\t\t</button>\n\t\t\t\t\t{#if sortMenuOpen}\n\t\t\t\t\t\t<div\n\t\t\t\t\t\t\trole=\"listbox\"\n\t\t\t\t\t\t\ttabindex=\"-1\"\n\t\t\t\t\t\t\tclass=\"absolute right-0 z-30 mt-1.5 w-48 max-w-[calc(100vw-2.5rem)] overflow-auto rounded-xl border border-border bg-surface p-1 shadow-[0_18px_50px_-18px_rgba(0,0,0,0.85)]\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{#each SORT_OPTIONS as o (o.value)}\n\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\trole=\"option\"\n\t\t\t\t\t\t\t\t\taria-selected={sort === o.value}\n\t\t\t\t\t\t\t\t\tonclick={() => selectSort(o.value)}\n\t\t\t\t\t\t\t\t\tclass=\"flex w-full items-center justify-between gap-2 rounded-lg px-3 py-2 text-left text-[13px] transition-colors {sort ===\n\t\t\t\t\t\t\t\t\to.value\n\t\t\t\t\t\t\t\t\t\t? 'bg-fuchsia/15 font-semibold text-text'\n\t\t\t\t\t\t\t\t\t\t: 'text-muted hover:bg-surface-2 hover:text-text'}\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t{o.label}\n\t\t\t\t\t\t\t\t\t{#if sort === o.value}\n\t\t\t\t\t\t\t\t\t\t<svg\n\t\t\t\t\t\t\t\t\t\t\tclass=\"h-3.5 w-3.5 text-fuchsia\"\n\t\t\t\t\t\t\t\t\t\t\tviewBox=\"0 0 24 24\"\n\t\t\t\t\t\t\t\t\t\t\tfill=\"none\"\n\t\t\t\t\t\t\t\t\t\t\tstroke=\"currentColor\"\n\t\t\t\t\t\t\t\t\t\t\tstroke-width=\"2.5\"\n\t\t\t\t\t\t\t\t\t\t\t><path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M5 13l4 4L19 7\" /></svg\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t{/if}\n\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t{/each}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t{/if}\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t\t{#if availableTags.length > 0}\n\t\t\t\t<!-- taste row — one quiet line, no box: the question is the label,\n\t\t\t\t     the chips are the answer. Selection persists across visits. -->\n\t\t\t\t<div class=\"mb-6 flex flex-wrap items-center gap-x-2 gap-y-2\">\n\t\t\t\t\t<span class=\"mr-1 text-[13px] font-semibold text-muted\">what are you into?</span>\n\t\t\t\t\t{#each shownTags as t (t)}\n\t\t\t\t\t\t<button\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tonclick={() => toggleTag(t)}\n\t\t\t\t\t\t\tclass=\"cursor-pointer rounded-full border px-3 py-1.5 text-[12.5px] font-semibold transition-colors {activeTags.includes(\n\t\t\t\t\t\t\t\tt\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t? 'border-fuchsia/50 bg-fuchsia/15 text-fuchsia'\n\t\t\t\t\t\t\t\t: 'border-border bg-surface text-muted hover:border-muted/40 hover:text-text'}\"\n\t\t\t\t\t\t\t>{ALBUM_TAG_LABELS[t]}</button\n\t\t\t\t\t\t>\n\t\t\t\t\t{/each}\n\t\t\t\t\t{#if moreTags > 0}\n\t\t\t\t\t\t<button\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tonclick={() => (tagsOpen = true)}\n\t\t\t\t\t\t\taria-expanded=\"false\"\n\t\t\t\t\t\t\tclass=\"cursor-pointer rounded-full bg-surface-2 px-3 py-1.5 text-[12.5px] font-semibold text-text transition-colors hover:bg-white/10\"\n\t\t\t\t\t\t\t>+{moreTags} more</button\n\t\t\t\t\t\t>\n\t\t\t\t\t{:else if tagsOpen}\n\t\t\t\t\t\t<button\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tonclick={() => (tagsOpen = false)}\n\t\t\t\t\t\t\taria-expanded=\"true\"\n\t\t\t\t\t\t\tclass=\"cursor-pointer text-[12px] font-semibold text-muted transition-colors hover:text-text\"\n\t\t\t\t\t\t\t>show less</button\n\t\t\t\t\t\t>\n\t\t\t\t\t{/if}\n\t\t\t\t\t{#if activeTags.length > 0}\n\t\t\t\t\t\t<button\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tonclick={() => {\n\t\t\t\t\t\t\t\tactiveTags = [];\n\t\t\t\t\t\t\t\tshown = PAGE;\n\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\tlocalStorage.setItem(PREF_KEY, '[]');\n\t\t\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t\t\t/* ignore */\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\tclass=\"cursor-pointer text-[12px] font-semibold text-muted transition-colors hover:text-text\"\n\t\t\t\t\t\t\t>clear</button\n\t\t\t\t\t\t>\n\t\t\t\t\t{/if}\n\t\t\t\t</div>\n\t\t\t{/if}\n\n\t\t\t<div class=\"grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4\">\n\t\t\t\t{#each visible as album (album.id)}\n\t\t\t\t\t<AlbumRichCard {album} surface=\"browse\" />\n\t\t\t\t{/each}\n\t\t\t\t<a\n\t\t\t\t\thref=\"/album\"\n\t\t\t\t\tclass=\"group flex min-h-[240px] flex-col items-center justify-center gap-2 rounded-xl border border-dashed border-border bg-surface/40 p-5 text-center transition-colors hover:border-white/20 hover:bg-surface\"\n\t\t\t\t>\n\t\t\t\t\t<span class=\"flex h-10 w-10 items-center justify-center rounded-full bg-fuchsia/15 text-2xl font-light text-fuchsia\">+</span>\n\t\t\t\t\t<span class=\"font-display text-sm font-bold text-text\">start an album</span>\n\t\t\t\t\t<span class=\"text-[11px] leading-snug text-muted\">upload a set. get paid every time someone unlocks it.</span>\n\t\t\t\t</a>\n\t\t\t</div>\n\n\t\t\t{#if filtered.length > shown}\n\t\t\t\t<div class=\"mt-6 flex justify-center\">\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tonclick={() => (shown += PAGE)}\n\t\t\t\t\t\tclass=\"inline-flex items-center gap-2 rounded-xl border border-border bg-surface px-6 py-3 font-display text-[14px] font-bold text-text transition-colors hover:border-fuchsia/50\"\n\t\t\t\t\t>\n\t\t\t\t\t\tload more\n\t\t\t\t\t\t<span class=\"font-mono text-[12px] font-normal text-muted\">{filtered.length - shown} left</span>\n\t\t\t\t\t</button>\n\t\t\t\t</div>\n\t\t\t{/if}\n\n\t\t\t{#if filtered.length === 0}\n\t\t\t\t<p class=\"mt-4 text-center text-[13px] text-muted\">nothing matches that. try less.</p>\n\t\t\t{/if}\n\t\t</section>\n\n\t\t<!-- RAT-602: crawlable links to the hubs, in the words people search with -->\n\t\t<section aria-labelledby=\"albums-hubs\" class=\"mt-14 md:mt-20\">\n\t\t\t<h2 id=\"albums-hubs\" class=\"font-display text-xl font-bold tracking-tight\">albums by category</h2>\n\t\t\t<div class=\"mt-4\">\n\t\t\t\t<AlbumHubChips hubs={ALBUM_HUBS_BY_SIZE} />\n\t\t\t</div>\n\t\t\t<!-- RAT-617: the SPH formats have pages of their own under /sph -->\n\t\t\t<p class=\"mt-5 text-sm text-text/80\">\n\t\t\t\tinto SPH?\n\t\t\t\t<a href=\"/sph/clips\" class=\"font-semibold text-text no-underline hover:text-fuchsia\">SPH clips</a>\n\t\t\t\t·\n\t\t\t\t<a href=\"/sph/joi\" class=\"font-semibold text-text no-underline hover:text-fuchsia\">SPH JOI</a>\n\t\t\t\t·\n\t\t\t\t<a href=\"/sph/captions\" class=\"font-semibold text-text no-underline hover:text-fuchsia\"\n\t\t\t\t\t>SPH captions</a\n\t\t\t\t>\n\t\t\t\t·\n\t\t\t\t<a href=\"/sph/small-dick-pics\" class=\"font-semibold text-text no-underline hover:text-fuchsia\"\n\t\t\t\t\t>small dick pics</a\n\t\t\t\t>\n\t\t\t</p>\n\t\t</section>\n\n\t\t<!-- HOW IT WORKS -->\n\t\t<section class=\"mt-16 md:mt-24\">\n\t\t\t<div class=\"mb-6\">\n\t\t\t\t<h2 class=\"font-display text-2xl font-bold tracking-tight\">your photos, your price.</h2>\n\t\t\t\t<p class=\"mt-1 text-sm text-muted\">three steps from camera roll to money in your bank.</p>\n\t\t\t</div>\n\t\t\t<div class=\"grid gap-px overflow-hidden rounded-2xl border border-border bg-border md:grid-cols-3\">\n\t\t\t\t{#each [{ n: '01', t: 'upload a set', d: 'drop in your photos or clips. mark a couple as free teasers, lock the rest.' }, { n: '02', t: 'name your price', d: 'set what the full set costs in tokens. slap on a cover, hit publish.' }, { n: '03', t: 'get paid', d: 'every unlock adds the price to your earnings, paid out to your bank.' }] as step (step.n)}\n\t\t\t\t\t<div class=\"flex flex-col gap-3 bg-surface p-6 md:p-8\">\n\t\t\t\t\t\t<span class=\"flex h-9 w-9 items-center justify-center rounded-lg bg-fuchsia/15 font-mono text-[13px] font-bold text-fuchsia\">{step.n}</span>\n\t\t\t\t\t\t<h3 class=\"font-display text-base font-bold\">{step.t}</h3>\n\t\t\t\t\t\t<p class=\"text-[13px] leading-relaxed text-muted\">{step.d}</p>\n\t\t\t\t\t</div>\n\t\t\t\t{/each}\n\t\t\t</div>\n\t\t\t<a\n\t\t\t\thref=\"/album\"\n\t\t\t\tclass=\"mt-6 inline-flex items-center justify-center rounded-xl bg-fuchsia px-7 py-3.5 font-display text-[15px] font-bold tracking-tight text-white no-underline transition-colors hover:bg-fuchsia-dark\"\n\t\t\t\t>start an album →</a\n\t\t\t>\n\t\t</section>\n\t</div>\n</main>\n\n<Footer />\n\n<style>\n\t/* Live flame: the tongue flickers from its base like a real flame. Pure\n\t   transform/opacity (GPU-cheap, no layout) and disabled for reduced motion. */\n\t.flame {\n\t\ttransform-origin: bottom center;\n\t\tanimation: flame-flicker 0.95s ease-in-out infinite;\n\t\twill-change: transform;\n\t}\n\t/* Flame licking up: stretches tall from its base, squashes, sways a hair\n\t   side to side, brightness flickering — irregular timing so it never reads as\n\t   a clean pulse. No rotation (that looked like a wobble, not a flame). */\n\t@keyframes flame-flicker {\n\t\t0% {\n\t\t\ttransform: translateX(0) scale(1, 1);\n\t\t\topacity: 1;\n\t\t}\n\t\t20% {\n\t\t\ttransform: translateX(-0.4px) scale(0.95, 1.14);\n\t\t\topacity: 0.82;\n\t\t}\n\t\t40% {\n\t\t\ttransform: translateX(0.5px) scale(1.06, 0.9);\n\t\t\topacity: 1;\n\t\t}\n\t\t60% {\n\t\t\ttransform: translateX(-0.3px) scale(0.97, 1.1);\n\t\t\topacity: 0.88;\n\t\t}\n\t\t80% {\n\t\t\ttransform: translateX(0.3px) scale(1.04, 0.95);\n\t\t\topacity: 1;\n\t\t}\n\t\t100% {\n\t\t\ttransform: translateX(0) scale(1, 1);\n\t\t\topacity: 1;\n\t\t}\n\t}\n\t@media (prefers-reduced-motion: reduce) {\n\t\t.flame {\n\t\t\tanimation: none;\n\t\t}\n\t}\n</style>\n"],"version":3}