/* ═══════════════════════════════════════════════════════════════════
COIN WATCHLIST RAIL · left side, 24 coins, sparkline + group dot
═══════════════════════════════════════════════════════════════════ */
function CoinRail({ activeSym, onSelect, coins: propCoins, portfolioTotal, portfolioPnl, onEditHoldings }) {
/* collapsible rail — reclaim space for charts; remembered across pages */
const [railHidden, setRailHidden] = React.useState(
() => localStorage.getItem('st-rail-hidden') === '1');
const toggleRail = () => {
localStorage.setItem('st-rail-hidden', railHidden ? '0' : '1');
setRailHidden(!railHidden);
setTimeout(() => window.dispatchEvent(new Event('resize')), 60);
};
const [filter, setFilter] = React.useState('ALL');
const [query, setQuery] = React.useState('');
const COINS = propCoins || ST_COINS;
const filtered = React.useMemo(() => {
return COINS.filter(c => {
const g = ST_GROUP[c.group];
if (filter !== 'ALL' && g && g.label !== filter) return false;
if (query && !c.sym.toLowerCase().includes(query.toLowerCase())) return false;
return true;
});
}, [filter, query, COINS]);
const filters = ['ALL', 'INST', 'MOM', 'DEFI', 'MEME'];
if (railHidden) {
return (
);
}
return (
);
}
function CoinRow({ sym, name, price, chg, group, active, vol, onClick }) {
const g = ST_GROUP[group] || { c: ST.ink3, label: 'N/A' };
return (
{/* group dot */}
{/* symbol + name */}
{sym}
{g.label}
${ST_fmt.price(price)}
{/* sparkline */}
{/* % change */}
= 0 ? ST.green : ST.red,
minWidth: 44, textAlign: 'right',
}}>
{ST_fmt.pct(chg, 2)}
);
}
/* ── Shadow mark (logo glyph) ─────────────────────────────────────── */
function ShadowMark({ size = 26 }) {
return (
);
}
window.CoinRail = CoinRail;
window.ShadowMark = ShadowMark;
/* ── Global product nav (shared across all pages) ──────────────────── */
const ST_NAV = [
{ id: 'dashboard', label: 'MARKET', href: '../dashboard/' },
{ id: 'coin', label: 'COIN', href: '../coin/' },
{ id: 'shadow', label: 'SHADOW', href: '../shadow/' },
{ id: 'trade', label: 'TRADE', href: '../trade/' },
{ id: 'bots', label: 'BOTS', href: '../bots/' },
];
function ShadowNav() {
const active = (window.ST_PAGE || '').toLowerCase();
return (
);
}
window.ShadowNav = ShadowNav;