/* The playful layer: palette, motion and effects. Moved out of includes/fun-head.php so browsers cache it between pages;
   edit it here. Linked from includes/fun-head.php at the same spot, so the cascade order is unchanged. */
/* ── Fun mode: palette ─────────────────────────────────────────
   Six arcade primaries around the brand cyan. Everything below
   layers on top of the standard design; nothing here is load-bearing. */
:root {
    --fun-red: #ff4d5e;
    --fun-orange: #ff8a3d;
    --fun-yellow: #ffc83d;
    --fun-green: #35d07f;
    --fun-blue: #01b0f1;
    --fun-purple: #9b6bff;
    --fun-pink: #ff5fb4;
    --fun-stripe: linear-gradient(90deg,
        var(--fun-red) 0 14.28%, var(--fun-orange) 0 28.57%, var(--fun-yellow) 0 42.85%,
        var(--fun-green) 0 57.14%, var(--fun-blue) 0 71.42%, var(--fun-purple) 0 85.71%,
        var(--fun-pink) 0 100%);
    --fun-spring: cubic-bezier(0.34, 1.56, 0.64, 1);
}

::selection {
    background: var(--fun-yellow);
    color: #12141a;
}

/* Clip (not scroll) sideways overflow: hover glows and the off-page
   tiles of an unclipped row must never widen the page. */
html,
body {
    overflow-x: clip;
}

html {
    scrollbar-color: var(--fun-blue) var(--bg);
}

/* Soft colour wash at the top of the page, behind everything */
body {
    background:
        radial-gradient(900px 520px at 12% -120px, rgba(155,107,255,0.16), transparent 70%),
        radial-gradient(800px 480px at 88% -80px, rgba(1,176,241,0.14), transparent 70%),
        radial-gradient(700px 420px at 50% -200px, rgba(255,95,180,0.10), transparent 70%),
        var(--bg);
    background-repeat: no-repeat;
}

/* Drifting pixel sparkles (drawn by the footer script) */
#fun-sky {
    position: fixed;
    inset: 0;
    width: 100%;
    height: 100%;
    z-index: -1;
    pointer-events: none;
}

/* ── Header ─────────────────────────────────────────────────── */
.logo {
    transform-origin: 8% 80%;
}

.logo.fun-hover {
    animation: fun-jump 0.6s var(--fun-spring);
}

@keyframes fun-jump {
    0%   { transform: translateY(0) scale(1, 1); }
    20%  { transform: translateY(0) scale(1.04, 0.92); }
    50%  { transform: translateY(-8px) scale(0.98, 1.04); }
    80%  { transform: translateY(0) scale(1.03, 0.96); }
    100% { transform: translateY(0) scale(1, 1); }
}

/* Each nav item gets its own colour, like a console menu */
.navigation > a {
    --c: var(--fun-blue);
    transition: background 0.15s, color 0.15s, box-shadow 0.25s, transform 0.25s var(--fun-spring);
}

.navigation > a:nth-child(1) { --c: var(--fun-green); }
.navigation > a:nth-child(2) { --c: var(--fun-blue); }
.navigation > a:nth-child(3) { --c: var(--fun-yellow); }
.navigation > a:nth-child(4) { --c: var(--fun-red); }

/* Same treatment as a hovered news card: coloured outline, a lift
   and a solid shadow underneath. The current section keeps the
   outline at rest; hover adds the lift. (Inset shadow, not a
   border, so the pill never changes size.) */
.navigation > a:is(:hover, .fun-hover),
.navigation > a.is-current {
    color: var(--c);
    background: color-mix(in srgb, var(--c) 12%, transparent);
    box-shadow: inset 0 0 0 1px var(--c);
}

.navigation > a:is(:hover, .fun-hover) {
    transform: translateY(-2px);
    box-shadow: inset 0 0 0 1px var(--c), 0 3px 0 color-mix(in srgb, var(--c) 55%, #000);
}

/* ── Section headings: retro drop shadow + menu cursor ──────── */
.sec-head h1,
.sec-head h2 {
    display: flex;
    align-items: center;
    gap: 14px;
    text-shadow: 3px 3px 0 rgba(155,107,255,0.45);
}

.sec-head h1::before,
.sec-head h2::before {
    content: "";
    flex: none;
    width: 14px;
    height: 16px;
    background: var(--fun-yellow);
    clip-path: polygon(0 0, 100% 50%, 0 100%);
    animation: fun-cursor 1s steps(2, jump-none) infinite;
    filter: drop-shadow(2px 2px 0 rgba(255,77,94,0.6));
}

@keyframes fun-cursor {
    0%   { transform: translateX(0); }
    100% { transform: translateX(5px); }
}

/* Letters split by the footer script do a wave on hover. They stay
   plain inline text (moved with "top", not a transform), so a title
   wraps exactly like ordinary text in every browser. */
.fun-wave .fun-ch {
    position: relative;
}

.fun-wave:hover .fun-ch {
    animation: fun-wave 0.6s var(--fun-spring) both;
    animation-delay: calc(var(--i) * 28ms);
}

@keyframes fun-wave {
    0%, 100% { top: 0; }
    40%      { top: -7px; color: var(--fun-yellow); }
}

.sec-head > a,
.hero-side .sec-link {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    transition: transform 0.25s var(--fun-spring), color 0.15s;
}

.sec-head > a::after,
.hero-side .sec-link::after {
    content: "\25B6";
    font-size: 0.6em;
    transition: transform 0.25s var(--fun-spring);
}

.sec-head > a:hover,
.hero-side .sec-link:hover {
    color: var(--fun-yellow);
    text-decoration: none;
}

.sec-head > a:hover::after,
.hero-side .sec-link:hover::after {
    transform: translateX(4px);
}

/* ── Buttons: chunky arcade press ───────────────────────────── */
.btn {
    box-shadow: 0 3px 0 rgba(0,0,0,0.55), inset 0 1px 0 rgba(255,255,255,0.12);
    transition: background 0.15s, border-color 0.15s, color 0.15s, transform 0.12s, box-shadow 0.12s;
}

.btn:is(:hover, .fun-hover) {
    transform: translateY(-2px);
    box-shadow: 0 5px 0 rgba(0,0,0,0.55), inset 0 1px 0 rgba(255,255,255,0.16);
}

.btn:active {
    transform: translateY(3px);
    box-shadow: 0 0 0 rgba(0,0,0,0.55), inset 0 1px 0 rgba(255,255,255,0.12);
}

.btn.primary {
    box-shadow: 0 4px 0 color-mix(in srgb, var(--app) 45%, #000), inset 0 1px 0 rgba(255,255,255,0.3);
}

.btn.primary:is(:hover, .fun-hover) {
    box-shadow: 0 6px 0 color-mix(in srgb, var(--app) 45%, #000), inset 0 1px 0 rgba(255,255,255,0.3);
}

.btn.primary:active {
    box-shadow: 0 0 0 color-mix(in srgb, var(--app) 45%, #000), inset 0 1px 0 rgba(255,255,255,0.3);
}

/* ── Home hero ─────────────────────────────────────────────── */
.hero-main {
    position: relative;
}

/* Rainbow aura glowing under the key art */
.hero-main::before {
    content: "";
    position: absolute;
    inset: -10px -10px 20px;
    border-radius: var(--r-lg);
    background: conic-gradient(from var(--fun-angle, 0deg),
        var(--fun-red), var(--fun-yellow), var(--fun-green),
        var(--fun-blue), var(--fun-purple), var(--fun-pink), var(--fun-red));
    filter: blur(40px);
    opacity: 0.4;
    z-index: -1;
    animation: fun-spin 14s linear infinite;
}

@property --fun-angle {
    syntax: "<angle>";
    initial-value: 0deg;
    inherits: false;
}

@keyframes fun-spin {
    to { --fun-angle: 360deg; }
}

.hero-frame .is-selected .slide-logo {
    animation: fun-float 3.2s ease-in-out infinite;
}

@keyframes fun-float {
    0%, 100% { translate: 0 0; rotate: 0deg; }
    50%      { translate: 0 -8px; rotate: -1deg; }
}

.game-availability::before {
    content: "";
    display: inline-block;
    width: 7px;
    height: 7px;
    margin-right: 7px;
    vertical-align: 1px;
    background: var(--app);
    box-shadow: 0 0 10px var(--app);
    animation: fun-blink 1.1s steps(2, jump-none) infinite;
}

@keyframes fun-blink {
    50% { opacity: 0.2; }
}

/* Page dots: one colour each; the active one is a timer bar that
   fills over the 6s auto-advance (and rests while hovered). The home
   page styles its hero dots after this sheet loads, so those rules
   lead with "html" to win. */
html .hero-main .flickity-page-dots .dot,
.tiles .flickity-page-dots .dot {
    position: relative;
    overflow: hidden;
    vertical-align: middle;
    background: color-mix(in srgb, var(--c) 35%, transparent);
    transition: width 0.35s var(--fun-spring), background 0.2s, transform 0.2s var(--fun-spring);
}

.flickity-page-dots .dot { --c: var(--fun-blue); }
.flickity-page-dots .dot:nth-child(7n+1) { --c: var(--fun-blue); }
.flickity-page-dots .dot:nth-child(7n+2) { --c: var(--fun-red); }
.flickity-page-dots .dot:nth-child(7n+3) { --c: var(--fun-yellow); }
.flickity-page-dots .dot:nth-child(7n+4) { --c: var(--fun-green); }
.flickity-page-dots .dot:nth-child(7n+5) { --c: var(--fun-purple); }
.flickity-page-dots .dot:nth-child(7n+6) { --c: var(--fun-pink); }
.flickity-page-dots .dot:nth-child(7n+7) { --c: var(--fun-orange); }

.flickity-page-dots .dot:hover {
    transform: scale(1.35);
}

html .hero-main .flickity-page-dots .dot.is-selected,
.tiles .flickity-page-dots .dot.is-selected {
    width: 28px;
    border-radius: 4px;
    background: color-mix(in srgb, var(--c) 35%, transparent);
    transform: none;
}

.tiles .flickity-page-dots .dot.is-selected {
    background: var(--c);
}

.hero-main .flickity-page-dots .dot.is-selected::after {
    content: "";
    position: absolute;
    inset: 0;
    background: var(--c);
    transform-origin: left;
    animation: fun-timer 6s linear forwards;
}

.hero-main:hover .flickity-page-dots .dot.is-selected::after {
    animation: none;
}

@keyframes fun-timer {
    from { transform: scaleX(0); }
    to   { transform: scaleX(1); }
}

/* ── Hover room: nothing that lifts or glows gets cut off ───── */

/* Tile rows: the slider viewport no longer clips, so a lifted, tilted
   tile and its glow show in full. Tiles off the current page are
   faded out by the footer script instead (by how much of each is
   inside the row), which also keeps a swipe looking natural.
   Phones keep the side clip (the neighbouring tiles are meant to
   peek in) but open the top and bottom, since a tap shows the hover. */
@media only screen and (max-width: 540px) {
    .tiles .flickity-viewport {
        overflow: visible;
        clip-path: inset(-48px 0);
    }
}

@media only screen and (min-width: 541px) {
    .tiles .flickity-viewport {
        overflow: visible;
    }

    .tiles.flickity-enabled .tile {
        transition: opacity 0.25s;
    }

    .tiles .tile.is-off {
        pointer-events: none;
    }
}

/* Home news column: the script already hides any card that would
   not fit, so the list can let a hovered card's lift and shadow out. */
.hero-side .hero-list {
    overflow: visible;
}

/* Phone nav scrolls sideways, which clips vertically too; give the
   lift and underline room inside the scroller. */
@media only screen and (max-width: 720px) {
    .navigation {
        padding-block: 4px;
        margin-block: -4px;
    }
}

/* ── Tiles: lift, tilt and glare ─────────────────────────────── */
/* The footer script eases the lift and cursor tilt frame by frame
   (html.fun-tilt) so the motion never restarts mid-move; without it
   (reduced motion) the tile just lifts. */
.tile-img {
    transition: box-shadow 0.25s;
    will-change: transform;
}

.tile:hover .tile-img {
    box-shadow: 0 22px 44px rgba(0,0,0,0.5), 0 0 0 2px var(--app), 0 10px 40px color-mix(in srgb, var(--app) 45%, transparent);
}

html:not(.fun-tilt) .tile:hover .tile-img {
    transform: translateY(-4px);
}

.fun-glare {
    position: absolute;
    inset: 0;
    border-radius: inherit;
    pointer-events: none;
    z-index: 3;
    opacity: 0;
    background: radial-gradient(circle at var(--mx, 50%) var(--my, 30%), rgba(255,255,255,0.35), rgba(255,255,255,0) 55%);
    mix-blend-mode: overlay;
    transition: opacity 0.25s;
}

.tile:hover .fun-glare {
    opacity: 1;
}

.tile-cap .badge {
    transition: transform 0.3s var(--fun-spring);
}

.tile:hover .tile-cap .badge {
    animation: fun-hop 0.45s var(--fun-spring) both;
}

.tile:hover .tile-cap .badge:nth-child(2) { animation-delay: 0.05s; }
.tile:hover .tile-cap .badge:nth-child(3) { animation-delay: 0.1s; }
.tile:hover .tile-cap .badge:nth-child(4) { animation-delay: 0.15s; }

@keyframes fun-hop {
    40% { transform: translateY(-5px); }
}

/* ── News cards: each pops in its own colour ────────────────── */
.card {
    --c: var(--fun-blue);
    transition: border-color 0.2s, background 0.2s, transform 0.3s var(--fun-spring), box-shadow 0.25s;
}

.hero-list .card:nth-child(4n+1), .news-grid .card:nth-child(4n+1), .news-list .card:nth-child(4n+1) { --c: var(--fun-pink); }
.hero-list .card:nth-child(4n+2), .news-grid .card:nth-child(4n+2), .news-list .card:nth-child(4n+2) { --c: var(--fun-yellow); }
.hero-list .card:nth-child(4n+3), .news-grid .card:nth-child(4n+3), .news-list .card:nth-child(4n+3) { --c: var(--fun-green); }
.hero-list .card:nth-child(4n+4), .news-grid .card:nth-child(4n+4), .news-list .card:nth-child(4n+4) { --c: var(--fun-purple); }

.card:is(:hover, .fun-hover) {
    border-color: var(--c);
    transform: translateY(-3px);
    box-shadow: 0 5px 0 color-mix(in srgb, var(--c) 55%, #000), 0 16px 34px rgba(0,0,0,0.35);
}

.card:is(:hover, .fun-hover) .label {
    color: var(--c);
}

/* ── Scroll-in pop ─────────────────────────────────────────── */
html.fun-pending :is(.card, .sec-head, .app-side .side-block, .channel, .product, .privacy-body .prose-heading) {
    opacity: 0;
}

.fun-pop {
    opacity: 0;
    translate: 0 18px;
    scale: 0.96;
}

.fun-pop.is-in {
    opacity: 1;
    translate: 0 0;
    scale: 1;
    transition: opacity 0.45s ease-out, translate 0.6s var(--fun-spring), scale 0.6s var(--fun-spring);
}

/* Tiles pop as a whole, like the news cards; this outranks the tile
   rows' own opacity transition while the pop plays */
.tiles .tile.fun-pop.is-in {
    transition: opacity 0.45s ease-out, translate 0.6s var(--fun-spring), scale 0.6s var(--fun-spring);
}

/* While a tile's art loads it shows an empty cartridge slot in its
   accent colour: a pixel grid, a slow shine and a three-block
   loader. The art then pops in over it. */
:is(html.fun-pending .tile, .tile.fun-pop) {
    position: relative;
    container-type: inline-size;
    opacity: 1;
    translate: none;
    scale: none;
}

:is(html.fun-pending .tile, .tile.fun-pop) > * {
    opacity: 0;
    translate: 0 14px;
    scale: 0.96;
}

.tile.fun-pop.is-in > * {
    opacity: 1;
    translate: 0 0;
    scale: 1;
    transition: opacity 0.4s ease-out, translate 0.6s var(--fun-spring), scale 0.6s var(--fun-spring);
}

:is(html.fun-pending .tile, .tile.fun-pop)::before {
    content: "";
    position: absolute;
    top: 6px;
    left: 0;
    right: 0;
    aspect-ratio: 2 / 3;
    border-radius: var(--r-sm);
    background:
        linear-gradient(105deg, transparent 38%, rgba(255,255,255,0.07) 50%, transparent 62%) 0 0 / 300% 100% no-repeat,
        radial-gradient(color-mix(in srgb, var(--app) 30%, transparent) 1px, transparent 1.6px) 0 0 / 10px 10px,
        color-mix(in srgb, var(--app) 10%, var(--surface));
    box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--app) 26%, transparent);
    animation: fun-slot-shine 2.2s linear infinite;
    pointer-events: none;
}

:is(html.fun-pending .tile, .tile.fun-pop)::after {
    content: "";
    position: absolute;
    top: calc(6px + 75cqw - 3px);
    left: 50%;
    width: 6px;
    height: 6px;
    margin-left: -15px;
    animation: fun-slot-load 0.9s steps(1) infinite;
    pointer-events: none;
}

.tile.fun-pop.is-in::before,
.tile.fun-pop.is-in::after {
    opacity: 0;
    transition: opacity 0.3s ease-out;
}

@keyframes fun-slot-shine {
    from { background-position: 150% 0, 0 0, 0 0; }
    to   { background-position: -50% 0, 0 0, 0 0; }
}

@keyframes fun-slot-load {
    0%   { background: var(--app); box-shadow: 12px 0 color-mix(in srgb, var(--app) 30%, transparent), 24px 0 color-mix(in srgb, var(--app) 30%, transparent); }
    33%  { background: color-mix(in srgb, var(--app) 30%, transparent); box-shadow: 12px 0 var(--app), 24px 0 color-mix(in srgb, var(--app) 30%, transparent); }
    66%  { background: color-mix(in srgb, var(--app) 30%, transparent); box-shadow: 12px 0 color-mix(in srgb, var(--app) 30%, transparent), 24px 0 var(--app); }
}

/* Social icons bump like a "?" block */
.social-icons > a {
    display: inline-block;
}

.social-icons > a:hover > div {
    animation: fun-bump 0.35s var(--fun-spring);
}

@keyframes fun-bump {
    40% { transform: translateY(-8px); }
}

/* Brand colour on hover. The footer script turns each icon's artwork
   into a mask (.fun-mask) so it can be filled with any colour; at
   rest it is the artwork's own grey. */
.social-icons > a > div.fun-mask {
    background-image: none;
    background-color: #d8d8d8;
    -webkit-mask: var(--fun-icon) 0 0 / cover no-repeat;
    mask: var(--fun-icon) 0 0 / cover no-repeat;
    transition: opacity 0.15s, background-color 0.2s;
}

.social-icons > a:hover > .icon-facebook.fun-mask  { background-color: #1877f2; }
.social-icons > a:hover > .icon-twitter.fun-mask   { background-color: #ffffff; }
.social-icons > a:hover > .icon-discord.fun-mask   { background-color: #5865f2; }
.social-icons > a:hover > .icon-bsky.fun-mask      { background-color: #1185fe; }
.social-icons > a:hover > .icon-mastodon.fun-mask  { background-color: #6364ff; }
.social-icons > a:hover > .icon-youtube.fun-mask   { background-color: #ff0000; }
.social-icons > a:hover > .icon-tiktok.fun-mask    { background-color: #ff0050; }
.social-icons > a:hover > .icon-threads.fun-mask   { background-color: #ffffff; }
.social-icons > a:hover > .icon-instagram.fun-mask {
    background-image: radial-gradient(circle at 30% 107%, #fdf497 0%, #fdf497 5%, #fd5949 45%, #d6249f 60%, #285aeb 90%);
}

.footer-col > a.label {
    transition: color 0.15s;
}

.footer-col:nth-child(2) > a.label { color: var(--fun-green); }
.footer-col:nth-child(3) > a.label { color: var(--fun-blue); }
.footer-col:nth-child(4) > a.label { color: var(--fun-red); }

/* ── Game and app pages (templates/game.php) ───────────────── */
/* Everything takes the page's own --app accent, so each title
   keeps its identity: Song Skipper glows red, Awaken blue, etc. */

/* Hero card: drifting dot grid, breathing glow and a light that
   sweeps around the border */
.app-page .app-hero {
    background:
        radial-gradient(circle, color-mix(in srgb, var(--app) 10%, transparent) 1.2px, transparent 1.7px) 0 0 / 22px 22px,
        var(--surface);
    animation: fun-grid 40s linear infinite;
}

@keyframes fun-grid {
    to { background-position: 220px 110px, 0 0; }
}

.app-hero::before {
    animation: fun-breathe 7s ease-in-out infinite;
}

@keyframes fun-breathe {
    50% { transform: scale(1.15) translate(-4%, 4%); opacity: 0.75; }
}

.app-hero::after {
    content: "";
    position: absolute;
    inset: 0;
    padding: 1.5px;
    border-radius: inherit;
    background: conic-gradient(from var(--fun-angle, 0deg), transparent 0 62%, var(--app) 80%, color-mix(in srgb, var(--app) 40%, #fff) 84%, transparent 92% 100%);
    -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
    -webkit-mask-composite: xor;
    mask: linear-gradient(#000 0 0) content-box exclude, linear-gradient(#000 0 0);
    pointer-events: none;
    opacity: 0;
    animation: fun-sweep 2.6s ease-in-out 0.3s both;
}

/* One lap around the border on arrival, fading in and out */
@keyframes fun-sweep {
    0%   { --fun-angle: 0deg; opacity: 0; }
    15%  { opacity: 1; }
    80%  { opacity: 1; }
    100% { --fun-angle: 360deg; opacity: 0; }
}

/* Logo: springs in on arrival, then stays put */
.app-hero .game-logo {
    animation: fun-logo-in 0.8s var(--fun-spring) both;
    transform-origin: 20% 80%;
}

@keyframes fun-logo-in {
    from { opacity: 0; scale: 0.7; translate: 0 18px; }
}

/* Badges row: blinking status light, each badge hops on hover */
.app-meta .badge-app::before {
    content: "";
    width: 6px;
    height: 6px;
    background: var(--app);
    box-shadow: 0 0 8px var(--app);
    animation: fun-blink 1.1s steps(2, jump-none) infinite;
}

.app-meta .badge {
    transition: transform 0.25s var(--fun-spring);
}

.app-meta .badge:is(:hover, .fun-hover) {
    transform: translateY(-3px);
}

/* Store buttons: arcade press in the page accent. The lift moves the
   button, so a strip below it keeps the hover from flickering at
   the bottom edge. */
.store-badges > a {
    position: relative;
    border-radius: var(--r-sm);
    transition: transform 0.2s var(--fun-spring), box-shadow 0.2s;
}

.store-badges > a::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    top: 100%;
    height: 6px;
}

.store-badges > a:is(:hover, .fun-hover) {
    transform: translateY(-3px);
    box-shadow: 0 4px 0 color-mix(in srgb, var(--app) 60%, #000), 0 12px 24px color-mix(in srgb, var(--app) 30%, transparent);
}

.store-badges > a:active {
    transform: translateY(1px);
    box-shadow: 0 0 0 color-mix(in srgb, var(--app) 60%, #000);
}

.store-badges > a > div {
    display: block;
}

/* Screenshot viewer: accent glow; tilt and glare follow the cursor
   (footer script) and each new shot lands with a small bounce */
.app-hero .viewer {
    box-shadow: 0 30px 60px rgba(0,0,0,0.5), 0 0 0 1px color-mix(in srgb, var(--app) 35%, transparent), 0 0 46px color-mix(in srgb, var(--app) 22%, transparent);
    will-change: transform;
}

.viewer .fun-glare {
    z-index: 2;
}

.viewer.is-tilting .fun-glare {
    opacity: 1;
}

/* Thumbnails: lift and glow. The slider's clip opens up and down for
   the lift and glow, and only as far sideways as the gap to the
   next (scrolled-away) thumbnail: 12px, or 8px on narrow screens. */
.app-hero .gallery .flickity-viewport {
    overflow: visible;
    clip-path: inset(-14px -10px -30px);
}

@media only screen and (max-width: 980px) {
    .app-hero .gallery .flickity-viewport {
        clip-path: inset(-14px -6px -30px);
    }
}

.app-hero .gallery-cell {
    transition: opacity 0.15s, box-shadow 0.2s, transform 0.25s var(--fun-spring);
}

.app-hero .gallery-cell::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    top: 100%;
    height: 6px;
}

.app-hero .gallery-cell:is(:hover, .fun-hover) {
    transform: translateY(-3px);
}

.app-hero .gallery-cell.selected {
    box-shadow: inset 0 0 0 2px var(--app), 0 8px 16px -6px color-mix(in srgb, var(--app) 55%, transparent);
}

/* Sidebar labels get a little pixel marker in a rotating colour */
.app-side .side-block > .label {
    display: flex;
    align-items: center;
    gap: 8px;
}

.app-side .side-block > .label::before {
    content: "";
    width: 7px;
    height: 7px;
    background: var(--c, var(--app));
    box-shadow: 2px 2px 0 rgba(0,0,0,0.5);
}

.app-side .side-block:nth-child(4n+1) > .label { --c: var(--fun-yellow); }
.app-side .side-block:nth-child(4n+2) > .label { --c: var(--fun-pink); }
.app-side .side-block:nth-child(4n+3) > .label { --c: var(--fun-green); }
.app-side .side-block:nth-child(4n+4) > .label { --c: var(--fun-purple); }

/* Features: pixel diamonds in the palette; hovering a line spins its
   diamond and nudges the line like a menu selection */
.app-side .feature-tags > ul li {
    --c: var(--app);
    transition: color 0.15s, transform 0.25s var(--fun-spring);
}

.app-side .feature-tags > ul li:nth-child(6n+1) { --c: var(--fun-red); }
.app-side .feature-tags > ul li:nth-child(6n+2) { --c: var(--fun-yellow); }
.app-side .feature-tags > ul li:nth-child(6n+3) { --c: var(--fun-green); }
.app-side .feature-tags > ul li:nth-child(6n+4) { --c: var(--fun-blue); }
.app-side .feature-tags > ul li:nth-child(6n+5) { --c: var(--fun-purple); }
.app-side .feature-tags > ul li:nth-child(6n+6) { --c: var(--fun-pink); }

.app-side .feature-tags > ul li::before {
    top: 7px;
    border-radius: 1px;
    background: var(--c);
    transform: rotate(45deg);
    box-shadow: 0 0 8px color-mix(in srgb, var(--c) 60%, transparent);
    transition: transform 0.4s var(--fun-spring);
}

.app-side .feature-tags > ul li:is(:hover, .fun-hover) {
    color: var(--text);
    transform: translateX(4px);
}

.app-side .feature-tags > ul li:is(:hover, .fun-hover)::before {
    transform: rotate(225deg) scale(1.3);
}

/* Genres and languages become pills (split by the footer script);
   genres in the palette, languages neutral */
.fun-pills {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}

.fun-pills > span {
    --c: rgba(255,255,255,0.6);
    padding: 5px 12px;
    border-radius: 999px;
    border: 1px solid color-mix(in srgb, var(--c) 40%, transparent);
    background: color-mix(in srgb, var(--c) 12%, transparent);
    color: color-mix(in srgb, var(--c) 70%, #fff);
    font-family: var(--display);
    font-size: 14px;
    line-height: 1.2;
    transition: transform 0.25s var(--fun-spring), background 0.15s;
}

.fun-pills > span:is(:hover, .fun-hover) {
    transform: translateY(-2px) rotate(-2deg);
    background: color-mix(in srgb, var(--c) 22%, transparent);
}

.fun-pills.is-genres > span:nth-child(6n+1) { --c: var(--fun-red); }
.fun-pills.is-genres > span:nth-child(6n+2) { --c: var(--fun-yellow); }
.fun-pills.is-genres > span:nth-child(6n+3) { --c: var(--fun-green); }
.fun-pills.is-genres > span:nth-child(6n+4) { --c: var(--fun-blue); }
.fun-pills.is-genres > span:nth-child(6n+5) { --c: var(--fun-purple); }
.fun-pills.is-genres > span:nth-child(6n+6) { --c: var(--fun-pink); }

/* What's New: a "NEW!" sticker, an accent version number, and the
   same lift as a news card */
.version-card {
    position: relative;
    transition: border-color 0.2s, transform 0.3s var(--fun-spring), box-shadow 0.25s;
}

.version-card::before {
    content: "NEW!";
    position: absolute;
    top: -12px;
    right: -10px;
    padding: 5px 10px;
    border-radius: 8px;
    background: var(--fun-yellow);
    color: #12141a;
    font-family: var(--display);
    font-weight: bold;
    font-size: 12px;
    letter-spacing: 0.08em;
    box-shadow: 0 3px 0 #a5781a;
    rotate: 8deg;
    animation: fun-sticker 2.4s ease-in-out infinite;
}

@keyframes fun-sticker {
    0%, 100% { rotate: 8deg; scale: 1; }
    50%      { rotate: 4deg; scale: 1.08; }
}

.version-card > header .version-number {
    color: var(--app);
    text-shadow: 2px 2px 0 rgba(0,0,0,0.6);
}

.version-card:is(:hover, .fun-hover) {
    border-color: var(--app);
    transform: translateY(-3px);
    box-shadow: 0 5px 0 color-mix(in srgb, var(--app) 55%, #000), 0 16px 34px rgba(0,0,0,0.35);
}

.version-link::after {
    content: "\25B6";
    font-size: 0.6em;
    transition: transform 0.25s var(--fun-spring);
}

.version-link:hover::after {
    transform: translateX(4px);
}

/* Version history window springs open */
.modal-overlay.active .modal-content {
    animation: fun-modal 0.45s var(--fun-spring);
}

@keyframes fun-modal {
    from { opacity: 0; transform: translateY(24px) scale(0.92); }
}

/* Reading column links get a wavy underline */
.app-page .prose a:hover {
    text-decoration: underline wavy;
    text-underline-offset: 4px;
}

/* Launch list (unreleased games): arcade button; confetti on sign-up
   comes from the footer script */
.notify .notify-row button {
    box-shadow: 0 3px 0 color-mix(in srgb, var(--app) 55%, #000);
    transition: filter 0.15s, transform 0.15s, box-shadow 0.15s;
}

.notify .notify-row button:is(:hover, .fun-hover) {
    transform: translateY(-1px);
    box-shadow: 0 4px 0 color-mix(in srgb, var(--app) 55%, #000);
}

.notify .notify-row button:active {
    transform: translateY(2px);
    box-shadow: 0 0 0 color-mix(in srgb, var(--app) 55%, #000);
}

/* ── News (pages/news.php, templates/news.php) ─────────────── */

/* Card images zoom gently inside their frame on hover (a copy of
   the image on ::after, so the card's own layout never moves) */
.card .card-img {
    position: relative;
    overflow: hidden;
}

.card .card-img::after {
    content: "";
    position: absolute;
    inset: 0;
    background: inherit;
    transition: transform 0.5s cubic-bezier(0.2, 0.7, 0.2, 1);
}

.card:is(:hover, .fun-hover) .card-img::after {
    transform: scale(1.06);
}

/* Dates get a pixel marker in the card's colour */
.card .card-body > .label {
    display: flex;
    align-items: center;
    gap: 8px;
}

.card .card-body > .label::before {
    content: "";
    flex: none;
    width: 7px;
    height: 7px;
    background: var(--c);
    box-shadow: 2px 2px 0 rgba(0,0,0,0.5);
}

/* The newest story on the News page wears the "NEW!" sticker */
.news-list > .card:first-child .card-img::before {
    content: "NEW!";
    position: absolute;
    top: 16px;
    left: 16px;
    z-index: 2;
    padding: 6px 12px;
    border-radius: 8px;
    background: var(--fun-yellow);
    color: #12141a;
    font-family: var(--display);
    font-weight: bold;
    font-size: 13px;
    letter-spacing: 0.08em;
    box-shadow: 0 3px 0 #a5781a;
    rotate: -6deg;
    animation: fun-sticker-l 2.4s ease-in-out infinite;
}

/* The sticker borrows ::before, which also held the 16:9 shape */
.news-list > .card:first-child .card-img {
    aspect-ratio: 16 / 9;
}

@keyframes fun-sticker-l {
    0%, 100% { rotate: -6deg; scale: 1; }
    50%      { rotate: -2deg; scale: 1.08; }
}

/* Article page: retro title, sidebar cards in the palette, a tilt
   on the lead image (footer script) and a sign-off under the story */
.news-title,
.contact-title {
    text-shadow: 3px 3px 0 rgba(155,107,255,0.45);
}

.news-date {
    display: flex;
    align-items: center;
    gap: 8px;
    color: var(--fun-yellow);
}

.news-date::before {
    content: "";
    width: 8px;
    height: 8px;
    background: var(--fun-yellow);
    box-shadow: 2px 2px 0 rgba(0,0,0,0.5);
    animation: fun-blink 1.1s steps(2, jump-none) infinite;
}

.news-side .card:nth-child(4n+2) { --c: var(--fun-pink); }
.news-side .card:nth-child(4n+3) { --c: var(--fun-yellow); }
.news-side .card:nth-child(4n+4) { --c: var(--fun-green); }
.news-side .card:nth-child(4n+5) { --c: var(--fun-purple); }

.news-image {
    position: relative;
    overflow: hidden;
    will-change: transform;
}

.news-image.is-tilting .fun-glare {
    opacity: 1;
}

.news-body::after {
    content: "";
    display: block;
    width: 72px;
    height: 10px;
    margin: 40px 0 0;
    background:
        linear-gradient(var(--fun-red) 0 0) 0 0 / 10px 10px no-repeat,
        linear-gradient(var(--fun-yellow) 0 0) 31px 0 / 10px 10px no-repeat,
        linear-gradient(var(--fun-blue) 0 0) 62px 0 / 10px 10px no-repeat;
}

.news-body a:hover,
.contact .prose a:hover {
    text-decoration: underline wavy;
    text-underline-offset: 4px;
}

/* ── Support (pages/contact-us.php) ─────────────────────────── */

/* "We'll get back to you" light pings like radar */
.contact-promise-dot {
    position: relative;
}

.contact-promise-dot::after {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: 50%;
    background: #3fb950;
    animation: fun-ping 2s cubic-bezier(0, 0, 0.2, 1) infinite;
}

@keyframes fun-ping {
    75%, 100% { transform: scale(3); opacity: 0; }
}

/* Channels light up in their brand colour */
.channel { --brand: var(--fun-blue); }
.channel:has(.icon-twitter)   { --brand: #ffffff; }
.channel:has(.icon-facebook)  { --brand: #1877f2; }
.channel:has(.icon-discord)   { --brand: #5865f2; }
.channel:has(.icon-bsky)      { --brand: #1185fe; }
.channel:has(.icon-mastodon)  { --brand: #6364ff; }
.channel:has(.icon-youtube)   { --brand: #ff0000; }
.channel:has(.icon-instagram) { --brand: #d6249f; }

.contact .channel {
    transition: border-color 0.15s, background 0.15s, transform 0.25s var(--fun-spring), box-shadow 0.2s;
}

.contact .channel:is(:hover, .fun-hover) {
    border-color: var(--brand);
    background: color-mix(in srgb, var(--brand) 8%, var(--surface));
    transform: translateY(-3px);
    box-shadow: 0 4px 0 color-mix(in srgb, var(--brand) 50%, #000);
}

.contact .channel .channel-ico {
    transition: background 0.2s, border-color 0.2s, transform 0.35s var(--fun-spring), color 0.2s;
}

.contact .channel:is(:hover, .fun-hover) .channel-ico {
    background: color-mix(in srgb, var(--brand) 18%, transparent);
    border-color: color-mix(in srgb, var(--brand) 45%, transparent);
    color: var(--brand);
    transform: rotate(-8deg) scale(1.08);
}

.channel-ico > span.fun-mask {
    background-image: none;
    background-color: #d8d8d8;
    -webkit-mask: var(--fun-icon) 0 0 / cover no-repeat;
    mask: var(--fun-icon) 0 0 / cover no-repeat;
    transition: background-color 0.2s;
}

.contact .channel:is(:hover, .fun-hover) .channel-ico > span.fun-mask {
    background-color: var(--brand);
    filter: none;
}

.contact .channel:is(:hover, .fun-hover):has(.icon-instagram) .channel-ico > span.fun-mask {
    background-image: radial-gradient(circle at 30% 107%, #fdf497 0%, #fdf497 5%, #fd5949 45%, #d6249f 60%, #285aeb 90%);
}

/* Form card: one lap of light around the border on arrival, in the
   chosen product's colour */
.contact-card::after {
    content: "";
    position: absolute;
    inset: 0;
    padding: 1.5px;
    border-radius: inherit;
    background: conic-gradient(from var(--fun-angle, 0deg), transparent 0 62%, var(--app) 80%, color-mix(in srgb, var(--app) 40%, #fff) 84%, transparent 92% 100%);
    -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
    -webkit-mask-composite: xor;
    mask: linear-gradient(#000 0 0) content-box exclude, linear-gradient(#000 0 0);
    pointer-events: none;
    opacity: 0;
    animation: fun-sweep 2.6s ease-in-out 0.3s both;
}

/* Product tiles: lift and a wobbly icon on hover; picking one
   springs it and pops its check mark */
.contact .product-face {
    transition: border-color 0.15s, background 0.15s, transform 0.25s var(--fun-spring), box-shadow 0.2s;
}

.contact .product:is(:hover, .fun-hover) .product-face {
    transform: translateY(-3px);
    box-shadow: 0 4px 0 color-mix(in srgb, var(--tile) 45%, #000);
}

.contact .product .product-icon,
.contact .product .product-glyph {
    transition: transform 0.35s var(--fun-spring);
}

.contact .product:is(:hover, .fun-hover) .product-icon,
.contact .product:is(:hover, .fun-hover) .product-glyph {
    transform: rotate(-8deg) scale(1.1);
}

.contact .product input:checked + .product-face {
    animation: fun-pick 0.45s var(--fun-spring);
}

.contact .product input:checked + .product-face .product-check {
    transition: opacity 0.15s, transform 0.4s var(--fun-spring);
}

@keyframes fun-pick {
    0%   { scale: 1; }
    35%  { scale: 0.95; }
    100% { scale: 1; }
}

/* Topic and platform chips: hop on hover, spring when picked */
.contact .chip > span {
    transition: border-color 0.15s, background 0.15s, color 0.15s, transform 0.25s var(--fun-spring);
}

.contact .chip:is(:hover, .fun-hover) > span {
    transform: translateY(-2px);
}

.contact .chip input:checked + span {
    animation: fun-pick 0.45s var(--fun-spring);
}

/* Sent: the check mark bounces in (confetti from the footer script) */
.contact-sent .sent-mark {
    animation: fun-logo-in 0.7s var(--fun-spring) 0.15s both;
}

/* ── Privacy policy (pages/privacy-policy.php) ──────────────── */
.privacy-title {
    text-shadow: 3px 3px 0 rgba(155,107,255,0.45);
}

.privacy-date {
    display: flex;
    align-items: center;
    gap: 8px;
    color: var(--fun-green);
}

.privacy-date::before {
    content: "";
    width: 8px;
    height: 8px;
    background: var(--fun-green);
    box-shadow: 2px 2px 0 rgba(0,0,0,0.5);
    animation: fun-blink 1.1s steps(2, jump-none) infinite;
}

.privacy-body a:hover {
    text-decoration: underline wavy;
    text-underline-offset: 4px;
}

.privacy-body::after {
    content: "";
    display: block;
    width: 72px;
    height: 10px;
    margin: 32px 0 0;
    background:
        linear-gradient(var(--fun-red) 0 0) 0 0 / 10px 10px no-repeat,
        linear-gradient(var(--fun-yellow) 0 0) 31px 0 / 10px 10px no-repeat,
        linear-gradient(var(--fun-blue) 0 0) 62px 0 / 10px 10px no-repeat;
}

/* ── Easter egg: confetti + toast (↑↑↓↓←→←→BA) ─────────────── */
.fun-confetti {
    position: fixed;
    top: 0;
    left: 0;
    width: 8px;
    height: 8px;
    z-index: 1000;
    pointer-events: none;
}

.fun-toast {
    position: fixed;
    left: 50%;
    top: 30%;
    z-index: 1001;
    translate: -50% 0;
    padding: 18px 28px;
    border-radius: 14px;
    background: #12141a;
    border: 3px solid var(--fun-yellow);
    box-shadow: 0 6px 0 #a5781a, 0 30px 60px rgba(0,0,0,0.6);
    font-family: var(--display);
    font-weight: bold;
    font-size: 28px;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    text-align: center;
    color: var(--fun-yellow);
    pointer-events: none;
    animation: fun-toast 2.6s var(--fun-spring) forwards;
}

.fun-toast small {
    display: block;
    margin-top: 6px;
    font-size: 13px;
    letter-spacing: 0.12em;
    color: var(--text-2);
}

@keyframes fun-toast {
    0%   { scale: 0.4; opacity: 0; }
    12%  { scale: 1; opacity: 1; }
    85%  { scale: 1; opacity: 1; }
    100% { scale: 0.9; opacity: 0; }
}

/* Party mode after the code: accents cycle through the rainbow */
body.fun-party .tile-img,
body.fun-party .hero-frame {
    animation: fun-hue 3s linear infinite;
}

@keyframes fun-hue {
    to { filter: hue-rotate(360deg); }
}

@media only screen and (max-width: 540px) {
    .sec-head h1::before,
    .sec-head h2::before {
        width: 10px;
        height: 12px;
    }
}

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

    .fun-pop {
        opacity: 1;
        translate: none;
        scale: none;
    }
}
