{"release_id":"01a1c502-4ad1-0000-ec62-adc54d3c69aa","chunk_id":"01a1c502-4be4-7f22-8834-12112536f793","file":"C2OAMFnx.mjs","mappings":"qTA0DO,MAAMA,EAA0D,CACtE,CAAE,MAAO,cAAe,KAAM,CAAC,OAAQ,QAAS,UAAW,OAAO,CAAA,EAClE,CACC,MAAO,QACP,KAAM,CACL,MACA,QACA,OACA,OACA,QACA,SACA,QACA,OACA,MACA,QACA,QACA,SACA,OACA,MACA,QACA,SACA,QACA,SAAA,CACD,EAED,CACC,MAAO,OACP,KAAM,CACL,OACA,UACA,UACA,OACA,OACA,UACA,WACA,UACA,UACA,QACA,OAIA,OAAA,CACD,EAED,CAAE,MAAO,OAAQ,KAAM,CAAC,MAAO,MAAO,WAAY,QAAS,IAAI,CAAA,CAChE,EAEaC,EAAyBD,EAAiB,QAASE,GAAMA,EAAE,IAAI,EAE/DC,EAAqB,EAErBC,EAA6C,CACzD,KAAM,OACN,MAAO,QACP,QAAS,UACT,MAAO,QACP,IAAK,MACL,MAAO,QACP,KAAM,OACN,KAAM,OACN,MAAO,QACP,OAAQ,SACR,MAAO,QACP,KAAM,OACN,IAAK,MACL,MAAO,QACP,MAAO,QACP,OAAQ,SACR,KAAM,OACN,IAAK,MACL,MAAO,QACP,OAAQ,SACR,MAAO,QACP,QAAS,UACT,KAAM,OACN,QAAS,UACT,QAAS,UACT,KAAM,OACN,KAAM,OACN,QAAS,WACT,SAAU,WACV,QAAS,UACT,QAAS,UACT,MAAO,QACP,KAAM,OACN,MAAO,QACP,MAAO,QACP,IAAK,MACL,IAAK,MACL,SAAU,WACV,MAAO,QACP,GAAI,SACL,EAKaC,EAAyC,CAAC,MAAO,MAAO,QAAS,IAAI,EAGzCJ,EAAW,OAAQK,GAAM,CAACD,EAAkB,SAASC,CAAC,CAAC","names":["ALBUM_TAG_GROUPS","ALBUM_TAGS","g","MAX_TAGS_PER_ALBUM","ALBUM_TAG_LABELS","CREATOR_ONLY_TAGS","t"],"sources":["../../../../../../src/lib/types/album-tags.ts"],"sourcesContent":["// Album tags — a FIXED, curated vocabulary (the arena-categories pattern),\n// deliberately not the community niche table: chips must never point at an\n// empty or hibernated bucket, and a browse filter needs a stable, short list.\n// Creators pick up to MAX_TAGS_PER_ALBUM in the editor; the /albums browse\n// page filters on them client-side (the whole catalog is already loaded).\n//\n// Grouped: WHO is in it (the top-level browse axis — guys, girls, couples,\n// trans), what it LOOKS like, the VIBE, and the KINK formats the /sph pages\n// list (RAT-617). Female-creator content is first class: tits/ass/lingerie/\n// cosplay etc. sit beside the dick vocabulary.\n\nexport type AlbumTag =\n\t// who\n\t| 'guys'\n\t| 'girls'\n\t| 'couples'\n\t| 'trans'\n\t// looks\n\t| 'big'\n\t| 'thick'\n\t| 'hard'\n\t| 'soft'\n\t| 'hairy'\n\t| 'shaved'\n\t| 'uncut'\n\t| 'tits'\n\t| 'ass'\n\t| 'pussy'\n\t| 'curvy'\n\t| 'petite'\n\t| 'milf'\n\t| 'bbc'\n\t| 'ebony'\n\t| 'latina'\n\t| 'asian'\n\t| 'tattoos'\n\t// vibe\n\t| 'solo'\n\t| 'cumshot'\n\t| 'blowjob'\n\t| 'anal'\n\t| 'toys'\n\t| 'closeup'\n\t| 'lingerie'\n\t| 'cosplay'\n\t| 'outdoor'\n\t| 'kinky'\n\t| 'feet'\n\t| 'video'\n\t| 'funny'\n\t// kink (RAT-617): what the /sph pages list\n\t| 'sph'\n\t| 'joi'\n\t| 'captions'\n\t| 'small'\n\t// made with AI: the album says so on its card and in its tags\n\t| 'ai';\n\nexport const ALBUM_TAG_GROUPS: { label: string; tags: AlbumTag[] }[] = [\n\t{ label: \"who's in it\", tags: ['guys', 'girls', 'couples', 'trans'] },\n\t{\n\t\tlabel: 'looks',\n\t\ttags: [\n\t\t\t'big',\n\t\t\t'thick',\n\t\t\t'hard',\n\t\t\t'soft',\n\t\t\t'hairy',\n\t\t\t'shaved',\n\t\t\t'uncut',\n\t\t\t'tits',\n\t\t\t'ass',\n\t\t\t'pussy',\n\t\t\t'curvy',\n\t\t\t'petite',\n\t\t\t'milf',\n\t\t\t'bbc',\n\t\t\t'ebony',\n\t\t\t'latina',\n\t\t\t'asian',\n\t\t\t'tattoos'\n\t\t]\n\t},\n\t{\n\t\tlabel: 'vibe',\n\t\ttags: [\n\t\t\t'solo',\n\t\t\t'cumshot',\n\t\t\t'blowjob',\n\t\t\t'anal',\n\t\t\t'toys',\n\t\t\t'closeup',\n\t\t\t'lingerie',\n\t\t\t'cosplay',\n\t\t\t'outdoor',\n\t\t\t'kinky',\n\t\t\t'feet',\n\t\t\t// no 'video': whether an album has clips comes from what's in it, and\n\t\t\t// the album browser's switch asks that (RAT-621). Albums that wear the\n\t\t\t// tag keep it; nobody picks it any more.\n\t\t\t'funny'\n\t\t]\n\t},\n\t{ label: 'kink', tags: ['sph', 'joi', 'captions', 'small', 'ai'] }\n];\n\nexport const ALBUM_TAGS: AlbumTag[] = ALBUM_TAG_GROUPS.flatMap((g) => g.tags);\n\nexport const MAX_TAGS_PER_ALBUM = 4;\n\nexport const ALBUM_TAG_LABELS: Record<AlbumTag, string> = {\n\tguys: 'guys',\n\tgirls: 'girls',\n\tcouples: 'couples',\n\ttrans: 'trans',\n\tbig: 'big',\n\tthick: 'thick',\n\thard: 'hard',\n\tsoft: 'soft',\n\thairy: 'hairy',\n\tshaved: 'shaved',\n\tuncut: 'uncut',\n\ttits: 'tits',\n\tass: 'ass',\n\tpussy: 'pussy',\n\tcurvy: 'curvy',\n\tpetite: 'petite',\n\tmilf: 'milf',\n\tbbc: 'bbc',\n\tebony: 'ebony',\n\tlatina: 'latina',\n\tasian: 'asian',\n\ttattoos: 'tattoos',\n\tsolo: 'solo',\n\tcumshot: 'cumshot',\n\tblowjob: 'blowjob',\n\tanal: 'anal',\n\ttoys: 'toys',\n\tcloseup: 'close-up',\n\tlingerie: 'lingerie',\n\tcosplay: 'cosplay',\n\toutdoor: 'outdoor',\n\tkinky: 'kinky',\n\tfeet: 'feet',\n\tvideo: 'video',\n\tfunny: 'funny',\n\tsph: 'SPH',\n\tjoi: 'JOI',\n\tcaptions: 'captions',\n\tsmall: 'small',\n\tai: 'AI-made'\n};\n\n/** Tags only the creator may set (RAT-617). Whether a scene is SPH or JOI\n *  can't be seen in three stills, nobody's size gets labelled \"small\" by a\n *  model, and whether an album is AI-made is the creator's to declare. */\nexport const CREATOR_ONLY_TAGS: readonly AlbumTag[] = ['sph', 'joi', 'small', 'ai'];\n\n/** What the AI tagger may pick from. */\nexport const AI_ALBUM_TAGS: AlbumTag[] = ALBUM_TAGS.filter((t) => !CREATOR_ONLY_TAGS.includes(t));\n\n/** `max` caps the count — the editor passes MAX_TAGS_PER_ALBUM (a card can't\n *  wear every tag); browse filters pass nothing (uncapped, harms no one). */\nexport function sanitizeAlbumTags(input: unknown, max = Infinity): AlbumTag[] {\n\tif (!Array.isArray(input)) return [];\n\tconst allowed = new Set<string>(ALBUM_TAGS);\n\tconst seen = new Set<AlbumTag>();\n\tfor (const raw of input) {\n\t\tif (typeof raw !== 'string') continue;\n\t\tconst v = raw.trim().toLowerCase();\n\t\tif (!allowed.has(v)) continue;\n\t\tseen.add(v as AlbumTag);\n\t\tif (seen.size >= max) break;\n\t}\n\treturn [...seen];\n}\n"],"version":3}