.timer-page { display: flex; flex-direction: column; align-items: center; justify-content: space-between; padding-top: 80rpx; padding-bottom: calc(170rpx + env(safe-area-inset-bottom)); min-height: 100vh; box-sizing: border-box; } /* ---- ring wrapper ---- */ .ring-wrapper { position: relative; display: flex; align-items: center; justify-content: center; } /* breathing guide rings — three concentric layers */ .breathe-ring { position: absolute; border-radius: 50%; border: 3rpx solid rgba(var(--primary-rgb), 0.15); animation: breathePulse 3.5s ease-in-out infinite; pointer-events: none; z-index: 0; } .breathe-ring-1 { width: 480rpx; height: 480rpx; animation-delay: 0s; } .breathe-ring-2 { width: 400rpx; height: 400rpx; animation-delay: 0.5s; border-color: rgba(var(--primary-rgb), 0.25); border-width: 4rpx; } .breathe-ring-3 { width: 320rpx; height: 320rpx; animation-delay: 1s; border-color: rgba(var(--primary-rgb), 0.35); border-width: 5rpx; } .breathe-ring.fast { animation: breathePulseFast 1.4s ease-in-out infinite; } .breathe-ring.fast.breathe-ring-1 { animation-delay: 0s; border-color: rgba(var(--primary-rgb), 0.3); } .breathe-ring.fast.breathe-ring-2 { animation-delay: 0.25s; border-color: rgba(var(--primary-rgb), 0.45); } .breathe-ring.fast.breathe-ring-3 { animation-delay: 0.5s; border-color: rgba(var(--primary-rgb), 0.6); } /* celebration burst */ .celebrate-burst { position: absolute; width: 520rpx; height: 520rpx; pointer-events: none; z-index: 2; } .spark { position: absolute; font-size: 36rpx; animation: sparkBurst 1s ease-out forwards; } .s1 { top: -10rpx; left: 50%; margin-left: -18rpx; animation-delay: 0s; } .s2 { top: 30rpx; right: -10rpx; animation-delay: 0.1s; } .s3 { bottom: -10rpx; right: 50rpx; animation-delay: 0.2s; } .s4 { bottom: 20rpx; left: 30rpx; animation-delay: 0.15s; } .s5 { top: 50%; right: -20rpx; animation-delay: 0.25s; } .s6 { top: -20rpx; left: 40rpx; animation-delay: 0.05s; } @keyframes sparkBurst { 0% { opacity: 0; transform: translate(0, 0) scale(0.3); } 40% { opacity: 1; transform: translate(0, -30rpx) scale(1.3); } 100% { opacity: 0; transform: translate(0, -80rpx) scale(0.4); } } /* overtime badge */ .overtime-badge { position: absolute; bottom: 10rpx; left: 50%; transform: translateX(-50%); background: rgba(76, 175, 80, 0.12); border: 2rpx solid rgba(76, 175, 80, 0.3); color: var(--success); padding: 8rpx 24rpx; border-radius: 24rpx; font-size: 28rpx; font-weight: 600; display: flex; align-items: center; gap: 6rpx; animation: popIn 0.4s cubic-bezier(0.34, 1.56, 0.64, 1); } .overtime-icon { width: 28rpx; height: 28rpx; } /* ---- hint section ---- */ .hint-section { margin-top: 36rpx; text-align: center; } .hint-row { display: inline-flex; align-items: center; justify-content: center; gap: 10rpx; } .hint-icon { width: 32rpx; height: 32rpx; } .running-pulse { animation: float 1.5s ease-in-out infinite; } .completed-bounce { animation: bounceSoft 0.6s ease infinite; } .hint-text { font-size: 28rpx; color: var(--text-secondary); line-height: 1.3; } .hint-text.running { color: var(--primary); font-weight: 600; } .hint-text.paused { color: var(--primary-light); } .hint-text.completed { color: var(--success); font-weight: 600; } .completed-hint { animation: popIn 0.5s ease; } /* ---- controls ---- */ .controls { margin-top: 60rpx; width: 100%; display: flex; justify-content: center; } .ctrl-row { display: flex; justify-content: center; align-items: center; }