home: replace single LiveWire ticker with stacked dual ticker

Two horizontal lanes stacked on top of each other:

  Lane 1  LIVE WIRE           red gradient label, pulsing white dot,
                              latest 14 published articles, 65s loop
  Lane 2  RECENT FORUM POSTS  green gradient label, pulsing white dot,
                              latest 14 forum threads, 82s loop

The two lanes use intentionally different animation durations (65s vs
82s) so they never sync up — feels alive like a real wire room. Both
loops use CSS translateX with a duplicated content track for seamless
infinite scroll. Edges fade via mask-image so items dissolve in/out
rather than appearing on a hard line.

Both lanes pause on hover (the whole row) so users can stop motion
to read or click. Each item is a real <Link>; clicking opens the
article or thread page.

Server component — data is fetched once at request time from
bb.wp_imported_posts and bb.forum_threads, cached at the page's
revalidate boundary. No client JS needed.

Old LiveWireTicker.tsx is removed (orphaned, not referenced elsewhere).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Ryan Salazar
2026-05-19 23:06:15 +00:00
parent b21ac70e0c
commit a52f8adb21
4 changed files with 290 additions and 122 deletions

View File

@@ -807,4 +807,197 @@ h1, h2, h3 {
.ProseMirror strong { font-weight: 700; color: #fff; }
.ProseMirror em { font-style: italic; }
.ProseMirror u { text-decoration: underline; }
.ProseMirror s { text-decoration: line-through; }
.ProseMirror s { text-decoration: line-through; }
/* =====================
DOUBLE TICKER (LIVE WIRE + RECENT FORUM POSTS)
===================== */
.bb-ticker-stack {
width: 100%;
border-bottom: 1px solid #1a1a1a;
}
.bb-ticker {
display: flex;
align-items: stretch;
height: 34px;
width: 100%;
overflow: hidden;
position: relative;
}
.bb-ticker--wire {
background: linear-gradient(90deg, #0a0a0a 0%, #161616 50%, #0a0a0a 100%);
border-bottom: 1px solid #1f1212;
}
.bb-ticker--forum {
background: linear-gradient(90deg, #08120e 0%, #0f1d18 50%, #08120e 100%);
}
.bb-ticker-label {
flex-shrink: 0;
display: inline-flex;
align-items: center;
gap: 8px;
padding: 0 16px;
font-family: var(--font-body);
font-size: 11px;
font-weight: 800;
letter-spacing: 0.22em;
color: #ffffff;
white-space: nowrap;
position: relative;
z-index: 2;
}
.bb-ticker-label--red {
background: linear-gradient(90deg, #d40000 0%, #a30000 100%);
box-shadow: 0 0 18px rgba(212, 0, 0, 0.45), inset 0 -1px 0 rgba(255, 255, 255, 0.05);
clip-path: polygon(0 0, 100% 0, calc(100% - 10px) 100%, 0 100%);
padding-right: 24px;
}
.bb-ticker-label--green {
background: linear-gradient(90deg, #0c8a63 0%, #086149 100%);
box-shadow: 0 0 18px rgba(12, 138, 99, 0.40), inset 0 -1px 0 rgba(255, 255, 255, 0.05);
clip-path: polygon(0 0, 100% 0, calc(100% - 10px) 100%, 0 100%);
padding-right: 24px;
}
.bb-ticker-pulse {
display: inline-block;
width: 7px;
height: 7px;
border-radius: 999px;
background: #ffffff;
box-shadow: 0 0 8px rgba(255, 255, 255, 0.9);
animation: bb-ticker-pulse-anim 1.4s ease-in-out infinite;
}
.bb-ticker-pulse--green {
animation-duration: 1.8s;
}
@keyframes bb-ticker-pulse-anim {
0%, 100% { opacity: 1; transform: scale(1); }
50% { opacity: 0.4; transform: scale(1.25); }
}
.bb-ticker-mask {
flex: 1;
min-width: 0;
overflow: hidden;
position: relative;
-webkit-mask-image: linear-gradient(to right, transparent 0, #000 28px, #000 calc(100% - 28px), transparent 100%);
mask-image: linear-gradient(to right, transparent 0, #000 28px, #000 calc(100% - 28px), transparent 100%);
}
.bb-ticker-track {
display: inline-flex;
align-items: center;
width: max-content;
white-space: nowrap;
animation-name: bb-ticker-scroll;
animation-timing-function: linear;
animation-iteration-count: infinite;
will-change: transform;
}
/* Different speeds so the two lanes never sync up — feels alive */
.bb-ticker-track--wire { animation-duration: 65s; }
.bb-ticker-track--forum { animation-duration: 82s; }
.bb-ticker-track:hover,
.bb-ticker-track:focus-within {
animation-play-state: paused;
}
@keyframes bb-ticker-scroll {
0% { transform: translate3d(0, 0, 0); }
100% { transform: translate3d(-50%, 0, 0); }
}
.bb-ticker-item {
display: inline-flex;
align-items: center;
gap: 10px;
padding: 0 22px;
height: 34px;
text-decoration: none;
font-family: var(--font-body);
font-size: 13px;
font-weight: 500;
letter-spacing: 0.005em;
color: #d8d8d8;
transition: color 0.18s ease;
border-right: 1px solid rgba(255, 255, 255, 0.05);
}
.bb-ticker-item--wire:hover { color: #ff6b6b; }
.bb-ticker-item--forum:hover { color: #5eead4; }
.bb-ticker-bullet {
flex-shrink: 0;
font-weight: 700;
color: rgba(255, 255, 255, 0.35);
}
.bb-ticker-item--wire:hover .bb-ticker-bullet { color: #ff6b6b; }
.bb-ticker-item--forum:hover .bb-ticker-bullet { color: #5eead4; }
/* =====================
BROWSE NAV BAR (sits below the 728x90 header banner)
===================== */
.bb-browse-bar {
background: linear-gradient(180deg, #0b0b0b 0%, #0e0e0e 100%);
border-top: 1px solid #1a1a1a;
border-bottom: 1px solid #1a1a1a;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.4);
}
.bb-browse-row {
display: flex;
align-items: stretch;
gap: 0;
height: 44px;
}
.bb-browse-item {
position: relative;
display: inline-flex;
align-items: center;
padding: 0 16px;
font-family: var(--font-body);
font-size: 12px;
font-weight: 700;
letter-spacing: 0.06em;
text-transform: uppercase;
color: #cccccc;
text-decoration: none;
border-right: 1px solid #1a1a1a;
transition: background 0.15s ease, color 0.15s ease;
}
.bb-browse-item:first-of-type {
border-left: 1px solid #1a1a1a;
}
.bb-browse-item:hover,
.bb-browse-item[aria-expanded="true"] {
background: #161616;
color: var(--color-accent);
}
.bb-browse-item .bb-browse-caret {
display: inline-block;
margin-left: 6px;
font-size: 8px;
opacity: 0.7;
transform: translateY(-1px);
transition: transform 0.15s ease;
}
.bb-browse-item[aria-expanded="true"] .bb-browse-caret {
transform: rotate(180deg) translateY(1px);
}