1
This commit is contained in:
parent
223b50886b
commit
562246e949
@ -1 +1 @@
|
|||||||
"""Application package for AlphaX Agent | Crypto."""
|
"""Application package for AlphaX Agent."""
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
"""Unified CLI entrypoint for AlphaX Agent | Crypto jobs."""
|
"""Unified CLI entrypoint for AlphaX Agent jobs."""
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
import sys
|
import sys
|
||||||
@ -7,7 +7,7 @@ from app.services import altcoin_confirm, altcoin_screener, event_driven_screene
|
|||||||
|
|
||||||
|
|
||||||
def build_parser():
|
def build_parser():
|
||||||
parser = argparse.ArgumentParser(description="AlphaX Agent | Crypto unified CLI")
|
parser = argparse.ArgumentParser(description="AlphaX Agent unified CLI")
|
||||||
subparsers = parser.add_subparsers(dest="command", required=True)
|
subparsers = parser.add_subparsers(dest="command", required=True)
|
||||||
|
|
||||||
screener = subparsers.add_parser("screener", help="运行粗筛/细筛")
|
screener = subparsers.add_parser("screener", help="运行粗筛/细筛")
|
||||||
|
|||||||
@ -28,7 +28,7 @@ DEFAULT_ENTRY_GATE = {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
# AlphaX Agent | Crypto 统一状态机:所有展示/统计/推送都应消费这些派生状态,不再各自解释 status/action_status。
|
# AlphaX Agent 统一状态机:所有展示/统计/推送都应消费这些派生状态,不再各自解释 status/action_status。
|
||||||
TERMINAL_STATUSES = {"hit_tp1", "hit_tp2", "stopped_out", "expired", "archived", "invalid"}
|
TERMINAL_STATUSES = {"hit_tp1", "hit_tp2", "stopped_out", "expired", "archived", "invalid"}
|
||||||
EXIT_ACTIONS = {"止损", "衰减", "反转", "放弃"}
|
EXIT_ACTIONS = {"止损", "衰减", "反转", "放弃"}
|
||||||
PROFIT_ACTIONS = {"止盈1", "止盈2", "跟踪止盈"}
|
PROFIT_ACTIONS = {"止盈1", "止盈2", "跟踪止盈"}
|
||||||
|
|||||||
@ -80,13 +80,13 @@ def send_verification_email(to_email: str, code: str) -> bool:
|
|||||||
sender = settings["sender"]
|
sender = settings["sender"]
|
||||||
|
|
||||||
msg = EmailMessage()
|
msg = EmailMessage()
|
||||||
msg["Subject"] = "AlphaX Agent | Crypto 邮箱验证码"
|
msg["Subject"] = "AlphaX Agent 邮箱验证码"
|
||||||
msg["From"] = sender
|
msg["From"] = sender
|
||||||
msg["To"] = to_email
|
msg["To"] = to_email
|
||||||
msg.set_content(
|
msg.set_content(
|
||||||
f"AlphaX Agent | Crypto 邮箱验证码:{code}\n\n"
|
f"AlphaX Agent 邮箱验证码:{code}\n\n"
|
||||||
f"AI Market Intelligence.\n"
|
f"AI Market Intelligence.\n"
|
||||||
f"验证码 {VERIFY_CODE_MINUTES} 分钟内有效,用于完成 AlphaX Agent | Crypto 注册或登录验证。\n"
|
f"验证码 {VERIFY_CODE_MINUTES} 分钟内有效,用于完成 AlphaX Agent 注册或登录验证。\n"
|
||||||
f"如果不是你本人操作,请忽略本邮件。"
|
f"如果不是你本人操作,请忽略本邮件。"
|
||||||
)
|
)
|
||||||
msg.add_alternative(
|
msg.add_alternative(
|
||||||
@ -98,12 +98,12 @@ def send_verification_email(to_email: str, code: str) -> bool:
|
|||||||
<div style="background:#ffffff;border:1px solid #ece7d8;border-radius:22px;overflow:hidden;box-shadow:0 18px 48px rgba(28,28,30,.08);">
|
<div style="background:#ffffff;border:1px solid #ece7d8;border-radius:22px;overflow:hidden;box-shadow:0 18px 48px rgba(28,28,30,.08);">
|
||||||
<div style="padding:26px 28px 18px;background:linear-gradient(135deg,#1c1c1e 0%,#2d2d32 52%,#4262ff 100%);color:#ffffff;">
|
<div style="padding:26px 28px 18px;background:linear-gradient(135deg,#1c1c1e 0%,#2d2d32 52%,#4262ff 100%);color:#ffffff;">
|
||||||
<div style="display:inline-block;width:34px;height:34px;line-height:34px;text-align:center;border-radius:10px;background:#ffd02f;color:#1c1c1e;font-weight:900;font-size:18px;margin-bottom:14px;">A</div>
|
<div style="display:inline-block;width:34px;height:34px;line-height:34px;text-align:center;border-radius:10px;background:#ffd02f;color:#1c1c1e;font-weight:900;font-size:18px;margin-bottom:14px;">A</div>
|
||||||
<div style="font-size:24px;font-weight:850;letter-spacing:0;">AlphaX Agent | Crypto</div>
|
<div style="font-size:24px;font-weight:850;letter-spacing:0;">AlphaX Agent</div>
|
||||||
<div style="font-size:13px;opacity:.78;margin-top:4px;letter-spacing:.02em;">AI Market Intelligence.</div>
|
<div style="font-size:13px;opacity:.78;margin-top:4px;letter-spacing:.02em;">AI Market Intelligence.</div>
|
||||||
</div>
|
</div>
|
||||||
<div style="padding:28px;">
|
<div style="padding:28px;">
|
||||||
<div style="font-size:18px;font-weight:800;margin-bottom:8px;">邮箱验证码</div>
|
<div style="font-size:18px;font-weight:800;margin-bottom:8px;">邮箱验证码</div>
|
||||||
<p style="margin:0 0 18px;color:#5f626b;font-size:14px;line-height:1.75;">请使用下面的验证码完成 AlphaX Agent | Crypto 注册或登录验证。验证码 {VERIFY_CODE_MINUTES} 分钟内有效。</p>
|
<p style="margin:0 0 18px;color:#5f626b;font-size:14px;line-height:1.75;">请使用下面的验证码完成 AlphaX Agent 注册或登录验证。验证码 {VERIFY_CODE_MINUTES} 分钟内有效。</p>
|
||||||
<div style="margin:22px 0;padding:20px 18px;border-radius:18px;background:#fff8d8;border:1px solid #f2de82;text-align:center;">
|
<div style="margin:22px 0;padding:20px 18px;border-radius:18px;background:#fff8d8;border:1px solid #f2de82;text-align:center;">
|
||||||
<div style="font-size:13px;color:#6d642b;margin-bottom:8px;">你的验证码</div>
|
<div style="font-size:13px;color:#6d642b;margin-bottom:8px;">你的验证码</div>
|
||||||
<div style="font-size:34px;font-weight:900;letter-spacing:8px;color:#1c1c1e;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;">{code}</div>
|
<div style="font-size:34px;font-weight:900;letter-spacing:8px;color:#1c1c1e;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;">{code}</div>
|
||||||
@ -111,7 +111,7 @@ def send_verification_email(to_email: str, code: str) -> bool:
|
|||||||
<p style="margin:0;color:#7a7d86;font-size:13px;line-height:1.7;">如果不是你本人操作,请忽略本邮件。为保护账号安全,请不要把验证码转发给任何人。</p>
|
<p style="margin:0;color:#7a7d86;font-size:13px;line-height:1.7;">如果不是你本人操作,请忽略本邮件。为保护账号安全,请不要把验证码转发给任何人。</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div style="text-align:center;color:#a0a3ad;font-size:12px;margin-top:18px;">© 2026 AlphaX Agent | Crypto · AI 驱动的 Crypto 市场情报系统</div>
|
<div style="text-align:center;color:#a0a3ad;font-size:12px;margin-top:18px;">© 2026 AlphaX Agent · AI 驱动的 Crypto 市场情报系统</div>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
-- AlphaX Agent | Crypto PostgreSQL initial schema.
|
-- AlphaX Agent PostgreSQL initial schema.
|
||||||
-- Keep column names compatible with the current SQLite data model.
|
-- Keep column names compatible with the current SQLite data model.
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS schema_migrations (
|
CREATE TABLE IF NOT EXISTS schema_migrations (
|
||||||
|
|||||||
@ -1414,7 +1414,7 @@ def main(compact: bool = False):
|
|||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
import argparse
|
import argparse
|
||||||
|
|
||||||
parser = argparse.ArgumentParser(description="AlphaX Agent | Crypto 爆发确认主流程")
|
parser = argparse.ArgumentParser(description="AlphaX Agent 爆发确认主流程")
|
||||||
parser.add_argument("--compact", action="store_true", help="输出紧凑 JSON,便于脚本消费")
|
parser.add_argument("--compact", action="store_true", help="输出紧凑 JSON,便于脚本消费")
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
main(compact=args.compact)
|
main(compact=args.compact)
|
||||||
|
|||||||
@ -1507,7 +1507,7 @@ def main(compact: bool = False):
|
|||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
import argparse
|
import argparse
|
||||||
|
|
||||||
parser = argparse.ArgumentParser(description="AlphaX Agent | Crypto 粗筛/细筛主流程")
|
parser = argparse.ArgumentParser(description="AlphaX Agent 粗筛/细筛主流程")
|
||||||
parser.add_argument("--compact", action="store_true", help="输出紧凑 JSON,便于脚本消费")
|
parser.add_argument("--compact", action="store_true", help="输出紧凑 JSON,便于脚本消费")
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
main(compact=args.compact)
|
main(compact=args.compact)
|
||||||
|
|||||||
@ -421,7 +421,7 @@ def main():
|
|||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
import argparse
|
import argparse
|
||||||
|
|
||||||
parser = argparse.ArgumentParser(description="AlphaX Agent | Crypto 价格跟踪任务")
|
parser = argparse.ArgumentParser(description="AlphaX Agent 价格跟踪任务")
|
||||||
parser.add_argument("--once", action="store_true", default=True, help="执行单轮跟踪并输出结果")
|
parser.add_argument("--once", action="store_true", default=True, help="执行单轮跟踪并输出结果")
|
||||||
parser.parse_args()
|
parser.parse_args()
|
||||||
main()
|
main()
|
||||||
|
|||||||
@ -1577,7 +1577,7 @@ def run_review(push_enabled: bool = True, compact: bool = False):
|
|||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
import argparse
|
import argparse
|
||||||
|
|
||||||
parser = argparse.ArgumentParser(description="AlphaX Agent | Crypto 复盘引擎")
|
parser = argparse.ArgumentParser(description="AlphaX Agent 复盘引擎")
|
||||||
parser.add_argument("--no-push", action="store_true", help="只运行复盘,不发送飞书通知")
|
parser.add_argument("--no-push", action="store_true", help="只运行复盘,不发送飞书通知")
|
||||||
parser.add_argument("--compact", action="store_true", help="输出紧凑 JSON,便于脚本消费")
|
parser.add_argument("--compact", action="store_true", help="输出紧凑 JSON,便于脚本消费")
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
"""
|
"""
|
||||||
FastAPI application assembly for the AlphaX Agent | Crypto web surface.
|
FastAPI application assembly for the AlphaX Agent web surface.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from contextlib import asynccontextmanager
|
from contextlib import asynccontextmanager
|
||||||
@ -40,7 +40,7 @@ async def lifespan(app: FastAPI):
|
|||||||
yield
|
yield
|
||||||
|
|
||||||
|
|
||||||
app = FastAPI(title="AlphaX Agent | Crypto", lifespan=lifespan)
|
app = FastAPI(title="AlphaX Agent", lifespan=lifespan)
|
||||||
templates = Jinja2Templates(directory=str(REPO_ROOT / "static"))
|
templates = Jinja2Templates(directory=str(REPO_ROOT / "static"))
|
||||||
|
|
||||||
app.include_router(auth_router)
|
app.include_router(auth_router)
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
|
||||||
<title>登录 / 注册 — AlphaX Agent | Crypto</title>
|
<title>登录 / 注册 — AlphaX Agent</title>
|
||||||
<style>
|
<style>
|
||||||
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
|
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
|
||||||
:root {
|
:root {
|
||||||
@ -141,11 +141,11 @@ a { color: inherit; text-decoration: none; }
|
|||||||
<div class="page">
|
<div class="page">
|
||||||
<a class="brand" href="/">
|
<a class="brand" href="/">
|
||||||
<span class="brand-mark"></span>
|
<span class="brand-mark"></span>
|
||||||
<span class="brand-name">AlphaX Agent | Crypto</span>
|
<span class="brand-name">AlphaX Agent</span>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<div class="notice" style="margin-bottom:16px">
|
<div class="notice" style="margin-bottom:16px">
|
||||||
<strong>AlphaX Agent | Crypto</strong><br>
|
<strong>AlphaX Agent</strong><br>
|
||||||
提前发现机会,别在强信号后追高。登录或开启免费体验,创建账号后可前往订阅中心。
|
提前发现机会,别在强信号后追高。登录或开启免费体验,创建账号后可前往订阅中心。
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
|
||||||
<title>AlphaX Agent | Crypto</title>
|
<title>AlphaX Agent</title>
|
||||||
<style>
|
<style>
|
||||||
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
|
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
|
||||||
:root {
|
:root {
|
||||||
@ -139,7 +139,7 @@ h1 { font-size: clamp(36px, 5.5vw, 56px); font-weight: 500; line-height: 1.1; le
|
|||||||
<nav class="nav">
|
<nav class="nav">
|
||||||
<a class="nav-left" href="/">
|
<a class="nav-left" href="/">
|
||||||
<span class="brand-mark"></span>
|
<span class="brand-mark"></span>
|
||||||
<span class="brand-name">AlphaX Agent | Crypto</span>
|
<span class="brand-name">AlphaX Agent</span>
|
||||||
</a>
|
</a>
|
||||||
<div class="nav-guest">
|
<div class="nav-guest">
|
||||||
<a class="btn btn-secondary" href="/auth?tab=login">登录</a>
|
<a class="btn btn-secondary" href="/auth?tab=login">登录</a>
|
||||||
@ -185,7 +185,7 @@ h1 { font-size: clamp(36px, 5.5vw, 56px); font-weight: 500; line-height: 1.1; le
|
|||||||
</div>
|
</div>
|
||||||
<div class="hero-brand">
|
<div class="hero-brand">
|
||||||
<span class="hero-mark"></span>
|
<span class="hero-mark"></span>
|
||||||
<span class="hero-word">AlphaX Agent | Crypto</span>
|
<span class="hero-word">AlphaX Agent</span>
|
||||||
<span class="beta-badge">Beta</span>
|
<span class="beta-badge">Beta</span>
|
||||||
</div>
|
</div>
|
||||||
<h1>AI Market Intelligence.</h1>
|
<h1>AI Market Intelligence.</h1>
|
||||||
@ -196,7 +196,7 @@ h1 { font-size: clamp(36px, 5.5vw, 56px); font-weight: 500; line-height: 1.1; le
|
|||||||
</section>
|
</section>
|
||||||
|
|
||||||
<footer class="footer">
|
<footer class="footer">
|
||||||
<span class="footer-copy">© 2026 AlphaX Agent | Crypto</span>
|
<span class="footer-copy">© 2026 AlphaX Agent</span>
|
||||||
</footer>
|
</footer>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@ -97,7 +97,7 @@ h2 { font-size:26px; font-weight:900; margin:0 0 8px; color:var(--ink); }
|
|||||||
<div class="hero">
|
<div class="hero">
|
||||||
<div>
|
<div>
|
||||||
<h2>策略进化</h2>
|
<h2>策略进化</h2>
|
||||||
<p class="subtitle">这里展示 AlphaX Agent | Crypto 策略是否真的在变聪明:本轮有没有发布、为什么没发布、哪些规律还在观察、哪些错误正在减少。</p>
|
<p class="subtitle">这里展示 AlphaX Agent 策略是否真的在变聪明:本轮有没有发布、为什么没发布、哪些规律还在观察、哪些错误正在减少。</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="toolbar">
|
<div class="toolbar">
|
||||||
<button class="btn" onclick="refreshCandidates()">刷新规则表现</button>
|
<button class="btn" onclick="refreshCandidates()">刷新规则表现</button>
|
||||||
|
|||||||
@ -86,7 +86,7 @@ main { max-width: 680px; margin: 0 auto; width: 100%; padding: 32px 20px; displa
|
|||||||
<main>
|
<main>
|
||||||
<div class="page-header">
|
<div class="page-header">
|
||||||
<h1>🎁 推荐好友</h1>
|
<h1>🎁 推荐好友</h1>
|
||||||
<p class="sub">邀请朋友加入 AlphaX Agent | Crypto,一起跟踪市场信号</p>
|
<p class="sub">邀请朋友加入 AlphaX Agent,一起跟踪市场信号</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="invite-card">
|
<div class="invite-card">
|
||||||
|
|||||||
@ -76,7 +76,7 @@
|
|||||||
<p class="sub">新用户可免费体验 1 个月,后续按需选择方案。</p>
|
<p class="sub">新用户可免费体验 1 个月,后续按需选择方案。</p>
|
||||||
|
|
||||||
<div id="guideBox" class="guide-box">
|
<div id="guideBox" class="guide-box">
|
||||||
<div class="guide-title" id="guideTitle">先开通套餐,开始使用 AlphaX Agent | Crypto</div>
|
<div class="guide-title" id="guideTitle">先开通套餐,开始使用 AlphaX Agent</div>
|
||||||
<div class="guide-text" id="guideText">新用户可领取 30 天免费体验。开通后即可进入看板、策略、迭代和舆情页面。</div>
|
<div class="guide-text" id="guideText">新用户可领取 30 天免费体验。开通后即可进入看板、策略、迭代和舆情页面。</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -154,7 +154,7 @@ async function loadMe() {
|
|||||||
document.getElementById('guideTitle').textContent = '订阅已到期,请先续订';
|
document.getElementById('guideTitle').textContent = '订阅已到期,请先续订';
|
||||||
document.getElementById('guideText').textContent = '当前账号没有有效订阅。续订或开通套餐后,才能继续访问看板、策略、迭代和舆情页面。';
|
document.getElementById('guideText').textContent = '当前账号没有有效订阅。续订或开通套餐后,才能继续访问看板、策略、迭代和舆情页面。';
|
||||||
} else if (!s) {
|
} else if (!s) {
|
||||||
document.getElementById('guideTitle').textContent = '欢迎使用 AlphaX Agent | Crypto,请先开通套餐';
|
document.getElementById('guideTitle').textContent = '欢迎使用 AlphaX Agent,请先开通套餐';
|
||||||
document.getElementById('guideText').textContent = '新用户可领取 30 天免费体验。开通后即可进入完整功能页面。';
|
document.getElementById('guideText').textContent = '新用户可领取 30 天免费体验。开通后即可进入完整功能页面。';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
{% extends "base.html" %}
|
{% extends "base.html" %}
|
||||||
{% block title %}关注 — AlphaX Agent | Crypto{% endblock %}
|
{% block title %}关注 — AlphaX Agent{% endblock %}
|
||||||
{% block extra_head_css %}
|
{% block extra_head_css %}
|
||||||
<style>
|
<style>
|
||||||
.shell{width:min(100% - 40px,1180px);margin:0 auto;padding:24px 0 48px}.page-head{margin-bottom:20px}.page-head h1{font-size:28px;letter-spacing:-.8px}.page-head p{color:var(--stone);font-size:14px;margin-top:4px}.grid{display:grid;grid-template-columns:1fr;gap:16px}.panel{border:1px solid var(--hairline-soft);background:var(--canvas);border-radius:var(--radius-xl);padding:18px}.panel h2{font-size:16px;margin-bottom:12px}.actions{display:flex;gap:8px;flex-wrap:wrap}.input{height:42px;border:1px solid var(--hairline-strong);border-radius:var(--radius-full);padding:0 14px;outline:none;min-width:220px}.btn{border:1px solid var(--hairline-strong);background:var(--canvas);border-radius:var(--radius-full);padding:9px 14px;font-size:13px;font-weight:700;cursor:pointer}.btn.primary{background:var(--primary);color:var(--on-primary);border-color:var(--primary)}.tokens{display:flex;gap:8px;flex-wrap:wrap;margin-top:14px}.token{display:inline-flex;align-items:center;gap:6px;background:var(--surface);border-radius:var(--radius-full);padding:6px 10px;font-size:13px;font-weight:800}.token button{border:0;background:transparent;color:var(--stone);cursor:pointer;font-weight:900}.watch-cards{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:12px;margin-top:14px}.watch-card{border:1px solid var(--hairline-soft);border-radius:var(--radius-lg);padding:14px;background:var(--surface)}.watch-card b{font-size:16px}.meta{font-size:12px;color:var(--stone);margin-top:6px}.status{display:inline-flex;margin-top:8px;border-radius:var(--radius-full);padding:3px 8px;font-size:11px;font-weight:800}.status.buy{color:var(--green);background:var(--green-light)}.status.wait{color:var(--yellow-dark);background:var(--yellow-light)}.status.obs{color:var(--blue);background:rgba(66,98,255,.06)}.empty{color:var(--stone);font-size:13px;padding:12px 0}@media(max-width:820px){.watch-cards{grid-template-columns:1fr}.shell{width:min(100% - 24px,1180px);padding-top:16px}.actions .input{flex:1;min-width:160px}.btn{min-height:44px}}
|
.shell{width:min(100% - 40px,1180px);margin:0 auto;padding:24px 0 48px}.page-head{margin-bottom:20px}.page-head h1{font-size:28px;letter-spacing:-.8px}.page-head p{color:var(--stone);font-size:14px;margin-top:4px}.grid{display:grid;grid-template-columns:1fr;gap:16px}.panel{border:1px solid var(--hairline-soft);background:var(--canvas);border-radius:var(--radius-xl);padding:18px}.panel h2{font-size:16px;margin-bottom:12px}.actions{display:flex;gap:8px;flex-wrap:wrap}.input{height:42px;border:1px solid var(--hairline-strong);border-radius:var(--radius-full);padding:0 14px;outline:none;min-width:220px}.btn{border:1px solid var(--hairline-strong);background:var(--canvas);border-radius:var(--radius-full);padding:9px 14px;font-size:13px;font-weight:700;cursor:pointer}.btn.primary{background:var(--primary);color:var(--on-primary);border-color:var(--primary)}.tokens{display:flex;gap:8px;flex-wrap:wrap;margin-top:14px}.token{display:inline-flex;align-items:center;gap:6px;background:var(--surface);border-radius:var(--radius-full);padding:6px 10px;font-size:13px;font-weight:800}.token button{border:0;background:transparent;color:var(--stone);cursor:pointer;font-weight:900}.watch-cards{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:12px;margin-top:14px}.watch-card{border:1px solid var(--hairline-soft);border-radius:var(--radius-lg);padding:14px;background:var(--surface)}.watch-card b{font-size:16px}.meta{font-size:12px;color:var(--stone);margin-top:6px}.status{display:inline-flex;margin-top:8px;border-radius:var(--radius-full);padding:3px 8px;font-size:11px;font-weight:800}.status.buy{color:var(--green);background:var(--green-light)}.status.wait{color:var(--yellow-dark);background:var(--yellow-light)}.status.obs{color:var(--blue);background:rgba(66,98,255,.06)}.empty{color:var(--stone);font-size:13px;padding:12px 0}@media(max-width:820px){.watch-cards{grid-template-columns:1fr}.shell{width:min(100% - 24px,1180px);padding-top:16px}.actions .input{flex:1;min-width:160px}.btn{min-height:44px}}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user