/* 打飞机对战小程序 - 统一样式表 */ /* 从所有原型页面提取的通用样式 */ /* ========== CSS变量定义 ========== */ :root { /* 主色调 - 深空科技蓝 */ --primary-color: #6366f1; --primary-light: #8b5cf6; --primary-dark: #4f46e5; /* 辅助色 - 科技青色 */ --secondary-color: #40e0d0; --secondary-light: #26d0ce; /* 强调色 - 橙色 */ --accent-color: #f59e0b; --accent-light: #fbbf24; /* 危险色 - 红色 */ --danger-color: #ff4757; --danger-light: #ff6b6b; /* 成功色 - 绿色 */ --success-color: #10b981; --success-light: #4ade80; /* 背景色系 - 深色渐变 */ --bg-primary: #0f1419; --bg-secondary: #1a1d29; --bg-tertiary: #252837; --bg-elevated: #2d3142; /* 渐变背景 */ --gradient-bg: linear-gradient(135deg, #0f0f1a 0%, #1a1a2e 30%, #16213e 70%, #0f3460 100%); /* 边框色系 */ --border-primary: #3d4159; --border-secondary: #4a5073; --border-highlight: #6366f1; --border-accent: rgba(64, 224, 208, 0.3); /* 文字色系 */ --text-primary: #ffffff; --text-secondary: #b4b7c9; --text-tertiary: #9ca3af; --text-disabled: #6b7280; /* 移动端触摸区域尺寸 */ --touch-target-min: 44px; --safe-area-padding: 20px; --cell-size: min(8.5vw, 38px); } /* ========== 基础重置样式 ========== */ * { margin: 0; padding: 0; box-sizing: border-box; -webkit-user-select: none; -webkit-touch-callout: none; -webkit-tap-highlight-color: transparent; } html, body { height: 100%; overflow-x: hidden; -webkit-text-size-adjust: 100%; } body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", "Microsoft YaHei UI", sans-serif; background: var(--gradient-bg); color: var(--text-primary); line-height: 1.6; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; touch-action: manipulation; user-select: none; } /* ========== 安全区域适配 ========== */ .safe-area { padding-left: env(safe-area-inset-left); padding-right: env(safe-area-inset-right); padding-top: env(safe-area-inset-top); padding-bottom: env(safe-area-inset-bottom); } /* ========== 动态星空背景 ========== */ .star-field { position: fixed; top: 0; left: 0; width: 100%; height: 100%; z-index: 0; overflow: hidden; } .star { position: absolute; background: rgba(64, 224, 208, 0.8); border-radius: 50%; animation: twinkle 3s infinite; } @keyframes twinkle { 0%, 100% { opacity: 0.3; transform: scale(1); } 50% { opacity: 1; transform: scale(1.2); } } /* ========== 主容器布局 ========== */ .app-container { display: flex; flex-direction: column; min-height: 100vh; position: relative; z-index: 1; } /* ========== 顶部导航栏 ========== */ .user-header, .status-header, .header { background: rgba(26, 29, 41, 0.95); backdrop-filter: blur(20px); padding: 15px var(--safe-area-padding); display: flex; justify-content: space-between; align-items: center; border-bottom: 1px solid var(--border-primary); position: sticky; top: 0; z-index: 100; } .top-nav { padding: 12px var(--safe-area-padding); border-bottom: 1px solid var(--border-primary); text-align: center; font-weight: 600; background: rgba(15, 20, 25, 0.8); backdrop-filter: blur(10px); } /* ========== 用户信息组件 ========== */ .user-info { display: flex; align-items: center; gap: 12px; } .user-avatar, .player-avatar { width: 40px; height: 40px; border-radius: 50%; background: linear-gradient(135deg, var(--primary-color) 0%, var(--primary-light) 100%); display: flex; align-items: center; justify-content: center; font-size: 18px; font-weight: 600; color: white; box-shadow: 0 4px 12px rgba(99, 102, 241, 0.3); } .user-details h3 { font-size: 16px; font-weight: 600; color: var(--text-primary); margin-bottom: 2px; } .user-level { font-size: 12px; color: var(--text-secondary); display: flex; align-items: center; gap: 4px; } .level-badge { background: linear-gradient(135deg, var(--accent-color) 0%, var(--accent-light) 100%); color: white; padding: 2px 8px; border-radius: 12px; font-size: 10px; font-weight: 600; } /* ========== 通用按钮样式 ========== */ .btn { min-height: var(--touch-target-min); border: none; border-radius: 12px; font-size: 16px; font-weight: 600; cursor: pointer; padding: 14px 24px; transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); display: flex; align-items: center; justify-content: center; gap: 8px; user-select: none; -webkit-tap-highlight-color: transparent; position: relative; overflow: hidden; } /* 主要按钮样式 */ .btn-primary { background: linear-gradient(135deg, var(--primary-color), var(--primary-light)); color: #ffffff; box-shadow: 0 4px 16px rgba(99, 102, 241, 0.3); } .btn-primary::before { content: ''; position: absolute; top: 50%; left: 50%; width: 0; height: 0; background: rgba(255, 255, 255, 0.3); border-radius: 50%; transform: translate(-50%, -50%); transition: width 0.3s, height 0.3s; } .btn-primary:hover, .btn-primary:focus { transform: translateY(-2px); box-shadow: 0 8px 25px rgba(99, 102, 241, 0.4); } .btn-primary:active { transform: translateY(0); box-shadow: 0 2px 8px rgba(99, 102, 241, 0.4); } .btn-primary:active::before { width: 100%; height: 100%; } /* 成功按钮样式 */ .btn-success { background: linear-gradient(135deg, var(--secondary-color), var(--secondary-light)); color: #1a1a2e; box-shadow: 0 4px 16px rgba(64, 224, 208, 0.3); } .btn-success::before { content: ''; position: absolute; top: 50%; left: 50%; width: 0; height: 0; background: rgba(255, 255, 255, 0.3); border-radius: 50%; transform: translate(-50%, -50%); transition: width 0.3s, height 0.3s; } .btn-success:hover, .btn-success:focus { transform: translateY(-2px); box-shadow: 0 8px 25px rgba(64, 224, 208, 0.4); } .btn-success:active { transform: translateY(0); box-shadow: 0 2px 8px rgba(64, 224, 208, 0.4); } .btn-success:active::before { width: 100%; height: 100%; } /* 次要按钮样式 */ .btn-secondary { background: rgba(99, 102, 241, 0.15); color: var(--primary-color); border: 1px solid var(--primary-color); backdrop-filter: blur(10px); } .btn-secondary::before { content: ''; position: absolute; top: 50%; left: 50%; width: 0; height: 0; background: rgba(99, 102, 241, 0.2); border-radius: 50%; transform: translate(-50%, -50%); transition: width 0.3s, height 0.3s; } .btn-secondary:hover, .btn-secondary:focus { background: rgba(99, 102, 241, 0.25); transform: translateY(-1px); } .btn-secondary:active { transform: translateY(0); } .btn-secondary:active::before { width: 100%; height: 100%; } /* 危险按钮样式 */ .btn-danger { background: linear-gradient(135deg, var(--danger-color), var(--danger-light)); color: white; box-shadow: 0 4px 16px rgba(255, 71, 87, 0.3); } /* 按钮禁用状态 */ .btn:disabled { background: var(--bg-tertiary) !important; color: var(--text-disabled) !important; border: 1px solid var(--border-primary) !important; opacity: 0.6; cursor: not-allowed; box-shadow: none !important; } .btn:disabled:active { transform: none !important; } /* 按钮图标和副标题 */ .button-icon { font-size: 18px; } .button-subtitle { font-size: 12px; opacity: 0.8; font-weight: 400; } /* ========== 设置和操作按钮 ========== */ .settings-btn, .back-btn, .share-btn { width: 40px; height: 40px; border-radius: 50%; border: none; display: flex; align-items: center; justify-content: center; cursor: pointer; transition: all 0.3s ease; font-size: 20px; } .settings-btn { background: rgba(99, 102, 241, 0.15); border: 1px solid var(--primary-color); color: var(--primary-color); } .back-btn { background: rgba(99, 102, 241, 0.15); border-radius: 12px; color: var(--primary-color); font-size: 18px; } .share-btn { background: rgba(64, 224, 208, 0.15); border-radius: 12px; color: var(--secondary-color); font-size: 16px; } .settings-btn:hover, .back-btn:active, .share-btn:active { transform: scale(1.05); } .settings-btn:active, .back-btn:active, .share-btn:active { transform: scale(0.95); } /* ========== 卡片样式 ========== */ .title-card, .rules-card { width: 100%; max-width: 400px; background: rgba(22, 33, 62, 0.8); border: 1px solid rgba(64, 224, 208, 0.3); border-radius: 16px; padding: 30px 20px; backdrop-filter: blur(10px); box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3); margin-bottom: 30px; position: relative; overflow: hidden; } .title-card::before { content: ''; position: absolute; top: 0; left: 0; right: 0; height: 3px; background: linear-gradient(90deg, var(--primary-color), var(--secondary-color), var(--accent-color)); animation: shimmer 3s ease-in-out infinite; } @keyframes shimmer { 0%, 100% { transform: translateX(-100%); } 50% { transform: translateX(100%); } } /* 游戏标题 */ .game-title { font-size: 28px; font-weight: 700; background: linear-gradient(135deg, var(--primary-color) 0%, var(--primary-light) 50%, var(--secondary-color) 100%); -webkit-background-clip: text; -webkit-text-fill-color: transparent; margin-bottom: 10px; position: relative; } .game-subtitle { font-size: 14px; color: var(--text-secondary); margin-bottom: 20px; } /* ========== 飞机装饰 ========== */ .plane-decoration { position: absolute; opacity: 0.1; font-size: 60px; color: var(--primary-color); } .plane-decoration.top-left { top: 10px; left: 10px; transform: rotate(-45deg); } .plane-decoration.top-right { top: 10px; right: 10px; transform: rotate(45deg); } .plane-decoration.bottom-left { bottom: 10px; left: 10px; transform: rotate(135deg); } .plane-decoration.bottom-right { bottom: 10px; right: 10px; transform: rotate(-135deg); } /* ========== 游戏规则样式 ========== */ .rules-header { display: flex; align-items: center; gap: 10px; margin-bottom: 20px; } .rules-icon { width: 24px; height: 24px; background: linear-gradient(135deg, var(--secondary-color) 0%, var(--secondary-light) 100%); border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 14px; color: #1a1a2e; font-weight: 600; } .rules-title { font-size: 18px; font-weight: 600; color: var(--text-primary); } .rules-content { text-align: left; } .rule-item { display: flex; align-items: flex-start; gap: 12px; margin-bottom: 12px; color: var(--text-secondary); font-size: 14px; line-height: 1.5; } .rule-item:last-child { margin-bottom: 0; } .rule-number { min-width: 20px; height: 20px; background: rgba(99, 102, 241, 0.2); border: 1px solid var(--primary-color); border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 11px; font-weight: 600; color: var(--primary-color); margin-top: 2px; } /* ========== 游戏棋盘样式 ========== */ .board-wrapper { position: relative; } .game-board { display: grid; grid-template-columns: repeat(10, var(--cell-size)); grid-template-rows: repeat(10, var(--cell-size)); gap: 1px; background: var(--border-primary); border: 1px solid var(--border-primary); } .board-cell { background: var(--bg-secondary); transition: background-color 0.2s; display: flex; align-items: center; justify-content: center; font-size: 10px; color: rgba(255, 255, 255, 0.4); position: relative; cursor: pointer; user-select: none; font-weight: 600; } .board-cell:active { background-color: var(--border-highlight); transform: scale(0.95); border-color: var(--secondary-color); } /* 棋盘飞机状态 */ .board-cell.plane-part { background-color: var(--primary-color); } .board-cell.plane-head { background-color: var(--accent-color); } .board-cell.plane-body { background-color: var(--primary-light); } .board-cell.plane-wing { background-color: var(--primary-light); } .board-cell.plane-tail { background-color: var(--primary-color); } .board-cell.selected { box-shadow: inset 0 0 0 2px var(--success-color); z-index: 1; } /* 坐标轴标识 */ .col-label, .row-label { position: absolute; font-size: 10px; color: var(--text-tertiary); display: flex; align-items: center; justify-content: center; font-weight: 600; } .col-label { top: -20px; height: 15px; width: var(--cell-size); } .row-label { left: -20px; width: 15px; height: var(--cell-size); } /* ========== 输入框样式 ========== */ .search-input { flex: 1; height: var(--touch-target-min); padding: 0 16px; background: rgba(22, 33, 62, 0.8); border: 1px solid rgba(64, 224, 208, 0.3); border-radius: 12px; color: var(--text-primary); font-size: 16px; backdrop-filter: blur(10px); transition: all 0.3s ease; } .search-input:focus { outline: none; border-color: var(--primary-color); box-shadow: 0 0 0 2px rgba(99, 102, 241, 0.2); } .search-input::placeholder { color: var(--text-tertiary); } /* ========== 状态徽章 ========== */ .status-badge { padding: 6px 12px; border-radius: 8px; font-size: 12px; font-weight: 600; } .status-ready { background: rgba(64, 224, 208, 0.2); color: var(--secondary-color); } .status-waiting { background: rgba(156, 163, 175, 0.2); color: var(--text-tertiary); } /* ========== 网络状态和指示器 ========== */ .network-status { display: flex; align-items: center; gap: 6px; color: var(--text-tertiary); } .connection-dot { width: 6px; height: 6px; border-radius: 50%; background: var(--secondary-color); animation: pulse 2s infinite; } @keyframes pulse { 0%, 100% { opacity: 1; transform: scale(1); } 50% { opacity: 0.4; transform: scale(1.3); } } .turn-indicator { padding: 6px 16px; border-radius: 16px; font-size: 14px; font-weight: 600; backdrop-filter: blur(10px); transition: all 0.3s ease; } .turn-indicator.my-turn { background: linear-gradient(135deg, var(--secondary-color) 0%, var(--secondary-light) 100%); color: #1a1a2e; box-shadow: 0 4px 20px rgba(64, 224, 208, 0.4); } .turn-indicator.opponent-turn { background: linear-gradient(135deg, rgba(255, 71, 87, 0.9) 0%, rgba(255, 56, 56, 0.9) 100%); color: white; border: 1px solid rgba(255, 71, 87, 0.6); box-shadow: 0 4px 20px rgba(255, 71, 87, 0.3); } /* ========== 响应式设计 ========== */ @media (max-width: 375px) { :root { --cell-size: min(8vw, 32px); } .user-header { padding: 12px var(--safe-area-padding); } .user-avatar, .player-avatar { width: 36px; height: 36px; font-size: 16px; } .game-title { font-size: 24px; } .btn { font-size: 16px; min-height: 42px; padding: 14px 24px; } } @media (max-height: 640px) { .main-content { padding-top: 15px; padding-bottom: 15px; } .title-card, .rules-card { margin-bottom: 20px; padding: 20px; } .game-title { margin-bottom: 8px; } } /* ========== 辅助功能支持 ========== */ @media (prefers-contrast: high) { :root { --text-primary: #ffffff; --text-secondary: #e5e5e5; --border-primary: #ffffff; --bg-secondary: #000000; } } @media (prefers-reduced-motion: reduce) { *, *::before, *::after { animation-duration: 0.01ms !important; animation-iteration-count: 1 !important; transition-duration: 0.01ms !important; } } @media (prefers-color-scheme: dark) { body { background: var(--bg-primary); color: var(--text-primary); } } /* ========== 触觉反馈动画 ========== */ .haptic-feedback { animation: hapticVibrate 0.1s ease-out; } @keyframes hapticVibrate { 0%, 100% { transform: translateX(0); } 25% { transform: translateX(-1px); } 75% { transform: translateX(1px); } }