/* Own card colour, text colours and name effects (card-style.js). Loaded last.
   Card colour is the base surface: background effects still paint over it, card borders run around it. */

/* ---------- Card colour ---------- */
.has-card-color { --card-fill: linear-gradient(var(--card-angle, 180deg), var(--card-a), var(--card-b)); }
.pp.has-card-color, .studio-preview.has-card-color, .reel-card.has-card-color, .hero-card.has-card-color { background: var(--card-fill); }
.pp.has-card-color .pp-identity { background: color-mix(in srgb, var(--card-a) 92%, transparent); }
.pp.has-card-color.has-fx-bg .pp-identity { background: color-mix(in srgb, var(--card-a) 78%, transparent); }
/* With a background effect the chosen colour stays the base: the effect's own dark backdrop gives way,
   its particles play transparently on top, and the modules are tinted with the card colour instead of navy. */
.pp.has-card-color.has-fx-bg:has(.fx-background[data-fx]),
.studio-preview.has-card-color:has(.fx-background[data-fx]),
.reel-card.has-card-color:has(.fx-background[data-fx]),
.hero-card.has-card-color:has(.fx-background[data-fx]) { background: var(--card-fill); }
.pp.has-card-color .pp-avatar > .avatar { border-color: var(--card-a); }
.studio-preview.has-card-color .studio-content, .rail-preview.has-card-color .studio-content { background: transparent; }
.studio-preview.has-card-color > .avatar { border-color: var(--card-a); }
.reel-card.has-card-color .reel-body, .reel-card.has-card-color .reel-head { background: transparent; }

/* ---------- Text colour ---------- */
.has-card-text { --muted: var(--card-muted); --subtle: var(--card-muted); color: var(--card-text); }
/* Links, kickers and the recommendation line take the text colour on a custom card, so the accent never fades on light colours. */
.pp.has-card-color :is(.pp-module-head .text-link, .pp-tools .text-link, .pp-rep-summary strong, .pp-rep strong, .pp-looking, .section-kicker),
.pp.has-card-color > .text-link { color: var(--card-text); }
.pp.has-card-color .pp-module-head .text-link, .pp.has-card-color .pp-tools .text-link { text-decoration: underline; text-underline-offset: 3px; }
.pp.has-card-text :is(.pp-name h1, .pp-module h2, .pp-module strong, .pp-game-info strong, .guestbook-entry strong, .pp-pin strong),
.studio-preview.has-card-text .studio-content :is(h2, strong),
.reel-card.has-card-text :is(.reel-name strong, .reel-bio),
.hero-card.has-card-text .hero-card-body strong { color: var(--card-text); }
.pp.has-card-text :is(.pp-name > small, .pp-status-text, .pp-module p, .pp-module small, .pp-playtimes, .guestbook-entry p, .guestbook-entry small, .pp-hint, .control-label),
.studio-preview.has-card-text .studio-content :is(small, p),
.reel-card.has-card-text :is(.reel-name small, .reel-shared, .reel-nogames, .presence),
.hero-card.has-card-text .hero-card-body :is(small, .presence, .hero-card-bio) { color: var(--card-muted); }
.has-card-text .chip { color: var(--card-text); background: color-mix(in srgb, var(--card-text) 10%, transparent); border-color: color-mix(in srgb, var(--card-text) 22%, transparent); }
/* The name colour on its own card. */
.pp .pp-name h1 .nfx.has-color, .studio-preview .studio-content .nfx.has-color, .reel-card .reel-name .nfx.has-color, .hero-card .hero-card-body .nfx.has-color { color: var(--nfx-c); }

/* ---------- Name effects ---------- */
.nfx { --nfx-glow: var(--nfx-c, #a99cff); position: relative; color: var(--nfx-c, inherit); }
.nfx-sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
.nfx-fill, .nfx-gradient, .nfx-rainbow, .nfx-fire, .nfx-frost, .nfx-gold, .nfx-aurora, .nfx-plasma, .nfx-holo, .nfx-sparkle {
  -webkit-background-clip: text; background-clip: text; color: transparent; -webkit-text-fill-color: transparent;
  background-size: 200% 100%; animation: nfx-slide 6s linear infinite;
}
@keyframes nfx-slide { to { background-position: -200% 0; } }

.nfx-glow { text-shadow: 0 0 6px color-mix(in srgb, var(--nfx-glow) 75%, transparent), 0 0 16px color-mix(in srgb, var(--nfx-glow) 45%, transparent); animation: nfx-glow 2.6s ease-in-out infinite; }
@keyframes nfx-glow { 50% { text-shadow: 0 0 3px color-mix(in srgb, var(--nfx-glow) 55%, transparent), 0 0 8px color-mix(in srgb, var(--nfx-glow) 25%, transparent); } }

.nfx-gradient { background-image: linear-gradient(90deg, var(--nfx-c, #a99cff), color-mix(in srgb, var(--nfx-c, #a99cff) 45%, #ffffff), var(--nfx-c, #a99cff)); animation-duration: 5s; }

.nfx-rainbow { background-image: linear-gradient(90deg, #ff6b6b, #ffb34d, #ffe66b, #6bff9e, #5ad1ff, #9d7bff, #ff6bd8, #ff6b6b); animation-duration: 4s; }

.nfx-sparkle { background-image: linear-gradient(100deg, var(--nfx-c, #d8d9e6) 0 40%, #ffffff 48%, #fff4c4 50%, #ffffff 52%, var(--nfx-c, #d8d9e6) 60% 100%); animation-duration: 3.2s; padding-inline-end: .35em; }
.nfx-sparkle::before, .nfx-sparkle::after { content: "✦" / ""; position: absolute; color: #fff6c9; -webkit-text-fill-color: #fff6c9; font-size: .45em; text-shadow: 0 0 6px #fff3b0; animation: nfx-twinkle 1.8s ease-in-out infinite; pointer-events: none; }
.nfx-sparkle::before { right: 0; top: -.1em; }
.nfx-sparkle::after { left: 30%; bottom: -.15em; font-size: .32em; animation-delay: .9s; }
@keyframes nfx-twinkle { 0%, 100% { opacity: 0; transform: scale(.4) rotate(0deg); } 50% { opacity: 1; transform: scale(1) rotate(45deg); } }

.nfx-glitch { color: var(--nfx-c, inherit); }
.nfx-glitch::before, .nfx-glitch::after { content: attr(data-text) / ""; position: absolute; left: 0; top: 0; width: 100%; overflow: hidden; white-space: nowrap; pointer-events: none; }
.nfx-glitch::before { color: #ff2e88; clip-path: inset(0 0 60% 0); animation: nfx-glitch-a 2.8s steps(1) infinite; }
.nfx-glitch::after { color: #2ee6ff; clip-path: inset(55% 0 0 0); animation: nfx-glitch-b 2.8s steps(1) infinite; }
@keyframes nfx-glitch-a { 0%, 72%, 100% { transform: none; opacity: 0; } 74% { transform: translate(-2px, -1px); opacity: .9; } 78% { transform: translate(2px, 0); clip-path: inset(20% 0 50% 0); opacity: .9; } 82% { opacity: 0; } 90% { transform: translate(-1px, 1px); opacity: .8; } 92% { opacity: 0; } }
@keyframes nfx-glitch-b { 0%, 72%, 100% { transform: none; opacity: 0; } 75% { transform: translate(2px, 1px); opacity: .9; } 79% { transform: translate(-2px, 0); clip-path: inset(60% 0 10% 0); opacity: .9; } 83% { opacity: 0; } 91% { transform: translate(1px, -1px); opacity: .8; } 93% { opacity: 0; } }

.nfx-fire { background-image: linear-gradient(0deg, #ff3d1f, #ff8a1f 35%, #ffd23f 65%, #fff3b8); background-size: 100% 220%; animation: nfx-rise 1.6s ease-in-out infinite alternate; filter: drop-shadow(0 0 4px #ff6a1f88); }
@keyframes nfx-rise { from { background-position: 0 100%; } to { background-position: 0 20%; } }

.nfx-frost { background-image: linear-gradient(100deg, #9fd8ff 0 35%, #ffffff 48%, #d7f2ff 52%, #9fd8ff 65% 100%); animation-duration: 4.5s; filter: drop-shadow(0 0 4px #8fd3ff66); }

.nfx-gold { background-image: linear-gradient(100deg, #b8862b 0 30%, #f6d77a 42%, #fff6d1 50%, #f6d77a 58%, #b8862b 70% 100%); animation-duration: 3.6s; filter: drop-shadow(0 1px 0 #6b4a1288); }

.nfx-neon { color: var(--nfx-c, #ff5ad9); text-shadow: 0 0 4px var(--nfx-c, #ff5ad9), 0 0 12px var(--nfx-c, #ff5ad9), 0 0 24px color-mix(in srgb, var(--nfx-c, #ff5ad9) 60%, transparent); animation: nfx-flicker 4s linear infinite; }
@keyframes nfx-flicker { 0%, 18%, 22%, 25%, 53%, 57%, 100% { opacity: 1; } 20%, 24%, 55% { opacity: .45; text-shadow: none; } }

.nfx-wave .nfx-ch { display: inline-block; animation: nfx-wave 1.8s ease-in-out infinite; animation-delay: calc(var(--i) * 80ms); }
@keyframes nfx-wave { 0%, 60%, 100% { transform: translateY(0); } 30% { transform: translateY(-.18em); } }

.nfx-pulse { display: inline-block; animation: nfx-pulse 1.6s ease-in-out infinite; transform-origin: left center; }
@keyframes nfx-pulse { 0%, 40%, 100% { transform: scale(1); text-shadow: none; } 15% { transform: scale(1.06); text-shadow: 0 0 10px color-mix(in srgb, var(--nfx-glow) 70%, transparent); } 28% { transform: scale(1.03); } }

.nfx-aurora { background-image: linear-gradient(90deg, #4dffb5, #4dc9ff, #a77bff, #ff7be5, #4dffb5); background-size: 300% 100%; animation-duration: 9s; filter: drop-shadow(0 0 5px #4dffb544); }

.nfx-plasma { background-image: linear-gradient(90deg, #ff3df2, #7b5cff, #3de0ff, #7b5cff, #ff3df2); animation-duration: 2.4s; filter: drop-shadow(0 0 6px #b04dff88); }

.nfx-void { color: var(--nfx-c, #e8ddff); text-shadow: 0 0 2px #000, 2px 0 10px #7a3dff99, -2px 0 14px #2a0b5599; animation: nfx-smoke 3.4s ease-in-out infinite; }
@keyframes nfx-smoke { 50% { text-shadow: 0 0 2px #000, -3px -1px 12px #7a3dffaa, 3px 1px 18px #3d0f6faa; } }

.nfx-holo { background-image: linear-gradient(115deg, #b9fbff, #f0b8ff 25%, #fff0b8 45%, #b8ffd6 65%, #b9c8ff 85%, #b9fbff); animation-duration: 5s; }
.nfx-holo::after { content: ""; position: absolute; inset: 0; background: repeating-linear-gradient(0deg, #ffffff22 0 1px, transparent 1px 3px); mix-blend-mode: overlay; animation: nfx-scan 2.2s linear infinite; pointer-events: none; }
@keyframes nfx-scan { to { background-position: 0 6px; } }

/* On a light card the bright palettes get a thin dark outline so the letters stay readable. */
.is-light-card :is(.nfx-gradient, .nfx-rainbow, .nfx-sparkle, .nfx-fire, .nfx-frost, .nfx-gold, .nfx-aurora, .nfx-plasma, .nfx-holo) { filter: drop-shadow(0 0 1px #000c) drop-shadow(0 1px 0 #0008); }

@media (prefers-reduced-motion: reduce) {
  .nfx, .nfx *, .nfx::before, .nfx::after { animation: none !important; }
  .nfx-glitch::before, .nfx-glitch::after, .nfx-sparkle::after { display: none; }
}

/* ---------- Studio: card and name tabs ---------- */
.cs-mode { display: flex; flex-wrap: wrap; gap: 8px; }
.cs-row { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 14px; margin-top: 12px; }
.cs-color { display: inline-flex; align-items: center; gap: 8px; font-size: 13px; color: var(--muted); }
.cs-color input[type="color"] { width: 44px; height: 32px; padding: 2px; border-radius: 10px; border: 1px solid var(--hairline); background: var(--surface-2); cursor: pointer; }
.cs-swatches { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 12px; }
.cs-swatch { width: 40px; height: 40px; border-radius: 12px; border: 2px solid transparent; background: var(--sw); cursor: pointer; box-shadow: inset 0 0 0 1px #ffffff1f; }
.cs-swatch.is-text { width: 32px; height: 32px; border-radius: 50%; }
.cs-swatch.active { border-color: var(--accent); box-shadow: 0 0 0 2px var(--bg), inset 0 0 0 1px #ffffff1f; }
.cs-swatch.is-auto { display: grid; place-items: center; width: auto; padding: 0 12px; border-radius: 999px; background: var(--surface-2); color: var(--ink); font-size: 12px; font-weight: 700; }
.cs-angles { display: inline-flex; gap: 4px; }
.cs-angles button { width: 34px; height: 32px; border-radius: 10px; border: 1px solid var(--hairline); background: var(--surface-2); color: var(--ink); cursor: pointer; }
.cs-angles button.active { background: var(--ink); color: var(--bg); }
.cs-check { display: flex; align-items: center; gap: 8px; margin-top: 12px; font-size: 12.5px; color: var(--muted); }
.cs-check b { font-variant-numeric: tabular-nums; color: var(--ink); }
.cs-check i { width: 14px; height: 14px; border-radius: 50%; background: var(--fix); box-shadow: inset 0 0 0 1px #ffffff40; }
.cs-check.is-fixed { color: #ffd27a; }
.name-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 10px; }
.name-choice { display: grid; gap: 6px; justify-items: start; padding: 12px 12px 10px; border-radius: 14px; border: 1px solid var(--hairline); background: var(--surface-2); color: var(--ink); text-align: left; cursor: pointer; transition: border-color .15s var(--ease), transform .15s var(--ease); }
.name-choice:hover { border-color: #ffffff2e; transform: translateY(-1px); }
.name-choice.active { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent); }
.name-choice .name-sample { font: 800 17px/1.3 var(--font); max-width: 100%; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; padding: 2px 0; }
.name-choice .opt-label { font-size: 12px; color: var(--muted); white-space: normal; overflow-wrap: anywhere; line-height: 1.35; }
.name-choice .opt-label small { display: block; font-size: 11px; color: var(--subtle); }
/* Seven tabs: they wrap into a second row instead of squeezing the labels. */
.studio2-tabs { flex-wrap: wrap; }
.studio2-tabs button { white-space: nowrap; flex: 1 0 auto; padding-inline: 10px; }
.name-choice .opt-tag { justify-self: start; }
@media (prefers-reduced-motion: reduce) { .name-choice { transition: none; } .name-choice:hover { transform: none; } }

/* ---------- Shop: name effect preview ---------- */
.shop-art:has(> .shop-name-preview) { position: relative; padding: 0; }
.shop-art:has(> .shop-name-preview)::before, .shop-art:has(> .shop-name-preview)::after { content: none !important; display: none !important; }
.shop-art .shop-name-preview { position: absolute; inset: 0; z-index: 1; width: auto; height: auto; border: 0; border-radius: 0; box-shadow: none; display: grid; place-items: center; padding: 0 14px; background: radial-gradient(120% 90% at 50% 0%, #2a2c38, #15161c); font: 800 21px/1.3 var(--font); color: #f2f3f5; overflow: hidden; white-space: nowrap; }
.shop-name-preview > .nfx { max-width: 100%; }
/* Other people's names on a custom card (guestbook) follow the card's text colour; their effect stays. */
.pp.has-card-color .guestbook-entry .nfx.has-color { color: inherit; }
/* The shop draws a ring around every span in its art box; name previews opt out. */
.shop-art .shop-name-preview span { width: auto; height: auto; border: 0; border-radius: 0; box-shadow: none; font-size: inherit; display: inline; color: var(--nfx-c, #f2f3f5); }
.shop-art .shop-name-preview :is(.nfx-pulse, .nfx-ch) { display: inline-block; }
.shop-art .shop-name-preview .nfx-sr { position: absolute; width: 1px; height: 1px; }
.shop-art .shop-name-preview .nfx-neon, .shop-art .shop-name-preview .nfx-glitch { color: var(--nfx-c, #ff5ad9); }
.shop-art .shop-name-preview .nfx-glitch { color: var(--nfx-c, #f2f3f5); }
/* Presence and status on a custom card. */
.pp.has-card-text .presence, .studio-preview.has-card-text .presence, .reel-card.has-card-text .presence, .hero-card.has-card-text .presence { color: var(--card-text); }

/* ---------- Card colour × background effect (2026-11-11) ----------
   Background scenes paint their own night sky. On an own card colour that sky used to cover the colour or clash with it,
   so the scene is blended into the card instead of laid on top:
   dark cards  – screen: the dark sky drops away, light, glow and particles shine on the chosen colour;
   light cards – inverted and multiplied: the sky turns into a light wash, the art reads as soft ink in its own hue. */
.has-card-color.is-dark-card > .fx-background,
.has-card-color.is-dark-card .studio-content > .fx-background { mix-blend-mode: screen; }
.has-card-color.is-light-card > .fx-background,
.has-card-color.is-light-card .studio-content > .fx-background { filter: invert(1) hue-rotate(180deg) saturate(1.25); mix-blend-mode: multiply; opacity: .9; }
/* The studio preview blends against the preview's own card colour, not against the transparent content box. */
.studio-preview.has-card-color:has(.fx-background) { isolation: isolate; }
.studio-preview.has-card-color .studio-content.has-fx-bg { isolation: auto; }

/* The name band over a background effect ends in a soft fade instead of a hard edge. */
.pp.has-fx-bg .pp-identity { --id-fill: color-mix(in srgb, var(--white) 78%, transparent); background: var(--id-fill); }
.pp.has-card-color.has-fx-bg .pp-identity { --id-fill: color-mix(in srgb, var(--card-a) 78%, transparent); }
.pp.has-fx-bg .pp-identity::after { content: ''; position: absolute; left: 0; right: 0; top: 100%; height: 36px; pointer-events: none; background: linear-gradient(180deg, var(--id-fill), transparent); }
@media (max-width: 730px) { .pp.has-fx-bg .pp-identity { position: relative; } }

/* Without an own card colour the modules over a background effect use the platform surface, not the old navy. */
.pp.has-fx-bg:not(.has-card-color) .pp-module { background: color-mix(in srgb, var(--surface, #1b161e) 84%, transparent); }
/* The studio card shows the background only behind its text block: let it fade out instead of stopping at a line. */
.studio-content > .fx-background { -webkit-mask-image: linear-gradient(180deg, #000 72%, transparent); mask-image: linear-gradient(180deg, #000 72%, transparent); }

/* ---------- Boxes on an own card colour (2026-11-11) ----------
   card-style.js hands every coloured card two box tones: --card-box for modules and the pin, --card-box-in for what sits
   inside them (inputs, empty states, game tiles, to-dos). Both are the card colour pushed away from the text colour, and
   their opacity follows the brightness of the colour: dark cards stay airy, light cards get solid, readable boxes. */
.pp.has-card-color :is(.pp-module, .pp-pin, .pp-rep) { background: var(--card-box); border-color: color-mix(in srgb, var(--card-ink) 14%, transparent); }
.pp.has-card-color :is(.empty, .todo-item, .todo-game-chip, .todo-form input, .pp-module input, .pp-module textarea, .pp-module select, .guestbook-entry, .pp-game, .pp-badge, .pp-game-chip, .todo-count button) {
  background: var(--card-box-in); border-color: color-mix(in srgb, var(--card-ink) 16%, transparent); color: var(--card-text, var(--card-ink));
}
.pp.has-card-color :is(.empty, .pp-module input::placeholder, .pp-module textarea::placeholder, .todo-form input::placeholder) { color: var(--card-muted, var(--card-ink)); }
.pp.has-card-color .pp-pin :is(strong, p, span:not(.pp-pin-icon):not([data-expires-at])) { color: var(--card-text, var(--card-ink)); }
.pp.has-card-color .pp-pin small:not([data-expires-at]) { color: var(--card-muted, var(--card-ink)); }
.pp.has-card-color .pp-game-info :is(strong, span) { color: var(--card-text, var(--card-ink)); }
.pp.has-card-color .pp-game-info small { color: var(--card-muted, var(--card-ink)); }
.pp.has-card-color .todo-game-chip.active { border-color: var(--accent, #ff9e57); background: color-mix(in srgb, var(--accent, #ff9e57) 22%, var(--card-box-in)); }
.pp.has-card-color .todo-check { border-color: color-mix(in srgb, var(--card-ink) 45%, transparent); }
/* The accent (timer, ranks) gets darker on light cards so it keeps its colour and stays readable. */
.pp.is-light-card :is(.pp-pin small[data-expires-at], .section-kicker [data-expires-at], .pp-game-info .pp-rank) { color: color-mix(in srgb, var(--accent, #ff9e57) 55%, #2a1206); }
/* Profile cards (popout, people reel) use the same tones for their inner boxes. */
.pop-card.has-card-color .pop-section, .pop-card.has-card-color.has-fx-bg .pop-section { background: var(--card-box); }
.reel-card.has-card-color .reel-games li { background: var(--card-box-in); }
.reel-card.has-card-color .reel-games span:not(.game-art) { color: var(--card-text, var(--card-ink)); }
/* A chosen text colour that reads in the boxes but not on the bare card colour: name, status and bio get a soft backing
   in the box tone (a spread shadow, so nothing moves). */
.pp.has-text-backing .pp-identity, .pp.has-card-color.has-fx-bg.has-text-backing .pp-identity { --id-fill: var(--card-box); background: var(--card-box); }
.studio-preview.has-text-backing .studio-content, .reel-card.has-text-backing .reel-head, .reel-card.has-text-backing .reel-body,
.hero-card.has-text-backing .hero-card-body, .pop-card.has-text-backing .pop-head {
  background: var(--card-box); box-shadow: 0 0 0 8px var(--card-box); border-radius: 10px;
}
.pop-card.is-light-card :is([data-profile-page], .pop-games b) { color: color-mix(in srgb, var(--accent, #ff9e57) 50%, #241005); }
/* Text backing on elements that span the whole card width (hero body, reel body, studio content): no spread shadow,
   it pushed the box 8px past the card edge, visible on cards with a border effect (overflow visible). Inset instead. */
.hero-card.has-text-backing .hero-card-body { margin: 2px 8px 0; padding: 8px; box-shadow: none; }
.reel-card.has-text-backing .reel-body { margin: 0 12px 12px; padding: 10px 8px 8px; box-shadow: none; }
.studio-preview.has-text-backing .studio-content { margin-inline: 8px; box-shadow: none; }
