/*
 * 高濃度活性氧 explained in seven beats (js/oxy-scene.js sets data-beat on .ox-scene; a tapped caption
 * jumps there). Reusable: colours come from the host page's tokens with the cleaning site's as
 * fallbacks; the drop's own motion (.ip-anim) comes from the host stylesheet (clean.css here).
 */
.ox { --ox-ink: var(--ink, #0f2a2e); --ox-muted: var(--muted, #4f6a6e); --ox-line: var(--line, #c6e0d7); --ox-surface: var(--surface, #f2faf7); --ox-accent: var(--accent, #0e9f97);
  --ox-deep: var(--accent-deep, #0b7f79); --ox-soft: var(--accent-soft, #cfeee6); --ox-outline: #16393f; --ox-ease: cubic-bezier(0.2, 0.7, 0.2, 1); }

.ox-scene { position: relative; aspect-ratio: 4 / 3; border-radius: 22px; overflow: hidden; border: 2px solid var(--ox-outline);
  background: linear-gradient(180deg, #d9f3f0, #b9e6e1); transition: background 0.8s; }
.ox-scene[data-beat="0"] { background: linear-gradient(180deg, #e3dccd, #cbbd9f); }
.ox-scene.idle *, .ox-scene.idle *::before { animation-play-state: paused !important; }
/* played once to the clean ending: everything comes to rest there (only the hero loops) */
.ox-scene.done *, .ox-scene.done *::before { animation: none !important; }
.ox-scene > * { position: absolute; transition: transform 0.9s var(--ox-ease), opacity 0.6s, left 0.9s var(--ox-ease), top 0.9s var(--ox-ease); }
.ox-scene svg { display: block; overflow: visible; }
.ox-o svg, .ox-s svg, .ox-g svg { width: 100%; height: auto; }

/* 60°C warm water */
.ox-warm { inset: 0; opacity: 0; background: radial-gradient(80% 60% at 50% 100%, rgba(255, 190, 120, 0.35), transparent 70%); }
.ox-temp { top: 12px; right: 12px; padding: 4px 10px; border-radius: 99px; background: #fff3e2; border: 2px solid var(--ox-outline); font: 800 13px/1.2 var(--mono, monospace); color: #b35a12; opacity: 0; transform: translateY(-8px); }
.ox-scene:is([data-beat="1"], [data-beat="2"], [data-beat="3"]) :is(.ox-warm, .ox-temp) { opacity: 1; transform: none; }

/* the back of the drum, with its holes */
.ox-wall { left: -2%; right: -2%; bottom: 0; height: 22%; }
.ox-wall svg { width: 100%; height: 100%; }
.ow-steel { fill: #9fb6b8; stroke: var(--ox-outline); stroke-width: 2.5; vector-effect: non-scaling-stroke; }
.ow-holes circle { fill: #5f7577; }

/* 黑泥: stuck (0), dissolving (2), lifted and floating (3), flushed by the spray (4), the stubborn one
   broken by the aimed jet (5). Flushed grime goes the way the water goes: down and to the left. */
.ox-g { bottom: 17%; width: 15%; z-index: 2; }
.ox-g.g1 { left: 34%; } .ox-g.g2 { left: 56%; width: 13%; } .ox-g.g3 { left: 76%; width: 14%; }
.ox-scene[data-beat="2"] .ox-g { transform: translateY(-6%) scale(0.84); filter: saturate(0.7) brightness(1.12); }
.ox-scene:is([data-beat="3"], [data-beat="4"], [data-beat="5"]) .ox-g { transform: translateY(-150%) scale(0.76) rotate(-6deg); filter: saturate(0.7) brightness(1.12); }
.ox-scene[data-beat="4"] :is(.g1, .g2) { transform: translate(-150%, 110%) rotate(-70deg) scale(0.35); opacity: 0; transition-duration: 0.8s; }
.ox-scene[data-beat="4"] .g2 { transition-delay: 0.6s; }
.ox-scene[data-beat="4"] .g1 { transition-delay: 1.3s; }
.ox-scene[data-beat="5"] :is(.g1, .g2) { opacity: 0; transition: none; }
.ox-scene[data-beat="4"] .g3 .oxa-body { animation: ox-shake 0.25s linear infinite; }
/* The stubborn one stays stuck low on the drum (Eddie 05:16Z: dirt sits mostly at 4 to 8 o'clock, soaked
   for years; the top is rarely dirty), so the foam cannot lift it and the jet has to come to it. */
.ox-scene:is([data-beat="3"], [data-beat="4"]) .g3 { transform: translateY(-4%) scale(0.96); filter: none; }
.ox-scene[data-beat="5"] .g3 { transform: translateY(-4%) scale(1.4); opacity: 0; filter: none; transition-delay: 2.2s; transition-duration: 0.4s; }
.ox-scene[data-beat="5"] .g3 .oxa-body { animation: ox-shake 0.12s linear infinite; }
.ox-scene[data-beat="6"] .ox-g { opacity: 0; transform: translateY(-150%) scale(0.3); }
@keyframes ox-shake { 0%, 100% { transform: translateX(0); } 25% { transform: translateX(-3px); } 75% { transform: translateX(3px); } }
.ox-g .oxa-body { transform-box: fill-box; transform-origin: center; animation: ox-grump 2.2s ease-in-out infinite; }
@keyframes ox-grump { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.04, 0.97); } }

/* 氧仔 drop in (1), push into the grime (2), cheer from the top (3–4), step aside for the jet (5), go
   back to water and oxygen (6). 梳打仔 helps in (2). */
.ox-o { width: 15%; top: -30%; opacity: 0; }
.ox-o.o1 { left: 30%; } .ox-o.o2 { left: 52%; } .ox-o.o3 { left: 73%; }
.ox-scene[data-beat="1"] .ox-o { top: 14%; opacity: 1; }
.ox-scene[data-beat="2"] .ox-o { top: 40%; opacity: 1; transform: translateX(-38%); }
.ox-scene[data-beat="3"] .ox-o { top: 6%; opacity: 1; transform: translateX(-50%) scale(0.9); }
.ox-scene[data-beat="4"] .ox-o { top: 6%; opacity: 1; transform: translateX(-90%) scale(0.8); }
.ox-scene[data-beat="5"] .ox-o { top: 4%; opacity: 0; transform: translateX(-120%) scale(0.6); }
.ox-scene[data-beat="6"] .ox-o { top: -10%; opacity: 0; transform: scale(0.3); }
.ox-o .oxa-body { animation: ox-bob 1.8s ease-in-out infinite; }
.ox-o.o2 .oxa-body { animation-delay: 0.3s; } .ox-o.o3 .oxa-body { animation-delay: 0.6s; }
.ox-o .oxa-eyes { transform-box: fill-box; transform-origin: center; animation: ox-blink 3.6s infinite; }
.ox-scene[data-beat="2"] .ox-o .oxa-body { animation: ox-push 0.7s ease-in-out infinite; }
@keyframes ox-bob { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-6px); } }
@keyframes ox-blink { 0%, 90%, 100% { transform: scaleY(1); } 94% { transform: scaleY(0.12); } }
@keyframes ox-push { 0%, 100% { transform: translate(0, 0); } 50% { transform: translate(4px, 3px); } }
.ox-s { width: 9%; left: 48%; bottom: 20%; opacity: 0; transform: scale(0.4); }
.ox-scene[data-beat="2"] .ox-s { opacity: 1; transform: none; }

/* 發泡促進劑: the foam rises under the grime (3), thins as the jet starts (4) */
.ox-foam { left: 28%; right: 4%; bottom: 14%; height: 34%; opacity: 0; transform: scale(0.85); transform-origin: 50% 100%; }
.ox-foam i { position: absolute; border-radius: 50%; aspect-ratio: 1; background: radial-gradient(circle at 35% 30%, #fff, #e6f7f6 60%, #c9ebe7); border: 2px solid rgba(22, 57, 63, 0.45); }
.ox-foam i:nth-child(1) { left: 0; bottom: 0; width: 22%; } .ox-foam i:nth-child(2) { left: 14%; bottom: 28%; width: 18%; }
.ox-foam i:nth-child(3) { left: 26%; bottom: 2%; width: 24%; } .ox-foam i:nth-child(4) { left: 42%; bottom: 34%; width: 16%; }
.ox-foam i:nth-child(5) { left: 50%; bottom: 0; width: 22%; } .ox-foam i:nth-child(6) { left: 64%; bottom: 30%; width: 18%; }
.ox-foam i:nth-child(7) { left: 74%; bottom: 2%; width: 24%; } .ox-foam i:nth-child(8) { left: 34%; bottom: 52%; width: 12%; }
.ox-foam i:nth-child(9) { left: 86%; bottom: 40%; width: 12%; }
.ox-scene[data-beat="3"] .ox-foam { opacity: 1; transform: none; }
.ox-scene[data-beat="4"] .ox-foam { opacity: 0.45; transform: translateX(-20%) scale(0.6); }

/* oxygen bubbles fizzing up (1–2) */
.ox-bub { left: 28%; right: 4%; bottom: 20%; height: 70%; opacity: 0; }
.ox-bub i { position: absolute; bottom: 0; width: 10px; height: 10px; border-radius: 50%; border: 2px solid rgba(22, 57, 63, 0.5); background: rgba(255, 255, 255, 0.7); animation: ox-fizz 2.4s ease-in infinite; }
.ox-bub i:nth-child(1) { left: 6%; } .ox-bub i:nth-child(2) { left: 18%; animation-delay: 0.5s; width: 7px; height: 7px; } .ox-bub i:nth-child(3) { left: 33%; animation-delay: 1.1s; }
.ox-bub i:nth-child(4) { left: 47%; animation-delay: 0.3s; width: 14px; height: 14px; } .ox-bub i:nth-child(5) { left: 62%; animation-delay: 1.6s; } .ox-bub i:nth-child(6) { left: 78%; animation-delay: 0.8s; width: 8px; height: 8px; }
.ox-bub i:nth-child(7) { left: 90%; animation-delay: 1.9s; }
@keyframes ox-fizz { 0% { transform: translateY(0); opacity: 0; } 15% { opacity: 1; } 100% { transform: translateY(-2400%); opacity: 0; } }
.ox-scene:is([data-beat="1"], [data-beat="2"]) .ox-bub { opacity: 1; }

/* The pressure washer. The wand is drawn pointing right from its grip (0,0) in a 400×300 scene; the
   whole group turns and moves, so the water always leaves the nozzle along the wand.
   4: from the top right it sweeps back and forth, a wide spray that scatters and flushes the grime.
   5: it swings over and comes in close, nozzle pointed straight at the stubborn grime, and a narrow
      hard jet hits it until it breaks. */
.ox-jet { inset: 0; width: 100%; height: 100%; z-index: 3; pointer-events: none; }
.oj-wand { transform-box: view-box; transform-origin: 0 0; transform: translate(520px, -140px) rotate(135deg); opacity: 0;
  transition: transform 1s var(--ox-ease), opacity 0.4s; }
.ox-scene[data-beat="4"] .oj-wand { opacity: 1; transform: translate(420px, -20px) rotate(122deg); animation: oj-sweep 2.2s ease-in-out 0.6s infinite; }
.ox-scene[data-beat="5"] .oj-wand { opacity: 1; transform: translate(179px, 98px) rotate(40deg); animation: oj-kick 0.16s linear 0.9s infinite; }
@keyframes oj-sweep { 0%, 100% { transform: translate(420px, -20px) rotate(122deg); } 50% { transform: translate(420px, -20px) rotate(150deg); } }
/* the recoil of a hard jet: the wand trembles along its own line */
@keyframes oj-kick { 0%, 100% { transform: translate(179px, 98px) rotate(40deg); } 50% { transform: translate(177px, 96.3px) rotate(40.6deg); } }
.oj-fan path { fill: none; stroke: #7fd8e6; stroke-width: 10; stroke-linecap: round; stroke-dasharray: 16 18; opacity: 0; }
.oj-fan path.w { stroke: #fff; stroke-width: 6; }
.ox-scene[data-beat="4"] .oj-fan path { opacity: 0.9; animation: oj-flow 0.45s linear infinite; transition: opacity 0.3s 0.5s; }
.oj-beam { fill: none; stroke: #fff; stroke-width: 15; stroke-linecap: round; stroke-dasharray: 12 7; opacity: 0; filter: drop-shadow(0 0 5px #7fd8e6); }
.ox-scene[data-beat="5"] .oj-beam { opacity: 1; animation: oj-flow 0.22s linear infinite; transition: opacity 0.2s 0.9s; }
@keyframes oj-flow { to { stroke-dashoffset: -34; } }
.oj-hit circle { fill: none; stroke: #fff; stroke-width: 4; opacity: 0; transform-box: fill-box; transform-origin: center; }
.ox-scene[data-beat="5"] .oj-hit circle { animation: oj-ring 0.5s ease-out 1s infinite; }
.ox-scene[data-beat="5"] .oj-hit circle + circle { animation-delay: 1.25s; }
@keyframes oj-ring { 0% { transform: scale(0.4); opacity: 1; } 100% { transform: scale(2.6); opacity: 0; } }
/* water and grime running off at the bottom while the spray works */
.oj-drip circle { fill: #bff1ff; stroke: var(--ox-outline); stroke-width: 2; opacity: 0; transform-box: fill-box; transform-origin: center; }
.ox-scene[data-beat="4"] .oj-drip circle { animation: oj-splash 0.9s ease-out infinite; }
.ox-scene[data-beat="4"] .oj-drip circle:nth-child(2n) { animation-delay: 0.35s; }
@keyframes oj-splash { 0% { transform: translateY(0) scale(0.6); opacity: 0; } 30% { opacity: 1; } 100% { transform: translateY(-24px) scale(1); opacity: 0; } }

/* the stubborn grime breaks into bits */
.ox-burst { left: 76%; width: 14%; bottom: 15%; height: 18%; z-index: 2; }
.ox-burst i { position: absolute; left: 45%; top: 45%; width: 12px; height: 9px; border-radius: 50%; background: #6b4724; border: 2px solid var(--ox-outline); opacity: 0; }
.ox-scene[data-beat="5"] .ox-burst i { animation: ox-burst 1.1s ease-out 2.3s 2; }
.ox-burst i:nth-child(1) { --dx: 40px; --dy: -50px; } .ox-burst i:nth-child(2) { --dx: 60px; --dy: -10px; } .ox-burst i:nth-child(3) { --dx: 30px; --dy: -60px; }
.ox-burst i:nth-child(4) { --dx: -20px; --dy: -70px; } .ox-burst i:nth-child(5) { --dx: 70px; --dy: -20px; } .ox-burst i:nth-child(6) { --dx: 10px; --dy: -80px; }
.ox-burst i:nth-child(7) { --dx: 55px; --dy: -45px; animation-delay: 2.5s; } .ox-burst i:nth-child(8) { --dx: -10px; --dy: -50px; animation-delay: 2.6s; }
@keyframes ox-burst { 0% { transform: translate(0, 0) scale(1.2); opacity: 1; } 100% { transform: translate(var(--dx), var(--dy)) scale(0.4); opacity: 0; } }

/* three rinses, and the oxygen back to water and oxygen (6) */
.ox-x3 { top: 12px; right: 12px; padding: 4px 12px; border-radius: 99px; background: #dff7fb; border: 2px solid var(--ox-outline); font: 800 14px/1.3 var(--sans, sans-serif); color: var(--ox-deep); opacity: 0; transform: translateY(-8px); }
.ox-scene[data-beat="6"] .ox-x3 { opacity: 1; transform: none; }
.ox-end { left: 30%; right: 6%; top: 18%; display: flex; justify-content: space-around; opacity: 0; transform: translateY(30%); }
.ox-end span { display: grid; place-items: center; width: 54px; height: 54px; flex: none; border-radius: 50%; background: radial-gradient(circle at 35% 30%, #fff, #c9f1f8); border: 2px solid var(--ox-outline); font: 800 14px/1 var(--mono, monospace); color: var(--ox-outline); }
.ox-end span:nth-child(2) { margin-top: 30px; }
.ox-scene[data-beat="6"] .ox-end { opacity: 1; transform: none; }
.ox-scene[data-beat="6"] .ox-end span { animation: ox-rise 2.4s ease-in-out infinite; }
.ox-scene[data-beat="6"] .ox-end span:nth-child(2) { animation-delay: 0.4s; }
@keyframes ox-rise { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-10px); } }

/* the drop at the bottom left clears beat by beat */
.ox-drop { left: 3%; bottom: 16%; width: 24%; z-index: 1; }
.ox-drop .d { display: none; } .ox-drop .d.on { display: block; }

/* 「由頭再睇」: shown once the beats have played to the end, over the scene's bottom right corner */
.ox-stage { position: relative; }
.ox-again { position: absolute; right: 12px; bottom: 12px; z-index: 2; display: flex; align-items: center; padding: 8px 14px; min-height: 40px;
  border: 2px solid var(--ox-outline); border-radius: 99px; background: #fff; color: var(--ox-outline); font: 800 15px/1.2 var(--sans, sans-serif); cursor: pointer; }
.ox-again:hover { background: var(--ox-soft); }
.ox-again[hidden] { display: none; }

/* the captions: one per beat, tap to jump */
.ox-say { list-style: none; margin: 14px 0 0; padding: 0; display: grid; gap: 6px; }
.ox-say button { width: 100%; display: flex; align-items: flex-start; gap: 10px; padding: 10px 12px; border: 1px solid transparent; border-radius: 14px; background: none; text-align: left; color: var(--ox-muted); font-size: 16px; line-height: 1.5; cursor: pointer; transition: background 0.3s, color 0.3s, border-color 0.3s; }
.ox-say button:hover { color: var(--ox-ink); }
.ox-say i { flex: none; width: 10px; height: 10px; margin-top: 7px; border-radius: 50%; background: var(--ox-line); transition: background 0.3s; }
.ox-say .on button { background: var(--ox-surface); border-color: var(--ox-line); color: var(--ox-ink); font-weight: 800; }
.ox-say .on i { background: var(--ox-accent); box-shadow: 0 0 0 4px var(--ox-soft); }
.ox-facts { list-style: none; margin: 16px 0 0; padding: 0; display: grid; gap: 8px; }
.ox-facts li { padding: 12px 14px; border-radius: 14px; background: var(--ox-soft); }
.ox-facts b { display: block; font-size: 17px; font-weight: 900; color: var(--ox-deep); }
.ox-facts span { font-size: 14.5px; color: var(--ox-muted); }

@media (min-width: 900px) {
  .ox { display: grid; grid-template-columns: 1.2fr 0.8fr; column-gap: 40px; align-items: start; }
  .ox-scene { grid-column: 1; grid-row: 1 / 5; }
  .ox-stage { grid-column: 1; grid-row: 1 / 5; }
  .ox > .cta-note { grid-column: 2; grid-row: 1; }
  .ox-say { grid-column: 2; grid-row: 2; margin-top: 6px; }
  .ox-facts { grid-column: 2; grid-row: 3; }
}
