バッテリー残量警告(段階的に減る)Battery Low Alert
/* 3幕構成: 残量が1目盛りずつカクッと減る → 残りわずかで色が警告色へ変わり、
本体がばねで震える → 稲妻マークが点灯し、枠が赤く脈打ったまま静止する */
.cg-al-batt {
display: flex;
align-items: center;
gap: 12px;
width: 320px;
padding: 12px 14px;
border: 2px solid #D9D4C8;
border-radius: 10px;
background: #FFFDF7;
font: 400 13px/1.5 "M PLUS 1", system-ui, sans-serif;
color: #1B1A17;
animation: cg-al-batt-frame 6s ease-in-out infinite;
}
.cg-al-batt-icon {
position: relative;
flex: none;
width: 38px;
height: 20px;
border: 2px solid #4A453E;
border-radius: 4px;
animation: cg-al-batt-shake 6s linear infinite;
}
/* 端子 */
.cg-al-batt-icon::after {
content: "";
position: absolute;
right: -6px;
top: 50%;
width: 4px;
height: 8px;
margin-top: -4px;
border-radius: 0 2px 2px 0;
background: #4A453E;
}
.cg-al-batt-fill {
position: absolute;
left: 2px;
top: 2px;
bottom: 2px;
width: 30px;
border-radius: 2px;
background: #4E9A51;
animation: cg-al-batt-drain 6s steps(1, end) infinite;
}
/* 稲妻(自作クリップパス。絵文字は使わない) */
.cg-al-batt-bolt {
position: absolute;
left: 50%;
top: 50%;
width: 9px;
height: 15px;
margin: -7.5px 0 0 -4.5px;
background: #FFFDF7;
clip-path: polygon(60% 0, 4% 58%, 42% 58%, 30% 100%, 96% 38%, 52% 38%);
opacity: 0;
animation: cg-al-batt-bolt 6s linear infinite;
}
.cg-al-batt-body {
display: flex;
flex-direction: column;
}
.cg-al-batt-body strong {
font-size: 13px;
font-weight: 700;
animation: cg-al-batt-alertify 6s linear infinite;
}
.cg-al-batt-body em {
font-style: normal;
font-size: 11px;
color: #6E6960;
}
@keyframes cg-al-batt-drain {
0%, 22% { width: 30px; background: #4E9A51; }
30%, 46% { width: 20px; background: #C8912A; }
54%, 70% { width: 10px; background: #E8590C; }
74%, 100% { width: 5px; background: #C0392B; }
}
@keyframes cg-al-batt-shake {
0%, 52% { transform: translateX(0) scale(1); animation-timing-function: cubic-bezier(.34, 1.56, .64, 1); }
56% { transform: translateX(-2px) scale(1.08, .92); }
60% { transform: translateX(2px) scale(.96, 1.06); }
64%, 72% { transform: translateX(0) scale(1); animation-timing-function: cubic-bezier(.34, 1.56, .64, 1); }
76% { transform: translateX(-3px) scale(1.1, .9); }
80% { transform: translateX(3px) scale(.95, 1.07); }
84% { transform: translateX(-1px) scale(1); }
88%, 100% { transform: translateX(0) scale(1); }
}
@keyframes cg-al-batt-bolt {
0%, 72% { opacity: 0; transform: scale(.6); animation-timing-function: cubic-bezier(.34, 1.56, .64, 1); }
77% { opacity: 1; transform: scale(1.18); }
83% { opacity: .3; transform: scale(1); }
89% { opacity: 1; transform: scale(1.06); }
95% { opacity: .4; transform: scale(1); }
100% { opacity: 1; transform: scale(1); }
}
@keyframes cg-al-batt-frame {
0%, 50% { border-color: #D9D4C8; box-shadow: 0 0 0 0 rgba(192, 57, 43, 0); }
58% { border-color: #E8A87C; box-shadow: 0 0 0 3px rgba(232, 89, 12, .1); }
72% { border-color: #C0392B; box-shadow: 0 0 0 5px rgba(192, 57, 43, .16); }
84% { border-color: #C0392B; box-shadow: 0 0 0 9px rgba(192, 57, 43, 0); }
92%, 100% { border-color: #C0392B; box-shadow: 0 0 0 5px rgba(192, 57, 43, .16); }
}
@keyframes cg-al-batt-alertify {
0%, 50% { color: #1B1A17; }
60%, 100% { color: #A5281B; }
}
@media (prefers-reduced-motion: reduce) {
/* 静止形は「残量わずかの警告状態」。アラートとして読んだままの意味が通る */
.cg-al-batt,
.cg-al-batt-icon,
.cg-al-batt-fill,
.cg-al-batt-bolt,
.cg-al-batt-body strong { animation: none; }
.cg-al-batt { border-color: #C0392B; box-shadow: 0 0 0 5px rgba(192, 57, 43, .16); }
.cg-al-batt-fill { width: 5px; background: #C0392B; }
.cg-al-batt-bolt { opacity: 1; transform: scale(1); background: #4A453E; }
.cg-al-batt-body strong { color: #A5281B; }
}
<div class="cg-al-batt" role="alert">
<span class="cg-al-batt-icon" aria-hidden="true">
<i class="cg-al-batt-fill"></i>
<i class="cg-al-batt-bolt"></i>
</span>
<span class="cg-al-batt-body">
<strong>バッテリー残量が少なくなっています</strong>
<em>電源に接続してください</em>
</span>
</div>