/* Directory motion: shortcuts, hub rows, chips, result rows and page-to-page
   transitions (docs/design/motion.md, "Directory interactions"). Same rules
   as the homepage field: transform and opacity only, motion answers the
   visitor, and reduced motion keeps light but drops movement. */

:root {
    /* Timing: feedback ~100 ms, small moves 180-260 ms, nothing over 500 ms */
    --m-press: 90ms;
    --m-hover: 180ms;
    --m-move: 260ms;
    --m-page: 320ms;
    --m-ripple: 460ms;
    /* Slow out: quick start, soft landing. Spring: slight overshoot on release. */
    --m-ease-out: cubic-bezier(.2, .8, .2, 1);
    --m-spring: cubic-bezier(.3, 1.4, .5, 1);
    --m-light: rgba(67, 229, 233, .14);
    --m-ripple-1: rgba(70, 224, 214, .42);   /* teal */
    --m-ripple-2: rgba(169, 139, 255, .42);  /* violet */
    --m-ripple-3: rgba(244, 188, 92, .36);   /* saffron */
    --m-ripple-4: rgba(170, 235, 255, .40);  /* pale aqua */
}

html[data-theme="light"] {
    --m-light: rgba(9, 113, 108, .10);
    --m-ripple-1: rgba(9, 113, 108, .30);    /* deep teal */
    --m-ripple-2: rgba(107, 70, 201, .26);   /* violet */
    --m-ripple-3: rgba(201, 122, 18, .28);   /* saffron */
    --m-ripple-4: rgba(196, 84, 128, .22);   /* lotus */
}

/* ---- Interactive surfaces (marked data-motion by js/motion.js) ---------- */

.home-hints a,
.hub-category,
.hub-subcategories a,
.hub-chips a,
.search-result, .shop-link {
    position: relative;
    isolation: isolate;
    transition:
        transform var(--m-hover) var(--m-ease-out),
        border-color var(--m-hover) var(--m-ease-out),
        color var(--m-hover) var(--m-ease-out);
}

/* Pointer light: a soft glow that follows the pointer across the surface
   (arcs, secondary action). js/motion.js sets --mx and --my. */
.home-hints a::before,
.hub-category::before,
.hub-subcategories a::before,
.hub-chips a::before,
.search-result::before, .shop-link::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: -1;
    border-radius: inherit;
    background: radial-gradient(160px circle at var(--mx, 50%) var(--my, 50%), var(--m-light), transparent 70%);
    opacity: 0;
    transition: opacity var(--m-hover) var(--m-ease-out);
    pointer-events: none;
}

.hub-category { border-radius: 12px; padding-inline: .6rem; margin-inline: -.6rem; }
.search-result { border-radius: 12px; padding-inline: .6rem; margin-inline: -.6rem; }
.home-hints a { border-radius: 999px; padding-inline: .7rem; }

@media (hover: hover) and (pointer: fine) {
    .home-hints a:hover::before,
    .hub-category:hover::before,
    .hub-subcategories a:hover::before,
    .hub-chips a:hover::before,
    .search-result:hover::before, .shop-link:hover::before { opacity: 1; }

    /* Lift on hover; the count follows a beat later (follow-through). */
    .home-hints a:hover,
    .hub-subcategories a:hover,
    .hub-chips a:hover { transform: translateY(-2px); }
    .hub-category:hover strong { transform: translateX(4px); }
    .hub-category:hover span { transform: translateX(4px); transition-delay: 40ms; }
    .search-result:hover { transform: translateX(3px); }
}

.hub-category strong,
.hub-category span { display: inline-block; transition: transform var(--m-move) var(--m-ease-out); }

/* Anticipation: a quick squash on press, released with a small spring. */
.home-hints a:active,
.hub-subcategories a:active,
.hub-chips a:active { transform: scale(.95); transition-duration: var(--m-press); }
.hub-category:active,
.search-result:active, .shop-link:active { transform: scale(.985); transition-duration: var(--m-press); }
.home-hints a:not(:active),
.hub-subcategories a:not(:active),
.hub-chips a:not(:active) { transition-timing-function: var(--m-spring); }

/* Tap ripple (js/motion.js): grows fast, settles slowly, fades last. */
.motion-ripple {
    position: absolute;
    z-index: -1;
    width: 12px;
    height: 12px;
    margin: -6px 0 0 -6px;
    border-radius: 50%;
    pointer-events: none;
}

/* Overflow is clipped only where a ripple can appear. */
.home-hints a, .hub-category, .hub-subcategories a, .hub-chips a, .search-result, .shop-link { overflow: hidden; }

/* A product card lifts as a whole; its button carries the press and ripple. */
.shop-card { transition: transform var(--m-hover) var(--m-ease-out), border-color var(--m-hover) var(--m-ease-out); }
@media (hover: hover) and (pointer: fine) {
    .shop-card:hover { transform: translateY(-3px); border-color: color-mix(in srgb, var(--cyan) 40%, var(--line)); }
}
@media (prefers-reduced-motion: reduce) { .shop-card:hover { transform: none; } }

/* ---- Staging: hub content arrives in order, once, on page load ---------- */

@keyframes motion-arrive {
    from { opacity: 0; transform: translateY(8px); }
    to { opacity: 1; transform: none; }
}

.hub-page h1,
.hub-lede,
.hub-categories > li,
.hub-chips a,
.hub-page .search-results > li, .shop-grid > .shop-card {
    animation: motion-arrive var(--m-move) var(--m-ease-out) backwards; /* backwards: hover can move it afterwards */
}
.hub-lede { animation-delay: 40ms; }
.hub-chips a { animation-delay: 80ms; }
.hub-categories > li:nth-child(1), .hub-page .search-results > li:nth-child(1), .shop-grid > .shop-card:nth-child(1) { animation-delay: 80ms; }
.hub-categories > li:nth-child(2), .hub-page .search-results > li:nth-child(2), .shop-grid > .shop-card:nth-child(2) { animation-delay: 110ms; }
.hub-categories > li:nth-child(3), .hub-page .search-results > li:nth-child(3), .shop-grid > .shop-card:nth-child(3) { animation-delay: 140ms; }
.hub-categories > li:nth-child(4), .hub-page .search-results > li:nth-child(4), .shop-grid > .shop-card:nth-child(4) { animation-delay: 170ms; }
.hub-categories > li:nth-child(5), .hub-page .search-results > li:nth-child(5), .shop-grid > .shop-card:nth-child(5) { animation-delay: 200ms; }
.hub-categories > li:nth-child(6), .hub-page .search-results > li:nth-child(6), .shop-grid > .shop-card:nth-child(6) { animation-delay: 230ms; }
.hub-categories > li:nth-child(n+7), .hub-page .search-results > li:nth-child(n+7), .shop-grid > .shop-card:nth-child(n+7) { animation-delay: 260ms; }

/* ---- Page to page: native view transitions (no JavaScript) -------------- */
/* Browsers without support simply load the next page. The clicked chip or
   row and the next page's heading share a view-transition-name, so the
   heading grows out of what was tapped (staging, slow in and slow out). */

@view-transition { navigation: auto; }

.site-header { view-transition-name: site-header; }

::view-transition-group(*) {
    animation-duration: var(--m-page);
    animation-timing-function: var(--m-ease-out);
}

::view-transition-old(root) { animation: motion-page-out 160ms ease-in both; }
::view-transition-new(root) { animation: motion-page-in var(--m-page) var(--m-ease-out) 60ms both; }

@keyframes motion-page-out { to { opacity: 0; transform: scale(.99); } }
@keyframes motion-page-in { from { opacity: 0; transform: translateY(10px); } }

/* ---- Living illustrations: our own art, gently alive -------------------- */
/* Shop gems (GemArt.razor) and the category artwork. Slow, offset per card so
   nothing moves in lockstep; transform and opacity only. */

.gem-art * { transform-box: view-box; }

/* Pendant: a pendulum around the bail. Slow in and out at each end (arcs). */
.gem-sway { transform-origin: 100px 44px; animation: gem-sway 3.6s ease-in-out infinite alternate; }
@keyframes gem-sway { from { transform: rotate(-4deg); } to { transform: rotate(4deg); } }

/* A glint crosses the facets about every six seconds, then rests. */
.gem-glint { animation: gem-glint 6s cubic-bezier(.4, 0, .2, 1) infinite; transform: translateX(-60px); }
@keyframes gem-glint {
    0% { transform: translateX(-60px); }
    22%, 100% { transform: translateX(110px); }
}

/* Highlights breathe, each a little after the last (overlapping action). */
.gem-twinkle { animation: gem-twinkle 2.4s ease-in-out infinite alternate; animation-delay: calc(var(--i, 0) * -0.3s); }
@keyframes gem-twinkle { from { opacity: .35; } to { opacity: 1; } }

/* Bead strand: a soft wave travels along the beads (follow-through). */
.gem-bead { animation: gem-bead 3.2s ease-in-out infinite alternate; animation-delay: calc(var(--i, 0) * -0.18s); }
@keyframes gem-bead { from { transform: translateY(0); } to { transform: translateY(-2.5px); } }

/* Bracelet: turns once a minute. */
.gem-turn { transform-origin: 100px 80px; animation: gem-turn 60s linear infinite; }
@keyframes gem-turn { to { transform: rotate(360deg); } }

/* Offset neighbouring cards so the shop never moves in unison. */
.shop-card:nth-child(3n+2) .gem-sway, .shop-card:nth-child(3n+2) .gem-glint { animation-delay: -1.4s; }
.shop-card:nth-child(3n) .gem-sway, .shop-card:nth-child(3n) .gem-glint { animation-delay: -2.7s; }
.shop-card:nth-child(2n) .gem-turn { animation-direction: reverse; }

/* Category artwork (CategoryArt.razor): a very slow drift, like a camera
   breathing over the illustration. Thumbnails stay still. */
.card-visual .category-art, .detail-visual .category-art { animation: art-drift 24s ease-in-out infinite alternate; }
@keyframes art-drift {
    from { transform: scale(1.04) translate(-1%, -.6%); }
    to { transform: scale(1.08) translate(1%, .6%); }
}

@media (prefers-reduced-motion: reduce) {
    .gem-sway, .gem-glint, .gem-twinkle, .gem-bead, .gem-turn,
    .card-visual .category-art, .detail-visual .category-art { animation: none; }
    .gem-glint { opacity: 0; }
}

/* ---- Reduced motion: light still answers, nothing moves ----------------- */

@media (prefers-reduced-motion: reduce) {
    @view-transition { navigation: none; }

    .home-hints a, .hub-category, .hub-subcategories a, .hub-chips a, .search-result, .shop-link,
    .hub-category strong, .hub-category span { transform: none !important; transition-property: border-color, color; }

    .hub-page h1, .hub-lede, .hub-categories > li, .hub-chips a, .hub-page .search-results > li, .shop-grid > .shop-card {
        animation: motion-fade 200ms linear backwards;
    }
}

@keyframes motion-fade { from { opacity: 0; } }
