/* Moonlit stone + enamel. Presentation overrides are isolated from legacy layout and mechanics. */
:root{
  --ui-ink:#101e30;--ui-rim:#547083;--ui-light:#d8e6e6;
  --ui-gold:#f0d393;--ui-shadow:#050e1db3;
}
/* One readable clock and one generous pause target. Match options live in Pause. */
#center{height:44px;top:calc(env(safe-area-inset-top,0px) + 8px);left:calc(env(safe-area-inset-left,0px) + 12px);right:calc(env(safe-area-inset-right,0px) + 12px)}
#center #clock{height:36px;min-width:88px;max-width:calc(100% - 108px);overflow:hidden;text-overflow:ellipsis;line-height:24px;padding:5px 14px;border-radius:12px;border:1px solid #869aac80;background:linear-gradient(#263b4feb,#122236f5);box-shadow:0 3px 0 #050f20b3,inset 0 1px 0 #dcebe72e;color:#f5edda;font-size:14px;letter-spacing:.5px;font-weight:800}
#center #clock.damped{color:#ffb296;border-color:#dba08799}
/* v0.9.20 (Henry): Pause sits in the middle, just right of the clock, so the enemy frames can use the top-right corner. */
#center #pauseBtn{position:absolute;top:-4px;left:calc(50% + 52px);width:44px;height:44px;min-width:44px;border-radius:13px;border:1px solid #8299a180;background:linear-gradient(#2c4257ee,#142438f2);box-shadow:0 3px 0 #050f20b3,inset 0 1px 0 #ffffff26;font-size:17px;color:#dce9e5}
#center #meter{position:absolute;left:0;top:44px;height:26px;line-height:16px;padding:5px 9px;border-radius:7px;font-size:10px;background:#102337e8;pointer-events:none}
.frames{width:min(210px,calc(50% - 14px))}
.frame{height:44px;min-height:44px;border-radius:9px;background:#14273cba;border-color:#68848b80}
.frame .bar{opacity:1}
body.show-frames #center{top:calc(env(safe-area-inset-top,0px) + 106px)}
#practiceTools{top:calc(env(safe-area-inset-top,0px) + 88px);gap:8px}
#practiceTools button{min-height:44px;border-radius:10px;background:#172e43ed;border-color:#79989f70;font-size:11px}
body.show-frames #practiceTools{top:calc(env(safe-area-inset-top,0px) + 186px)}
.match-tools{display:grid;grid-template-columns:repeat(5,minmax(0,1fr));gap:6px;margin:22px 0 6px}
.match-tool{display:grid;gap:7px;text-align:center;font-size:10px;color:#b7cbd1}
.match-tool .camera-offset{display:flex;align-items:center;justify-content:center;gap:8px;min-height:44px}
.match-tool button{min-height:44px;min-width:44px;border:1px solid var(--ui-rim);border-radius:10px;background:linear-gradient(#2b4359,#172c40);box-shadow:0 3px 0 #081323;color:#e0ece7;cursor:pointer;font-size:12px}
.match-tool #muteBtn svg{margin:auto;width:19px;height:19px}
.match-tool button:active,#center #pauseBtn:active{transform:translateY(2px);box-shadow:0 1px 0 #081323}
#abil{width:260px;height:204px;right:calc(env(safe-area-inset-right,0px)*.4 + 6px);bottom:calc(env(safe-area-inset-bottom,0px)*.5 + 6px);transform:none}
:is(#abil,#breakFreeSlot) .ab{
  /* v0.9.19, Overwatch Rush-style: a semi-transparent fill so the arena shows through, inside a thick light rim
     tinted by the ability's colour, with a thin dark edge so the rim reads on bright floors too. */
  border:3.5px solid color-mix(in srgb,var(--ability-bg,#3b4b5c) 35%,#fff);border-radius:50%;isolation:isolate;
  background:radial-gradient(circle at 50% 26%,color-mix(in srgb,var(--ability-bg,#3b4b5c) 72%,#ffffffb3),color-mix(in srgb,var(--ability-bg,#3b4b5c) 74%,transparent) 58%,color-mix(in srgb,var(--ability-bg,#3b4b5c) 60%,#000000a6));
  box-shadow:0 0 0 1.5px #0b1622b3,0 4px 10px #02081259;
  transition:transform .09s ease-out,border-color .12s,box-shadow .12s;
}
:is(#abil,#breakFreeSlot) .ab .ic{width:26px;height:26px;transform:translateY(-9px);color:#fff;filter:drop-shadow(0 1px 1px #000a)}
:is(#abil,#breakFreeSlot) .ab .ic svg{stroke-width:2.1}
:is(#abil,#breakFreeSlot) .ab .nm{bottom:8px;font-size:9.5px;line-height:1.03;letter-spacing:0;padding:0 6px;color:#fff;font-weight:700;text-shadow:0 1px 2px #000c,0 0 3px #0008;overflow-wrap:normal}
:is(#abil,#breakFreeSlot) .ab .pot{top:5px;font-size:8px;letter-spacing:.4px}
:is(#abil,#breakFreeSlot) .ab .key{top:6px;right:9px;font-size:8px;color:#c0cfd7}
:is(#abil,#breakFreeSlot) .ab .cd{inset:3px;z-index:1;opacity:.86}
:is(#abil,#breakFreeSlot) .ab .tx{z-index:3;padding-bottom:8px;color:#fff4d6;font-size:22px;font-weight:850;text-shadow:0 2px 3px #000}
:is(#abil,#breakFreeSlot) .ab .cast-progress{position:absolute;inset:2px;border-radius:50%;pointer-events:none;z-index:2;opacity:0;mask:radial-gradient(circle,transparent 61%,#000 63%);-webkit-mask:radial-gradient(circle,transparent 61%,#000 63%)}
:is(#abil,#breakFreeSlot) .ab .queue-mark{display:none;position:absolute;right:8px;top:4px;color:#fff4d4;font-size:13px;z-index:4}
:is(#abil,#breakFreeSlot) .ab.ready{border-color:var(--ability-color,#91c5cc)}
:is(#abil,#breakFreeSlot) .ab.cdn .ic{filter:grayscale(.85) brightness(.42)}
:is(#abil,#breakFreeSlot) .ab.cdn .nm{color:#d5dde3}
:is(#abil,#breakFreeSlot) .ab.bad{border-color:#9e6970}
:is(#abil,#breakFreeSlot) .ab.bad{filter:saturate(.3) brightness(.85)}
:is(#abil,#breakFreeSlot) .ab.casting{border-color:#f0d393}
:is(#abil,#breakFreeSlot) .ab.casting .cast-progress{opacity:1}
:is(#abil,#breakFreeSlot) .ab.casting .ic{filter:brightness(.55)}
:is(#abil,#breakFreeSlot) .ab.queued{border-color:#fff1c8;box-shadow:0 0 0 1.5px #0b1622b3,0 0 0 4px #fff1c866}
:is(#abil,#breakFreeSlot) .ab.queued .queue-mark{display:block}
:is(#abil,#breakFreeSlot) .ab.press{transform:scale(.93);box-shadow:0 0 0 1.5px #0b1622b3,0 1px 4px #02081266}
:is(#abil,#breakFreeSlot) .ab.flash::after{inset:3px;border-width:2px;animation:readyflash .4s ease-out forwards}
/* Henry (2026-10-30): Execute (any `executeAt` ability) glows gold while its window is open, pulsing like WoW's spell alert.
   2026-11-03: every proc does, with a ring of gold sparks circling the icon's edge inside the rim (WoW's spell-activation
   overlay; the button clips anything outside). Lighting up (.procin) the ring closes in from wide and the icon pops. Declared before the ready flash so a cooldown
   coming back still flashes over it. Steady with reduced motion. */
:is(#abil,#breakFreeSlot) .ab.proc{border-color:#ffe27a;animation:procglow .9s ease-in-out infinite alternate}
@keyframes procglow{from{box-shadow:0 0 0 2px #ffe27a,0 0 10px 3px #ffb347aa}to{box-shadow:0 0 0 3px #fff3b0,0 0 22px 8px #ffb347}}
:is(#abil,#breakFreeSlot) .ab.proc::before{content:'';position:absolute;inset:0;border-radius:50%;pointer-events:none;z-index:2;
  background:repeating-conic-gradient(from 0deg,#ffc84a00 0deg,#ffc84a 22deg,#fff8d0 28deg,#ffc84a00 30deg);
  mask:radial-gradient(closest-side,transparent calc(100% - 7px),#000 calc(100% - 6px));
  -webkit-mask:radial-gradient(closest-side,transparent calc(100% - 7px),#000 calc(100% - 6px));
  filter:drop-shadow(0 0 3px #ffb347);animation:procspin 2.4s linear infinite}
@keyframes procspin{to{rotate:360deg}}
:is(#abil,#breakFreeSlot) .ab.procin::before{animation:procslam .35s cubic-bezier(.2,.9,.3,1.2),procspin 2.4s linear infinite}
@keyframes procslam{from{scale:1.4;opacity:0}to{scale:1;opacity:1}}
:is(#abil,#breakFreeSlot) .ab.procin .ic{animation:iconpop .45s ease-out}
@keyframes iconpop{0%{scale:1}35%{scale:1.16;filter:brightness(1.8)}100%{scale:1;filter:brightness(1)}}
@media(prefers-reduced-motion:reduce){:is(#abil,#breakFreeSlot) .ab.proc{animation:none;box-shadow:0 0 0 3px #ffe27a,0 0 16px 5px #ffb347cc}
  :is(#abil,#breakFreeSlot) .ab.proc::before,:is(#abil,#breakFreeSlot) .ab.procin::before,:is(#abil,#breakFreeSlot) .ab.procin .ic{animation:none}}
/* Henry (2026-10-28): a cooldown coming back glows and flashes for one second: a white flash on the icon twice, and a
   glow in the ability's colour that fades out. The ring above still pops on top. */
:is(#abil,#breakFreeSlot) .ab.flash{animation:readyglow 1s ease-out forwards}
:is(#abil,#breakFreeSlot) .ab.flash .ic{animation:readyicon 1s linear forwards}
@keyframes readyglow{0%,40%{box-shadow:0 0 0 3px #fff,0 0 22px 8px var(--ability-color,#fff)}100%{box-shadow:0 0 0 0 #fff0,0 0 0 0 transparent}}
/* 2026-11-03: the icon also pops (a quick swell) as it comes back, so the change reads beside a thumb. */
@keyframes readyicon{0%{filter:brightness(2.2);scale:1}12%{scale:1.15}20%{filter:brightness(2.2)}30%{filter:brightness(1);scale:1}45%,60%{filter:brightness(1.9)}75%,100%{filter:brightness(1);scale:1}}
/* v0.9.17: one layout for every class. Slots by role: s0 main, s1-s2 rotation, s3 cooldown, s4 movement or utility,
   s5 control. v0.9.19: exactly where Henry placed them on his iPhone screenshot (yellow markers), measured from the
   main button, which keeps its 0.9.18 corner spot: s1 left of it, s2 up-left, s3 straight up into the edge, s4 far
   left and low, s5 between s4 and s2. v0.9.22 (Henry): the big cooldown takes the far-left low spot and movement goes
   up into the edge (s3 and s4 swapped places; each spot keeps its size). */
#hud #abil .ab.s0{width:80px;height:80px;right:0;bottom:0}
#hud #abil .ab.s0 .ic{width:31px;height:31px}
#hud #abil .ab.s0 .nm{font-size:10px;bottom:12px}
#hud #abil .ab.s1{width:64px;height:64px;right:104px;bottom:4px}
#hud #abil .ab.s2{width:64px;height:64px;right:68px;bottom:81px}
#hud #abil .ab.s3{width:58px;height:58px;right:201px;bottom:13px}
#hud #abil .ab.s4{width:64px;height:64px;right:0;bottom:132px}
#hud #abil .ab.s5{width:58px;height:58px;right:163px;bottom:88px}
/* v0.9.29: a seventh button above, between the cooldown arc and the rotation, for each class's new ability. */
#hud #abil .ab.s6{width:58px;height:58px;right:99px;bottom:145px}
/* Portrait phones are narrow: the 260px arc would reach into the left 45% where touches start the joystick, so it is
   drawn at 85% from the corner (Larger controls still overrides). */
@media(orientation:portrait){#abil{transform:scale(.85);transform-origin:bottom right}}
/* v0.9.26 (Henry): players move the whole cluster (--abil-x right, --abil-y up, in px) and spread it around the main
   button (--abil-spread, 1 = as placed above), from Layout in the pause menu. Each slot's centre, measured from the
   cluster's bottom-right corner, is repeated here so the spread scales its distance from the main button's centre
   (40, 40); tests/hud.test.cjs checks the two stay in step. The cluster moves with translate (transform stays free for
   scale); the spread uses margins, which the failed-press shake (it animates translate) leaves alone. */
#hud #abil{translate:var(--abil-x,0px) calc(var(--abil-y,0px)*-1)}
#hud #abil .ab.s1{--cx:136;--cy:36}
#hud #abil .ab.s2{--cx:100;--cy:113}
#hud #abil .ab.s3{--cx:230;--cy:42}
#hud #abil .ab.s4{--cx:32;--cy:164}
#hud #abil .ab.s5{--cx:192;--cy:117}
#hud #abil .ab.s6{--cx:128;--cy:174}
#hud #abil .ab:is(.s1,.s2,.s3,.s4,.s5,.s6){margin:0 calc((var(--cx) - 40)*(var(--abil-spread,1) - 1)*1px) calc((var(--cy) - 40)*(var(--abil-spread,1) - 1)*1px) 0}
:is(#hud #abil .ab.s1,#hud #abil .ab.s2,#hud #abil .ab.s4) .ic{width:25px;height:25px}
:is(#hud #abil .ab.s3,#hud #abil .ab.s5,#hud #abil .ab.s6) .ic{width:23px;height:23px}
.large-controls #abil{transform:scale(1.12);transform-origin:bottom right}
#toast{border:1px solid #b28b7080;border-radius:10px;background:#18283def;box-shadow:0 4px 15px #07122070}
/* Wide screens put each team's two frames side by side, keeping their 44px targets. */
@media(orientation:landscape){
  .frames{flex-direction:row;width:calc(50% - 12px);max-width:none}
  .frame{flex:1;min-width:0}
  body.show-frames #center{top:calc(env(safe-area-inset-top,0px) + 56px)}
  body.show-frames #practiceTools{top:calc(env(safe-area-inset-top,0px) + 136px)}
}
@media(prefers-reduced-motion:reduce){:is(#abil,#breakFreeSlot) .ab{transition:none}:is(#abil,#breakFreeSlot) .ab.flash::after,:is(#abil,#breakFreeSlot) .ab.flash .ic{animation:none}:is(#abil,#breakFreeSlot) .ab.press{transform:none}}
/* v0.8.7: practice tools stack at the top-left under the meter, off the arena centre and the target's bar.
   The decorative arena caption stays out of combat, where it sat over the player in landscape. */
#practiceTools{left:calc(env(safe-area-inset-left,0px) + 12px);right:auto;transform:none;flex-direction:column;align-items:flex-start;top:calc(env(safe-area-inset-top,0px) + 86px)}
#practiceTools button{min-height:40px;padding:0 12px;font-size:11px}
/* Practice actions sit above friendly frames at 70% of their former size. */
#hud #practiceTools{width:max-content;flex-direction:row;align-items:center;transform:scale(.7);transform-origin:top left;white-space:nowrap}
body.training #hud #allies{top:calc(env(safe-area-inset-top,0px) + max(var(--frame-top-a,8px),44px))}
@media(orientation:portrait){body.training #hud #allies{top:calc(env(safe-area-inset-top,0px) + max(var(--frame-top-a,58px),84px))}}
#hud #arenaLabel{display:none}
/* v0.8.8: frames respect iPhone safe areas. In landscape the notch insets come off the frames row before it is
   split between the teams. */
.frames{width:min(210px,calc(50% - 14px - (env(safe-area-inset-left,0px) + env(safe-area-inset-right,0px))/2))}
@media(orientation:landscape){
  .frames{width:calc(50% - 12px - (env(safe-area-inset-left,0px) + env(safe-area-inset-right,0px))/2)}
}
/* v0.8.8: middle-of-screen notices are quieter: a translucent pill and a softer control bar,
   readable at a glance but never a panel over the fight. */
#toast{background:rgba(10,20,32,.55);border:1px solid rgba(178,139,112,.25);box-shadow:none;padding:5px 12px;font-size:13px;font-weight:600;color:#ffe2d4;text-shadow:0 1px 2px #000,0 0 6px #000c}
#toast.on{opacity:.86}

/* v0.9.0: out-of-mana buttons turn blue-grey; mana shows as a thin strip under each frame's health. */
:is(#abil,#breakFreeSlot) .ab.oom{border-color:#5a7fd0}
:is(#abil,#breakFreeSlot) .ab.oom{filter:saturate(.25) brightness(.8)}
/* Execute's glow stays gold when it is short of rage or on cooldown: the dimming moves to the icon (Henry, 2026-10-30). */
:is(#abil,#breakFreeSlot) .ab.proc{filter:none;border-color:#ffe27a}
:is(#abil,#breakFreeSlot) .ab.proc:is(.oom,.bad) .ic{filter:saturate(.25) brightness(.8)}
.frame .bar .mp{position:absolute;left:0;bottom:0;height:3px;background:#5a93ff;z-index:1}
/* Energy shows gold where mana shows blue. */
.frame .bar .mp.en{background:#f2c94c}
/* 2026-10-29 hybrids: the meter (in its own colour) sits on a thin mana line on your own frame. */
.frame .bar .mp.dual{bottom:2px}
.frame .bar .mp2{position:absolute;left:0;bottom:0;height:2px;background:#5a93ff;z-index:1}
.frame:not(.me) .bar .mp.dual{bottom:0}

/* v0.9.4: Break Free has its own spot by the joystick: when you are controlled you cannot move, so the left
   thumb is free. It sits clear of where drags usually start (the dashed joystick hint) and pulses when it would
   free you. */
#breakFreeSlot{position:absolute;left:calc(env(safe-area-inset-left,0px) + 14px);bottom:calc(env(safe-area-inset-bottom,0px) + 14px);width:56px;height:56px;pointer-events:none;z-index:4}
#breakFreeSlot .ab{width:56px;height:56px;left:0;bottom:0}
#breakFreeSlot .ab .ic{width:22px;height:22px;transform:translateY(-7px)}
/* "Escape" sits in front of the cooldown dial (.cd, z-index 1), like the seconds left (.tx, z-index 3). */
#breakFreeSlot .ab .nm{font-size:8px;bottom:8px;padding:0 4px;z-index:3}
.large-controls #breakFreeSlot{transform:scale(1.12);transform-origin:bottom left}
/* Landscape (v0.9.18, Henry's playtest): the trinket sits low, just right of the joystick's resting spot.
   v0.9.21/22 (Henry): thumbs reach the screen edges badly, so the ability arc, the trinket and the joystick hint each
   sit 10% of the screen width closer to the middle. */
@media(orientation:landscape){
  #abil{right:calc(env(safe-area-inset-right,0px)*.4 + 6px + 10vw)}
  #breakFreeSlot{left:calc(env(safe-area-inset-left,0px) + 166px + 10vw);bottom:calc(env(safe-area-inset-bottom,0px)*.5 + 10px)}
  /* The two practice buttons sit side by side so the left edge stays free for Break Free. */
  #practiceTools{flex-direction:row}
}
/* Henry (2026-11-04): "Escape should be shinier when available". While it would free you it shines like a proc (the
   pulsing gold glow and the ring of gold sparks, procglow/procspin above), its icon brightens and a sheen sweeps across
   it. Steady with reduced motion. A ready flash (.flash::after) still plays over it. */
#breakFreeSlot .ab.urgent{border-color:#fff1b0;animation:procglow .9s ease-in-out infinite alternate}
#breakFreeSlot .ab.urgent::before{content:'';position:absolute;inset:0;border-radius:50%;pointer-events:none;z-index:2;
  background:repeating-conic-gradient(from 0deg,#ffc84a00 0deg,#ffc84a 22deg,#fff8d0 28deg,#ffc84a00 30deg);
  mask:radial-gradient(closest-side,transparent calc(100% - 7px),#000 calc(100% - 6px));
  -webkit-mask:radial-gradient(closest-side,transparent calc(100% - 7px),#000 calc(100% - 6px));
  filter:drop-shadow(0 0 3px #ffb347);animation:procspin 2.4s linear infinite}
#breakFreeSlot .ab.urgent .ic{filter:brightness(1.18) drop-shadow(0 0 5px #ffd36b)}
#breakFreeSlot .ab.urgent:not(.flash)::after{content:'';position:absolute;inset:0;border-radius:50%;pointer-events:none;z-index:2;
  background:linear-gradient(110deg,transparent 40%,#ffffffc0 50%,transparent 60%) no-repeat;background-size:300% 100%;animation:escsheen 1.8s ease-in-out infinite}
@keyframes escsheen{0%,30%{background-position:100% 0}80%,100%{background-position:0 0}}
@media(prefers-reduced-motion:reduce){#breakFreeSlot .ab.urgent{animation:none;box-shadow:0 0 0 3px #fff3b0,0 0 18px 6px #ffb347}
  #breakFreeSlot .ab.urgent::before{animation:none}#breakFreeSlot .ab.urgent:not(.flash)::after{animation:none;background:none}}
/* v0.9.5: Eclipse evolves Warlock's abilities in place; touch targets and cooldowns never move. */
#abil .ab.evolved{outline:2px solid #b18fd4;outline-offset:1px}
#abil .ab.evolved .pot{color:#f2d6ff;letter-spacing:.04em;font-size:8px}

/* v0.9.7: arena frames are always on. Your team stacks down the left, the enemy team down the right (flush to the corner since v0.9.20, with Pause by the clock),
   nearer the right thumb. Each frame's layout is described with its rules below. Tapping a frame targets that
   character, or makes an ally the heal target. Translucent, so the arena shows through. */
#hud #center{top:calc(env(safe-area-inset-top,0px) + 8px)}
#hud .frames{display:flex;flex-direction:column;gap:5px;width:var(--frame-w,168px);max-width:none}
#hud #allies{left:calc(env(safe-area-inset-left,0px) + 8px);right:auto;top:calc(env(safe-area-inset-top,0px) + var(--frame-top-a,8px))}
#hud #enemies{right:calc(env(safe-area-inset-right,0px) + 8px);left:auto;top:calc(env(safe-area-inset-top,0px) + var(--frame-top-e,8px))}
/* v0.9.17, WoW arena-addon style (sArena, Gladius): every frame is the same height. Top row: the class icon (covered
   by control with its time left), the health bar and the PvP Trinket. Under it, the aura row: type-coloured icons with
   whole-second timers, then diminishing returns. */
#hud .frame{--row:calc(var(--frame-bar,19px) + 6px);display:grid;grid-template-columns:var(--row) minmax(0,1fr) var(--row);grid-template-rows:var(--row) 15px;column-gap:5px;row-gap:3px;align-items:center;flex:none;width:auto;height:auto;min-height:0;padding:4px 5px 4px 8px;border:1px solid #a9c0cc3d;border-radius:8px;background:rgba(10,20,32,.42);box-shadow:none}
#hud .frame .gl{position:relative;width:var(--row);height:var(--row);border-radius:6px;display:grid;place-items:center;background:#050d1680;color:var(--class-fill,var(--cc))}
#hud .frame .gl>svg{width:17px;height:17px}
#hud .frame .bar{grid-column:2;height:var(--row);margin:0;border-radius:4px}
#hud .frame .bar .nm,#hud .frame .bar b{line-height:var(--row)}
#hud .frame .gl .cc{display:none;position:absolute;inset:-1px;border-radius:6px;place-items:center;background:#3b4b5c;border:2px solid currentColor;overflow:hidden}
#hud .frame.cc-on .gl .cc{display:grid}
#hud .frame.hardcc .gl .cc{box-shadow:0 0 9px currentColor}
#hud .frame .gl .cc svg{position:absolute;top:2px;left:50%;width:13px;height:13px;transform:translateX(-50%);color:#fff;filter:drop-shadow(0 1px 1px #000a)}
#hud .frame .gl .cc b{position:absolute;left:0;right:0;bottom:0;text-align:center;font-size:11px;line-height:12px;font-weight:850;color:#fff;font-variant-numeric:tabular-nums;text-shadow:0 0 2px #000,0 1px 2px #000}
#hud .frame .tk{position:relative;width:var(--row);height:var(--row);border-radius:6px;display:grid;place-items:center;background:#9c6b1f;border:1.5px solid #ffe6a3;color:#fff;overflow:hidden}
#hud .frame .tk svg{width:15px;height:15px}
#hud .frame .tk i{position:absolute;inset:0}
#hud .frame .tk b{position:absolute;inset:0;display:grid;place-items:center;font-size:10.5px;font-weight:850;color:#fff;font-variant-numeric:tabular-nums;text-shadow:0 0 2px #000,0 0 3px #000}
#hud .frame .tk.spent{background:#2a3540;border-color:#55636d;color:#8593a0}
#hud .frame .bf,#hud .frame .bf:empty{grid-column:1/-1;display:flex;gap:3px;height:15px;margin:0;padding:0 1px;overflow:hidden}
#hud .frame .bf .au{position:relative;display:flex;align-items:center;gap:1px;width:auto;height:15px;padding:0 3px 0 2px;border-radius:3px;background:var(--bg,#3b4b5c);border:1.5px solid var(--au);color:#fff;flex:none}
#hud .frame .bf .au svg{width:10px;height:10px;flex:none;filter:drop-shadow(0 1px 1px #0009)}
#hud .frame .bf .au b{font-size:9.5px;line-height:1;font-weight:850;color:#fff;font-variant-numeric:tabular-nums;text-shadow:0 1px 1px #0009}
#hud .frame .bf .au sub{position:static;margin-left:1px;font-size:8px;line-height:1;font-weight:850;color:#fff;text-shadow:0 1px 1px #0009}
/* v0.9.18: teammate and enemy frames add a third row, their key cooldowns: bright in the ability's colour when ready,
   dark with the time left while spent. Your own frame has no cooldown row; its auras are bigger instead. */
#hud .frame:not(.me){grid-template-rows:var(--row) 15px 18px}
#hud .frame .cds{grid-column:1/-1;display:flex;gap:3px;height:18px;overflow:hidden}
#hud .frame .cds span{position:relative;width:18px;height:18px;border-radius:4px;display:grid;place-items:center;background:var(--bg);border:1px solid #0b1622cc;color:#fff;flex:none}
#hud .frame .cds svg{width:12px;height:12px;filter:drop-shadow(0 1px 1px #0009)}
#hud .frame .cds span.spent{background:color-mix(in srgb,var(--bg) 30%,#0b141c);color:#ffffff59}
#hud .frame .cds b{position:absolute;inset:0;display:grid;place-items:center;font-size:9.5px;font-weight:850;color:#fff;font-variant-numeric:tabular-nums;text-shadow:0 0 2px #000,0 0 3px #000}
#hud .frame.me{grid-template-rows:var(--row) 21px}
#hud .frame.me .bf,#hud .frame.me .bf:empty{height:21px}
#hud .frame.me .bf .au{height:21px;padding:0 4px 0 3px;gap:2px;border-width:2px;border-radius:4px}
#hud .frame.me .bf .au svg{width:14px;height:14px}
#hud .frame.me .bf .au b{font-size:12px}
#hud .frame.me .bf .au sub{font-size:9.5px}
.au.magic{--au:#7cc0ff}.au.curse{--au:#d39bff}.au.phys{--au:#ff6b5e}.au.help{--au:#9ff5b8}
/* The selected enemy and heal target stand out: a thick bright border, a glow and a warmer fill. */
#hud .frame.tgtE{border:2px solid #ffd76a;padding:3px 5px 3px 8px;background:rgba(66,50,12,.62);box-shadow:0 0 0 1px #000a,0 0 12px #ffd76a99}
#hud .frame.tgtA{border:2px solid #7dffb0;padding:3px 5px 3px 8px;background:rgba(14,56,38,.6);box-shadow:0 0 0 1px #000a,0 0 12px #7dffb080}
#hud .frame.dead{opacity:.5}
/* Henry (2026-11-04): enemy frames stay solid out of reach or behind a pillar; only the dashed outline on the bar says so.
   Teammate frames still dim (a healer reads range from them). */
#hud .frame.enemy.oor{opacity:1}
/* Training: the meter sits under the clock, and the practice tools below your frames. */
#center #meter{left:50%;transform:translateX(-50%);white-space:nowrap}
body.show-frames #practiceTools{top:calc(env(safe-area-inset-top,0px) + 116px)}
/* Portrait: the clock row first, then both teams side by side (yours left, enemies right). */
@media(orientation:portrait){
  #hud .frames{width:var(--frame-w,calc(50% - 12px))}
  #hud #allies{top:calc(env(safe-area-inset-top,0px) + var(--frame-top-a,58px))}
  #hud #enemies{top:calc(env(safe-area-inset-top,0px) + var(--frame-top-e,58px))}
  #hud #allies{left:8px}
  #hud #enemies{right:8px}
  #center #meter{left:0;top:4px;transform:none}
  body.show-frames #practiceTools{top:calc(env(safe-area-inset-top,0px) + 202px);flex-direction:row}
}
/* Experimental frame tuner (Pause → Frames): a compact panel at the bottom middle while the match stays paused. */
#frameTuner{position:absolute;left:50%;bottom:calc(env(safe-area-inset-bottom,0px) + 10px);transform:translateX(-50%);z-index:7;width:min(300px,calc(100% - 24px));display:grid;gap:6px;padding:10px 12px;border:1px solid #79989f80;border-radius:12px;background:rgba(12,24,38,.9);pointer-events:auto;font-size:11px;color:#dce9e5}
#frameTuner strong{font-size:12px}#frameTuner small{font-weight:400;color:#9fb3bb}
#frameTuner label{display:grid;grid-template-columns:118px 1fr 44px;align-items:center;gap:6px}
#frameTuner input{width:100%;margin:0;min-height:28px}#frameTuner output{text-align:right;font-variant-numeric:tabular-nums}
#frameTuner .tune-actions{display:flex;gap:8px;justify-content:flex-end}#frameTuner .tune-group{display:grid;gap:6px}
#frameTuner .tune-tabs{display:grid;grid-template-columns:1fr 1fr 1fr;gap:6px}#frameTuner .tune-tabs button{min-width:0;font-size:12px}
#frameTuner .tune-tabs button[aria-pressed="true"]{background:#2b5a63;border-color:#9fd6cf;color:#fff}
#frameTuner .tune-group{display:none}
#frameTuner[data-tab="frames"] .tune-group[data-group="frames"],#frameTuner[data-tab="buttons"] .tune-group[data-group="buttons"],#frameTuner[data-tab="hud"] .tune-group[data-group="hud"]{display:grid}
#frameTuner[data-tab="buttons"]{top:calc(env(safe-area-inset-top,0px) + 58px);bottom:auto}
/* Cast & alerts: the panel stays at the bottom in portrait (over the buttons) and moves to the right edge in landscape,
   clear of your character, the alert and the cooldown tracker. */
@media(orientation:landscape){#frameTuner[data-tab="hud"]{left:auto;right:calc(env(safe-area-inset-right,0px) + 12px);transform:none}}
#frameTuner button{min-height:40px;min-width:76px;border-radius:10px;border:1px solid var(--ui-rim);background:#172c40;color:#e0ece7}

/* v0.9.13: Eclipse at a glance. A violet ring around Thread fills as curses tick and brightens when nearly full; while
   Eclipse lasts it turns pale, pulses and drains, and the screen edge flashes once as it starts. Every Warlock's frame
   carries the same charge as a strip along the top of its health bar, so an enemy Eclipse can be seen coming. */
#abil .eclipse-ring{position:absolute;right:-7px;bottom:-7px;width:94px;height:94px;border-radius:50%;pointer-events:none;
  mask:radial-gradient(circle closest-side,transparent calc(100% - 4.5px),#000 calc(100% - 4px));-webkit-mask:radial-gradient(circle closest-side,transparent calc(100% - 4.5px),#000 calc(100% - 4px))}
#abil .eclipse-ring.ready{filter:brightness(1.4) saturate(1.3)}
#abil.eclipse-on .eclipse-ring{animation:eclipseRing 1.1s ease-in-out infinite}
@keyframes eclipseRing{50%{filter:brightness(.7)}}
#abil.eclipse-on .ab.evolved{box-shadow:0 0 14px #b18fd4aa}
#eclipseFlash{position:fixed;inset:0;pointer-events:none;opacity:0;box-shadow:inset 0 0 70px 18px #b98cffcc;z-index:1}
#eclipseFlash.on{animation:eclipseFlash 1.4s ease-out}
@keyframes eclipseFlash{12%{opacity:1}100%{opacity:0}}
@media(prefers-reduced-motion:reduce){#abil.eclipse-on .eclipse-ring{animation:none;filter:brightness(1.2)}#eclipseFlash.on{animation-duration:.8s}}
.frame .bar .ec{position:absolute;left:0;top:0;height:3px;background:#a77fd6;z-index:1;transition:width .2s}
.frame .bar .ec.on{background:#f3e2ff;box-shadow:0 0 5px #d9b8ff;transition:none}

/* Diminishing-returns step colours: green half, amber quarter, red immune. */
.dr1{--dr:#8fe07a}.dr2{--dr:#ffc857}.dr3{--dr:#ff6b6b}


/* Readable effects: full-width aura lane, then a reserved DR lane only while needed.
   DR wraps at the narrowest custom frame widths; buffs never compete with it. */
#hud .frame,#hud .frame.me{grid-template-rows:var(--row) auto}
#hud .frame:not(.me){grid-template-rows:var(--row) auto 18px}
#hud .frame .bf,#hud .frame .bf:empty,#hud .frame.me .bf,#hud .frame.me .bf:empty{height:auto;min-height:22px;display:flex;flex-direction:column;gap:3px;overflow:visible;min-width:0}
#hud .frame .bf .auras{display:flex;gap:3px;min-height:22px;min-width:0}
#hud .frame .bf .au,#hud .frame.me .bf .au{box-sizing:border-box;width:34px;height:22px;padding:1px 2px;gap:2px;border-width:1px;border-radius:4px}
#hud .frame .bf .au.stacked{width:52px}
#hud .frame .bf .au svg,#hud .frame.me .bf .au svg{width:14px;height:14px}
#hud .frame .bf .au b,#hud .frame.me .bf .au b{font-size:10px}
#hud .frame .bf .au sub,#hud .frame.me .bf .au sub{font-size:9px;margin:0;background:#101621cc;padding:2px 1px;border-radius:2px}
#hud .frame .bf .au.expiring{border-color:#fff1b3;box-shadow:inset 0 -2px #fff1b3}
#hud .frame .bf .au[data-aura="bloom"]{gap:1px}
#hud .frame .bf .bloom-dots{display:flex;align-items:center;justify-content:center;gap:1px;width:17px;height:9px;flex:none}
#hud .frame .bf .bloom-dots i{position:static;inset:auto;display:block;flex:none;width:5px;height:5px;border-radius:50%;background:var(--bg);box-shadow:0 0 0 1px #050d16}
#hud .frame .bf .au.expiring .bloom-dots i{box-shadow:0 0 0 1px #050d16,0 0 0 2px #fff1b3}
#hud .frame .bf .bloom-dots.blink{animation:lifebloom-blink 1s steps(1,end) infinite}
@keyframes lifebloom-blink{0%,100%{opacity:1}50%{opacity:.3}}
@media(prefers-reduced-motion:reduce){#hud .frame .bf .bloom-dots.blink{animation:none}}
#hud .frame .bf .aura-more{width:24px;flex:none;display:grid;place-items:center;border:1px solid #96a9b5;border-radius:4px;color:#fff;background:#142432;font-size:10px;font-weight:800}

/* v0.10.9 (Henry): sArena-style frames without the tile. The class icon faces the middle of the screen (enemies:
   icon, bar, trinket; teammates mirrored: trinket, bar, icon) and the diminishing returns float outside the frame
   beside it, in one row growing away from it. The frame keeps its padding as tap area; the selected frame's
   health bar glows instead of the tile. */
#hud .frame,#hud .frame.tgtE,#hud .frame.tgtA{padding:4px 0;border:0;border-radius:0;background:none;box-shadow:none}
#hud .frame{--icon:calc(var(--row) + 6px);grid-template-columns:var(--icon) minmax(0,1fr) var(--row)}
#hud .frame.ally{grid-template-columns:var(--row) minmax(0,1fr) var(--icon)}
#hud .frame::before{display:none}
#hud .frame.ally .gl{grid-column:3;grid-row:1}
#hud .frame.ally .tk{grid-column:1;grid-row:1}
#hud .frame .bar{box-shadow:0 0 0 1px #050d16b3,0 2px 5px #0006}
#hud .frame.tgtE .bar{box-shadow:0 0 0 2px #ffd76a,0 0 0 3px #000a,0 0 12px #ffd76acc}
#hud .frame.tgtA .bar{box-shadow:0 0 0 2px #7dffb0,0 0 0 3px #000a,0 0 12px #7dffb0b3}
/* Class icon, BigDebuffs-style: the covering effect's icon fills it, a dial shades the time left, the time sits on top. */
#hud .frame .gl{width:var(--icon);height:var(--icon);margin:-3px 0;border-radius:7px;box-shadow:0 0 0 1px #050d16b3}
#hud .frame .gl>svg{width:20px;height:20px}
#hud .frame .gl .cc{border-radius:7px}
#hud .frame .gl .cc .ci{position:absolute;inset:0;display:grid;place-items:center}
#hud .frame .gl .cc .ci svg{position:static;width:22px;height:22px;transform:none;opacity:.9}
#hud .frame .gl .cc i{position:absolute;inset:0}
#hud .frame .gl .cc b{inset:0;display:grid;place-items:center;font-size:12.5px;line-height:1;text-shadow:0 0 2px #000,0 0 3px #000,0 1px 2px #000}
#hud .frame.bigbuff .gl .cc{box-shadow:0 0 7px currentColor}
/* Diminishing returns: a little smaller than the class icon, step-coloured border, reset dial, no text. */
#hud .frame .drs{position:absolute;top:4px;height:var(--row);display:flex;align-items:center;gap:3px;pointer-events:none}
#hud .frame.enemy .drs{right:calc(100% + 4px);flex-direction:row-reverse}
#hud .frame.ally .drs{left:calc(100% + 4px)}
#hud .frame .dr{box-sizing:border-box;position:relative;flex:none;width:var(--row);height:var(--row);display:grid;place-items:center;border:2px solid var(--dr);border-radius:5px;background:#050d16d9;color:#fff;overflow:hidden;box-shadow:0 1px 3px #0008}
#hud .frame .dr svg{width:15px;height:15px}
#hud .frame .dr i{position:absolute;inset:0}
/* Portrait has no room beside the frames: the diminishing returns take their own row at the bottom, from the icon side. */
@media(orientation:portrait){
  #hud .frame .drs{position:static;grid-column:1/-1;grid-row:4;height:auto}
  #hud .frame .drs:empty{display:none}
  #hud .frame.ally .drs{flex-direction:row-reverse}
  #hud .frame.enemy .drs{flex-direction:row}
}
/* Enemy frames carry no aura row (their effects are on their nameplates): bar, then the cooldown row. */
#hud .frame.enemy{grid-template-rows:var(--row) 18px}
/* v0.10.9 (Henry): the match clock is a small translucent label, not a panel; Pause moves in beside it. */
#center #clock{height:auto;min-width:0;line-height:16px;padding:2px 8px;border:0;border-radius:8px;background:#0a141f66;box-shadow:none;color:#f5edda;opacity:.85;font-size:12px;font-weight:750;top:4px}
#center #pauseBtn{left:calc(50% + 26px)}
#center #pauseBtn{top:-8px;border:0;border-radius:50%;background:radial-gradient(circle,#0a141f80 0 14px,transparent 15px);box-shadow:none;font-size:11px;color:#f5edda;opacity:.85}

/* #156: an enemy's cast or channel covers its cooldown row while it lasts (no layout shift): gold fill with the
   spell name and seconds left; channels show where later pulses land. */
#hud .frame .fc{display:none;position:absolute;left:0;right:0;top:calc(4px + var(--row) + 3px);height:18px;border-radius:4px;background:#3b2c0c;box-shadow:0 0 0 1px #050d16,0 0 8px #ffc23d66;overflow:hidden;pointer-events:none;z-index:2}
#hud .frame.fcast .fc{display:block}
#hud .frame .fc i{position:absolute;left:0;top:0;bottom:0;width:0;background:#ffc23d}
#hud .frame .fc b{position:absolute;inset:0;padding:0 34px 0 5px;font-size:11px;line-height:18px;font-weight:850;color:#fff;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;text-shadow:0 0 2px #000,0 1px 2px #000}
#hud .frame .fc s{position:absolute;right:4px;top:0;font-size:10.5px;line-height:18px;font-weight:850;color:#fff;text-decoration:none;font-variant-numeric:tabular-nums;text-shadow:0 0 2px #000,0 1px 2px #000}

/* #171 (Henry, 2026-10-27): class-coloured health, like WoW arena frames. The fill takes --class-fill, which buildHUD points
   at the --class-<key> variables it sets on #hud from CLASS_COLOURS (index.html). The bar's rim keeps the team colour, so
   friend and enemy still read at a glance; the selected-target glow above is unchanged and wins over the rim. Names and
   numbers carry a dark outline that reads on white, yellow and the dark track alike; low health turns the empty track red. */
#hud .frame.ally{--team:#3fd27a}
#hud .frame.enemy{--team:#ff3b30}
#hud .frame .bar{background:#141b26;box-shadow:0 0 0 2px var(--team,#a9c0cc),0 0 0 3px #050d16cc,0 2px 5px #0006}
#hud .frame .bar i{background:linear-gradient(#ffffff3d,#ffffff00 45%,#00000026),var(--class-fill,#48e27c)}
#hud .frame .bar .nm,#hud .frame .bar>b{color:#fff;text-shadow:-1px -1px 0 #050d16,1px -1px 0 #050d16,-1px 1px 0 #050d16,1px 1px 0 #050d16,0 0 3px #050d16}
#hud .frame.low .bar{background:#6a1420;animation:frame-low .8s ease-in-out infinite}
#hud .frame.low .bar i{animation:none;filter:none}
@keyframes frame-low{50%{background:#9a1c2a}}
@media(prefers-reduced-motion:reduce){#hud .frame.low .bar{animation:none}}

/* Henry (2026-10-28): your teammate's key cooldowns sit in a row above its bar, so its health bar sits right on top of
   yours. Enemy frames carry no cooldown row; their 18px lane stays for the cast strip (#156). */
#hud .frame.ally:not(.me){grid-template-rows:18px var(--row) auto}
#hud .frame.ally:not(.me) .cds{grid-row:1}
#hud .frame.ally:not(.me) .gl,#hud .frame.ally:not(.me) .tk,#hud .frame.ally:not(.me) .bar{grid-row:2}
#hud .frame.ally:not(.me) .bf{grid-row:3}
#hud .frame.ally:not(.me) .drs{top:calc(4px + 18px + 3px)}

/* Your cast bar, WoW-style: centred just under your character (updateHUD places it), above every nameplate and button,
   only while you cast. Same reading as the enemy frame strip: gold fill and channel ticks. */
#hud #pcast{position:absolute;z-index:60;width:98px;height:18px;transform:translateX(-50%);border-radius:4px;background:#3b2c0ce6;box-shadow:0 0 0 1.5px #050d16,0 0 10px #ffc23d66;overflow:hidden;pointer-events:none}
#hud #pcastFail{position:absolute;z-index:60;transform:translateX(-50%);font-size:11px;line-height:13px;font-weight:850;color:#ff9f7a;text-shadow:0 1px 2px #000,0 0 3px #000;white-space:nowrap;pointer-events:none}
#hud #pcast i{position:absolute;left:0;top:0;bottom:0;width:0;background:#ffc23d}
#hud #pcast b{position:absolute;inset:0;padding:0 34px 0 6px;font-size:11px;line-height:18px;font-weight:850;color:#fff;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;text-shadow:0 0 2px #000,0 1px 2px #000}
/* Combo points under you, where your cast bar shows (#pcp). */
#hud #pcp{position:absolute;z-index:60;transform:translateX(-50%);display:flex;align-items:center;gap:6px;padding:4px 8px;border-radius:9px;background:#050d16b3;pointer-events:none}
#hud #pcp span{width:10px;height:10px;transform:rotate(45deg);background:#3a3f46;border:1px solid #050d16}
#hud #pcp span.lit{background:#ffd76a;box-shadow:0 0 5px #ffd76a}
#hud #pcp.arcane span.lit{background:#d59bff;box-shadow:0 0 5px #d59bff}
#hud #pcp span.off{display:none}
#hud #pcast s{position:absolute;right:5px;top:0;font-size:10.5px;line-height:18px;font-weight:850;color:#fff;text-decoration:none;font-variant-numeric:tabular-nums;text-shadow:0 0 2px #000,0 1px 2px #000}

/* OmniCC-style enemy cooldown tracker just below the screen centre: translucent icons (rimmed in the owner's colour)
   with big time-left numbers, only while a 30s+ cooldown runs. Never takes a touch. */
#hud #cdTrack{position:absolute;left:calc(50% + var(--track-x,0px));top:calc(40% - 14px - var(--track-y,0px));transform:translate(-50%,calc(28px - 100%));display:flex;flex-direction:column-reverse;align-items:center;gap:4px;pointer-events:none}
#hud #cdTrack>div{display:flex;gap:4px}
/* The interrupt row (Henry, 2026-11-04) stacks above the big cooldowns, so the tracker grows away from the control alert
   under it; the big row keeps its place (28px tall even while empty). */
#hud #cdTrack>.big{min-height:28px}
#hud #cdTrack span{position:relative;width:28px;height:28px;border-radius:5px;display:grid;place-items:center;background:var(--bg);border:1.5px solid var(--cc);color:#fff;opacity:.6}
#hud #cdTrack svg{width:18px;height:18px;margin-top:-7px;filter:drop-shadow(0 1px 1px #0009)}
#hud #cdTrack b{position:absolute;left:0;right:0;bottom:0;text-align:center;font-size:11px;line-height:12px;font-weight:900;color:#fff;font-variant-numeric:tabular-nums;text-shadow:0 0 2px #000,0 0 3px #000,0 1px 2px #000}

/* Raid-frame auras (Settings > Teammate auras, on the bar by default since 0.10.81; Enemy auras > On the bar too, off by
   default): the bars grow to --barh (twice the frame bar plus 10px; the frame bar starts at 20px in landscape, so 50px)
   and the aura row goes. Buffs sit in the bar's top-right corner growing left, debuffs in its bottom-left corner growing
   right, each a third of the bar's height (Henry, 2026-10-29); name and health stay centred between. */
@media (orientation:landscape){body{--frame-bar:20px}}
body.auras-on-bar #hud .frame.ally,body.enemy-auras-on-bar #hud .frame.enemy{--barh:calc(var(--frame-bar,19px)*2 + 10px)}
body.auras-on-bar #hud .frame.ally{grid-template-rows:auto}
body.auras-on-bar #hud .frame.ally:not(.me){grid-template-rows:18px auto}
body.enemy-auras-on-bar #hud .frame.enemy{grid-template-rows:auto 18px}
body.auras-on-bar #hud .frame.ally .bar,body.enemy-auras-on-bar #hud .frame.enemy .bar{height:var(--barh)}
body.auras-on-bar #hud .frame.ally .bar .nm,body.auras-on-bar #hud .frame.ally .bar>b,
body.enemy-auras-on-bar #hud .frame.enemy .bar .nm,body.enemy-auras-on-bar #hud .frame.enemy .bar>b{line-height:var(--barh)}
body.auras-on-bar #hud .frame.ally .bf{display:none}
/* An enemy's cast strip sits in the row under its taller bar, clear of the debuff icons (Codex on #223). */
body.enemy-auras-on-bar #hud .frame.enemy .fc{top:calc(4px + var(--barh) + 3px)}
body.auras-on-bar #hud .frame.ally:not(.me) .drs{top:calc(4px + 18px + 3px + (var(--barh) - var(--row))/2)}
body.auras-on-bar #hud .frame.ally.me .drs{top:calc(4px + (var(--barh) - var(--row))/2)}
#hud .frame .ob{display:none}
body.auras-on-bar #hud .frame.ally .ob,body.enemy-auras-on-bar #hud .frame.enemy .ob{display:block;position:absolute;inset:0;z-index:2;pointer-events:none;--obs:calc(var(--barh)/3)}
#hud .frame .ob .obuff,#hud .frame .ob .odebuff{position:absolute;display:flex;gap:1px}
#hud .frame .ob .obuff{top:1px;right:1px;flex-direction:row-reverse}
#hud .frame .ob .odebuff{bottom:1px;left:1px}
#hud .frame .ob .au{position:relative;box-sizing:border-box;width:var(--obs);height:var(--obs);display:grid;place-items:center;border-radius:2px;background:var(--bg,#3b4b5c);border:1px solid #050d16;color:#fff;overflow:hidden}
#hud .frame .ob .au.magic{border-color:#3b8cff}#hud .frame .ob .au.curse{border-color:#b35cff}#hud .frame .ob .au.phys{border-color:#ff4b4b}
#hud .frame .ob .au.expiring{border-color:#fff1b3}
#hud .frame .ob .au svg{width:80%;height:80%}
#hud .frame .ob .au .dl{position:absolute;inset:0}
#hud .frame .ob .au sup{position:absolute;right:0;bottom:-1px;font-size:7px;line-height:1;font-weight:900;color:#fff;text-shadow:0 0 2px #000}

/* Henry (2026-10-28): arena frames carry no name or health text (the class icon and the fill say it). Only enemy frames
   keep the trinket square; your teammate's trinket leads its cooldown row, and yours is the break-free button. Team
   frames are bar then class icon. */
#hud .frame .bar .nm,#hud .frame .bar>b{display:none}
#hud .frame.ally{grid-template-columns:minmax(0,1fr) var(--icon)}
#hud .frame.ally .bar{grid-column:1}
#hud .frame.ally .gl{grid-column:2}

/* Loss of control, WoW-style, over your character (updateHUD places it), under the enemy cooldown tracker: the controlling ability's icon with a dial and the time left, a thin red line
   either side, and its type in small text above it (12px line + 2px gap, so the lines sit at 14 + 22px). The Escape button sits at your feet while it could free you. */
#hud #loc{position:absolute;transform:translateX(-50%) scale(1.5);transform-origin:top center;display:flex;flex-direction:column-reverse;align-items:center;gap:2px;pointer-events:none;z-index:5}
#hud #loc::before,#hud #loc::after{content:'';position:absolute;top:36px;width:56px;height:2px;background:linear-gradient(90deg,transparent,#ff3b30cc)}
#hud #loc::before{right:calc(50% + 28px)}
#hud #loc::after{left:calc(50% + 28px);transform:scaleX(-1)}
#hud #loc .li{position:relative;width:44px;height:44px;border-radius:7px;display:grid;place-items:center;border:2px solid #ff3b30;box-shadow:0 0 12px #ff3b3080,0 2px 6px #000a;color:#fff;overflow:hidden}
#hud #loc .lic{display:grid;place-items:center}
#hud #loc .lic svg{width:28px;height:28px;filter:drop-shadow(0 1px 1px #000a)}
#hud #loc .li i{position:absolute;inset:0}
#hud #loc .li b{position:absolute;inset:0;display:grid;place-items:center;font-size:15px;font-weight:900;color:#fff;font-variant-numeric:tabular-nums;text-shadow:0 0 2px #000,0 0 3px #000,0 1px 2px #000}
#hud #loc .lt{font-size:10px;line-height:12px;font-weight:800;letter-spacing:.06em;text-transform:uppercase;color:#ffd2cc;white-space:nowrap;text-shadow:0 0 2px #000,0 1px 2px #000}
/* Henry (2026-11-04): the alert (above) and Escape are 50% bigger, Escape level with the alert's icon on its left. */
#hud #breakFreeSlot{bottom:auto;transform:translateX(-50%) scale(1.2);transform-origin:top center;z-index:6}
.large-controls #hud #breakFreeSlot{transform:translateX(-50%) scale(1.35)}
/* Swipe casting (Henry, 2026-10-29): arena numbers on enemy frames, the drag label and the matching frame's highlight. */
#hud .frame.enemy{position:relative}
#hud .frame .arena-no{position:absolute;left:-6px;top:-6px;z-index:3;min-width:15px;height:15px;padding:0 3px;border-radius:8px;display:grid;place-items:center;background:#050d16e6;border:1.5px solid #f2c14ecc;color:#ffe9b0;font-size:10px;line-height:1;font-weight:900;font-variant-numeric:tabular-nums;pointer-events:none}
#hud .frame.swipe-pick{outline:3px solid #f2c14e;outline-offset:1px;background:rgba(242,193,78,.22)}
#hud .frame.swipe-pick .arena-no{background:#f2c14e;color:#050d16;border-color:#fff}
#swipeHint{position:fixed;z-index:40;pointer-events:none;transform:translate(-50%,-100%);padding:5px 10px;border-radius:9px;background:#050d1699;border:2px solid var(--hint-color,#f2c14e);opacity:.9;color:#fff;text-align:center;white-space:nowrap;box-shadow:0 2px 10px #000a;text-shadow:0 1px 2px #000}
#swipeHint b{display:block;font-size:14px;line-height:17px;font-weight:900;letter-spacing:.02em}
#swipeHint small{display:block;margin-top:1px;font-size:11px;line-height:13px;font-weight:800;color:#ffb8a8}
#swipeHint.bad{border-color:#ff8a7a}
#swipeHint:not(.armed){opacity:.6;border-style:dashed}
#swipeHint.hidden{display:none}
@media (prefers-reduced-motion:no-preference){#swipeHint:not(.hidden){animation:swipe-hint .12s ease-out}}
@keyframes swipe-hint{from{opacity:0;transform:translate(-50%,-90%)}to{opacity:1;transform:translate(-50%,-100%)}}
/* Painted icon art (icon-art.js, Henry 2026-11-03): each icon is re-fitted to its own content (the art files themselves) so it fills the
   button's circle; the rim keeps the ability's colour and the name gets a heavier shadow over the art. */
:is(#abil,#breakFreeSlot) .ab:has(>.ic>svg.art){background:#0e0e0e}
#hud :is(#abil,#breakFreeSlot) .ab:has(>.ic>svg.art) .ic,#breakFreeSlot .ab:has(>.ic>svg.art) .ic{width:100%;height:100%;transform:none}
:is(#abil,#breakFreeSlot) .ab .ic>svg.art{width:100%;height:100%;clip-path:circle(50%)}
:is(#abil,#breakFreeSlot) .ab:has(>.ic>svg.art) .nm{text-shadow:0 0 2px #000,0 1px 3px #000,0 0 6px #000e}
/* Painted art (icon-art.js): the class icon fills its frame box; aura chips show their ability art with rounded corners. */
#hud .frame .gl>svg.art{width:100%;height:100%;clip-path:inset(0 round 6px)}
#hud .frame .bf .au svg.art{width:16px;height:16px;clip-path:inset(0 round 3px);filter:none}
#hud .frame .ob .au svg.art{width:100%;height:100%;clip-path:inset(0 round 3px)}
#hud .frame .dr svg.art{width:100%;height:100%;clip-path:inset(0 round 3px)}
#hud .frame .gl .cc .ci svg.art{width:100%;height:100%;opacity:1;clip-path:inset(0 round 6px)}

/* Warrior's combined slot: a readable sheen when Execute is actually usable. */
#abil .ab.execute-ready:not(.flash)::after{content:'';position:absolute;inset:3px;border-radius:50%;pointer-events:none;background:linear-gradient(115deg,transparent 30%,#fff4c080 48%,transparent 66%);background-size:260% 100%;animation:execute-sheen 1.8s ease-in-out infinite;z-index:1}
#abil .ab.execute-ready .nm{color:#fff2bd;text-shadow:0 1px 3px #000,0 0 7px #ff9d36}
@keyframes execute-sheen{0%,20%{background-position:160% 0}80%,100%{background-position:-60% 0}}
@media(prefers-reduced-motion:reduce){#abil .ab.execute-ready:not(.flash)::after{animation:none;background-position:50% 0;opacity:.35}}

/* Earth Shock: a sustained gold rim and restrained sheen while it can actually be cast.
   No pop/chime on each GCD; a steady rim also carries the cue with Screen effects off. */
#abil .ab.earth-shock-ready{border-color:#fff0a6;box-shadow:0 0 0 2px #ffd66d,0 0 14px 4px #ffb347bb,inset 0 0 9px #ffe39199}
#abil .ab.earth-shock-ready::before{content:'';position:absolute;inset:3px;border:2px solid #ffeab0;border-radius:50%;pointer-events:none;z-index:2}
#abil .ab.earth-shock-ready::after{content:'';position:absolute;inset:5px;border-radius:50%;pointer-events:none;background:linear-gradient(115deg,transparent 30%,#fff4c080 48%,transparent 66%);background-size:260% 100%;animation:execute-sheen 2.4s ease-in-out infinite;z-index:1}
#abil .ab.earth-shock-ready .nm{color:#fff2bd;text-shadow:0 1px 3px #000,0 0 5px #ff9d36}
#abil .ab.earth-shock-ready.earth-shock-calm::after{animation:none;background:none}
@media(prefers-reduced-motion:reduce){#abil .ab.earth-shock-ready::after{animation:none;background:none}}

/* Banked resource casts: a small dark badge, separate from central cooldowns and proc/wound hints. */
#abil .ab .casts{position:absolute;right:15%;top:15%;z-index:6;min-width:15px;height:15px;padding:0 2px;box-sizing:border-box;border:1px solid #fff1b0;border-radius:5px;background:#142235;color:#fff1b0;font-size:11px;line-height:13px;font-weight:900;font-variant-numeric:tabular-nums;text-align:center;text-shadow:0 1px 1px #000;pointer-events:none}
#abil .ab:has(.casts:not(:empty)) .pot{left:12%;width:44%;font-size:7px;letter-spacing:0}
#abil .ab .casts:empty{display:none}
#abil .ab.casts-blocked .casts{border-color:#8d9baa;color:#d6dfe9;background:#202b38}

/* #162 live DPS/HPS meter: under your team's frames (left/top set by paintLiveMeter), never a touch target. */
#liveMeter{position:absolute;z-index:3;pointer-events:none;display:grid;gap:2px;padding:4px 6px 3px;border-radius:7px;background:#050d16b8;color:#eef4f2;font-size:10.5px;font-variant-numeric:tabular-nums;line-height:1.15;box-shadow:0 3px 10px #0004}
#liveMeter .lm-head,#liveMeter .lm-row{display:grid;grid-template-columns:14px 52px 52px;align-items:center;gap:5px}
#liveMeter .lm-head{font-size:8.5px;font-weight:700;letter-spacing:.6px;color:#a9bcc4}
#liveMeter .lm-head span,#liveMeter .lm-row>span:not(.gl){text-align:right}
#liveMeter .lm-row{border-left:2px solid var(--cc);padding-left:3px;margin-left:-5px}
#liveMeter .lm-row.enemy:not(.enemy ~ .enemy){margin-top:3px}
#liveMeter .gl{width:14px;height:14px;color:var(--class-fill,var(--cc))}
#liveMeter b{font-weight:700}#liveMeter small{font-size:8.5px;color:#a9bcc4;margin-left:3px}
#liveMeter .lm-row.me b{color:#fff3c5}
#liveMeter .lm-foot{font-size:7.5px;color:#8ea2ab;text-align:right;letter-spacing:.3px}
