Rebrand to 比特骆驼自动化对冲系统; clear login autofill and sim subtitle.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-07-26 22:02:09 +08:00
parent cb97a45051
commit 86d3c94f32
20 changed files with 873 additions and 855 deletions
+8 -3
View File
@@ -1,6 +1,9 @@
# eth_hedge_sim # 比特骆驼自动化对冲系统(eth_hedge_sim
独立自动对冲**模拟盘**:OKX 实盘只读行情 + 本地虚拟资金撮合。 **产品名:比特骆驼自动对冲系统**
工程仓库 / 目录名:`eth_hedge_sim`(与产品名分离,部署路径不变)。
独立自动对冲系统:OKX / 币安行情 + 本地 SIM 撮合,可选 LIVE 实盘。
与现网 `crypto_monitor` **无代码、进程、密钥共用** 与现网 `crypto_monitor` **无代码、进程、密钥共用**
仓库:<https://git.bz121.com/dekun/eth_hedge_sim.git> 仓库:<https://git.bz121.com/dekun/eth_hedge_sim.git>
@@ -11,12 +14,14 @@
- [代码结构](docs/代码结构.md) - [代码结构](docs/代码结构.md)
- [商业化与授权方案](docs/商业化与授权方案.md) - [商业化与授权方案](docs/商业化与授权方案.md)
- [策略说明](docs/策略说明.md) - [策略说明](docs/策略说明.md)
- [实盘策略说明](docs/实盘策略说明.md)
## 访问(测试机) ## 访问(测试机)
- 反代:[`https://dc.hyf2.cc`](https://dc.hyf2.cc) → 本机 `5155`PM2: `eth-hedge-api` - 反代:[`https://dc.hyf2.cc`](https://dc.hyf2.cc) → 本机 `5155`PM2: `eth-hedge-api`
- 默认登录:见服务器 `/opt/eth_hedge_sim/.env``AUTH_USERNAME` / `AUTH_PASSWORD`(示例 `admin` / `admin123` - 登录账号:见服务器 `/opt/eth_hedge_sim/.env``AUTH_USERNAME` / `AUTH_PASSWORD`
- 可在「系统设置」修改用户名/密码;前端固定同源 API,无 API 地址配置项 - 可在「系统设置」修改用户名/密码;前端固定同源 API,无 API 地址配置项
- 支持电脑 / 平板安装为独立应用(PWA)
## 一键部署 / 更新(禁止 scp 传代码) ## 一键部署 / 更新(禁止 scp 传代码)
+2 -2
View File
@@ -73,9 +73,9 @@ async def lifespan(app: FastAPI):
app = FastAPI( app = FastAPI(
title="eth_hedge_sim", title="比特骆驼自动化对冲系统",
version="0.3.0", version="0.3.0",
description="ETH 自动对冲模拟盘 P1/P2", description="比特骆驼自动对冲系统(eth_hedge_sim",
lifespan=lifespan, lifespan=lifespan,
) )
app.add_middleware( app.add_middleware(
+2 -2
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# deploy/lib/common.sh — eth_hedge_sim 部署公共函数 # deploy/lib/common.sh — 比特骆驼自动化对冲系统 部署公共函数
set -e set -e
set -u set -u
if [ -n "${BASH_VERSION:-}" ]; then if [ -n "${BASH_VERSION:-}" ]; then
@@ -144,7 +144,7 @@ print_post_install_guide() {
ip="$(detect_server_ip)" ip="$(detect_server_ip)"
echo "" echo ""
echo "══════════════════════════════════════" echo "══════════════════════════════════════"
echo " eth_hedge_sim 部署完成" echo " 比特骆驼自动化对冲系统 部署完成"
echo " 目录: ${INSTALL_ROOT}" echo " 目录: ${INSTALL_ROOT}"
echo " 本机: http://${ip}:${API_PORT}/health" echo " 本机: http://${ip}:${API_PORT}/health"
echo " 进程: pm2 status → ${PM2_APP_NAME}" echo " 进程: pm2 status → ${PM2_APP_NAME}"
+1 -1
View File
@@ -24,7 +24,7 @@ main_uninstall() {
REPO_ROOT="${root}" REPO_ROOT="${root}"
echo "" echo ""
echo "将卸载 eth_hedge_sim:" echo "将卸载 比特骆驼自动化对冲系统 (eth_hedge_sim):"
echo " - 停止并删除 PM2 进程: ${PM2_APP_NAME}" echo " - 停止并删除 PM2 进程: ${PM2_APP_NAME}"
echo " - 移走目录: ${INSTALL_ROOT}" echo " - 移走目录: ${INSTALL_ROOT}"
echo " - 备份 .env 到 ${BACKUP_ROOT}" echo " - 备份 .env 到 ${BACKUP_ROOT}"
+1 -1
View File
@@ -19,7 +19,7 @@ main_update() {
die "安装不完整,请先执行「1) 一键部署」" die "安装不完整,请先执行「1) 一键部署」"
fi fi
step "更新 eth_hedge_sim (git pull + 构建 + pm2 reload)" step "更新 比特骆驼自动化对冲系统 (git pull + 构建 + pm2 reload)"
bash "${REPO_ROOT}/deploy/pull_and_restart.sh" bash "${REPO_ROOT}/deploy/pull_and_restart.sh"
verify_health || true verify_health || true
echo "" echo ""
+3 -3
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# eth_hedge_sim 部署管理器 — 一键部署 / 卸载 / 更新 # 比特骆驼自动化对冲系统 部署管理器(工程 eth_hedge_sim
# #
# 新服务器(免克隆): # 新服务器(免克隆):
# curl -fsSL https://git.bz121.com/dekun/eth_hedge_sim/raw/branch/main/deploy/manage.sh | bash # curl -fsSL https://git.bz121.com/dekun/eth_hedge_sim/raw/branch/main/deploy/manage.sh | bash
@@ -136,7 +136,7 @@ bootstrap_repo() {
heal_existing_install "${INSTALL_ROOT}" "$@" heal_existing_install "${INSTALL_ROOT}" "$@"
fi fi
echo "eth_hedge_sim 部署管理器 — 首次自举" echo "比特骆驼自动化对冲系统 部署管理器 — 首次自举"
echo "将克隆到: ${INSTALL_ROOT}" echo "将克隆到: ${INSTALL_ROOT}"
if [[ "$(id -u)" -ne 0 ]]; then if [[ "$(id -u)" -ne 0 ]]; then
echo "错误: 请使用 root 执行" >&2 echo "错误: 请使用 root 执行" >&2
@@ -157,7 +157,7 @@ show_banner() {
fi fi
echo "" echo ""
echo "╔══════════════════════════════════════╗" echo "╔══════════════════════════════════════╗"
echo "║ eth_hedge_sim 部署管理器 ║" echo "║ 比特骆驼自动化对冲系统 部署管理器 ║"
echo "║ 路径: ${path}" echo "║ 路径: ${path}"
echo "╚══════════════════════════════════════╝" echo "╚══════════════════════════════════════╝"
echo "" echo ""
+4 -4
View File
@@ -8,21 +8,21 @@ set -euo pipefail
ROOT="$(cd "$(dirname "$0")/.." && pwd)" ROOT="$(cd "$(dirname "$0")/.." && pwd)"
cd "$ROOT" cd "$ROOT"
echo "[eth_hedge_sim] pull @ $ROOT" echo "[比特骆驼] pull @ $ROOT"
if [[ -d "$ROOT/.git" ]]; then if [[ -d "$ROOT/.git" ]]; then
git fetch --all --prune git fetch --all --prune
git pull --ff-only git pull --ff-only
fi fi
if [[ ! -f "$ROOT/.env" ]]; then if [[ ! -f "$ROOT/.env" ]]; then
echo "[eth_hedge_sim] missing .env — copy from example" echo "[比特骆驼] missing .env — copy from example"
cp "$ROOT/.env.example" "$ROOT/.env" cp "$ROOT/.env.example" "$ROOT/.env"
# 云上测试机默认直连 OKX # 云上测试机默认直连 OKX
sed -i 's/^OKX_HTTP_PROXY=.*/OKX_HTTP_PROXY=/' "$ROOT/.env" || true sed -i 's/^OKX_HTTP_PROXY=.*/OKX_HTTP_PROXY=/' "$ROOT/.env" || true
sed -i 's/^API_PORT=.*/API_PORT=5155/' "$ROOT/.env" || true sed -i 's/^API_PORT=.*/API_PORT=5155/' "$ROOT/.env" || true
sed -i 's/^ENV_NAME=.*/ENV_NAME=test/' "$ROOT/.env" || true sed -i 's/^ENV_NAME=.*/ENV_NAME=test/' "$ROOT/.env" || true
sed -i 's/^EXCHANGE=.*/EXCHANGE=okx/' "$ROOT/.env" || true sed -i 's/^EXCHANGE=.*/EXCHANGE=okx/' "$ROOT/.env" || true
echo "[eth_hedge_sim] wrote .env — please review AUTH_* secrets" echo "[比特骆驼] wrote .env — please review AUTH_* secrets"
fi fi
if [[ ! -d "$ROOT/.venv" ]]; then if [[ ! -d "$ROOT/.venv" ]]; then
@@ -52,4 +52,4 @@ fi
pm2 startOrReload "$ROOT/deploy/ecosystem.config.cjs" --update-env pm2 startOrReload "$ROOT/deploy/ecosystem.config.cjs" --update-env
pm2 save pm2 save
echo "[eth_hedge_sim] done. health: http://127.0.0.1:5155/health" echo "[比特骆驼] done. health: http://127.0.0.1:5155/health"
+1 -1
View File
@@ -1,6 +1,6 @@
# OKX 实盘策略说明 # OKX 实盘策略说明
> 专用于 **OKX** LIVE。通用对冲逻辑见 [策略说明](./策略说明.md);币安见 [币安实盘策略说明](./币安实盘策略说明.md)。 > 产品:**比特骆驼自动化对冲系统** · 专用于 **OKX** LIVE。通用对冲逻辑见 [策略说明](./策略说明.md);币安见 [币安实盘策略说明](./币安实盘策略说明.md)。
> **标准仓**:永续 **1 ETH** + 期权 **2 ETH** 名义(倍数 `k` 可缩放)。 > **标准仓**:永续 **1 ETH** + 期权 **2 ETH** 名义(倍数 `k` 可缩放)。
> 更新:2026-07-26 > 更新:2026-07-26
+5 -4
View File
@@ -1,5 +1,6 @@
# eth_hedge_sim — 代码结构 # 比特骆驼自动化对冲系统 — 代码结构
> **产品名**:比特骆驼自动化对冲系统 · **工程目录**`eth_hedge_sim`
> 本文描述目标仓库目录与模块职责。当前阶段以文档为准;业务代码按阶段逐步添加。 > 本文描述目标仓库目录与模块职责。当前阶段以文档为准;业务代码按阶段逐步添加。
> 可从 `crypto_monitor` **复制** 有用片段到本仓库后改造;**禁止修改** 现网仓库内文件。 > 可从 `crypto_monitor` **复制** 有用片段到本仓库后改造;**禁止修改** 现网仓库内文件。
@@ -8,7 +9,7 @@
## 1. 根目录总览 ## 1. 根目录总览
```text ```text
eth_hedge_sim/ eth_hedge_sim/ # 产品:比特骆驼自动化对冲系统
├── README.md ├── README.md
├── .gitignore ├── .gitignore
├── .env.example # 无密钥的示例;真 .env 不上库 ├── .env.example # 无密钥的示例;真 .env 不上库
@@ -34,7 +35,7 @@ eth_hedge_sim/
│ │ └── services/ # 组、统计、设置等应用服务 │ │ └── services/ # 组、统计、设置等应用服务
│ ├── data/ # 本地 SQLite 等(gitignore 数据文件) │ ├── data/ # 本地 SQLite 等(gitignore 数据文件)
│ └── tests/ │ └── tests/
├── frontend/ # OKX 风格 Web ├── frontend/ # Web 控制台(比特骆驼)
│ ├── index.html │ ├── index.html
│ ├── package.json │ ├── package.json
│ ├── src/ │ ├── src/
@@ -48,7 +49,7 @@ eth_hedge_sim/
│ │ │ └── Settings.tsx # 系统设置 │ │ │ └── Settings.tsx # 系统设置
│ │ ├── components/ # 盘口、组标识、持仓条等 │ │ ├── components/ # 盘口、组标识、持仓条等
│ │ ├── api/ # 调后端 │ │ ├── api/ # 调后端
│ │ └── styles/ # OKX 深色交易台风 │ │ └── styles/ # 深色交易台风
│ └── dist/ # 构建产物(可部署由 API 托管或 nginx) │ └── dist/ # 构建产物(可部署由 API 托管或 nginx)
└── scripts/ # 运维/一次性工具(可选) └── scripts/ # 运维/一次性工具(可选)
└── smoke_market.py # 只读行情连通性检查 └── smoke_market.py # 只读行情连通性检查
+4 -2
View File
@@ -1,5 +1,6 @@
# eth_hedge_sim — 商业化与授权方案(初步) # 比特骆驼自动化对冲系统 — 商业化与授权方案(初步)
> **产品名**:比特骆驼自动化对冲系统 · **工程**`eth_hedge_sim`
> 状态:草案,指导后续开发,细节可迭代。 > 状态:草案,指导后续开发,细节可迭代。
> 商业模式结论:**客户侧部署 + 软件授权**(不做中心化多租户托管)。 > 商业模式结论:**客户侧部署 + 软件授权**(不做中心化多租户托管)。
> 关联文档:[开发方案](./开发方案.md)、[代码结构](./代码结构.md) > 关联文档:[开发方案](./开发方案.md)、[代码结构](./代码结构.md)
@@ -12,6 +13,7 @@
| 项 | 约定 | | 项 | 约定 |
|----|------| |----|------|
| 产品名 | **比特骆驼自动化对冲系统** |
| 产品形态 | 可独立部署的对冲交易系统(SIM + 可选实盘) | | 产品形态 | 可独立部署的对冲交易系统(SIM + 可选实盘) |
| 交付方式 | 安装包 / 一键脚本 / Docker(后续择一为主) | | 交付方式 | 安装包 / 一键脚本 / Docker(后续择一为主) |
| 收费方式 | **授权(License**:按实例、按期限、按功能档 | | 收费方式 | **授权(License**:按实例、按期限、按功能档 |
@@ -30,7 +32,7 @@
### 1.3 产品定位一句话 ### 1.3 产品定位一句话
> 客户在自己的服务器上部署;API Key 不出客户环境;你提供软件、更新与授权。 > **比特骆驼自动化对冲系统**客户在自己的服务器上部署;API Key 不出客户环境;你提供软件、更新与授权。
--- ---
+2 -1
View File
@@ -1,5 +1,6 @@
# ETH 永续 + 期权对冲 · 实盘说明索引 # 比特骆驼自动化对冲系统 · 实盘说明索引
> 产品:**比特骆驼自动化对冲系统**
> 通用规则见 [策略说明](./策略说明.md)。**开平仓、资金币种、API 按交易所分开写**,请直接打开对应文档。 > 通用规则见 [策略说明](./策略说明.md)。**开平仓、资金币种、API 按交易所分开写**,请直接打开对应文档。
> 更新:2026-07-26 > 更新:2026-07-26
+1 -1
View File
@@ -1,6 +1,6 @@
# 币安实盘策略说明 # 币安实盘策略说明
> 专用于 **币安** LIVE。通用对冲逻辑见 [策略说明](./策略说明.md)OKX 见 [OKX实盘策略说明](./OKX实盘策略说明.md)。 > 产品:**比特骆驼自动化对冲系统** · 专用于 **币安** LIVE。通用对冲逻辑见 [策略说明](./策略说明.md)OKX 见 [OKX实盘策略说明](./OKX实盘策略说明.md)。
> **标准仓**:永续 **1 ETH** + 期权 **2 ETH** 名义(倍数 `k` 可缩放)。 > **标准仓**:永续 **1 ETH** + 期权 **2 ETH** 名义(倍数 `k` 可缩放)。
> 更新:2026-07-26 > 更新:2026-07-26
+6 -3
View File
@@ -1,5 +1,7 @@
# eth_hedge_sim — 自动对冲模拟盘开发方案 # 比特骆驼自动对冲系统 — 开发方案
> **产品名**:比特骆驼自动化对冲系统
> **工程名 / 目录**`eth_hedge_sim`
> 独立项目,与现网 `crypto_monitor` / `zk.hyf2.cc` **无部署、无进程、无密钥共用关系**。 > 独立项目,与现网 `crypto_monitor` / `zk.hyf2.cc` **无部署、无进程、无密钥共用关系**。
> 可参考现有仓库的实现思路或复制片段到本仓库,但 **禁止修改** `crypto_monitor` 内任何文件。 > 可参考现有仓库的实现思路或复制片段到本仓库,但 **禁止修改** `crypto_monitor` 内任何文件。
> Git 仓库由负责人自行创建;本目录为本地工程骨架与文档。 > Git 仓库由负责人自行创建;本目录为本地工程骨架与文档。
@@ -10,7 +12,8 @@
| 项 | 约定 | | 项 | 约定 |
|----|------| |----|------|
| 项目名 / 目录名 | `eth_hedge_sim` | | 产品名 | **比特骆驼自动化对冲系统** |
| 工程名 / 目录名 | `eth_hedge_sim` |
| 本机路径 | `C:\Users\dekun\Desktop\新建文件夹\eth_hedge_sim` | | 本机路径 | `C:\Users\dekun\Desktop\新建文件夹\eth_hedge_sim` |
| 云服务器 | **单独一台 Ubuntu**(或同机不同目录/不同 PM2 进程名,且与现网隔离) | | 云服务器 | **单独一台 Ubuntu**(或同机不同目录/不同 PM2 进程名,且与现网隔离) |
| 部署 | PM2 | | 部署 | PM2 |
@@ -218,4 +221,4 @@ TZ=Asia/Shanghai
## 9. 一句话 ## 9. 一句话
**独立仓 `eth_hedge_sim`OKX 真行情只读 + 本地虚拟资金撮合(永续市价、期权只买吃买卖一、滑点=1×手续费)+ OKX 风四页前端 + Ubuntu/PM2 单独部署;可抄现网思路,但不改现网代码、不共用现网进程。** **独立仓 `eth_hedge_sim`(产品:比特骆驼自动化对冲系统)OKX/币安真行情只读 + 本地虚拟资金撮合(永续市价、期权只买吃买卖一、滑点=1×手续费)+ 四页前端 + Ubuntu/PM2 单独部署;可抄现网思路,但不改现网代码、不共用现网进程。**
+2 -1
View File
@@ -1,5 +1,6 @@
# ETH 永续 + 期权对冲策略说明 # 比特骆驼自动化对冲系统 — 策略说明
> 产品:**比特骆驼自动化对冲系统**(工程 `eth_hedge_sim`
> 依据当前代码逻辑整理(SIM 默认真值参数)。 > 依据当前代码逻辑整理(SIM 默认真值参数)。
> 关联:[开发方案](./开发方案.md)、[商业化与授权方案](./商业化与授权方案.md)、[实盘索引](./实盘策略说明.md)、[OKX实盘](./OKX实盘策略说明.md)、[币安实盘](./币安实盘策略说明.md) > 关联:[开发方案](./开发方案.md)、[商业化与授权方案](./商业化与授权方案.md)、[实盘索引](./实盘策略说明.md)、[OKX实盘](./OKX实盘策略说明.md)、[币安实盘](./币安实盘策略说明.md)
> 更新:2026-07-26 > 更新:2026-07-26
+4 -4
View File
@@ -11,16 +11,16 @@
<meta name="mobile-web-app-capable" content="yes" /> <meta name="mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-capable" content="yes" /> <meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" /> <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
<meta name="apple-mobile-web-app-title" content="对冲系统" /> <meta name="apple-mobile-web-app-title" content="比特骆驼" />
<meta name="application-name" content="对冲系统" /> <meta name="application-name" content="比特骆驼" />
<meta <meta
name="description" name="description"
content="ETH 永续+期权对冲监控与策略控制台,支持电脑与平板安装为独立应用。" content="比特骆驼自动化对冲系统:ETH 永续+期权对冲监控与策略控制台,支持电脑与平板安装为独立应用。"
/> />
<link rel="manifest" href="/manifest.webmanifest" /> <link rel="manifest" href="/manifest.webmanifest" />
<link rel="icon" type="image/png" sizes="32x32" href="/icons/favicon-32.png" /> <link rel="icon" type="image/png" sizes="32x32" href="/icons/favicon-32.png" />
<link rel="apple-touch-icon" sizes="180x180" href="/icons/apple-touch-icon.png" /> <link rel="apple-touch-icon" sizes="180x180" href="/icons/apple-touch-icon.png" />
<title>OKX 自动化对冲系统</title> <title>比特骆驼自动化对冲系统</title>
<link rel="preconnect" href="https://fonts.googleapis.com" /> <link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin /> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link <link
+2 -1
View File
@@ -1,7 +1,8 @@
{ {
"name": "eth-hedge-sim-web", "name": "bitcamel-hedge-web",
"private": true, "private": true,
"version": "0.2.0", "version": "0.2.0",
"description": "比特骆驼自动化对冲系统 Web",
"type": "module", "type": "module",
"scripts": { "scripts": {
"dev": "vite", "dev": "vite",
+3 -3
View File
@@ -1,7 +1,7 @@
{ {
"name": "OKX 自动化对冲系统", "name": "比特骆驼自动化对冲系统",
"short_name": "对冲系统", "short_name": "比特骆驼",
"description": "ETH 永续+期权对冲监控与策略控制台", "description": "比特骆驼自动化对冲系统:ETH 永续+期权对冲监控与策略控制台",
"start_url": "/plan", "start_url": "/plan",
"scope": "/", "scope": "/",
"display": "standalone", "display": "standalone",
+1 -1
View File
@@ -14,7 +14,7 @@ function Shell({ children }: { children: ReactNode }) {
<div className="app-shell"> <div className="app-shell">
<header className="topnav"> <header className="topnav">
<div className="topnav-side left"> <div className="topnav-side left">
<div className="brand">OKX </div> <div className="brand"></div>
<InstallBadge /> <InstallBadge />
</div> </div>
<nav className="topnav-center"> <nav className="topnav-center">
+2 -3
View File
@@ -5,7 +5,7 @@ import InstallBadge from "../components/InstallBadge";
export default function LoginPage() { export default function LoginPage() {
const nav = useNavigate(); const nav = useNavigate();
const [username, setUsername] = useState("admin"); const [username, setUsername] = useState("");
const [password, setPassword] = useState(""); const [password, setPassword] = useState("");
const [err, setErr] = useState(""); const [err, setErr] = useState("");
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
@@ -29,10 +29,9 @@ export default function LoginPage() {
<div className="login-wrap"> <div className="login-wrap">
<form className="login-box" onSubmit={onSubmit}> <form className="login-box" onSubmit={onSubmit}>
<div className="login-title-row"> <div className="login-title-row">
<h1>OKX </h1> <h1></h1>
<InstallBadge /> <InstallBadge />
</div> </div>
<p> · /</p>
{err ? <div className="err">{err}</div> : null} {err ? <div className="err">{err}</div> : null}
<div className="field"> <div className="field">
<label htmlFor="user"></label> <label htmlFor="user"></label>
+8 -3
View File
@@ -144,7 +144,7 @@ input {
@media (max-width: 900px) { @media (max-width: 900px) {
.topnav-side.left .brand { .topnav-side.left .brand {
max-width: 9em; max-width: 11em;
} }
} }
@@ -400,7 +400,8 @@ input {
.login-box h1 { .login-box h1 {
margin: 0; margin: 0;
font-size: 22px; font-size: 20px;
line-height: 1.35;
} }
.login-title-row { .login-title-row {
@@ -408,7 +409,7 @@ input {
align-items: flex-start; align-items: flex-start;
justify-content: space-between; justify-content: space-between;
gap: 10px; gap: 10px;
margin-bottom: 6px; margin-bottom: 20px;
} }
.login-box p { .login-box p {
@@ -417,6 +418,10 @@ input {
font-size: 13px; font-size: 13px;
} }
.login-box .err {
margin-bottom: 14px;
}
.field { .field {
display: grid; display: grid;
gap: 6px; gap: 6px;