/* ----------------------------------------------------------------------------------------------------------------------
   ui/hud.css - the HUD's own look, in the create screen's language (ui/creator.css): round portraits ringed in white with
   a glow in their colour, ink-outlined cards with a coloured edge, badges on a portrait's rim, meters in inked tracks.
   Loaded after style.css (ui/ui.js, index.html), whose tokens it uses (:root) and whose ties it wins.

   The parts (ui/parts.js): .hd-portrait (sm, md, lg; --pc), .hd-badge (--bc), .hd-meter (--mc; hp, st, res, cast...),
   .hd-pips. The unit frames (ui/frames.js): .uf-player, .uf-target (the mirror), .uf-tot, .uf-pet; --rc is a unit's
   reaction colour (red foe, yellow neutral, green friend), --uc your class's. The action-bar assembly (ui/actionbar.js):
   .ab - its dock (.ab-dock: the red line, .ab-cast, .ab-swing), its bars (.ab-stack of .ab-bar grids of .ab-slot) and
   its status bars (.ab-status: .ab-st.rep, .ab-st.xp). The minimap (ui/minimap.js): .mmx - the zone's name, the ringed
   map, the buttons on its ring (.mm-btn) and the warning under it. The nameplates (ui/plates.js): .plate.

   Where the frames sit (each is movable in Edit mode, ui/layout.js; that move is a `translate` on top of this):
     desktop       World of Warcraft's centred layout: you left of the character and your target right of it, just above
                   the action bars (--hud-dock: how far the bars reach up the screen, measured by ui/actionbar.js); your
                   pal under you, your target's target under it. The bars at the bottom centre, the experience bar
                   under them, the cast bar and swing timer over them, between the two frames.
     .pv.hud-top   touch, or a screen under 1024px (ui.js decides: one class, one place): a column in the top-left -
                   you, your target, its target, your pal - clear of the stick, the pad and the bars.
     touch         the bars between the stick and the pad in rows that fit (--ab-cols); on a portrait phone they stand
                   on the right edge above the pad (.ab.portrait) and the experience bar spans the free bottom strip.
   Every frame that can be pressed is a 44 px+ target; nothing needs hover; motion stops for prefers-reduced-motion.
   --------------------------------------------------------------------------------------------------------------------- */

/* ------------------------------------------------------------------------------------------------ parts */
.hd-portrait {
  --pc: var(--accent); --ps: 3.3em;
  position: relative; display: grid; place-items: center; flex: none; width: var(--ps); height: var(--ps); border-radius: 50%;
  background: radial-gradient(circle at 50% 36%, #40557d, #121b2e 72%);
  box-shadow: 0 0 0 0.15em #fff, 0 0 0 0.3em var(--pc), 0 0 1.1em 0.15em color-mix(in srgb, var(--pc) 55%, transparent), 0 0.25em 0.6em rgba(0, 0, 0, 0.45);
  transition: box-shadow 200ms var(--ease);
}
.hd-portrait.sm { --ps: 2.3em; box-shadow: 0 0 0 0.12em #fff, 0 0 0 0.24em var(--pc), 0 0 0.7em 0.1em color-mix(in srgb, var(--pc) 50%, transparent), 0 0.2em 0.5em rgba(0, 0, 0, 0.45); }
.hd-portrait.lg { --ps: 4.5em; }
.hd-face { display: grid; place-items: center; width: 62%; height: 62%; color: var(--pc); }
.hd-face svg { display: block; width: 100%; height: 100%; filter: drop-shadow(0 1px 0 var(--ink)); }
.hd-face:has(> img) { width: 100%; height: 100%; overflow: hidden; border-radius: 50%; }
.hd-face img { width: 118%; height: 118%; object-fit: cover; opacity: 0; transition: opacity 240ms; }
.hd-face img.in { opacity: 1; }

.hd-badge {
  --bc: var(--accent);
  position: absolute; z-index: 2; display: grid; place-items: center; min-width: 1.75em; height: 1.75em; padding: 0 0.3em;
  border-radius: 999px; color: #fff; font-size: 0.7em; font-weight: 900; line-height: 1;
  background: radial-gradient(circle at 35% 30%, color-mix(in srgb, var(--bc) 45%, #1b2944), #0d1627 76%);
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--bc) 70%, #fff), 0 0 0 4px var(--ink), 0 3px 8px rgba(0, 0, 0, 0.45);
}
.hd-badge[hidden] { display: none; }

.hd-meter {
  --mc: #3fd46a;
  position: relative; height: 0.95em; border-radius: 999px; overflow: hidden; background: rgba(4, 8, 16, 0.8);
  box-shadow: inset 0 0 0 1.5px rgba(255, 255, 255, 0.14), inset 0 2px 4px rgba(0, 0, 0, 0.45);
}
.hd-meter > i { position: absolute; inset: 0; border-radius: inherit; transform-origin: 0 50%; transform: scaleX(0); will-change: transform; }
.hd-fill { background: linear-gradient(180deg, color-mix(in srgb, var(--mc) 50%, #fff), var(--mc) 55%, color-mix(in srgb, var(--mc) 72%, #000)); transition: transform 160ms var(--ease); }
.hd-fill::after { content: ""; position: absolute; left: 0; right: 0; top: 0; height: 40%; border-radius: inherit; background: rgba(255, 255, 255, 0.26); }
.hd-trail { background: rgba(255, 238, 196, 0.62); transition: transform 600ms var(--ease) 350ms; }  /* lags behind: the damage trail */
.hd-mtext { position: absolute; inset: 0; display: grid; place-items: center; font-size: 0.66em; font-weight: 900; line-height: 1; color: #fff;
  text-shadow: 0 1px 0 var(--ink), 0 0 3px var(--ink); pointer-events: none; white-space: nowrap; }
.hd-meter.st { --mc: var(--st); height: 0.42em; transition: opacity 500ms; }
.hd-meter.st.full { opacity: 0.28; }
.hd-meter.res { height: 0.78em; }

.hd-pips { display: flex; gap: 0.28em; padding: 0.1em 0; }
.hd-pips i { width: 0.78em; height: 0.78em; border-radius: 50%; background: rgba(8, 14, 26, 0.85); box-shadow: 0 0 0 1.5px var(--ink), inset 0 0 0 1px rgba(255, 255, 255, 0.18);
  transition: background 160ms, transform 200ms var(--spring); }
.hd-pips i.on { background: radial-gradient(circle at 35% 30%, #fff5b0, #ffc53a 58%, #d68a00); transform: scale(1.08); }

/* ------------------------------------------------------------------------------------------------ unit frames */
.frames { position: absolute; inset: 0; pointer-events: none; --uf-base: calc(var(--hud-dock, calc(var(--safe-b) + 9.2em)) + 0.6em); --uf-gap: 7.6em; }
.uf {
  position: absolute; display: none; align-items: center; min-height: var(--tap); margin: 0; padding: 0; border: 0; background: none;
  color: var(--text); font: inherit; text-align: left; pointer-events: auto; touch-action: manipulation;
}
button.uf { cursor: pointer; }
.uf.on, .uf-player { display: flex; }
.pv.lay-edit .uf { display: flex; }                          /* Edit mode: placed before they are needed */
.uf:focus-visible { outline: none; }
.uf:focus-visible .uf-card { outline: 3px solid var(--accent); outline-offset: 2px; }
.uf-face { position: relative; z-index: 1; flex: none; margin-right: -1.35em; }
.uf-card {
  --uw: 12.5em;
  position: relative; display: flex; flex-direction: column; gap: 0.26em; min-width: 0; width: var(--uw);
  padding: 0.42em 0.7em 0.5em 1.85em; border-radius: var(--r);
  background: var(--panel-menu); border: 2px solid var(--line-2);
  box-shadow: inset 0 3px 0 var(--uc, var(--rc, var(--accent))), 0 0 0 3px var(--ink), var(--shadow-sm);
  transition: border-color 200ms, box-shadow 200ms;
}
.uf-top { display: flex; align-items: center; gap: 0.35em; min-width: 0; }
.uf-name { min-width: 0; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; color: var(--rc, var(--text)); font-size: 0.92em; font-weight: 900;
  text-shadow: 0 1px 0 var(--ink); }
.uf-sub { flex: none; margin-left: auto; color: var(--text-3); font-size: 0.7em; font-weight: 800; white-space: nowrap; }
.uf-sub:empty { display: none; }
.uf-crest { flex: none; width: 1em; height: 1em; color: var(--fc, var(--accent)); filter: drop-shadow(0 1px 0 var(--ink)); }
.uf-crest[hidden] { display: none; }
.uf-crown { flex: none; width: 0.95em; height: 0.95em; color: var(--gold); }
.uf-lvl { left: -0.35em; bottom: -0.3em; }
.uf-pools { display: flex; flex-direction: column; gap: 0.22em; }
.uf-pools:empty { display: none; }

/* you: the big portrait on the left; with the experience bar turned off (.xpbar-off) the level badge's rim carries it */
.uf-player .uf-name { color: var(--text); }
.uf-player .uf-lvl { min-width: 2em; height: 2em; font-size: 0.74em; }
.pv.xpbar-off .uf-player .uf-lvl {
  border: 0.2em solid transparent;
  background: radial-gradient(circle at 35% 30%, color-mix(in srgb, var(--bc) 45%, #1b2944), #0d1627 76%) padding-box,
    conic-gradient(var(--exp) var(--xp, 0%), rgba(8, 14, 26, 0.92) 0) border-box;
  box-shadow: 0 0 0 2px var(--ink), 0 3px 8px rgba(0, 0, 0, 0.45);
}
.uf-player.pop .hd-portrait { animation: pop 600ms var(--spring); }
.uf-player.low .hd-meter.hp .hd-fill { animation: blink 0.9s ease-in-out infinite; }
.uf-player .hd-meter.hp { height: 1.1em; }
.uf-o2 { display: none; gap: 0.2em; padding-top: 0.1em; }
.uf-o2.on { display: flex; }
.uf-o2 i { width: 0.82em; height: 0.82em; border-radius: 50%; border: 2px solid #c4f4ff; background: radial-gradient(circle at 34% 30%, #fff 0 16%, rgba(90, 216, 255, 0.6) 20% 100%);
  box-shadow: 0 0 0 1px var(--ink); transition: transform 220ms var(--spring), opacity 220ms; }
.uf-o2 i.gone { transform: scale(0.2); opacity: 0; }
.uf-o2.low i { border-color: #ff9aa6; animation: shake-x 0.45s ease-in-out infinite; }

/* your target: the mirror - portrait on the right, level on its right rim */
.uf-target { flex-direction: row-reverse; text-align: right; }
.uf-target .uf-face { margin: 0 0 0 -1.35em; }
.uf-target .uf-card { padding: 0.42em 1.85em 0.5em 0.7em; }
.uf-target .uf-top { flex-direction: row-reverse; }
.uf-target .uf-sub { margin: 0 auto 0 0; }
.uf-target .uf-lvl { left: auto; right: -0.35em; }
.uf-target .mcast { position: relative; left: auto; top: auto; width: 100%; transform: none; margin-top: 0.1em; }
.uf.soft { opacity: 0.72; }
.uf.soft .uf-card { border-style: dashed; }
/* auto attacking it (systems/autoattack.js): crossed swords on its portrait */
.uf-atk { position: absolute; z-index: 2; left: -0.4em; top: -0.4em; display: grid; place-items: center; width: 1.45em; height: 1.45em; border-radius: 50%;
  background: #ff4d4d; color: #1a0606; box-shadow: 0 0 0 1.5px var(--ink); }
.uf-atk svg { width: 0.95em; height: 0.95em; }
.uf-atk[hidden] { display: none; }
/* aggroed on you (hunting or attacking you): lined in red, the genre's in-combat frame */
.uf.aggro .uf-card, .uf.attacking .uf-card {
  border-color: #ff3b3b;
  box-shadow: inset 0 3px 0 #ff3b3b, 0 0 0 3px var(--ink), 0 0 0 5px rgba(255, 59, 59, 0.6), 0 0 18px 2px rgba(255, 59, 59, 0.5), var(--shadow-sm);
}
.uf.aggro .hd-portrait { box-shadow: 0 0 0 0.15em #fff, 0 0 0 0.3em #ff3b3b, 0 0 1.2em 0.3em rgba(255, 59, 59, 0.7), 0 0.25em 0.6em rgba(0, 0, 0, 0.45); }
.uf.aggro .uf-card::before { content: ""; position: absolute; inset: -2px; border-radius: inherit; pointer-events: none; animation: uf-aggro 1.4s ease-in-out infinite; }
@keyframes uf-aggro { 50% { box-shadow: 0 0 22px 4px rgba(255, 59, 59, 0.55); } }

/* the small frames: your target's target, your pal */
.uf.sm .uf-face { margin-right: -1em; }
.uf.sm .uf-card { --uw: 8.4em; gap: 0.2em; padding: 0.3em 0.55em 0.36em 1.35em; }
.uf.sm .uf-name { font-size: 0.78em; }
.uf.sm .hd-meter.hp { height: 0.55em; }
.uf-pet { --uc: #3fe0ff; }

/* ------------------------------------------------------------------------------------------------ where they sit */
/* desktop: flanking the character above the bars (see the header) */
.uf-player { right: calc(50% + var(--uf-gap)); bottom: calc(var(--uf-base) + 3.4em); }
.uf-pet { right: calc(50% + var(--uf-gap) + 1em); bottom: var(--uf-base); }
.uf-target { left: calc(50% + var(--uf-gap)); bottom: calc(var(--uf-base) + 3.4em); }
.uf-tot { left: calc(50% + var(--uf-gap) + 1em); bottom: var(--uf-base); }
/* touch or a narrower screen: a column in the top-left */
.pv.hud-top .uf { right: auto; bottom: auto; left: calc(var(--safe-l) + var(--gap)); }
.pv.hud-top .uf-player { top: calc(var(--safe-t) + var(--gap)); }
.pv.hud-top .uf-target { top: calc(var(--safe-t) + var(--gap) + 5.6em); flex-direction: row; text-align: left; }
.pv.hud-top .uf-target .uf-face { margin: 0 -1.35em 0 0; }
.pv.hud-top .uf-target .uf-card { padding: 0.42em 0.7em 0.5em 1.85em; }
.pv.hud-top .uf-target .uf-top { flex-direction: row; }
.pv.hud-top .uf-target .uf-sub { margin: 0 0 0 auto; }
.pv.hud-top .uf-target .uf-lvl { left: -0.35em; right: auto; }
.pv.hud-top .uf-tot { top: calc(var(--safe-t) + var(--gap) + 9.7em); left: calc(var(--safe-l) + var(--gap) + 1em); }
.pv.hud-top .uf-pet { top: calc(var(--safe-t) + var(--gap) + 12.6em); left: calc(var(--safe-l) + var(--gap) + 1em); }
.pv.hud-top:not(:has(.uf-tot.on)) .uf-pet { top: calc(var(--safe-t) + var(--gap) + 9.7em); }
.pv.hud-top:not(:has(.uf-target.on)) .uf-pet { top: calc(var(--safe-t) + var(--gap) + 5.6em); }
@media (max-width: 599px) {
  .uf-card { --uw: 10.5em; }
  .uf.sm .uf-card { --uw: 7em; }
  .hd-portrait.lg { --ps: 3.9em; }
}
/* phones on their side: the column is short, so your target sits beside you and your pal under you; your target's
   target is left out (its place is the cast bar's and the swing timer's there) */
@media (max-height: 499px) and (orientation: landscape) {
  .pv.hud-top:not(.lay-edit) .uf-tot { display: none; }
  .pv.hud-top .uf-target { top: calc(var(--safe-t) + var(--gap)); left: calc(var(--safe-l) + var(--gap) + 16em); }
  .pv.hud-top .uf-tot { top: calc(var(--safe-t) + var(--gap) + 4.4em); left: calc(var(--safe-l) + var(--gap) + 17em); }
  .pv.hud-top .uf-pet, .pv.hud-top:not(:has(.uf-tot.on)) .uf-pet, .pv.hud-top:not(:has(.uf-target.on)) .uf-pet { top: calc(var(--safe-t) + var(--gap) + 5em); }
  .uf-card { --uw: 10em; }
  .hd-portrait.lg { --ps: 3.6em; }
}

/* ------------------------------------------------------------------------------------------------ minimap */
/* World of Warcraft's minimap (ui/minimap.js) in the create screen's ring: the zone's name over it, buttons on its ring
   (ui/minimapbuttons.js: each placed by its --a, degrees clockwise from north, at --ring-r from the centre; the player
   moves them round), a warning pill under it. The cluster leaves --mm-pad round the map so a button fits anywhere on the
   ring and stays on screen. Buttons are 44 px (40 on a phone) and nothing needs hover. */
.pv { --mb: max(2.3em, var(--tap)); --ring-k: 0.22; --mm-pad: calc(var(--mb) * (0.5 + var(--ring-k))); }   /* ring-k: how far out the buttons sit */
@media (max-width: 599px), (max-height: 499px) { .pv { --mb: 40px; --ring-k: 0.34; } }                              /* (a small map: further out) */
.mmx { position: absolute; top: calc(var(--safe-t) + var(--gap) * 0.5); right: calc(var(--safe-r) + var(--gap) * 0.5); display: flex; flex-direction: column; align-items: center; }
.mm-zone { position: relative; z-index: 1; max-width: calc(var(--mm) + 2 * var(--mm-pad)); padding: 0.22em 0.9em; border-radius: 999px;
  background: var(--panel-menu); border: 2px solid var(--line-2); box-shadow: 0 0 0 2px var(--ink), var(--shadow-sm); color: var(--gold); font-size: 0.8em; font-weight: 900;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; text-shadow: 0 1px 0 var(--ink); pointer-events: none; }
.mm-zone:empty { visibility: hidden; }
.mm-wrap { --ring-r: calc(var(--mm) / 2 + var(--mb) * var(--ring-k)); position: relative; width: var(--mm); height: var(--mm); margin: var(--mm-pad); }
.mm { pointer-events: auto; position: absolute; inset: 0; padding: 0; border: 0; border-radius: 50%; overflow: hidden; cursor: pointer; background: #2a78c8; touch-action: manipulation;
  box-shadow: 0 0 0 0.2em #fff, 0 0 0 0.42em var(--accent), 0 0 1.3em 0.2em rgba(63, 224, 255, 0.45), 0 0 0 calc(0.42em + 3px) var(--ink), var(--shadow); }
.mm:focus-visible { outline: 3px solid var(--accent); outline-offset: 0.6em; }
.mm canvas { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
/* N E S W on the rim (--r: px from the centre, set by minimap.js; --hd: the camera's heading when the minimap turns) */
.mm-letters { position: absolute; inset: 0; pointer-events: none; --hd: 0deg; --r: 60px; }
.mm-letters span { position: absolute; left: 50%; top: 50%; width: 1.35em; height: 1.35em; margin: -0.675em 0 0 -0.675em; display: grid; place-items: center; border-radius: 50%;
  font-size: 0.62em; font-weight: 900; color: #fff; background: rgba(8, 14, 26, 0.72);
  transform: rotate(calc(var(--a) - var(--hd))) translateY(calc(-1 * var(--r))) rotate(calc(var(--hd) - var(--a))); }
.mm-letters span.n { background: var(--bad); }
/* a button on the ring: a round badge, lit (the create screen's active fill) while what it opens is open */
.mm-ring { position: absolute; inset: 0; pointer-events: none; }
.mm-btn { pointer-events: auto; position: absolute; left: 50%; top: 50%; display: grid; place-items: center; width: var(--mb); height: var(--mb); margin: calc(var(--mb) / -2) 0 0 calc(var(--mb) / -2);
  padding: 0; border: 0; border-radius: 50%; color: var(--text); font: inherit; cursor: pointer; touch-action: none; -webkit-touch-callout: none; user-select: none;
  background: radial-gradient(circle at 35% 30%, #2b4170, #0d1627 76%); box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.85), 0 0 0 4px var(--ink), 0 3px 8px rgba(0, 0, 0, 0.45);
  transform: rotate(var(--a)) translateY(calc(-1 * var(--ring-r))) rotate(calc(-1 * var(--a)));
  transition: box-shadow 140ms, color 140ms, background 140ms, scale 160ms var(--spring); }
.mm-btn > svg { width: 48%; height: 48%; filter: drop-shadow(0 1px 0 var(--ink)); }
.mm-btn:active { scale: 0.9; }
.mm-btn:focus-visible { outline: 3px solid var(--accent); outline-offset: 2px; }
.mm-btn:disabled { opacity: 0.4; cursor: default; }
.mm-btn.lit { color: var(--ink); background: radial-gradient(circle at 35% 30%, #c4f8ff, #6deeff 45%, #1fb8e6 90%);
  box-shadow: 0 0 0 2px #fff, 0 0 0 4px var(--ink), 0 0 14px 2px rgba(63, 224, 255, 0.75); }
.mm-btn.lit > svg { filter: none; }
.mm-btn.moving { z-index: 2; cursor: grabbing; scale: 1.14; box-shadow: 0 0 0 2px #fff, 0 0 0 4px var(--ink), 0 0 0 7px rgba(63, 224, 255, 0.5), 0 6px 14px rgba(0, 0, 0, 0.5); transition: none; }
.mm-bdg { position: absolute; top: -0.35em; right: -0.35em; display: grid; place-items: center; min-width: 1.4em; height: 1.4em; padding: 0 0.25em; border-radius: 999px;
  background: var(--bad); color: #fff; font-size: 0.6em; font-weight: 900; box-shadow: 0 0 0 2px var(--ink); }
.mm-bdg[hidden] { display: none; }
/* under the map: a warning (a tsunami's countdown, hurricane winds, a storm on its way) - a steady pill, it never blinks */
.mm-under { display: flex; justify-content: center; }
.mm-warn { display: flex; align-items: center; gap: 0.35em; padding: 0.2em 0.7em; border-radius: 999px; font-size: 0.8em; font-weight: 900; white-space: nowrap;
  color: #ffe2dc; background: rgba(40, 10, 8, 0.82); border: 2px solid rgba(255, 110, 92, 0.9); box-shadow: 0 0 0 2px var(--ink); }
.mm-warn[hidden] { display: none; }
.mm-warn[data-kind="storm"] { color: #efe4ff; background: rgba(26, 14, 44, 0.82); border-color: rgba(185, 150, 255, 0.9); }
.mm-warn .ico { width: 1.1em; height: 1.1em; }
@media (max-height: 499px) and (orientation: landscape) { .mm-zone { display: none; } }   /* (short: the place card names a new zone) */

/* ------------------------------------------------------------------------------------------------ action bars */
/* The main assembly (ui/actionbar.js), bottom to top: the status bars (experience, reputation), the stack of bars (bar 1
   lowest), the dock (the red line, the cast bar, the swing timer). The stack's height is measured (--ab-h, --ab-status)
   so each part sits on the one below. A slot is a 44 px+ target; a bar is a grid of twelve in whole rows (--ab-cols). */
html.is-touch { --ab-pad: 216px; }                                             /* the action pad's height: 3.6 x 56 + 14 */
@media (min-width: 600px) and (min-height: 600px) { html.is-touch { --ab-pad: 260px; } }   /* tablet: 3.6 x 66 + 22 */
.ab {
  --slot: max(2.75em, var(--tap)); --slot-gap: 0.28em; --ab-cols: 12;
  --ab-sb: calc(var(--safe-b) + 0.45em + var(--ab-status, 0px) + 0.4em);      /* the stack's bottom: on the status bars */
  position: absolute; inset: 0; pointer-events: none; opacity: 0; visibility: hidden; transition: opacity 200ms, visibility 0s linear 200ms;
}
.ab.on, .pv.lay-edit .ab { opacity: 1; visibility: visible; transition: opacity 200ms; }

/* the bars: trays in the create screen's card look, their slots a fixed grid (empty cells drawn) */
.ab-stack { position: absolute; left: calc(var(--safe-l) + var(--tz-left) + var(--gap)); right: calc(var(--safe-r) + var(--tz-right) + var(--gap)); bottom: var(--ab-sb);
  display: flex; flex-direction: column-reverse; align-items: center; gap: 0.4em; }
.ab-bar { pointer-events: auto; display: flex; align-items: center; gap: 0.35em; padding: 0.3em; border-radius: var(--r);
  background: rgba(11, 18, 32, 0.8); border: 2px solid var(--line-2); box-shadow: inset 0 2px 0 rgba(255, 255, 255, 0.06), 0 0 0 3px var(--ink), var(--shadow-sm); }
.ab-bar.off, .ab-bar.never { display: none; }
/* carried (ui/drag.js) or being placed (Edit mode): a bar that is not Hidden shows, as a place to drop */
.pv.dragging-any .ab-bar.off:not(.never), .pv.lay-edit .ab-bar.off:not(.never) { display: flex; }
.pv.dragging-any .ab-bar.off:not(.never) { border-style: dashed; }
.ab-grid { display: grid; grid-template-columns: repeat(var(--ab-cols), var(--slot)); gap: var(--slot-gap); }

/* a slot: what it holds in its colour (--school: an ability's school, an item's, a pal's element, Attack's red) */
.ab-slot { position: relative; display: grid; place-items: center; width: var(--slot); height: var(--slot); padding: 0; overflow: hidden;
  border-radius: var(--r-sm); border: 2px solid color-mix(in srgb, var(--school) 70%, var(--line-2));
  background: radial-gradient(circle at 35% 28%, color-mix(in srgb, var(--school) 38%, #16223a), #0f1829 78%);
  box-shadow: 0 0 0 1.5px var(--ink), inset 0 0 0.8em color-mix(in srgb, var(--school) 25%, transparent);
  color: var(--text); font: inherit; cursor: pointer; touch-action: manipulation; -webkit-touch-callout: none; user-select: none;
  transition: transform 140ms var(--spring), filter 140ms, box-shadow 140ms, border-color 140ms; }
.ab-slot:active { transform: scale(0.93); }
.ab-slot:focus-visible { outline: 3px solid var(--accent); outline-offset: 2px; }
.ab-slot.empty { cursor: default; border-color: rgba(255, 255, 255, 0.08); background: rgba(4, 8, 16, 0.6); box-shadow: 0 0 0 1.5px var(--ink), inset 0 2px 6px rgba(0, 0, 0, 0.6); }
.ab-slot.empty:active { transform: none; }
.ab-slot.empty .ab-key { opacity: 0.5; }
.pv.dragging-any .ab-slot.empty { border-style: dashed; border-color: color-mix(in srgb, var(--accent) 45%, transparent); }
.ab-slot.dragging { opacity: 0.5; cursor: grabbing; }
.ab-mark { position: absolute; inset: 0.4em; opacity: 0.3; color: var(--school); pointer-events: none; }
.ab-mark svg { width: 100%; height: 100%; }
.ab-mark.pal { opacity: 0.4; inset: 0.3em; }
.ab-mono { position: relative; font-weight: 900; font-size: 1.1em; letter-spacing: 0.02em; text-shadow: 0 1px 0 var(--ink), 0 0 4px var(--ink); pointer-events: none; }
.ab-ico { position: absolute; inset: 0.32em; display: grid; place-items: center; pointer-events: none; }
.ab-ico svg { width: 100%; height: 100%; }
.ab-ico.attack { color: #ff8a7a; inset: 0.55em; }
.ab-sweep, .ab-gsweep { position: absolute; inset: 0; pointer-events: none; }
.ab-sweep { background: conic-gradient(rgba(4, 8, 16, 0.74) calc(var(--cd, 0) * 360deg), transparent 0); }
.ab-gsweep { background: conic-gradient(rgba(4, 8, 16, 0.42) calc(var(--gcd, 0) * 360deg), transparent 0); }
.ab-time { position: absolute; inset: 0; display: grid; place-items: center; font-weight: 900; font-size: 1.05em; pointer-events: none;
  text-shadow: 0 1px 0 var(--ink), 0 0 3px var(--ink), 0 0 3px var(--ink); }
.ab-time:empty, .ab-charges:empty { display: none; }
.ab-charges { position: absolute; right: 0.28em; bottom: 0.1em; font-size: 0.72em; font-weight: 900; pointer-events: none; text-shadow: 0 1px 0 var(--ink), 0 0 3px var(--ink); }
.ab-key { position: absolute; top: 0.1em; left: 0.3em; font-size: 0.6em; font-weight: 900; color: var(--text-2); text-shadow: 0 1px 0 var(--ink); pointer-events: none; }
html.is-touch .ab-key { display: none; }
.ab-slot.no { filter: saturate(0.2) brightness(0.6); }
/* lit: being cast, the sphere you throw, your pal out, Attack on */
.ab-slot.active { border-color: color-mix(in srgb, var(--school) 45%, #fff);
  box-shadow: 0 0 0 1.5px var(--ink), 0 0 0 3px color-mix(in srgb, var(--school) 60%, transparent), 0 0 14px color-mix(in srgb, var(--school) 75%, transparent); }
/* a proc made it better for its next use ("your next Greater Fireball is instant"): a gold rim that breathes until used */
.ab-slot.empowered { border-color: #ffd65a; animation: ab-empowered 1.1s ease-in-out infinite alternate; }
@keyframes ab-empowered {
  from { box-shadow: 0 0 0 1.5px var(--ink), 0 0 6px rgba(255, 214, 90, 0.55), inset 0 0 0.6em rgba(255, 214, 90, 0.25); }
  to { box-shadow: 0 0 0 1.5px var(--ink), 0 0 16px rgba(255, 214, 90, 0.95), inset 0 0 0.9em rgba(255, 214, 90, 0.45); }
}

/* the dock: over the stack, between your frame and your target's */
/* (the dock and the status bars are centred between the touch zones, as the stack is: left, right and an auto margin) */
.ab-dock, .ab-status { position: absolute; left: calc(var(--safe-l) + var(--tz-left) + var(--gap)); right: calc(var(--safe-r) + var(--tz-right) + var(--gap)); margin: 0 auto;
  display: flex; flex-direction: column; align-items: stretch; }
.ab-dock { bottom: calc(var(--ab-sb) + var(--ab-h, 3.6em) + 0.5em); width: 14em; max-width: calc(100% - var(--safe-l) - var(--safe-r) - 2 * var(--gap)); gap: 0.35em; }
.ab-err { min-height: 1.3em; font-weight: 900; color: #ff5a6e; text-align: center; white-space: nowrap; text-shadow: 0 1px 0 var(--ink), 0 0 6px rgba(0, 0, 0, 0.7); opacity: 0; }
.ab-err.on { animation: ab-err 1.6s var(--ease) both; }
@keyframes ab-err { 0% { opacity: 0; transform: translateY(4px); } 10% { opacity: 1; transform: none; } 75% { opacity: 1; } 100% { opacity: 0; } }
/* the cast bar and the swing timer's tracks: inked pills with a label on the left and the seconds on the right */
.ab-cast, .ab-sw { position: relative; overflow: hidden; border-radius: 999px; background: rgba(4, 8, 16, 0.84);
  box-shadow: 0 0 0 2px var(--ink), inset 0 0 0 1.5px rgba(255, 255, 255, 0.14), var(--shadow-sm); }
.ab-cast { display: none; height: 1.55em; }
.ab-cast.on, .pv.lay-edit .ab-cast { display: block; }
.ab-cast-fill, .ab-sw-fill { position: absolute; inset: 0; transform-origin: 0 50%; transform: scaleX(0); will-change: transform; }
.ab-cast-fill { background: linear-gradient(180deg, #fff1b8, #ffc53a 55%, #d68a00); }
.ab-cast.channel .ab-cast-fill { background: linear-gradient(180deg, #d4f6ff, #3fd0ff 55%, #0b8fc0); }
.ab-cast.stopped .ab-cast-fill { background: linear-gradient(180deg, #ffc0c0, #ff4d4d 55%, #b01c1c); }
.pv.lay-edit .ab-cast:not(.on) .ab-cast-fill { transform: scaleX(0.6); }                /* Edit mode's sample */
.ab-cast-name, .ab-cast-time, .ab-sw-name, .ab-sw-time { position: absolute; top: 0; bottom: 0; display: flex; align-items: center; font-weight: 900; color: #fff;
  white-space: nowrap; pointer-events: none; text-shadow: 0 1px 0 var(--ink), 0 0 3px var(--ink); }
.ab-cast-name { left: 0.8em; right: 3em; justify-content: center; overflow: hidden; font-size: 0.8em; }
.ab-cast-time { right: 0.75em; font-size: 0.74em; }
.ab-swing { display: none; flex-direction: column; gap: 0.3em; }
.ab.swing .ab-swing, .pv.lay-edit .ab-swing { display: flex; }
.ab-sw { height: 1.1em; }
.ab-sw + .ab-sw { display: none; }
.ab-swing.two .ab-sw + .ab-sw { display: block; }
.ab-sw-fill { background: linear-gradient(180deg, #ffd6c8, #ff7a5a 55%, #c2412a); }
.ab-sw + .ab-sw .ab-sw-fill { background: linear-gradient(180deg, #ecd0ff, #b36bff 55%, #7a3bb0); }
.pv.lay-edit .ab:not(.swing) .ab-sw-fill { transform: scaleX(0.6) !important; }         /* Edit mode's sample */
.ab-sw-name { left: 0.8em; font-size: 0.62em; letter-spacing: 0.04em; text-transform: uppercase; }
.ab-sw-time { right: 0.75em; font-size: 0.68em; }
/* the blow lands: a flash round the track */
.ab-sw.hit { animation: ab-hit 360ms var(--ease); }
@keyframes ab-hit { from { box-shadow: 0 0 0 2px var(--ink), 0 0 0 3.5px #fff, 0 0 16px 4px rgba(255, 170, 140, 0.9); } }

/* the status bars: experience (rested ahead of it, blue) and the watched reputation, as wide as the bars */
.ab-status { bottom: calc(var(--safe-b) + 0.45em); width: var(--ab-bw, 36em); max-width: calc(100% - var(--safe-l) - var(--safe-r) - 2 * var(--gap)); gap: 0.35em; }
.ab-st { --sc: var(--exp); position: relative; height: 1.05em; overflow: hidden; border-radius: 999px; background: rgba(4, 8, 16, 0.84);
  box-shadow: 0 0 0 2px var(--ink), inset 0 0 0 1.5px rgba(255, 255, 255, 0.12); }
.ab-st > i { position: absolute; inset: 0; transform-origin: 0 50%; transform: scaleX(0); transition: transform 400ms var(--ease); }
.ab-st-fill { background: linear-gradient(180deg, color-mix(in srgb, var(--sc) 50%, #fff), var(--sc) 55%, color-mix(in srgb, var(--sc) 70%, #000)); }
.ab-st-ahead { background: color-mix(in srgb, #5aa8ff 55%, transparent); }
.ab-st.xp.rested { --sc: #5a8cff; }                                            /* the genre's rested blue */
.ab-st.max { --sc: var(--gold); }
.ab-st > .ab-st-ticks { transform: none; transition: none; background: repeating-linear-gradient(90deg, transparent 0 calc(10% - 1.5px), rgba(4, 8, 16, 0.55) calc(10% - 1.5px) 10%); }
.ab-st-text { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; overflow: hidden; font-size: 0.62em; font-weight: 900;
  color: #fff; white-space: nowrap; text-shadow: 0 1px 0 var(--ink), 0 0 3px var(--ink); }
.ab-st.rep { --sc: #ffd84a; }
.ab-st.rep.none .ab-st-text { color: var(--text-3); }

/* the tooltip (hover, focus or a long press): a small card over the slot */
.ab-tip { position: absolute; z-index: 3; transform: translate(-50%, calc(-100% - 0.7em)); width: max-content; max-width: min(18em, calc(100vw - 2em)); padding: 0.6em 0.8em;
  border-radius: var(--r-sm); background: var(--panel-menu); border: 2px solid var(--line-2); box-shadow: 0 0 0 3px var(--ink), var(--shadow-sm); color: var(--text-2);
  font-size: 0.82em; pointer-events: none; opacity: 0; transition: opacity 120ms; }
.ab-tip.on { opacity: 1; }
.ab-tip.side { transform: translate(calc(-100% - 0.7em), -50%); }
.ab-tip b { display: block; margin-bottom: 0.2em; color: var(--text); font-size: 1.1em; }
.ab-tip-row { display: flex; justify-content: space-between; gap: 1em; }
.ab-tip-row span:empty { display: none; }
.ab-tip p { margin: 0.4em 0 0; color: var(--text); }

/* a portrait phone: the bars stand on the right edge above the action pad (bar 1 outermost),
   the dock beside them over the stick, the status bars across the free strip at the bottom */
.ab.portrait .ab-stack { left: auto; right: calc(var(--safe-r) + 10px); bottom: calc(var(--safe-b) + var(--tz-strip) + var(--ab-pad) + 8px);
  flex-direction: row-reverse; align-items: flex-end; }
.ab.portrait .ab-dock { left: calc(var(--safe-l) + 12px); right: calc(var(--safe-r) + 12px + var(--ab-w, 6em) + 12px); width: auto; max-width: 18em;
  bottom: calc(var(--safe-b) + var(--tz-strip) + var(--ab-pad) + 8px); }
.ab.portrait .ab-status { left: calc(var(--safe-l) + 10px); right: calc(var(--safe-r) + 10px); width: auto; max-width: none;
  bottom: calc(var(--safe-b) + max(6px, (var(--tz-strip) - 2.6em) / 2)); }
@media (max-height: 499px) and (orientation: landscape) { .ab-dock { gap: 0.25em; } .ab-stack { gap: 0.3em; } }

/* the sphere you throw, named under the reticle for a moment when it changes (ui/hud.js) */
.sphere-name { position: absolute; left: 50%; top: calc(50% + 2.6em); translate: -50% 0; display: flex; align-items: center; gap: 0.4em;
  padding: 0.3em 0.85em 0.3em 0.4em; border-radius: 999px; background: var(--panel-menu); border: 2px solid var(--line-2); box-shadow: 0 0 0 3px var(--ink), var(--shadow-sm);
  white-space: nowrap; font-size: 0.85em; font-weight: 900; opacity: 0; pointer-events: none; transition: opacity 250ms; }
.sphere-name.on { opacity: 1; animation: pop 400ms var(--spring); }
.sphere-name .ico { width: 1.5em; height: 1.5em; }
.sphere-name small { color: var(--text-2); font-weight: 700; }

/* ------------------------------------------------------------------------------------------------ nameplates */
.plates { position: absolute; inset: 0; overflow: hidden; }
.plate { --rc: #ffd84a; position: absolute; left: 0; top: 0; display: none; flex-direction: column; align-items: center; gap: 0.2em; white-space: nowrap;
  font-size: 0.8em; will-change: transform, opacity; }
.plate.on { display: flex; }
.pl-row { display: flex; align-items: center; gap: 0.32em; padding: 0.16em 0.55em 0.16em 0.2em; border-radius: 999px;
  background: rgba(8, 14, 26, 0.7); border: 1.5px solid rgba(255, 255, 255, 0.14); box-shadow: 0 0 0 1.5px var(--ink); }
.pl-lv { display: grid; place-items: center; min-width: 1.6em; height: 1.6em; padding: 0 0.25em; border-radius: 999px; font-size: 0.78em; font-weight: 900; color: #fff;
  background: radial-gradient(circle at 35% 30%, color-mix(in srgb, var(--rc) 45%, #1b2944), #0d1627 76%); box-shadow: 0 0 0 1.5px color-mix(in srgb, var(--rc) 75%, #fff); }
.pl-name { color: var(--rc); font-weight: 900; text-shadow: 0 1px 0 var(--ink), 0 0 3px rgba(0, 0, 0, 0.7); }
.pl-el { width: 1.3em; height: 1.3em; }
.pl-mk { width: 1.1em; height: 1.1em; }
.pl-mk.alpha { color: #ff6a7c; }
.pl-mk.lucky { color: var(--gold); }
.pl-mk[hidden] { display: none; }
.pl-st { font-weight: 900; font-size: 0.9em; }
.pl-st:empty { display: none; }
.pl-hp { width: 6.4em; height: 0.46em; border-radius: 999px; overflow: hidden; background: rgba(8, 14, 26, 0.8); box-shadow: 0 0 0 1.5px var(--ink); }
.pl-hp[hidden] { display: none; }
.pl-hp i { display: block; height: 100%; transform-origin: 0 50%; background: linear-gradient(180deg, color-mix(in srgb, var(--rc) 55%, #fff), var(--rc) 60%, color-mix(in srgb, var(--rc) 70%, #000)); }
/* your target: it stands out */
.plate.target { z-index: 1; font-size: 0.9em; }
.plate.target .pl-row { border-color: rgba(255, 255, 255, 0.85); background: rgba(8, 14, 26, 0.86); }
/* aggroed on you: lined in red */
.plate.aggro .pl-row { border-color: #ff3b3b; box-shadow: 0 0 0 1.5px var(--ink), 0 0 10px 1px rgba(255, 59, 59, 0.65); }
.plate.aggro .pl-hp { box-shadow: 0 0 0 1.5px var(--ink), 0 0 0 3px rgba(255, 59, 59, 0.75); }
.plate.aggro .pl-st { color: #ff5a5a; }
.plate.evade .pl-row { border-color: rgba(160, 200, 255, 0.8); opacity: 0.85; }
.plate.evade .pl-st { color: #c8d8ff; font-size: 0.72em; letter-spacing: 0.04em; font-style: italic; }
.plate.asleep { opacity: 0.8; }
.plate.asleep .pl-st { color: var(--info); }
.plate.party .pl-row { border-color: rgba(63, 224, 255, 0.75); }

@media (prefers-reduced-motion: reduce) {
  .uf.aggro .uf-card::before, .uf-player.low .hd-meter.hp .hd-fill, .uf-o2.low i, .ab-sw.hit, .ab-err.on, .sphere-name.on { animation: none; }
  .ab-err.on { opacity: 1; }
  .ab-slot.empowered { animation: none; box-shadow: 0 0 0 1.5px var(--ink), 0 0 12px rgba(255, 214, 90, 0.85), inset 0 0 0.8em rgba(255, 214, 90, 0.35); }
  .hd-fill, .hd-trail, .hd-portrait, .uf-card, .ab-st > i, .ab-slot, .mm-btn { transition: none; }
}

/* ------------------------------------------------------------------------------------------------ toasts and cards */
/* a toast: the create screen's card - ink-outlined, its kind's colour on its left edge and its icon */
.toast { --tc: var(--info); background: var(--panel-menu); border-color: var(--line-2); box-shadow: inset 4px 0 0 var(--tc), 0 0 0 2.5px var(--ink), var(--shadow-sm); }
.toast.good { --tc: var(--good); }
.toast.warn { --tc: var(--warn); }
.toast.error { --tc: var(--bad); }
.toast.unlock, .toast.level { --tc: var(--gold); }
.toast.capture { --tc: var(--accent); }
.toast.exp { --tc: var(--exp); }
/* a weather warning announced once (ui/weatherhud.js): a card in the middle, its tone on its edge - it fades, never flashes */
.wx-card { --tc: var(--gold); width: min(30em, calc(100vw - 2 * var(--gap))); padding: 0.8em 1.4em 0.9em; border-radius: var(--r-lg); white-space: normal;
  background: var(--panel-menu); border: 2px solid color-mix(in srgb, var(--tc) 55%, var(--line-2)); box-shadow: inset 0 4px 0 var(--tc), 0 0 0 3px var(--ink), var(--shadow); }
.wx-card[data-tone="danger"] { --tc: #ff5a4e; }
.wx-card-h { font-size: 1.45em; color: color-mix(in srgb, var(--tc) 80%, #fff); }
.wx-card-sub { font-size: 0.95em; line-height: 1.35; }


/* with the frames in the top-left column (.hud-top), the toasts stack on the right, under the minimap (not while a
   menu or a screen is up: style.css puts them at the bottom then) */
.pv.hud-top:not(:has(.menu.on, .scr.on)) > .toasts {
  left: auto; right: calc(var(--safe-r) + var(--gap)); top: calc(var(--safe-t) + var(--gap) + var(--mm) + 2 * var(--mm-pad) + 1.4em); width: min(18em, 56vw); align-items: flex-end;
}
/* the bars standing on a portrait screen's right edge (.bars-side: ui/actionbar.js): the toasts go under the frames on
   the left, as wide as the room left of the bars */
.pv.hud-top.bars-side:not(:has(.menu.on, .scr.on)) > .toasts {
  left: calc(var(--safe-l) + var(--gap)); right: auto; top: calc(var(--safe-t) + var(--gap) + 15em); align-items: flex-start;
  width: min(18em, calc(100vw - var(--safe-l) - var(--safe-r) - var(--ab-side, 0px) - 3 * var(--gap)));
}
/* a phone on its side: the right is the action pad's, so the toasts go under your frame on the left (the latest three) */
@media (max-height: 499px) and (orientation: landscape) {
  html.is-touch .pv.hud-top:not(:has(.menu.on, .scr.on)) > .toasts {
    left: calc(var(--safe-l) + var(--gap)); right: auto; top: calc(var(--safe-t) + var(--gap) + 8.2em); width: min(15em, 38vw); align-items: flex-start;
  }
  html.is-touch .pv.hud-top:not(:has(.menu.on, .scr.on)) > .toasts > .toast:nth-last-child(n + 4) { display: none; }
}
