PageSourceSearch

https://mtg.studio/js/domain/cosmetics.js

js mtg.studio collected 2026-10-09 22:16:47 UTC 2,044 bytes, 55 lines download raw bytes

1// @ts-check
2/**
3 * Supporter cosmetics (M11 Phase B) — pure registry for the Foil Patron accent palettes.
4 * Cosmetics are client-side unlocks by doctrine (docs/gtm/monetization-tiers.md §2:
5 * "cosmetics are exempt from the server-enforcement rule"); the gate here is a courtesy
6 * UX, not security. Palettes apply as a `data-palette` attribute on <html> layered over
7 * the light/dark `data-theme`; the CSS variable overrides live in styles.css.
8 */
9
10/**
11 * @typedef {Object} Palette
12 * @property {string} id        '' = default (no attribute); also the data-palette value
13 * @property {string} nameKey   i18n key for the display name
14 * @property {boolean} supporter  true = Foil Patron unlock (client-side gate)
15 */
16
17/** @type {Palette[]} */
18export const PALETTES = [
19    { id: '', nameKey: 'cosDefault', supporter: false },
20    { id: 'foil', nameKey: 'cosFoil', supporter: true },
21    { id: 'mythic', nameKey: 'cosMythic', supporter: true },
22    { id: 'island', nameKey: 'cosIsland', supporter: true },
23];
24
25/** @param {string} id */
26export function paletteById(id) {
27    return PALETTES.find((p) => p.id === id) || PALETTES[0];
28}
29
30/**
31 * Can this palette be activated by this user? Default is always available; supporter
32 * palettes need the Paid entitlement.
33 * @param {string} id @param {boolean} isPaid
34 */
35export function canUsePalette(id, isPaid) {
36    const p = paletteById(id);
37    return !p.supporter || !!isPaid;
38}
39
40/**
41 * Apply a palette to the document root (empty id removes the attribute). Returns the id
42 * actually applied (falls back to default when the palette is unknown).
43 * @param {string} id
44 * @param {{ setAttribute(n: string, v: string): void, removeAttribute(n: string): void }} [root]
45 */
46export function applyPalette(
47    id,
48    root = typeof document !== 'undefined' ? document.documentElement : /** @type {any} */ (null)
49) {
50    const p = paletteById(id);
51    if (!root) return p.id;
52    if (p.id) root.setAttribute('data-palette', p.id);
53    else root.removeAttribute('data-palette');
54    return p.id;
55}

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.