/* New Year (config/themes/newyear.yml): midnight blue, champagne gold and firework neon from the day
   after Christmas until a week into the new year. Every rule keys on body[data-app-theme="newyear"] or
   on a ny- class only this theme's partials and scripts add, so the file does nothing on any other
   day. Most of the costume is the app's own tokens with new values; the rest styles
   app/views/themes/newyear. docs/THEMES.md. */

body[data-app-theme="newyear"] {
  --ny-midnight: #0b1030;
  --ny-midnight-2: #24195a;
  --ny-gold: #e6be5a;
  --ny-gold-deep: #b8862b;
  --ny-gold-hi: #fff1c1;
  --ny-magenta: #ff3d8b;
  --ny-cyan: #3fd7ff;
  --ny-lime: #8be15c;
  --ny-violet: #9b6bff;
  --ny-sugar: #d9d1c1;       /* powdered sugar: a warm grey that shows on a white card */
  --ny-oil: #e0a23a;
  --ny-bol: #a8662c;
  --ny-bol-deep: #6e3d14;

  --plane: #f3f2f9;
  --rail: var(--ny-midnight);
  --rail-ink: #f6f1ff;
  --rail-ink-2: #c6bde8;
  --rail-hover: rgba(255, 255, 255, 0.1);
  --rail-active: rgba(255, 255, 255, 0.16);

  --chart-annotation: rgba(70, 50, 160, 0.09);
  --chart-annotation-ink: #3b2a8a;
  --chart-endpoint: var(--ny-gold-deep);
}

@media (prefers-color-scheme: dark) {
  body[data-app-theme="newyear"] {
    --ny-midnight: #090c26;
    --ny-sugar: #f4efe4;
    --plane: #08091a;
    --rail-ink-2: #b3a9dc;
    --chart-annotation: rgba(255, 220, 140, 0.08);
    --chart-annotation-ink: var(--ny-gold);
    --chart-endpoint: var(--ny-gold);
  }
}

/* Fireworks behind the content (fireworks_controller.js): over the plane, under the rail, cards and
   panels. The finale brings them in front for a few seconds, still letting every click through. */
.ny-sky { position: fixed; inset: 0; width: 100%; height: 100%; z-index: -1; pointer-events: none; }
.ny-fireworks.is-finale .ny-sky { z-index: 60; }

/* The rail: a midnight sky with gold glitter drifting slowly up it, and a gold edge a glint runs down.
   On a phone the rail is a bar at the top, and the edge runs along its foot. */
@media (max-width: 900px) { body[data-app-theme="newyear"] .rail { position: relative; } } /* sticky, so positioned, on wider screens */
body[data-app-theme="newyear"] .rail {
  background:
    radial-gradient(circle at 12px 18px, rgba(255, 233, 168, 0.9) 0 1px, transparent 1.6px),
    radial-gradient(circle at 70px 52px, rgba(255, 255, 255, 0.75) 0 0.8px, transparent 1.4px),
    radial-gradient(circle at 44px 96px, rgba(255, 210, 120, 0.85) 0 1.2px, transparent 1.8px),
    radial-gradient(circle at 96px 130px, rgba(255, 255, 255, 0.6) 0 0.7px, transparent 1.3px),
    radial-gradient(circle at 26px 160px, rgba(255, 61, 139, 0.6) 0 0.9px, transparent 1.5px),
    radial-gradient(circle at 84px 8px, rgba(63, 215, 255, 0.55) 0 0.8px, transparent 1.4px),
    linear-gradient(180deg, var(--ny-midnight) 0%, var(--ny-midnight-2) 140%);
  background-size: 120px 180px, 120px 180px, 120px 180px, 120px 180px, 120px 180px, 120px 180px, 100% 100%;
  animation: ny-glitter 60s linear infinite;
}
body[data-app-theme="newyear"] .rail::before {
  content: ""; position: absolute; top: 0; bottom: 0; right: 0; width: 3px; pointer-events: none;
  background: linear-gradient(180deg, var(--ny-gold-deep), var(--ny-gold) 40%, var(--ny-gold-hi) 50%, var(--ny-gold) 60%, var(--ny-gold-deep)) 0 0 / 100% 300%;
  animation: ny-glint 6s ease-in-out infinite;
}
@media (max-width: 900px) {
  body[data-app-theme="newyear"] .rail::before {
    top: auto; left: 0; bottom: 0; width: auto; height: 3px;
    background: linear-gradient(90deg, var(--ny-gold-deep), var(--ny-gold) 40%, var(--ny-gold-hi) 50%, var(--ny-gold) 60%, var(--ny-gold-deep)) 0 0 / 300% 100%;
    animation-name: ny-glint-across;
  }
}
@keyframes ny-glitter {
  from { background-position: 0 0, 0 0, 0 0, 0 0, 0 0, 0 0, 0 0; }
  to { background-position: 0 -360px, 0 -540px, 0 -360px, 0 -720px, 0 -540px, 0 -360px, 0 0; }
}
@keyframes ny-glint { 0%, 100% { background-position: 0 0; } 50% { background-position: 0 100%; } }
@keyframes ny-glint-across { 0%, 100% { background-position: 0 0; } 50% { background-position: 100% 0; } }

/* Confetti lying along the top of every card and panel. Panels use their ::before only while being
   arranged (components.css), so those keep it. */
body[data-app-theme="newyear"] .card,
body[data-app-theme="newyear"] .panel { position: relative; }
body[data-app-theme="newyear"] .card::before,
body[data-app-theme="newyear"] .panel:not(.is-drop-before)::before {
  content: ""; position: absolute; top: -3px; left: 10px; right: 10px; height: 7px; pointer-events: none;
  background:
    radial-gradient(circle at 5px 3px, var(--ny-magenta) 0 2px, transparent 2.5px) 0 0 / 70px 7px repeat-x,
    linear-gradient(100deg, transparent 18px, var(--ny-gold) 18px 23px, transparent 23px) 0 2px / 70px 3px repeat-x,
    radial-gradient(circle at 33px 4px, var(--ny-cyan) 0 1.6px, transparent 2.1px) 0 0 / 70px 7px repeat-x,
    linear-gradient(80deg, transparent 47px, var(--ny-lime) 47px 51px, transparent 51px) 0 1px / 70px 4px repeat-x,
    radial-gradient(circle at 61px 3px, var(--ny-violet) 0 2px, transparent 2.5px) 0 0 / 70px 7px repeat-x;
  -webkit-mask: linear-gradient(90deg, transparent, #000 12%, #000 88%, transparent);
  mask: linear-gradient(90deg, transparent, #000 12%, #000 88%, transparent);
}

/* A sparkler (sterretje) in the corner of each dashboard card, burning down its stick over half a
   minute and lit again; its sparks fly further while the card is hovered. */
body[data-app-theme="newyear"] .card { padding-right: 64px; }
.ny-sparkler { position: absolute; top: 10px; right: 20px; width: 34px; height: 62px; pointer-events: none; transform: rotate(-16deg); transform-origin: 50% 100%; }
.ny-sparkler::before { content: ""; position: absolute; left: 16px; top: 6px; width: 2px; height: 56px; border-radius: 1px; background: linear-gradient(#5b5b66, #8d8d99 70%, #b59a6a 70%); }
.ny-sparkler-head {
  position: absolute; left: 17px; top: 8px; width: 0; height: 0;
  animation: ny-burn 30s linear infinite; animation-delay: calc(var(--d) * -1);
}
.ny-sparkler-head b {
  position: absolute; left: -4px; top: -4px; width: 8px; height: 8px; border-radius: 50%;
  background: radial-gradient(circle, #fff 0 30%, #ffe9a8 45%, rgba(255, 190, 80, 0) 72%);
  box-shadow: 0 0 10px 4px rgba(255, 200, 90, 0.55);
  animation: ny-flare 0.18s steps(2) infinite alternate;
}
.ny-sparkler-head i {
  position: absolute; left: -0.75px; top: 0; width: 1.5px; height: 9px; border-radius: 1px;
  background: linear-gradient(#fff, #ffd166 40%, rgba(255, 140, 40, 0));
  transform-origin: 50% 0; transform: rotate(var(--a)) translateY(2px);
  animation: ny-spark 0.55s linear infinite; animation-delay: var(--s);
}
.card:hover .ny-sparkler-head i { animation-duration: 0.32s; height: 15px; }
@keyframes ny-burn { from { transform: translateY(0); } to { transform: translateY(40px); } }
@keyframes ny-flare { from { transform: scale(0.85); } to { transform: scale(1.2); } }
@keyframes ny-spark {
  0% { transform: rotate(var(--a)) translateY(2px) scaleY(0.3); opacity: 1; }
  100% { transform: rotate(var(--a)) translateY(15px) scaleY(1.1); opacity: 0; }
}

/* The banner: midnight over the canal houses, fireworks going up over the roofs, and the countdown to
   the turn of the year; after midnight the new year's number, in gold. The words sit on the sky to
   the left of the houses. */
.ny-banner {
  position: relative; overflow: hidden; display: flex; align-items: center; gap: 12px 16px; flex-wrap: wrap;
  margin-bottom: 22px; padding: 18px 18px 22px; min-height: 132px; border-radius: var(--radius);
  background:
    radial-gradient(ellipse 60% 90% at 78% 115%, rgba(155, 107, 255, 0.45), transparent 70%),
    radial-gradient(ellipse 40% 60% at 15% -10%, rgba(255, 61, 139, 0.18), transparent 70%),
    linear-gradient(180deg, #050820, #15114a 65%, #2a1a5e);
  box-shadow: inset 0 0 0 1px rgba(230, 190, 90, 0.35);
  color: #f6f1ff;
}
.ny-scene { position: absolute; inset: 0; width: 100%; height: 100%; }
.ny-banner-words, .ny-banner .btn { position: relative; }
.ny-banner-words { flex: 1; min-width: 18ch; max-width: 50ch; display: flex; flex-direction: column; gap: 10px; }
.ny-banner-words p { margin: 0; text-shadow: 0 1px 3px rgba(0, 0, 0, 0.6); }
.ny-banner .btn { flex: none; align-self: flex-start; }
.ny-banner.is-new-year .ny-before, .ny-banner:not(.is-new-year) .ny-after { display: none; }
@media (max-width: 700px) { /* the scene drops to a strip under the words instead of behind them */
  .ny-banner { padding-bottom: 96px; }
  .ny-scene { top: auto; height: 90px; }
}

.ny-clock { display: flex; align-items: flex-start; gap: 6px; perspective: 300px; }
.ny-unit {
  display: inline-flex; flex-direction: column; align-items: center; gap: 3px; min-width: 54px; padding: 7px 8px 5px;
  border-radius: 8px; border: 1px solid rgba(230, 190, 90, 0.4);
  background: linear-gradient(180deg, #1d2050 0 50%, #13163c 50%);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.08), 0 3px 8px rgba(0, 0, 0, 0.45);
}
.ny-unit b {
  display: block; font: 700 1.65rem/1 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-variant-numeric: tabular-nums;
  color: #ffe08a; text-shadow: 0 0 10px rgba(255, 200, 80, 0.75);
}
.ny-unit small { font-size: 0.62rem; letter-spacing: 0.1em; text-transform: uppercase; color: #c6bde8; }
.ny-unit.is-tick b { animation: ny-flip 0.32s ease-out; }
.ny-colon { align-self: center; margin-top: -14px; font: 700 1.4rem/1 ui-monospace, Menlo, monospace; color: var(--ny-gold); animation: ny-blink 1s steps(2) infinite; }
@keyframes ny-flip { 0% { transform: rotateX(-55deg); opacity: 0.55; } 65% { transform: rotateX(8deg); opacity: 1; } 100% { transform: rotateX(0); } }
@keyframes ny-blink { 50% { opacity: 0.25; } }

.ny-year {
  font: 900 clamp(2.4rem, 6vw, 3.4rem)/1 system-ui, -apple-system, "Segoe UI", sans-serif; letter-spacing: -0.02em;
  background: linear-gradient(100deg, #b8862b 0%, #ffe9a8 22%, #d9a63c 40%, #fff6d6 55%, #c9952f 75%, #ffe9a8 100%) 0 0 / 220% 100%;
  -webkit-background-clip: text; background-clip: text; color: transparent;
  filter: drop-shadow(0 0 12px rgba(255, 200, 80, 0.45));
  animation: ny-shimmer 3.2s linear infinite;
}
@keyframes ny-shimmer { to { background-position: -220% 0; } }

/* The scene's own movement: stars twinkling, fireworks going up and bursting over the roofs in turn,
   windows flickering and the lights trembling in the canal. */
.ny-star { animation: ny-twinkle 2.6s ease-in-out infinite alternate; animation-delay: var(--d); }
.ny-rocket { animation: ny-rise var(--t) ease-out infinite; animation-delay: var(--d); opacity: 0; }
.ny-burst { transform-origin: 0 0; animation: ny-pop var(--t) ease-out infinite; animation-delay: var(--d); opacity: 0; }
.ny-window { animation: ny-lamp 4s ease-in-out infinite alternate; animation-delay: var(--d, 0s); }
.ny-ripple { animation: ny-ripple 3s ease-in-out infinite alternate; animation-delay: var(--d); }
@keyframes ny-twinkle { from { opacity: 0.2; } to { opacity: 1; } }
@keyframes ny-rise {
  0% { transform: translateY(var(--h)); opacity: 0; }
  5% { opacity: 1; }
  28% { transform: translateY(0); opacity: 1; }
  30%, 100% { transform: translateY(0); opacity: 0; }
}
@keyframes ny-pop {
  0%, 29% { transform: scale(0.05); opacity: 0; }
  31% { transform: scale(0.25); opacity: 1; }
  60% { transform: scale(1) translateY(2px); opacity: 0.95; }
  85% { transform: scale(1.08) translateY(7px); opacity: 0; }
  100% { transform: scale(1.08) translateY(7px); opacity: 0; }
}
@keyframes ny-lamp { 0% { fill: #ffd77a; } 50% { fill: #ffbe55; } 100% { fill: #ffe7a6; } }
@keyframes ny-ripple { from { transform: translateX(-3px); opacity: 0.35; } to { transform: translateX(3px); opacity: 0.9; } }

/* Oliebollen frying while figures are counted, powdered sugar coming down on them: on the warming page
   and in a computing panel (chart_controller.js sets is-computing; hidden the rest of the time). */
body[data-app-theme="newyear"] .empty:has(.ny-fryer) { position: relative; overflow: hidden; }
.empty:has(.ny-fryer) > :not(.ny-fryer) { position: relative; }
.panel-body > .ny-fryer { display: none; }
body[data-app-theme="newyear"] .panel-body.is-computing { overflow: hidden; }
.panel-body.is-computing > .ny-fryer { display: block; }
.ny-fryer { position: absolute; inset: 0; pointer-events: none; }
.ny-fryer > i {
  position: absolute; bottom: 30px; right: calc(22px + var(--x)); width: var(--s); height: var(--s); border-radius: 50%;
  background: var(--ny-sugar); opacity: 0.9;
  animation: ny-dust 3.6s linear infinite; animation-delay: var(--d);
}
.ny-pan { position: absolute; right: 12px; bottom: 6px; }
.ny-bol { transform-box: fill-box; transform-origin: 50% 60%; animation: ny-bob 2.2s ease-in-out infinite; animation-delay: var(--d); }
.ny-bubble { animation: ny-fizz 1.4s ease-in infinite; animation-delay: var(--d); opacity: 0; }
@keyframes ny-dust {
  0% { transform: translate(0, -200px); opacity: 0; }
  10% { opacity: 0.9; }
  60% { transform: translate(-8px, -80px); }
  100% { transform: translate(4px, 0); opacity: 0.2; }
}
@keyframes ny-bob {
  0%, 100% { transform: translateY(0) rotate(0); }
  30% { transform: translateY(-3px) rotate(-8deg); }
  55% { transform: translateY(1px) rotate(5deg); }
  80% { transform: translateY(-5px) rotate(180deg); }
}
@keyframes ny-fizz { 0% { transform: translateY(0) scale(0.6); opacity: 0; } 20% { opacity: 0.9; } 100% { transform: translateY(-9px) scale(1.2); opacity: 0; } }

/* The finale's countdown in the middle of the window, over everything, taking no clicks: ten (or, when
   asked for in a search box, five) seconds, then the wish (fireworks_controller.js). */
.ny-finale { position: fixed; inset: 0; z-index: 61; display: grid; place-items: center; pointer-events: none; }
.ny-finale[hidden] { display: none; }
.ny-finale-count, .ny-finale-wish {
  grid-area: 1 / 1; text-align: center;
  font: 900 clamp(5rem, 22vw, 16rem)/1 system-ui, -apple-system, "Segoe UI", sans-serif; letter-spacing: -0.04em;
  color: #fff; -webkit-text-stroke: 2px rgba(255, 233, 168, 0.9);
  text-shadow: 0 0 30px rgba(255, 61, 139, 0.75), 0 0 60px rgba(63, 215, 255, 0.55), 0 6px 0 rgba(11, 16, 48, 0.55);
}
.ny-finale-count.is-tick { animation: ny-slam 0.95s cubic-bezier(.15, .85, .3, 1) both; }
/* The wish sits under the year the fireworks write (at a third of the window's height). */
.ny-finale-wish { align-self: end; margin-bottom: 22vh; padding: 0 16px; font-size: clamp(2.2rem, 7vw, 5rem); }
.ny-finale-wish.is-shown { animation: ny-arrive 4.6s cubic-bezier(.2, .9, .3, 1) both; }
@keyframes ny-slam {
  0% { transform: scale(2.6); opacity: 0; filter: blur(8px); }
  30% { transform: scale(0.94); opacity: 1; filter: blur(0); }
  45% { transform: scale(1.04); }
  75% { transform: scale(1); opacity: 1; }
  100% { transform: scale(0.7); opacity: 0; }
}
@keyframes ny-arrive {
  0% { transform: scale(0.3) rotate(-6deg); opacity: 0; }
  14% { transform: scale(1.08) rotate(1deg); opacity: 1; }
  22% { transform: scale(1) rotate(0); }
  85% { transform: scale(1); opacity: 1; }
  100% { transform: scale(1.1); opacity: 0; }
}

/* The bottle of bubbly peeking up from the bottom corner; it comes up on hover or focus, and a click
   pops its cork, sprays foam and says something (bottle_controller.js). Not on a phone, where the
   corner is precious. */
.ny-bottle { position: fixed; right: max(18px, env(safe-area-inset-right, 0px)); bottom: 0; z-index: 40; pointer-events: none; display: flex; flex-direction: column; align-items: flex-end; }
.ny-bottle-button {
  pointer-events: auto; position: relative; padding: 0; border: 0; background: none; cursor: pointer; line-height: 0;
  transform: translateY(52%) rotate(8deg); transform-origin: 50% 100%; transition: transform 0.35s cubic-bezier(.3, 1.5, .5, 1);
}
.ny-bottle-button:hover, .ny-bottle-button:focus-visible, .ny-bottle.is-popping .ny-bottle-button { transform: translateY(8%) rotate(-14deg); }
.ny-bottle.is-shaking .ny-bottle-figure { animation: ny-shake 0.09s linear 5 alternate; }
.ny-bottle-figure { width: 54px; height: auto; filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.25)); }
.ny-bottle.is-uncorked .ny-cork { visibility: hidden; }
@keyframes ny-shake { from { transform: translateX(-2px) rotate(-3deg); } to { transform: translateX(2px) rotate(3deg); } }
.ny-flying-cork { position: fixed; width: 12px; height: 14px; margin: -7px 0 0 -6px; border-radius: 3px 3px 5px 5px; background: linear-gradient(90deg, #b07a43, #e3b47a 45%, #9a6332); z-index: 62; pointer-events: none; }
.ny-foam { position: fixed; width: var(--s); height: var(--s); margin: calc(var(--s) / -2) 0 0 calc(var(--s) / -2); border-radius: 50%; background: radial-gradient(circle at 35% 35%, #fff, #fff7d6 60%, rgba(255, 240, 190, 0.6)); z-index: 62; pointer-events: none; }
.ny-bottle-says {
  pointer-events: auto; position: relative; max-width: 24ch; margin: 0 6px 8px 0; padding: 8px 12px; border-radius: 12px;
  background: var(--surface); color: var(--ink); border: 1px solid var(--line); box-shadow: 0 6px 18px rgba(0, 0, 0, 0.15); font-size: 0.95rem;
}
.ny-bottle-says::after { content: ""; position: absolute; right: 22px; bottom: -7px; width: 12px; height: 12px; background: var(--surface); border-right: 1px solid var(--line); border-bottom: 1px solid var(--line); transform: rotate(45deg); }
@media (max-width: 700px) { .ny-bottle { display: none; } }
