/* geoguess.es — pixel icons (DECISIONS #29; js/ui/pixel.js draws them, js/ui/px/registry.js documents the letters).
   The palette letters map to these --px-* tokens; the hues are the site's own (tokens.css), so Day and Night follow the
   theme. Pixel art keeps a DARK outline at Night (the fills carry the shape on the dark ground) and a warm highlight.
   The skin pair (--px-e*) is the one place a hex appears outside tokens.css: it is art, not UI colour, and has no
   token equivalent. Hover motion lives at the end of this file. */
:root {
  --px-k: var(--ink);
  --px-w: color-mix(in srgb, var(--raised) 80%, white);
  --px-n: color-mix(in srgb, var(--ink) 45%, var(--paper));
  --px-n2: var(--ink-2);
  --px-l: var(--line-2);
  --px-r: var(--rose);   --px-r2: var(--rose-ink);   --px-r1: var(--rose-wash);
  --px-p: var(--plum);   --px-p2: var(--plum-ink);   --px-p1: var(--plum-wash);
  --px-s: var(--sky);    --px-s2: var(--sky-ink);    --px-s1: var(--sky-wash);
  --px-t: var(--teal);   --px-t2: var(--teal-ink);   --px-t1: var(--teal-wash);
  --px-g: var(--green);  --px-g2: var(--green-ink);  --px-g1: var(--green-wash);
  --px-o: var(--ochre);  --px-o2: var(--ochre-ink);  --px-o1: var(--ochre-wash);
  --px-b: var(--action); --px-b2: color-mix(in srgb, var(--action) 72%, black); --px-b1: var(--action-wash);
  --px-v: var(--signal); --px-v2: var(--signal-ink); --px-v1: var(--signal-wash);
  --px-y: var(--brass);  --px-y2: color-mix(in srgb, var(--brass) 65%, black); --px-y1: color-mix(in srgb, var(--brass) 35%, var(--raised));
  --px-e: #f1c9a5;  --px-e2: #c98e64;
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --px-k: color-mix(in srgb, var(--paper) 40%, black); --px-w: #f4efe4;
    /* keep the light ramp in order at Night (the -ink tokens turn LIGHTER and the washes near-black there): deep = hue + black, wash = hue + white */
    --px-n2: color-mix(in srgb, var(--ink) 24%, var(--paper)); --px-l: color-mix(in srgb, var(--ink) 74%, var(--paper));
    --px-r2: color-mix(in srgb, var(--rose) 62%, black); --px-r1: color-mix(in srgb, var(--rose) 42%, white);
    --px-p2: color-mix(in srgb, var(--plum) 62%, black); --px-p1: color-mix(in srgb, var(--plum) 42%, white);
    --px-s2: color-mix(in srgb, var(--sky) 62%, black); --px-s1: color-mix(in srgb, var(--sky) 42%, white);
    --px-t2: color-mix(in srgb, var(--teal) 62%, black); --px-t1: color-mix(in srgb, var(--teal) 42%, white);
    --px-g2: color-mix(in srgb, var(--green) 62%, black); --px-g1: color-mix(in srgb, var(--green) 42%, white);
    --px-o2: color-mix(in srgb, var(--ochre) 62%, black); --px-o1: color-mix(in srgb, var(--ochre) 42%, white);
    --px-b2: color-mix(in srgb, var(--action) 62%, black); --px-b1: color-mix(in srgb, var(--action) 42%, white);
    --px-v2: color-mix(in srgb, var(--signal) 62%, black); --px-v1: color-mix(in srgb, var(--signal) 42%, white);
    --px-y2: color-mix(in srgb, var(--brass) 62%, black); --px-y1: color-mix(in srgb, var(--brass) 42%, white);
  }
}
:root[data-theme="dark"] {
    --px-k: color-mix(in srgb, var(--paper) 40%, black); --px-w: #f4efe4;
    /* keep the light ramp in order at Night (the -ink tokens turn LIGHTER and the washes near-black there): deep = hue + black, wash = hue + white */
    --px-n2: color-mix(in srgb, var(--ink) 24%, var(--paper)); --px-l: color-mix(in srgb, var(--ink) 74%, var(--paper));
    --px-r2: color-mix(in srgb, var(--rose) 62%, black); --px-r1: color-mix(in srgb, var(--rose) 42%, white);
    --px-p2: color-mix(in srgb, var(--plum) 62%, black); --px-p1: color-mix(in srgb, var(--plum) 42%, white);
    --px-s2: color-mix(in srgb, var(--sky) 62%, black); --px-s1: color-mix(in srgb, var(--sky) 42%, white);
    --px-t2: color-mix(in srgb, var(--teal) 62%, black); --px-t1: color-mix(in srgb, var(--teal) 42%, white);
    --px-g2: color-mix(in srgb, var(--green) 62%, black); --px-g1: color-mix(in srgb, var(--green) 42%, white);
    --px-o2: color-mix(in srgb, var(--ochre) 62%, black); --px-o1: color-mix(in srgb, var(--ochre) 42%, white);
    --px-b2: color-mix(in srgb, var(--action) 62%, black); --px-b1: color-mix(in srgb, var(--action) 42%, white);
    --px-v2: color-mix(in srgb, var(--signal) 62%, black); --px-v1: color-mix(in srgb, var(--signal) 42%, white);
    --px-y2: color-mix(in srgb, var(--brass) 62%, black); --px-y1: color-mix(in srgb, var(--brass) 42%, white);
}

.px { display: inline-flex; line-height: 0; flex: none; }
.px-svg { display: block; overflow: visible; }
.px-c-k { fill: var(--px-k); }   .px-c-w { fill: var(--px-w); }   .px-c-n { fill: var(--px-n); }
.px-c-n2 { fill: var(--px-n2); } .px-c-l { fill: var(--px-l); }
.px-c-r { fill: var(--px-r); }   .px-c-r2 { fill: var(--px-r2); } .px-c-r1 { fill: var(--px-r1); }
.px-c-p { fill: var(--px-p); }   .px-c-p2 { fill: var(--px-p2); } .px-c-p1 { fill: var(--px-p1); }
.px-c-s { fill: var(--px-s); }   .px-c-s2 { fill: var(--px-s2); } .px-c-s1 { fill: var(--px-s1); }
.px-c-t { fill: var(--px-t); }   .px-c-t2 { fill: var(--px-t2); } .px-c-t1 { fill: var(--px-t1); }
.px-c-g { fill: var(--px-g); }   .px-c-g2 { fill: var(--px-g2); } .px-c-g1 { fill: var(--px-g1); }
.px-c-o { fill: var(--px-o); }   .px-c-o2 { fill: var(--px-o2); } .px-c-o1 { fill: var(--px-o1); }
.px-c-b { fill: var(--px-b); }   .px-c-b2 { fill: var(--px-b2); } .px-c-b1 { fill: var(--px-b1); }
.px-c-v { fill: var(--px-v); }   .px-c-v2 { fill: var(--px-v2); } .px-c-v1 { fill: var(--px-v1); }
.px-c-y { fill: var(--px-y); }   .px-c-y2 { fill: var(--px-y2); } .px-c-y1 { fill: var(--px-y1); }
.px-c-e { fill: var(--px-e); }   .px-c-e2 { fill: var(--px-e2); }
.px-missing-box { fill: none; stroke: var(--signal); stroke-width: 1; stroke-dasharray: 2 2; }
.px-layer-alt, .px-layer-on { visibility: hidden; }

/* ---- hover motion: the shell agent (DECISIONS #29) owns everything below this line ---- */
/* Every pixel icon (js/ui/pixel.js) names its motion in data-anim; it plays ONCE each time its nearest hover host is
   hovered, keyboard-focused (or holds a focused control), or carries .is-hover — and never on its own. The motion
   moves in whole art pixels and holds each frame (steps), so it reads as sprite animation, not tweening: translations
   are in % of the icon (6.25 % = one pixel of a 16-grid icon, two of a 32-grid illustration). Layers: `alt` flashes in
   during the middle of the motion (a blink, a flap, a spark); `on` shows for as long as the host is hovered.
   Hover hosts: [data-hover-host] (put it on any row, tile or control that holds an icon) plus the shared controls
   that are always hosts — buttons, icon buttons, chips, tabs, menu items, sidebar / sheet rows, tiles, rows, links
   to stats, search hits. Reduced motion (the OS, or Settings → Reduce motion): no motion and no flash at all; the
   `on` layer still shows (a state, not a motion). */
.px-svg { transform-origin: var(--px-origin, 50% 50%); }
.px[data-anim="hop"]    { --px-anim: px-hop;    --px-dur: 520ms; --px-origin: 50% 100%; }
.px[data-anim="wiggle"] { --px-anim: px-wiggle; --px-dur: 480ms; --px-origin: 50% 70%; }
.px[data-anim="spin"]   { --px-anim: px-spin;   --px-dur: 560ms; }
.px[data-anim="blink"]  { --px-anim: px-blink;  --px-dur: 440ms; --px-origin: 50% 55%; }
.px[data-anim="wave"]   { --px-anim: px-wave;   --px-dur: 640ms; --px-origin: 50% 92%; }
.px[data-anim="flip"]   { --px-anim: px-flip;   --px-dur: 560ms; }
.px[data-anim="pulse"]  { --px-anim: px-pulse;  --px-dur: 520ms; }
.px[data-anim="shine"]  { --px-anim: px-shine;  --px-dur: 600ms; --px-origin: 50% 100%; }
.px[data-anim="drop"]   { --px-anim: px-drop;   --px-dur: 560ms; --px-origin: 50% 100%; }
.px[data-anim="nudge"]  { --px-anim: px-nudge;  --px-dur: 480ms; }
.px[data-anim="tick"]   { --px-anim: px-tick;   --px-dur: 600ms; --px-origin: 50% 12%; }
.px[data-anim="bob"]    { --px-anim: px-bob;    --px-dur: 700ms; }
.px[data-anim="ring"]   { --px-anim: px-ring;   --px-dur: 640ms; --px-origin: 50% 8%; }

/* the hosts — keep this list in step with FINAL.md §15 */
:is([data-hover-host], .btn, .icon-btn, .chip, [role="tab"], [role="menuitem"], [role="menuitemcheckbox"], [role="menuitemradio"], .menu-item, .nv-row, .nv-me, .ms-link, .bx-tile, a.bx-row, button.bx-row, a.list-row, a.stat, a.card, .search-hit):is(:hover, :focus-visible, :has(:focus-visible), .is-hover) .px[data-anim] > .px-svg,
.px[data-anim]:hover > .px-svg {
  animation: var(--px-anim) var(--px-dur) steps(1, end) 1;
}
:is([data-hover-host], .btn, .icon-btn, .chip, [role="tab"], [role="menuitem"], [role="menuitemcheckbox"], [role="menuitemradio"], .menu-item, .nv-row, .nv-me, .ms-link, .bx-tile, a.bx-row, button.bx-row, a.list-row, a.stat, a.card, .search-hit):is(:hover, :focus-visible, :has(:focus-visible), .is-hover) .px > .px-svg > .px-layer-alt,
.px:hover > .px-svg > .px-layer-alt {
  animation: px-alt var(--px-dur, 560ms) steps(1, end) 1;
}
:is([data-hover-host], .btn, .icon-btn, .chip, [role="tab"], [role="menuitem"], [role="menuitemcheckbox"], [role="menuitemradio"], .menu-item, .nv-row, .nv-me, .ms-link, .bx-tile, a.bx-row, button.bx-row, a.list-row, a.stat, a.card, .search-hit):is(:hover, :focus-visible, :has(:focus-visible), .is-hover) .px > .px-svg > .px-layer-on,
.px:hover > .px-svg > .px-layer-on { visibility: visible; }

/* the frames (each keyframe holds until the next: steps(1, end)) */
@keyframes px-alt    { 0% { visibility: hidden; } 22% { visibility: visible; } 78% { visibility: hidden; } }
@keyframes px-hop    { 0% { transform: none; } 15% { transform: translateY(-6.25%); } 30% { transform: translateY(-12.5%); } 55% { transform: translateY(-6.25%); } 72% { transform: none; } 84% { transform: translateY(-3.125%); } 100% { transform: none; } }
@keyframes px-wiggle { 0% { transform: none; } 16% { transform: rotate(-9deg); } 33% { transform: rotate(9deg); } 50% { transform: rotate(-9deg); } 67% { transform: rotate(6deg); } 84% { transform: none; } }
@keyframes px-spin   { 0% { transform: none; } 20% { transform: rotate(90deg); } 40% { transform: rotate(180deg); } 60% { transform: rotate(270deg); } 80% { transform: rotate(360deg); } 100% { transform: none; } }
@keyframes px-blink  { 0% { transform: none; } 30% { transform: scaleY(.5); } 45% { transform: scaleY(.25); } 62% { transform: scaleY(.5); } 78% { transform: none; } }
@keyframes px-wave   { 0% { transform: none; } 14% { transform: rotate(14deg); } 30% { transform: rotate(-8deg); } 46% { transform: rotate(14deg); } 62% { transform: rotate(-8deg); } 80% { transform: rotate(6deg); } 92% { transform: none; } }
@keyframes px-flip   { 0% { transform: none; } 18% { transform: scaleX(.5); } 36% { transform: scaleX(.125); } 54% { transform: scaleX(.5); } 72% { transform: none; } 86% { transform: translateY(-6.25%); } 100% { transform: none; } }
@keyframes px-pulse  { 0% { transform: none; } 20% { transform: scale(1.125); } 40% { transform: none; } 60% { transform: scale(1.125); } 80% { transform: none; } }
@keyframes px-shine  { 0% { transform: none; filter: none; } 18% { transform: translateY(-6.25%); filter: brightness(1.18); } 40% { transform: translateY(-6.25%); filter: brightness(1.4) saturate(1.15); } 62% { transform: translateY(-6.25%); filter: brightness(1.18); } 80% { transform: none; filter: none; } }
@keyframes px-drop   { 0% { transform: translateY(-25%); } 18% { transform: translateY(-12.5%); } 34% { transform: none; } 52% { transform: translateY(-6.25%); } 68% { transform: none; } }
@keyframes px-nudge  { 0% { transform: none; } 16% { transform: translateX(6.25%); } 32% { transform: translateX(12.5%); } 50% { transform: translateX(6.25%); } 66% { transform: translateX(12.5%); } 84% { transform: none; } }
@keyframes px-tick   { 0% { transform: none; } 16% { transform: rotate(10deg); } 33% { transform: none; } 50% { transform: rotate(-10deg); } 67% { transform: none; } 84% { transform: rotate(5deg); } 100% { transform: none; } }
@keyframes px-bob    { 0% { transform: none; } 20% { transform: translateY(-6.25%); } 45% { transform: translateY(-12.5%); } 65% { transform: translateY(-6.25%); } 85% { transform: none; } }
@keyframes px-ring   { 0% { transform: none; } 12% { transform: rotate(16deg); } 26% { transform: rotate(-16deg); } 40% { transform: rotate(11deg); } 54% { transform: rotate(-11deg); } 68% { transform: rotate(5deg); } 82% { transform: none; } }

/* reduced motion: nothing moves or flashes (base.css also shortens every animation; this makes it explicit) */
@media (prefers-reduced-motion: reduce) {
  .px .px-svg, .px .px-layer-alt { animation: none !important; }
}
:root[data-motion="reduce"] :is(.px .px-svg, .px .px-layer-alt) { animation: none !important; }
/* a pixel icon in a muted (disabled) control does not play */
:is(:disabled, [aria-disabled="true"]) .px .px-svg, :is(:disabled, [aria-disabled="true"]) .px .px-layer-alt { animation: none !important; }
