/* ═══════════════════════════════════════════════════════════════
   fx.css — the motion layer's pieces (js/fx.js) and the hover and
   press details that make the terminal feel alive. Movement answers
   something: a price that moved, a row that arrived, a button you
   pressed, the thing under your cursor.
   ═══════════════════════════════════════════════════════════════ */

/* ── glide: the moving selection (js/fx.js) ── */
.fx-glide{position:absolute;left:0;top:0;pointer-events:none;will-change:transform,width}
.fx-arrive{background-color:transparent!important;background-image:none!important;box-shadow:none!important}
.fx-arrive-c{color:var(--text)!important}
.fx-arrive-l{border-bottom-color:transparent!important}
.fx-arrive-a::after{opacity:0!important}

/* ── spotlight: cards light up under the cursor ── */
.fx-lit{background-image:radial-gradient(260px circle at var(--fx-x,50%) var(--fx-y,50%),rgba(var(--brand-rgb),.11),transparent 72%)!important}

/* ── the top nav: an underline on this page, a pill under the pointer ── */
.nav-tabs{position:relative;isolation:isolate}
.fx-navbar{position:absolute;left:0;top:0;height:2px;border-radius:2px;background:var(--brand);opacity:0;pointer-events:none;
  box-shadow:0 0 12px rgba(var(--brand-rgb),.7);
  transition:transform .5s var(--spring-snappy,cubic-bezier(.22,1,.36,1)),width .5s var(--spring-snappy,cubic-bezier(.22,1,.36,1)),opacity .2s}
.fx-navhov{position:absolute;left:0;top:0;z-index:-1;border-radius:8px;background:var(--hover);opacity:0;pointer-events:none;
  transition:transform .32s var(--spring-snappy,cubic-bezier(.22,1,.36,1)),width .32s var(--spring-snappy,cubic-bezier(.22,1,.36,1)),opacity .18s}
.nav-tabs a:hover{background:transparent}

/* ── a page opening: a sweep along the top ── */
.fx-sweep{position:fixed;left:0;right:0;top:0;height:2px;z-index:9001;pointer-events:none;transform-origin:0 50%;transform:scaleX(0);opacity:0;
  background:linear-gradient(90deg,rgba(var(--brand-rgb),.2),var(--brand) 70%,#fff);box-shadow:0 0 12px rgba(var(--brand-rgb),.8)}

/* ── a closed position's PnL floating up from the button ── */
.fx-float{position:absolute;font:700 16px/1 var(--mono);white-space:nowrap;letter-spacing:-.01em;text-shadow:0 2px 14px rgba(0,0,0,.65)}

/* ── the logo's clan (.lm-live): the crest pops in on load and the three rise over the wall; now and then they
      peek, they blink, their eyes follow the pointer (js/fx.js sets --lx / --ly), and they hop when you point at
      the logo. Lengths are the mark's own units (64 across) ── */
.lm-live .lm-f,.lm-live .lm-k,.lm-live .lm-bl,.lm-live .lm-c{transform-box:fill-box}
.lm-live .lm-f,.lm-live .lm-k{transform-origin:50% 100%}
.lm-live .lm-bl,.lm-live .lm-c{transform-origin:50% 50%}
.lm-live .lm-e{transform:translate(var(--lx,0px),var(--ly,0px));transition:transform .45s var(--spring-snappy,cubic-bezier(.22,1,.36,1))}
.lm-live .lm-f1{animation:lm-peek 7s 2.2s ease-in-out infinite}
.lm-live .lm-f2{animation:lm-peek 7s 2.34s ease-in-out infinite}
.lm-live .lm-f3{animation:lm-peek 7s 2.48s ease-in-out infinite}
.lm-live .lm-f1 .lm-bl{animation:lm-blink 4.3s 1.8s infinite}
.lm-live .lm-f2 .lm-bl{animation:lm-blink 5.1s 2.7s infinite}
.lm-live .lm-f3 .lm-bl{animation:lm-blink 5.9s 3.4s infinite}
body:not(.booted) .logo-mark.lm-live{animation:lm-pop .6s .05s var(--spring-bouncy,cubic-bezier(.34,1.56,.64,1)) both}
body:not(.booted) .lm-live .lm-f{animation:lm-rise .75s var(--spring-bouncy,cubic-bezier(.34,1.56,.64,1)) both}
body:not(.booted) .lm-live .lm-f1{animation-delay:.3s}
body:not(.booted) .lm-live .lm-f2{animation-delay:.42s}
body:not(.booted) .lm-live .lm-f3{animation-delay:.54s}
body:not(.booted) .lm-live .lm-k{animation:lm-crown-in .55s .78s var(--spring-bouncy,cubic-bezier(.34,1.56,.64,1)) both}
.logo:hover .lm-live .lm-f{animation:lm-hop .62s var(--spring-bouncy,cubic-bezier(.34,1.56,.64,1)) both}
.logo:hover .lm-live .lm-f2{animation-delay:.07s}
.logo:hover .lm-live .lm-f3{animation-delay:.14s}
.logo:hover .lm-live .lm-k{animation:lm-crown .7s .12s var(--spring-bouncy,cubic-bezier(.34,1.56,.64,1)) both}
.logo:hover .lm-live .lm-c{animation:lm-chev .6s .2s var(--spring-bouncy,cubic-bezier(.34,1.56,.64,1)) both}
@keyframes lm-peek{0%,78%,100%{transform:none}84%{transform:translateY(-3.2px)}90%{transform:translateY(.6px)}95%{transform:none}}
@keyframes lm-blink{0%,90%,100%{transform:none}94%{transform:scaleY(.1)}}
@keyframes lm-pop{from{transform:scale(.3) rotate(-14deg);opacity:0}}
@keyframes lm-rise{from{transform:translateY(16px)}}
@keyframes lm-crown-in{from{transform:translateY(-10px) rotate(-24deg);opacity:0}}
@keyframes lm-hop{0%{transform:none}32%{transform:translateY(-7px)}62%{transform:translateY(1px)}100%{transform:none}}
@keyframes lm-crown{0%,100%{transform:none}30%{transform:rotate(-14deg) translateY(-2px)}65%{transform:rotate(10deg)}}
@keyframes lm-chev{0%,100%{transform:none}40%{transform:translateY(-4px) scale(1.15)}}

/* ── icons answer the pointer ── */
.icon-btn svg,.chipbtn svg,.btn svg{transition:transform .45s var(--spring-bouncy,cubic-bezier(.34,1.56,.64,1))}
.icon-btn:hover svg{transform:translateY(-1px) scale(1.1)}
#settingsBtn:hover svg,[data-a="settings"]:hover svg{transform:rotate(75deg)}
#dockBtn:hover svg{transform:translateX(-2px)}
.btn:hover > svg:first-child{transform:translateX(-1px) scale(1.08)}
[data-star]:hover svg,#watchBtn:hover svg{animation:fx-wig .55s ease}
@keyframes fx-wig{0%,100%{transform:rotate(0)}25%{transform:rotate(-14deg) scale(1.12)}60%{transform:rotate(10deg) scale(1.08)}}

/* ── the big trade buttons: a glow in their colour and a sheen on hover ── */
.btn-up,.btn-down,.btn-cta,.btn-brand{position:relative;overflow:hidden;isolation:isolate}
.btn-up::after,.btn-down::after,.btn-cta::after,.btn-brand::after{content:"";position:absolute;inset:0;z-index:-1;pointer-events:none;
  background:linear-gradient(105deg,transparent 30%,rgba(255,255,255,.28) 48%,transparent 66%);transform:translateX(-110%)}
.btn-up:hover:not(:disabled)::after,.btn-down:hover:not(:disabled)::after,.btn-cta:hover:not(:disabled)::after,.btn-brand:hover:not(:disabled)::after{animation:fx-sheen .9s cubic-bezier(.22,1,.36,1)}
@keyframes fx-sheen{to{transform:translateX(110%)}}
.btn-up:hover:not(:disabled){box-shadow:0 8px 26px -10px rgba(var(--up-rgb),.85)}
.btn-down:hover:not(:disabled){box-shadow:0 8px 26px -10px rgba(var(--down-rgb),.85)}
.btn-cta:hover:not(:disabled),.btn-brand:hover:not(:disabled){box-shadow:0 8px 26px -10px rgba(var(--brand-rgb),.9)}
/* sending: stripes run along the button until the order is answered */
.btn.fx-busy{background-image:repeating-linear-gradient(-45deg,rgba(255,255,255,.14) 0 8px,transparent 8px 16px)!important;background-size:23px 100%;
  animation:fx-busy .6s linear infinite}
@keyframes fx-busy{to{background-position:23px 0}}

/* ── long / short and buy / sell: the side you point at takes its colour ── */
.pt-side .t-long:not([aria-pressed=true]):hover,.trade-tabs .t-long:not([aria-pressed=true]):hover,.trade-tabs .t-buy:not([aria-pressed=true]):hover{color:var(--up)}
.pt-side .t-short:not([aria-pressed=true]):hover,.trade-tabs .t-short:not([aria-pressed=true]):hover,.trade-tabs .t-sell:not([aria-pressed=true]):hover{color:var(--down)}

/* ── table rows: an accent grows on the left of the one you point at (Trenches rows have theirs in terminal.css) ── */
.ptable tbody tr > td:first-child{background-image:linear-gradient(var(--brand),var(--brand));background-repeat:no-repeat;background-size:2px 0;
  background-position:0 50%;transition:background-size .28s var(--spring-snappy,cubic-bezier(.22,1,.36,1))}
.ptable tbody tr:hover > td:first-child{background-size:2px 70%}
.tbody .trow::before{transition:opacity .2s,transform .4s var(--spring-bouncy,cubic-bezier(.34,1.56,.64,1))}

/* ── the order book: levels you point at glow; the mid price in the middle ── */
button.ob-r{transition:background .12s}
button.ob-r.ask:hover{background:rgba(var(--down-rgb),.08)}
button.ob-r.bid:hover{background:rgba(var(--up-rgb),.08)}
.ob-r > i{transition:width .32s var(--spring-snappy,cubic-bezier(.22,1,.36,1))}
.ob-r .fx-u,.ob-r .fx-d{border-radius:2px}
.ob-spr .ob-mid{display:inline-flex;align-items:center;gap:4px;font:600 14px var(--mono);color:var(--text)}
.ob-spr .ob-mid.up{color:var(--up)}
.ob-spr .ob-mid.down{color:var(--down)}
.ob-mid svg{transition:transform .35s var(--spring-bouncy,cubic-bezier(.34,1.56,.64,1))}
.ob-mid.down svg{transform:rotate(180deg)}
.ob-mid:not(.up):not(.down) svg{opacity:0}
.ob-trades .ob-r{transition:background .2s}
.ob-r.ob-big{font-weight:600}
.ob-r.ob-big::before{content:"";position:absolute;left:0;top:3px;bottom:3px;width:2px;border-radius:2px;background:currentColor}
.ob-r.ob-big.buy::before{background:var(--up)}
.ob-r.ob-big.sell::before{background:var(--down)}
.ob-whale{margin-left:4px;font-size:11px}

/* ── the size slider: a bubble with the share rides the thumb while you drag ── */
.pt-sl{position:relative}
.pt-slb{position:absolute;top:-20px;left:var(--fill,0%);transform:translateX(-50%) scale(.6);opacity:0;padding:2px 6px;border-radius:5px;pointer-events:none;
  background:var(--text);color:var(--bg);font:600 10.5px/1.3 var(--mono);transition:opacity .15s,transform .3s var(--spring-bouncy,cubic-bezier(.34,1.56,.64,1))}
.pt-slb::after{content:"";position:absolute;left:50%;bottom:-3px;width:6px;height:6px;margin-left:-3px;background:inherit;transform:rotate(45deg);border-radius:1px}
.pt-sl.drag .pt-slb{opacity:1;transform:translateX(-50%) scale(1)}
.pt-sl input[type=range]::-webkit-slider-thumb{transition:transform .3s var(--spring-bouncy,cubic-bezier(.34,1.56,.64,1)),box-shadow .2s}
.pt-sl input[type=range]:hover::-webkit-slider-thumb{transform:scale(1.15)}
.pt-sl.drag input[type=range]::-webkit-slider-thumb{transform:scale(1.3);box-shadow:0 0 0 3px var(--card),0 0 0 7px rgba(var(--brand-rgb),.25)}
.pt-ticks button.past{color:var(--text-2)}

/* ── the leverage sheet: the number heats up as you raise it ── */
.pt-lv{--heat:var(--up)}
.pt-lvv b{display:inline-block;color:var(--heat);transition:color .25s;text-shadow:0 0 22px color-mix(in srgb,var(--heat) 45%,transparent)}
.pt-lv input[type=range]{background:linear-gradient(90deg,var(--heat) var(--fill,0%),var(--line-2) var(--fill,0%))}
.pt-lv input[type=range]::-webkit-slider-thumb{box-shadow:0 0 0 3px var(--card),0 0 14px color-mix(in srgb,var(--heat) 70%,transparent)}

/* ── live dots breathe ── */
.fx-live{position:relative;display:inline-block;width:7px;height:7px;border-radius:50%;background:var(--up)}
.fx-live::after{content:"";position:absolute;inset:0;border-radius:50%;background:inherit;animation:fx-ping 1.8s cubic-bezier(0,0,.2,1) infinite}
@keyframes fx-ping{0%{transform:scale(1);opacity:.7}80%,100%{transform:scale(2.6);opacity:0}}

/* ── cards you can open lift a little ── */
.pm-card,.st-card,.pd-card,.cs-pick{transition:translate .35s var(--spring-snappy,cubic-bezier(.22,1,.36,1)),box-shadow .25s,border-color .2s,background-color .2s}
.pm-card:hover,.st-card:hover,.pd-card:hover,.cs-pick:hover{translate:0 -2px;box-shadow:0 14px 30px -18px rgba(0,0,0,.9)}

/* ── counts in tabs pop when they change ── */
.pt-tabs .n.fx-n,.pt-tabs .n.fl-up,.pt-tabs .n.fl-dn{display:inline-block;animation:fx-pop .5s var(--spring-bouncy,cubic-bezier(.34,1.56,.64,1))}
@keyframes fx-pop{0%{transform:scale(1)}35%{transform:scale(1.45)}100%{transform:none}}

/* ═══════════════ round 7: more motion, each piece answering something ═══════════════ */

/* the pointer's light (js/fx.js) is registered as not inherited, so moving it restyles only the lit element, not all it holds */
@property --fx-x{syntax:'<length-percentage>';inherits:false;initial-value:50%}
@property --fx-y{syntax:'<length-percentage>';inherits:false;initial-value:50%}

/* ── a panel's border lights up near the pointer (.fx-edge): the hairline, with a glow where the pointer is ── */
.panel.fx-edge{border-color:transparent;background:linear-gradient(var(--card),var(--card)) padding-box,
  radial-gradient(220px circle at var(--fx-x) var(--fx-y),rgba(var(--brand-rgb),.85),transparent 70%) border-box,
  linear-gradient(var(--line),var(--line)) border-box}

/* ── sheets and menus spring open out of the control that opened them (ui-shell.js sets the transform-origin there) ── */
/* a move along a page's own tabs (fx.js → routed): the page as a whole doesn't rise (terminal.css .view.vt), only what's below the tabs slides */
.view.vt.fx-tabmove > *{animation:none}

.sheet.fx-from{animation:fx-sheet-in .48s var(--spring-snappy,cubic-bezier(.22,1,.36,1))}
@keyframes fx-sheet-in{0%{opacity:0;transform:scale(.72)}35%{opacity:1}}
.dd.fx-from{animation:fx-dd-in .36s var(--spring-snappy,cubic-bezier(.22,1,.36,1))}
@keyframes fx-dd-in{0%{opacity:0;transform:scale(.8)}40%{opacity:1}}

/* ── toasts: the icon pops in; then the tick draws itself (terminal.css), a warning or error shakes, info drops in ── */
.toast .ti{animation:fx-ti-pop .5s var(--spring-bouncy,cubic-bezier(.34,1.56,.64,1)) .04s backwards}
.toast.t-ok .ti{animation:fx-ti-pop .5s var(--spring-bouncy,cubic-bezier(.34,1.56,.64,1)) .04s backwards,ping 1.2s ease-out .3s}
.toast.t-ok .ti path{animation-delay:.24s}
.toast.t-warn .ti .ic,.toast.t-err .ti .ic{animation:fx-ti-shake .52s ease-in-out .34s}        /* no fill: it starts and ends at rest */
.toast.t-info .ti .ic{animation:fx-ti-drop .5s var(--spring-bouncy,cubic-bezier(.34,1.56,.64,1)) .16s backwards}
@keyframes fx-ti-pop{from{transform:scale(0) rotate(-35deg)}}
@keyframes fx-ti-shake{0%,100%{transform:none}18%{transform:translateX(-2.5px) rotate(-9deg)}38%{transform:translateX(2.5px) rotate(8deg)}58%{transform:translateX(-1.5px) rotate(-5deg)}78%{transform:translateX(1px) rotate(2deg)}}
@keyframes fx-ti-drop{from{transform:translateY(-7px);opacity:0}}

/* ── sparklines (util.js → sparkSvg): the line draws in, left to right, the first time it shows; a dot rides the last
      price, glides when it moves and pings once (each new price is a new .spk-ping) ── */
.spark{overflow:visible}
.spark:not(.spk-none){animation:fx-spk-in .75s cubic-bezier(.22,1,.36,1)}
@keyframes fx-spk-in{from{clip-path:inset(0 100% 0 0)}to{clip-path:inset(0 0 0 0)}}
.spark .spk-end{transition:transform .6s var(--spring-snappy,cubic-bezier(.22,1,.36,1))}
.spark .spk-dot,.spark .spk-ping{fill:none;stroke-linecap:round;vector-effect:non-scaling-stroke}
.spark .spk-dot{stroke-width:4.5}
.spark .spk-ping{stroke-width:4.5;stroke-opacity:0;animation:fx-spk-ping 1.3s cubic-bezier(0,0,.2,1) .12s}
@keyframes fx-spk-ping{0%{stroke-width:4.5;stroke-opacity:.7}100%{stroke-width:16;stroke-opacity:0}}

/* ── PnL magnitude (util.js → pnlBar): a bar behind each PnL, as long as its share of the biggest one; it grows in the
      first time and eases to a new share ── */
.pnl-c{position:relative;isolation:isolate}
.pnl-bar{position:absolute;right:0;top:4px;bottom:4px;width:100%;z-index:-1;border-radius:3px;pointer-events:none;opacity:.16;
  transform-origin:100% 50%;transform:scaleX(var(--w,0));transition:transform .6s var(--spring-snappy,cubic-bezier(.22,1,.36,1));
  animation:fx-bar-grow .85s var(--spring-snappy,cubic-bezier(.22,1,.36,1))}
.pnl-bar.up{background:var(--up)}
.pnl-bar.down{background:var(--down)}
@keyframes fx-bar-grow{from{transform:scaleX(0)}}

/* ── the order book: a level's depth bar grows in when the level appears (then eases, above); a trade lights up the
      level it hit (ui-token.js → bookHit) ── */
.ob-asks .ob-r > i,.ob-bids .ob-r > i,.ob-side .ob-r > i{animation:fx-ob-in .4s cubic-bezier(.22,1,.36,1)}
@keyframes fx-ob-in{from{width:0}}
button.ob-r.fx-u{animation:fx-hit-u .85s ease-out}
button.ob-r.fx-d{animation:fx-hit-d .85s ease-out}
@keyframes fx-hit-u{0%{background-color:rgba(var(--up-rgb),.36);box-shadow:inset 2px 0 0 var(--up)}100%{background-color:rgba(var(--up-rgb),0);box-shadow:inset 2px 0 0 rgba(var(--up-rgb),0)}}
@keyframes fx-hit-d{0%{background-color:rgba(var(--down-rgb),.36);box-shadow:inset 2px 0 0 var(--down)}100%{background-color:rgba(var(--down-rgb),0);box-shadow:inset 2px 0 0 rgba(var(--down-rgb),0)}}

/* ── the clan's crest heads the empty states (ui-room.js, ui-clanhq.js): it pops in, then peeks and watches as the logo does ── */
.logo-mark.fx-crest{margin:0 auto 6px;animation:lm-pop .6s .05s var(--spring-bouncy,cubic-bezier(.34,1.56,.64,1)) both}
.hn-pitch .logo-mark.fx-crest{margin:0 0 12px}

/* ── the clan banner: the clan's colour washes across it as the room opens; online dots ping ── */
.hq-ban.fx-wash::after{content:"";position:absolute;inset:0;border-radius:inherit;pointer-events:none;background:var(--cc);
  animation:fx-wash 1.3s cubic-bezier(.22,1,.36,1) both}
@keyframes fx-wash{0%{opacity:.34;clip-path:inset(0 100% 0 0)}30%{opacity:.26;clip-path:inset(0 0 0 0)}100%{opacity:0;clip-path:inset(0 0 0 0)}}
.hb-dot,.hm-on,.cc-on i{position:relative}
.hb-dot::after,.hm-on::after,.cc-on i::after{content:"";position:absolute;inset:0;border-radius:50%;background:var(--up);opacity:0;
  animation:fx-ping 2.4s cubic-bezier(0,0,.2,1) infinite}

@media (prefers-reduced-motion:reduce){
  .fx-glide,.fx-sweep,.fx-navhov{display:none}
  .fx-live::after,.btn.fx-busy,.logo-mark.lm-live,.lm-live *{animation:none!important;transition:none!important}
  .spark .spk-ping,.hb-dot::after,.hm-on::after,.cc-on i::after,.hq-ban.fx-wash::after{display:none}
}
body.motion-reduced .fx-live::after,body.motion-reduced .btn.fx-busy{animation:none!important}
body.motion-reduced .spark .spk-ping,body.motion-reduced .hb-dot::after,body.motion-reduced .hm-on::after,body.motion-reduced .cc-on i::after,
body.motion-reduced .hq-ban.fx-wash::after{display:none}
