/* ==========================================================================
   assets/motion.css — the motion layer
   --------------------------------------------------------------------------
   Loaded after clay.css and components.css, before views.css.

   clay.css is the reference, byte for byte, and stays that way. This file
   only adds movement to it, so the design can be re-synced from the reference
   at any time without losing the polish.

   The house rules, and why they are these:

   - transform and opacity carry anything that can be on screen in bulk. They
     are the only two properties a compositor can animate without asking the
     main thread to repaint, which is what keeps a long notice list smooth.
   - Colour transitions are reserved for a handful of large surfaces, and
     only while the theme is actually changing. Transitioning colour
     everywhere makes hover feel laggy.
   - 120ms to 340ms. Slower reads as sluggish on a page this dense.
   - --nx-ease carries state changes and --nx-spring carries press feedback,
     exactly as the reference documents them. Nothing here invents an easing.
   - Every entrance is gated behind @media (scripting: enabled) or
     @supports, so a reader without JavaScript gets the finished layout
     rather than a page of invisible content waiting on an animation.
   ========================================================================== */

/* --- 1. Finishing what the reference started --------------------------- */
/* These all move on hover or press but ship with no transition at all, so
   they jump between states instead of travelling. That single omission is
   most of what makes an interface feel cheap: the movement is there, it just
   isn't connected to anything. Same intent as the reference, now animated. */

.tile,
.chip,
.section-link,
.feed-tab,
.category-card,
.utility-card,
.sync-card,
.user-card,
.retry-button,
.view-option,
.status-badge {
  transition:
    transform 0.18s var(--nx-spring),
    box-shadow 0.2s var(--nx-ease),
    color 0.2s var(--nx-ease),
    background-color 0.2s var(--nx-ease),
    border-color 0.2s var(--nx-ease);
}

/* The press group the reference lists in one rule. A press that snaps reads
   as a glitch; the spring is what makes a tap feel like it lands. */
.icon-button:active,
.nav-item:active,
.category-card:active,
.utility-card:active,
.sync-card:active,
.user-card:active {
  transition-duration: 0.09s;
}

/* --- 2. The listing wall ------------------------------------------------- */
/* The wall is this project's own component rather than the reference's, and
   it had no feedback at all: no hover, no press, and the title colour changed
   in a single frame. The bullet is the row's anchor, so it grows with the row
   instead of the row sliding out from under it. */

.wall-row {
  transition: transform 0.18s var(--nx-spring);
}

.wall-row::before {
  transition:
    transform 0.2s var(--nx-spring),
    opacity 0.2s var(--nx-ease);
}

.wall-title {
  transition: color 0.18s var(--nx-ease);
}

@media (hover: hover) {
  .wall-row:hover {
    transform: translateX(3px);
  }

  .wall-row:hover::before {
    opacity: 1;
    transform: translateY(-50%) scale(1.35);
  }
}

/* Keyboard reaches the same affordance a pointer does. */
.wall-row:focus-within {
  transform: translateX(3px);
}

.wall-row:active {
  transform: translateX(3px) scale(0.995);
}

.wall-more {
  transition:
    color 0.2s var(--nx-ease),
    gap 0.2s var(--nx-ease);
}

@media (hover: hover) {
  .wall-more:hover {
    gap: 10px;
  }
}

/* --- 3. Sheets ----------------------------------------------------------- */
/* components.css already slides each panel up, but on a linear curve with no
   scale, so it arrives rather than settles. A trace of scale plus the spring
   is the difference between a dialog and a balloon.

   .search-panel is listed with .sheet on purpose: search is the panel people
   open most, and it was the one overlay still riding the linear curve while
   every other dialog had been given the spring. */

.overlay {
  transition: opacity 0.22s var(--nx-ease);
}

.sheet,
.search-panel {
  transform: translateY(16px) scale(0.985);
  transition:
    transform 0.34s var(--nx-spring),
    opacity 0.22s var(--nx-ease);
}

.overlay.open .sheet,
.overlay.open .search-panel {
  transform: translateY(0) scale(1);
}

/* --- 4. Entrance choreography ------------------------------------------- */
/* A list that arrives as one block reads as a screenshot; the same list
   arriving in a short sequence reads as a page loading. --i is stamped by
   scripts on the children of a list, and the total is deliberately short —
   long staggers make people wait for content they could already be reading. */

@keyframes nx-motion-enter {
  from {
    opacity: 0;
    transform: translateY(8px);
  }

  to {
    opacity: 1;
    transform: translateY(0);
  }
}

@media (scripting: enabled) {
  .wall-list > *,
  .tile-grid > *,
  .feed-list > *,
  .category-grid > * {
    animation: nx-motion-enter 0.34s var(--nx-ease) backwards;
    animation-delay: calc(var(--i, 0) * 22ms);
  }
}

/* --- 5. Reduced motion --------------------------------------------------- */
/* base.css and clay.css already collapse durations globally, but
   `.retheme, .retheme *` in components.css is `!important` at a higher
   specificity than their `*` rule, so the theme cross-fade kept running at
   0.4s for visitors who asked for reduced motion. It has to be named here
   explicitly. An entrance animation left running at 0.01ms would also still
   spend its delay before arriving, so those are switched off outright. */

@media (prefers-reduced-motion: reduce) {
  .wall-list > *,
  .tile-grid > *,
  .feed-list > *,
  .category-grid > * {
    animation: none !important;
  }

  .wall-row,
  .wall-row::before,
  .wall-title,
  .tile,
  .chip,
  .section-link,
  .feed-tab,
  .category-card,
  .utility-card,
  .sync-card,
  .user-card,
  .retry-button,
  .view-option,
  .status-badge,
  .sheet,
  .search-panel,
  .overlay,
  .wall-more,
  .retheme,
  .retheme * {
    transition: none !important;
  }
}
