/* ═══ PUMP MODE ═══
   Everything here is inert until <html> carries .pump-on. Nothing in this file
   touches the ordinary page, so the site is exactly as it was until the switch
   is thrown — and goes back to exactly as it was when it is thrown again.

   The rule throughout: colour and light do the shouting, layout does not move.
   A page that reflows while somebody is reading a number is a broken page, not
   an exciting one — so every effect here is paint, never geometry. */

/* ── the switch ──
   It should not announce itself. A button reading PUMP MODE tells everybody
   what it does and nobody wonders — so this says nothing at all: three bars in
   a circle, the shape of a level meter, which reads as sound or energy without
   naming either. Dim, hairline, easy to miss and then hard to un-notice, since
   every so often the bars stir on their own. That flicker is the whole pitch.

   Found, it warms under the cursor. Thrown, the bars dance on the beat and the
   ring catches. The word only ever appears in the label a screen reader hears,
   where being cryptic would be rudeness rather than intrigue. */
/* ── the dock ──
   Not in the header. That rail already overflows its own width by three
   hundred pixels on a laptop, so anything added to the end of it lands past
   the edge of the screen — which is where this button was, unseen, being
   judged. The two controls that are about the site rather than about the
   numbers sit level with the tip bar, in its empty corners below the chart
   card, so neither covers a card edge nor costs the chart any height. */
.site-dock {
  position: fixed; left: 12px; bottom: 6px; z-index: 2147483003;
  display: flex; flex-direction: column-reverse; gap: 10px;
}
/* the X link takes the other corner, so the two controls bracket the page
   rather than stacking in one heap */
.dock-x {
  position: fixed; right: 12px; bottom: 6px; z-index: 2147483003;
}
.dock-btn, .pump-toggle {
  display: grid; place-items: center;
  width: 44px; height: 44px; padding: 0;
  border: 1px solid rgba(255, 255, 255, .16); border-radius: 50%;
  background: rgba(20, 0, 8, .5);
  backdrop-filter: blur(10px) saturate(1.2);
  -webkit-backdrop-filter: blur(10px) saturate(1.2);
  color: rgba(255, 255, 255, .62);
  cursor: pointer;
  transition: border-color .3s ease, background .3s ease, box-shadow .3s ease,
              transform .25s cubic-bezier(.2, 1.3, .4, 1), color .3s ease;
}
.dock-btn svg { width: 17px; height: 17px; display: block; }
.dock-btn:hover, .pump-toggle:hover { transform: scale(1.08); }
.dock-btn:hover { color: #fff; border-color: rgba(255, 255, 255, .5); background: rgba(0, 0, 0, .62); }
.dock-btn:focus-visible { outline: 2px solid rgba(255, 255, 255, .8); outline-offset: 2px; }
@media (max-width: 800px), (orientation: landscape) and (max-height: 500px) and (max-width: 950px) {
  /* Wherever the app zeroes its bottom strip (phones, and landscape phones up
     to 950px), the dock goes back to floating in the corners. Launched from the home screen
     there is no browser chrome, and the foot of the screen belongs to the
     home indicator — a control sitting twelve pixels up is under the thumb
     rest. The inset is zero in a browser tab and about thirty-four points on
     a phone that has one, so the same rule serves both. */
  .site-dock { left: 12px; bottom: calc(12px + env(safe-area-inset-bottom)); gap: 8px; }
  .dock-x { right: 12px; bottom: calc(12px + env(safe-area-inset-bottom)); }
  .dock-btn, .pump-toggle { width: 40px; height: 40px; }
  .dock-btn svg { width: 15px; height: 15px; }
  .pump-player { bottom: calc(62px + env(safe-area-inset-bottom)); }
}
.pump-toggle:hover { border-color: rgba(255, 190, 0, .55); background: rgba(255, 138, 0, .1); }
.pump-toggle:focus-visible { outline: 2px solid rgba(255, 190, 0, .8); outline-offset: 2px; }

/* The mark: a bolt inside a hexagon. The hexagon is the shape this whole site
   is built on, so the control belongs to it rather than being borrowed from a
   media player; the bolt is what the mode does. Asleep it is a hairline
   outline with the bolt barely there. Awake the bolt fills, and on the
   downbeat it flares. */
.pump-mark { display: block; width: 22px; height: 22px; overflow: visible; }
.pump-hex {
  fill: none;
  stroke: rgba(255, 255, 255, .32);
  stroke-width: 1.4;
  transition: stroke .3s ease;
}
.pump-bolt {
  fill: rgba(255, 255, 255, .34);
  transform-origin: 50% 50%;
  transition: fill .3s ease, transform .12s ease-out;
  animation: pump-flicker 6s ease-in-out infinite;
}
/* asleep it flickers now and then — long enough apart to be a question rather
   than a decoration, and the reason anybody clicks it at all */
@keyframes pump-flicker {
  0%, 88%, 100% { fill: rgba(255, 255, 255, .34); }
  90% { fill: rgba(255, 200, 90, .95); }
  92% { fill: rgba(255, 255, 255, .34); }
  95% { fill: rgba(255, 170, 40, .8); }
}
.pump-toggle:hover .pump-hex { stroke: rgba(255, 200, 90, .8); }
.pump-toggle:hover .pump-bolt { fill: rgba(255, 200, 90, .95); }

/* awake */
.pump-on .pump-toggle {
  border-color: rgba(255, 210, 63, .9);
  background: radial-gradient(circle at 50% 120%, rgba(255, 138, 0, .6), rgba(255, 0, 89, .3));
  box-shadow: 0 0 22px rgba(255, 138, 0, .7), inset 0 0 14px rgba(255, 210, 63, .35);
}
.pump-on .pump-hex { stroke: #ffd23f; }
.pump-on .pump-bolt { fill: url(#pump-bolt-fill); animation: none; }
.pump-on.pump-beat .pump-bolt { transform: scale(1.14); }
.pump-on.pump-bar .pump-bolt { transform: scale(1.3); filter: drop-shadow(0 0 6px #ffd23f); }

/* ── the layers, mounted once and only lit in pump mode ── */
.pump-layer {
  position: fixed; inset: 0; z-index: 2147483000;
  pointer-events: none; opacity: 0;
  transition: opacity .45s ease;
}
.pump-on .pump-layer { opacity: 1; }

/* The wash sits in the hot end of the wheel and stays there. A full rotation
   was the obvious idea and the wrong one: for most of every cycle the site was
   blue, which is nobody's idea of this site, and screen blending lifted so
   much light that the reds went pale. Overlay deepens what is already there
   instead of adding to it, and the swing is a shimmer of a few degrees rather
   than a trip round the wheel. */
.pump-wash {
  mix-blend-mode: overlay;
  background:
    radial-gradient(60% 55% at 12% 12%, rgba(255, 0, 60, .55), transparent 70%),
    radial-gradient(55% 50% at 88% 18%, rgba(255, 90, 0, .45), transparent 70%),
    radial-gradient(65% 60% at 50% 96%, rgba(255, 190, 0, .45), transparent 72%);
  animation: pump-hue 1.6s ease-in-out infinite alternate;
}
@keyframes pump-hue {
  from { filter: hue-rotate(-14deg) saturate(1.2); }
  to   { filter: hue-rotate(16deg) saturate(1.5); }
}

/* a second pass in colour-dodge, which is what makes the bright parts glow
   rather than merely brighten */
.pump-heat {
  mix-blend-mode: color-dodge;
  background: radial-gradient(120% 90% at 50% 50%, rgba(90, 20, 0, .55), rgba(30, 0, 0, .15) 60%, transparent 80%);
}
/* The throb animates brightness, not opacity, and only runs while the mode is
   on. Animating opacity here meant the keyframes outranked the layer's own
   opacity:0 — so switching pump mode off left this one lit over the whole
   site, glowing at everybody with nothing to explain it. */
.pump-on .pump-heat { animation: pump-heat .8s ease-in-out infinite alternate; }
@keyframes pump-heat { from { filter: brightness(.75); } to { filter: brightness(1.35); } }

/* the rim: the edges of the screen catch fire on every beat */
.pump-rim {
  box-shadow:
    inset 0 0 90px rgba(255, 0, 89, .55),
    inset 0 0 200px rgba(255, 138, 0, .28);
  transition: box-shadow .09s ease-out;
}
.pump-on.pump-beat .pump-rim {
  box-shadow:
    inset 0 0 130px rgba(255, 255, 255, .5),
    inset 0 0 260px rgba(255, 210, 63, .55);
}

/* the scan: a bar of light travelling down the page, the way a rig sweeps a room */
.pump-scan {
  background: linear-gradient(180deg, transparent 42%, rgba(255, 255, 255, .09) 50%, transparent 58%);
  background-size: 100% 220%;
  animation: pump-sweep 2.6s linear infinite;
}
@keyframes pump-sweep { to { background-position: 0 220%; } }

/* the fireworks live on a canvas, because a hundred sparks are a hundred
   things to move and the compositor should not be asked to do it in CSS */
.pump-sparks { z-index: 2147483001; }

/* ── the page on steroids ──
   The site sets --acc1 and --acc2 per asset and everything downstream reads
   them, so overriding those two carries the new palette everywhere at once
   without this file having to know a single component's name. */
.pump-on {
  --acc1: #ff0059 !important;
  --acc2: #ffd23f !important;
  --fire: #ff2b00 !important;
  --red: #ff0059 !important;
}
/* No filter on <body>: it would make body the containing block for everything
   fixed inside it — these layers, and any modal or sticky bar the site has —
   which is a strange way to break a page. The intensity comes from the layers
   above and from the accents below, neither of which moves anything. */

/* the big figures breathe on the beat — the hero, the price, the percentage */
.pump-on :is(#hero-multiple, #price-now, #pulse-change, .hero-figure, .hero-multiple) {
  text-shadow: 0 0 18px currentColor, 0 0 42px rgba(255, 210, 63, .55);
  transition: transform .09s ease-out;
  will-change: transform;
}
.pump-on.pump-beat :is(#hero-multiple, #price-now, #pulse-change, .hero-figure, .hero-multiple) {
  transform: scale(1.045);
}

/* every card gains a lit edge that cycles with the wash */
.pump-on :is(.card, .panel, .metric, .top-metric, .market-card) {
  animation: pump-edge 1.6s linear infinite;
}
@keyframes pump-edge {
  0%, 100% { box-shadow: 0 0 0 1px rgba(255, 0, 89, .55), 0 0 26px rgba(255, 0, 89, .28); }
  50%      { box-shadow: 0 0 0 1px rgba(255, 210, 63, .6), 0 0 30px rgba(255, 138, 0, .34); }
}

/* ── the fourth beat ──
   A beat every half second is a pulse; it stops being an event. So every
   fourth one is the one that matters: the page kicks, the screen flashes, a
   ring goes out and the lasers cross. Four to the bar, the way the music is
   counted, which is why it feels like it is keeping time rather than blinking. */
/* The transform is written every frame by script, from an envelope — so there
   is no transition here to fight it. A transition would be a second opinion
   about where the page is, arriving late. */
.pump-on .workspace { will-change: transform; }

/* the flash — the thing a camera does, in the colour of the room */
.pump-strobe {
  background: radial-gradient(circle at 50% 40%, #fff, #ffd2a0 45%, #ff2f8f);
  opacity: 0 !important;
  transition: opacity .3s ease-out;
}
.pump-on.pump-bar .pump-strobe { opacity: .26 !important; transition-duration: .04s; }

/* ── the rig ──
   Two crossed lines were a laser and read as a scratch on the screen. What a
   room actually looks like is beams: wide soft wedges swinging out of the
   ceiling, coloured, overlapping where they cross. Conic gradients rotating
   from a point above the top edge, which is where the lights would be. */
.pump-beams {
  mix-blend-mode: screen;
  background:
    conic-gradient(from 200deg at 22% -12%,
      transparent 0deg, rgba(255, 0, 110, .5) 16deg, transparent 34deg,
      transparent 46deg, rgba(255, 160, 0, .42) 62deg, transparent 80deg),
    conic-gradient(from 118deg at 78% -12%,
      transparent 0deg, rgba(0, 190, 255, .42) 15deg, transparent 32deg,
      transparent 44deg, rgba(180, 60, 255, .45) 60deg, transparent 78deg);
  animation: pump-beams 5.5s ease-in-out infinite alternate;
}
@keyframes pump-beams {
  from { transform: rotate(-7deg) scale(1.25); }
  to   { transform: rotate(7deg) scale(1.25); }
}

/* the room lights hit on the downbeat */
.pump-on.pump-bar .pump-beams { filter: brightness(1.9) saturate(1.4); }

/* the floor burns */
.pump-floor {
  background: linear-gradient(0deg, rgba(255, 60, 0, .55), rgba(255, 150, 0, .22) 22%, transparent 42%);
}
/* brightness, not opacity, and only while the mode is on — the same trap the
   heat layer fell into: keyframes on opacity outrank the gate that hides it,
   so the floor went on burning after the switch was thrown */
.pump-on .pump-floor { animation: pump-floor 1.1s ease-in-out infinite alternate; }
@keyframes pump-floor { from { filter: brightness(.7); } to { filter: brightness(1.3); } }

/* the numbers split into their channels on the beat, the way a bad signal does */
.pump-on.pump-bar :is(#hero-multiple, #price-now, .hero-figure, .hero-multiple) {
  text-shadow:
    -3px 0 rgba(255, 0, 90, .9), 3px 0 rgba(0, 230, 255, .8),
    0 0 22px currentColor, 0 0 50px rgba(255, 210, 63, .7);
}

/* The record has no appearance any more: it plays through YouTube's player
   API in a one-pixel host parked off screen, so what arrives is sound and
   nothing else. There is nothing here to style. */

/* the banner: says what is happening, and by how much */
.pump-banner {
  position: fixed; left: 50%; top: 0; z-index: 2147483002;
  transform: translate(-50%, -110%);
  display: flex; align-items: center; gap: 14px;
  padding: 12px 30px;
  border: 0; border-radius: 0 0 14px 14px;
  background: linear-gradient(100deg, #ff0059, #ff8a00 50%, #ffd23f);
  color: #1a0008;
  font: 800 13px/1 Inter, system-ui, sans-serif; letter-spacing: .24em; text-transform: uppercase;
  box-shadow: 0 10px 46px rgba(255, 89, 0, .75);
  transition: transform .5s cubic-bezier(.2, 1.4, .4, 1);
  pointer-events: none; white-space: nowrap;
}
.pump-on .pump-banner { transform: translate(-50%, 0); }
.pump-banner b { font-size: 19px; letter-spacing: .08em; }
.pump-on.pump-bar .pump-banner { filter: brightness(1.25); }

/* ── a reader who has asked for less movement gets the colour and none of the
   motion. The mode still reads as ON; it simply stops jumping about. ── */
@media (prefers-reduced-motion: reduce) {
  .pump-wash, .pump-heat, .pump-scan, .pump-floor, .pump-beams,
  .pump-on .workspace, .pump-strobe,
  .pump-on :is(.card, .panel, .metric, .top-metric, .market-card),
  .pump-bolt { animation: none; }
  .pump-on.pump-beat :is(#hero-multiple, #price-now, #pulse-change, .hero-figure, .hero-multiple) { transform: none; }
  .pump-on .workspace { transform: none !important; }
  .pump-sparks { display: none; }
}
