/*
 * Calhou.me! motion system (UI v2). Loaded on every page by the Layout, after app.css.
 *
 * Tokens (custom properties on :root):
 *   --dur-fast 120ms, --dur 220ms, --dur-slow 420ms
 *   --ease-out (snappy), --ease-in-out, --ease-back (small overshoot), --ease-pixel steps(4)
 *   --press-depth (pressed-button travel, default 4px)
 *
 * Utility classes:
 *   .anim-pop       scale-in with a pixel overshoot (use on things that appear)
 *   .anim-slide-up  rise + fade in
 *   .anim-fade      fade in
 *   .anim-bob       gentle idle bob (sprites, icons)
 *   .anim-delay-1..4  stagger helpers (60 ms steps)
 *   .press          game-button press: translateY + shadow shrink on :active
 *   .focus-ring     pixel focus ring (yellow + dark offset) on :focus-visible
 *   .icon           base class of every pixel icon <svg> (src/views/icons.tsx)
 *
 * Game buttons (pixel 3D edge, press effect, 48 px touch target):
 *   .btn-pixel                       base (yellow)
 *   .btn-pixel.btn-pixel--pink       pink (sharing, src/views/share-button.tsx)
 *   .btn-pixel.btn-pixel--ghost      dark, outlined (secondary actions)
 *   .btn-pixel.btn-pixel--sm         compact
 *   [aria-disabled="true"] / [disabled]  disabled look, no press
 *
 * <details>: every details on the site animates open/close (except .reveal on the
 * result page and anything with .no-anim). Native via ::details-content +
 * interpolate-size where supported; public/js/details-anim.js animates height
 * elsewhere. No-JS and keyboard keep the native behaviour.
 *
 * Modals (src/views/modal.tsx + public/js/modal.js): .modal, .modal-box, .modal-head,
 * .modal-title, .modal-close, .modal-body, .modal-foot; html.modal-open locks scroll.
 *
 * Page transitions: cross-document View Transitions (@view-transition) with a short
 * stepped retro wipe. Everything here is disabled under prefers-reduced-motion.
 */

:root {
  --dur-fast: 120ms;
  --dur: 220ms;
  --dur-slow: 420ms;
  --ease-out: cubic-bezier(0.2, 0.8, 0.2, 1);
  --ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);
  --ease-back: cubic-bezier(0.34, 1.56, 0.64, 1);
  --ease-pixel: steps(4, end);
  --press-depth: 4px;
  --pink: #ff6fae;
  --pink-dark: #b8336a;
  --pink-light: #ffc4de;
}

/* ---------- Icons ---------- */

.icon {
  display: inline-block;
  flex: none;
  vertical-align: middle;
  image-rendering: pixelated;
}

/* ---------- Keyframes ---------- */

@keyframes calhou-pop {
  0% { opacity: 0; transform: scale(0.6); }
  60% { opacity: 1; transform: scale(1.06); }
  100% { opacity: 1; transform: scale(1); }
}

@keyframes calhou-slide-up {
  from { opacity: 0; transform: translateY(16px); }
  to { opacity: 1; transform: none; }
}

@keyframes calhou-fade {
  from { opacity: 0; }
  to { opacity: 1; }
}

@keyframes calhou-fade-out {
  from { opacity: 1; }
  to { opacity: 0; }
}

@keyframes calhou-bob {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-4px); }
}

/* Pixel "blip" pop for modals: stepped scale, like an old console window. */
@keyframes calhou-blip-in {
  0% { opacity: 0; transform: scale(0.2, 0.05); }
  40% { opacity: 1; transform: scale(1.04, 0.1); }
  70% { transform: scale(1.02, 1.04); }
  100% { opacity: 1; transform: none; }
}

@keyframes calhou-blip-out {
  0% { opacity: 1; transform: none; }
  50% { opacity: 1; transform: scale(1.02, 0.1); }
  100% { opacity: 0; transform: scale(0.2, 0.05); }
}

@keyframes calhou-sheet-in {
  from { transform: translateY(100%); }
  to { transform: none; }
}

@keyframes calhou-sheet-out {
  from { transform: none; }
  to { transform: translateY(100%); }
}

@keyframes calhou-wipe-in {
  from { clip-path: inset(0 100% 0 0); }
  to { clip-path: inset(0 0 0 0); }
}

/* ---------- Utility animations ---------- */

@media (prefers-reduced-motion: no-preference) {
  .anim-pop { animation: calhou-pop var(--dur-slow) var(--ease-out) both; }
  .anim-slide-up { animation: calhou-slide-up var(--dur-slow) var(--ease-out) both; }
  .anim-fade { animation: calhou-fade var(--dur) ease-out both; }
  .anim-bob { animation: calhou-bob 1.6s steps(4, end) infinite; }
  .anim-delay-1 { animation-delay: 60ms; }
  .anim-delay-2 { animation-delay: 120ms; }
  .anim-delay-3 { animation-delay: 180ms; }
  .anim-delay-4 { animation-delay: 240ms; }
}

/* ---------- Focus ring ---------- */

.focus-ring:focus-visible,
.btn-pixel:focus-visible,
.modal-close:focus-visible {
  outline: 3px solid var(--accent);
  outline-offset: 3px;
  box-shadow: 0 0 0 6px var(--deep);
}

/* ---------- Game buttons ---------- */

.btn-pixel {
  --btn-bg: var(--accent);
  --btn-bg-hover: #ffdc5c;
  --btn-fg: var(--stage);
  --btn-edge: var(--accent-dark);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  min-height: 48px;
  padding: 10px 18px;
  margin-bottom: var(--press-depth);
  border: 0;
  border-radius: 2px;
  background: var(--btn-bg);
  color: var(--btn-fg);
  font-family: var(--body-font);
  font-size: 1rem;
  font-weight: 800;
  line-height: 1.25;
  text-align: center;
  text-decoration: none;
  cursor: pointer;
  box-shadow:
    0 var(--press-depth) 0 0 var(--btn-edge),
    0 calc(var(--press-depth) + 3px) 0 0 var(--deep);
  transition:
    transform var(--dur-fast) steps(2, end),
    box-shadow var(--dur-fast) steps(2, end),
    background-color var(--dur-fast) linear;
}

.btn-pixel:hover {
  background: var(--btn-bg-hover);
  color: var(--btn-fg);
}

.btn-pixel:active,
.press:active {
  transform: translateY(var(--press-depth));
  box-shadow:
    0 0 0 0 var(--btn-edge, var(--accent-dark)),
    0 3px 0 0 var(--deep);
}

.btn-pixel--pink {
  --btn-bg: var(--pink);
  --btn-bg-hover: #ff8cc0;
  --btn-fg: #2a0f1d;
  --btn-edge: var(--pink-dark);
}

/* The pink heart sits in a dark pixel chip so it pops on the pink button. */
.share-wa-icon {
  display: inline-flex;
  padding: 4px;
  margin-left: -6px;
  background: #3a1428;
  box-shadow: inset 0 -3px 0 0 #24091a;
  border-radius: 2px;
  line-height: 0;
}

.btn-pixel--ghost {
  --btn-bg: var(--stage-2);
  --btn-bg-hover: var(--edge);
  --btn-fg: var(--text);
  --btn-edge: var(--edge);
}

.btn-pixel--sm {
  min-height: 48px;
  padding: 8px 14px;
  font-size: 0.9375rem;
}

.btn-pixel[aria-disabled="true"],
.btn-pixel[disabled] {
  --btn-bg: var(--stage-2);
  --btn-bg-hover: var(--stage-2);
  --btn-fg: var(--muted);
  --btn-edge: var(--edge);
  cursor: not-allowed;
  opacity: 0.75;
}

.btn-pixel[aria-disabled="true"]:active,
.btn-pixel[disabled]:active {
  transform: none;
  box-shadow:
    0 var(--press-depth) 0 0 var(--btn-edge),
    0 calc(var(--press-depth) + 3px) 0 0 var(--deep);
}

/* Little hop of the icon on hover: feels like a game cursor. */
@media (prefers-reduced-motion: no-preference) {
  .btn-pixel:not([aria-disabled="true"]):hover .icon {
    animation: calhou-bob 600ms steps(2, end) infinite;
  }
}

/* ---------- Animated <details> ---------- */

@supports (interpolate-size: allow-keywords) {
  :root {
    interpolate-size: allow-keywords;
  }
}

@media (prefers-reduced-motion: no-preference) {
  details:not(.reveal):not(.no-anim)::details-content {
    block-size: 0;
    overflow-y: clip;
    opacity: 0;
    transition:
      block-size var(--dur) var(--ease-out),
      opacity var(--dur) ease-out,
      content-visibility var(--dur) allow-discrete;
  }

  details:not(.reveal):not(.no-anim)[open]::details-content {
    block-size: auto;
    opacity: 1;
  }

  /* Chevrons and +/- markers turn smoothly. */
  .faq-item > summary::after,
  .collapsible > summary::after {
    transition: transform var(--dur) var(--ease-back);
  }
}

/* JS fallback (details-anim.js) keeps the content clipped while it animates. */
details.is-animating {
  overflow: hidden;
}

/* ---------- Modals ---------- */

html.modal-open {
  overflow: hidden;
}

.modal {
  width: min(40rem, calc(100% - 32px));
  max-width: none;
  max-height: min(88vh, 52rem);
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--text);
  overflow: visible;
  outline: none;
}

.modal:focus,
.modal:focus-visible {
  outline: none;
}

.modal::backdrop {
  background: rgba(8, 11, 26, 0.78);
  /* A faint scanline grid on the backdrop. */
  background-image: repeating-linear-gradient(0deg, rgba(255, 255, 255, 0.03) 0 2px, transparent 2px 4px);
}

.modal-box {
  display: flex;
  flex-direction: column;
  max-height: min(88vh, 52rem);
  background: var(--stage);
  border: 4px solid var(--edge);
  box-shadow:
    0 0 0 4px var(--deep),
    0 12px 0 4px var(--deep);
  outline: none;
}

.modal-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 10px 10px 10px 20px;
  background: var(--stage-2);
  border-bottom: 4px solid var(--edge);
}

.modal-title {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 0;
  font-family: var(--pixel-font);
  font-weight: 400;
  font-size: 0.9375rem;
  line-height: 1.5;
  color: var(--accent);
  text-shadow: 2px 2px 0 var(--deep);
}

.modal-close {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 48px;
  height: 48px;
  flex: none;
  color: var(--text);
  background: var(--stage);
  border: 3px solid var(--edge);
  border-radius: 2px;
  cursor: pointer;
  text-decoration: none;
  transition: color var(--dur-fast) linear, border-color var(--dur-fast) linear, transform var(--dur-fast) steps(2, end);
}

.modal-close:hover {
  color: var(--accent);
  border-color: var(--accent);
}

.modal-close:active {
  transform: translateY(2px);
}

.modal-body {
  position: relative;
  padding: 20px;
  overflow-y: auto;
  overscroll-behavior: contain;
}

.modal-body > :last-child {
  margin-bottom: 0;
}

/* 8-bit scrollbar (public/js/modal.js pxScroll): always visible, unlike overlay scrollbars. */
.px-scroll-wrap {
  display: flex;
  flex: 1 1 auto;
  min-height: 0;
}

.px-scroll-wrap > .modal-body {
  flex: 1 1 auto;
  min-width: 0;
}

.modal-body.has-px-scroll {
  scrollbar-width: none;
}

.modal-body.has-px-scroll::-webkit-scrollbar {
  display: none;
}

.px-scroll {
  display: flex;
  flex-direction: column;
  flex: none;
  width: 20px;
  margin: 8px 8px 8px 0;
  user-select: none;
  -webkit-user-select: none;
  touch-action: none;
}

.px-scroll[hidden] {
  display: none;
}

.px-scroll-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  flex: none;
  width: 20px;
  height: 20px;
  padding: 0;
  border: 0;
  background: var(--stage-2);
  color: var(--accent);
  box-shadow: inset -2px -2px 0 0 var(--deep), inset 2px 2px 0 0 var(--edge);
  cursor: pointer;
}

.px-scroll-btn svg {
  fill: currentColor;
  shape-rendering: crispEdges;
}

.px-scroll-down svg {
  transform: scaleY(-1);
}

.px-scroll-btn:hover {
  background: var(--edge);
}

.px-scroll-btn:active {
  box-shadow: inset 2px 2px 0 0 var(--deep);
}

.px-scroll-track {
  position: relative;
  flex: 1 1 auto;
  margin: 4px 0;
  /* A dotted pixel rail. */
  background:
    repeating-linear-gradient(0deg, transparent 0 4px, rgba(255, 255, 255, 0.06) 4px 8px),
    var(--deep);
  box-shadow: inset 0 0 0 2px var(--edge);
  cursor: pointer;
}

.px-scroll-thumb {
  position: absolute;
  top: 0;
  left: 2px;
  right: 2px;
  background: var(--accent);
  /* Bevel in hard steps: light top-left, dark bottom-right, a grip in the middle. */
  box-shadow:
    inset 2px 2px 0 0 #ffe98a,
    inset -2px -2px 0 0 var(--accent-dark);
  background-image: linear-gradient(
    var(--accent) 0 calc(50% - 6px),
    var(--accent-dark) calc(50% - 6px) calc(50% - 4px),
    var(--accent) calc(50% - 4px) calc(50% - 1px),
    var(--accent-dark) calc(50% - 1px) calc(50% + 1px),
    var(--accent) calc(50% + 1px) calc(50% + 4px),
    var(--accent-dark) calc(50% + 4px) calc(50% + 6px),
    var(--accent) calc(50% + 6px)
  );
  cursor: grab;
}

.px-scroll-thumb.is-dragging {
  cursor: grabbing;
  background-color: #ffe98a;
}

.modal-body .card {
  background: var(--stage-2);
}

.modal-body h3 {
  margin: 0 0 12px;
  font-size: 1.25rem;
  color: var(--accent);
}

.modal-foot {
  margin: 20px 0 0;
  font-size: 1rem;
  color: var(--muted);
  text-align: center;
}

@media (prefers-reduced-motion: no-preference) {
  .modal[open] .modal-box {
    animation: calhou-blip-in var(--dur-slow) var(--ease-pixel) both;
  }
  .modal[open]::backdrop {
    animation: calhou-fade var(--dur) ease-out both;
  }
  .modal.is-closing .modal-box {
    animation: calhou-blip-out var(--dur) var(--ease-pixel) both;
  }
  .modal.is-closing::backdrop {
    animation: calhou-fade-out var(--dur) ease-in both;
  }
}

/* Phones: full-height sheet sliding up from the bottom. */
@media (max-width: 600px) {
  .modal {
    width: 100%;
    height: 100%;
    max-height: none;
    margin: 0;
    inset: 0;
  }
  .modal-box {
    height: 100%;
    max-height: none;
    border-width: 4px 0 0;
    box-shadow: none;
  }
  .modal-head {
    padding-left: 16px;
  }
  .modal-body {
    padding: 16px;
  }
  @media (prefers-reduced-motion: no-preference) {
    .modal[open] .modal-box {
      animation: calhou-sheet-in var(--dur-slow) var(--ease-out) both;
    }
    .modal.is-closing .modal-box {
      animation: calhou-sheet-out var(--dur) ease-in both;
    }
  }
}

/* No JS: the modal opens through :target (footer links point to #id or to an anchor inside it). */
html:not(.js) .modal:target,
html:not(.js) .modal:has(:target) {
  display: block;
  position: fixed;
  inset: 0;
  z-index: 100;
  margin: auto;
  height: fit-content;
}

/* ---------- Cross-document page transitions ---------- */

@media (prefers-reduced-motion: no-preference) {
  @view-transition {
    navigation: auto;
  }

  ::view-transition-old(root) {
    animation: calhou-fade-out 160ms steps(3, end) both;
  }

  ::view-transition-new(root) {
    animation: calhou-wipe-in 280ms steps(7, end) both;
  }
}

/* ---------- Reduced motion: everything instant ---------- */

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after,
  ::backdrop {
    animation-duration: 1ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 1ms !important;
    scroll-behavior: auto !important;
  }
}
