/* * Feed list: scroll snap, the new-posts pill and the loading-more skeleton * (spec "Feed list", ADR 0001). Prefixed `feed-` classes, tokens only. */ .feed .feed-list { scroll-snap-type: y proximity; } .feed-message { text-align: center; color: var(--ink-3); padding: 32px 16px; } .feed-message button { margin-top: 8px; } .feed-center { display: grid; place-items: center; padding: 16px; } .sentinel { height: 1px; } .spinner { width: 24px; height: 24px; border: 3px solid var(--line); border-top-color: var(--accent); border-radius: 50%; animation: spin .8s linear infinite; } @keyframes spin { to { transform: rotate(360deg); } } /* The pill floats at the top center of the list. The zero-height sticky wrapper takes the entrance animation, so the button keeps its own transforms (hover expand, press). */ .feed-pill { position: sticky; top: 12px; z-index: 4; display: flex; justify-content: center; height: 0; margin-bottom: -16px; overflow: visible; animation: feed-pill-in .45s var(--ease) backwards; } .feed-pill .btn-grow { flex: none; } @keyframes feed-pill-in { from { opacity: 0; transform: translateY(-10px) scale(.96); } to { opacity: 1; transform: none; } } /* Skeleton card: same footprint as a post, with a shimmer band sweeping over it. */ .feed-skel { flex: none; position: relative; overflow: hidden; display: flex; flex-direction: column; gap: 12px; padding: 16px; background: var(--tile); border: 1px solid var(--line); border-radius: var(--r-card); scroll-snap-align: none; } .feed-skel::after { content: ""; position: absolute; inset: 0; background: linear-gradient(100deg, transparent 20%, color-mix(in srgb, var(--ink), transparent 90%) 50%, transparent 80%); transform: translateX(-100%); animation: feed-shimmer 1.4s ease-in-out infinite; } @keyframes feed-shimmer { to { transform: translateX(100%); } } .feed-skel-head { display: flex; align-items: center; gap: 12px; } .feed-skel-lines { display: flex; flex-direction: column; gap: 6px; flex: 1; } .feed-skel-dot { width: 40px; height: 40px; border-radius: 50%; background: var(--tile-3); flex: none; } .feed-skel-line { display: block; height: 12px; border-radius: 6px; background: var(--tile-3); } .feed-skel-w25 { width: 25%; } .feed-skel-w40 { width: 40%; } .feed-skel-w80 { width: 80%; } .feed-skel-w100 { width: 100%; } .feed-skel-media { display: block; aspect-ratio: 16 / 9; border-radius: 12px; background: var(--tile-3); } /* Refresh button in the feed header. Its disabled state keeps full opacity, so the spinning icon is the only sign that a reload is running. */ .refresh-icon { display: block; } .refresh-icon-spin { animation: spin .8s linear infinite; } @media (prefers-reduced-motion: reduce) { .refresh-icon-spin { animation: none !important; } }