Some checks failed
Deploy to Frontend Servers / deploy (push) Failing after 14s
Recommended cards already routed to /browse#post-<id>, but the stream had no logic to scroll to the target bubble — and the post might not be paged in yet. MessageStream now resolves the #post-<id> hash, auto-loads more pages until the bubble renders, scrolls to it, and gives it a brief gold highlight. Bubbles get scroll-mt so they clear the sticky header. Also adds a global floating back-to-top button (BackToTop) mounted in PublicLayout, shown after scrolling past 400px. Bundles related staging UI work already present in the working tree. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
151 lines
2.7 KiB
CSS
151 lines
2.7 KiB
CSS
@tailwind base;
|
|
@tailwind components;
|
|
@tailwind utilities;
|
|
|
|
html,
|
|
body,
|
|
#root {
|
|
height: 100%;
|
|
}
|
|
|
|
html,
|
|
body {
|
|
overflow-x: hidden;
|
|
}
|
|
|
|
body {
|
|
@apply bg-ark-bg text-neutral-100 antialiased;
|
|
}
|
|
|
|
/* Match theme: avoid default blue accent on controls */
|
|
:root {
|
|
accent-color: #eeb726;
|
|
}
|
|
|
|
header a,
|
|
header button {
|
|
-webkit-tap-highlight-color: transparent;
|
|
}
|
|
|
|
.ark-header-menu-enter,
|
|
.ark-header-popover-enter {
|
|
animation: ark-header-menu-enter 180ms ease-out both;
|
|
transform-origin: top center;
|
|
will-change: clip-path, opacity;
|
|
}
|
|
|
|
@keyframes ark-header-menu-enter {
|
|
from {
|
|
opacity: 0;
|
|
clip-path: inset(0 0 100% 0);
|
|
}
|
|
|
|
to {
|
|
opacity: 1;
|
|
clip-path: inset(0 0 0 0);
|
|
}
|
|
}
|
|
|
|
/* Desktop header nav: thin scrollbar when links overflow (still 單列) */
|
|
.header-nav-scroll {
|
|
scrollbar-width: thin;
|
|
scrollbar-color: rgba(238, 183, 38, 0.45) transparent;
|
|
}
|
|
.header-nav-scroll::-webkit-scrollbar {
|
|
height: 4px;
|
|
}
|
|
.header-nav-scroll::-webkit-scrollbar-thumb {
|
|
background-color: rgba(238, 183, 38, 0.45);
|
|
border-radius: 9999px;
|
|
}
|
|
.header-nav-scroll::-webkit-scrollbar-track {
|
|
background: transparent;
|
|
}
|
|
|
|
.gold-underline {
|
|
box-shadow: inset 0 -2px 0 #eeb726;
|
|
}
|
|
|
|
/* Reusable skeleton placeholder with a soft shimmer sweep. */
|
|
.ark-skeleton {
|
|
position: relative;
|
|
overflow: hidden;
|
|
background-color: #1d1e23;
|
|
}
|
|
.ark-skeleton::after {
|
|
content: "";
|
|
position: absolute;
|
|
inset: 0;
|
|
transform: translateX(-100%);
|
|
background: linear-gradient(
|
|
90deg,
|
|
transparent,
|
|
rgba(255, 255, 255, 0.05),
|
|
transparent
|
|
);
|
|
animation: ark-shimmer 1.5s infinite;
|
|
}
|
|
|
|
@keyframes ark-shimmer {
|
|
100% {
|
|
transform: translateX(100%);
|
|
}
|
|
}
|
|
|
|
/* Image fade-in: add .is-loaded on the img's onLoad handler. */
|
|
.ark-img-fade {
|
|
opacity: 0;
|
|
transition: opacity 0.4s ease-out;
|
|
}
|
|
.ark-img-fade.is-loaded {
|
|
opacity: 1;
|
|
}
|
|
|
|
@media (prefers-reduced-motion: reduce) {
|
|
.ark-skeleton::after {
|
|
animation: none;
|
|
}
|
|
.ark-img-fade {
|
|
opacity: 1;
|
|
transition: none;
|
|
}
|
|
}
|
|
|
|
/* Brief gold ring pulse when a bubble is targeted via a #post-<id> deep link. */
|
|
.ark-bubble-highlight {
|
|
border-radius: 1rem;
|
|
animation: ark-bubble-highlight 2s ease-out both;
|
|
}
|
|
|
|
@keyframes ark-bubble-highlight {
|
|
0%,
|
|
35% {
|
|
box-shadow: 0 0 0 2px rgba(238, 183, 38, 0.9);
|
|
}
|
|
100% {
|
|
box-shadow: 0 0 0 2px rgba(238, 183, 38, 0);
|
|
}
|
|
}
|
|
|
|
@media (prefers-reduced-motion: reduce) {
|
|
.ark-bubble-highlight {
|
|
animation: none;
|
|
}
|
|
}
|
|
|
|
.message-stream-copyable-text,
|
|
.message-stream-copyable-text * {
|
|
-webkit-user-select: text;
|
|
user-select: text;
|
|
}
|
|
|
|
.message-stream-copyable-text {
|
|
-webkit-touch-callout: default;
|
|
cursor: text;
|
|
}
|
|
|
|
.message-stream-copyable-text::selection,
|
|
.message-stream-copyable-text *::selection {
|
|
background: rgba(238, 183, 38, 0.35);
|
|
}
|