feat(miniprogram): 按设计稿重写小程序前端界面

This commit is contained in:
stu2not
2026-09-02 15:55:48 +08:00
parent af8ddb26c6
commit 9eb3c002fb
27 changed files with 902 additions and 19 deletions
+8 -1
View File
@@ -25,8 +25,15 @@ const config = {
options: {
}
},
fontUrlLoaderOption: {
// Inline the subset so WeChat DevTools does not treat the local font URL as a network request.
limit: 500000,
},
framework: 'react',
mini: {
fontUrlLoaderOption: {
limit: 500000,
},
postcss: {
pxtransform: {
enable: true,
@@ -37,7 +44,7 @@ const config = {
url: {
enable: true,
config: {
limit: 1024 // 设定转换尺寸上限
url: 'copy'
}
},
cssModules: {
+4 -4
View File
@@ -14,14 +14,14 @@ export default defineAppConfig({
],
window: {
backgroundTextStyle: "light",
navigationBarBackgroundColor: "#F5F7FA",
navigationBarBackgroundColor: "#FFF9EA",
navigationBarTitleText: "伴伴",
navigationBarTextStyle: "black",
},
tabBar: {
color: "#999999",
selectedColor: "#FF8C42",
backgroundColor: "#FFFFFF",
color: "#B9A17F",
selectedColor: "#B86E2F",
backgroundColor: "#FFFDF7",
borderStyle: "white",
list: [
{
+2
View File
@@ -76,3 +76,5 @@ page {
justify-content: space-between;
align-items: center;
}
@import './styles/ui-theme.scss';
Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 603 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

+12
View File
@@ -569,6 +569,7 @@ export default function Bind() {
if (loading) {
return (
<View className='bind-page'>
<View className='bb-design-nav-title'><Text>微信登录</Text></View>
<View className='loading'>
<Text>加载中...</Text>
</View>
@@ -579,6 +580,7 @@ export default function Bind() {
return (
<View className='bind-page'>
<View className='bb-design-nav-title'><Text>微信登录</Text></View>
<View className='bind-header'>
<View className='back-btn' onClick={handleBack}>
<Image className='back-icon' src={require('../../assets/tab-icons/arrow-left.png')} mode='aspectFit' />
@@ -587,6 +589,16 @@ export default function Bind() {
<Text className='title'>{pageTitle}</Text>
</View>
{bindStatus === SESSION_STATUS_PENDING && (
<Image className='bind-state-mascot pending' src={require('../../assets/ui/dog-running.png')} mode='aspectFit' />
)}
{bindStatus === SESSION_STATUS_COMPLETED && (
<Image className='bind-state-mascot success' src={require('../../assets/ui/dog-success.png')} mode='aspectFit' />
)}
{(bindStatus === SESSION_STATUS_EXPIRED || bindStatus === SESSION_STATUS_FAILED || bindStatus === SESSION_STATUS_CANCELLED) && (
<Image className='bind-state-mascot failure' src={require('../../assets/ui/dog-failure.png')} mode='aspectFit' />
)}
{isAddingCard ? (
<View className='pending-device-card'>
<View className='icon-bg orange'>
@@ -748,6 +748,7 @@ export default function ChatDetail() {
return (
<View className='chat-detail-page'>
<View className='bb-design-nav-title'><Text>微信登录</Text></View>
<View className='chat-header'>
<View className='back-btn' onClick={handleBack}>
<Image src={require('../../../assets/tab-icons/arrow-left.png')} className='back-arrow-img' />
+1
View File
@@ -75,6 +75,7 @@ export default function Chat() {
return (
<View className='chat-page'>
<View className='bb-design-nav-title'><Text>微信登录</Text></View>
<View className='page-header'>
<Text className='page-title'>玩伴</Text>
</View>
+31
View File
@@ -6,6 +6,37 @@
padding-bottom: calc(160px + env(safe-area-inset-bottom));
}
// Keep the artwork reference's title band in the page flow when custom
// navigation is enabled. The page-local rule ensures it wins over the
// generated page stylesheet order in the mini-program runtime.
.bb-design-nav-title {
position: fixed;
top: 88px;
left: 0;
z-index: 1000;
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 84px;
box-sizing: border-box;
border-bottom: 1px solid rgba(237, 237, 237, 0.95);
background: rgba(255, 255, 255, 0.96);
color: #222;
font-size: 26px;
line-height: 1;
text-align: center;
font-weight: 700;
pointer-events: none;
}
.bb-design-nav-title text {
display: block;
color: #222 !important;
font-size: 26px !important;
line-height: 1;
}
.page-header {
padding: 80px 32px 24px;
+29 -7
View File
@@ -272,6 +272,7 @@ export default function Device() {
if (isLoading) {
return (
<View className='device-page'>
<View className='bb-design-nav-title'><Text>微信登录</Text></View>
<View className='loading'>
<Text>加载中...</Text>
</View>
@@ -283,12 +284,13 @@ export default function Device() {
if (isGuest) {
return (
<View className='device-page'>
<View className='bb-design-nav-title'><Text>微信登录</Text></View>
<View className='guest-hero'>
<View className='guest-device-icon'>
<Image className='robot-img' src={require('../../assets/tab-icons/robot.png')} mode='aspectFit' />
<Image className='guest-mascot' src={require('../../assets/ui/dog-happy.png')} mode='aspectFit' />
</View>
<Text className='guest-title'>伴伴宝贝陪伴设备</Text>
<Text className='guest-subtitle'>查看设备状态、定位轨迹、亲子消息和休眠管理。浏览功能后,可在需要绑定设备时登录。</Text>
<Text className='guest-title'>先认识一下伴伴</Text>
<Text className='guest-subtitle'>无需登录即可浏览主要能力,绑定设备时再完成登录。</Text>
</View>
<View className='guest-feature-grid'>
@@ -321,6 +323,11 @@ export default function Device() {
<Text className='guest-primary-btn-text'>去登录 / 绑定设备</Text>
</View>
</View>
<Image
className='guest-footer-art'
src={require('../../assets/ui/paw-dog-footer.png')}
mode='aspectFit'
/>
{systemBanner}
</View>
)
@@ -330,13 +337,14 @@ export default function Device() {
const hasPendingDevice = Boolean(pendingBinding?.device_id)
return (
<View className='device-page'>
<View className='bb-design-nav-title'><Text>微信登录</Text></View>
<View className='page-header'>
<Text className='page-title'>设备首页</Text>
</View>
<View className='empty-card'>
<View className='empty-robot'>
<Image className='robot-img' src={require('../../assets/tab-icons/robot.png')} mode='aspectFit' />
<Image className='empty-mascot' src={require('../../assets/ui/dog-happy.png')} mode='aspectFit' />
</View>
<Text className='empty-title'>{hasPendingDevice ? '设备已绑定,待关联宝贝' : '先绑定一台伴伴设备'}</Text>
<Text className='empty-subtitle'>
@@ -348,6 +356,7 @@ export default function Device() {
<Text className='empty-btn-text'>{hasPendingDevice ? '关联宝贝' : '添加设备'}</Text>
</View>
</View>
<Image className='guest-footer-art' src={require('../../assets/ui/paw-dog-footer.png')} mode='aspectFit' />
{systemBanner}
</View>
)
@@ -357,6 +366,7 @@ export default function Device() {
const hasPendingDevice = Boolean(pendingBinding?.device_id)
return (
<View className='device-page'>
<View className='bb-design-nav-title'><Text>微信登录</Text></View>
<View className='page-header'>
<Text className='page-title'>{child.child_name} 的伴伴</Text>
</View>
@@ -373,7 +383,7 @@ export default function Device() {
<View className='empty-card'>
<View className='empty-robot'>
<Image className='robot-img' src={require('../../assets/tab-icons/robot.png')} mode='aspectFit' />
<Image className='empty-mascot' src={require('../../assets/ui/dog-happy.png')} mode='aspectFit' />
</View>
<Text className='empty-title'>{hasPendingDevice ? '有设备待关联' : '给当前宝贝绑定一台设备'}</Text>
<Text className='empty-subtitle'>
@@ -385,6 +395,7 @@ export default function Device() {
<Text className='empty-btn-text'>{hasPendingDevice ? '关联到当前宝贝' : '去绑定设备'}</Text>
</View>
</View>
<Image className='guest-footer-art' src={require('../../assets/ui/paw-dog-footer.png')} mode='aspectFit' />
{systemBanner}
</View>
)
@@ -394,6 +405,16 @@ export default function Device() {
const pageTitle = `${childName} 的伴伴`
const batteryValue = deviceStatus?.power ?? deviceStatus?.battery_pct ?? null
const batteryDisplay = formatBatteryDisplay(batteryValue)
const statusMascotSrc =
batteryValue === null
? require('../../assets/ui/dog-happy.png')
: batteryValue > 85
? require('../../assets/ui/dog-happy.png')
: batteryValue > 60
? require('../../assets/ui/dog-sparkle.png')
: batteryValue > 35
? require('../../assets/ui/dog-lying.png')
: require('../../assets/ui/dog-question.png')
const signalLabel = getSignalLabel(deviceStatus?.signal)
const versionLabel = deviceStatus?.version || '--'
const coordinateLabel = formatCoordinates(deviceStatus)
@@ -405,7 +426,8 @@ export default function Device() {
return (
<View className='device-page'>
<View className='page-header'>
<View className='bb-design-nav-title'><Text>微信登录</Text></View>
<View className='page-header bound-device-header'>
<Text className='page-title'>{pageTitle}</Text>
</View>
@@ -433,7 +455,7 @@ export default function Device() {
</View>
<View className='device-avatar'>
<View className='robot-icon'>
<Image className='robot-img' src={require('../../assets/tab-icons/robot.png')} mode='aspectFit' />
<Image className='device-mascot' src={statusMascotSrc} mode='aspectFit' />
</View>
</View>
</View>
@@ -1,4 +1,4 @@
import { View, Text } from '@tarojs/components'
import { View, Text, Image } from '@tarojs/components'
import Taro, { useDidShow, useRouter } from '@tarojs/taro'
import { useState } from 'react'
@@ -75,6 +75,8 @@ export default function FamilyInvite() {
return (
<View className='family-invite-page'>
<View className='bb-design-nav-title'><Text>微信登录</Text></View>
<Image className='invite-mascot' src={require('../../assets/ui/dog-running.png')} mode='aspectFit' />
<View className='invite-panel'>
<Text className='invite-title'>家庭共享邀请</Text>
{loading ? (
+1
View File
@@ -377,6 +377,7 @@ export default function Location() {
return (
<View className='location-page'>
<View className='bb-design-nav-title'><Text>微信登录</Text></View>
<View className='page-header'>
<Text className='page-title'>设备定位</Text>
</View>
+9 -5
View File
@@ -1,4 +1,4 @@
import { View, Text, Button, Checkbox, CheckboxGroup } from '@tarojs/components'
import { View, Text, Button, Checkbox, CheckboxGroup, Image } from '@tarojs/components'
import { useEffect, useState } from 'react'
import Taro from '@tarojs/taro'
import { getToken, wechatLogin } from '@/services/auth'
@@ -134,7 +134,11 @@ export default function Login() {
<View className='login-page'>
<View className='login-header'>
<View className='logo'>
<Text className='logo-icon'>🤖</Text>
<Image
className='login-hero-art'
src={require('../../assets/ui/login-hero.png')}
mode='aspectFit'
/>
</View>
<Text className='title'>伴伴</Text>
<Text className='subtitle'>让关爱随时随地</Text>
@@ -143,15 +147,15 @@ export default function Login() {
<View className='login-content'>
<View className='features'>
<View className='feature-item'>
<Text className='feature-icon'>💬</Text>
<Image className='feature-icon-image' src={require('../../assets/tab-icons/chat-icon.png')} mode='aspectFit' />
<Text className='feature-text'>AI 智能对话</Text>
</View>
<View className='feature-item'>
<Text className='feature-icon'>📍</Text>
<Image className='feature-icon-image' src={require('../../assets/tab-icons/location-icon.png')} mode='aspectFit' />
<Text className='feature-text'>实时定位追踪</Text>
</View>
<View className='feature-item'>
<Text className='feature-icon'>🔋</Text>
<Image className='feature-icon-image' src={require('../../assets/tab-icons/device-icon.png')} mode='aspectFit' />
<Text className='feature-text'>设备状态监控</Text>
</View>
</View>
+3 -1
View File
@@ -1,4 +1,4 @@
import { View, Text } from '@tarojs/components'
import { View, Text, Image } from '@tarojs/components'
import { useEffect, useState } from 'react'
import Taro, { useRouter } from '@tarojs/taro'
import { getToken } from '@/services/auth'
@@ -50,6 +50,8 @@ export default function NotificationEntry() {
return (
<View className='notification-page'>
<View className='bb-design-nav-title'><Text>微信登录</Text></View>
<Image className='notification-mascot' src={require('../../assets/ui/dog-question.png')} mode='aspectFit' />
<View className='notification-panel'>
<Text className='notification-title'>伴伴</Text>
<Text className='notification-message'>{message}</Text>
@@ -108,6 +108,7 @@ export default function SleepSchedule() {
if (isLoading) {
return (
<View className='sleep-page'>
<View className='bb-design-nav-title'><Text>微信登录</Text></View>
<View className='loading'>
<Text>加载中...</Text>
</View>
@@ -119,6 +120,7 @@ export default function SleepSchedule() {
if (!child) {
return (
<View className='sleep-page'>
<View className='bb-design-nav-title'><Text>微信登录</Text></View>
<View className='page-header'>
<Text className='page-title'>定时休眠</Text>
<Text className='page-subtitle'>先绑定设备并选择宝贝,再为对应设备设置休眠时间</Text>
@@ -135,6 +137,7 @@ export default function SleepSchedule() {
if (!binding) {
return (
<View className='sleep-page'>
<View className='bb-design-nav-title'><Text>微信登录</Text></View>
<View className='page-header'>
<Text className='page-title'>定时休眠</Text>
<Text className='page-subtitle'>{child.child_name} 还没有绑定设备</Text>
@@ -157,6 +160,7 @@ export default function SleepSchedule() {
return (
<View className='sleep-page'>
<View className='bb-design-nav-title'><Text>微信登录</Text></View>
<View className='page-header'>
<Text className='page-title'>定时休眠</Text>
<Text className='page-subtitle'>每天在设定时段内,设备将进入不可启动状态</Text>
@@ -169,6 +173,7 @@ export default function SleepSchedule() {
<Text className='hero-detail'>{childName} 的当前休眠时段:{currentRange}</Text>
</View>
<View className='hero-icon-wrap'>
<Image className='sleep-hero-mascot' src={require('../../assets/ui/dog-sleep.png')} mode='aspectFit' />
<Image className='hero-icon' src={require('../../assets/tab-icons/moon.png')} mode='aspectFit' />
</View>
</View>
+4
View File
@@ -962,6 +962,7 @@ export default function Sleep() {
if (loading) {
return (
<View className='manage-page'>
<View className='bb-design-nav-title'><Text>微信登录</Text></View>
<View className='loading'>
<Text>加载中...</Text>
</View>
@@ -973,6 +974,7 @@ export default function Sleep() {
if (isGuest) {
return (
<View className='manage-page'>
<View className='bb-design-nav-title'><Text>微信登录</Text></View>
<View className='page-header'>
<Text className='page-title'>设置与管理</Text>
</View>
@@ -1019,6 +1021,7 @@ export default function Sleep() {
<Text className='guest-manage-btn-text'>去登录 / 绑定设备</Text>
</View>
</View>
<Image className='manage-footer-art' src={require('../../assets/ui/paw-dog-footer.png')} mode='aspectFit' />
{systemBanner}
</View>
)
@@ -1158,6 +1161,7 @@ export default function Sleep() {
return (
<View className='manage-page'>
<View className='bb-design-nav-title'><Text>微信登录</Text></View>
<View className='page-header'>
<Text className='page-title'>设置与管理</Text>
</View>
+789
View File
@@ -0,0 +1,789 @@
@font-face {
font-family: 'MuyaoSoftbrush';
src: url('../assets/fonts/Muyao-Softbrush.ttf') format('truetype');
font-weight: 400;
font-style: normal;
}
/* Shared visual language from the supplied companion UI artwork. */
page {
--bb-cream: #fff9ea;
--bb-paper: #fffdf7;
--bb-brown: #70451f;
--bb-muted: #a98258;
--bb-border: #edc994;
--bb-orange: #ffad62;
--bb-orange-deep: #e8873c;
--bb-lime: #c4e52d;
--bb-lime-deep: #93b516;
--bb-danger: #ff6d61;
background-color: var(--bb-cream);
color: var(--bb-brown);
font-family: 'MuyaoSoftbrush', -apple-system, BlinkMacSystemFont, 'PingFang SC', 'Microsoft YaHei', sans-serif;
}
button,
input,
textarea {
font-family: 'MuyaoSoftbrush', -apple-system, BlinkMacSystemFont, 'PingFang SC', 'Microsoft YaHei', sans-serif;
}
.login-page,
.bind-page,
.device-page,
.chat-page,
.chat-detail-page,
.location-page,
.manage-page,
.sleep-page,
.family-invite-page,
.notification-page,
.webview-empty {
background-color: var(--bb-cream) !important;
background-image:
radial-gradient(circle at 16px 18px, rgba(241, 191, 116, 0.17) 0 3px, transparent 3.5px),
radial-gradient(circle at 27px 13px, rgba(241, 191, 116, 0.12) 0 2px, transparent 2.5px),
radial-gradient(circle at 7px 13px, rgba(241, 191, 116, 0.12) 0 2px, transparent 2.5px),
radial-gradient(circle at 16px 5px, rgba(241, 191, 116, 0.12) 0 2px, transparent 2.5px);
background-size: 48px 48px;
}
.page-header,
.bind-header,
.login-header {
position: relative;
z-index: 1;
}
.page-header {
padding-top: 46px !important;
padding-bottom: 22px !important;
text-align: center;
}
.page-title,
.bind-header .title,
.login-header .title {
color: var(--bb-brown) !important;
font-family: 'MuyaoSoftbrush', -apple-system, BlinkMacSystemFont, 'PingFang SC', sans-serif;
letter-spacing: 0 !important;
}
.page-title {
display: inline-block !important;
padding: 9px 26px !important;
border: 2px solid var(--bb-border);
border-radius: 48% 52% 45% 55%;
background: rgba(255, 253, 247, 0.94);
box-shadow: 0 4px 0 rgba(237, 201, 148, 0.35);
font-size: 38px !important;
}
.bind-header {
padding-top: 46px !important;
}
.bind-header .title {
font-size: 38px !important;
padding: 10px 64px !important;
border: 2px solid var(--bb-border);
border-radius: 46% 54% 52% 48%;
background: rgba(255, 253, 247, 0.95);
}
.bind-header .back-btn,
.chat-header .back-btn {
background: var(--bb-paper) !important;
border: 2px solid var(--bb-border);
box-shadow: none !important;
}
.back-text,
.bind-header .back-text {
color: var(--bb-brown) !important;
}
.card,
.login-info-card,
.control-card,
.status-card,
.fold-card,
.alarm-card,
.empty-card,
.guest-card,
.guest-demo-card,
.guest-guide-card,
.location-card,
.location-empty-card,
.guest-location-card,
.guest-manage-card,
.guest-manage-list,
.user-card,
.summary-card,
.settings-card,
.tips-card,
.hero-card,
.invite-panel,
.notification-panel,
.modal-card,
.bound-cards-card,
.system-update-card,
.menu-card {
background: rgba(255, 253, 247, 0.96) !important;
border: 2px solid rgba(237, 201, 148, 0.72);
border-radius: 18px !important;
box-shadow: 0 5px 0 rgba(237, 201, 148, 0.22) !important;
}
.login-info-card,
.guest-card,
.guest-demo-card,
.guest-guide-card,
.guest-manage-card {
border-radius: 22px !important;
}
.title,
.subtitle,
.login-info-title,
.guest-card-title,
.guest-demo-title,
.guest-guide-title,
.guest-manage-title,
.empty-title,
.empty-chat-text,
.location-empty-title,
.invite-title,
.notification-title,
.modal-title,
.control-name,
.section-title,
.fold-title,
.alarm-title,
.system-update-title,
.menu-name,
.character-name {
color: var(--bb-brown) !important;
}
.subtitle,
.login-info-desc,
.guest-card-desc,
.guest-demo-message,
.guest-guide-desc,
.guest-manage-desc,
.empty-subtitle,
.empty-desc,
.location-empty-desc,
.invite-desc,
.notification-message,
.control-detail,
.control-link,
.setting-hint,
.tips-text,
.character-desc,
.conversation-meta,
.conversation-time {
color: var(--bb-muted) !important;
}
.login-btn,
.submit-btn,
.guest-card-btn.secondary,
.guest-manage-btn.secondary,
.location-empty-action,
.invite-action,
.primary-btn,
.save-btn,
.family-primary-action,
.system-update-action,
.quick-sleep-btn,
.guest-primary-btn {
background: var(--bb-orange) !important;
color: var(--bb-brown) !important;
border: 2px solid rgba(213, 131, 56, 0.45) !important;
box-shadow: 0 4px 0 rgba(213, 131, 56, 0.2);
}
.empty-btn,
.phone-auth-btn {
background: #ffad62 !important;
color: #70451f !important;
border: 2px solid rgba(213, 131, 56, 0.45) !important;
box-shadow: 0 4px 0 rgba(213, 131, 56, 0.2);
}
.empty-btn-text,
.phone-auth-btn {
color: #70451f !important;
}
.logout-btn {
background: #fffdf7 !important;
border: 2px solid rgba(237, 201, 148, 0.9) !important;
box-shadow: 0 4px 0 rgba(237, 201, 148, 0.24);
}
.logout-text {
color: #e8873c !important;
}
.login-btn .btn-text,
.submit-btn,
.guest-card-btn.secondary .guest-card-btn-text,
.guest-manage-btn.secondary .guest-manage-btn-text,
.location-empty-action-text,
.invite-action-text,
.primary-btn-text,
.save-btn-text,
.family-primary-action-text,
.system-update-action-text,
.quick-sleep-btn-text,
.guest-primary-btn-text {
color: var(--bb-brown) !important;
}
.guest-card-btn:not(.secondary),
.guest-manage-btn:not(.secondary),
.guest-chat-shell .guest-card-btn,
.composer-record,
.mode-chip.active {
background: var(--bb-lime) !important;
border-color: rgba(112, 137, 18, 0.4) !important;
box-shadow: 0 4px 0 rgba(147, 181, 22, 0.22);
}
.guest-card-btn:not(.secondary) .guest-card-btn-text,
.guest-manage-btn:not(.secondary) .guest-manage-btn-text,
.composer-record-text,
.mode-chip.active .mode-chip-text {
color: var(--bb-brown) !important;
}
.login-btn-wrapper .guest-browse-text,
.agreement-link,
.control-detail,
.control-link,
.setting-value,
.invite-value,
.menu-value {
color: var(--bb-orange-deep) !important;
}
.status-badge,
.status-pill,
.verified-badge,
.conversation-tag,
.guest-demo-tag {
background: #f7e5b9 !important;
color: var(--bb-brown) !important;
border: 1px solid rgba(237, 201, 148, 0.85);
}
.volume-slider .wx-slider-handle,
.volume-slider .wx-slider-track,
.volume-slider .wx-slider-bar {
background: var(--bb-orange) !important;
}
.login-header {
padding-top: 56px !important;
padding-bottom: 34px !important;
}
.login-header .logo {
width: 178px !important;
height: 178px !important;
border-radius: 50% !important;
background: #ffd26b !important;
border: 4px solid #eaa34f;
box-shadow: 0 7px 0 rgba(234, 163, 79, 0.25) !important;
}
.login-header .logo-icon {
font-size: 78px !important;
}
.features {
margin-bottom: 42px !important;
}
.feature-item .feature-icon {
width: 72px;
height: 72px;
border-radius: 22px;
display: flex;
align-items: center;
justify-content: center;
background: #ffe7b5;
font-size: 38px !important;
}
.feature-item .feature-text {
color: var(--bb-brown) !important;
}
.feature-item .feature-icon-image {
width: 72px;
height: 72px;
padding: 16px;
box-sizing: border-box;
border-radius: 22px;
background: #ffe7b5;
}
.scan-frame,
.pending-device-card,
.form-card,
.bind-options .option-item,
.pending-tip {
background: rgba(255, 253, 247, 0.96) !important;
border: 2px solid rgba(237, 201, 148, 0.72);
box-shadow: 0 5px 0 rgba(237, 201, 148, 0.22) !important;
}
.scan-frame .scan-text,
.pending-device-id,
.field-label,
.option-text,
.pending-device-title,
.form-title {
color: var(--bb-brown) !important;
}
.scan-corners .corner {
border-color: var(--bb-orange) !important;
}
.field-input,
.modal-input {
background: #fff8e9 !important;
border: 2px solid rgba(237, 201, 148, 0.7) !important;
color: var(--bb-brown) !important;
}
.child-item {
background: #fff0ce !important;
border: 1px solid rgba(237, 201, 148, 0.76);
}
.child-item.selected {
background: var(--bb-lime) !important;
border-color: var(--bb-lime-deep) !important;
}
.child-item.selected .child-item-text {
color: var(--bb-brown) !important;
}
.message-bubble .user,
.message-bubble.user,
.user .message-bubble {
background: var(--bb-lime) !important;
color: var(--bb-brown) !important;
}
.message-bubble .peer,
.peer .message-bubble {
background: var(--bb-paper) !important;
color: var(--bb-brown) !important;
border: 1px solid rgba(237, 201, 148, 0.72);
}
.chat-header {
background: rgba(255, 253, 247, 0.96) !important;
border-bottom: 2px solid rgba(237, 201, 148, 0.72) !important;
}
.composer {
background: rgba(255, 253, 247, 0.97) !important;
border-top: 2px solid rgba(237, 201, 148, 0.72) !important;
}
.hero-card {
background: #f7bd64 !important;
}
.status-card {
background: #c7e52d !important;
border-color: #9fba1c !important;
}
.status-card .status-title,
.status-card .status-value,
.status-card .status-meta,
.status-card .battery-label,
.status-card .battery-percent {
color: var(--bb-brown) !important;
}
.alarm-card,
.alarm-history-item,
.detail-body,
.control-item,
.menu-item,
.family-member-item,
.device-switch-item,
.bound-card-item,
.setting-row,
.summary-row {
border-color: rgba(237, 201, 148, 0.6) !important;
}
.modal-mask {
background: rgba(87, 57, 28, 0.5) !important;
}
.modal-action.confirm {
background: var(--bb-orange) !important;
color: var(--bb-brown) !important;
}
.notification-panel {
border-radius: 22px !important;
}
.divider {
background: rgba(237, 201, 148, 0.6) !important;
}
@media (max-width: 360px) {
.page-title {
font-size: 34px !important;
padding-left: 20px !important;
padding-right: 20px !important;
}
.login-content {
padding-left: 28px !important;
padding-right: 28px !important;
}
}
/* Artwork placement follows the 750px reference boards while leaving all
existing controls in their original document flow. */
.login-header .logo {
position: relative;
width: 600px !important;
height: 360px !important;
margin-bottom: -12px !important;
overflow: hidden;
background: transparent !important;
border: 0 !important;
border-radius: 0 !important;
box-shadow: none !important;
}
.login-header .logo .login-hero-art {
position: absolute;
top: -255px;
left: 50%;
width: 510px;
height: 675px;
transform: translateX(-50%);
pointer-events: none;
}
.login-header .logo-icon {
display: none;
}
.device-page,
.bind-page,
.chat-page,
.chat-detail-page,
.location-page,
.sleep-page,
.manage-page,
.family-invite-page,
.notification-page {
position: relative;
}
.bb-design-nav-title {
position: fixed;
top: 88px;
left: 0;
z-index: 1000;
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 84px;
box-sizing: border-box;
border-bottom: 1px solid rgba(237, 237, 237, 0.95);
background: rgba(255, 255, 255, 0.96);
color: #222;
font-size: 26px;
line-height: 1;
text-align: center;
font-weight: 700;
pointer-events: none;
}
.bb-design-nav-title text {
display: block;
color: #222 !important;
font-size: 26px !important;
line-height: 1;
}
.device-page > .bound-device-header {
display: none !important;
}
.guest-footer-art,
.manage-footer-art {
position: fixed;
right: 8px;
bottom: 152px;
width: 340px;
height: 567px;
opacity: 0.98;
pointer-events: none;
z-index: 0;
}
.device-page > .guest-hero,
.device-page > .guest-feature-grid,
.device-page > .guest-action-card,
.device-page > .empty-card,
.device-page > .page-header,
.device-page > .child-focus-card,
.manage-page > .page-header,
.manage-page > .guest-manage-card,
.manage-page > .guest-manage-list {
position: relative;
z-index: 1;
}
.guest-device-icon {
background: transparent !important;
width: 460px !important;
height: 230px !important;
margin-bottom: 0 !important;
}
.guest-device-icon .guest-mascot {
width: 290px !important;
height: 210px !important;
}
.device-page > .guest-hero {
margin: 314px 42px 0;
padding: 124px 30px 118px;
background: rgba(255, 253, 247, 0.96) !important;
border: 3px solid rgba(214, 174, 125, 0.9);
border-radius: 42% 48% 44% 50% / 38% 40% 46% 44%;
box-shadow: 0 5px 0 rgba(237, 201, 148, 0.24) !important;
}
.device-page > .guest-hero .guest-device-icon {
display: none;
}
.device-page > .guest-hero .guest-title {
font-size: 38px !important;
line-height: 1.3;
}
.device-page > .guest-hero .guest-subtitle {
margin-top: 10px;
font-size: 24px !important;
line-height: 1.45;
}
.device-page > .guest-feature-grid {
display: none;
}
.device-page > .guest-action-card {
margin: 78px 48px 0;
padding: 0;
background: transparent !important;
border: 0;
box-shadow: none !important;
text-align: center;
}
.device-page > .guest-action-card .guest-action-title,
.device-page > .guest-action-card .guest-action-desc {
display: none;
}
.device-page > .guest-action-card .guest-primary-btn {
margin-top: 0;
height: 88px;
border-radius: 44px !important;
}
.device-page > .page-header:not(.bound-device-header) {
display: none !important;
}
.device-page > .empty-card {
margin: 70px 48px 0;
padding: 38px 30px 26px;
background: rgba(255, 253, 247, 0.96) !important;
border: 3px solid rgba(214, 174, 125, 0.9);
border-radius: 42% 48% 44% 50% / 38% 40% 46% 44% !important;
box-shadow: 0 5px 0 rgba(237, 201, 148, 0.24) !important;
}
.device-page > .empty-card .empty-robot {
display: none;
}
.device-page > .empty-card .empty-title {
font-size: 38px !important;
line-height: 1.35;
}
.device-page > .empty-card .empty-subtitle {
margin-top: 8px;
font-size: 24px !important;
line-height: 1.45;
}
.device-page > .empty-card .empty-btn {
height: 88px;
margin-top: 34px;
border-radius: 44px !important;
}
.device-page > .child-focus-card {
margin-top: 52px;
}
.empty-robot {
background: #ffe7b5 !important;
border: 2px solid rgba(237, 201, 148, 0.75);
}
.empty-robot .robot-img {
display: none;
}
.empty-robot .empty-mascot {
width: 96px;
height: 96px;
}
.status-card {
min-height: 310px;
padding: 34px 34px 26px !important;
border-radius: 34px !important;
background: #c7e52d !important;
}
.device-avatar {
top: 48%;
right: 14px;
width: 250px !important;
height: 210px !important;
border: 0 !important;
border-radius: 0 !important;
background: transparent !important;
}
.device-avatar .robot-icon {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
}
.device-avatar .device-mascot {
width: 190px;
height: 180px;
}
.status-meta {
max-width: 52%;
}
.bind-state-mascot {
display: block;
width: 180px;
height: 150px;
margin: 4px auto 8px;
pointer-events: none;
}
.bind-state-mascot.pending {
width: 210px;
height: 145px;
}
.bind-state-mascot.success,
.bind-state-mascot.failure {
width: 190px;
height: 170px;
}
.invite-mascot {
display: block;
width: 245px;
height: 175px;
margin: 18px auto 4px;
pointer-events: none;
}
.family-invite-page {
padding-top: 24px !important;
}
.notification-page {
flex-direction: column;
justify-content: center;
gap: 4px;
}
.notification-mascot {
width: 190px;
height: 190px;
margin-bottom: -14px;
pointer-events: none;
}
.notification-panel {
position: relative;
z-index: 1;
background: rgba(255, 253, 247, 0.96) !important;
}
.sleep-hero-mascot {
width: 112px;
height: 104px;
margin-right: -44px;
z-index: 1;
}
.hero-icon-wrap .hero-icon {
position: relative;
z-index: 2;
}
@media (max-width: 360px) {
.login-header .logo {
width: 520px !important;
height: 320px !important;
}
.login-header .logo .login-hero-art {
width: 455px;
height: 602px;
top: -230px;
}
.device-avatar {
right: -2px;
width: 210px !important;
}
.device-avatar .device-mascot {
width: 160px;
height: 155px;
}
}