您好,' . htmlspecialchars($username) . ':
+感谢您注册 ' . SITE_NAME . '!请点击下方按钮验证您的邮箱地址:
++ ✅ 验证邮箱 +
+如果按钮无法点击,请复制以下链接到浏览器打开:
+
+ ⏰ 此链接 24 小时 内有效。
+ 🔒 如果您没有注册 ' . SITE_NAME . ',请忽略并删除此邮件。
+
diff --git a/README.md b/README.md index 04ad167..06d7405 100644 Binary files a/README.md and b/README.md differ diff --git a/functions.php b/functions.php new file mode 100644 index 0000000..9de4e79 --- /dev/null +++ b/functions.php @@ -0,0 +1,962 @@ +prepare("SELECT id FROM users WHERE username = ?"); + $stmt->execute([$username]); + if ($stmt->fetch()) { + return ['success' => false, 'message' => '用户名已被使用']; + } + + // 检查邮箱是否已存在 + $stmt = $pdo->prepare("SELECT id FROM users WHERE email = ?"); + $stmt->execute([$email]); + if ($stmt->fetch()) { + return ['success' => false, 'message' => '邮箱已被注册']; + } + + $pdo->beginTransaction(); + try { + $hashedPassword = password_hash($password, PASSWORD_DEFAULT); + $verificationToken = bin2hex(random_bytes(32)); + $inviteCodeGen = strtoupper(substr(bin2hex(random_bytes(6)), 0, 8)); + + // 处理邀请 + $invitedBy = null; + if ($inviteCode) { + $stmt = $pdo->prepare("SELECT id FROM users WHERE invite_code = ?"); + $stmt->execute([$inviteCode]); + $inviter = $stmt->fetch(); + if ($inviter) { + $invitedBy = $inviter['id']; + } + } + + // 创建用户 + $stmt = $pdo->prepare("INSERT INTO users (username, email, password, invite_code, invited_by, verification_token) VALUES (?, ?, ?, ?, ?, ?)"); + $stmt->execute([$username, $email, $hashedPassword, $inviteCodeGen, $invitedBy, $verificationToken]); + $userId = $pdo->lastInsertId(); + + // 如果是邀请注册,给邀请人加积分 + if ($invitedBy) { + // 增加邀请人积分 + $stmt = $pdo->prepare("UPDATE users SET credits = credits + ? WHERE id = ?"); + $stmt->execute([INVITE_CREDIT, $invitedBy]); + + // 记录邀请日志 + $stmt = $pdo->prepare("INSERT INTO invite_logs (inviter_id, invitee_id, credits_earned) VALUES (?, ?, ?)"); + $stmt->execute([$invitedBy, $userId, INVITE_CREDIT]); + } + + $pdo->commit(); + + // 发送验证邮件 + sendVerificationEmail($email, $username, $verificationToken); + + return ['success' => true, 'message' => '注册成功!请查收验证邮件']; + + } catch (Exception $e) { + $pdo->rollBack(); + return ['success' => false, 'message' => '注册失败: ' . $e->getMessage()]; + } +} + +/** + * 用户登录 + */ +function loginUser($username, $password) { + $pdo = getDB(); + + $stmt = $pdo->prepare("SELECT * FROM users WHERE username = ? OR email = ?"); + $stmt->execute([$username, $username]); + $user = $stmt->fetch(); + + if (!$user) { + return ['success' => false, 'message' => '用户不存在']; + } + + if (!$user['is_verified']) { + return ['success' => false, 'message' => '请先验证邮箱']; + } + + if (!password_verify($password, $user['password'])) { + return ['success' => false, 'message' => '密码错误']; + } + + $_SESSION['user_id'] = $user['id']; + $_SESSION['username'] = $user['username']; + $_SESSION['is_admin'] = $user['is_admin']; + + return ['success' => true, 'message' => '登录成功']; +} + +/** + * 发送验证邮件(修复乱码问题) + */ +function sendVerificationEmail($email, $username, $token) { + $mail = new PHPMailer(true); + + try { + $mail->isSMTP(); + $mail->Host = SMTP_HOST; + $mail->SMTPAuth = true; + $mail->Username = SMTP_USERNAME; + $mail->Password = SMTP_PASSWORD; + $mail->SMTPSecure = SMTP_SECURE; + $mail->Port = SMTP_PORT; + + // 设置字符编码 - 解决乱码问题 + $mail->CharSet = 'UTF-8'; + $mail->Encoding = 'base64'; + + $mail->setFrom(SMTP_FROM_EMAIL, SMTP_FROM_NAME); + $mail->addAddress($email, $username); + $mail->isHTML(true); + + $verifyLink = SITE_URL . "/verify.php?token=" . $token; + $mail->Subject = '验证邮箱 - ' . SITE_NAME; + + // 邮件正文 - 使用完整的HTML模板 + $mail->Body = ' + + +
+ + +验证您的邮箱地址
+您好,' . htmlspecialchars($username) . ':
+感谢您注册 ' . SITE_NAME . '!请点击下方按钮验证您的邮箱地址:
++ ✅ 验证邮箱 +
+如果按钮无法点击,请复制以下链接到浏览器打开:
+
+ ⏰ 此链接 24 小时 内有效。
+ 🔒 如果您没有注册 ' . SITE_NAME . ',请忽略并删除此邮件。
+
+ 轻松获取免费的二级域名,支持 A、AAAA、CNAME、MX、NS、TXT 记录
+
积分制管理,每日签到免费领取积分
+
注册送 10 积分,每日签到得 2 积分,邀请好友得 10 积分
+支持 A、AAAA、CNAME、MX、NS、TXT 全部记录类型
+域名自动托管到 Cloudflare,全球节点加速,稳定可靠
+邀请好友注册,双方都获得积分奖励,共同成长
+您已安装 Parlz Domains Beta 0.1。
" + echo "请访问 注册页面 来创建管理员账户。
"; + echo ""; + +} catch (PDOException $e) { + die("安装失败: " . $e->getMessage()); +} +?> \ No newline at end of file diff --git a/style.css b/style.css new file mode 100644 index 0000000..479b776 --- /dev/null +++ b/style.css @@ -0,0 +1,1514 @@ +@import url("https://cdn.jsdmirror.com/gh/willow-god/Sharding-fonts/Yozai-Medium/result.min.css"); + +:root { + --bg-primary: #0d1117; + --bg-secondary: #161b22; + --bg-card: #1c2333; + --bg-input: #0d1117; + --bg-hover: #1c2333; + --text-primary: #e6edf3; + --text-secondary: #8b949e; + --text-muted: #484f58; + --border-color: #30363d; + --shadow: 0 8px 32px rgba(0, 0, 0, 0.4); + --shadow-hover: 0 12px 48px rgba(0, 0, 0, 0.6); + --accent-blue: #58a6ff; + --accent-blue-dark: #1f6feb; + --accent-green: #3fb950; + --accent-red: #f85149; + --accent-yellow: #d29922; + --accent-purple: #bc8cff; + --accent-orange: #f0883e; + --radius: 12px; + --radius-sm: 6px; + --transition: 0.3s cubic-bezier(0.4, 0, 0.2, 1); +} + +[data-theme="light"] { + --bg-primary: #f6f8fa; + --bg-secondary: #ffffff; + --bg-card: #ffffff; + --bg-input: #f6f8fa; + --bg-hover: #f3f4f6; + --text-primary: #24292f; + --text-secondary: #57606a; + --text-muted: #8b949e; + --border-color: #d0d7de; + --shadow: 0 8px 32px rgba(0, 0, 0, 0.08); + --shadow-hover: 0 12px 48px rgba(0, 0, 0, 0.12); + --accent-blue: #0969da; + --accent-blue-dark: #0550ae; + --accent-green: #1a7f37; + --accent-red: #cf222e; + --accent-yellow: #9a6700; + --accent-purple: #8250df; + --accent-orange: #bd5612 +} + +*, +*::before, +*::after { + margin: 0; + padding: 0; + box-sizing: border-box +} + +* { + font-family: "Yozai Medium" +} + +html { + scroll-behavior: smooth +} + +body { + background: var(--bg-primary); + color: var(--text-primary); + line-height: 1.6; + transition: background var(--transition), color var(--transition); + min-height: 100vh; + padding: 20px; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale +} + +::-webkit-scrollbar { + width: 8px; + height: 8px +} + +::-webkit-scrollbar-track { + background: var(--bg-primary) +} + +::-webkit-scrollbar-thumb { + background: var(--border-color); + border-radius: 4px; + transition: background var(--transition) +} + +::-webkit-scrollbar-thumb:hover { + background: var(--text-muted) +} + +.container { + max-width: 1100px; + margin: 0 auto; + padding: 0 10px +} + +header { + background: var(--bg-secondary); + border: 1px solid var(--border-color); + border-radius: var(--radius); + padding: 18px 28px; + margin-bottom: 28px; + box-shadow: var(--shadow); + transition: all var(--transition) +} + +header:hover { + box-shadow: var(--shadow-hover) +} + +.header-content { + display: flex; + justify-content: space-between; + align-items: center; + flex-wrap: wrap; + gap: 15px +} + +header h1 { + font-size: 24px; + font-weight: 700; + display: flex; + align-items: center; + gap: 12px; + letter-spacing: -0.5px +} + +header h1 i { + color: var(--accent-blue); + font-size: 26px +} + +.header-actions { + display: flex; + align-items: center; + gap: 12px; + flex-wrap: wrap +} + +.domain-badge { + background: var(--bg-primary); + padding: 6px 16px; + border-radius: 20px; + font-size: 13px; + color: var(--text-secondary); + border: 1px solid var(--border-color); + display: flex; + align-items: center; + gap: 6px; + transition: all var(--transition) +} + +.domain-badge:hover { + border-color: var(--accent-blue); + color: var(--text-primary) +} + +.theme-toggle { + background: var(--bg-primary); + border: 1px solid var(--border-color); + color: var(--text-secondary); + width: 40px; + height: 40px; + border-radius: 50%; + cursor: pointer; + font-size: 18px; + transition: all var(--transition); + display: flex; + align-items: center; + justify-content: center; + flex-shrink: 0 +} + +.theme-toggle:hover { + background: var(--accent-blue); + color: #fff; + border-color: var(--accent-blue); + transform: rotate(20deg) scale(1.05) +} + +.theme-toggle:active { + transform: rotate(40deg) scale(0.95) +} + +.btn { + padding: 10px 24px; + border: none; + border-radius: var(--radius-sm); + font-size: 14px; + font-weight: 600; + cursor: pointer; + transition: all var(--transition); + display: inline-flex; + align-items: center; + gap: 8px; + text-decoration: none; + font-family: var(--font-family); + letter-spacing: 0.3px +} + +.btn:disabled { + opacity: 0.5; + cursor: not-allowed; + transform: none !important +} + +.btn-primary { + background: var(--accent-blue); + color: #fff +} + +.btn-primary:hover:not(:disabled) { + opacity: 0.85; + transform: translateY(-2px); + box-shadow: 0 4px 16px rgba(88, 166, 255, 0.35) +} + +.btn-primary:active:not(:disabled) { + transform: translateY(0) +} + +.btn-success { + background: var(--accent-green); + color: #fff +} + +.btn-success:hover:not(:disabled) { + opacity: 0.85; + transform: translateY(-2px); + box-shadow: 0 4px 16px rgba(63, 185, 80, 0.35) +} + +.btn-danger { + background: var(--accent-red); + color: #fff +} + +.btn-danger:hover:not(:disabled) { + opacity: 0.85; + transform: translateY(-2px); + box-shadow: 0 4px 16px rgba(248, 81, 73, 0.35) +} + +.btn-warning { + background: var(--accent-yellow); + color: #fff +} + +.btn-warning:hover:not(:disabled) { + opacity: 0.85; + transform: translateY(-2px) +} + +.btn-outline { + background: transparent; + border: 2px solid var(--border-color); + color: var(--text-primary) +} + +.btn-outline:hover:not(:disabled) { + border-color: var(--accent-blue); + color: var(--accent-blue); + transform: translateY(-2px) +} + +.btn-sm { + padding: 5px 14px; + font-size: 12px; + border-radius: var(--radius-sm) +} + +.btn-large { + padding: 14px 36px; + font-size: 16px; + border-radius: 10px +} + +.card { + background: var(--bg-secondary); + border: 1px solid var(--border-color); + border-radius: var(--radius); + margin-bottom: 25px; + box-shadow: var(--shadow); + overflow: hidden; + transition: all var(--transition) +} + +.card:hover { + box-shadow: var(--shadow-hover) +} + +.card-header { + padding: 18px 25px; + border-bottom: 1px solid var(--border-color); + display: flex; + justify-content: space-between; + align-items: center; + flex-wrap: wrap; + gap: 10px; + background: var(--bg-primary) +} + +.card-header h2 { + font-size: 18px; + font-weight: 600; + display: flex; + align-items: center; + gap: 10px +} + +.card-header h2 i { + color: var(--accent-blue) +} + +.card-body { + padding: 25px +} + +.badge { + background: var(--accent-blue); + color: #fff; + padding: 2px 14px; + border-radius: 20px; + font-size: 13px; + font-weight: 600; + display: inline-flex; + align-items: center; + gap: 4px +} + +.badge-success { + background: var(--accent-green) +} + +.badge-danger { + background: var(--accent-red) +} + +.badge-warning { + background: var(--accent-yellow) +} + +.add-form { + display: flex; + flex-direction: column; + gap: 18px +} + +.form-row { + display: grid; + grid-template-columns: 1fr 2fr; + gap: 18px +} + +@media (max-width:600px) { + .form-row { + grid-template-columns: 1fr + } +} + +.form-group { + display: flex; + flex-direction: column; + gap: 6px +} + +.form-group label { + font-size: 14px; + font-weight: 500; + color: var(--text-secondary); + display: flex; + align-items: center; + gap: 8px +} + +.form-group label i { + color: var(--accent-blue); + width: 18px; + font-size: 14px +} + +.form-group input, +.form-group select, +.form-group textarea { + padding: 10px 14px; + border: 1px solid var(--border-color); + border-radius: var(--radius-sm); + background: var(--bg-input); + color: var(--text-primary); + font-size: 14px; + transition: all var(--transition); + outline: none; + font-family: var(--font-family); + width: 100% +} + +.form-group input:focus, +.form-group select:focus, +.form-group textarea:focus { + border-color: var(--accent-blue); + box-shadow: 0 0 0 3px rgba(88, 166, 255, 0.15) +} + +.form-group input:disabled, +.form-group select:disabled { + opacity: 0.6; + cursor: not-allowed +} + +.form-group input::placeholder { + color: var(--text-muted) +} + +.input-group { + display: flex; + align-items: center +} + +.input-group input { + flex: 1; + border-radius: var(--radius-sm) 0 0 var(--radius-sm) +} + +.input-group input:focus { + border-radius: var(--radius-sm) 0 0 var(--radius-sm) +} + +.input-suffix { + padding: 10px 14px; + background: var(--bg-primary); + border: 1px solid var(--border-color); + border-left: none; + border-radius: 0 var(--radius-sm) var(--radius-sm) 0; + color: var(--text-secondary); + font-size: 13px; + white-space: nowrap; + font-weight: 500 +} + +.form-hint { + font-size: 12px; + color: var(--text-muted); + margin-top: 4px; + padding: 4px 10px; + background: var(--bg-primary); + border-radius: 4px; + border-left: 3px solid var(--accent-yellow) +} + +.form-hint i { + color: var(--accent-yellow); + margin-right: 4px +} + +.record-type-help { + background: var(--bg-primary); + border-radius: var(--radius-sm); + padding: 10px 14px; + font-size: 13px; + color: var(--text-secondary); + border: 1px solid var(--border-color); + margin-top: 6px; + transition: all var(--transition) +} + +.record-type-help i { + color: var(--accent-yellow); + margin-right: 6px +} + +.record-type-help code { + background: var(--bg-secondary); + padding: 2px 8px; + border-radius: 3px; + font-size: 12px; + font-family: 'SF Mono', 'Fira Code', monospace; + color: var(--text-primary); + border: 1px solid var(--border-color) +} + +.form-group input:invalid { + border-color: var(--accent-red) +} + +.form-group input:invalid:focus { + border-color: var(--accent-red); + box-shadow: 0 0 0 3px rgba(248, 81, 73, 0.15) +} + +.form-group input:valid { + border-color: var(--accent-green) +} + +.table-responsive { + overflow-x: auto; + margin: -5px; + padding: 5px +} + +table { + width: 100%; + border-collapse: collapse; + font-size: 14px +} + +thead { + background: var(--bg-primary); + border-bottom: 2px solid var(--border-color) +} + +th { + text-align: left; + padding: 12px 16px; + font-size: 13px; + font-weight: 600; + color: var(--text-secondary); + white-space: nowrap +} + +th i { + margin-right: 6px; + color: var(--accent-blue) +} + +td { + padding: 12px 16px; + border-bottom: 1px solid var(--border-color); + vertical-align: middle +} + +tbody tr { + transition: background var(--transition) +} + +tbody tr:hover { + background: var(--bg-hover) +} + +tbody tr:last-child td { + border-bottom: none +} + +.domain-name { + font-weight: 600 +} + +.domain-name small { + color: var(--text-muted); + font-weight: 400 +} + +.main-domain { + font-weight: 600; + color: var(--accent-blue); + background: var(--bg-primary); + padding: 2px 12px; + border-radius: 4px; + font-size: 13px; + border: 1px solid var(--border-color) +} + +.record-type { + display: inline-block; + padding: 2px 12px; + border-radius: 4px; + background: var(--bg-primary); + font-weight: 700; + font-size: 12px; + color: var(--accent-yellow); + border: 1px solid var(--border-color); + font-family: 'SF Mono', 'Fira Code', monospace +} + +.record-type.a { + color: var(--accent-blue) +} + +.record-type.aaaa { + color: var(--accent-purple) +} + +.record-type.cname { + color: var(--accent-green) +} + +.record-type.mx { + color: var(--accent-orange) +} + +.record-type.ns { + color: var(--accent-red) +} + +.record-type.txt { + color: var(--accent-yellow) +} + +.domain-value { + color: var(--text-secondary); + font-size: 13px; + word-break: break-all; + max-width: 300px; + font-family: 'SF Mono', 'Fira Code', monospace; + background: var(--bg-primary); + padding: 2px 10px; + border-radius: 4px; + border: 1px solid var(--border-color); + display: inline-block +} + +.domain-item { + display: flex; + justify-content: space-between; + align-items: center; + padding: 12px 16px; + border-bottom: 1px solid var(--border-color); + flex-wrap: wrap; + gap: 10px; + transition: background var(--transition) +} + +.domain-item:hover { + background: var(--bg-hover) +} + +.domain-item:last-child { + border-bottom: none +} + +.domain-info { + display: flex; + align-items: center; + gap: 15px; + flex-wrap: wrap +} + +.domain-full { + font-weight: 600 +} + +.domain-full small { + color: var(--text-muted); + font-weight: 400 +} + +.stats-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); + gap: 15px; + margin-bottom: 25px +} + +.stat-card { + background: var(--bg-secondary); + border: 1px solid var(--border-color); + border-radius: var(--radius); + padding: 18px 20px; + text-align: center; + transition: all var(--transition); + box-shadow: var(--shadow) +} + +.stat-card:hover { + border-color: var(--accent-blue); + transform: translateY(-3px); + box-shadow: var(--shadow-hover) +} + +.stat-card .number { + font-size: 28px; + font-weight: 700; + color: var(--accent-blue); + line-height: 1.2 +} + +.stat-card .label { + font-size: 13px; + color: var(--text-secondary); + margin-top: 4px; + display: flex; + align-items: center; + justify-content: center; + gap: 4px +} + +.stat-card.credits .number { + color: var(--accent-yellow) +} + +.stat-card.domains .number { + color: var(--accent-green) +} + +.stat-card.signin .number { + color: var(--accent-blue) +} + +.alert { + padding: 14px 20px; + border-radius: var(--radius); + margin-bottom: 20px; + display: flex; + align-items: center; + gap: 12px; + border: 1px solid transparent; + animation: slideDown 0.4s ease +} + +@keyframes slideDown { + from { + opacity: 0; + transform: translateY(-20px) + } + + to { + opacity: 1; + transform: translateY(0) + } +} + +.alert-success { + background: rgba(63, 185, 80, 0.12); + border-color: var(--accent-green); + color: var(--accent-green) +} + +.alert-error { + background: rgba(248, 81, 73, 0.12); + border-color: var(--accent-red); + color: var(--accent-red) +} + +.alert-warning { + background: rgba(210, 153, 34, 0.12); + border-color: var(--accent-yellow); + color: var(--accent-yellow) +} + +.alert-info { + background: rgba(88, 166, 255, 0.12); + border-color: var(--accent-blue); + color: var(--accent-blue) +} + +.alert i { + font-size: 18px; + flex-shrink: 0 +} + +.empty-state { + text-align: center; + padding: 50px 20px; + color: var(--text-secondary) +} + +.empty-state i { + font-size: 48px; + margin-bottom: 15px; + opacity: 0.3; + display: block +} + +.empty-state p { + font-size: 16px; + margin-bottom: 6px +} + +.empty-state .sub-text { + font-size: 13px; + color: var(--text-muted) +} + +.invite-box { + background: var(--bg-primary); + border: 1px solid var(--border-color); + border-radius: var(--radius); + padding: 15px 20px; + display: flex; + align-items: center; + justify-content: space-between; + flex-wrap: wrap; + gap: 12px; + margin-bottom: 20px; + transition: all var(--transition) +} + +.invite-box:hover { + border-color: var(--accent-yellow) +} + +.invite-code { + font-family: 'SF Mono', 'Fira Code', monospace; + font-size: 18px; + font-weight: 700; + color: var(--accent-blue); + background: var(--bg-secondary); + padding: 6px 16px; + border-radius: var(--radius-sm); + border: 1px solid var(--border-color); + letter-spacing: 2px +} + +.copy-btn { + background: var(--bg-secondary); + border: 1px solid var(--border-color); + color: var(--text-primary); + padding: 6px 16px; + border-radius: var(--radius-sm); + cursor: pointer; + transition: all var(--transition); + font-size: 13px; + font-weight: 500 +} + +.copy-btn:hover { + background: var(--accent-blue); + color: #fff; + border-color: var(--accent-blue); + transform: scale(1.02) +} + +.features-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); + gap: 20px; + margin: 40px 0 +} + +.feature-card { + background: var(--bg-secondary); + border: 1px solid var(--border-color); + border-radius: var(--radius); + padding: 24px 20px; + text-align: center; + transition: all var(--transition); + box-shadow: var(--shadow) +} + +.feature-card:hover { + transform: translateY(-4px); + border-color: var(--accent-blue); + box-shadow: var(--shadow-hover) +} + +.feature-card i { + font-size: 32px; + color: var(--accent-blue); + margin-bottom: 12px; + display: block +} + +.feature-card h3 { + font-size: 16px; + margin-bottom: 6px; + font-weight: 600 +} + +.feature-card p { + font-size: 13px; + color: var(--text-secondary); + line-height: 1.5 +} + +.hero { + text-align: center; + padding: 60px 20px 40px +} + +.hero h1 { + font-size: 42px; + font-weight: 800; + margin-bottom: 16px; + letter-spacing: -1px +} + +.hero h1 i { + color: var(--accent-blue) +} + +.hero p { + font-size: 18px; + color: var(--text-secondary); + max-width: 600px; + margin: 0 auto 30px; + line-height: 1.7 +} + +.hero .btn-group { + display: flex; + gap: 12px; + justify-content: center; + flex-wrap: wrap +} + +.stats-bar { + display: flex; + justify-content: center; + gap: 40px; + flex-wrap: wrap; + padding: 20px 30px; + background: var(--bg-secondary); + border-radius: var(--radius); + border: 1px solid var(--border-color); + margin: 30px 0; + box-shadow: var(--shadow) +} + +.stats-bar .stat-item { + text-align: center +} + +.stats-bar .stat-number { + font-size: 28px; + font-weight: 700; + color: var(--accent-blue); + line-height: 1.2 +} + +.stats-bar .stat-label { + font-size: 13px; + color: var(--text-secondary) +} + +.recent-list { + margin-top: 0 +} + +.recent-item { + display: flex; + justify-content: space-between; + align-items: center; + padding: 10px 16px; + border-bottom: 1px solid var(--border-color); + font-size: 14px; + flex-wrap: wrap; + gap: 8px; + transition: background var(--transition) +} + +.recent-item:hover { + background: var(--bg-hover) +} + +.recent-item:last-child { + border-bottom: none +} + +.recent-domain { + font-weight: 600 +} + +.recent-domain small { + color: var(--text-muted); + font-weight: 400 +} + +.recent-user { + color: var(--text-secondary); + font-size: 12px; + display: flex; + align-items: center; + gap: 4px +} + +.recent-type { + background: var(--bg-primary); + padding: 1px 10px; + border-radius: 4px; + font-size: 11px; + font-weight: 700; + color: var(--accent-yellow); + border: 1px solid var(--border-color) +} + +.auth-container { + max-width: 440px; + margin: 60px auto 40px +} + +.auth-card { + background: var(--bg-secondary); + border: 1px solid var(--border-color); + border-radius: var(--radius); + padding: 40px; + box-shadow: var(--shadow) +} + +.auth-card h2 { + text-align: center; + margin-bottom: 30px; + font-weight: 700; + font-size: 24px +} + +.auth-card h2 i { + color: var(--accent-blue) +} + +.auth-switch { + text-align: center; + margin-top: 20px; + color: var(--text-secondary); + font-size: 14px +} + +.auth-switch a { + color: var(--accent-blue); + text-decoration: none; + font-weight: 500 +} + +.auth-switch a:hover { + text-decoration: underline +} + +.invite-hint { + font-size: 12px; + color: var(--text-muted); + margin-top: 4px +} + +.user-row { + display: flex; + justify-content: space-between; + align-items: center; + padding: 12px 16px; + border-bottom: 1px solid var(--border-color); + flex-wrap: wrap; + gap: 10px; + transition: background var(--transition) +} + +.user-row:hover { + background: var(--bg-hover) +} + +.user-row:last-child { + border-bottom: none +} + +.user-info { + display: flex; + align-items: center; + gap: 15px; + flex-wrap: wrap +} + +.user-badge { + font-size: 12px; + padding: 2px 12px; + border-radius: 4px; + font-weight: 500 +} + +.user-badge.admin { + background: var(--accent-blue); + color: #fff +} + +.user-badge.user { + background: var(--bg-primary); + color: var(--text-secondary); + border: 1px solid var(--border-color) +} + +.user-badge.verified { + background: var(--accent-green); + color: #fff +} + +.user-badge.unverified { + background: var(--accent-red); + color: #fff +} + +.admin-actions { + display: flex; + gap: 8px; + flex-wrap: wrap; + align-items: center +} + +.admin-actions input[type="number"] { + width: 60px; + padding: 4px 6px; + border-radius: 4px; + border: 1px solid var(--border-color); + background: var(--bg-input); + color: var(--text-primary); + font-size: 13px +} + +.admin-actions select { + padding: 4px 6px; + border-radius: 4px; + border: 1px solid var(--border-color); + background: var(--bg-input); + color: var(--text-primary); + font-size: 13px +} + +.welcome-header { + display: flex; + justify-content: space-between; + align-items: center; + flex-wrap: wrap; + gap: 15px; + margin-bottom: 25px +} + +.welcome-header h1 { + font-size: 24px; + font-weight: 700 +} + +.user-actions { + display: flex; + gap: 10px; + flex-wrap: wrap; + align-items: center +} + +footer { + text-align: center; + padding: 30px 0 20px; + color: var(--text-muted); + font-size: 13px; + border-top: 1px solid var(--border-color); + margin-top: 30px +} + +footer a { + color: var(--accent-blue); + text-decoration: none +} + +footer a:hover { + text-decoration: underline +} + +footer .fa-heart { + color: var(--accent-red) +} + +@keyframes spin { + from { + transform: rotate(0deg) + } + + to { + transform: rotate(360deg) + } +} + +.fa-spinner { + animation: spin 1s linear infinite +} + +.text-center { + text-align: center +} + +.text-muted { + color: var(--text-muted) +} + +.text-secondary { + color: var(--text-secondary) +} + +.mt-10 { + margin-top: 10px +} + +.mb-10 { + margin-bottom: 10px +} + +.mt-20 { + margin-top: 20px +} + +.mb-20 { + margin-bottom: 20px +} + +.flex { + display: flex +} + +.flex-center { + display: flex; + align-items: center; + justify-content: center +} + +.gap-10 { + gap: 10px +} + +.gap-20 { + gap: 20px +} + +.w-full { + width: 100% +} + +@media (max-width:768px) { + body { + padding: 12px + } + + header { + padding: 14px 18px + } + + header h1 { + font-size: 20px + } + + .header-content { + flex-direction: column; + align-items: stretch; + gap: 12px + } + + .header-actions { + justify-content: flex-start; + flex-wrap: wrap + } + + .card-header { + flex-direction: column; + align-items: stretch; + gap: 8px + } + + .card-body { + padding: 16px + } + + .stats-grid { + grid-template-columns: 1fr 1fr; + gap: 10px + } + + .stat-card { + padding: 14px 12px + } + + .stat-card .number { + font-size: 22px + } + + .hero { + padding: 30px 10px 20px + } + + .hero h1 { + font-size: 28px + } + + .hero p { + font-size: 15px; + padding: 0 10px + } + + .hero .btn-group { + flex-direction: column; + align-items: center; + width: 100% + } + + .hero .btn-group .btn { + width: 100%; + justify-content: center + } + + .stats-bar { + gap: 20px; + padding: 16px 20px; + flex-wrap: wrap + } + + .stats-bar .stat-number { + font-size: 22px + } + + .features-grid { + grid-template-columns: 1fr 1fr; + gap: 12px; + margin: 20px 0 + } + + .feature-card { + padding: 16px 14px + } + + .feature-card i { + font-size: 24px + } + + .feature-card h3 { + font-size: 14px + } + + .feature-card p { + font-size: 12px + } + + .invite-box { + flex-direction: column; + align-items: stretch; + text-align: center + } + + .invite-code { + font-size: 16px; + text-align: center + } + + .domain-item { + flex-direction: column; + align-items: stretch; + gap: 8px; + padding: 10px 12px + } + + .domain-info { + flex-direction: column; + align-items: flex-start; + gap: 6px + } + + .domain-value { + max-width: 100%; + word-break: break-all; + font-size: 12px + } + + .domain-full { + font-size: 14px + } + + .user-row { + flex-direction: column; + align-items: stretch; + gap: 10px + } + + .user-info { + flex-direction: column; + align-items: flex-start; + gap: 6px; + font-size: 13px + } + + .admin-actions { + flex-wrap: wrap; + gap: 6px + } + + .admin-actions form { + flex-wrap: wrap + } + + .auth-container { + margin: 30px auto; + padding: 0 10px + } + + .auth-card { + padding: 24px 20px + } + + .recent-item { + flex-direction: column; + align-items: flex-start; + gap: 4px; + padding: 8px 12px; + font-size: 13px + } + + .recent-user { + font-size: 11px + } + + .record-type-help { + font-size: 12px; + padding: 8px 10px + } + + .table-responsive { + margin: 0 -10px; + padding: 0 5px + } + + table { + font-size: 12px + } + + th, + td { + padding: 8px 10px + } + + .btn-large { + padding: 12px 24px; + font-size: 14px + } + + .btn { + font-size: 13px; + padding: 8px 18px + } + + .btn-sm { + font-size: 11px; + padding: 4px 10px + } +} + +@media (max-width:480px) { + .stats-grid { + grid-template-columns: 1fr 1fr; + gap: 8px + } + + .stat-card { + padding: 10px 8px + } + + .stat-card .number { + font-size: 18px + } + + .stat-card .label { + font-size: 11px + } + + .features-grid { + grid-template-columns: 1fr 1fr; + gap: 8px + } + + .feature-card { + padding: 12px 10px + } + + .feature-card i { + font-size: 20px + } + + .feature-card h3 { + font-size: 12px + } + + .feature-card p { + font-size: 11px + } + + .hero h1 { + font-size: 22px + } + + .hero p { + font-size: 13px + } + + header h1 { + font-size: 17px + } + + .domain-badge { + font-size: 11px; + padding: 4px 10px + } + + .card-header h2 { + font-size: 15px + } + + .badge { + font-size: 11px; + padding: 1px 10px + } + + .form-group label { + font-size: 12px + } + + .form-group input, + .form-group select { + font-size: 13px; + padding: 8px 12px + } + + .invite-code { + font-size: 14px; + padding: 4px 12px + } + + .stats-bar .stat-number { + font-size: 18px + } + + .stats-bar .stat-label { + font-size: 11px + } +} \ No newline at end of file