/* Blob gradient colors — used by inline styles in application layout */
:root {
  --blob-1: rgba(37, 99, 235, 0.08);
  --blob-2: rgba(59, 130, 246, 0.06);
  --blob-3: rgba(37, 99, 235, 0.04);
}

[data-theme=dark] {
  --blob-1: rgba(20, 50, 175, 0.22);
  --blob-2: rgba(10, 28, 110, 0.2);
  --blob-3: rgba(30, 64, 175, 0.1);
}

/* ========================
   Animations
   (@keyframes cannot be expressed via @apply)
======================== */
@keyframes fadeInUp {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: translateY(0); }
}

@keyframes slideDown {
  from { opacity: 0; transform: translateY(-8px); }
  to   { opacity: 1; transform: translateY(0); }
}

@keyframes menuEnter {
  from { opacity: 0; transform: scale(0.96) translateY(-4px); }
  to   { opacity: 1; transform: scale(1) translateY(0); }
}

@keyframes pulseDot {
  0%, 100% { opacity: 1; transform: scale(1); }
  50%       { opacity: 0.35; transform: scale(0.65); }
}

.animate-menu-enter { animation: menuEnter 0.18s cubic-bezier(0.16, 1, 0.3, 1) both; }

.animate-in   { animation: fadeInUp 350ms cubic-bezier(0.16, 1, 0.3, 1) both; }
.animate-in-1 { animation: fadeInUp 350ms cubic-bezier(0.16, 1, 0.3, 1) 0.05s both; }
.animate-in-2 { animation: fadeInUp 350ms cubic-bezier(0.16, 1, 0.3, 1) 0.10s both; }
.animate-in-3 { animation: fadeInUp 350ms cubic-bezier(0.16, 1, 0.3, 1) 0.15s both; }
.animate-in-4 { animation: fadeInUp 350ms cubic-bezier(0.16, 1, 0.3, 1) 0.20s both; }

.stagger > *:nth-child(1) { animation: fadeInUp 350ms cubic-bezier(0.16, 1, 0.3, 1) 0.00s both; }
.stagger > *:nth-child(2) { animation: fadeInUp 350ms cubic-bezier(0.16, 1, 0.3, 1) 0.05s both; }
.stagger > *:nth-child(3) { animation: fadeInUp 350ms cubic-bezier(0.16, 1, 0.3, 1) 0.10s both; }
.stagger > *:nth-child(4) { animation: fadeInUp 350ms cubic-bezier(0.16, 1, 0.3, 1) 0.15s both; }
.stagger > *:nth-child(5) { animation: fadeInUp 350ms cubic-bezier(0.16, 1, 0.3, 1) 0.20s both; }
.stagger > *:nth-child(6) { animation: fadeInUp 350ms cubic-bezier(0.16, 1, 0.3, 1) 0.25s both; }
.stagger > *:nth-child(7) { animation: fadeInUp 350ms cubic-bezier(0.16, 1, 0.3, 1) 0.30s both; }
.stagger > *:nth-child(8) { animation: fadeInUp 350ms cubic-bezier(0.16, 1, 0.3, 1) 0.35s both; }

/* ========================
   Processing pulse (import batch status indicator)
======================== */
.badge-processing::before {
  content: '';
  display: inline-block;
  width: 0.42rem; height: 0.42rem;
  border-radius: 50%;
  background: currentColor;
  animation: pulseDot 1.4s ease-in-out infinite;
}

.processing-pulse {
  animation: pulseDot 2.2s ease-in-out infinite;
}

/* ========================
   Scrollbar
======================== */
::-webkit-scrollbar { width: 5px; height: 5px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: rgb(148 163 184 / 0.3); border-radius: 3px; }
::-webkit-scrollbar-thumb:hover { background: rgb(148 163 184 / 0.5); }

/* ========================
   Bulk select
======================== */
[data-bulk-col] { display: table-cell; }

/* ========================
   Brand Logo Animations
======================== */
@keyframes logoIn {
  from {
    opacity: 0;
    transform: scale(0.5) rotate(-25deg);
  }
  to {
    opacity: 1;
    transform: scale(1) rotate(0deg);
  }
}

.animate-logo-in {
  animation: logoIn 450ms cubic-bezier(0.16, 1, 0.3, 1) both;
}

.navbar-loader-container {
  transition: opacity 0.2s ease;
}

#right-half {
  transition: transform 450ms cubic-bezier(0.16, 1, 0.3, 1);
  transform-origin: 16px 16px;
}

.navbar-loading #right-half {
  transition: transform 100ms linear !important;
}

.turbo-progress-bar {
  display: none !important;
}


/* ========================
   Moments (celebrations played once; see Moment)
======================== */
@keyframes momentIn {
  from { opacity: 0; transform: translateY(16px) scale(0.97); }
  to   { opacity: 1; transform: none; }
}

@keyframes momentOut {
  to { opacity: 0; transform: translateY(12px) scale(0.97); }
}

@keyframes drawStroke {
  from { stroke-dashoffset: 100; }
  to   { stroke-dashoffset: 0; }
}

@keyframes ringPop {
  50% { transform: scale(1.1); }
}

.moment         { animation: momentIn 450ms cubic-bezier(0.16, 1, 0.3, 1) both; }
.moment-leaving { animation: momentOut 250ms ease-in both; }
.moment-ring    { transform-origin: center; animation: ringPop 380ms ease-out 1150ms; }
.moment-ring-fill { stroke-dasharray: 100; animation: drawStroke 900ms cubic-bezier(0.65, 0, 0.35, 1) 250ms both; }
.moment-check     { stroke-dasharray: 100; animation: drawStroke 320ms ease-out 1100ms both; }

@media (prefers-reduced-motion: reduce) {
  .moment, .moment-ring, .moment-ring-fill, .moment-check { animation: none; }
}

@keyframes popIn {
  0%   { transform: scale(0); }
  70%  { transform: scale(1.12); }
  100% { transform: scale(1); }
}

.moment-pop { transform-origin: center; transform-box: fill-box; animation: popIn 420ms cubic-bezier(0.34, 1.56, 0.64, 1) 200ms both; }

@media (prefers-reduced-motion: reduce) {
  .moment-pop { animation: none; }
}

/* A streak's months lighting up one by one (moments/_streak sets each delay) */
@keyframes squareIn {
  from { opacity: 0.15; transform: scale(0.5); }
  60%  { opacity: 1; transform: scale(1.2); }
  to   { opacity: 1; transform: none; }
}

.moment-square { animation: squareIn 320ms ease-out both; }

@media (prefers-reduced-motion: reduce) {
  .moment-square { animation: none; }
}

/* The review's "Needs a look" badge turning into a check (_review_header) */
@keyframes clearedPop {
  0%   { transform: scale(0.4); opacity: 0; }
  60%  { transform: scale(1.25); opacity: 1; box-shadow: 0 0 0 6px rgb(16 185 129 / 0.25); }
  100% { transform: scale(1); box-shadow: 0 0 0 0 rgb(16 185 129 / 0); }
}

.review-cleared { animation: clearedPop 520ms cubic-bezier(0.34, 1.56, 0.64, 1) both; }

@media (prefers-reduced-motion: reduce) {
  .review-cleared { animation: none; }
}

/* A category well above its usual on Home (CategorySpikes): a red glow,
   and one shake the first time it's shown (play-once) */
.cat-spike {
  border-color: rgb(239 68 68 / 0.45);
  box-shadow: 0 0 0 3px rgb(239 68 68 / 0.08), 0 8px 24px -12px rgb(239 68 68 / 0.45);
}

[data-theme="dark"] .cat-spike {
  border-color: rgb(248 113 113 / 0.4);
  box-shadow: 0 0 0 3px rgb(248 113 113 / 0.08), 0 8px 28px -12px rgb(248 113 113 / 0.5);
}

@keyframes spikeShake {
  0%, 100% { transform: none; }
  20% { transform: translateX(-5px); }
  40% { transform: translateX(4px); }
  60% { transform: translateX(-3px); }
  80% { transform: translateX(2px); }
}

.cat-spike-shake { animation: spikeShake 450ms ease-in-out 700ms; }

@media (prefers-reduced-motion: reduce) {
  .cat-spike-shake { animation: none; }
}

/* A budget line over its budget (budgets/_line): the fill runs up to where the
   budget was, spills past the end and settles red, once (play-once) */
@keyframes budgetSpill {
  0%   { transform: scaleX(var(--budget-ratio, 0.8)); }
  55%  { transform: scaleX(1.015); }
  75%  { transform: scaleX(0.99); }
  100% { transform: none; }
}

@keyframes budgetGlow {
  0%, 40% { box-shadow: 0 0 0 0 rgb(239 68 68 / 0); }
  60%     { box-shadow: 0 0 0 4px rgb(239 68 68 / 0.25); }
  100%    { box-shadow: 0 0 0 0 rgb(239 68 68 / 0); }
}

.budget-overflow { animation: budgetGlow 1100ms ease-out 500ms; }
.budget-overflow .budget-fill { transform-origin: left; animation: budgetSpill 900ms ease-out 400ms both; }

@media (prefers-reduced-motion: reduce) {
  .budget-overflow, .budget-overflow .budget-fill { animation: none; }
}

/* A record (PersonalBests) on Home: a green tint, and a light sweeping across
   it once (play-once). The element is relative with overflow hidden. */
.cat-record {
  position: relative;
  border-color: rgb(16 185 129 / 0.4);
}

[data-theme="dark"] .cat-record { border-color: rgb(52 211 153 / 0.35); }

@keyframes recordShimmer {
  from { transform: translateX(-100%); }
  to   { transform: translateX(100%); }
}

.record-shimmer::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(105deg, transparent 35%, rgb(16 185 129 / 0.16) 50%, transparent 65%);
  animation: recordShimmer 1100ms ease-in-out 600ms both;
}

@media (prefers-reduced-motion: reduce) {
  .record-shimmer::after { display: none; }
}
