/* DripDash motion (motion.js does the moving parts). One feel everywhere: things settle with a little spring,
   presses ripple like water, and highlights slide rather than jump. */
:root { --spring: cubic-bezier(.34, 1.56, .64, 1); --out: cubic-bezier(.16, 1, .3, 1); }

/* --- presses: a ripple from the finger, and a small squeeze ---------------------------------------- */
.rippling { overflow: hidden; isolation: isolate; }
.ripple { position: absolute; border-radius: 50%; pointer-events: none; z-index: -1;
  background: radial-gradient(circle, rgb(var(--primary2-rgb) / 0.45) 0%, rgb(var(--primary2-rgb) / 0.18) 40%, transparent 70%);
  transform: scale(0); animation: ripple-out 0.7s var(--out) forwards; }
.btn.primary .ripple, .level.on .ripple { background: radial-gradient(circle, rgb(255 255 255 / 0.55) 0%, rgb(255 255 255 / 0.15) 45%, transparent 70%); }
@keyframes ripple-out { to { transform: scale(1); opacity: 0; } }

.btn, .icon-btn, .tbl-btn, .cause, .pick, .style-pick, .tech .acts button {
  transition: transform 0.18s var(--spring), box-shadow 0.25s var(--out), border-color 0.2s, background-color 0.2s, color 0.2s; }
.btn:hover:not(:disabled), .icon-btn:hover, .pick:hover { transform: translateY(-1px); }
.btn:active:not(:disabled), .icon-btn:active, .cause:active, .pick:active, .tbl-btn:active { transform: scale(0.96); transition-duration: 0.08s; }
.btn.primary:hover:not(:disabled) { box-shadow: 0 10px 30px rgb(var(--primary-rgb) / 0.42); }
/* a sheen across the main buttons on hover */
.btn.primary { position: relative; overflow: hidden; }
.btn.primary::after { content: ""; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(105deg, transparent 35%, rgb(255 255 255 / 0.35) 50%, transparent 65%); transform: translateX(-120%); }
.btn.primary:hover:not(:disabled)::after { transform: translateX(120%); transition: transform 0.75s var(--out); }

/* --- sliding highlights in every set of options ----------------------------------------------------- */
.has-glider { position: relative; }
.has-glider > :not(.glider) { position: relative; z-index: 1; }
.glider { position: absolute; left: 0; top: 0; z-index: 0; pointer-events: none; border-radius: 8px;
  background: rgb(var(--primary-rgb) / 0.18); box-shadow: inset 0 0 0 1px rgb(var(--primary-rgb) / 0.42); } /* moved by anime.js springs (motion.js) */
.has-glider > .on, .has-glider > [aria-checked="true"], .has-glider > [aria-current="page"] { background: transparent !important; box-shadow: none !important; }
.tabs.has-glider > .on { border-color: transparent !important; }
.tabs > .glider { border-radius: 2px; background: var(--primary); box-shadow: 0 0 10px rgb(var(--primary-rgb) / 0.6); }
.seg3 > .glider { background: var(--surface-solid); box-shadow: 0 2px 8px rgb(var(--shade) / 0.3); border-radius: 9px; }
.seg button, .seg3 button, .filter button, .nav a, .tabs button, #period button { transition: color 0.25s; }

/* --- switches: the knob springs across ------------------------------------------------------------ */
.switch i, .switch i::after { transition: transform 0.38s var(--spring), background-color 0.25s, width 0.2s; }
.switch:active i::after { width: 22px; }

/* --- severity tiles fill with rising water when chosen -------------------------------------------------- */
.level { position: relative; overflow: hidden; isolation: isolate; transition: transform 0.25s var(--spring), border-color 0.25s, box-shadow 0.25s; }
.level::before { content: ""; position: absolute; left: -10%; right: -10%; bottom: 0; height: 0; z-index: -1;
  background: linear-gradient(to top, color-mix(in srgb, var(--c) 36%, transparent), color-mix(in srgb, var(--c) 12%, transparent));
  transition: height 0.6s var(--out); }
.level::after { content: ""; position: absolute; left: -50%; width: 200%; bottom: 0; height: 12px; z-index: -1; opacity: 0;
  background: radial-gradient(ellipse 18px 9px at 50% 100%, color-mix(in srgb, var(--c) 12%, transparent) 98%, transparent) 0 0 / 36px 12px repeat-x;
  transition: bottom 0.6s var(--out), opacity 0.3s; }
.level.on { transform: scale(1.02); background: transparent; box-shadow: 0 0 0 1px var(--c) inset, 0 8px 24px color-mix(in srgb, var(--c) 25%, transparent); }
.level.on::before { height: 100%; }
.level.on::after { bottom: 100%; opacity: 1; animation: wavelet 2.4s linear infinite; }
@keyframes wavelet { to { transform: translateX(36px); } }
.level.on .drops svg { animation: bob 1.6s ease-in-out infinite; }
.level.on .drops svg:nth-child(2) { animation-delay: 0.15s; } .level.on .drops svg:nth-child(3) { animation-delay: 0.3s; } .level.on .drops svg:nth-child(4) { animation-delay: 0.45s; }
@keyframes bob { 50% { transform: translateY(-3px); } }

/* --- chips and choices pop when picked ----------------------------------------------------------- */
.cause.on, .style-pick.on { animation: pop-in 0.42s var(--spring); }
@keyframes pop-in { 0% { transform: scale(0.9); } 60% { transform: scale(1.06); } 100% { transform: none; } }

/* --- dialogs and panels arrive -------------------------------------------------------------------- */
dialog[open] { animation: dialog-in 0.42s var(--spring); }
dialog[open]::backdrop { animation: fade-in 0.3s var(--out); }
@keyframes dialog-in { from { opacity: 0; transform: translateY(14px) scale(0.96); } }
@keyframes fade-in { from { opacity: 0; } }
/* the detail panel grows from its row and shrinks back into it: anime.js (control.js) */
@keyframes photo-in { from { opacity: 0; transform: scale(1.06); filter: blur(6px); } }
@keyframes rise-in { from { opacity: 0; transform: translateY(8px); } }
.menu.open .menu-list { animation: menu-in 0.32s var(--spring); transform-origin: top right; }
@keyframes menu-in { from { opacity: 0; transform: translateY(-6px) scale(0.96); } }
.drawer:not([hidden]) { animation: drawer-in 0.42s var(--spring); }
@keyframes drawer-in { from { opacity: 0; transform: translateX(30px); } }
.toast:not([hidden]) { animation: toast-in 0.45s var(--spring); }
@keyframes toast-in { from { opacity: 0; transform: translate(-50%, 16px) scale(0.95); } }

/* --- the control room: rows, pins, badges ------------------------------------------------------------ */
.leak, .tech { transition: background-color 0.25s, transform 0.25s var(--spring), box-shadow 0.25s; }
.leak:hover { transform: translateX(3px); }
.leak.on { box-shadow: inset 3px 0 0 var(--c), 0 0 0 1px color-mix(in srgb, var(--c) 40%, transparent); }
.leak.fresh { animation: fresh 2.2s var(--out); }
@keyframes fresh { 0% { background: color-mix(in srgb, var(--c) 38%, transparent); box-shadow: 0 0 0 2px var(--c); } }
.leak-pin svg { transition: transform 0.3s var(--spring); transform-origin: 50% 100%; }
.leaflet-marker-icon:hover .leak-pin svg { transform: translateY(-3px) scale(1.12); }
.leak-pin.on::before { content: ""; position: absolute; left: 50%; bottom: -4px; width: 46px; height: 16px; margin-left: -23px; border-radius: 50%;
  border: 2px solid var(--c); animation: puddle 1.6s var(--out) infinite; }
.leaflet-marker-icon:hover .tech-pin { transform: scale(1.12); }
.stat .v { display: inline-block; }
.stat.flash .v { animation: number-pop 0.6s var(--spring); }
@keyframes number-pop { 40% { transform: scale(1.25); } }
.splash.in3d .label { top: 26px; }
.splash3d { position: fixed; inset: 0; pointer-events: none; z-index: 850; }
/* a critical leak: the edges of the screen pulse red twice */
.alarm { position: fixed; inset: 0; pointer-events: none; z-index: 2500;
  box-shadow: inset 0 0 0 0 var(--sev-critical), inset 0 0 120px 10px color-mix(in srgb, var(--sev-critical) 55%, transparent);
  animation: alarm 0.9s ease-in-out 2 forwards; opacity: 0; }
@keyframes alarm { 30% { opacity: 1; } 100% { opacity: 0; } }

/* --- the crew app: a job that changes state glows -------------------------------------------------- */
.job { transition: box-shadow 0.4s var(--out); }
.job.changed { animation: job-changed 1.4s var(--out); }
@keyframes job-changed { 0% { box-shadow: 0 0 0 3px var(--c), 0 0 40px color-mix(in srgb, var(--c) 50%, transparent); } }
.shot-slot.has img { animation: photo-in 0.6s var(--out); }
.finish:not(:disabled) { animation: ready 0.5s var(--spring); }
@keyframes ready { 50% { transform: scale(1.03); } }

/* --- the phone apps: a wave of water washes from one step to the next (motion.js) ------------------------------ */
.flood { position: fixed; left: 0; right: 0; top: 0; height: 100%; z-index: 3000; pointer-events: none; transform: translateY(105%);
  background: linear-gradient(180deg, rgb(var(--primary2-rgb)) 0%, rgb(var(--primary-rgb)) 55%, color-mix(in srgb, rgb(var(--primary-rgb)) 70%, #001a33) 100%); }
.flood .crest { position: absolute; left: 0; bottom: 100%; width: 200%; height: 46px; margin-bottom: -1px; fill: rgb(var(--primary2-rgb)); }
.flood .crest.back { height: 62px; opacity: 0.45; }
.flood .crest.tail { bottom: auto; top: 100%; margin: -1px 0 0; height: 40px; fill: color-mix(in srgb, rgb(var(--primary-rgb)) 70%, #001a33); }
.flood .bubble { position: absolute; width: calc(14px * var(--s)); height: calc(14px * var(--s)); border-radius: 50%;
  border: 2px solid rgb(255 255 255 / 0.55); background: rgb(255 255 255 / 0.12); }
.snap:active { transform: scale(0.94); transition: transform 0.1s; }
.snap { transition: transform 0.4s var(--spring); }
.steps li { animation: rise-in 0.5s var(--out) backwards; }
.steps li:nth-child(2) { animation-delay: 0.06s; } .steps li:nth-child(3) { animation-delay: 0.12s; }
.steps li:nth-child(4) { animation-delay: 0.18s; } .steps li:nth-child(5) { animation-delay: 0.24s; }
.steps li.step-done i { animation: tick-fill 0.5s var(--spring) backwards; }
@keyframes tick-fill { from { transform: scale(0.4); } }

/* --- Insights: charts grow in ------------------------------------------------------------------------- */
.chart svg .grow { transform-box: fill-box; transform-origin: 50% 100%; } /* grown by anime.js as the chart comes into view (insights.js) */
.chart svg .grow.h { transform-origin: 0 50%; }

@media (prefers-reduced-motion: reduce) {
  .switch i, .switch i::after, .level::before, .level::after { transition: none !important; }
  .ripple, .level.on::after { display: none; }
}
