/* =============================================================================
   HOOD ARENA — "OBSIDIAN PREMIUM"
   A private room with a doorman, and a fight going on in it.

   Three rules the whole file obeys:
     1. Every surface is one machined obsidian slab: lit top bevel, hairline ring,
        contact shadow, ambient shadow. One --slab token. No hex soup.
     2. Gold is jewellery and money. ONE seam per surface (rail, chat, hero,
        section rule, stake plinth, modal, duel head) and every currency value
        struck in foil. Nothing else gets gold.
     3. Green means you can act. Red means money can be lost. Neither is wallpaper.
     4. No coloured bloom anywhere. Depth is a lit bevel, a hairline ring and a
        black contact + ambient shadow. Colour signals through a crisp 1px edge,
        a 2px signal bar or a stronger fill — never a halo.

   Perf contract: every looping animation moves transform or opacity only, every
   ambient loop inside .ha-app pauses under body.ca-lock, and NOTHING applies
   filter, clip-path or backdrop-filter to an ancestor of the live THREE canvas.
   ============================================================================= */

:root {
  /* --- obsidian stack. each step is a physical layer, not a shade ---------- */
  --bg:        #06070a;
  --bg-soft:   #090b10;
  --panel:     #0b0e13;
  --panel-2:   #101419;
  --card:      #0d1015;
  --raise:     #151a21;
  --raise-2:   #1c232c;

  --line:      rgba(255, 255, 255, .075);
  --line-soft: rgba(255, 255, 255, .042);
  --edge:      rgba(255, 255, 255, .10);

  --txt:      #eef2f6;
  --txt-dim:  #a7b4c0;   /* 9.5:1 on --bg */
  --txt-mute: #7e8b98;   /* 5.8:1 on --bg — passes AA at every size used */

  /* Robinhood Chain's lime. Bright enough that it is a background colour with
     dark text on it, never a background with light text: white on #ccff00
     measures 1.18:1, and --green-ink measures 15.18:1. The token exists so the
     next person does not have to rediscover that. */
  --green:      #ccff00;
  --green-soft: #ddff4d;
  --green-dark: #6b8a00;
  --green-ink:  #141a00;
  --green-dim:  rgba(204, 255, 0, .12);

  --gold:     #e8c07a;
  --gold-hi:  #fff3d4;
  --gold-lo:  #a9772a;
  --gold-dim: rgba(232, 192, 122, .16);

  /* risk. this product can take your money, so the palette says so. */
/* Measured against white at both ends of the button's gradient, because the
     label sits across the middle of it: the first pick topped out at 3.93:1,
     under AA, while its bottom stop passed at 5.13. These are 4.75 and 6.85. */
  --red:      #e0544a;
  --red-hot:  #ff6a5c;
  --red-deep: #3d1310;
  --red-dim:  rgba(224, 84, 74, .14);

  /* --- one scale. every size in this file comes from here. ----------------- */
  --fs-1: 10px;   /* struck chips only: LIVE, LIMITED, badges, win tag */
  --fs-2: 11px;   /* structural micro labels */
  --fs-3: 12px;   /* secondary copy, requirements, notes */
  --fs-4: 13px;   /* dense UI */
  --fs-5: 14px;   /* body */
  --fs-6: 16px;   /* lead */
  --fs-7: 18px;   /* sub display */
  --fs-8: 22px;   /* section heads, card money */
  --fs-9: 26px;   /* modal titles, pot, locker stats */
  --fs-10: 34px;  /* the money shot */

  --r-chip: 5px;  /* struck chips: badges, LIMITED, WINNER */
  --r-xs:  8px;
  --r-sm:  12px;
  --radius-sm: var(--r-sm);   /* legacy alias, still consumed below */
  --r:     16px;
  --radius: var(--r);
  --r-lg:  22px;
  --r-pill: 999px;

  --s1: 4px;  --s2: 8px;  --s3: 12px; --s4: 16px;
  --s5: 20px; --s6: 28px; --s7: 40px;

  --bnav-h: 66px;

  --font:    "Sora", system-ui, -apple-system, "Segoe UI", sans-serif;
  --display: "Cinzel", Georgia, "Times New Roman", serif;
  --num:     "Chivo Mono", ui-monospace, SFMono-Regular, Menlo, monospace;

  /* --- materials ----------------------------------------------------------- */
  /* volcanic-glass micro grain. one decoded tile, reused everywhere. */
  --grain: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23g)' opacity='.055'/%3E%3C/svg%3E");
  --brush: repeating-linear-gradient(114deg, rgba(255, 255, 255, .017) 0 1px, transparent 1px 5px);
  --sheen: linear-gradient(157deg, rgba(255, 255, 255, .055) 0%, rgba(255, 255, 255, .014) 30%, transparent 58%);
  /* gold ledger ticks. the money rail. */
  --ticks: repeating-linear-gradient(90deg, rgba(232, 192, 122, .3) 0 2px, transparent 2px 6px);

  /* the three control faces. every raised control uses one of these — this is
     what stops a dozen near-identical dark values from drifting apart. */
  --face:    linear-gradient(180deg, var(--raise), var(--panel-2));
  --face-hi: linear-gradient(180deg, var(--raise-2), var(--raise));
  --well:    linear-gradient(180deg, #080b0f, var(--panel));

  /* machined edge + ambient occlusion. the inset top highlight IS the bevel. */
  --slab:    inset 0 1px 0 rgba(255, 255, 255, .075), 0 0 0 1px rgba(255, 255, 255, .05),
             0 2px 4px rgba(0, 0, 0, .5), 0 18px 34px -18px rgba(0, 0, 0, .9);
  --slab-hi: inset 0 1px 0 rgba(255, 255, 255, .14), 0 0 0 1px rgba(255, 255, 255, .1),
             0 4px 10px rgba(0, 0, 0, .55), 0 26px 48px -20px rgba(0, 0, 0, .95);
  --slab-lg: inset 0 1px 0 rgba(255, 255, 255, .1), 0 0 0 1px rgba(255, 255, 255, .06),
             0 40px 90px -34px rgba(0, 0, 0, 1);
  --sink:    inset 0 2px 5px rgba(0, 0, 0, .8), inset 0 -1px 0 rgba(255, 255, 255, .045);

  --ease: cubic-bezier(.16, 1, .3, 1);
}

/* --------------------------------- reset ---------------------------------- */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html {
  background: var(--bg);
  overflow-x: hidden; overscroll-behavior-x: none;
  -webkit-text-size-adjust: 100%;
}
body {
  background:
    radial-gradient(120% 78% at 50% -14%, rgba(204, 255, 0, .04), transparent 58%),
    radial-gradient(90% 60% at 100% 100%, rgba(232, 192, 122, .035), transparent 62%),
    var(--grain),
    var(--bg);
  color: var(--txt);
  font-family: var(--font); font-size: var(--fs-5); line-height: 1.5; font-weight: 400;
  -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale;
  overscroll-behavior-x: none;   /* the clip lives on <html>: making <body> a
     scroll container too breaks window.scrollY and scroll anchoring */
}
body.ca-lock { overflow: hidden; }
img { max-width: 100%; display: block; }
a { color: inherit; text-decoration: none; }
button { font-family: inherit; color: inherit; background: none; border: 0; cursor: pointer; }
input, select, textarea { font-family: inherit; font-size: var(--fs-5); color: var(--txt); }
h1, h2, h3 { font-weight: 700; }
/* no border-radius here: it would mutate the element's real geometry, snapping
   round controls into squares the instant they take keyboard focus. */
:focus-visible { outline: 2px solid var(--green-soft); outline-offset: 2px; }

::-webkit-scrollbar { width: 9px; height: 9px; }
::-webkit-scrollbar-thumb {
  background: linear-gradient(180deg, #232a34, var(--raise));
  border-radius: var(--r-pill); border: 2px solid transparent; background-clip: padding-box;
}
::-webkit-scrollbar-thumb:hover { background: linear-gradient(180deg, #2e3742, #1d232b); background-clip: padding-box; }
::-webkit-scrollbar-track { background: transparent; }
* { scrollbar-width: thin; scrollbar-color: #232a34 transparent; }

/* =============================================================================
   MONEY — its own typographic system, not a colour swap.
   Mono face + tabular figures + gold foil, everywhere a value is currency.
   The HOOD coin glyph stays green so token never blurs with value.
   ============================================================================= */
.ha-stake span, .ha-bt-pot .amt, .ha-bt-pstake, .ha-lk-stat .v,
.ca-state .row b, .ha-summary b, #ha-balance-amt, .ha-tick b, .ha-mark b,
.ha-count, .ha-quick, .ca-fair, .ha-input input {
  font-family: var(--num); font-variant-numeric: tabular-nums; letter-spacing: -.01em;
}
/* struck metal. gradient runs top-lit to shadowed, like a stamped coin face. */
.ha-stake span, .ha-bt-pot .amt, .ha-bt-pstake, .ha-lk-stat .v,
.ca-state .row b, .ha-summary b, #ha-balance-amt, .ha-tick b, .ha-mark b {
  background: linear-gradient(180deg, var(--gold-hi) 0%, var(--gold) 44%, var(--gold-lo) 100%);
  -webkit-background-clip: text; background-clip: text;
  color: transparent; -webkit-text-fill-color: transparent;
  font-weight: 700;
}
/* Automation stays identifiable without the old HOUSE pill. */
.ha-auto-player { display: inline-flex; align-items: center; flex: 0 0 14px; width: 14px; height: 14px; color: #9aa4b4; }
.ha-auto-player svg { display: block; width: 100%; height: 100%; }

.ha-coin {
  /* `img { display: block }` is the page reset, which was invisible while the
     coin only ever sat in a flex row. money() puts it inline beside a number in
     tiles, table cells and list rows, and a block image there took its own line
     and doubled the height of every one of them. */
  display: inline-block; vertical-align: -2px;
  flex-shrink: 0; border-radius: 50%; object-fit: contain;
  filter: drop-shadow(0 1px 1px rgba(0, 0, 0, .9));
}

/* Two escape hatches. Engines without background-clip:text, and Windows High
   Contrast — where transparent fill would blank every price on the site. */
@supports not ((-webkit-background-clip: text) or (background-clip: text)) {
  .ha-stake span, .ha-bt-pot .amt, .ha-bt-pstake, .ha-lk-stat .v,
  .ca-state .row b, .ha-summary b, #ha-balance-amt, .ha-tick b, .ha-mark b,
  .ha-hero-title, .ha-hero-title em, .ha-modal h3, .ha-top-logo span, .ca-state h2 {
    background: none; color: var(--gold); -webkit-text-fill-color: var(--gold);
  }
  .ha-hero-title, .ha-modal h3, .ha-top-logo span { color: var(--txt); -webkit-text-fill-color: var(--txt); }
}
@media (forced-colors: active) {
  .ha-stake span, .ha-bt-pot .amt, .ha-bt-pstake, .ha-lk-stat .v,
  .ca-state .row b, .ha-summary b, #ha-balance-amt, .ha-tick b, .ha-mark b,
  .ha-hero-title, .ha-hero-title em, .ha-modal h3, .ha-top-logo span, .ca-state h2 {
    background: none; color: CanvasText; -webkit-text-fill-color: CanvasText;
    forced-color-adjust: auto;
  }
}

/* ------------------------------- app frame -------------------------------- */
.ha-app {
  display: grid;
  /* No transition on this. Animating a track list left it stuck: with the
     open class removed the computed columns stayed 336px 1104px, so the panel
     never closed, while the same measurement with transitions off read
     0px 1440px. The panel snaps instead. */
  grid-template-columns: 0 minmax(0, 1fr);
  /* an auto row grows to its content, so height:100dvh alone left the row at
     full content height and the document scrolled instead of .ha-main. That
     scrolled the rail and the docked chat off the screen with it. */
  grid-template-rows: minmax(0, 1fr);
  height: 100vh; height: 100dvh;
  overflow: hidden;
  isolation: isolate;
}
.ha-frame { display: flex; flex-direction: column; min-width: 0; position: relative; }
body.ha-chat-open .ha-app { grid-template-columns: 336px minmax(0, 1fr); }
/* the panel is clipped by the column rather than squeezed: text reflowing to
   nothing on the way out looks like a rendering fault, not a close */
.ha-chat > * { width: 336px; }

/* --- top nav: the rail laid on its side ----------------------------------
   Everything used to live in an 84px spine down the left. It is one bar now,
   logo then destinations then money, which is what the reference does and
   what leaves the lobby its full width. The bottom bar still owns phones. */
.ha-topnav {
  display: flex; align-items: center; gap: 10px;
  min-width: 0; flex: 0 1 auto; margin-left: var(--s4);
  overflow-x: auto; scrollbar-width: none;
}
.ha-topnav::-webkit-scrollbar { display: none; }
/* 8px, not the 10 that fitted exactly on a local build. The right group is
     not a fixed width: staging carries a symbol chip next to the balance that
     local did not, and that alone pushed the nav 9px into its own scroller.
     Anything that lengthens a number there eats the last item's padding, so
     the bar needs slack rather than an exact fit. */
.ha-topnav-item {
  position: relative; height: 42px; padding: 0 8px; border-radius: var(--r-sm);
  display: flex; align-items: center; gap: 8px; white-space: nowrap;
  color: var(--txt-mute);
  transition: color .2s, background .25s, box-shadow .25s;
}
.ha-topnav-item svg { width: 17px; height: 17px; flex-shrink: 0; transition: transform .3s var(--ease); }
.ha-topnav-item[data-nav="locker"], .ha-topnav-item[data-nav="shop"] { min-width: 44px; min-height: 44px; }
/* sentence case, no tracking. these are destinations, not struck labels. */
.ha-topnav-item span { font-size: var(--fs-4); font-weight: 600; letter-spacing: .01em; }
/* the rail marked the active page with a bar down its left edge; lying flat,
   that edge is the bottom one, and it sits on the bar's own hairline */
.ha-topnav-item::before {
  content: ''; position: absolute; left: 50%; bottom: -12px; height: 2px; width: 0;
  border-radius: 2px 2px 0 0; background: var(--green);
  transform: translateX(-50%); transition: width .3s var(--ease);
}
.ha-topnav-item:hover { color: var(--txt-dim); background: rgba(255, 255, 255, .035); }
.ha-topnav-item:hover svg { transform: translateY(-1px); }
.ha-topnav-item.is-active {
  color: var(--green-soft);
  background: linear-gradient(180deg, rgba(204, 255, 0, .11), rgba(204, 255, 0, .03));
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .07), inset 0 0 0 1px rgba(204, 255, 0, .3);
}
.ha-topnav-item.is-active::before { width: 26px; }
@media (min-width: 1280px) { .ha-topnav-item[data-nav="chat"] { display: none; } }
/* Below that the chat is a drawer, so its tab has to come back, and six labelled
   items no longer fit: measured at 1100, the nav wanted 79px more than it had and
   clipped Chat, the one item that width depends on. Icons only, titles intact. */
@media (max-width: 1279px) {
  .ha-topnav-item span { display: none; }
  .ha-topnav-item { padding: 0 11px; }
}
.ha-online {
  display: flex; align-items: center; gap: 7px; padding: var(--s2) 10px; border-radius: var(--r-pill);
  font-family: var(--num); font-size: var(--fs-2); font-weight: 700; color: var(--txt-dim);
  font-variant-numeric: tabular-nums;
  background: rgba(255, 255, 255, .03); box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .04);
}
.ha-online-dot {
  position: relative; width: 7px; height: 7px; border-radius: 50%; flex-shrink: 0;
  background: var(--green-soft); box-shadow: 0 0 0 2px rgba(4, 6, 9, .8); display: inline-block;
}
.ha-online-dot::after {
  content: ''; position: absolute; inset: -4px; border-radius: 50%;
  box-shadow: 0 0 0 1px rgba(204, 255, 0, .35);
  animation: ha-ping 2.6s var(--ease) infinite;
}
@keyframes ha-ping { 0% { opacity: .9; transform: scale(.6); } 70%, 100% { opacity: 0; transform: scale(1.5); } }

/* ------------------------------- top bar ---------------------------------- */
.ha-top {
  container: arena-header / inline-size;
  position: relative; z-index: 20; flex-shrink: 0;
  display: flex; align-items: center; gap: var(--s3);
  height: 66px; padding: 0 var(--s5) 0 22px;
  background: linear-gradient(180deg, rgba(17, 21, 28, .88), rgba(9, 12, 16, .9));
  -webkit-backdrop-filter: blur(20px) saturate(135%); backdrop-filter: blur(20px) saturate(135%);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .05), 0 12px 30px -22px #000;
}
.ha-top::after {   /* GOLD SEAM 1 of 7, inherited from the rail that carried it */
  content: ''; position: absolute; left: 0; right: 0; bottom: 0; height: 1px;
  background: linear-gradient(90deg, transparent, rgba(232, 192, 122, .32) 14%, rgba(232, 192, 122, .05) 62%, var(--line) 88%, transparent);
}
.ha-top-logo { display: flex; align-items: center; flex-shrink: 0; }
/* A stacked wordmark is two lines inside the bar's height, so it needs the
   height it can get: 46px leaves each line about 23px against 24px of spare
   air in a 66px bar. The margin is the real fix though, the crowding was
   sideways: 8px from the mark to the chain badge read as one blob. */
.ha-top-logo img {
  flex-shrink: 0; height: 46px; width: auto; margin-right: var(--s3);
  filter: drop-shadow(0 1px 2px rgba(0, 0, 0, .9));
}
.ha-top-logo span {
  font-family: var(--display); font-weight: 800; font-size: var(--fs-7); letter-spacing: .2em;
  background: linear-gradient(180deg, #ffffff, #b9c6d2);
  -webkit-background-clip: text; background-clip: text; color: transparent; -webkit-text-fill-color: transparent;
  white-space: nowrap; overflow: hidden; min-width: 0;
}
.ha-socials { display: flex; align-items: center; gap: 2px; flex-shrink: 0; margin-left: auto; }
.ha-social-link {
  display: inline-flex; align-items: center; justify-content: center;
  width: 44px; height: 44px; border-radius: var(--r-sm); color: var(--txt-mute);
  transition: color .2s, background .2s;
}
.ha-social-link svg { width: 18px; height: 18px; }
.ha-social-link:hover { color: var(--green-soft); background: rgba(255, 255, 255, .045); }
.ha-social-link:focus-visible { outline: 2px solid var(--green-soft); outline-offset: 2px; color: var(--green-soft); }
.ha-top-right { display: flex; align-items: center; gap: 10px; flex-shrink: 0; }
.ha-currency { min-width: 0; }
.ha-currency #ha-balance { min-height: 44px; }
.ha-currency #ha-balance-amt { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ha-currency #ha-balance-icon { width: 18px; height: 18px; object-fit: contain; flex-shrink: 0; }
#ha-balance[aria-expanded="true"] { box-shadow: var(--slab), 0 0 0 1px rgba(204, 255, 0, .45); }
#ha-balance .ha-pill-caret { transition: transform .16s var(--ease); }
#ha-balance[aria-expanded="true"] .ha-pill-caret { transform: rotate(180deg); }
/* Portalled out of the header so its backdrop/container cannot clip the menu. */
.ha-currency-menu {
  position: fixed; z-index: 150; width: 324px; max-width: calc(100vw - 24px);
  overflow-y: auto; overscroll-behavior: contain;
  border: 1px solid var(--edge); border-radius: var(--r-sm);
  background: #141a22; color: var(--txt);
  box-shadow: 0 18px 48px rgba(0, 0, 0, .5), inset 0 1px 0 rgba(255, 255, 255, .035);
}
.ha-currency-heading { display: flex; justify-content: space-between; align-items: baseline; gap: var(--s3); padding: var(--s4) var(--s4) var(--s3); }
.ha-currency-heading b { font-size: var(--fs-3); font-weight: 600; }
.ha-currency-heading > span { font-size: 11px; color: var(--txt-dim); }
.ha-currency-options { padding: 0 6px 6px; }
.ha-currency-option {
  display: flex; align-items: center; gap: 10px; width: 100%; min-height: 64px; padding: 10px;
  border: 1px solid transparent; border-radius: var(--r-xs); color: var(--txt); text-align: left;
  transition: background .15s, border-color .15s;
}
.ha-currency-option:hover, .ha-currency-option:focus-visible { background: rgba(255, 255, 255, .045); }
.ha-currency-option[aria-checked="true"] { background: rgba(204, 255, 0, .065); border-color: rgba(204, 255, 0, .13); }
.ha-currency-option[aria-disabled="true"] { cursor: default; }
.ha-currency-icon { display: grid; place-items: center; width: 32px; height: 32px; flex-shrink: 0; }
.ha-currency-icon img { display: block; object-fit: contain; }
.ha-currency-icon.is-eth { border-radius: 50%; background: rgba(150, 139, 245, .12); }
.ha-currency-identity { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.ha-currency-identity b { font-size: var(--fs-4); font-weight: 600; line-height: 1.4; overflow-wrap: anywhere; }
.ha-currency-identity > span { font-size: 11px; color: var(--txt-dim); line-height: 1.4; overflow-wrap: anywhere; }
.ha-currency-value { margin-left: auto; min-width: 0; text-align: right; }
.ha-currency-value b { display: block; font-family: var(--num); font-size: var(--fs-3); font-weight: 500; overflow-wrap: anywhere; }
.ha-currency-value > span { display: block; margin-top: 4px; font-size: 10px; color: var(--txt-dim); white-space: nowrap; }
.ha-currency-value > span:empty { display: none; }
.ha-currency-check { width: 16px; height: 16px; flex-shrink: 0; color: var(--green); visibility: hidden; }
.ha-currency-option[aria-checked="true"] .ha-currency-check { visibility: visible; }
.ha-currency-option[aria-disabled="true"] .ha-currency-check { display: none; }
.ha-currency-footer { display: grid; gap: 2px; padding: var(--s2); border-top: 1px solid var(--line); }
.ha-currency-footer button { display: flex; align-items: center; justify-content: center; gap: var(--s2); min-height: 44px; padding: var(--s2); border-radius: var(--r-xs); font-size: var(--fs-3); font-weight: 600; }
.ha-currency-cashier { background: var(--green-dim); color: var(--green-soft); }
.ha-currency-cashier:hover { background: rgba(204, 255, 0, .2); }
.ha-currency-menu :focus-visible { outline-offset: -2px; }
/* A docked chat narrows the header without changing the viewport width. */
@container arena-header (max-width: 1100px) {
  .ha-topnav-item span { display: none; }
  .ha-topnav-item { padding-inline: 11px; }
}
@media (min-width: 820px) and (max-width: 959px) {
  .ha-top { gap: 8px; padding-inline: 12px; }
  .ha-top-logo img { margin-right: 0; }
  .ha-topnav { margin-left: 0; gap: 4px; }
  .ha-topnav-item { padding-inline: 9px; }
}

.ha-pill {
  position: relative; overflow: hidden;
  display: flex; align-items: center; gap: 9px; height: 42px; padding: 0 var(--s4) 0 var(--s3);
  border-radius: var(--r-sm); font-weight: 600; font-size: var(--fs-4);
  background: var(--face), var(--brush);
  box-shadow: var(--slab);
  transition: box-shadow .25s, transform .2s var(--ease);
}
.ha-pill:hover { box-shadow: var(--slab-hi); transform: translateY(-1px); }
.ha-pill:active { transform: translateY(0); }
.ha-pill-balance { padding-right: 9px; gap: var(--s2); }
.ha-pill-balance #ha-balance-amt { font-size: var(--fs-6); line-height: 1; }
/* slow gold sheen crossing the vault. the only idle motion in the header. */
.ha-pill-balance::after {
  content: ''; position: absolute; top: -50%; bottom: -50%; left: -60%; width: 40%;
  background: linear-gradient(90deg, transparent, rgba(255, 243, 212, .1), transparent);
  transform: skewX(-18deg) translateX(0);
  animation: ha-sheen 7s ease-in-out infinite;
}
@keyframes ha-sheen { 0%, 62% { transform: skewX(-18deg) translateX(0); } 100% { transform: skewX(-18deg) translateX(560%); } }
/* the balance moved. the single most important number on the page says so. */
.ha-pill-balance.is-bump {
  animation: ha-bump .5s var(--ease);
  box-shadow: 0 0 0 1px rgba(232, 192, 122, .8), inset 0 1px 0 rgba(255, 255, 255, .2),
              0 4px 10px rgba(0, 0, 0, .55), 0 26px 48px -20px rgba(0, 0, 0, .95);
}
.ha-pill-balance.is-down {
  animation: ha-bump .5s var(--ease);
  box-shadow: 0 0 0 1px rgba(224, 84, 74, .85), inset 0 1px 0 rgba(255, 255, 255, .2),
              0 4px 10px rgba(0, 0, 0, .55), 0 26px 48px -20px rgba(0, 0, 0, .95);
}
@keyframes ha-bump { 0% { transform: scale(1); } 34% { transform: scale(1.055); } 100% { transform: scale(1); } }
.ha-pill-caret { flex-shrink: 0; color: var(--txt-mute); transition: color .2s, transform .2s var(--ease); }
.ha-pill-balance:hover .ha-pill-caret { color: var(--txt-dim); transform: translateY(1px); }
.ha-pill-wallet {
  padding: 0 var(--s4); color: var(--green-ink);
  background: linear-gradient(180deg, #ddff4d, #ccff00);
  box-shadow: 0 0 0 1px #7a9c00,
              inset 0 1px 0 rgba(255, 255, 255, .5), inset 0 -1px 0 rgba(0, 0, 0, .22),
              0 2px 6px rgba(0, 0, 0, .5), 0 10px 26px -14px rgba(204, 255, 0, .5);
}
.ha-pill-wallet:hover { background: linear-gradient(180deg, #e8ff80, #d9ff33); }
/* signed in: the label carries the address, so the button stops shouting and
   goes back to being chrome with the lime only as an outline */
.ha-pill-wallet.is-on {
  color: var(--green-soft);
  background: var(--face), var(--brush);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .08), 0 0 0 1px rgba(204, 255, 0, .4), 0 2px 6px rgba(0, 0, 0, .5);
}
/* avatar only, the way the reference has it: the name lives in the profile */
.ha-pill-profile { padding: 0; width: 42px; justify-content: center; }
.ha-pill-profile span { display: none; }
.ha-pill-profile img {
  width: 28px; height: 28px; border-radius: 50%; background: var(--panel-2); flex-shrink: 0;
  box-shadow: 0 0 0 1px rgba(255, 255, 255, .12), 0 0 0 3px rgba(0, 0, 0, .5);
}
.ha-pill-profile span {
  max-width: 130px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 600;
}

/* --- account panes -------------------------------------------------------
   The strip switches [hidden] on panes that are all built up front. It does
   not re-render: the locker pane holds a WebGL canvas whose context and raf
   loop would be thrown away and rebuilt on every switch. */
.ha-acct-tabs {
  display: flex; gap: 4px; margin: 0 0 var(--s5);
  padding: 4px; border-radius: var(--r-sm);
  background: rgba(0, 0, 0, .3); box-shadow: inset 0 0 0 1px var(--line-soft);
}
.ha-acct-tab {
  flex: 1; height: 38px; border-radius: var(--r-xs);
  font-size: var(--fs-4); font-weight: 700; letter-spacing: .04em;
  color: var(--txt-mute); transition: color .2s, background .2s, box-shadow .2s;
}
.ha-acct-tab:hover { color: var(--txt-dim); background: rgba(255, 255, 255, .04); }
.ha-acct-tab.is-on {
  color: var(--txt); background: var(--raise);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .08), 0 2px 6px rgba(0, 0, 0, .5);
}
.ha-acct-pane[hidden] { display: none !important; }

/* --- the account page ----------------------------------------------------
   Sections of rows: what a thing is on the left, what you can do about it on
   the right. Rows share one card so the dividers read as a list rather than
   as a stack of separate panels. */
/* centred: the page is a column of cards, and left-aligning it against a
   1900px window leaves two thirds of the screen empty beside it */
.ha-acct { max-width: 760px; margin: 0 auto; }
.ha-acct-h {
  font-family: var(--display); font-weight: 800; font-size: var(--fs-9);
  letter-spacing: .04em; margin: 0 0 var(--s5);
}
.ha-acct-sec {
  font-size: var(--fs-3); font-weight: 700; letter-spacing: .16em; text-transform: uppercase;
  color: var(--txt-mute); margin: var(--s6) 0 var(--s3);
}
.ha-acct-sec:first-of-type { margin-top: var(--s5); }
.ha-acct-card {
  border-radius: var(--r-sm); overflow: hidden;
  background: var(--face); box-shadow: var(--slab);
}
.ha-acct-row {
  display: flex; align-items: center; justify-content: space-between; gap: var(--s4);
  padding: var(--s4) var(--s5); min-height: 68px;
}
.ha-acct-row + .ha-acct-row { box-shadow: inset 0 1px 0 var(--line-soft); }
.ha-acct-lab { display: flex; align-items: center; gap: var(--s4); min-width: 0; }
.ha-acct-lab b { display: block; font-size: var(--fs-5); font-weight: 700; }
.ha-acct-lab span {
  display: block; margin-top: 2px; font-size: var(--fs-3); color: var(--txt-mute);
  overflow-wrap: anywhere;
}
.ha-acct-lab code { font-family: var(--num); font-size: var(--fs-3); color: var(--txt-dim); }
.ha-acct-act { display: flex; align-items: center; gap: 8px; flex-shrink: 0; }
.ha-sound-settings .ha-acct-row:first-child { flex-direction: row; align-items: center; }
.ha-sound-settings #ha-sound-enabled { flex: 0 0 44px; min-height: 44px; padding: 0 6px; }
.ha-sound-volume-row > label { font-size: var(--fs-4); font-weight: 600; }
.ha-sound-volume-control { display: flex; align-items: center; gap: 14px; width: min(100%, 300px); }
.ha-sound-volume-control input { min-width: 0; flex: 1; height: 44px; accent-color: var(--green); cursor: pointer; }
.ha-sound-volume-control output { min-width: 4ch; color: var(--txt-dim); font-variant-numeric: tabular-nums; text-align: right; }
.ha-sound-settings :is(button,input):focus-visible { outline: 2px solid var(--gold); outline-offset: 3px; }
.ha-acct-ava {
  border-radius: 50%; background: var(--panel-2); flex-shrink: 0;
  box-shadow: 0 0 0 1px rgba(255, 255, 255, .12), 0 0 0 3px rgba(0, 0, 0, .5);
}
/* the locker brings its own width; the rest of the page is a column */
.ha-acct-pane[data-pane="locker"] { max-width: none; }
@media (max-width: 640px) {
  .ha-acct-row { flex-direction: column; align-items: stretch; }
  .ha-acct-act { justify-content: stretch; }
  .ha-acct-act .ha-btn { flex: 1; }
}

/* the price of a voice, said where the box is */
.ha-chat-gate {
  display: flex; align-items: flex-start; gap: 9px; min-width: 0; padding: 11px 12px;
  border: 1px solid var(--line-soft); border-radius: 8px;
  font-size: 12px; line-height: 1.5; color: var(--txt-dim); background: rgba(255, 255, 255, .025);
}
.ha-chat-gate > svg { flex: 0 0 16px; width: 16px; height: 16px; margin-top: 2px; color: var(--txt-mute); }
.ha-chat-gate > div { min-width: 0; overflow-wrap: anywhere; }
.ha-chat-gate strong { display: block; font-weight: 500; color: var(--txt-dim); }
.ha-chat-gate span { display: block; margin-top: 3px; font-size: 11px; color: var(--txt-mute); font-variant-numeric: tabular-nums; }
.ha-chat-foot input:disabled { opacity: .55; cursor: not-allowed; }
.ha-chat-foot .ha-btn:disabled { opacity: .45; cursor: not-allowed; }

/* --- the cashier ---------------------------------------------------------
   One mode at a time. The field means one thing, and there is one button to
   press, so nothing has to be read twice to work out what it will do. */
.ha-cashier h3 { margin: 0 0 var(--s3); }
.ha-cash-lede { margin: 0 0 var(--s5); color: var(--txt-mute); font-size: var(--fs-4); }
.ha-cash-switch {
  display: flex; gap: 4px; padding: 4px; margin-bottom: var(--s5);
  border-radius: var(--r-sm); background: rgba(0, 0, 0, .3);
  box-shadow: inset 0 0 0 1px var(--line-soft);
}
.ha-cash-mode {
  flex: 1; height: 44px; border-radius: var(--r-xs);
  font-size: var(--fs-4); font-weight: 700; color: var(--txt-mute);
  transition: color .2s, background .2s, box-shadow .2s;
}
.ha-cash-mode:hover { color: var(--txt-dim); background: rgba(255, 255, 255, .04); }
.ha-cash-mode.is-on {
  color: var(--txt); background: var(--raise);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .08), 0 2px 6px rgba(0, 0, 0, .5);
}
.ha-cash-avail {
  display: flex; align-items: baseline; justify-content: space-between; gap: var(--s3);
  padding: var(--s4); margin-bottom: var(--s5); border-radius: var(--r-sm);
  background: var(--face); box-shadow: var(--slab);
}
.ha-cash-avail span { font-size: var(--fs-3); color: var(--txt-mute); }
.ha-cash-avail b { font-family: var(--num); font-size: var(--fs-7); }
.ha-cash-lab {
  display: block; margin-bottom: 6px;
  font-size: var(--fs-3); font-weight: 700; letter-spacing: .14em; text-transform: uppercase;
  color: var(--txt-mute);
}
/* Max sits inside the field, because it is a way of filling the field in */
/* A figure larger than there is: the field says so and the button stands down,
   rather than letting the contract refuse it after a wallet prompt. */
.ha-cash-field.is-over input { box-shadow: var(--sink), 0 0 0 1px #e0996a; }
.ha-cash-over { margin: -8px 0 12px; font-size: 13px; line-height: 1.5; color: #e0996a; }
.ha-cash-field { position: relative; margin-bottom: var(--s4); }
.ha-cash-field input {
  width: 100%; height: 54px; padding: 0 78px 0 var(--s4);
  border-radius: var(--r-sm); font-family: var(--num); font-size: var(--fs-7);
  color: var(--txt); background: var(--panel); box-shadow: var(--sink);
}
.ha-cash-field input:focus { outline: none; box-shadow: var(--sink), 0 0 0 2px var(--green); }
.ha-cash-field button {
  position: absolute; right: 8px; top: 50%; transform: translateY(-50%);
  height: 44px; padding: 0 14px; border-radius: var(--r-xs);
  font-size: var(--fs-3); font-weight: 800; letter-spacing: .1em; text-transform: uppercase;
  color: var(--green-soft); background: var(--green-dim);
  box-shadow: inset 0 0 0 1px rgba(204, 255, 0, .35);
  transition: color .2s, background .2s;
}
.ha-cash-field button:hover { color: var(--green-ink); background: var(--green); }
.ha-cash-go { width: 100%; }
.ha-cash-mini {
  display: flex; flex-wrap: wrap; gap: var(--s3) var(--s5); margin-top: var(--s4);
  font-size: var(--fs-3); color: var(--txt-mute);
}
.ha-cash-mini b { font-family: var(--num); color: var(--txt-dim); }
.ha-cash-foot {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
  gap: var(--s3); margin-top: var(--s5); padding-top: var(--s4);
  box-shadow: inset 0 1px 0 var(--line-soft);
}
.ha-cash-buy { font-size: var(--fs-4); font-weight: 700; color: var(--gold); }
.ha-cash-buy:hover { color: var(--gold-hi); }
.ha-cash-note { font-size: var(--fs-3); color: var(--txt-mute); }

/* a result you can watch again says so before you click it */
.ha-card.is-replayable { cursor: pointer; }
.ha-card.is-replayable:hover { box-shadow: var(--slab-hi); transform: translateY(-2px); }
.ha-card.is-replayable:focus-visible { outline: 2px solid var(--green-soft); outline-offset: 3px; }

/* what the board is actually showing, under its heading */
.ha-lb-note {
  margin: -6px 0 var(--s5); font-size: var(--fs-4); color: var(--txt-mute);
}
.ha-lb-note b { color: var(--green-soft); font-weight: 700; }

/* ------------------------------ main column -------------------------------- */
.ha-main {
  flex: 1; min-height: 0; overflow-y: auto; overflow-x: hidden;
  padding: var(--s6) var(--s6) 56px; scroll-behavior: smooth;
  /* Reserve the scrollbar's gutter whether or not it is needed. This column is
     the scroller, so without it a tall page took width away from its own
     content and every centred thing inside shifted by half a scrollbar the
     moment you moved between a short tab and a long one. */
  scrollbar-gutter: stable;
}

/* =============================================================================
   HERO — an arena plate with the house numbers on it, not a landing page.
   No eyebrow pill, no fact strip. The only static claim is the headline; the
   rest of the block is live and changes while you look at it.
   ============================================================================= */
.ha-hero {
  position: relative; overflow: hidden; isolation: isolate;
  border-radius: var(--r-lg); margin-bottom: var(--s7); padding: var(--s7) var(--s7) var(--s6);
  min-height: 340px; display: flex; align-items: flex-end;
  /* the light sits on the RIGHT, opposite the type, so the plate's dark stone
     silhouette has something to read against instead of vanishing into it. */
  background:
    var(--sheen),
    radial-gradient(120% 132% at 72% 2%, #28323f 0%, #161d27 36%, #0a0d13 70%, #07090c 100%),
    var(--grain);
  box-shadow: var(--slab-lg);
  animation: ha-rise .7s var(--ease) both;
}
/* z-index 0, NOT -2. a negative-index child paints beneath the parent's own
   background layers, which is how the sheen and grain went missing before. */
.ha-hero > img {
  position: absolute; inset: 0; z-index: 0;
  /* The art puts the fighters hard right with empty dark on the left, which
     is where the type and the scrim are. Cover crops ~35px of height on a
     3.34:1 box, and 74% pushed that crop onto their heads and the crystal. */
  width: 100%; height: 100%; object-fit: cover; object-position: 100% 34%;
}
.ha-hero-fx { position: absolute; inset: 0; z-index: 1; pointer-events: none; }
/* legibility scrim, weighted left where the type sits, so the plate stays
   genuinely visible on the right instead of being a texture nobody can see. */
.ha-hero-fx::before {
  content: ''; position: absolute; inset: 0;
  background:
    linear-gradient(96deg, rgba(6, 7, 10, .94) 0%, rgba(6, 7, 10, .8) 26%, rgba(6, 7, 10, .3) 52%, rgba(6, 7, 10, .04) 78%, transparent 100%),
    linear-gradient(180deg, rgba(6, 7, 10, .45), transparent 30%);
}
.ha-hero-fx::after {
  content: ''; position: absolute; left: -30%; right: -30%; top: 0; height: 100%;
  background: radial-gradient(60% 46% at 50% 8%, rgba(150, 178, 210, .08), transparent 68%);
  animation: ha-breathe 14s ease-in-out infinite;
}
@keyframes ha-breathe { 0%, 100% { opacity: .55; } 50% { opacity: 1; } }
.ha-hero::after {          /* GOLD SEAM 2 of 7 — picks up the plate's horizon */
  content: ''; position: absolute; left: 0; right: 0; bottom: 0; height: 1px; z-index: 2;
  background: linear-gradient(90deg, transparent, rgba(232, 192, 122, .38) 30%, rgba(232, 192, 122, .1) 70%, transparent);
}

.ha-hero-in { position: relative; z-index: 3; width: 100%; max-width: 660px; }
.ha-hero-title {
  font-family: var(--display); font-weight: 900;
  font-size: clamp(40px, 6.6vw, 78px); line-height: .94; letter-spacing: .04em;
  text-transform: uppercase; margin-bottom: var(--s4);
  background: linear-gradient(176deg, #ffffff 0%, #dfe7ee 32%, #8e9ba8 78%, #5c6773 100%);
  -webkit-background-clip: text; background-clip: text; color: transparent; -webkit-text-fill-color: transparent;
  filter: drop-shadow(0 2px 0 rgba(0, 0, 0, .8)) drop-shadow(0 14px 34px rgba(0, 0, 0, .8));
}
.ha-hero-title em {
  font-style: normal; display: block;
  background: linear-gradient(176deg, var(--gold-hi), var(--gold) 46%, var(--gold-lo));
  -webkit-background-clip: text; background-clip: text; color: transparent; -webkit-text-fill-color: transparent;
}
.ha-hero-sub {
  font-size: var(--fs-6); color: var(--txt-dim); max-width: 48ch; margin-bottom: var(--s6); line-height: 1.6;
}

/* Compact token overview: identity, holder allocation and two clear actions. */
.ha-hero-coin {
  width: 336px; max-width: 100%; padding: var(--s3);
  border: 1px solid var(--edge); border-radius: var(--r-sm);
  background: var(--panel-2);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .025), 0 8px 24px rgba(0, 0, 0, .14);
}
.ha-cash-token { position: relative; margin-bottom: var(--s2); }
.ha-cash-token img { position: absolute; left: 14px; top: 50%; transform: translateY(-50%); object-fit: contain; pointer-events: none; }
.ha-cash-token select {
  display: block; width: 100%; height: 58px; padding: 0 40px 0 54px;
  border: 1px solid var(--edge); border-radius: var(--r-sm); appearance: none;
  background: var(--panel-2) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='m4 6 4 4 4-4' fill='none' stroke='%23a7b4c0' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") no-repeat right 14px center / 16px;
  color: var(--txt); font-size: var(--fs-5); font-weight: 600; cursor: pointer;
}
.ha-cash-token select:focus-visible { outline: 2px solid var(--green-soft); outline-offset: 2px; }
.ha-cash-token option { color: var(--txt); background: var(--panel-2); }
.ha-cash-token.is-custom > img, .ha-cash-token select[hidden] { display: none; }
.ha-cash-choice { display: grid; grid-template-columns: 28px minmax(0, 1fr) minmax(0, 1.2fr) 12px; align-items: center; gap: 12px; width: 100%; min-height: 64px; padding: 12px 14px; text-align: left; border: 1px solid var(--edge); border-radius: var(--r-sm); background: var(--panel-2); color: var(--txt); cursor: pointer; }
.ha-cash-choice img { position: static; transform: none; width: 28px; height: 28px; object-fit: contain; }
.ha-cash-choice-id, .ha-cash-choice-balance { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.ha-cash-choice b { font-size: 14px; font-weight: 700; line-height: 1.35; overflow-wrap: anywhere; }
.ha-cash-choice small { font-size: 11px; font-weight: 400; line-height: 1.4; color: var(--txt-mute); }
.ha-cash-choice-balance { text-align: right; }
.ha-cash-choice-balance b { font-family: var(--num); font-variant-numeric: tabular-nums; }
.ha-cash-choice-chevron { width: 7px; height: 7px; border-right: 1.5px solid currentColor; border-bottom: 1.5px solid currentColor; transform: rotate(45deg); }
.ha-cash-choice[aria-expanded="true"] .ha-cash-choice-chevron { transform: rotate(225deg); }
.ha-cash-choice-check { color: var(--green); visibility: hidden; }
.ha-cash-choice[aria-selected="true"] { background: rgba(204, 255, 0, .06); }
.ha-cash-choice[aria-selected="true"] .ha-cash-choice-check { visibility: visible; }
.ha-cash-choice:hover { background: rgba(255, 255, 255, .04); }
.ha-cash-choice:focus-visible { outline: 2px solid var(--green); outline-offset: -2px; }
.ha-cash-choices { margin-top: 6px; padding: 4px; background: #0c1117; border: 1px solid var(--edge); border-radius: var(--r-sm); }
.ha-cash-choices[hidden] { display: none; }
.ha-cash-choices .ha-cash-choice { border-color: transparent; }
@media (max-width: 520px) {
  .ha-cash-choice { grid-template-columns: 24px minmax(0, .8fr) minmax(0, 1.2fr) 10px; gap: 8px; padding: 10px; }
  .ha-cash-choice img { width: 24px; height: 24px; }
  .ha-cash-choice b { font-size: 13px; }
  .ha-cash-choice small { font-size: 10px; }
}
.ha-cash-currency-note { margin: 0 0 var(--s5); color: var(--txt-dim); font-size: var(--fs-3); line-height: 1.6; }
.ha-cash-currency-note.is-upcoming { padding: var(--s3); border-radius: var(--r-xs); background: rgba(232, 192, 122, .07); color: var(--gold-hi); }
.ha-cashier :disabled { cursor: not-allowed; opacity: .5; }
.ha-cashier .ha-btn:disabled { transform: none; }
.ha-cash-avail { flex-wrap: wrap; }
.ha-cash-avail b { overflow-wrap: anywhere; }
.ha-hcoin-id { display: flex; align-items: center; gap: var(--s3); min-width: 0; }
.ha-hcoin-mark {
  display: grid; place-items: center; flex: 0 0 48px; height: 48px;
  border: 1px solid var(--edge); border-radius: var(--r-xs); background: var(--bg);
}
.ha-hcoin-mark img { display: block; }
.ha-hcoin-info { min-width: 0; flex: 1; }
.ha-hcoin-title { display: flex; align-items: center; flex-wrap: wrap; gap: 5px var(--s2); }
.ha-hcoin-title > b { font-size: var(--fs-5); font-weight: 700; line-height: 1.4; }
.ha-hcoin-ticker {
  max-width: 100%; padding: 2px 5px; border-radius: 4px;
  font-size: 10px; font-weight: 600; line-height: 1.4; letter-spacing: .03em;
  color: var(--txt-dim); background: rgba(255, 255, 255, .06); overflow-wrap: anywhere;
}
.ha-hcoin-fig { margin: 5px 0 0; font-size: var(--fs-3); line-height: 1.5; color: var(--txt-dim); overflow-wrap: anywhere; }
.ha-hcoin-fig b { font-family: var(--num); font-weight: 600; color: var(--green); }
.ha-hcoin-actions { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: var(--s2); margin-top: var(--s3); }
.ha-hcoin-go { min-width: 0; }
.ha-hcoin-actions .ha-btn {
  width: 100%; min-width: 0; height: auto; min-height: 44px; padding: 8px;
  border: 1px solid transparent; border-radius: var(--r-xs);
  font-size: var(--fs-3); font-weight: 600; line-height: 1.4; letter-spacing: 0; text-transform: none;
  white-space: normal; overflow-wrap: anywhere; box-shadow: none;
  color: var(--txt); background: var(--raise-2);
}
.ha-hcoin-actions .ha-btn:hover { background: #28323e; }
.ha-hcoin-actions .ha-hcoin-get { color: var(--green-soft); background: var(--green-dim); border-color: rgba(204, 255, 0, .16); }
.ha-hcoin-actions .ha-hcoin-get:hover { background: rgba(204, 255, 0, .2); border-color: rgba(204, 255, 0, .35); }

/* .ha-tick is the hero's old counter cell. The hero no longer has counters,
   but the leaderboard's marks strip is the same material, so the shared rules
   stay under .ha-mark. */
.ha-tick, .ha-mark {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 0 7px;
  padding: 11px var(--s3) 10px; min-width: 0;
  background: linear-gradient(180deg, rgba(19, 24, 31, .94), rgba(10, 13, 18, .94));
}
.ha-tick .ha-online-dot { align-self: center; }
.ha-tick b, .ha-mark b { font-size: var(--fs-7); line-height: 1.1; }
.ha-tick span, .ha-mark span {
  font-size: var(--fs-3); color: var(--txt-mute); line-height: 1.35;
  flex: 1 1 100%; min-width: 0;
}
.ha-mark span { flex-basis: auto; width: 100%; }
/* the pit is hot while anyone is in it */
.ha-tick.is-live { background: linear-gradient(180deg, rgba(30, 20, 19, .95), rgba(16, 10, 10, .95)); }
.ha-tick.is-live b {
  background: linear-gradient(180deg, #ffd0c9, var(--red-hot) 52%, #9c2f26);
  -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent;
}
.ha-tick.is-live span { color: #c99089; }

/* -------------------------------- sections ---------------------------------- */
.ha-sec { margin-bottom: var(--s7); }
/* h2 → engraved rule → actions, all as flex order. the rule fills whatever is
   left, so the header terminates itself and still wraps correctly. */
.ha-sec-head {
  display: flex; align-items: center; gap: var(--s3) var(--s4); flex-wrap: wrap; margin-bottom: var(--s5);
}
.ha-sec-head h2 {
  order: 0; display: flex; align-items: center; gap: var(--s3);
  font-family: var(--display); font-weight: 700; font-size: var(--fs-8);
  letter-spacing: .1em; text-transform: uppercase; color: #e6ecf2;
}
.ha-sec-head h2::before {
  content: ''; width: 3px; height: 20px; border-radius: 2px; flex-shrink: 0;
  background: linear-gradient(180deg, var(--gold-hi), var(--gold-lo));
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .5), 0 1px 2px rgba(0, 0, 0, .8);
}
.ha-sec-head::after {      /* GOLD SEAM 3 of 7 */
  content: ''; order: 1; flex: 1 1 40px; height: 1px; min-width: 40px;
  background: linear-gradient(90deg, rgba(232, 192, 122, .34), rgba(255, 255, 255, .07) 34%, transparent);
}
.ha-sec-actions { order: 2; display: flex; align-items: center; gap: 9px; flex-wrap: wrap; }
/* Its sibling had no rule at all, so the buttons in a section's tool row sat
   flush against each other. Same row, same spacing. */
.ha-sec-tools { display: flex; align-items: center; gap: 9px; flex-wrap: wrap; }

/* The board bar: which slice of the board you are looking at, and the controls
   that refine it. Built from the same segmented control the account tabs use,
   so a game board and a settings page read as one product. Both games share it. */
.ha-board-bar { display: flex; align-items: center; gap: var(--s4); flex-wrap: wrap; margin: 0 0 var(--s5); }
.ha-board-bar .ha-sec-actions { margin-left: auto; }
.ha-status-filters {
  display: flex; align-items: center; gap: 4px; padding: 4px;
  border-radius: var(--r-sm); background: rgba(0, 0, 0, .3);
  box-shadow: inset 0 0 0 1px var(--line-soft);
}
.ha-status-filters button {
  min-height: 34px; padding: 0 var(--s3); border-radius: var(--r-xs);
  font-size: var(--fs-3); font-weight: 700; letter-spacing: .04em;
  color: var(--txt-mute); white-space: nowrap;
  transition: color .2s, background .2s, box-shadow .2s;
}
.ha-status-filters button:hover { color: var(--txt-dim); background: rgba(255, 255, 255, .04); }
.ha-status-filters button[aria-pressed="true"], .ha-status-filters button[aria-selected="true"] {
  color: var(--txt); background: var(--raise);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .08), 0 2px 6px rgba(0, 0, 0, .5);
}
.ha-status-filters button:focus-visible { outline: 2px solid var(--green-soft); outline-offset: -2px; }
.ha-status-filters .ha-count { margin-left: 6px; }
@media (max-width: 820px) {
  .ha-board-bar { gap: var(--s3); }
  .ha-status-filters { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); width: 100%; }
  .ha-status-filters button { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 4px; min-width: 0; min-height: 60px; padding: 6px 4px; font-size: 11px; letter-spacing: 0; }
  .ha-status-filters button .ha-count { margin-left: 0; }
  .ha-board-bar .ha-sec-actions { margin-left: 0; width: 100%; }
}
@media (max-width: 380px) { .ha-status-filters button { font-size: 10px; } }
.ha-count {
  font-size: var(--fs-3); font-weight: 700; color: var(--txt-dim);
  border-radius: var(--r-pill); min-width: 28px; height: 24px; padding: 0 9px;
  display: inline-flex; align-items: center; justify-content: center;
  background: rgba(255, 255, 255, .04);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .06), inset 0 1px 0 rgba(255, 255, 255, .06);
}

/* --------------------------- controls: selects ------------------------------ */
.ha-select {
  height: 42px; padding: 0 34px 0 var(--s3); border: 0; border-radius: var(--r-sm);
  font-size: var(--fs-4); font-weight: 600; color: var(--txt-dim); appearance: none; cursor: pointer;
  background-color: transparent;
  background-image:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M1 1l4 4 4-4' stroke='%237e8b98' stroke-width='1.6' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E"),
    linear-gradient(180deg, #151a21, #101419);
  background-repeat: no-repeat, no-repeat;
  background-position: right var(--s3) center, 0 0;
  background-size: 10px 6px, 100% 100%;
  box-shadow: var(--slab);
  transition: box-shadow .22s, color .2s;
}
.ha-select:hover { color: var(--txt); box-shadow: var(--slab-hi); }
.ha-select:focus { outline: none; box-shadow: 0 0 0 2px var(--green), var(--slab); }
.ha-select option { background: #0f141a; color: var(--txt); }

/* -------------------------------- buttons ----------------------------------- */
.ha-btn {
  position: relative; overflow: hidden;
  display: inline-flex; align-items: center; justify-content: center; gap: var(--s2);
  height: 42px; padding: 0 var(--s5); border-radius: var(--r-sm);
  font-size: var(--fs-3); font-weight: 700; letter-spacing: .1em; text-transform: uppercase;
  white-space: nowrap;
  transition: transform .16s var(--ease), box-shadow .22s, background .22s, color .2s;
}
.ha-btn svg { width: 15px; height: 15px; flex-shrink: 0; }
.ha-btn > span { overflow: hidden; text-overflow: ellipsis; min-width: 0; }
.ha-btn:active { transform: translateY(1px) scale(.995); }

.ha-btn-green {
  color: #141a00;
  background: linear-gradient(180deg, #ddff4d 0%, #ccff00 52%, #a8d400 100%);
  box-shadow:
    0 0 0 1px #7a9c00,
    inset 0 1px 0 rgba(255, 255, 255, .55), inset 0 -1px 0 rgba(0, 0, 0, .3),
    0 2px 6px rgba(0, 0, 0, .5), 0 12px 26px -14px rgba(0, 0, 0, .95);
}
.ha-btn-green:hover {
  background: linear-gradient(180deg, #e8ff80 0%, #d9ff33 52%, #b8e600 100%);
  box-shadow:
    0 0 0 1px #8fb300,
    inset 0 1px 0 rgba(255, 255, 255, .7), inset 0 -1px 0 rgba(0, 0, 0, .3),
    0 3px 8px rgba(0, 0, 0, .55), 0 16px 30px -14px rgba(0, 0, 0, 1);
}
.ha-btn-gold {
  color: #2a1d06;
  background: linear-gradient(180deg, var(--gold-hi) 0%, var(--gold) 48%, #c99a45 100%);
  box-shadow:
    0 0 0 1px #8a6323,
    inset 0 1px 0 rgba(255, 255, 255, .7), inset 0 -1px 0 rgba(0, 0, 0, .25),
    0 2px 6px rgba(0, 0, 0, .5), 0 12px 26px -14px rgba(0, 0, 0, .95);
}
.ha-btn-gold:hover {
  background: linear-gradient(180deg, #fffaea 0%, #f3d193 48%, #d5a851 100%);
  box-shadow:
    0 0 0 1px #a9772a,
    inset 0 1px 0 rgba(255, 255, 255, .85), inset 0 -1px 0 rgba(0, 0, 0, .25),
    0 3px 8px rgba(0, 0, 0, .55), 0 16px 30px -14px rgba(0, 0, 0, 1);
}
.ha-btn-ghost {
  color: var(--txt-dim);
  background: var(--face), var(--brush);
  box-shadow: var(--slab);
}
.ha-btn-ghost:hover { color: var(--txt); box-shadow: var(--slab-hi); }
.ha-btn-lg { height: 50px; padding: 0 var(--s6); font-size: var(--fs-4); letter-spacing: .12em; border-radius: var(--r-sm); }
/* one specular pass on hover. compositor only, and it never runs idle. */
.ha-btn::after {
  content: ''; position: absolute; top: -60%; bottom: -60%; left: -40%; width: 34%;
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, .3), transparent);
  transform: skewX(-20deg) translateX(-260%); opacity: 0;
}
.ha-btn:hover::after { opacity: 1; transition: transform .7s var(--ease), opacity .1s; transform: skewX(-20deg) translateX(560%); }

/* =============================================================================
   DUEL GRID — a board of struck vault tickets.
   Halves are SYMMETRIC. The medallion sits in the avatar band and clears the
   names vertically, so nothing has to lean and the two HP bars mirror exactly
   around the card centre, which is the comparison the eye makes in a fight.
   ============================================================================= */
.ha-grid { display: grid; gap: var(--s3); grid-template-columns: repeat(auto-fill, minmax(292px, 1fr)); }
.ha-grid > *:nth-child(2) { animation-delay: 30ms; }
.ha-grid > *:nth-child(3) { animation-delay: 60ms; }
.ha-grid > *:nth-child(4) { animation-delay: 90ms; }
.ha-grid > *:nth-child(n + 5) { animation-delay: 115ms; }

.ha-empty:has(.ha-lobby-empty) {
  /* it is holding the shared empty block, which brings its own panel: two
     nested panels read as a mistake */
  padding: 0; background: none; box-shadow: none; border: 0;
}
.ha-empty:has(.ha-lobby-empty)::before { content: none; }
.ha-lobby-empty {
  grid-column: 1 / -1; display: grid; grid-template-columns: 100px minmax(0, 1fr) auto;
  align-items: center; gap: 24px; min-height: 132px; padding: 16px 24px;
  border: 1px dashed var(--line); border-radius: 12px; background: var(--bg-soft); text-align: left;
}
.ha-lobby-empty > img { display: block; width: 100px; height: 100px; object-fit: contain; }
.ha-lobby-empty > div { min-width: 0; }
.ha-lobby-empty b { display: block; margin-bottom: 7px; color: var(--txt); font: 600 14px/1.5 var(--font); }
.ha-lobby-empty span { display: block; max-width: 480px; color: var(--txt-mute); font-size: 12px; line-height: 1.7; }
.ha-lobby-empty .ha-btn { min-height: 44px; font-size: 10px; }
@media (max-width: 819px) {
  .ha-board-bar .ha-sec-actions { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
  .ha-board-bar .ha-sec-actions > :is(select, button) { width: 100%; min-width: 0; }
  .ha-board-bar .ha-sec-actions > .ha-btn { grid-column: 1 / -1; min-height: 44px; }
  .ha-lobby-empty { grid-template-columns: 72px minmax(0, 1fr); gap: 12px 16px; padding: 16px; }
  .ha-lobby-empty > img { width: 72px; height: 72px; }
  .ha-lobby-empty .ha-btn { grid-column: 2; justify-self: start; }
}
.ha-empty {
  position: relative; overflow: hidden;
  padding: var(--s7) var(--s6); text-align: center; font-size: var(--fs-4); color: var(--txt-dim);
  border-radius: var(--r);
  background:
    linear-gradient(0deg, rgba(204, 255, 0, .05), transparent 34%),
    linear-gradient(180deg, rgba(255, 255, 255, .015), transparent 60%), var(--grain), var(--bg-soft);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, .05), 0 0 0 1px rgba(255, 255, 255, .045),
    inset 0 -1px 0 rgba(204, 255, 0, .3);
}
.ha-empty::before {   /* the arena mark, watermarked. overflow:hidden above keeps it safe at 375px.
     Was a crest of a figure inside a ringed dial, which read as a clock face
     rather than as anything to do with duelling. */
  content: ''; position: absolute; right: -20px; bottom: -30px; width: 172px; height: 172px;
  background: url("/mark-arena.svg") center / contain no-repeat; opacity: .09; pointer-events: none;
}
.ha-empty[hidden] { display: none; }

.ha-card {
  position: relative; overflow: hidden; border-radius: var(--r);
  display: flex; flex-direction: column;   /* the stake plinth always seats on the floor */
  background:
    linear-gradient(157deg, rgba(255, 255, 255, .085) 0%, rgba(255, 255, 255, .022) 26%, transparent 54%),
    radial-gradient(120% 80% at 50% 0%, rgba(120, 150, 190, .07), transparent 62%),
    linear-gradient(180deg, #1a212b 0%, #121821 34%, var(--card) 74%, #090c11 100%),
    var(--grain);
  box-shadow: var(--slab);
  transition: transform .28s var(--ease), box-shadow .28s;
  animation: ha-deal .42s var(--ease) both;
}
@keyframes ha-deal { from { opacity: 0; transform: translateY(14px) scale(.985); } }
@keyframes ha-rise { from { opacity: 0; transform: translateY(18px); } }
.ha-card::before {   /* the lit bevel across the top edge */
  content: ''; position: absolute; left: 12%; right: 12%; top: 0; height: 1px; z-index: 3;
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, .55), transparent);
  opacity: .8; transition: opacity .28s, left .35s var(--ease), right .35s var(--ease);
}
.ha-card-body { position: relative; flex: 1; display: flex; align-items: stretch; overflow: hidden; }
/* signal edge: the card is typed by what it CONTAINS. no markup, no JS. */
.ha-card-body::before {
  content: ''; position: absolute; left: 0; top: 0; bottom: 0; width: 2px; z-index: 4;
  background: rgba(255, 255, 255, .07);
}
.ha-card:has(.ha-half-join) .ha-card-body::before { background: linear-gradient(180deg, var(--green-soft), var(--green-dark)); }
.ha-card:has(.ha-mini-actions) .ha-card-body::before { background: linear-gradient(180deg, var(--gold-hi), var(--gold-lo)); }
.ha-card:has(.ha-replay-btn) .ha-card-body::before { background: linear-gradient(180deg, rgba(255, 255, 255, .16), rgba(255, 255, 255, .04)); }
.ha-card-live .ha-card-body::before { background: linear-gradient(180deg, var(--red-hot), #7a1f18); }

.ha-half {
  flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; align-items: center;
  gap: 9px; padding: var(--s4) 10px var(--s3); position: relative;
}
.ha-half + .ha-half::before {
  content: ''; position: absolute; left: 0; top: 70px; bottom: 0; width: 1px;
  background: linear-gradient(180deg, transparent, var(--line) 30%, var(--line));
}
.ha-ava { position: relative; }
.ha-ava img {
  width: 52px; height: 52px; border-radius: 50%; object-fit: cover; background: var(--panel-2);
  box-shadow:
    0 0 0 1px rgba(255, 255, 255, .14), 0 0 0 4px rgba(0, 0, 0, .55),
    0 8px 18px -8px rgba(0, 0, 0, .9), inset 0 1px 0 rgba(255, 255, 255, .1);
  transition: box-shadow .28s;
}
.ha-card:hover .ha-ava img { box-shadow: 0 0 0 1px rgba(255, 255, 255, .22), 0 0 0 4px rgba(0, 0, 0, .55), 0 10px 22px -8px rgba(0, 0, 0, .9); }
.ha-ava .ha-rank {
  position: absolute; right: -4px; bottom: -2px; width: 19px; height: 19px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: linear-gradient(180deg, #1a212a, var(--card));
  box-shadow: 0 0 0 1px rgba(232, 192, 122, .3), 0 3px 8px rgba(0, 0, 0, .8), inset 0 1px 0 rgba(255, 255, 255, .18);
}
.ha-ava .ha-rank img { width: 11px; height: 11px; border-radius: 0; background: none; box-shadow: none; }
/* the badge drops under the name instead of eating it on a narrow column */
.ha-name {
  display: flex; align-items: center; justify-content: center; flex-wrap: wrap;
  gap: 5px 3px; max-width: 100%; text-align: center;
  font-size: var(--fs-4); font-weight: 700; letter-spacing: .04em;
}
.ha-name > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; max-width: 100%; }
.ha-lost { opacity: .48; }
.ha-lost .ha-ava img { filter: grayscale(1); box-shadow: 0 0 0 1px rgba(224, 84, 74, .28), 0 0 0 4px rgba(0, 0, 0, .55); }
.ha-lost .ha-name { color: #b1868a; }

/* Equipped badges use their original artwork, without a text-chip backing. */
.ha-badge {
  display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0;
  width: 28px; height: 28px; padding: 0; border-radius: 0;
  background: none; box-shadow: none; line-height: 0; vertical-align: middle;
}
.ha-badge > img { display: block; width: 100%; height: 100%; object-fit: contain; border-radius: 0; background: none; box-shadow: none; }
.ha-player-badges .ha-badge { width: 32px; height: 32px; }

/* --- the weapon seal: knurled ring, gold rim, sunk into the seam ----------- */
.ha-vs {
  position: absolute; left: 50%; top: var(--s3); z-index: 5;
  transform: translateX(-50%);
  width: 50px; height: 50px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  border: 1px solid transparent;
  /* gradient rim via border-box, face via padding-box. a solid border colour
     cannot do a rim that shades round the circle. */
  background:
    radial-gradient(circle at 50% 28%, rgba(255, 255, 255, .13), transparent 60%) padding-box,
    repeating-conic-gradient(from 200deg, #1e252f 0deg 7deg, #0b0f14 7deg 14deg) padding-box,
    linear-gradient(180deg, rgba(232, 192, 122, .6), rgba(232, 192, 122, .12) 55%, rgba(232, 192, 122, .34)) border-box;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, .2), inset 0 0 0 4px rgba(0, 0, 0, .4),
    0 8px 20px -8px rgba(0, 0, 0, .95);
  transition: transform .4s var(--ease), box-shadow .3s;
}
.ha-card:hover .ha-vs {
  transform: translateX(-50%) rotate(-8deg) scale(1.07);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .3), inset 0 0 0 4px rgba(0, 0, 0, .4), 0 12px 28px -8px rgba(0, 0, 0, 1);
}
.ha-vs svg, .ha-vs > div, .ha-wpn-art { width: 30px; height: 30px; display: block; }
.ha-vs .ha-wpn-art { filter: drop-shadow(0 2px 3px rgba(0, 0, 0, .8)); }
/* each weapon strikes its own seal */
.ha-card[data-weapon="heartwood"] .ha-vs { background:
  radial-gradient(circle at 50% 28%, rgba(180, 255, 200, .12), transparent 60%) padding-box,
  repeating-conic-gradient(from 200deg, #1a2620 0deg 7deg, #0a110d 7deg 14deg) padding-box,
  linear-gradient(180deg, rgba(232, 192, 122, .6), rgba(232, 192, 122, .12) 55%, rgba(232, 192, 122, .34)) border-box; }

/* --- stake plinth: the loudest number on the card ------------------------- */
.ha-stake {
  position: relative;
  display: flex; align-items: center; gap: 10px;
  padding: var(--s3) var(--s4);
  background: linear-gradient(180deg, rgba(0, 0, 0, .34), rgba(0, 0, 0, .52)), var(--brush);
  /* GOLD SEAM 4 of 7, as a bevel rather than another pseudo */
  box-shadow: inset 0 1px 0 rgba(232, 192, 122, .26);
}
/* ledger rails. turns a number into an entry in a book. */
.ha-stake::before, .ha-stake::after {
  content: ''; flex: 1 1 auto; min-width: var(--s2); height: 1px; background: var(--ticks); opacity: .5;
}
.ha-stake span {
  font-size: var(--fs-8); line-height: 1.15;
  filter: drop-shadow(0 1px 0 rgba(0, 0, 0, .9));
}
.ha-stake .ha-coin { width: 17px; height: 17px; }

/* Shared winner enamel, including recent results and battle presentations. */
.ha-win-tag {
  font-size: var(--fs-1); font-weight: 800; letter-spacing: .16em; line-height: 1;
  color: #2a1d06; padding: 5px 10px 4px; border-radius: var(--r-chip); text-transform: uppercase;
  background: linear-gradient(180deg, var(--gold-hi) 0%, var(--gold) 48%, #c1913f 100%);
  box-shadow: 0 0 0 1px #8a6323, inset 0 1px 0 rgba(255, 255, 255, .8), 0 2px 6px rgba(0, 0, 0, .7);
}
.ha-half-id { display: flex; flex-direction: column; align-items: center; gap: 5px; min-width: 0; }
/* A reserved label row keeps every portrait aligned. The winner label lives
   above its own portrait in normal flow on Duels, Chest Battle and Jackpot. */
.ha-result-portrait {
  display: grid; grid-template-rows: 20px auto; justify-items: center; align-items: start;
  gap: 10px; min-width: 76px; flex-shrink: 0;
}
.ha-result-portrait > .ha-win-tag { grid-row: 1; white-space: nowrap; }
.ha-result-portrait > :last-child { grid-row: 2; }

/* --- join / owner side ------------------------------------------------------ */
.ha-join-cta { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 10px; flex: 1; }
.ha-join-plus {
  width: 54px; height: 54px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center; color: var(--txt-mute);
  background: radial-gradient(circle at 50% 30%, rgba(255, 255, 255, .05), transparent 70%);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .1), inset 0 0 0 5px rgba(255, 255, 255, .02);
  transition: color .25s, box-shadow .3s, transform .35s var(--ease);
}
.ha-join-plus svg { width: 19px; height: 19px; transition: transform .4s var(--ease); }
.ha-half-join { cursor: pointer; }
.ha-half-join::after {
  content: ''; position: absolute; inset: 0; pointer-events: none; opacity: 0;
  background: linear-gradient(180deg, rgba(204, 255, 0, .1), rgba(204, 255, 0, .028));
  transition: opacity .3s;
}
.ha-half-join:hover::after { opacity: 1; }
.ha-half-join:hover .ha-join-plus {
  color: #032109; transform: scale(1.06);
  background: linear-gradient(180deg, #ddff4d, #ccff00);
  box-shadow: 0 0 0 1px #7a9c00, inset 0 1px 0 rgba(255, 255, 255, .6), inset 0 -1px 0 rgba(0, 0, 0, .3), 0 6px 14px -6px rgba(0, 0, 0, .9);
}
.ha-half-join:hover .ha-join-plus svg { transform: rotate(90deg); }
.ha-half-join:hover .ha-join-label { color: var(--green-soft); }
.ha-join-label {
  font-size: var(--fs-4); font-weight: 600; letter-spacing: .01em;
  color: var(--txt-mute); transition: color .25s;
}
.ha-wait-spin {
  width: 26px; height: 26px; color: var(--green-soft);
  animation: ha-rot 1.05s linear infinite;
}
@keyframes ha-rot { to { transform: rotate(360deg); } }
.ha-mini-actions { display: flex; flex-direction: column; gap: 7px; width: 100%; padding: 0 var(--s1); }
.ha-mini-actions .ha-btn { height: 40px; font-size: var(--fs-2); letter-spacing: .1em; padding: 0 10px; width: 100%; border-radius: var(--r-xs); }

/* --- HP: a machined channel with red underneath, notched into blows -------- */
.ha-lifebar, .ca-lifebar {
  position: relative; width: 88%; height: 7px; border-radius: var(--r-pill); overflow: hidden;
  /* the empty channel IS the danger read: as HP drains, red is what shows */
  background: linear-gradient(90deg, var(--red-deep), #1c0605);
  box-shadow: var(--sink);
}
.ha-lifebar > div, .ca-lifebar > div {
  position: relative; height: 100%; width: 100%; border-radius: var(--r-pill);
  background: linear-gradient(90deg, #0a8f22, #35d955 62%, #66f183);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .35), inset 0 -1px 0 rgba(0, 0, 0, .3);
  transition: width .55s var(--ease), background .3s;
}
.ha-lifebar > div::after, .ca-lifebar > div::after {
  content: ''; position: absolute; right: 0; top: 0; bottom: 0; width: 5px; border-radius: var(--r-pill);
  background: linear-gradient(90deg, rgba(255, 255, 255, 0), rgba(255, 255, 255, .6)); opacity: .9;
}
/* segment notches painted ON TOP, so the fill stays a plain width transition */
.ha-lifebar::after, .ca-lifebar::after {
  content: ''; position: absolute; inset: 0; pointer-events: none; z-index: 2;
  background: repeating-linear-gradient(90deg, transparent 0 7px, rgba(3, 5, 8, .8) 7px 9px);
}

.ha-replay-btn {
  position: relative; width: 100%; height: 42px; border-radius: 0;
  font-size: var(--fs-3); font-weight: 700; letter-spacing: .12em; text-transform: uppercase;
  color: var(--txt-mute); background: rgba(0, 0, 0, .3);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .045);
  transition: color .2s, background .2s;
}
.ha-replay-btn:hover { color: var(--txt); background: rgba(255, 255, 255, .05); }

/* The same footer slot on a result read back out of the book. There is no
   replay for these, so the row carries when it settled and a link to the
   payout instead: the part that survives a restart. */
.ha-done-tx {
  display: flex; align-items: center; justify-content: center;
  width: 100%; height: 42px; text-decoration: none;
  font-size: var(--fs-3); font-weight: 700; letter-spacing: .12em; text-transform: uppercase;
  color: var(--txt-dim); background: rgba(0, 0, 0, .3);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .045);
  transition: color .2s, background .2s;
}
a.ha-done-tx:hover { color: var(--txt); background: rgba(255, 255, 255, .05); }

/* --- live: the one card on the page that is actually happening ------------- */
.ha-card-live { cursor: pointer; box-shadow: 0 0 0 1px rgba(224, 84, 74, .34), var(--slab); }
.ha-card-live:hover {
  box-shadow: 0 0 0 1px rgba(224, 84, 74, .6), inset 0 1px 0 rgba(255, 255, 255, .14),
              0 4px 10px rgba(0, 0, 0, .55), 0 34px 56px -24px #000;
}
.ha-card-live .ha-card-body::after {
  content: ''; position: absolute; top: 0; bottom: 0; left: -50%; width: 42%; pointer-events: none; z-index: 1;
  background: linear-gradient(90deg, transparent, rgba(255, 138, 124, .1), transparent);
  transform: skewX(-16deg) translateX(0);
  animation: ha-scan 2.6s var(--ease) infinite;
}
@keyframes ha-scan { 0% { transform: skewX(-16deg) translateX(0); } 55%, 100% { transform: skewX(-16deg) translateX(420%); } }
.ha-card-live::after {
  content: 'LIVE'; position: absolute; top: var(--s3); right: var(--s3); z-index: 6;
  font-size: var(--fs-1); font-weight: 800; letter-spacing: .16em; line-height: 1;
  color: #ffb3a9; padding: 6px 10px 5px 21px; border-radius: var(--r-pill);
  /* the indicator dot is a radial stop inside the same pseudo. one node. */
  background:
    radial-gradient(circle at 11px 50%, var(--red-hot) 0 2.8px, transparent 3.4px),
    linear-gradient(180deg, rgba(38, 12, 10, .96), rgba(18, 5, 4, .96));
  box-shadow: inset 0 0 0 1px rgba(224, 84, 74, .8), 0 1px 3px rgba(0, 0, 0, .8);
  animation: ha-pulse 1.6s ease-in-out infinite;
}
@keyframes ha-pulse { 0%, 100% { opacity: 1; } 50% { opacity: .58; } }

/* --- stake tiers. real money on the line, so the object gets hotter. ------- */
.ha-card[data-tier="high"] { box-shadow: var(--slab), inset 0 0 0 1px rgba(232, 192, 122, .14); }
.ha-card[data-tier="high"] .ha-stake { box-shadow: inset 0 1px 0 rgba(232, 192, 122, .45); }
.ha-card[data-tier="whale"] {
  box-shadow: 0 0 0 1px rgba(232, 192, 122, .4), var(--slab), inset 0 0 0 1px rgba(232, 192, 122, .3);
}
.ha-card[data-tier="whale"] .ha-stake {
  box-shadow: inset 0 1px 0 rgba(232, 192, 122, .7);
  background:
    linear-gradient(180deg, rgba(60, 34, 6, .5), rgba(0, 0, 0, .6)),
    radial-gradient(80% 200% at 50% 130%, rgba(232, 192, 122, .22), transparent 70%), var(--brush);
}
.ha-card[data-tier="whale"] .ha-stake::before,
.ha-card[data-tier="whale"] .ha-stake::after { opacity: .9; }
.ha-card[data-tier="whale"] .ha-vs { box-shadow: inset 0 1px 0 rgba(255, 255, 255, .3), inset 0 0 0 1px rgba(232, 192, 122, .45), inset 0 0 0 4px rgba(0, 0, 0, .4), 0 8px 20px -8px rgba(0, 0, 0, .95); }
/* your own duel, findable in a full grid at a glance */
.ha-card[data-mine="1"] .ha-card-body { background: linear-gradient(90deg, rgba(204, 255, 0, .055), transparent 42%); }

/* ---------------------------------- chat ------------------------------------ */
.ha-chat {
  position: relative; z-index: 40; min-width: 0; overflow: hidden;
  display: flex; flex-direction: column;
  background: linear-gradient(180deg, var(--card) 0%, var(--bg-soft) 45%, #07090d 100%), var(--grain);
  box-shadow: inset -1px 0 0 rgba(255, 255, 255, .045), 8px 0 34px -20px #000;
}
.ha-chat::before {         /* GOLD SEAM 5 of 7 — on the edge facing the page */
  content: ''; position: absolute; top: 0; bottom: 0; right: 0; width: 1px; z-index: 1;
  background: linear-gradient(180deg, transparent, rgba(232, 192, 122, .3) 12%, rgba(232, 192, 122, .04) 56%, transparent);
}

/* the toggle. Fixed to the page, not to a column, so it is reachable whether
   the panel is open, shut, or a drawer over the top of everything. */
.ha-chat-toggle {
  position: fixed; left: 14px; bottom: 16px; z-index: 96;
  width: 44px; height: 44px; border-radius: var(--r-sm);
  display: flex; align-items: center; justify-content: center;
  color: var(--txt-dim); background: color-mix(in srgb, var(--raise) 88%, transparent);
  -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
  /* It floats over the page, so it has to read as an overlay rather than as
     something that clipped the line underneath it. */
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .07), 0 0 0 1px var(--line),
              0 0 0 4px rgba(6, 7, 10, .55), 0 6px 18px -8px #000;
  transition: color .2s, background .2s, transform .2s var(--ease), left .28s var(--ease);
}
.ha-chat-toggle:hover { color: var(--txt); background: var(--raise-2); transform: translateY(-1px); }
body.ha-chat-open .ha-chat-toggle { left: 350px; color: var(--green-soft); }
/* Docked and open, the panel already has its own close button, so a second
   control floating at left:350 is redundant AND it sits on top of whatever
   scrolls past: measured covering the leaderboard's BIGGEST HIT figure, a gold
   currency number under a button. On a phone the chat is a drawer and this is
   the only way to open it, so it stays there. */
@media (min-width: 820px) { body.ha-chat-open .ha-chat-toggle { display: none; } }
.ha-sr {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap;
}
.ha-chat-head {
  position: relative; flex-shrink: 0;
  display: flex; align-items: center; gap: 10px; height: 66px; padding: 0 var(--s4);
  background: linear-gradient(180deg, rgba(19, 24, 31, .8), rgba(10, 13, 18, .5));
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .05);
}
.ha-chat-head::after {
  content: ''; position: absolute; left: 0; right: 0; bottom: 0; height: 1px;
  background: linear-gradient(90deg, var(--line), var(--line) 70%, transparent);
}
/* Sora, not the display face: at 15px Cinzel caps go thin and precious. */
.ha-chat-title {
  flex: 1; min-width: 0; font-weight: 700; font-size: var(--fs-6); letter-spacing: .02em; color: #dfe6ed;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.ha-chat-online {
  display: flex; align-items: center; gap: 6px; flex-shrink: 0;
  font-family: var(--num); font-size: var(--fs-3); font-weight: 700; color: var(--green-soft);
  font-variant-numeric: tabular-nums;
  padding: 5px 10px; border-radius: var(--r-pill); background: rgba(204, 255, 0, .07);
  box-shadow: inset 0 0 0 1px rgba(204, 255, 0, .32);
}
.ha-chat-x {
  /* The close control belongs on the panel it closes, at every width. It used
     to be phone-only, which is why the desktop close was a button floating out
     over the page content. */
  display: flex; width: 40px; height: 40px; border-radius: var(--r-xs); flex-shrink: 0;
  align-items: center; justify-content: center; font-size: 24px; line-height: 1; color: var(--txt-mute);  /* glyph metric, not type */
  transition: color .2s, background .2s;
}
.ha-chat-x:hover { color: var(--txt); background: rgba(255, 255, 255, .05); }
.ha-chat-log {
  flex: 1; min-height: 0; overflow-y: auto; overflow-x: hidden;
  padding: var(--s4) var(--s4) var(--s3); display: flex; flex-direction: column; gap: 13px;
}
.ha-chat-notice {
  flex-shrink: 0; display: flex; align-items: flex-start; gap: 9px; padding: 14px var(--s4);
  background: linear-gradient(110deg, rgba(204, 255, 0, .07), rgba(204, 255, 0, .015));
  border-bottom: 1px solid rgba(204, 255, 0, .13);
}
.ha-chat-pin { width: 17px; height: 17px; flex-shrink: 0; color: var(--green-soft); margin-top: 2px; }
.ha-chat-notice p { flex: 1; min-width: 0; margin: 0; font-size: 12px; line-height: 1.65; }
.ha-chat-notice strong { display: block; color: var(--txt); font-weight: 600; }
.ha-chat-notice p > span { display: block; color: var(--txt-dim); margin-top: 3px; }
.ha-chat-notice code { color: var(--green-soft); font-family: var(--num); overflow-wrap: anywhere; }
.ha-chat-notice strong a { color: inherit; text-decoration: underline; text-decoration-color: rgba(204, 255, 0, .3); text-underline-offset: 3px; }
.ha-chat-notice strong a:hover { color: var(--green-soft); }
.ha-chat-token-copy { display: flex; align-items: center; gap: 8px; width: 100%; min-height: 44px; padding: 5px 0; color: var(--green-soft); text-align: left; font-size: 11px; line-height: 1.6; cursor: pointer; border-radius: 4px; }
.ha-chat-token-copy code { min-width: 0; flex: 1; user-select: text; }
.ha-chat-token-copy svg { flex: 0 0 15px; width: 15px; height: 15px; opacity: .7; }
.ha-chat-token-copy:hover svg { opacity: 1; }
.ha-chat-token-copy:focus-visible, .ha-chat-notice a:focus-visible { outline: 2px solid var(--green); outline-offset: 3px; }
.ha-chat-dismiss { display: flex; align-items: center; justify-content: center; flex: 0 0 28px; width: 28px; height: 28px; border-radius: 5px; color: var(--txt-dim); font-size: 21px; cursor: pointer; }
.ha-chat-dismiss:hover { background: rgba(255, 255, 255, .07); color: var(--txt); }
.ha-chat-reply { flex-shrink: 0; display: flex; gap: 10px; align-items: center; padding: 11px var(--s4); border-top: 1px solid var(--line); background: var(--raise); }
.ha-chat-notice[hidden], .ha-chat-reply[hidden] { display: none; }
.ha-chat-reply-copy { flex: 1; min-width: 0; padding-left: 10px; border-left: 2px solid var(--green); }
.ha-chat-reply-copy span { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 12px; line-height: 1.6; }
#ha-chat-reply-label { color: var(--green-soft); font-weight: 600; }
#ha-chat-reply-text { color: var(--txt-dim); }
.ha-msg { position: relative; display: flex; gap: 10px; flex-shrink: 0; font-size: var(--fs-4); animation: ha-msg-in .34s var(--ease) both; }
.ha-msg[data-chat-id] .ha-msg-top { padding-right: 30px; }
.ha-msg-reply { position: absolute; right: 0; top: 0; display: flex; align-items: center; justify-content: center; width: 28px; height: 28px; border-radius: 5px; color: var(--txt-dim); opacity: .5; cursor: pointer; }
.ha-msg-reply svg { width: 17px; height: 17px; }
.ha-msg:hover .ha-msg-reply, .ha-msg:focus-within .ha-msg-reply { opacity: 1; }
.ha-msg-reply:hover { color: var(--txt); background: rgba(255, 255, 255, .07); }
.ha-msg-quote { display: flex; align-items: center; gap: 5px; width: 100%; min-width: 0; padding: 2px 30px 5px 0; text-align: left; color: #87969e; font-size: 11px; line-height: 1.5; cursor: pointer; }
.ha-msg-quote svg { flex: 0 0 12px; width: 12px; height: 12px; opacity: .7; }
.ha-msg-quote span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ha-msg-quote:hover { color: var(--txt); }
.ha-msg.is-reply-highlight { background: rgba(204, 255, 0, .08); border-radius: 5px; box-shadow: 0 0 0 5px rgba(204, 255, 0, .08); }
.ha-msg-reply:focus-visible, .ha-msg-quote:focus-visible, .ha-chat-dismiss:focus-visible { outline: 2px solid var(--green); outline-offset: 2px; }
@media (pointer: coarse) {
  .ha-msg-reply, .ha-chat-dismiss { min-width: 44px; width: 44px; height: 44px; opacity: 1; }
  .ha-chat-dismiss { flex-basis: 44px; }
  .ha-msg[data-chat-id] .ha-msg-top { padding-right: 46px; }
  .ha-msg[data-chat-id] { min-height: 44px; }
  .ha-msg-quote { padding-right: 46px; min-height: 32px; }
}
@keyframes ha-msg-in { from { opacity: 0; transform: translateY(6px); } }
.ha-msg > img, .ha-msg-avatar img {
  width: 30px; height: 30px; border-radius: 50%; flex-shrink: 0; background: var(--panel-2); object-fit: cover;
  box-shadow: 0 0 0 1px rgba(255, 255, 255, .1), 0 2px 6px rgba(0, 0, 0, .6);
}
.ha-msg-avatar { flex: 0 0 34px; width: 34px; height: 34px; padding: 2px; border: 0; border-radius: 50%; background: transparent; cursor: pointer; }
.ha-msg-name.ha-profile-link { border: 0; padding: 2px 0; background: transparent; text-align: left; cursor: pointer; font-family: inherit; }
.ha-profile-link:hover { color: var(--txt); }
.ha-profile-link:focus-visible { outline: 2px solid var(--green); outline-offset: 3px; border-radius: 4px; }
.ha-player-name { appearance: none; border: 0; margin: 0; padding: 0; background: transparent; color: inherit; font: inherit; letter-spacing: inherit; text-transform: inherit; text-align: inherit; max-width: 100%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; vertical-align: bottom; cursor: pointer; pointer-events: auto; }
.ha-player-name:hover { text-decoration: underline; text-underline-offset: 3px; }
.ha-player-name:focus-visible { outline: 2px solid var(--green); outline-offset: -2px; border-radius: 3px; }
.ha-player-dialog { border: 0; color: var(--txt); margin: auto; width: calc(100% - 32px); }
.ha-player-dialog::backdrop { background: rgba(3, 4, 6, .8); backdrop-filter: blur(8px); }
.ha-player-targets { position: absolute; inset: 0; z-index: 2; overflow: hidden; pointer-events: none; }
.ha-player-hit { position: absolute; transform: translate(-50%, -50%); color: transparent; font-size: 0; min-height: 24px; border-radius: 4px; }
.ha-player-hit:hover, .ha-player-hit:focus-visible { background: rgba(255, 255, 255, .1); outline: 1px solid var(--green); outline-offset: -1px; }
.ha-player-hit[hidden] { display: none; }
.ha-msg-quote-wrap { color: var(--txt-mute); font-size: 11px; margin-bottom: 6px; }
.ha-msg-quote-wrap > .ha-player-name { margin-bottom: 3px; }
.ha-msg-avatar:hover img { box-shadow: 0 0 0 2px var(--green-soft); }
.ha-msg-badges:empty { display: none; }
/* Keep badge artwork at its box size; legacy chat icons must not shrink it. */
.ha-msg-badges { display: inline-flex; align-items: center; flex: 0 0 auto; }
.ha-msg-badges .ha-badge { width: 22px; height: 22px; }
.ha-player-heading { display: flex; align-items: center; gap: 18px; padding-right: 24px; margin-bottom: 20px; }
.ha-player-portrait { width: 80px; height: 80px; flex: 0 0 80px; border-radius: 20px; background: var(--panel-2); border: 1px solid var(--line); }
.ha-player-heading > div { min-width: 0; }
.ha-player-eyebrow { display: block; color: var(--txt-mute); text-transform: uppercase; font-size: 10px; font-weight: 700; letter-spacing: .14em; margin-bottom: 5px; }
.ha-player-heading h3 { margin: 0 0 7px; overflow-wrap: anywhere; }
.ha-player-badges { display: flex; align-items: center; gap: 6px; color: var(--txt-dim); font-size: 12px; }
.ha-player-badges > img { width: 16px; height: 16px; }
.ha-player-address { margin-bottom: 18px; }
.ha-player-address code { min-width: 0; overflow-wrap: anywhere; }
.ha-profile-summary { display: flex; gap: 12px; padding-bottom: 16px; margin-bottom: 16px; border-bottom: 1px solid var(--line); }
.ha-profile-summary > div { flex: 1; display: flex; flex-direction: column; gap: 5px; min-width: 0; }
.ha-profile-summary span { font-size: 12px; color: var(--txt-mute); }
.ha-profile-summary b { font-size: 18px; color: var(--txt); overflow-wrap: anywhere; }
.ha-msg-body { min-width: 0; flex: 1; }
.ha-msg-top { display: flex; align-items: center; gap: 3px; margin-bottom: 2px; flex-wrap: wrap; }
.ha-msg-top > img { width: 13px; height: 13px; flex-shrink: 0; }
.ha-msg-name { font-size: var(--fs-3); font-weight: 700; letter-spacing: .02em; color: var(--txt-dim); }
.ha-msg-name.is-me { color: var(--green-soft); }
.ha-msg-text { color: #d7dee6; word-break: break-word; line-height: 1.5; font-size: var(--fs-4); }
.ha-msg:has(.ha-msg-name.is-me) .ha-msg-body {
  padding-left: 9px; box-shadow: inset 2px 0 0 rgba(204, 255, 0, .4); border-radius: 2px;
}
.ha-chat-foot {
  flex-shrink: 0; display: flex; gap: 9px; padding: 13px var(--s4);
  background: linear-gradient(180deg, transparent, rgba(0, 0, 0, .3));
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .045);
}
.ha-chat-foot input {
  flex: 1; min-width: 0; height: 42px; padding: 0 var(--s3); border: 0; border-radius: var(--r-sm);
  background: var(--well);
  box-shadow: var(--sink), 0 0 0 1px rgba(255, 255, 255, .05);
  transition: box-shadow .22s;
}
.ha-chat-foot input::placeholder { color: var(--txt-mute); }
.ha-chat-foot input:focus { outline: none; box-shadow: var(--sink), 0 0 0 2px var(--green); }
.ha-chat-foot .ha-btn { flex-shrink: 0; padding: 0 var(--s4); }

/* Keep the gate, reply preview and controls inside one padded column. Direct
   chat children retain the dock's fixed width, so margins on a direct child
   would push its right edge outside the panel. */
.ha-chat-compose {
  flex-shrink: 0; min-width: 0; display: flex; flex-direction: column; gap: 10px;
  padding: 12px var(--s4); border-top: 1px solid var(--line-soft); background: var(--bg-soft);
}
.ha-chat-compose .ha-chat-reply { padding: 0; border: 0; background: none; }
.ha-chat-compose .ha-chat-foot {
  display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: stretch; gap: 8px;
  min-width: 0; padding: 0; background: none; box-shadow: none;
}
.ha-chat-compose .ha-chat-foot input {
  width: 100%; height: 44px; border: 1px solid var(--line); border-radius: 8px;
  font-size: 13px; box-shadow: none;
}
.ha-chat-compose .ha-chat-foot input:focus { border-color: var(--green); box-shadow: 0 0 0 2px rgba(204, 255, 0, .12); }
.ha-chat-compose .ha-chat-foot .ha-btn { height: 44px; min-height: 44px; padding: 0 15px; border: 1px solid transparent; border-radius: 8px; }
.ha-chat-compose .ha-chat-foot input:disabled { opacity: 1; color: var(--txt-mute); background: rgba(0, 0, 0, .15); }
.ha-chat-compose .ha-chat-foot .ha-btn:disabled {
  opacity: 1; color: var(--txt-mute); background: var(--raise); border: 1px solid var(--line);
  box-shadow: none; text-shadow: none; transform: none;
}

/* ------------------------------- bottom nav --------------------------------- */
.ha-bnav {
  display: none; position: fixed; left: 0; right: 0; bottom: 0; z-index: 90;
  height: calc(var(--bnav-h) + env(safe-area-inset-bottom));
  padding-bottom: env(safe-area-inset-bottom);
  grid-template-columns: repeat(5, 1fr); align-items: center;
  background: linear-gradient(180deg, rgba(14, 18, 24, .93), rgba(6, 8, 11, .97));
  -webkit-backdrop-filter: blur(22px) saturate(140%); backdrop-filter: blur(22px) saturate(140%);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .07), 0 -18px 40px -20px #000;
}
.ha-bnav::before {
  content: ''; position: absolute; left: 0; right: 0; top: 0; height: 1px;
  background: linear-gradient(90deg, transparent, var(--line) 20%, var(--line) 80%, transparent);
}
.ha-bnav button {
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: var(--s1);
  min-height: 48px; padding: 6px 0; color: var(--txt-mute);
  font-size: var(--fs-2); font-weight: 600; letter-spacing: .01em;
  transition: color .2s;
}
.ha-bnav button svg { width: 21px; height: 21px; transition: transform .3s var(--ease); }
.ha-bnav button.is-active { color: var(--green-soft); }
.ha-bnav button.is-active svg { transform: translateY(-1px); }
.ha-bnav-fab {
  width: 56px; height: 56px; margin: 0 auto; border-radius: 50%; transform: translateY(-15px);
  display: flex; align-items: center; justify-content: center;
  color: #141a00 !important;
  border: 1px solid transparent;
  background:
    linear-gradient(180deg, #ddff4d 0%, #ccff00 55%, #a8d400 100%) padding-box,
    conic-gradient(from 210deg, rgba(232, 192, 122, .7), rgba(232, 192, 122, .1) 40%, rgba(232, 192, 122, .8) 70%, rgba(232, 192, 122, .15)) border-box;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, .6), inset 0 -1px 0 rgba(0, 0, 0, .3),
    0 0 0 5px rgba(6, 8, 11, .9), 0 6px 16px rgba(0, 0, 0, .7), 0 14px 30px -10px rgba(0, 0, 0, .95);
  transition: transform .25s var(--ease), box-shadow .25s;
}
.ha-bnav-fab:active { transform: translateY(-13px) scale(.96); }
.ha-bnav-fab svg { width: 24px !important; height: 24px !important; }

/* --------------------------------- modals ----------------------------------- */
#ha-modals { position: relative; z-index: 1000; }
.ha-modal-back {
  position: fixed; inset: 0; z-index: 1000;
  display: flex; align-items: center; justify-content: center; padding: 18px;
  background: radial-gradient(120% 90% at 50% 0%, rgba(11, 15, 21, .74), rgba(3, 4, 6, .93));
  -webkit-backdrop-filter: blur(10px) saturate(120%); backdrop-filter: blur(10px) saturate(120%);
  animation: ha-fade .22s ease;
}
@keyframes ha-fade { from { opacity: 0; } }
.ha-modal {
  position: relative; width: 100%; max-width: 480px; max-height: 92vh; max-height: 92dvh;
  overflow-y: auto; overflow-x: hidden; padding: var(--s6); border-radius: var(--r-lg);
  background:
    var(--sheen),
    radial-gradient(90% 60% at 12% -8%, rgba(204, 255, 0, .05), transparent 60%),
    linear-gradient(180deg, #131820 0%, #0b0e14 60%, #090c11 100%),
    var(--grain);
  box-shadow: var(--slab-lg);
  animation: ha-modal-in .38s var(--ease) both;
}
@keyframes ha-modal-in { from { opacity: 0; transform: translateY(18px) scale(.975); } }
.ha-modal::before {        /* GOLD SEAM 6 of 7 */
  content: ''; position: absolute; left: 16%; right: 16%; top: 0; height: 1px;
  background: linear-gradient(90deg, transparent, rgba(232, 192, 122, .8), transparent);
}
.ha-modal-wide { max-width: 760px; }
/* Direct child only: this is the dialog's title. A dialog whose body carries
   its own h3 headings was getting them uppercased, tracked out and inset by
   44px too, which is how the token rules ended up shouting theirs. */
.ha-modal > h3 {
  font-family: var(--display); font-weight: 700; font-size: var(--fs-9);
  letter-spacing: .1em; text-transform: uppercase; margin-bottom: var(--s5); padding-right: 44px;
  background: linear-gradient(180deg, #ffffff, #a8b5c1);
  -webkit-background-clip: text; background-clip: text; color: transparent; -webkit-text-fill-color: transparent;
}
.ha-modal-x {
  /* The modal is the scroll container, so an absolutely positioned close button
     scrolls away with the content: on a phone, a long dialog left no way out at
     the bottom. Sticky keeps it against the top edge while the body moves, and
     the negative margins keep it from taking a row of its own. */
  position: sticky; float: right; top: 0; margin: 0 0 calc(var(--s3) * -1) var(--s3); z-index: 3;
  width: 40px; height: 40px; border-radius: var(--r-sm);
  display: flex; align-items: center; justify-content: center; color: var(--txt-mute);
  background: rgba(255, 255, 255, .03); box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .05);
  transition: color .2s, background .2s, transform .25s var(--ease);
}
.ha-modal-x:hover { color: var(--txt); background: rgba(255, 255, 255, .08); transform: rotate(90deg); }

.ha-field { margin-bottom: var(--s5); }
.ha-field label {
  display: block; margin-bottom: 9px;
  font-size: var(--fs-2); font-weight: 700; letter-spacing: .14em; text-transform: uppercase; color: var(--txt-mute);
}
.ha-input {
  display: flex; align-items: center; gap: 10px; height: 50px; padding: 0 var(--s3); border-radius: var(--r-sm);
  background: var(--well);
  box-shadow: var(--sink), 0 0 0 1px rgba(255, 255, 255, .05);
  transition: box-shadow .22s;
}
.ha-input svg { flex-shrink: 0; }
.ha-input input {
  flex: 1; min-width: 0; height: 100%; background: none; border: 0;
  font-weight: 600; font-size: var(--fs-6);
}
.ha-input input:focus { outline: none; }
.ha-input .ha-amount-max { flex:0 0 auto; min-width:48px; min-height:36px; padding:0 10px; border:1px solid var(--green-dark); border-radius:8px; color:var(--green); background:var(--green-dim); font:700 12px var(--font); text-transform:uppercase; cursor:pointer; }
.ha-input .ha-amount-max:hover { background:rgba(204,255,0,.2); }
.ha-input .ha-amount-max:focus-visible { outline:2px solid var(--green); outline-offset:2px; }
.ha-input .ha-amount-max:disabled { opacity:.45; cursor:not-allowed; }
.ha-input:focus-within { box-shadow: var(--sink), 0 0 0 2px var(--green); }
.ha-row { display: flex; gap: 9px; }
.ha-row > * { flex: 1; min-width: 0; }
.ha-row:has(> .ha-input) > .ha-btn { height: 50px; }   /* sit level with the field */
.ha-quick {
  height: 42px; border-radius: var(--r-sm);
  font-size: var(--fs-4); font-weight: 700; color: var(--txt-dim);
  background: var(--face);
  box-shadow: var(--slab);
  transition: color .2s, box-shadow .22s, transform .16s var(--ease);
}
/* green, not gold: picking a stake is an action, and gold is reserved. */
.ha-quick:hover { color: var(--green-soft); box-shadow: 0 0 0 1px rgba(204, 255, 0, .55), var(--slab-hi); transform: translateY(-1px); }

.ha-wpn-tile {
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 8px;
  padding: var(--s3) 10px; min-height: 164px; border-radius: var(--r-sm);
  background: var(--face), var(--brush);
  box-shadow: var(--slab);
  transition: box-shadow .25s, transform .22s var(--ease);
}
.ha-wpn-tile .ha-wpn-art { width: 112px; height: 112px; max-width: 100%; flex-shrink: 0; }
.ha-wpn-art > svg { display: block; }
.ha-wpn-tile span { font-size: var(--fs-3); font-weight: 600; color: var(--txt-dim); text-align: center; }
.ha-wpn-tile:hover { transform: translateY(-2px); box-shadow: var(--slab-hi); }
.ha-wpn-tile.is-on {
  background: linear-gradient(180deg, rgba(204, 255, 0, .12), rgba(204, 255, 0, .03)), var(--face);
  box-shadow: 0 0 0 1px rgba(204, 255, 0, .7), inset 0 1px 0 rgba(255, 255, 255, .14), 0 18px 34px -18px rgba(0, 0, 0, .9);
}
.ha-wpn-tile.is-on span { color: var(--green-soft); }

/* the receipt row: label, dotted leader, value. one pattern, reused for the
   create-duel summary and every payout row in the finish panel. */
.ha-summary {
  display: flex; align-items: center; gap: var(--s3);
  margin-bottom: var(--s5); padding: var(--s4) var(--s4) var(--s3);
  border-radius: var(--r-sm);
  background: linear-gradient(180deg, rgba(232, 192, 122, .07), rgba(232, 192, 122, .02));
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .07), inset 0 0 0 1px rgba(232, 192, 122, .16);
}
.ha-summary > span {
  order: 0; flex-shrink: 0;
  font-size: var(--fs-2); font-weight: 700; letter-spacing: .14em; text-transform: uppercase; color: var(--txt-mute);
}
.ha-summary::before {
  content: ''; order: 1; flex: 1 1 auto; min-width: var(--s3); height: 1px;
  background: repeating-linear-gradient(90deg, rgba(232, 192, 122, .34) 0 2px, transparent 2px 6px);
}
.ha-summary b { order: 2; flex-shrink: 0; font-size: var(--fs-9); line-height: 1.1; }

.ha-fair-note { font-size: var(--fs-3); color: var(--txt-dim); line-height: 1.65; }
details.ha-details, .ca-fair-wrap { position: relative; }
details.ha-details summary {
  cursor: pointer; margin-bottom: 10px; list-style: none;
  font-size: var(--fs-3); font-weight: 600; color: var(--txt-mute);
  transition: color .2s;
}
details.ha-details summary::-webkit-details-marker, .ca-fair-wrap summary::-webkit-details-marker { display: none; }
details.ha-details summary::before, .ca-fair-wrap summary::before {
  content: '+'; display: inline-block; width: 15px; font-family: var(--num); color: var(--gold);
}
details.ha-details[open] summary::before, .ca-fair-wrap[open] summary::before { content: '–'; }
details.ha-details summary:hover { color: var(--txt-dim); }

/* ------------------------------ locker modal -------------------------------- */
.ha-locker { display: block; }
.ha-lk-stats { display: flex; gap: 10px; margin-bottom: 18px; flex-wrap: wrap; }
.ha-lk-stat {
  flex: 1; min-width: 148px; padding: var(--s4); border-radius: var(--r-sm);
  background: var(--face), var(--brush);
  box-shadow: var(--slab);
}
.ha-lk-stat .v { font-size: var(--fs-9); line-height: 1.15; margin-bottom: var(--s1); }
.ha-lk-stat .l { font-size: var(--fs-2); font-weight: 700; letter-spacing: .14em; text-transform: uppercase; color: var(--txt-mute); }
.ha-lk-tabs { display: flex; gap: 7px; margin-bottom: var(--s4); flex-wrap: wrap; }
.ha-lk-tab {
  height: 42px; padding: 0 var(--s4); border-radius: var(--r-sm);
  font-size: var(--fs-4); font-weight: 600; color: var(--txt-dim);
  background: var(--face);
  box-shadow: var(--slab);
  transition: color .2s, box-shadow .22s;
}
.ha-lk-tab:hover { color: var(--txt); box-shadow: var(--slab-hi); }
.ha-lk-tab.is-on {
  color: var(--green-soft);
  background: linear-gradient(180deg, rgba(204, 255, 0, .16), rgba(204, 255, 0, .04));
  box-shadow: 0 0 0 1px rgba(204, 255, 0, .6), inset 0 1px 0 rgba(255, 255, 255, .12), 0 2px 6px rgba(0, 0, 0, .5);
}
.ha-lk-grid { display: grid; gap: 11px; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); }

/* One-week releases, with permanent ownership. Fire lives in the item art;
   the shop keeps the same readable obsidian surfaces as the wardrobe. */
.ha-shop-intro { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: center; gap: var(--s3); padding-top: var(--s5); border-top: 1px solid var(--line); }
.ha-shop-intro h3, .ha-shop-og-copy h3 { font-size: var(--fs-6); font-weight: 700; line-height: 1.3; margin: 0 0 var(--s2); }
.ha-shop-intro p, .ha-shop-og-copy p { color: var(--txt-dim); font-size: var(--fs-3); line-height: 1.6; }
.ha-shop-clock { display: block; color: var(--gold); font-family: var(--num); font-size: var(--fs-2); font-weight: 500; font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }
.ha-shop-meta { display: flex; flex-wrap: wrap; justify-content: space-between; gap: var(--s2); margin: var(--s4) 0; color: var(--txt-dim); font-size: var(--fs-3); }
.ha-lk-grid.ha-shop-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.ha-shop-og { display: grid; grid-template-columns: 88px minmax(0, 1fr) 148px; align-items: center; gap: var(--s4); padding: var(--s4) 0 var(--s5); margin-bottom: var(--s4); }
.ha-shop-og-art { width: 88px; height: 104px; object-fit: contain; }
.ha-shop-og-copy, .ha-shop-og-action { min-width: 0; }
.ha-shop-og-copy .ha-shop-clock { margin-top: var(--s2); }
.ha-shop-og-terms { display: block; margin-top: var(--s1); font-size: var(--fs-2); color: var(--txt-mute); }
.ha-shop-og-action { display: flex; flex-direction: column; gap: var(--s3); text-align: center; }
.ha-shop-og-action .ha-btn { white-space: normal; min-height: 44px; padding-inline: var(--s3); }
.ha-shop-price { color: var(--gold); font-family: var(--num); font-weight: 600; }
@container locker (max-width: 480px) {
  .ha-shop-og { grid-template-columns: 72px minmax(0, 1fr); gap: var(--s3); }
  .ha-shop-og-art { width: 72px; height: 88px; }
  .ha-shop-og-action { grid-column: 1 / -1; flex-direction: row; align-items: center; justify-content: space-between; }
  .ha-shop-og-action .ha-btn { min-width: 148px; }
}
@container locker (max-width: 600px) {
  .ha-lk-grid.ha-shop-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
.ha-shop-grid .ha-item-prev { height: 116px; }
.ha-shop-grid .ha-item-art { width: 108px; height: 108px; }
.ha-shop-item .ha-shop-price { color: var(--gold); font-family: var(--num); font-weight: 600; }
.ha-shop-permanent { color: var(--txt-mute); font-size: var(--fs-2); margin-top: -5px; }
.ha-btn.ha-shop-buy { color: var(--green-ink); background: var(--green); min-height: 44px; margin-top: auto; }
.ha-btn.ha-shop-buy:hover:not(:disabled) { background: var(--green-soft); }
.ha-btn.ha-shop-buy:disabled { opacity: .45; cursor: default; }
.ha-shop-note { margin-top: var(--s4); color: var(--txt-mute); font-size: var(--fs-3); line-height: 1.7; }
.ha-shop-check-art { display: flex; justify-content: center; margin: var(--s4) 0; background: var(--panel); border-radius: var(--r-sm); }
.ha-shop-terms { display: grid; gap: var(--s2); padding: var(--s4) 0; }
.ha-shop-terms div { display: flex; gap: var(--s4); justify-content: space-between; font-size: var(--fs-4); }
.ha-shop-terms dt { color: var(--txt-mute); }
.ha-shop-terms dd { text-align: right; overflow-wrap: anywhere; }
.ha-shop-check-actions { display: flex; gap: var(--s3); margin-top: var(--s4); }
.ha-shop-check-actions button { flex: 1; min-width: 0; min-height: 44px; white-space: normal; }
#ha-shop-check-status { color: var(--green-soft); font-size: var(--fs-4); }
#ha-shop-check-error { margin-top: var(--s3); }
@media (max-width: 400px) {
  .ha-shop-grid { gap: var(--s2); }
  .ha-shop-grid .ha-item { padding: var(--s2); }
}

.ha-item {
  position: relative; display: flex; flex-direction: column; gap: 9px;
  padding: 13px; border-radius: var(--r);
  background: var(--sheen), linear-gradient(180deg, #151b23, var(--card)), var(--grain);
  box-shadow: var(--slab);
  transition: transform .25s var(--ease), box-shadow .25s;
  animation: ha-deal .4s var(--ease) both;
}
.ha-item:hover { transform: translateY(-3px); box-shadow: var(--slab-hi); }
/* every card is a try-on, locked or not: the ring says which one the figure is
   wearing right now. The art is a real button, so the keyboard gets it too. */
.ha-item[data-slot] { cursor: pointer; }
.ha-item-tryb {
  position: relative; display: block; width: 100%; padding: 0; border: 0; background: none;
  border-radius: var(--r-sm); cursor: pointer; color: inherit; font: inherit; text-align: inherit;
}
.ha-item-tryb:focus-visible { outline: 2px solid var(--green-soft); outline-offset: 2px; }
.ha-item.is-trying, .ha-item.is-limited.is-trying { box-shadow: 0 0 0 2px var(--gold), inset 0 1px 0 rgba(255, 255, 255, .1), 0 18px 34px -18px rgba(0, 0, 0, .9); }
/* bottom-left of the art, clear of the LIMITED ribbon in the top-right corner */
.ha-item-try {
  position: absolute; left: 6px; bottom: 6px; z-index: 1; padding: 3px 7px; border-radius: var(--r-chip);
  font-size: var(--fs-1); font-weight: 800; letter-spacing: .14em; text-transform: uppercase;
  background: var(--gold); color: #1a1408;
}
/* the trophy a player carries: a rendered chip beside their name, everywhere a name is */
.ha-trophy {
  display: inline-block; width: 26px; height: 26px; object-fit: contain; vertical-align: middle; flex: 0 0 auto;
  filter: drop-shadow(0 1px 2px rgba(0, 0, 0, .7));
}
.c-line { display: flex; align-items: center; gap: 4px; min-width: 0; }
.c-line .ha-lb-name { min-width: 0; }
.c-id .ha-trophy { width: 22px; height: 22px; margin-left: 2px; }
.ha-lower3-addr .ha-trophy { width: 20px; height: 20px; }
/* a timed sale: the one-week Burning collection and the OG badge. One chip,
   struck in a card's top-right corner and above the OG offer's title. */
.ha-item.is-limited { box-shadow: 0 0 0 1px rgba(232, 192, 122, .6), inset 0 1px 0 rgba(255, 255, 255, .1), 0 18px 34px -18px rgba(0, 0, 0, .9); }
.ha-item.is-limited::before, .ha-limited {
  font-size: var(--fs-1); font-weight: 800; letter-spacing: .12em; line-height: 1; color: #2a1d06;
  padding: 4px 7px 3px; border-radius: var(--r-chip); text-transform: uppercase;
  background: linear-gradient(180deg, var(--gold-hi), var(--gold) 55%, #c1913f);
  box-shadow: 0 0 0 1px #8a6323, inset 0 1px 0 rgba(255, 255, 255, .8), 0 2px 5px rgba(0, 0, 0, .7);
}
.ha-item.is-limited::before { content: 'LIMITED'; position: absolute; top: 10px; right: 10px; z-index: 2; }
.ha-limited { display: inline-block; }
.ha-shop-og-copy .ha-limited { margin-bottom: var(--s2); }
.ha-item.is-equipped { box-shadow: 0 0 0 1px rgba(204, 255, 0, .7), inset 0 1px 0 rgba(255, 255, 255, .1), 0 18px 34px -18px rgba(0, 0, 0, .9); }
.ha-item-prev {
  height: 72px; border-radius: var(--r-xs); overflow: hidden;
  display: flex; align-items: center; justify-content: center;
  background: radial-gradient(circle at 50% 34%, #151b23, #080a0e 74%);
  box-shadow: var(--sink);
}
.ha-item-prev .swatch {
  width: 38px; height: 38px; border-radius: var(--r-xs);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .45), inset 0 -6px 12px rgba(0, 0, 0, .35), 0 5px 14px -3px rgba(0, 0, 0, .85), 0 0 0 1px rgba(255, 255, 255, .09);
}
.ha-item-prev .chipprev { transform: scale(1.5); }
.ha-item-prev .ha-fair-note { font-size: var(--fs-3); color: var(--txt-mute); }
.ha-item-name { font-size: var(--fs-4); font-weight: 700; line-height: 1.3; }
.ha-item-req { font-size: var(--fs-3); font-weight: 500; color: var(--txt-mute); }
.ha-item-req.ok { color: var(--green-soft); }
.ha-prog { height: 5px; border-radius: var(--r-pill); overflow: hidden; background: rgba(0, 0, 0, .6); box-shadow: var(--sink); }
.ha-prog > div {
  height: 100%; border-radius: var(--r-pill);
  background: linear-gradient(90deg, var(--gold-lo), var(--gold) 70%, var(--gold-hi));
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .4), inset 0 -1px 0 rgba(0, 0, 0, .3);
  transition: width .6s var(--ease);
}
.ha-item .ha-btn { height: 40px; font-size: var(--fs-2); letter-spacing: .1em; border-radius: var(--r-xs); }
.ha-equip { color: var(--green-soft); }
.ha-equip:hover { color: #8ef0a2; box-shadow: 0 0 0 1px rgba(204, 255, 0, .6), var(--slab-hi); }
.ha-item-lock {
  display: flex; align-items: center; justify-content: center; gap: 6px; height: 40px;
  font-size: var(--fs-3); font-weight: 600; color: var(--txt-mute);
}
.ha-item-lock.is-on { color: var(--green-soft); font-weight: 700; }
.ha-item-lock svg { width: 14px; height: 14px; }

/* --------------------------- profile avatar grid ----------------------------- */
.ha-ava-grid { display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); gap: 9px; }
.ha-ava-pick {
  min-width: 0; padding: 3px; border-radius: 50%;
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .07);
  transition: box-shadow .22s, transform .25s var(--ease);
}
.ha-ava-pick img { width: 100%; height: auto; border-radius: 50%; background: var(--panel-2); }
.ha-ava-pick:hover { transform: translateY(-2px); box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .2); }
.ha-ava-pick.is-on { box-shadow: inset 0 0 0 2px var(--green); }

/* =============================================================================
   BATTLE OVERLAY
   HARD RULE: no filter, no clip-path and no backdrop-filter on .ha-duel,
   .ca-stage or any other ancestor of .ca-arena3d. Those re-run per rendered
   frame over a live WebGL canvas. Depth here comes from box-shadow only.
   ============================================================================= */
.ca-battle {
  position: fixed; inset: 0; z-index: 1200;
  display: flex; align-items: center; justify-content: center;
  background: radial-gradient(120% 90% at 50% 0%, rgba(8, 11, 16, .9), rgba(2, 3, 4, .97));
  animation: ha-fade .24s ease;
}
.ha-duel {
  position: relative; width: min(920px, 94vw); max-height: 92vh;
  display: flex; flex-direction: column; overflow: hidden; border-radius: var(--r-lg);
  background: linear-gradient(180deg, var(--card) 0%, #080a0e 42%, #06080b 100%), var(--grain);
  box-shadow: var(--slab-lg);
  animation: ha-modal-in .4s var(--ease) both;
}
.ca-x {
  position: absolute; top: var(--s3); right: var(--s3); z-index: 8;
  width: 40px; height: 40px; border-radius: var(--r-sm); cursor: pointer;
  display: flex; align-items: center; justify-content: center; color: var(--txt-mute);
  background: rgba(8, 11, 15, .72); box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .07);
  transition: color .2s, background .2s;
}
.ca-x:hover { color: var(--txt); background: rgba(255, 255, 255, .1); }

.ha-bt-head {
  position: relative; flex-shrink: 0;
  display: flex; align-items: center; justify-content: space-between; gap: var(--s3);
  padding: var(--s4) 62px var(--s4) 18px;   /* right gutter keeps the close button off the avatar */
  background: linear-gradient(180deg, rgba(20, 26, 34, .8), rgba(9, 12, 17, .4));
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .06);
}
.ha-bt-head::after {       /* GOLD SEAM 7 of 7 */
  content: ''; position: absolute; left: 0; right: 0; bottom: 0; height: 1px;
  background: linear-gradient(90deg, transparent, var(--line) 14%, rgba(232, 192, 122, .3) 50%, var(--line) 86%, transparent);
}
.ha-bt-player { display: flex; align-items: center; gap: var(--s3); min-width: 0; flex: 1; }
.ha-bt-player.right { flex-direction: row-reverse; text-align: right; }
.ha-bt-player img.ava {
  width: 46px; height: 46px; border-radius: 50%; flex-shrink: 0; object-fit: cover; background: var(--panel-2);
  box-shadow: 0 0 0 1px rgba(255, 255, 255, .16), 0 0 0 4px rgba(0, 0, 0, .6), 0 8px 18px -8px #000;
}
.ha-bt-pinfo { min-width: 0; }
.ha-bt-pname {
  display: flex; align-items: center; gap: 3px; overflow: hidden; margin-bottom: 3px;
  font-size: var(--fs-4); font-weight: 700; letter-spacing: .04em;
}
.ha-bt-pname > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.ha-bt-player.right .ha-bt-pname { justify-content: flex-end; }
.ha-bt-pstake { display: flex; align-items: center; gap: 6px; font-size: var(--fs-6); line-height: 1.1; }
.ha-bt-pstake .ha-coin { width: 15px; height: 15px; }
.ha-bt-player.right .ha-bt-pstake { justify-content: flex-end; }
.ha-bt-pot {
  position: relative; flex-shrink: 0; text-align: center; padding: var(--s2) 20px; border-radius: var(--r-sm);
  background: linear-gradient(180deg, rgba(232, 192, 122, .09), rgba(232, 192, 122, .02));
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1), inset 0 0 0 1px rgba(232, 192, 122, .22);
}
.ha-bt-pot .amt {
  display: flex; align-items: center; gap: var(--s2); justify-content: center;
  font-size: var(--fs-9); line-height: 1.15;
}
.ha-bt-pot .amt .ha-coin { width: 19px; height: 19px; }
.ha-bt-pot .lbl { font-size: var(--fs-2); font-weight: 700; letter-spacing: .16em; text-transform: uppercase; color: var(--txt-mute); margin-top: 3px; }
.ha-bt-pot .wpn { font-size: var(--fs-3); color: var(--gold); opacity: .8; margin-top: 2px; }

/* --- the stage. INVARIANTS LIVE HERE. do not loosen them. ----------------- */
.ca-stage {
  /* the flexible member of the panel: when the footer grows (Rematch/Close
     appear on finish) the panel hits max-height, and if the stage cannot give
     then the chat input and the buttons get clipped off the bottom instead. */
  /* flex-basis is the PREFERRED height, shrink is what saves the controls.
     flex-grow is useless here: the panel is content-sized under a max-height,
     so there is no free space to grow into and grow:1 just left the arena
     sitting at its min-height on tall screens. */
  position: relative; flex: 0 1 auto; min-height: 220px; display: flex;
  background: radial-gradient(120% 90% at 50% 8%, #0e131a, #05070a 78%);
}
.ca-arena3d { position: absolute; inset: 0; z-index: 0; overflow: hidden; pointer-events: none; }
.ca-3d .ca-arena3d { pointer-events: auto; }               /* the swipe/drag camera orbit */
/* bounded, not fixed: the canvas resizes to its container every frame, so the
   stage may shrink, but never below a height the fight is readable at. */
.ca-3d .ca-stage { flex: 0 1 min(58vh, 500px); min-height: 220px; }
.ca-3d .ca-stage > .ca-fighter-creator,
.ca-3d .ca-stage > .ca-fighter-opponent { display: none; }
.ca-3d .ca-weapon { display: none; }
/* .ca-mid is a flex item, so a z-index on it would build a stacking context —
   static keeps .ca-status free to position against the STAGE. */
.ca-3d .ca-mid { position: static; z-index: 3; }
/* Everything but the canvas is click-through, exactly as the invariant states.
   The finish panel is re-armed on its .inner instead of being exempted here,
   so the orbit gesture keeps working over the rest of the stage after a win. */
.ca-3d .ca-stage > div:not(.ca-arena3d) { pointer-events: none; }
.ca-state .inner { pointer-events: auto; }
/* arena viewport: HUD corner brackets from eight one-pixel gradients on ONE
   pseudo, plus the cinema vignette. pointer-events:none, so the orbit is safe. */
.ca-3d .ca-stage::before {
  content: ''; position: absolute; inset: var(--s3); z-index: 3; pointer-events: none; opacity: .75;
  background:
    linear-gradient(var(--gold), var(--gold)) 0 0 / 1px 16px no-repeat,
    linear-gradient(90deg, var(--gold), var(--gold)) 0 0 / 16px 1px no-repeat,
    linear-gradient(var(--gold), var(--gold)) 100% 0 / 1px 16px no-repeat,
    linear-gradient(90deg, var(--gold), var(--gold)) 100% 0 / 16px 1px no-repeat,
    linear-gradient(var(--gold), var(--gold)) 0 100% / 1px 16px no-repeat,
    linear-gradient(90deg, var(--gold), var(--gold)) 0 100% / 16px 1px no-repeat,
    linear-gradient(var(--gold), var(--gold)) 100% 100% / 1px 16px no-repeat,
    linear-gradient(90deg, var(--gold), var(--gold)) 100% 100% / 16px 1px no-repeat;
}
.ca-3d .ca-stage::after {
  content: ''; position: absolute; inset: 0; z-index: 2; pointer-events: none;
  background:
    linear-gradient(180deg, rgba(4, 6, 9, .82), transparent 22%),
    radial-gradient(130% 100% at 50% 50%, transparent 48%, rgba(3, 4, 6, .64) 100%);
}
.ca-fighter-creator, .ca-fighter-opponent {
  position: relative; z-index: 1; flex: 1;
  display: flex; flex-direction: column; align-items: center; justify-content: flex-start; gap: 10px;
  padding: var(--s5) var(--s3);
}
.ca-fighter-creator .ha-ava img, .ca-fighter-opponent .ha-ava img { width: 66px; height: 66px; }
.ca-mid {
  position: relative; z-index: 1; width: 150px;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: var(--s3);
}
.ca-weapon { width: 88px; height: 88px; filter: drop-shadow(0 8px 20px rgba(0, 0, 0, .9)); }
.ca-status {
  font-weight: 800; font-size: var(--fs-6); letter-spacing: .06em;
  text-align: center; color: var(--txt-dim); transition: color .3s;
}
.ca-3d .ca-status {
  position: absolute; left: 0; right: 0; top: var(--s4); bottom: auto; z-index: 3;
  font-family: var(--display); font-weight: 700; font-size: var(--fs-9); letter-spacing: .13em;
  text-transform: uppercase; color: var(--txt); padding: 0 var(--s4);
  text-shadow: 0 2px 4px rgba(0, 0, 0, 1), 0 2px 18px rgba(0, 0, 0, .95), 0 0 44px rgba(0, 0, 0, .9);
  animation: ha-status-in .4s var(--ease), ha-status-hold 3.4s ease-in-out .4s infinite;
}
@keyframes ha-status-in { from { opacity: 0; transform: translateY(-6px); } }
@keyframes ha-status-hold { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.018); } }

/* --- provably-fair drawer --------------------------------------------------- */
.ca-fair-wrap {
  flex-shrink: 0; padding: 10px var(--s5);
  background: rgba(0, 0, 0, .28); box-shadow: inset 0 1px 0 rgba(255, 255, 255, .045);
}
.ca-fair-wrap summary {
  cursor: pointer; list-style: none;
  font-size: var(--fs-3); font-weight: 600; color: var(--txt-mute);
  transition: color .2s;
}
.ca-fair-wrap summary:hover { color: var(--txt-dim); }
.ca-fair {
  display: flex; flex-direction: column; gap: 5px; padding: 10px 0 var(--s1);
  font-size: var(--fs-2); line-height: 1.6; color: var(--txt-mute); word-break: break-all;
}
.ca-fair b { color: var(--txt-dim); font-weight: 600; }
.ca-reveal:not(:empty) { padding-top: 6px; box-shadow: inset 0 1px 0 rgba(255, 255, 255, .05); margin-top: 2px; }

/* --- proximity chat --------------------------------------------------------- */
.ha-bt-chat {
  /* a flex column of its own so the log can shrink inside it while the input
     row and the Rematch/Close buttons keep their full height */
  flex: 0 0 auto; display: flex; flex-direction: column; min-height: 0;
  background: rgba(0, 0, 0, .25); box-shadow: inset 0 1px 0 rgba(255, 255, 255, .05);
}
.ha-bt-chat-top { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 10px var(--s5) 2px; flex-wrap: wrap; }
.ha-bt-chat-top .lbl { font-size: var(--fs-2); font-weight: 700; letter-spacing: .16em; text-transform: uppercase; color: var(--txt-mute); }
.ha-bt-chat-top > div { display: flex; flex-wrap: wrap; gap: 2px; }
.ca-emote {
  width: 40px; height: 40px; border-radius: var(--r-xs); font-size: 19px; line-height: 1; flex-shrink: 0;
  display: inline-flex; align-items: center; justify-content: center;
  transition: transform .2s var(--ease), background .2s;
}
.ca-emote:hover { transform: scale(1.25) translateY(-2px); background: rgba(255, 255, 255, .06); }
.ca-chat-log {
  flex: 0 1 92px; min-height: 56px; overflow-y: auto; overflow-x: hidden;
  padding: var(--s2) var(--s5); display: flex; flex-direction: column; gap: 6px;
}
.ca-chat-log .ha-msg-line { display: flex; gap: 7px; font-size: var(--fs-4); color: #cfd7df; animation: ha-msg-in .3s var(--ease) both; }
.ca-chat-log .ha-msg-line > span:last-child { word-break: break-word; min-width: 0; }
.ha-bt-chat .ha-chat-foot { background: none; box-shadow: none; padding: var(--s2) var(--s5) var(--s3); }
.ca-foot { display: flex; gap: 11px; padding: 0 var(--s5) var(--s4); flex-shrink: 0; }
.ca-foot:empty { padding: 0 0 var(--s2); }
.ca-foot .ha-btn { flex: 1; }

/* --- finish panel: the money shot ------------------------------------------- */
.ca-state {
  position: absolute; inset: 0; z-index: 5;
  display: flex; align-items: center; justify-content: center;
  /* no backdrop-filter: this sits directly over the live canvas */
  background: radial-gradient(90% 70% at 50% 42%, rgba(6, 9, 13, .78), rgba(3, 4, 7, .94));
  animation: ha-fade .35s ease;
}
.ca-state .inner {
  width: min(380px, 88%); padding: var(--s6) var(--s5); border-radius: var(--r-lg);
  display: flex; flex-direction: column; gap: var(--s4);
  background:
    radial-gradient(80% 50% at 50% 0%, rgba(232, 192, 122, .1), transparent 62%),
    linear-gradient(180deg, #141a22, #0a0d12), var(--grain);
  box-shadow: 0 0 0 1px rgba(232, 192, 122, .34), inset 0 1px 0 rgba(255, 255, 255, .12), 0 2px 8px rgba(0, 0, 0, .8), 0 40px 90px -30px #000;
  animation: ha-modal-in .45s var(--ease) both;
}
.ca-state h2 {
  font-family: var(--display); font-weight: 700; font-size: var(--fs-10);
  letter-spacing: .12em; text-transform: uppercase; text-align: center; line-height: 1.1;
  background: linear-gradient(180deg, var(--gold-hi), var(--gold) 50%, var(--gold-lo));
  -webkit-background-clip: text; background-clip: text; color: transparent; -webkit-text-fill-color: transparent;
}
.ca-state .duo { display: flex; gap: var(--s3); }
.ca-state .pc { flex: 1; min-width: 0; display: flex; flex-direction: column; align-items: center; gap: var(--s2); }
.ca-state .pc img.ava {
  width: 56px; height: 56px; border-radius: 50%; object-fit: cover;
  box-shadow: 0 0 0 1px rgba(232, 192, 122, .75), 0 0 0 4px rgba(0, 0, 0, .6), 0 8px 18px -8px rgba(0, 0, 0, .95);
}
.ca-state .pc.lost { opacity: .42; }
.ca-state .pc.lost img.ava { filter: grayscale(1); box-shadow: 0 0 0 1px rgba(224, 84, 74, .35), 0 0 0 4px rgba(0, 0, 0, .6); }
.ca-state .pc.lost .nm { color: #b1868a; }
.ca-state .pc .nm { font-size: var(--fs-4); font-weight: 700; letter-spacing: .03em; text-align: center; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 100%; }
.ca-state .rows { display: flex; flex-direction: column; gap: 10px; padding-top: var(--s3); box-shadow: inset 0 1px 0 rgba(255, 255, 255, .07); }
/* same receipt row as .ha-summary. money reads the same everywhere. */
.ca-state .row { display: flex; align-items: center; gap: 10px; }
.ca-state .row > span {
  order: 0; flex-shrink: 0;
  font-size: var(--fs-2); font-weight: 700; letter-spacing: .12em; text-transform: uppercase; color: var(--txt-mute);
}
.ca-state .row::before {
  content: ''; order: 1; flex: 1 1 auto; min-width: var(--s2); height: 1px;
  background: repeating-linear-gradient(90deg, rgba(232, 192, 122, .28) 0 2px, transparent 2px 6px);
}
.ca-state .row b { order: 2; flex-shrink: 0; display: flex; align-items: center; gap: 6px; font-size: var(--fs-7); }
.ca-state .row b .ha-coin { width: 15px; height: 15px; }
.ca-state-close { width: 100%; }

/* ------------------------------ toasts + fx ---------------------------------- */
.ha-toasts {
  position: fixed; left: 50%; bottom: var(--s6); z-index: 2000;
  display: flex; flex-direction: column; align-items: center; gap: 9px;
  transform: translateX(-50%); max-width: calc(100vw - 32px); pointer-events: none;
}
.ha-toast {
  padding: var(--s3) 18px; border-radius: var(--r-sm); font-size: var(--fs-4); font-weight: 500; color: var(--txt);
  background: linear-gradient(180deg, rgba(22, 28, 36, .97), rgba(12, 16, 21, .97));
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1), 0 0 0 1px rgba(255, 255, 255, .07), inset 3px 0 0 var(--green), 0 18px 40px -16px #000;
  animation: ha-toast-in .4s var(--ease) both;
}
@keyframes ha-toast-in { from { opacity: 0; transform: translateY(16px) scale(.96); } }
.ha-stake-status { position: fixed; z-index: 2001; bottom: calc(var(--bnav-h, 0px) + 20px); left: 50%; transform: translateX(-50%); width: min(560px, calc(100vw - 32px)); display: flex; gap: 14px; align-items: center; padding: 18px; border: 1px solid #364354; border-radius: 14px; background: #111923; color: var(--txt); box-shadow: 0 12px 48px #0009; }
.ha-stake-status strong { display: block; font-size: 14px; }
.ha-stake-status p { margin: 5px 0 0; color: var(--txt-dim); font-size: 12px; line-height: 1.5; }
.ha-stake-status-icon { width: 20px; height: 20px; flex: 0 0 20px; border: 2px solid #465263; border-top-color: #c7d6e8; border-radius: 50%; animation: ha-stake-spin 1s linear infinite; }
.ha-stake-status button { flex: 0 0 auto; font-size: 10px; }
.ha-stake-status button[hidden] { display: none; }
.ha-stake-status[data-state="success"] { border-color: #537d39; }
.ha-stake-status[data-state="error"] { border-color: #ac5656; }
.ha-stake-status[data-state="success"] .ha-stake-status-icon, .ha-stake-status[data-state="error"] .ha-stake-status-icon, .ha-stake-status[data-state="cancelled"] .ha-stake-status-icon { animation: none; border: none; text-align: center; }
.ha-stake-status[data-state="success"] .ha-stake-status-icon::after { content: '✓'; color: var(--green); }
.ha-stake-status[data-state="error"] .ha-stake-status-icon::after { content: '!'; color: #f79494; }
.ha-stake-status[data-state="cancelled"] .ha-stake-status-icon::after { content: '—'; }
@keyframes ha-stake-spin { to { transform: rotate(360deg); } }
@media (max-width: 520px) { .ha-stake-status { gap: 10px; padding: 14px; flex-wrap: wrap; } .ha-stake-status > div { flex: 1; min-width: 180px; } .ha-stake-status button { margin-left: 30px; } }
@media (prefers-reduced-motion: reduce) { .ha-stake-status-icon { animation: none; } }
@keyframes ca-shake { 0%, 100% { transform: translateX(0); } 25% { transform: translateX(-5px); } 75% { transform: translateX(5px); } }

/* The arena owns the frame. Every ambient loop inside the shell stops while a
   duel is on screen, so nothing composites behind the THREE canvas. Scoped to
   .ha-app so the battle overlay — appended to body — keeps its own motion. */
body.ca-lock .ha-app *,
body.ca-lock .ha-app *::before,
body.ca-lock .ha-app *::after { animation-play-state: paused !important; }

/* =============================================================================
   RESPONSIVE
   1280 — chat becomes an off-canvas drawer
    820 — rail out, bottom nav in, duel goes fullscreen
    400 — single column, wordmark drops to the mark
   ============================================================================= */
@media (max-width: 1279px) {
  .ha-app, body.ha-chat-open .ha-app { grid-template-columns: minmax(0, 1fr); }
  .ha-chat > * { width: auto; }
  body.ha-chat-open .ha-chat-toggle { left: 14px; }
  .ha-chat {
    position: fixed; top: 0; left: 0; bottom: 0; width: min(360px, 92vw); z-index: 95;
    /* visibility is what stops a real phone panning into the closed drawer */
    transform: translateX(-100%); visibility: hidden;
    transition: transform .3s var(--ease), visibility .3s;
    box-shadow: inset 1px 0 0 rgba(255, 255, 255, .05);
  }
  body.ha-chat-open .ha-chat {
    transform: translateX(0); visibility: visible;
    box-shadow: inset -1px 0 0 rgba(255, 255, 255, .05), 30px 0 70px -20px rgba(0, 0, 0, .9);
  }
  .ca-3d .ca-stage { flex-basis: 46vh; }
  .ha-main { padding: 22px 22px 52px; }
  .ha-hero { padding: var(--s6) var(--s6) var(--s5); min-height: 300px; }
}

@media (max-width: 819px) {
  /* the document scrolls here, not .ha-main: a 100dvh grid whose single row
     overflows leaves the page scrolling <body> instead, which is unanchorable */
  .ha-app { grid-template-columns: minmax(0, 1fr); grid-template-rows: auto; height: auto; min-height: 100dvh; overflow: visible; }
  .ha-main { overflow-y: visible; min-height: 0; }
  .ha-topnav { display: flex; flex: 0 0 auto; margin-left: 0; overflow: visible; }
  .ha-topnav-item:not([data-nav="locker"]):not([data-nav="shop"]) { display: none; }
  .ha-topnav-item[data-nav="locker"], .ha-topnav-item[data-nav="shop"] { padding-inline: 8px; }
  .ha-topnav-item[data-nav="locker"] span, .ha-topnav-item[data-nav="shop"] span { display: inline; }
  .ha-bnav { display: grid; }
  .ha-main { padding: var(--s3) var(--s3) calc(var(--bnav-h) + 34px); }
  /* the document scrolls on phones, so the bar has to stick or the balance
     scrolls away with it */
  .ha-top { height: 58px; padding: 0 var(--s3); position: sticky; top: 0; z-index: 60; }
  .ha-top-logo span { font-size: var(--fs-6); letter-spacing: .16em; }
  .ha-top-logo img { height: 40px; width: auto; margin-right: var(--s2); }
  .ha-pill { height: 42px; padding: 0 11px; gap: 7px; }
  .ha-pill-balance #ha-balance-amt { font-size: var(--fs-5); }
  .ha-pill-profile span { display: none; }
  .ha-chat { width: 100vw; max-width: 100vw; padding-bottom: env(safe-area-inset-bottom); }

  .ha-hero { min-height: 0; padding: var(--s6) var(--s5) var(--s5); margin-bottom: 22px; border-radius: var(--r); }
  .ha-hero > img { opacity: .55; }
  .ha-hero-title { margin-bottom: var(--s3); }
  .ha-hero-sub { font-size: var(--fs-5); margin-bottom: var(--s5); }
  .ha-tick, .ha-mark { padding: 10px 11px; }
  .ha-tick b, .ha-mark b { font-size: var(--fs-6); }

  .ha-sec { margin-bottom: var(--s6); }
  .ha-sec-head { flex-direction: column; align-items: stretch; gap: var(--s3); }
  .ha-sec-head h2 { font-size: var(--fs-7); }
  .ha-sec-head::after { flex: 0 0 1px; width: 100%; min-width: 0; }
  .ha-sec-actions { justify-content: stretch; }
  /* three selects in 360px clip their own labels; two per row read whole */
  .ha-sec-actions .ha-select { flex: 1 1 40%; min-width: 0; }
  .ha-sec-actions #ha-affordable { flex: 1 1 40%; min-width: 0; }
  .ha-sec-actions #ha-create { flex: 1 0 100%; min-height: 44px; }
  .ha-sec-actions #bt-new { display: none; } /* Chest Battle has its own mobile create action. */
  .ha-grid { grid-template-columns: repeat(auto-fill, minmax(258px, 1fr)); gap: var(--s3); }

  .ha-toasts { bottom: calc(var(--bnav-h) + 18px); }

  /* fullscreen battle */
  .ca-battle { padding: 0; align-items: stretch; }
  .ha-duel {
    width: 100vw; max-width: 100vw; height: 100vh; height: 100dvh; max-height: 100dvh;
    border-radius: 0; box-shadow: none; animation: none;
  }
  .ca-stage { flex: 0 1 auto; min-height: 200px; }
  .ca-3d .ca-stage { flex: 0 1 52dvh; min-height: 180px; }
  .ha-bt-head { padding: var(--s3) 54px var(--s3) var(--s3); gap: var(--s2); }
  .ha-bt-player img.ava { width: 38px; height: 38px; }
  .ha-bt-pname { font-size: var(--fs-3); }
  .ha-bt-pname .ha-badge { width: 22px; height: 22px; }
  .ha-bt-pstake { font-size: var(--fs-5); }
  .ha-bt-pot { padding: 6px var(--s3); }
  .ha-bt-pot .amt { font-size: var(--fs-8); }
  .ha-bt-pot .amt .ha-coin { width: 16px; height: 16px; }
  .ca-3d .ca-status { font-size: var(--fs-7); top: var(--s3); }
  .ca-chat-log { height: 74px; padding: var(--s2) var(--s3); }
  .ha-bt-chat-top { padding: var(--s2) var(--s3) 2px; }
  .ha-bt-chat .ha-chat-foot { padding: var(--s2) var(--s3) var(--s3); }
  .ca-foot { padding: 0 var(--s3) var(--s3); }
  .ca-fair-wrap { padding: 9px var(--s3); }
  /* one scrolling strip instead of two wrapped rows: the log needs the height */
  .ha-bt-chat-top > div {
    flex-wrap: nowrap; overflow-x: auto; overflow-y: hidden;
    -webkit-overflow-scrolling: touch; scrollbar-width: none; max-width: 100%;
  }
  .ha-bt-chat-top > div::-webkit-scrollbar { display: none; }

  .ha-modal-back { padding: var(--s3); }
  .ha-modal { padding: 22px 18px; border-radius: var(--r); }
  .ha-modal > h3 { font-size: var(--fs-8); margin-bottom: 18px; }
  .ha-lk-grid { grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 9px; }
  .ha-lk-stat { min-width: 124px; padding: var(--s3); }
  .ha-lk-stat .v { font-size: var(--fs-8); }
  .ha-ava-grid { grid-template-columns: repeat(5, minmax(0, 1fr)); }
  .ha-btn { height: 44px; }
  .ha-btn-lg { height: 50px; }
  .ha-select { height: 44px; }
}

@media (max-width: 400px) {
  /* the lobby is the product: keep the hero to roughly one thumb-scroll so a
     duel card is always the next thing on screen. */
  .ha-hero { padding: 22px var(--s4) 18px; }
  .ha-hero-title { letter-spacing: .02em; margin-bottom: 10px; }
  /* Drop the second sentence rather than clamping the paragraph: a clamp cut
     it mid-phrase at "Two fighters, one…", which reads as a rendering bug. */
  .ha-hero-sub { font-size: var(--fs-4); margin-bottom: var(--s4); }
  .ha-hero-sub-more { display: none; }
  /* side by side, not stacked: saves ~55px of fold for one card edge */
  /* measured at 375px: 113px of room in the bar, so the wordmark is tuned to
     fit it rather than hidden (a lone mark reads as a broken header). */
  /* The header now carries a chain badge, balance, wallet and avatar: measured
     at 375px the right side takes 283 of it, leaving 21px for a wordmark that
     needs 105. It rendered as "HO", which is worse than the mark standing
     alone, so below 500px the mark carries the brand by itself. */
  .ha-top-logo span { display: none; }
  .ha-top-logo { gap: 0; }
  .ha-grid { grid-template-columns: minmax(0, 1fr); }
  /* three across, labels allowed to wrap: 62px of board instead of 165px */
  .ha-tick { padding: 9px var(--s2) 8px; }
  .ha-tick b { font-size: var(--fs-6); }
  .ha-tick span { font-size: var(--fs-2); line-height: 1.25; }
  .ha-half { padding: var(--s3) 6px var(--s3); }
  .ha-vs { width: 46px; height: 46px; top: 14px; }
  .ha-vs svg, .ha-vs > div, .ha-vs .ha-wpn-art { width: 27px; height: 27px; }
  .ha-stake { padding: var(--s3) 10px; gap: var(--s2); }
  .ha-stake span { font-size: var(--fs-7); }
  .ha-ava-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .ha-row { gap: 7px; }
  .ha-modal { padding: 20px 14px; }
  .ca-emote { width: 40px; height: 40px; }
}

/* short viewports: keep the whole duel panel on screen */
@media (min-width: 820px) and (max-height: 720px) {
  .ca-3d .ca-stage { flex-basis: 40vh; min-height: 150px; }
  .ca-chat-log { height: 64px; }
  .ha-bt-head { padding-top: 11px; padding-bottom: 11px; }
}

/* ----------------------------- reduced motion -------------------------------- */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    scroll-behavior: auto !important;
  }
  .ha-card:hover, .ha-item:hover, .ha-pill:hover, .ha-wpn-tile:hover,
  .ha-quick:hover, .ha-ava-pick:hover, .ca-emote:hover { transform: none; }
  .ha-card:hover .ha-vs { transform: translateX(-50%); }
  .ha-half-join:hover .ha-join-plus { transform: none; }
  .ha-half-join:hover .ha-join-plus svg { transform: none; }
  .ha-modal-x:hover { transform: none; }
}

/* =============================================================================
   TOKEN PAGE : $HOOD
   A full-width panel that replaces the lobby inside .ha-main.

   Depth here is neutral only: black elevation, the 1px lit top bevel, the
   hairline ring, contrast. No coloured blur anywhere on this page, the three
   inherited glows it would otherwise pick up are switched off near the bottom.
   Gold = money and the token itself. Green = the one thing you can press.

   Layout breaks on the PANEL's width, not the viewport's, because the docked
   chat column takes 336px off this panel between 820px and 1279px. A viewport
   breakpoint would hand a 560px-wide panel the full desktop grid.
   ============================================================================= */
.ha-tok {
  container: tok / inline-size;
  animation: ha-rise .55s var(--ease) both;
}

/* money and token values: mono, tabular, struck in foil like every other
   currency figure on the site. */
.ha-tok-money, .ha-tok-fig {
  font-family: var(--num); font-variant-numeric: tabular-nums;
  letter-spacing: -.01em; font-weight: 700;
}
.ha-tok-money {
  background: linear-gradient(180deg, var(--gold-hi) 0%, var(--gold) 44%, var(--gold-lo) 100%);
  -webkit-background-clip: text; background-clip: text;
  color: transparent; -webkit-text-fill-color: transparent;
}
/* a percentage is not currency, so it stays white. that difference is the
   whole point of the foil. */
.ha-tok-fig { color: var(--txt); }

@supports not ((-webkit-background-clip: text) or (background-clip: text)) {
  .ha-tok-money { background: none; color: var(--gold); -webkit-text-fill-color: var(--gold); }
}
@media (forced-colors: active) {
  .ha-tok-money { background: none; color: CanvasText; -webkit-text-fill-color: CanvasText; forced-color-adjust: auto; }
}

/* ===========================================================================
   TOKEN PAGE - THE LOOP

   The page was five stacked essays about one loop: the 50/50 split stated six
   times across 431 words, the reader's own position printed twice from three
   duplicated setTxt pairs, and the biggest element on the page a hardcoded
   "50%". Pre-launch the h1 rendered as a single "$" over 780px of gold zeros
   under a heading reading "Live numbers".

   It is now the money flow itself: one gold conduit down the left, five stops
   on it, each carrying the single live figure that stage has produced, and the
   line turning back at the bottom because the token you are paid in is the
   token you stake. The mechanism is drawn whether or not anything has flowed
   through it, which is the only reason it survives a page where every live
   number is currently zero.

   Tiers are @container tok, never @media: the docked chat column takes 336px
   off this panel between 820 and 1279, so a viewport query would hand a 560px
   panel the desktop grid.
   =========================================================================== */

/* --- masthead. Flat on the page ground, so the conduit is the first raised
       thing the eye meets. ------------------------------------------------- */
.ha-tok-head { margin-bottom: var(--s6); }
.ha-tok-kicker {
  font-size: var(--fs-2); font-weight: 700; letter-spacing: .2em;
  text-transform: uppercase; color: var(--txt-mute); margin-bottom: var(--s2);
}
.ha-tok-title {
  font-family: var(--display); font-weight: 900; font-size: var(--fs-7);
  line-height: 1.1; letter-spacing: .03em; color: var(--txt); margin-bottom: var(--s4);
}
.ha-tok-title em {
  font-style: normal;
  background: linear-gradient(180deg, var(--gold-hi) 0%, var(--gold) 46%, #c9a25c 100%);
  -webkit-background-clip: text; background-clip: text;
  color: transparent; -webkit-text-fill-color: transparent;
}
.ha-tok-rule {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--s2) var(--s3);
  font-size: var(--fs-3); color: var(--txt-dim); margin-bottom: var(--s4);
}
.ha-tok-rule b { font-size: var(--fs-9); line-height: 1; margin-right: 6px; }
.ha-tok-rule i { font-style: normal; font-size: var(--fs-6); color: var(--txt-mute); }
.ha-tok-lede { max-width: 54ch; font-size: var(--fs-5); line-height: 1.6; color: var(--txt-dim); margin-bottom: var(--s4); }
.ha-tok-actions { display: flex; flex-wrap: wrap; gap: var(--s3); }
.ha-tok-actions > .ha-btn, .ha-tok-actions > a.ha-btn { flex: 1 1 200px; min-height: 44px; }
/* The gas sentence sits under the buy button it is a prerequisite for, rather
   than 500 words below it as a separately injected section. */
/* Not a link until there is an address to link to. The one claim on the old
   page that could cost somebody money was a live buy link to a listing that
   does not exist. */
.ha-tok-actions .is-off { opacity: .45; pointer-events: none; filter: saturate(.4); }

@supports not ((-webkit-background-clip: text) or (background-clip: text)) {
  .ha-tok-title em { background: none; color: var(--gold); -webkit-text-fill-color: var(--gold); }
}
@media (forced-colors: active) {
  .ha-tok-title em { background: none; color: CanvasText; -webkit-text-fill-color: CanvasText; forced-color-adjust: auto; }
}

/* --- the conduit --------------------------------------------------------- */
.ha-flow { list-style: none; display: grid; gap: var(--s6); margin: 0; padding: 0; }
.ha-stop {
  position: relative; min-width: 0;
  display: grid; grid-template-columns: 30px minmax(0, 1fr);
  column-gap: var(--s4); align-items: start;
}
/* Drawn per stop and overlapping the gap, so consecutive stops form one
   unbroken line with no wrapper element to keep in sync. */
.ha-stop::before {
  content: ''; position: absolute; left: 14px; top: 0; width: 2px; border-radius: 1px;
  bottom: calc(var(--s6) * -1 - 1px);
  background: linear-gradient(180deg, var(--gold-lo), rgba(169, 119, 42, .45));
}
.ha-stop:last-child::before { bottom: auto; height: 30px; }
.ha-stop-mark {
  width: 30px; height: 30px; border-radius: 50%; position: relative; z-index: 1;
  display: grid; place-items: center;
  font-family: var(--num); font-size: var(--fs-2); font-weight: 700; color: var(--gold);
  background: var(--well); box-shadow: var(--sink), 0 0 0 1px rgba(232, 192, 122, .38);
}
.ha-stop h2 {
  font-family: var(--display); font-weight: 700; font-size: var(--fs-6);
  letter-spacing: .06em; text-transform: uppercase; color: var(--txt); margin-bottom: var(--s2);
}
.ha-stop p { font-size: var(--fs-3); line-height: 1.6; color: var(--txt-dim); max-width: 56ch; }
.ha-stop p + p { margin-top: var(--s2); }
.ha-stop-meta { color: var(--txt-mute); }
.ha-stop-meta b { font-family: var(--num); color: var(--txt-dim); font-weight: 700; }

.ha-stop-fig {
  display: flex; align-items: baseline; gap: var(--s2); margin-bottom: var(--s2);
  overflow-wrap: anywhere;   /* wrap a monster number, never ellipsis it */
}
.ha-stop-fig b { font-size: var(--fs-8); line-height: 1.05; }
.ha-stop-fig .u { font-family: var(--num); font-size: var(--fs-3); letter-spacing: .08em; color: var(--txt-mute); }
/* No flex gap held open for a unit that is not there yet. */
.ha-stop-fig .u:empty, .ha-you .u:empty, .ha-rail .u:empty { display: none; }

/* --- stop 3: the fork. The column widths come off live balances, so the
       picture IS the data rather than a hardcoded 50% in the largest type on
       the page. Pre-launch it holds at 50/50 and the amounts say so in words. */
.ha-fork {
  display: grid; min-height: 76px; margin-bottom: var(--s3);
  grid-template-columns: max(24%, calc(var(--to-holders, 50) * 1%)) 2px minmax(0, 1fr);
  border-radius: var(--r-sm); overflow: hidden;
  background: var(--well); box-shadow: var(--sink);
}
.ha-branch {
  position: relative; min-width: 0; padding: var(--s3);
  display: flex; flex-direction: column; justify-content: flex-end; gap: 2px;
}
.ha-branch::before { content: ''; position: absolute; inset: 0 0 auto; height: 2px; }
.ha-branch.is-holders { background: linear-gradient(180deg, rgba(232, 192, 122, .16), rgba(232, 192, 122, .05)); }
.ha-branch.is-holders::before { background: linear-gradient(90deg, var(--gold-hi), var(--gold-lo)); }
.ha-branch.is-ops { background: linear-gradient(180deg, var(--raise), var(--panel-2)), var(--brush); }
.ha-branch.is-ops::before { background: rgba(255, 255, 255, .14); }
.ha-branch .pct {
  font-family: var(--num); font-weight: 700; font-size: var(--fs-8); line-height: 1;
  color: var(--gold);   /* flat gold, not a fourth background-clip:text instance */
}
.ha-branch.is-ops .pct { color: var(--txt-dim); }
.ha-branch .lbl { font-size: var(--fs-2); font-weight: 700; letter-spacing: .12em; text-transform: uppercase; color: var(--txt-mute); }
.ha-branch .amt { font-family: var(--num); font-size: var(--fs-2); color: var(--txt-mute); }
.ha-fork-div { background: rgba(0, 0, 0, .6); box-shadow: 0 0 0 1px rgba(255, 255, 255, .06); }

/* --- stop 4: the holders' meter. Paid is solid foil, owed is gold ticks.
       It shows the half instead of restating it. --------------------------- */
.ha-rail { margin-bottom: var(--s3); }
.ha-rail-track {
  display: flex; height: 10px; border-radius: var(--r-pill); overflow: hidden;
  background: var(--well); box-shadow: var(--sink); margin-bottom: var(--s3);
}
.ha-rail-track i { display: block; height: 100%; transition: width .6s var(--ease); }
.ha-rail-track .is-paid {
  background: linear-gradient(180deg, var(--gold-hi), var(--gold) 55%, #c9a25c);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .45);
}
.ha-rail-track .is-owed { background: var(--ticks), rgba(232, 192, 122, .16); }
/* pre-launch: a meter waiting, not a chart that broke */
.ha-rail.is-empty .ha-rail-track { box-shadow: var(--sink), inset 0 0 0 1px var(--gold-dim); }
.ha-rail-legend { display: grid; gap: var(--s3); margin: 0; }
.ha-rail-legend > div { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: baseline; gap: var(--s3); }
.ha-rail-legend dt { font-size: var(--fs-2); font-weight: 700; letter-spacing: .1em; text-transform: uppercase; color: var(--txt-dim); }
.ha-rail-legend dd { display: flex; align-items: baseline; gap: var(--s2); text-align: right; margin: 0; }
.ha-rail-legend dd b { font-family: var(--num); font-weight: 700; font-size: var(--fs-7); line-height: 1.1; }
.ha-rail-legend dd .u { font-family: var(--num); font-size: var(--fs-2); letter-spacing: .08em; color: var(--txt-mute); }

/* --- stop 5: the one stop the reader can act on, and the only place on the
       page a personal number appears. Green earns its place here only. ----- */
.ha-stop.is-you::before { background: linear-gradient(180deg, var(--gold-lo), rgba(204, 255, 0, .5)); }
.ha-stop.is-you .ha-stop-mark { color: var(--green); box-shadow: var(--sink), 0 0 0 1px rgba(204, 255, 0, .45); }
.ha-you {
  margin-top: var(--s3); padding: var(--s4); border-radius: var(--r);
  background: var(--card), var(--grain); box-shadow: var(--slab);
}
/* No text-overflow anywhere in here: a truncated currency figure is not a
   small number, it is a wrong number in gold foil. */
.ha-you-rows dd b { font-family: var(--num); font-weight: 700; font-size: var(--fs-7); line-height: 1.1; }
.ha-you-rows dd .u { font-family: var(--num); font-size: var(--fs-2); letter-spacing: .08em; color: var(--txt-mute); }
.ha-you-note, .ha-you-cos { margin-top: var(--s3); font-size: var(--fs-3); line-height: 1.6; color: var(--txt-mute); }
.ha-you-out { font-size: var(--fs-5); line-height: 1.55; color: var(--txt); max-width: 44ch; margin-bottom: var(--s4); }
.ha-link {
  background: none; border: 0; padding: 0; cursor: pointer;
  font: inherit; color: var(--green-soft); text-decoration: underline; text-underline-offset: 2px;
}
/* Claims render inside the stop. The old page injected them as their own
   section outside the container-query root, so no tier ever reached them. */
#ha-claims-slot:empty { display: none; }
#ha-claims-slot { margin-top: var(--s3); display: grid; gap: var(--s2); }

/* --- the loop closes. Two pseudo-elements, no SVG, no new asset. --------- */
.ha-flow-back {
  position: relative; margin: 0 0 0 46px; padding-top: var(--s4);
  font-size: var(--fs-3); color: var(--txt-mute);
}
.ha-flow-back::before {
  content: ''; position: absolute; left: -32px; top: -30px; width: 30px; height: 46px;
  border-left: 2px solid rgba(232, 192, 122, .45);
  border-bottom: 2px solid rgba(232, 192, 122, .45);
  border-bottom-left-radius: 12px;
}
.ha-flow-back::after {
  content: ''; position: absolute; left: -37px; top: -36px;
  border: 5px solid transparent; border-bottom-color: rgba(232, 192, 122, .6);
}

/* --- ONE tier. The diagram becomes an aligned ledger, from one query. ---- */
@container tok (min-width: 640px) {
  .ha-tok-title { font-size: var(--fs-8); }
  .ha-tok-rule b { font-size: var(--fs-10); }
  .ha-tok-lede { font-size: var(--fs-6); }
  .ha-tok-actions > .ha-btn, .ha-tok-actions > a.ha-btn { flex: 0 0 auto; }
  .ha-stop { column-gap: var(--s5); }
  .ha-stop-body {
    display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 32%);
    column-gap: var(--s5); align-items: start;
  }
  .ha-stop h2, .ha-stop p { grid-column: 1; }
  .ha-stop-fig { grid-column: 2; grid-row: 1 / span 2; justify-content: flex-end; margin: 0; }
  .ha-fork, .ha-rail, .ha-you, #ha-claims-slot { grid-column: 1 / -1; }
  .ha-fork { min-height: 100px; }
  .ha-branch .pct { font-size: var(--fs-9); }
  .ha-rail-legend { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s5); }
  .ha-rail-legend > div { grid-template-columns: minmax(0, 1fr); }
  .ha-rail-legend dd { justify-content: flex-start; }
}

/* ===========================================================================
   LOCKER PREVIEW, ITEM ART AND THE NEW-DUELS PILL
   Same material rules as the rest of the sheet: neutral elevation, a lit 1px
   bevel, a hairline ring. No coloured bloom anywhere.
   =========================================================================== */

/* --- item art: real drawings replace the old gradient swatches ------------ */
.ha-item-art {
  width: 100%; height: 72px; object-fit: contain; display: block;
  /* the art carries its own contact shadow, so the frame stays flat */
}
.ha-item-prev { padding: 6px; }

/* --- the live character turntable ----------------------------------------- */
.ha-lk-top {
  display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--s3);
  min-width: 0; margin-bottom: 0;
}
.ha-locker { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--s4); align-items: start; }
.ha-lk-body { min-width: 0; container: locker / inline-size; }
.ha-lk-body .ha-item { min-width: 0; }
.ha-lk-3d canvas:focus-visible { outline: 2px solid var(--green); outline-offset: -3px; }
.ha-lk-preview {
  position: relative; min-width: 0; border-radius: var(--r-sm); overflow: hidden;
  background:
    radial-gradient(120% 90% at 50% 8%, #161c25 0%, #0c1015 52%, #07090c 100%);
  box-shadow: var(--sink);
}
.ha-lk-3d { width: 100%; height: 250px; }
.ha-lk-controls {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 4px;
  padding: 4px 8px 8px; border-top: 1px solid var(--line-soft);
}
.ha-lk-controls button {
  min-height: 44px; min-width: 0; padding: 0 10px; border-radius: var(--r-xs);
  font-size: var(--fs-3); font-weight: 600; color: var(--txt-dim); cursor: pointer;
}
.ha-lk-controls button:hover { color: var(--txt); background: var(--raise); }
.ha-lk-controls button[aria-pressed="true"] { color: var(--txt); background: var(--raise); box-shadow: inset 0 -2px var(--green); }
.ha-lk-controls button:disabled { opacity: .5; cursor: default; }
.ha-lk-hint {
  padding: 0 8px 8px; text-align: center;
  font-size: var(--fs-1); font-weight: 700; letter-spacing: .14em;
  text-transform: uppercase; color: var(--txt-mute); pointer-events: none;
}
.ha-lk-nogl {
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: var(--s2); height: 100%;
  font-size: var(--fs-3); color: var(--txt-mute); text-align: center; padding: var(--s4);
}
.ha-lk-nogl img { display: block; width: 140px; height: 140px; object-fit: contain; }
.ha-lk-side { min-width: 0; display: flex; flex-direction: column; gap: var(--s3); }
.ha-lk-side .ha-lk-stats { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s2); margin-bottom: 0; }
.ha-lk-side .ha-lk-stat { min-width: 0; padding: var(--s3); background: var(--panel-2); box-shadow: none; border: 1px solid var(--line); }
.ha-lk-side .ha-lk-stat .v { font-size: var(--fs-7); overflow-wrap: anywhere; }
.ha-lk-side .ha-lk-stat .l { font-size: var(--fs-1); letter-spacing: .04em; }
.ha-lk-side .ha-src { display: block; margin: var(--s1) 0 0; }
.ha-lk-side .ha-fair-note { margin: 0; font-size: var(--fs-3); line-height: 1.6; }

@media (min-width: 820px) {
  .ha-locker { grid-template-columns: minmax(220px, 300px) minmax(0, 1fr); gap: var(--s6); }
  .ha-lk-3d { height: min(360px, 45vh); }
}
/* One sticky column keeps the figure, balances and explanation together.
   Short screens use normal page scrolling so every control stays reachable. */
@media (min-width: 820px) and (min-height: 760px) {
  .ha-lk-top { position: sticky; top: var(--s3); }
}

/* --- "N new duels": the lobby churns, so arrivals wait for a tap ---------- */
.ha-newpill {
  position: fixed; left: 50%; transform: translateX(-50%);
  top: calc(60px + var(--s3));
  z-index: 80; display: inline-flex; align-items: center; gap: 8px;
  height: 38px; padding: 0 16px; border-radius: var(--r-pill);
  font-size: var(--fs-3); font-weight: 700; letter-spacing: .02em;
  color: #141a00; background: linear-gradient(180deg, #d9ff33, var(--green));
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, .5),
    0 0 0 1px rgba(204, 255, 0, .5),
    0 2px 6px rgba(0, 0, 0, .55),
    0 14px 26px -14px #000;
  animation: ha-pill-in .22s var(--ease) both;
}
.ha-newpill:hover { background: linear-gradient(180deg, #2ae033, #08c30d); }
.ha-newpill:focus-visible { outline: 2px solid var(--gold); outline-offset: 3px; }
.ha-newpill-n {
  font-family: var(--num); font-variant-numeric: tabular-nums; font-weight: 700;
  min-width: 18px; text-align: center;
}
@keyframes ha-pill-in { from { opacity: 0; transform: translate(-50%, -8px); } }

@media (max-width: 819px) {
  .ha-newpill { top: calc(54px + var(--s2)); height: 40px; }
}
@media (prefers-reduced-motion: reduce) {
  .ha-newpill { animation: none; }
}

/* --- the $HOOD mark, used wherever the token is named --------------------- */
.ha-hoodmark { color: var(--gold); flex-shrink: 0; }

/* ---------------------------------------------------------------------------
   SHORT VIEWPORTS: the battle panel must never clip its own controls.
   A laptop at 620px tall cannot hold a 220px arena plus the full chat block
   plus the Rematch/Close row, so on short screens the optional chrome gives
   way first and the arena scales with the viewport rather than a fixed floor.
   --------------------------------------------------------------------------- */
@media (min-width: 820px) and (max-height: 780px) {
  .ha-duel { max-height: 96vh; }
  .ca-stage,
  .ca-3d .ca-stage { min-height: 26vh; }
  .ha-bt-head { padding-top: var(--s2); padding-bottom: var(--s2); }
  .ha-bt-player img.ava { width: 38px; height: 38px; }
  .ca-fair-wrap { padding-top: 4px; padding-bottom: 4px; }
  .ha-bt-chat-top { padding-top: 6px; padding-bottom: 0; }
  .ca-chat-log { flex: 0 1 68px; min-height: 48px; }
  .ha-bt-chat .ha-chat-foot { padding-top: 6px; padding-bottom: var(--s2); }
  .ca-foot { padding-bottom: var(--s3); }
}
@media (min-width: 820px) and (max-height: 620px) {
  /* very short: the emote strip and the fairness row are the first to go */
  .ca-stage, .ca-3d .ca-stage { min-height: 30vh; }
  .ca-chat-log { flex: 0 1 52px; min-height: 40px; }
  .ha-bt-chat-top .lbl { display: none; }
  .ha-bt-head { padding-top: 6px; padding-bottom: 6px; }
}

/* The finish card lives inside .ca-stage, and the stage now shrinks to keep the
   panel's controls on screen. Cap the card to its stage so it can never spill
   over the fairness row and the chat below it. */
.ca-state { overflow: hidden; }
.ca-state .inner {
  max-height: calc(100% - var(--s4));
  overflow-y: auto;
}
@media (max-height: 820px) {
  .ca-state .inner { padding: var(--s4) var(--s4); gap: var(--s3); }
  .ca-state h2 { font-size: var(--fs-7); }
  .ca-state .pc img.ava { width: 42px; height: 42px; }
  .ca-state .rows { padding-top: var(--s2); gap: 5px; }
  .ca-state .inner .ha-btn { height: 38px; }
}

/* the finish card has to live inside a stage that can be as short as 26vh */
@media (max-height: 900px) {
  .ca-state .inner { padding: var(--s4); gap: var(--s3); width: min(420px, 92%); }
  .ca-state h2 { font-size: var(--fs-7); letter-spacing: 1.4px; }
  .ca-state .duo { gap: var(--s3); }
  .ca-state .pc { gap: 4px; }
  .ca-state .pc img.ava { width: 40px; height: 40px; }
  .ca-state .pc .nm { font-size: var(--fs-3); }
  .ca-state .rows { padding-top: var(--s2); gap: 4px; }
  .ca-state .row { font-size: var(--fs-3); }
}

/* ---------------------------------------------------------------------------
   BATTLE HEADER ON NARROW PHONES
   Both stakes are equal by construction and the pot in the middle already
   states the total, so printing each player's stake as well is the third copy
   of the same number and it was squeezing names down to "Gue…". Drop the
   per-player line under 430px and give the name the width instead.
   --------------------------------------------------------------------------- */
@media (max-width: 430px) {
  .ha-bt-pstake { display: none; }
  /* measured at 375: side by side leaves the name 49px and it needs 73, so it
     came out as "Gues…". Stacked, the name gets the whole 95px column. */
  .ha-bt-player, .ha-bt-player.right { flex-direction: column; gap: 5px; text-align: center; }
  .ha-bt-pname, .ha-bt-player.right .ha-bt-pname { justify-content: center; max-width: 100%; }
  .ha-bt-pname { font-size: var(--fs-3); }
  .ha-bt-player img.ava { width: 34px; height: 34px; }
  .ha-bt-pinfo { min-width: 0; max-width: 100%; }
  .ha-bt-pot { min-width: 0; }
  .ha-bt-pot .amt { font-size: var(--fs-6); }
  /* the emote strip stays a horizontal scroller, but say so with a fade */
  .ha-bt-chat-top > div {
    -webkit-mask-image: linear-gradient(90deg, #000 0, #000 88%, transparent 100%);
            mask-image: linear-gradient(90deg, #000 0, #000 88%, transparent 100%);
  }
}

/* the logo is a link home, so it needs a real target, not the height of its text */
.ha-top-logo { padding: 8px 4px; margin: -8px -4px; }

/* ---------------------------------------------------------------------------
   LOCKER > FACE TAB
   Identity, not loot. Nothing here is locked, so no item card, no lock icon,
   no requirement line and no Save: a tap writes the option and the turntable
   redraws. Four labelled groups, each one row of pickers. Selection reads as
   a green ring + a lifted face + a check chip. No bloom anywhere.
   --------------------------------------------------------------------------- */
.ha-face { display: flex; flex-direction: column; }
.ha-face-save {
  display: flex; align-items: center; justify-content: space-between; gap: var(--s3);
  min-height: 36px; margin-bottom: var(--s3); font-size: var(--fs-3); line-height: 1.5; color: var(--txt-dim);
}
.ha-face-save button { flex-shrink: 0; }

.ha-face-group { padding: var(--s4) 0; border-top: 1px solid var(--line-soft); }
.ha-face-group:first-child { padding-top: 2px; border-top: 0; }
.ha-face-group:last-child { padding-bottom: 2px; }
.ha-face-head {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: var(--s3); margin-bottom: 11px;
}
.ha-face-label {
  font-size: var(--fs-2); font-weight: 700; letter-spacing: .14em;
  text-transform: uppercase; color: var(--txt-mute);
}
/* the swatches carry no text, so the head says what is picked right now */
.ha-face-val { font-size: var(--fs-3); font-weight: 600; color: var(--txt-dim); }
.ha-face-note { margin-top: 10px; font-size: var(--fs-3); color: var(--txt-mute); line-height: 1.55; }

/* --- colour rows: skin tone, hair colour ---------------------------------- */
.ha-face-row { display: flex; flex-wrap: wrap; gap: 10px; }
.ha-face-sw {
  position: relative; flex: 0 0 auto; width: 44px; height: 44px; padding: 0;
  border-radius: var(--r-xs); cursor: pointer;
  /* one hard 2-tone facet, same shading logic as the fighters. not a gradient. */
  background:
    linear-gradient(135deg, rgba(255, 255, 255, .16) 0 46%, rgba(0, 0, 0, .24) 46% 100%),
    var(--sw, #444);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, .3),
    0 0 0 1px rgba(255, 255, 255, .09),
    0 3px 8px -3px rgba(0, 0, 0, .9);
  transition: transform .22s var(--ease), box-shadow .22s;
}
.ha-face-sw:hover {
  transform: translateY(-2px);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, .36),
    0 0 0 1px rgba(255, 255, 255, .2),
    0 7px 14px -5px rgba(0, 0, 0, .95);
}
.ha-face-sw.is-on {
  transform: translateY(-2px);
  /* black hairline first so the ring still reads on the green 'dyed' swatch */
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, .36),
    0 0 0 1px rgba(0, 0, 0, .85),
    0 0 0 3px var(--green),
    0 7px 14px -5px rgba(0, 0, 0, .95);
}

/* --- shape rows: hair style, beard. the square takes an <img> -------------- */
.ha-face-thumbs {
  /* 88px floor = 3 up at 375px, 4 up in the full 480px modal. Bigger squares
     because a hairline and a jaw have to read at a glance. */
  display: grid; grid-template-columns: repeat(auto-fill, minmax(88px, 1fr)); gap: 10px;
}
.ha-face-thumb {
  position: relative; display: flex; flex-direction: column; align-items: center;
  gap: 6px; min-width: 0; padding: 0; cursor: pointer;
  transition: transform .22s var(--ease);
}
.ha-face-thumb-art {
  width: 100%; aspect-ratio: 1 / 1; min-height: 56px; overflow: hidden;
  border-radius: var(--r-xs);
  display: flex; align-items: center; justify-content: center;
  background: radial-gradient(circle at 50% 34%, #151b23, #080a0e 74%);
  box-shadow: var(--sink), 0 0 0 1px rgba(255, 255, 255, .07);
  transition: box-shadow .22s;
}
.ha-face-thumb-art img { width: 100%; height: 100%; object-fit: contain; display: block; }
.ha-face-thumb-name {
  font-size: var(--fs-3); font-weight: 600; color: var(--txt-mute);
  line-height: 1.2; text-align: center;
  max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.ha-face-thumb:hover { transform: translateY(-2px); }
.ha-face-thumb:hover .ha-face-thumb-art { box-shadow: var(--sink), 0 0 0 1px rgba(255, 255, 255, .2); }
.ha-face-thumb:hover .ha-face-thumb-name { color: var(--txt-dim); }
.ha-face-thumb.is-on { transform: translateY(-2px); }
.ha-face-thumb.is-on .ha-face-thumb-art { box-shadow: var(--sink), 0 0 0 2px var(--green); }
.ha-face-thumb.is-on .ha-face-thumb-name { color: var(--txt); }

/* --- the check. sits INSIDE the target: .ha-modal clips overflow-x --------- */
.ha-face-sw.is-on::after, .ha-face-thumb.is-on::after {
  content: '\2713' / ''; position: absolute; z-index: 2;
  width: 18px; height: 18px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  font-size: 11px; font-weight: 800; line-height: 1; color: #04210a;
  background: linear-gradient(180deg, var(--green-soft), var(--green));
  box-shadow: 0 0 0 1.5px rgba(0, 0, 0, .6), inset 0 1px 0 rgba(255, 255, 255, .5);
}
.ha-face-sw.is-on::after { right: 3px; bottom: 3px; }
.ha-face-thumb.is-on::after { right: 4px; top: 4px; }

@media (max-width: 400px) {
  /* Keep all six tones in one row even at the 320px account width. */
  .ha-face-sw { width: 100%; min-width: 0; height: 44px; }
  .ha-face-row { display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); gap: 6px; }
  .ha-face-thumbs { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; }
  .ha-face-group { padding: var(--s3) 0; }
}

@media (prefers-reduced-motion: reduce) {
  .ha-face-sw, .ha-face-thumb, .ha-face-thumb-art { transition: none; }
  .ha-face-sw:hover, .ha-face-sw.is-on,
  .ha-face-thumb:hover, .ha-face-thumb.is-on { transform: none; }
}

@media (forced-colors: active) {
  /* the ring is a box-shadow and box-shadows are dropped here */
  .ha-face-sw.is-on, .ha-face-thumb.is-on .ha-face-thumb-art { outline: 3px solid Highlight; outline-offset: 1px; }
  /* a skin tone repainted as Canvas is meaningless, so keep the real colour */
  .ha-face-sw { forced-color-adjust: none; border: 1px solid CanvasText; }
}

/* ===========================================================================
   WALLET, CHAIN STATUS AND DEPOSIT
   The badge is the most important element here: a balance shown without
   a label is the most misleading thing this product could do.
   =========================================================================== */
.ha-chainbadge {
  display: inline-flex; align-items: center; height: 24px; padding: 0 9px;
  border-radius: var(--r-xs); font-size: var(--fs-1); font-weight: 800;
  letter-spacing: .12em; white-space: nowrap;
  background: var(--raise); color: var(--txt-mute);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .06), 0 0 0 1px rgba(255, 255, 255, .07);
}
.ha-chainbadge.is-live { color: var(--green-soft); box-shadow: inset 0 1px 0 rgba(255,255,255,.08), 0 0 0 1px rgba(204, 255, 0, .45); }
.ha-chainbadge.is-warn,
.ha-chainbadge.is-warn { color: var(--red); box-shadow: inset 0 1px 0 rgba(255,255,255,.08), 0 0 0 1px rgba(224, 84, 74, .5); }

.ha-pill-wallet.is-on { color: var(--green-soft); box-shadow: inset 0 1px 0 rgba(255,255,255,.08), 0 0 0 1px rgba(204, 255, 0, .4), 0 2px 6px rgba(0,0,0,.5); }
.ha-pill-wallet svg { flex-shrink: 0; }

/* Community links share the logo row on phones; wallet controls get a full
   second row so a connected address cannot push the profile off screen. */
@media (max-width: 639px) {
  .ha-top { flex-wrap: wrap; height: auto; min-height: 60px; gap: 8px; padding: 8px 12px; }
  .ha-top-right { flex: 1 0 100%; width: 100%; min-width: 0; gap: 6px; justify-content: flex-end; }
  /* Give the actual balance room before shortening the wallet address. The
     old 130px cap clipped even 1,200 HP while unused row space remained. */
  .ha-top-right .ha-pill-balance { flex: 1 1 auto; min-width: 0; max-width: none; }
  .ha-top-right .ha-currency { flex: 1 0 152px; max-width: none; }
  .ha-top-right .ha-currency .ha-pill-balance { width: 100%; }
  .ha-top-right .ha-pill-wallet { flex: 0 1 150px; min-width: 0; max-width: 150px; }
  .ha-top-right #ha-wallet-label { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .ha-top-right .ha-pill-profile { flex: 0 0 42px; }
}
#ha-wallet-label { font-variant-numeric: tabular-nums; }

/* where a number came from, printed next to it */
.ha-src {
  display: inline-block; margin-left: 6px; padding: 1px 5px; border-radius: 3px;
  font-size: 8.5px; font-weight: 800; letter-spacing: .08em;
  color: var(--txt-mute); background: rgba(255, 255, 255, .05);
}
.ha-src.is-chain { color: var(--green-soft); background: rgba(204, 255, 0, .12); }

/* --- deposit routes --- */
.ha-dep-wallet {
  display: flex; align-items: center; gap: var(--s3); flex-wrap: wrap;
  padding: var(--s3) var(--s4); border-radius: var(--r-sm); margin-bottom: var(--s4);
  background: var(--face); box-shadow: var(--slab);
}
.ha-dep-wallet .l { font-size: var(--fs-2); font-weight: 700; letter-spacing: .12em; text-transform: uppercase; color: var(--txt-mute); }
.ha-dep-wallet b { font-family: var(--num); font-size: var(--fs-5); color: var(--txt); }
.ha-dep-wallet a { color: var(--gold); font-size: var(--fs-3); text-decoration: none; }
.ha-dep-wallet a:hover { text-decoration: underline; }
.ha-dep-wallet.is-on { box-shadow: var(--slab), inset 3px 0 0 var(--green); }

.ha-dep-list { display: grid; gap: 10px; }
.ha-dep-row {
  display: grid; gap: 4px; padding: var(--s4); border-radius: var(--r-sm);
  text-decoration: none; color: inherit;
  background: var(--face), var(--brush); box-shadow: var(--slab);
  transition: box-shadow .18s, transform .18s var(--ease);
}
.ha-dep-row:hover { transform: translateY(-2px); box-shadow: var(--slab-hi); }
.ha-dep-row:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }
.ha-dep-name { font-size: var(--fs-5); font-weight: 700; color: var(--txt); display: flex; align-items: center; gap: var(--s2); flex-wrap: wrap; }
.ha-dep-kind {
  font-size: var(--fs-1); font-weight: 700; letter-spacing: .1em; text-transform: uppercase;
  color: var(--txt-mute); padding: 2px 6px; border-radius: 3px; background: rgba(255, 255, 255, .05);
}
.ha-dep-meta { display: flex; gap: var(--s3); flex-wrap: wrap; font-size: var(--fs-3); color: var(--txt-mute); }
.ha-dep-meta b { font-family: var(--num); font-variant-numeric: tabular-nums; color: var(--gold); font-weight: 700; }
.ha-dep-note { font-size: var(--fs-3); line-height: 1.55; color: var(--txt-dim); }

@media (min-width: 700px) {
  .ha-dep-row { grid-template-columns: minmax(0, 1fr) auto; align-items: baseline; }
  .ha-dep-note { grid-column: 1 / -1; }
}
@media (max-width: 500px) {
  .ha-chainbadge { height: 22px; padding: 0 7px; font-size: 8.5px; }
  /* An unlabelled wallet glyph is a guess. The one button a signed-out
     visitor needs says what it does. */
  .ha-pill-wallet { padding: 0 15px; }
  .ha-pill-wallet { padding: 0 10px; }
}

@media (max-width: 430px) {
  #ha-balance { padding: 0 9px; gap: 6px; }
  .ha-pill-profile { padding: 0 6px; }
}



/* ------------------------------ cashier --------------------------------
   Deposit and withdraw tokens. Deliberately plainer than the rest of the
   arena: money moving is not the place for flourish. */
.ha-pill-kind {
  font-size: 9px; font-weight: 800; letter-spacing: .1em;
  color: var(--txt-mute); padding: 2px 5px; border-radius: 4px;
  background: rgba(255, 255, 255, .06);
}
.ha-pill-balance.is-real .ha-pill-kind { color: #7fd4a0; background: rgba(64, 190, 122, .14); }
.ha-pill-balance.is-stale #ha-balance-amt { color: var(--txt-mute); }

.ha-cash-grid {
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px; margin-bottom: var(--s5);
}
.ha-cash-stat {
  padding: var(--s4); border-radius: var(--r-sm);
  background: var(--face); box-shadow: var(--slab);
}
.ha-cash-stat span {
  display: block; margin-bottom: 6px;
  font-size: var(--fs-2); font-weight: 700; letter-spacing: .1em; text-transform: uppercase; color: var(--txt-mute);
}
.ha-cash-stat b { font-family: var(--num); font-size: var(--fs-7); color: var(--txt); }

.ha-cash-row { display: flex; flex-wrap: wrap; align-items: center; gap: 9px; }
.ha-cash-row label {
  font-size: var(--fs-2); font-weight: 700; letter-spacing: .14em; text-transform: uppercase; color: var(--txt-mute);
}
.ha-cash-input {
  flex: 1 1 130px; min-width: 0; height: 46px; padding: 0 var(--s3);
  border: 0; border-radius: var(--r-sm); background: var(--well); color: var(--txt);
  font-family: var(--num); font-weight: 600; font-size: var(--fs-6);
  box-shadow: var(--sink), 0 0 0 1px rgba(255, 255, 255, .05);
}
.ha-cash-input:focus { outline: none; box-shadow: var(--sink), 0 0 0 2px var(--green); }
.ha-cash-row .ha-btn { height: 46px; flex: 0 0 auto; }
.ha-cash-row .ha-btn[disabled] { opacity: .6; cursor: default; }
.ha-cash-actions { margin-top: var(--s4); }

@media (max-width: 640px) {
  .ha-cash-grid { grid-template-columns: 1fr; }
  .ha-cash-row { display: grid; grid-template-columns: 1fr 1fr; }
  .ha-cash-row label { grid-column: 1 / -1; }
  .ha-cash-input { grid-column: 1 / -1; }
  .ha-cash-row .ha-btn { width: 100%; }
  .ha-cash-row .ha-btn:first-of-type { grid-column: 1 / -1; }
}

/* The escape hatch when a payout did not go through. Deliberately loud: the
   whole fairness claim rests on the player being able to do this themselves. */
.ha-settle-bar {
  position: fixed; left: 50%; bottom: 18px; transform: translateX(-50%); z-index: 9000;
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap; justify-content: center;
  max-width: min(560px, calc(100vw - 24px)); padding: 12px 14px;
  border-radius: var(--r-sm); background: var(--panel-2);
  box-shadow: 0 10px 34px rgba(0, 0, 0, .55), 0 0 0 1px var(--line);
  font-size: var(--fs-4); color: var(--txt);
}
.ha-settle-bar .ha-btn { height: 38px; }


/* ===== v2 pass: measured defects, in the order they were found ============
   Every rule here answers a screenshot or a number, not a taste. ============ */

/* The result card now carries the headline, so the stage's own status line
   (which the card half-covered: "YOU WON 19.40" peeking out above it) steps
   out of the way. */
.ca-battle.ca-done .ca-mid { visibility: hidden; }

/* The header said DEMO twice on a phone: once in the chain badge, once in the
   balance pill. The pill is the one next to the number, so it stays. */
@media (max-width: 819px) {
}

/* The hero took the entire first screen on desktop; the duels, which are the
   product, started below the fold. Half the height, same plate. */
@media (min-width: 820px) {
  .ha-hero { min-height: 220px; padding: var(--s6) var(--s7) var(--s5); margin-bottom: var(--s6); }
  .ha-hero-title { font-size: clamp(40px, 4.6vw, 60px); margin-bottom: var(--s3); }
  .ha-hero-sub { margin-bottom: var(--s4); }
}

/* An empty chat is a big black rectangle. Say so, briefly, and let the arena
   feed keep it alive between human messages. */
.ha-chat-empty {
  margin: auto; padding: var(--s6) var(--s5); text-align: center;
  color: var(--txt-mute); font-size: var(--fs-4); line-height: 1.55;
}
.ha-chat-empty b { display: block; color: var(--txt-dim); font-weight: 700; margin-bottom: 4px; }
.ha-msg.is-system { align-items: center; }
.ha-msg.is-system .ha-msg-text { color: var(--txt-mute); font-size: var(--fs-3); }
.ha-msg.is-system .ha-msg-text b { color: var(--txt-dim); font-weight: 700; }
.ha-msg.is-system > img { display: none; }
.ha-msg.is-system .ha-msg-top { display: none; }


/* compact duel cards on a phone. Measured at 375 wide: one joinable card was
   330px tall, three of them filled a thousand pixels, and the Join target was
   an empty 54px circle in a 160px column. The card becomes a row: face and
   name on the left, weapon in the middle, a real Join button on the right,
   the stake plinth under it. Live and result cards use the same row. */
@media (max-width: 819px) {
  .ha-card { border-radius: var(--r-sm); }
  .ha-card-body { align-items: center; min-height: 0; }
  .ha-half {
    flex-direction: row; align-items: center; justify-content: flex-start;
    gap: 10px; padding: 12px 10px 12px 14px; text-align: left;
  }
  .ha-half + .ha-half::before { top: 14px; bottom: 14px; }
  .ha-ava img { width: 40px; height: 40px; }
  .ha-ava .ha-rank { width: 16px; height: 16px; right: -3px; bottom: -2px; }
  .ha-ava .ha-rank img { width: 9px; height: 9px; }
  .ha-name { justify-content: flex-start; text-align: left; row-gap: 4px; font-size: var(--fs-4); }
  .ha-name > span { max-width: 100%; }
  /* the join side is a button now, not a circle with a caption */
  .ha-half-join { flex: 0 0 auto; padding: 10px 14px 10px 10px; gap: 8px; flex-direction: row-reverse; }
  .ha-half-join::after { display: none; }
  .ha-join-cta { flex-direction: row-reverse; gap: 8px; }
  .ha-join-plus {
    width: 40px; height: 40px; color: #032109;
    background: linear-gradient(180deg, #ddff4d, #ccff00);
    box-shadow: 0 0 0 1px #7a9c00, inset 0 1px 0 rgba(255, 255, 255, .6), inset 0 -1px 0 rgba(0, 0, 0, .3), 0 6px 14px -6px rgba(0, 0, 0, .9);
  }
  .ha-join-plus svg { width: 17px; height: 17px; }
  .ha-join-label { color: var(--txt-dim); font-size: var(--fs-3); }
  .ha-vs { width: 34px; height: 34px; }
  .ha-stake { padding: 8px 14px; gap: 8px; }
  .ha-stake span { font-size: var(--fs-6); }
  .ha-stake .ha-coin { width: 14px; height: 14px; }
  .ha-lifebar { width: 100%; }
}

/* locker cards lined up. "Equipped" was a bare line of text where its
   neighbours had a 40px button, so the equipped card was a different height
   from the one next to it. Every card ends in the same 40px slot. */
.ha-item { display: flex; flex-direction: column; }
.ha-item .ha-btn, .ha-item-lock { margin-top: auto; }
.ha-item-lock {
  min-height: 40px; display: flex; align-items: center; justify-content: center; gap: 6px;
  border-radius: var(--r-xs); font-size: var(--fs-2); font-weight: 700; letter-spacing: .1em; text-transform: uppercase;
  color: var(--txt-mute); box-shadow: inset 0 0 0 1px var(--line);
}
.ha-item-lock.is-on { color: var(--green-soft); box-shadow: inset 0 0 0 1px rgba(204, 255, 0, .45); background: var(--green-dim); }


/* phone card: badge and target size. Measured after the compact pass: the
   HIGH ROLLER chip ran under the weapon medallion, and the join button came
   out at 39px. The chip now sits under the name, and the button is 44. */
@media (max-width: 819px) {
  .ha-half:not(.ha-half-join) .ha-name { flex-direction: column; align-items: flex-start; gap: 3px; }
  .ha-half:not(.ha-half-join) { flex: 1 1 0; min-width: 0; padding-right: 44px; }
  .ha-join-plus { width: 44px; height: 44px; }
  .ha-half-join { padding: 8px 12px 8px 8px; }
}


/* two-fighter cards on a phone (live and results). In the row layout the
   weapon medallion, still centred at the top, sat on the second fighter's
   face; the LIVE chip sat on the second name; the WINNER tag ran off the
   right edge. The medallion becomes a small coin on the divider and LIVE
   moves to the stake plinth. Result portraits use their own layout below. */
@media (max-width: 819px) {
  .ha-card:where(:not(.ha-result-card)):has(.ha-half + .ha-half) .ha-half + .ha-half { padding-left: 32px; }
  .ha-card:where(:not(.ha-result-card)):has(.ha-half + .ha-half) .ha-vs {
    width: 30px; height: 30px; top: 50%; transform: translate(-50%, -50%);
  }
  .ha-card:where(:not(.ha-result-card)):has(.ha-half + .ha-half) .ha-vs svg,
  .ha-card:where(:not(.ha-result-card)):has(.ha-half + .ha-half) .ha-vs > div,
  .ha-card:where(:not(.ha-result-card)):has(.ha-half + .ha-half) .ha-wpn-art { width: 18px; height: 18px; }
  .ha-card-live::after { top: auto; bottom: 9px; right: 10px; }
  .ha-lost .ha-name { color: #9a8f90; }
}


/* two-fighter cards, second pass. Measured: the avatar shrank to a sliver
   because the row let it flex; the medallion at top:50% of the CARD landed on
   the stake amount; the live card's name and life bar fought for one line. */
@media (max-width: 819px) {
  .ha-ava { flex-shrink: 0; }
  .ha-name { min-width: 0; }
  .ha-card:where(:not(.ha-result-card)):has(.ha-half + .ha-half) .ha-vs { top: 30px; }
  .ha-card-live .ha-half {
    display: grid; grid-template-columns: 40px minmax(0, 1fr); grid-template-areas: 'ava name' 'ava bar';
    column-gap: 10px; row-gap: 5px; align-items: center;
  }
  .ha-card-live .ha-half .ha-ava { grid-area: ava; }
  .ha-card-live .ha-half .ha-name { grid-area: name; }
  .ha-card-live .ha-half .ha-lifebar { grid-area: bar; width: 100%; max-width: 110px; }
}

/* two-fighter cards, third pass: the coin still kissed the winner's ring. */
@media (max-width: 819px) {
  .ha-card:where(:not(.ha-result-card)):has(.ha-half + .ha-half) .ha-half + .ha-half { padding-left: 40px; }
  /* Wallet prefixes need the full half-card width, below the portrait. */
  .ha-card.ha-card-live:has(.ha-half + .ha-half) .ha-half {
    grid-template-columns: minmax(0, 1fr); grid-template-areas: 'ava' 'name' 'bar';
    justify-items: center; padding: 12px 8px; row-gap: 8px;
  }
  .ha-card-live .ha-half:not(.ha-half-join) .ha-name {
    flex-direction: row; align-items: center; justify-content: center; text-align: center;
  }
}

/* the new-duels pill is a lobby control. It was floating over the Token page,
   on top of the bridging notes, counting duels the reader could not see. */
body:has(#ha-lobby[hidden]) .ha-newpill { display: none; }

/* locker tabs on a phone: five chips wrapped to a second row ("Chat badge" and
   "Face" orphaned underneath). One row that scrolls sideways, like every
   tab strip a phone user already knows. */
@media (max-width: 819px) {
  .ha-lk-tabs { flex-wrap: nowrap; overflow-x: auto; -webkit-overflow-scrolling: touch; scrollbar-width: none; padding-bottom: 2px; margin-inline: -4px; padding-inline: 4px; }
  .ha-lk-tabs::-webkit-scrollbar { display: none; }
  .ha-lk-tab { flex: 0 0 auto; white-space: nowrap; }
}

/* desktop hero title on one line. Two stacked words at 60px were a poster,
   and the poster pushed the product 373px down the page. One line, and the
   duels sit higher. The phone keeps the stack: there is no width for one. */
@media (min-width: 820px) {
  .ha-hero-title { font-size: clamp(36px, 3.6vw, 52px); letter-spacing: .06em; margin-bottom: var(--s3); }
  .ha-hero-title em { display: inline; margin-left: .22em; }
}


/* ===== v2 pass, second batch: the mobile audit's measurements ============ */

/* Touch targets. Measured 32 to 42px on pills, close buttons, emotes, tab
   chips and quick amounts; the fairness <summary> was 18px tall. 44 is the
   floor on a phone, and the header pills are the most tapped thing on it. */
@media (max-width: 819px) {
  .ha-pill, .ha-top-logo { min-height: 44px; }
  .ha-modal-x, .ca-x, #ha-chat-close, .ca-emote { width: 44px; height: 44px; }
  .ha-lk-tab, .ha-quick, .ha-replay-btn, .ha-item .ha-btn, .ha-item-lock, .ha-face-sw { min-height: 44px; }
  .ha-chat-foot input, #ha-chat-input, .ca-chat-input { min-height: 44px; }
  details.ha-details > summary, .ca-fair-wrap > summary { padding: 12px 0; min-height: 44px; display: flex; align-items: center; }
}

/* Type. iOS zooms into any field under 16px, so every field is 16px on a
   phone. The 8.5px source tag and 9px chip were below anything
   a phone renders cleanly; 11px is the floor. */
@media (max-width: 819px) {
  input, select, textarea, .ha-select, #ha-chat-input, .ca-chat-input, #ha-seed, #ha-fseed { font-size: 16px !important; }
  .ha-pill-kind { font-size: 10px; }
  .ha-src { font-size: 11px; }
  .ha-win-tag { font-size: 10.5px; }
  .ha-msg-text, .ha-hero-sub, .ha-name { font-size: 14px; }
}

/* Contrast. Loser halves ran at opacity .48 (names at 2.25:1); the result
   card's loser name measured 1.96:1. Still clearly the loser, now legible. */
.ha-lost { opacity: .68; }
.ha-lost .ha-name { color: #c9a9ab; }
.ca-state .pc.lost .nm { opacity: 1; color: #b7a3a5; }
.ha-pill-kind { color: var(--txt-dim); }

/* The chat drawer sat above the tab bar, so the Chat tab could not close
   what it opened; the only way out was a 40px X at the far top corner. The
   drawer now stops at the bar and the bar stays on top. */
@media (max-width: 819px) {
  .ha-bnav { z-index: 120; }
  .ha-chat { bottom: var(--bnav-h); }
  #ha-chat-log { overscroll-behavior: contain; }
}

/* Landscape phone: the duel panel clipped its own Rematch/Close buttons and
   the chat input under a fixed height with overflow hidden. Let it scroll. */
@media (max-height: 500px) and (orientation: landscape) {
  .ha-duel { overflow-y: auto; -webkit-overflow-scrolling: touch; }
  .ca-3d .ca-stage { flex: 0 0 auto; height: 60vh; min-height: 0; }
}

/* Sticky hover on touch: tapping a card left it lifted. Hover is for mice. */
@media (hover: none) {
  .ha-card:hover, .ha-item:hover, .ha-pill:hover, .ha-wpn-tile:hover, .ha-quick:hover, .ha-ava-pick:hover, .ca-emote:hover { transform: none; }
  .ha-modal-x:hover, .ca-x:hover { transform: none; }
}

/* 320px: retain both community links on the logo/navigation row and give
   the featured badge copy a full measure above its compact claim card. */
@media (max-width: 360px) {
  .ha-top { gap: 4px; }
  .ha-top-logo img { width: 64px; height: 36px; margin-right: 0; object-fit: contain; }
  .ha-topnav { gap: 4px; }
  .ha-topnav-item[data-nav="locker"] span { display: none; }
  .ha-topnav-item[data-nav="locker"] { justify-content: center; }
}


/* ===== v2 pass, third batch: the desktop audit's measurements =========== */

/* Inline validation and the quick-amount selected state. */
.ha-field-err {
  margin: 8px 0 2px; font-size: var(--fs-3); font-weight: 600; color: var(--red-hot);
}
.ha-input:has(input[aria-invalid="true"]) { box-shadow: var(--sink), 0 0 0 2px var(--red); }
.ha-quick.is-on { color: var(--green-soft); box-shadow: 0 0 0 1px rgba(204, 255, 0, .6), var(--slab); }
.ha-summary-note { margin-top: 8px; font-size: var(--fs-3); color: var(--txt-mute); }
.ha-summary-note b { font-family: var(--num); color: var(--txt-dim); }
.ha-btn[disabled] { opacity: .45; cursor: not-allowed; filter: saturate(.4); }

/* The duel panel clipped its own Rematch and Close at 768px tall (buttons
   ending at 775 in a 768 box) and cut the Commission row of the result card.
   The panel scrolls when it must; nothing in it is ever unreachable. */
.ha-duel { overflow-y: auto; overflow-x: hidden; }

/* The status line ("Seeding... awaiting block", "Fight!") was drawn across
   the top of the stage, exactly where the canvas paints both HP plates. It
   sits on the floor now, under the fighters, where nothing else is. */
.ca-3d .ca-status { top: auto; bottom: var(--s4); }
@media (max-width: 819px) { .ca-3d .ca-status { top: auto; bottom: var(--s3); } }

/* Recent duel seats stay in their original order at every viewport width.
   Equal columns leave room for Winner above the portrait, including phones. */
.ha-result-card .ha-card-body { align-items: stretch; }
.ha-result-card .ha-card-body .ha-half {
  flex-direction: column; align-items: center; justify-content: flex-start;
  padding: 18px 12px; gap: 12px; text-align: center;
}
.ha-result-card .ha-half .ha-name { flex-direction: row; flex-wrap: nowrap; align-items: center; justify-content: center; text-align: center; font-size: 12px; line-height: 20px; letter-spacing: 0; }
.ha-result-card .ha-half-id { width: 100%; min-height: 28px; justify-content: center; }
.ha-result-card .ha-stake { min-height: 58px; padding: 12px; gap: 7px; }
.ha-result-card .ha-stake > span { font-size: 24px; }
.ha-result-card .ha-replay-btn { min-height: 44px; }
.ha-result-meta {
  display: flex; flex-wrap: wrap; justify-content: center; align-items: center; gap: 4px 10px;
  min-height: 52px; padding: 8px 12px; border-top: 1px solid var(--line); background: #0002;
  color: var(--txt-mute); font-size: 10px; line-height: 1.5; text-align: center;
}
.ha-result-meta > span { white-space: nowrap; }
.ha-result-meta > span:first-child { color: var(--txt-dim); }
.ha-result-meta b { color: var(--gold); font-weight: 600; }
.ha-result-foot {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  min-height: 45px; padding: 0 12px; border-top: 1px solid var(--line); background: #0003;
  color: var(--txt-mute); font: 10px/1.5 var(--num);
}
.ha-result-foot > span { min-width: 0; }
.ha-result-foot .ha-link { flex-shrink: 0; min-height: 44px; color: var(--gold); font-size: 10px; }
.ha-result-foot .ha-done-tx { width: auto; height: auto; background: none; box-shadow: none; letter-spacing: 0; text-transform: none; }
.ha-card.ha-result-card .ha-vs { top: 49px; width: 44px; height: 44px; transform: translateX(-50%); }
.ha-result-card .ha-card-body .ha-half + .ha-half::before { top: 88px; }
@media (max-width: 819px) {
  .ha-card.ha-result-card .ha-vs { top: 59px; }
  .ha-result-card .ha-half .ha-ava > img { width: 52px; height: 52px; }
}


/* the notch. viewport-fit=cover was added so the bottom bar could clear the
   home indicator, and it makes the TOP inset real as well: without this the
   balance pill, the wallet button and the duel's close button sit underneath
   the status bar on a notched phone. The bottom bar already handled its end. */
.ha-top { padding-top: env(safe-area-inset-top, 0px); }
@media (max-width: 639px) {
  .ha-top { padding-top: calc(8px + env(safe-area-inset-top, 0px)); }
}
.ha-duel { margin-top: env(safe-area-inset-top, 0px); }
.ca-battle { padding-top: env(safe-area-inset-top, 0px); }
@media (max-width: 819px) {
  .ha-chat { padding-top: env(safe-area-inset-top, 0px); }
  .ha-chat-foot { padding-bottom: max(var(--s3), env(safe-area-inset-bottom, 0px)); }
  .ca-foot { padding-bottom: max(var(--s3), env(safe-area-inset-bottom, 0px)); }
}

/* the money bar now names its own quantity */
.ha-stake-k {
  font-style: normal; font-size: var(--fs-2); font-weight: 700; letter-spacing: .12em;
  text-transform: uppercase; color: var(--txt-mute); flex-shrink: 0;
}


/* the create modal states the price next to the prize. It showed only what a
   winner takes, with no unit, in a product that runs two currencies. */
.ha-summary-u { font-size: var(--fs-3); font-weight: 700; letter-spacing: .1em; color: var(--txt-mute); margin-left: 6px; }
.ha-summary-risk { margin-top: 8px; }
.ha-summary-risk b { color: var(--red-hot); }

/* ============================================================================
   ACCOUNTS, DEPOSIT ADDRESSES, WITHDRAWALS AND THE HOLDER CLAIM
   The custodial side. A deposit address is the single most dangerous string on
   this site: paste it wrong and the money is gone with nobody to appeal to. So
   it gets a monospace slab, its own chain name beside it, and a copy button
   that is easier to hit than the text is to mis-select.
   ========================================================================== */

.ha-pill-account.is-on { color: var(--green-soft); box-shadow: inset 0 1px 0 rgba(255,255,255,.08), 0 0 0 1px rgba(204, 255, 0, .4), 0 2px 6px rgba(0,0,0,.5); }
.ha-pill-account svg { flex-shrink: 0; }

/* ---- the sign in / create account modal ---- */
.ha-acct-tabs { display: flex; gap: 4px; margin: 0 0 var(--s5); padding: 4px; border-radius: var(--r-sm); background: rgba(0,0,0,.28); }
.ha-acct-tab {
  flex: 1 1 0; padding: 9px 10px; border: 0; border-radius: calc(var(--r-sm) - 3px); cursor: pointer;
  font: inherit; font-size: var(--fs-3); font-weight: 700; letter-spacing: .04em;
  color: var(--txt-mute); background: transparent; transition: color .18s, background .18s;
}
.ha-acct-tab:hover { color: var(--txt); }
.ha-acct-tab.is-active { color: #0d1216; background: linear-gradient(180deg, var(--gold-hi), var(--gold-lo)); }
.ha-acct-tab:focus-visible { outline: 2px solid var(--gold-hi); outline-offset: 2px; }

/* One frame for the whole account page.

   The shell was 760px and grew to 1120px whenever the locker was the visible
   pane, so the title, the tab strip and the column under them jumped sideways
   every time you changed tab. A first attempt capped only the strip, and a
   later `margin: 0 0 var(--s5)` shorthand in this file reset its auto margins,
   which left it pinned to the wide shell's left edge instead of centred: the
   same jump, now with the buttons off-centre as well.

   The shell is one width on every tab. The page chrome and the two column
   panes share one 760px measure inside it, so they land on the same pixel
   whichever tab is open, and only the gear grid uses the full width.
   Declared here, after that shorthand, so nothing can reset it again. */
.ha-acct { max-width: 1120px; }
.ha-acct-h,
.ha-acct-tabs,
.ha-acct-pane[data-pane="settings"],
.ha-acct-pane[data-pane="record"] { max-width: 760px; margin-inline: auto; }
.ha-acct-pane[data-pane="locker"] { max-width: none; }

.ha-acct-form { display: flex; flex-direction: column; gap: 6px; }
.ha-acct-form label {
  font-size: var(--fs-2); font-weight: 700; letter-spacing: .1em; text-transform: uppercase; color: var(--txt-mute);
}
.ha-acct-form input {
  width: 100%; padding: 12px var(--s4); border: 0; border-radius: var(--r-sm);
  font: inherit; font-size: var(--fs-5); color: var(--txt);
  background: rgba(0,0,0,.32); box-shadow: inset 0 0 0 1px var(--line);
  margin-bottom: var(--s4);
}
.ha-acct-form input:focus { outline: none; box-shadow: inset 0 0 0 1px var(--gold-hi); }
.ha-acct-form input::placeholder { color: var(--txt-mute); }
.ha-acct-name-row { display: contents; }
.ha-acct-name-row[hidden] { display: none; }
.ha-acct-err {
  margin: 0 0 var(--s4); padding: 10px var(--s4); border-radius: var(--r-sm);
  font-size: var(--fs-3); line-height: 1.4; color: #ffd9d4;
  background: rgba(255, 106, 92, .12); box-shadow: inset 0 0 0 1px rgba(255, 106, 92, .35);
}
.ha-acct-note { margin-top: var(--s5); }
.ha-acct-email { font-family: var(--num); font-size: var(--fs-4) !important; word-break: break-all; }

/* ---- deposit addresses ---- */
.ha-sub {
  margin: var(--s6) 0 var(--s4);
  font-family: var(--display); font-weight: 700; font-size: var(--fs-4);
  letter-spacing: .12em; text-transform: uppercase; color: var(--txt-mute);
}
.ha-addr-list { display: grid; gap: 10px; }
.ha-addr { padding: var(--s4); border-radius: var(--r-sm); background: var(--face); box-shadow: var(--slab); }
.ha-addr-head { display: flex; align-items: baseline; gap: var(--s3); margin-bottom: 8px; flex-wrap: wrap; }
.ha-addr-head b { font-size: var(--fs-5); color: var(--txt); }
.ha-addr-tok {
  padding: 2px 6px; border-radius: 3px;
  font-size: var(--fs-2); font-weight: 700; letter-spacing: .08em; text-transform: uppercase;
  color: var(--gold-hi); background: rgba(232, 192, 122, .1); box-shadow: inset 0 0 0 1px rgba(232, 192, 122, .28);
}
.ha-addr-row { display: flex; align-items: center; gap: 8px; }
.ha-addr-code {
  flex: 1 1 auto; min-width: 0; padding: 9px 10px; border-radius: 6px;
  font-family: var(--num); font-size: var(--fs-3); line-height: 1.4; color: var(--txt);
  background: rgba(0,0,0,.34); box-shadow: inset 0 0 0 1px var(--line);
  /* an address must never be truncated: a player copying by hand from an
     ellipsis sends money to nowhere */
  word-break: break-all; overflow-wrap: anywhere;
}
.ha-addr-copy { flex-shrink: 0; }
.ha-addr-note { margin-top: 8px; font-size: var(--fs-2); line-height: 1.45; color: var(--txt-mute); }

/* .ha-btn fixes height at 42px, so a "small" variant that only changes
   padding is not smaller at all. */
.ha-btn-sm { height: 34px; padding: 0 12px; font-size: var(--fs-2); letter-spacing: .08em; }

/* The section head is a wrapping flex row, so an action next to the heading
   stretched to the full width on a phone and read as a second heading rather
   than a button. */
.ha-sec-head > .ha-btn { flex: 0 0 auto; margin-left: auto; }
@media (max-width: 619px) {
  .ha-sec-head > .ha-btn { margin-left: 0; }
}

.ha-wd-to { flex: 2 1 260px; font-family: var(--num); font-size: var(--fs-3); }
.ha-wd-list { display: grid; gap: 6px; margin-top: var(--s4); }
.ha-wd-row {
  display: flex; align-items: center; gap: var(--s3); flex-wrap: wrap;
  padding: 9px var(--s4); border-radius: 6px; background: rgba(0,0,0,.22);
}
.ha-wd-row b { font-family: var(--num); font-size: var(--fs-4); color: var(--txt); }
.ha-wd-row code { font-family: var(--num); font-size: var(--fs-2); color: var(--txt-mute); margin-left: auto; }
.ha-wd-state {
  padding: 2px 7px; border-radius: 3px;
  font-size: var(--fs-2); font-weight: 700; letter-spacing: .08em; text-transform: uppercase;
}
.ha-wd-state.is-queued   { color: var(--gold-hi);  background: rgba(232, 192, 122, .12); }
.ha-wd-state.is-sending,
.ha-wd-state.is-sent     { color: #9fd0ff;         background: rgba(120, 180, 255, .12); }
.ha-wd-state.is-confirmed{ color: var(--green-soft); background: rgba(204, 255, 0, .12); }
.ha-wd-state.is-failed,
.ha-wd-state.is-stuck    { color: var(--red-hot);  background: rgba(255, 106, 92, .14); }

/* ---- the holders' claim ---- */
.ha-claim-total {
  display: flex; align-items: baseline; gap: var(--s3); margin-bottom: var(--s4);
  padding: var(--s4); border-radius: var(--r-sm); background: var(--face); box-shadow: var(--slab);
}
.ha-claim-total span { font-size: var(--fs-2); font-weight: 700; letter-spacing: .1em; text-transform: uppercase; color: var(--txt-mute); }
.ha-claim-total b { margin-left: auto; font-family: var(--num); font-size: var(--fs-7); color: var(--gold-hi); }
.ha-claim-list { display: grid; gap: 6px; }
.ha-claim-row {
  display: flex; align-items: center; gap: var(--s3); flex-wrap: wrap;
  padding: 10px var(--s4); border-radius: 6px; background: rgba(0,0,0,.22);
}
.ha-claim-row b { font-family: var(--num); font-size: var(--fs-5); color: var(--txt); }
.ha-claim-row span { font-size: var(--fs-2); color: var(--txt-mute); }
.ha-claim-go { margin-left: auto; }

@media (max-width: 619px) {
  /* the address slab is the one thing that must stay readable on a phone, so
     the copy button drops below it rather than squeezing it */
  .ha-addr-row { flex-wrap: wrap; }
  .ha-addr-copy { width: 100%; }
  .ha-claim-go, .ha-wd-row code { margin-left: 0; }
  .ha-wd-row code { flex-basis: 100%; }
}

/* The account pill added 98px to a header bar that had 20px of slack, and the
   wordmark absorbed all of it: the logo read "HOOD AREN" at 1280px, measured.
   The profile pill's name is the thing to drop, because when somebody is
   signed in the account pill next to it already shows the same name, and when
   they are not, the avatar still opens the same panel. The 819px rule below
   already did this on phones; this is the same call, one breakpoint earlier. */
@media (max-width: 1439px) {
  .ha-pill-profile span { display: none; }
  .ha-pill-profile { padding-right: var(--s3); }
}
/* Below this the account label goes too, and the icon carries it. Losing the
   wordmark would cost more than losing one word. */
@media (max-width: 1023px) {
  .ha-pill-account { padding-right: var(--s3); }
}

/* Says plainly that the fee figures below it are figures from the fee book
   states them in the token next to a pool that says it goes out at the next
   snapshot. */
.ha-tok-sim {
  margin-bottom: var(--s5); padding: 11px var(--s4); border-radius: var(--r-sm);
  font-size: var(--fs-3); line-height: 1.5; color: var(--gold-hi);
  background: rgba(232, 192, 122, .08); box-shadow: inset 0 0 0 1px rgba(232, 192, 122, .26);
}

/* An element with an explicit display beats the user agent's [hidden] rule, so
   el.hidden = true did nothing to a .ha-pill and the account button stayed on
   screen on a deployment that cannot take a deposit. This is the standard
   remedy and it applies to everything, not just that one button. */
[hidden] { display: none !important; }

/* the token symbol beside a stake amount on lobby cards */
.ha-stake-sym{flex-shrink:0;font-size:var(--fs-3);font-weight:700;letter-spacing:.04em;color:var(--txt-dim);font-style:normal}
.ha-btn-green .ha-stake-sym { color: inherit; }

/* The house money format: icon, amount, ticker, in that order and nowhere any
   other way. money() deliberately emits no wrapper and no element around the
   number, because the figures that were already right read exactly like that
   and a nested span changes what every caller's own styling sees. So the
   numerals are set where the figures live, not on a wrapper that is not there.
   The ticker takes its colour from its parent, so a net that is green or red
   stays green or red and only the ticker is muted. */
.ha-prof-tile b, .ha-prof-row b, .ha-hist-stake, .ha-hist-delta {
  font-family: var(--num); font-variant-numeric: tabular-nums; letter-spacing: -.01em; white-space: nowrap;
}
.ha-prof-tile .ha-stake-sym, .ha-prof-row .ha-stake-sym,
.ha-hist-stake .ha-stake-sym, .ha-hist-delta .ha-stake-sym {
  font-size: .75em; letter-spacing: 0; color: inherit; opacity: .75;
}
/* the seeding countdown on a live card */
.ha-seed-eta{padding:6px 14px 10px;font-family:var(--mono,ui-monospace,monospace);font-size:11px;letter-spacing:.04em;color:var(--gold,#e0b45c);text-align:center}

.ha-cash-opt{display:flex;gap:8px;align-items:flex-start;margin:10px 0 4px;font-size:12px;color:var(--txt-dim,#9aa3b2);line-height:1.5}
.ha-cash-opt input{margin-top:3px}
.ha-cash-read-status { margin: -6px 0 18px; color: var(--txt-dim, #9aa3b2); font-size: 13px; line-height: 1.5; }
.ha-cash-read-status[hidden], .ha-cash-read-status button[hidden] { display: none; }
.ha-cash-read-status p { margin: 0 0 10px; }

.ha-wmenu-grid{grid-template-columns:repeat(2,minmax(0,1fr));margin:14px 0}
.ha-wmenu-actions{display:grid;grid-template-columns:1fr 1fr;gap:8px}
.ha-wmenu-actions .ha-btn{height:auto;min-height:42px;padding:10px 12px;white-space:normal;line-height:1.25;text-align:center;letter-spacing:.06em}
.ha-wmenu-actions #ha-wmenu-cash{grid-column:1 / -1}
@media (max-width:420px){.ha-wmenu-grid{grid-template-columns:1fr}}
.ha-wmenu-addr{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.ha-wmenu-addr code{font-size:12px;word-break:break-all;color:var(--txt-dim,#9aa3b2)}

/* a wallet's record, under the profile */
.ha-hist{display:flex;flex-direction:column;gap:6px;max-height:340px;overflow:auto;padding-right:4px}
.ha-hist-row{display:grid;grid-template-columns:auto 1fr auto auto auto;gap:10px;align-items:center;padding:8px 12px;border-radius:10px;background:rgba(255,255,255,.03);font-size:12px}
.ha-hist-when{color:var(--txt-dim,#9aa3b2);font-family:var(--mono,ui-monospace,monospace);font-size:11px}
.ha-hist-stake{color:var(--txt-dim,#9aa3b2)}
.ha-hist-delta{font-family:var(--num,inherit)}
.ha-hist-row.is-win .ha-hist-delta{color:var(--green-soft,#35d955)}
.ha-hist-row.is-loss .ha-hist-delta{color:#e05a4a}
.ha-hist-row.is-refund .ha-hist-delta{color:var(--txt-dim,#9aa3b2)}
.ha-hist-tx a{color:var(--gold,#e0b45c)}
.ha-lk-stat .v.is-neg{color:#e05a4a}
@media (max-width:640px){.ha-hist-row{grid-template-columns:1fr auto;row-gap:2px}.ha-hist-when,.ha-hist-tx{grid-column:1/-1}}

.ha-tok-actions{display:flex;gap:10px;flex-wrap:wrap;margin-top:18px}
.ha-cashier h3{margin:0 0 12px}

/* ------------------------------- the profile ------------------------------
   Four figures and a per-game split, and the same layout whoever it belongs
   to. One line per currency inside a figure, never a sum across them. */
.ha-modal.ha-player-dialog { position: fixed; inset: 0; margin: auto; height: fit-content; width: calc(100% - 32px); overscroll-behavior: contain; }
.ha-prof-results { display: grid; grid-template-columns: 1.2fr 1fr 1fr; margin: 0; gap: 12px; }
.ha-prof-results > div { min-width: 0; }
.ha-prof-results > div + div { border-left: 1px solid var(--line); padding-left: 16px; }
.ha-prof-results dt { font-size: 11px; color: var(--txt-mute); }
.ha-prof-results dd { margin: 2px 0 0; color: var(--txt); font: 700 24px/1.3 var(--num); font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }
.ha-prof-results .ha-prof-winrate { color: var(--green); }
.ha-prof-results-note { margin: 8px 0 16px; color: var(--txt-mute); font-size: 11px; }
.ha-prof-breakdown > summary { display: flex; align-items: center; justify-content: space-between; min-height: 44px; gap: 12px; color: var(--txt-dim); font-size: 12px; font-weight: 600; cursor: pointer; list-style: none; }
.ha-prof-breakdown > summary::-webkit-details-marker { display: none; }
.ha-prof-breakdown > summary::after { content: ''; width: 7px; height: 7px; margin-right: 4px; border-right: 1.5px solid currentColor; border-bottom: 1.5px solid currentColor; transform: rotate(45deg); }
.ha-prof-breakdown[open] > summary::after { transform: rotate(225deg); }
.ha-prof-breakdown > summary:hover { color: var(--txt); }
.ha-prof-breakdown > summary:focus-visible { outline: 2px solid var(--green); outline-offset: 2px; border-radius: 4px; }
.ha-prof-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; margin: 0 0 14px; }
.ha-prof-tile {
  min-width: 0; padding: 14px 16px; border-radius: var(--r-sm);
  background: rgba(0, 0, 0, .28); box-shadow: inset 0 0 0 1px var(--line-soft);
}
.ha-prof-tile > span {
  display: block; margin-bottom: 7px; font-size: var(--fs-2);
  letter-spacing: .08em; text-transform: uppercase; color: var(--txt-mute);
}
.ha-prof-tile > div { display: flex; flex-direction: column; gap: 3px; }
.ha-prof-tile b { font-size: var(--fs-6); font-weight: 700; color: var(--txt); }
.ha-prof-nil { color: var(--txt-mute); font-weight: 500; }
.ha-prof-table {
  border-radius: var(--r-sm); overflow: hidden;
  background: rgba(0, 0, 0, .28); box-shadow: inset 0 0 0 1px var(--line-soft);
}
.ha-prof-row {
  display: grid; grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr) minmax(0, 1fr);
  gap: 10px; align-items: center; padding: 11px 16px;
}
.ha-prof-row + .ha-prof-row { box-shadow: inset 0 1px 0 var(--line-soft); }
.ha-prof-row.is-head {
  font-size: var(--fs-2); letter-spacing: .08em; text-transform: uppercase; color: var(--txt-mute);
}
.ha-prof-row > span:first-child { font-weight: 600; color: var(--txt-dim); min-width: 0; }
.ha-prof-row.is-head > span:first-child { font-weight: inherit; color: inherit; }
.ha-prof-row > span + span { display: flex; flex-direction: column; gap: 2px; align-items: flex-end; }
.ha-prof-row b { font-weight: 700; color: var(--txt); }
.ha-prof-tile .is-pos, .ha-prof-row .is-pos { color: var(--green-soft); }
.ha-prof-tile .is-neg, .ha-prof-row .is-neg { color: var(--red-hot); }
@media (max-width: 520px) {
  .ha-modal.ha-player-dialog { width: calc(100% - 24px); max-height: calc(100dvh - 32px); padding: 16px; border-radius: 18px; }
  .ha-player-dialog .ha-modal-x { width: 44px; height: 44px; margin-left: 8px; background: #1d252b; }
  .ha-player-heading { gap: 10px; padding-right: 0; margin-bottom: 10px; }
  .ha-player-portrait { width: 56px; height: 56px; flex-basis: 56px; border-radius: 14px; }
  .ha-player-heading h3 { font-size: 15px; line-height: 1.3; margin-bottom: 4px; }
  .ha-player-eyebrow { font-size: 9px; letter-spacing: .1em; margin-bottom: 3px; }
  .ha-player-badges .ha-badge { width: 24px; height: 24px; }
  .ha-player-address { flex-wrap: nowrap; gap: 8px; margin-bottom: 12px; }
  .ha-player-address code { flex: 1; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-size: 11px; }
  .ha-player-address a { flex-shrink: 0; min-height: 44px; padding: 0 10px; }
  .ha-prof-results { gap: 8px; }
  .ha-prof-results > div + div { padding-left: 12px; }
  .ha-prof-results dd { font-size: 22px; }
  .ha-prof-results-note { margin: 6px 0 12px; font-size: 10px; }
  .ha-prof-grid { gap: 8px; margin-bottom: 4px; }
  .ha-prof-tile { padding: 10px; }
  .ha-prof-tile > span { font-size: 9px; letter-spacing: .04em; margin-bottom: 5px; }
  .ha-prof-tile > div { gap: 3px; }
  .ha-prof-tile b { font-size: 14px; }
  .ha-prof-tile b, .ha-prof-row b { white-space: normal; overflow-wrap: anywhere; line-height: 1.45; }
  .ha-prof-row { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 6px 12px; padding: 10px; font-size: 12px; }
  .ha-prof-row > span { min-width: 0; }
  .ha-prof-row > span:first-child { grid-column: 1 / -1; }
  .ha-prof-row.is-head { font-size: 9px; letter-spacing: .04em; }
  .ha-prof-row.is-head > span:first-child { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }
}
@media (max-width: 360px) {
  .ha-prof-tile { padding: 8px; }
  .ha-prof-tile b { font-size: 13px; }
}
.ha-lb-empty { padding: var(--s5) var(--s4); font-size: var(--fs-4); color: var(--txt-dim); }
.ha-lb-note { margin-top: var(--s3); font-size: var(--fs-3); color: var(--txt-mute); }

/* ============================================================================
   MORE THAN ONE STAKE ASSET
   Stakes use the header's currency icons and a ticker after the amount. */
.ha-hist-stake { display: inline-flex; align-items: center; gap: 6px; }

/* the create modal's asset picker: the same segmented control as the
   cashier's Deposit/Withdraw switch */
.ha-asset-pick {
  display: flex; gap: 4px; padding: 4px;
  border-radius: var(--r-sm); background: rgba(0, 0, 0, .3);
  box-shadow: inset 0 0 0 1px var(--line-soft);
}
.ha-asset-opt {
  flex: 1; height: 38px; border-radius: var(--r-xs);
  font-family: var(--num); font-size: var(--fs-4); font-weight: 700; letter-spacing: .06em; color: var(--txt-mute);
  transition: color .2s, background .2s, box-shadow .2s;
}
.ha-asset-opt:hover { color: var(--txt-dim); background: rgba(255, 255, 255, .04); }
.ha-asset-opt.is-on {
  color: var(--txt); background: var(--raise);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .08), 0 2px 6px rgba(0, 0, 0, .5);
}
/* fees taken in the other assets, under the fork on the token page */
.ha-fees-more { font-size: var(--fs-3); color: var(--txt-mute); line-height: 1.6; }
.ha-fees-more b { font-family: var(--num); color: var(--txt-dim); }

/* Rug Pot */
.ha-pot-board{display:grid;grid-template-columns:minmax(0,1.6fr) minmax(260px,1fr);gap:14px}
.ha-pot-main,.ha-pot-side{background:var(--face);border-radius:var(--r-sm);box-shadow:var(--slab);padding:16px;position:relative}
.ha-pot-figs{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:10px;margin-bottom:14px}
.ha-pot-fig .l{display:block;font-size:var(--fs-2);font-weight:700;letter-spacing:.1em;text-transform:uppercase;color:var(--txt-mute);margin-bottom:4px}
.ha-pot-fig b{font-family:var(--num);font-size:var(--fs-7);color:var(--txt);font-variant-numeric:tabular-nums}
.ha-pot-fig .u{margin-left:6px;font-family:var(--num);font-size:12px;color:var(--txt-dim)}
.ha-pot-fig.is-clock b{color:var(--gold)}
.ha-pot-fig.is-clock b.is-hot{color:#ff6b5a}
.ha-pot-bar{display:flex;height:34px;border-radius:9px;overflow:hidden;background:rgba(255,255,255,.04);box-shadow:inset 0 0 0 1px rgba(255,255,255,.06)}
.ha-pot-slice{position:relative;min-width:2px;display:flex;align-items:center;justify-content:center;font-size:11px;font-weight:700;letter-spacing:.04em;color:#06070a;transition:width .5s var(--ease)}
.ha-pot-slice span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;padding:0 6px}
.ha-pot-slice.is-me{box-shadow:inset 0 0 0 2px #fff}
.ha-pot-slice.is-empty{flex:1;background:transparent;color:var(--txt-mute);font-weight:600;letter-spacing:.06em}
.ha-pot-entries{display:flex;flex-wrap:wrap;gap:6px;margin-top:10px}
.ha-pot-chip{display:inline-flex;align-items:center;gap:6px;padding:5px 9px;border-radius:999px;background:rgba(255,255,255,.04);font-size:12px;font-family:var(--num);color:var(--txt-dim)}
.ha-pot-chip i{width:9px;height:9px;border-radius:50%;display:inline-block}
.ha-pot-chip b{color:var(--txt);font-family:inherit;font-weight:600}
.ha-pot-chip small{color:var(--txt-mute)}
.ha-pot-chip.is-me{box-shadow:inset 0 0 0 1px rgba(224,180,92,.5)}
.ha-pot-status{margin:12px 0 0;font-size:13px;line-height:1.55;color:var(--txt-dim);max-width:62ch}
.ha-pot-reveal{position:absolute;inset:0;border-radius:var(--r-sm);background:rgba(6,7,10,.92);display:flex;flex-direction:column;justify-content:center;gap:14px;padding:22px;z-index:2}
.ha-pot-reveal-bar{position:relative;display:flex;height:44px;border-radius:10px;overflow:visible;background:rgba(255,255,255,.04)}
.ha-pot-reveal-bar .ha-pot-slice{border-radius:0;transition:none;opacity:.85}
.ha-pot-reveal-bar .ha-pot-slice:first-child{border-radius:10px 0 0 10px}
.ha-pot-reveal-bar .ha-pot-slice:nth-last-child(2){border-radius:0 10px 10px 0}
.ha-pot-reveal-bar .ha-pot-slice.is-winner{opacity:1;box-shadow:0 0 0 2px #fff,0 0 22px 2px rgba(224,180,92,.55);z-index:1}
.ha-pot-needle{position:absolute;top:-8px;bottom:-8px;left:0;width:3px;margin-left:-1px;background:#fff;box-shadow:0 0 10px 1px rgba(255,255,255,.8);z-index:2}
.ha-pot-needle::before{content:"";position:absolute;top:-7px;left:-5px;border:6px solid transparent;border-top:8px solid #fff}
.ha-pot-reveal-text{font-family:var(--display);font-size:20px;letter-spacing:.04em;color:var(--txt);text-align:center;min-height:1.4em}
.ha-pot-reveal-text b{color:var(--gold)}
.ha-pot-you{display:block;font-family:var(--body);font-size:13px;letter-spacing:0;color:var(--green-soft);margin-top:4px}
.ha-pot-enter label{display:block;font-size:var(--fs-2);font-weight:700;letter-spacing:.1em;text-transform:uppercase;color:var(--txt-mute);margin-bottom:8px}
.ha-pot-row{gap:8px}
.ha-pot-row .ha-input{flex:1;min-width:0}
.ha-pot-quick{display:flex;flex-wrap:wrap;gap:6px;margin-top:8px}
.ha-pot-q{height:30px;padding:0 10px;border-radius:8px;border:1px solid var(--line,#232735);background:transparent;color:var(--txt-dim);font-family:var(--num);font-size:12px;cursor:pointer}
.ha-pot-q:hover{color:var(--txt);border-color:var(--gold-deep,#b58a3c)}
.ha-pot-odds{margin:10px 0 0;font-size:12.5px;line-height:1.5;color:var(--txt-dim);min-height:2.6em}
.ha-pot-last{margin-top:16px;padding-top:14px;border-top:1px solid rgba(255,255,255,.06)}
.ha-pot-last-head{display:flex;align-items:center;justify-content:space-between;gap:8px;margin-bottom:6px}
.ha-pot-last-head .l{font-size:var(--fs-2);font-weight:700;letter-spacing:.1em;text-transform:uppercase;color:var(--txt-mute)}
.ha-pot-last-body{font-size:13px;line-height:1.55;color:var(--txt-dim)}
.ha-pot-last-body b{color:var(--txt)}
.ha-pot-last-body .ha-pot-win{color:var(--green-soft)}
.ha-pot-last-body small{display:block;margin-top:4px;font-family:var(--num);font-size:11px;color:var(--txt-mute)}
@media (max-width:820px){.ha-pot-board{grid-template-columns:1fr}}
@media (max-width:480px){.ha-pot-figs{grid-template-columns:1fr 1fr}.ha-pot-fig:nth-child(3){grid-column:1/-1}}
.ha-pot-main,.ha-pot-side{min-width:0}
@media (max-width:640px){
  .ha-pot-status{max-width:none}
  .ha-pot-row{flex-wrap:wrap}
  .ha-pot-row .ha-input{flex:1 1 100%}
  .ha-pot-row .ha-btn{flex:1 1 100%}
  .ha-pot-fig b{font-size:var(--fs-6)}
}

/* the pot stage */
.ha-pot-stage{display:grid;grid-template-columns:minmax(280px,440px) minmax(0,1fr);gap:18px;align-items:start}
.ha-pot-wheelwrap{position:relative}
#ha-pot-wheel{display:block;width:100%;aspect-ratio:1/1;height:auto}
.ha-pot-clockline{position:absolute;left:50%;transform:translateX(-50%);bottom:22%;display:flex;flex-direction:column;align-items:center;pointer-events:none}
.ha-pot-clockline span{font-size:10px;font-weight:700;letter-spacing:.14em;text-transform:uppercase;color:var(--txt-mute)}
.ha-pot-clockline b{font-family:var(--num);font-size:18px;color:var(--gold);font-variant-numeric:tabular-nums}
.ha-pot-clockline b.is-hot{color:#ff6b5a;animation:ha-pot-hot .5s ease-in-out infinite alternate}
@keyframes ha-pot-hot{from{transform:scale(1)}to{transform:scale(1.12)}}
.ha-pot-wheelwrap .ha-pot-entries{justify-content:center;margin-top:6px}
.ha-pot-panel{background:var(--face);border-radius:var(--r-sm);box-shadow:var(--slab);padding:16px;min-width:0}
.ha-pot-fig.is-share b{color:var(--green-soft)}
.ha-pot-enter{padding:14px;border-radius:10px;background:rgba(255,255,255,.03);border:1px solid rgba(232,192,122,.18)}
.ha-pot-row .ha-btn-lg{height:48px;padding:0 22px;white-space:nowrap}
.ha-pot-odds b{color:var(--txt)}
.ha-pot-oddspct{color:var(--green-soft)!important;font-family:var(--num);font-size:15px}
.ha-pot-feed{display:flex;flex-direction:column;gap:5px;margin-top:14px;min-height:36px}
.ha-pot-feed-empty{font-size:12px;color:var(--txt-mute);padding:6px 2px}
.ha-pot-feed-row{display:flex;align-items:center;gap:8px;font-size:13px;color:var(--txt-dim);padding:6px 10px;border-radius:8px;background:rgba(255,255,255,.03)}
.ha-pot-feed-row i{width:9px;height:9px;border-radius:50%;flex-shrink:0}
.ha-pot-feed-row b{color:var(--txt)}
.ha-pot-feed-row .amt{font-family:var(--num);color:var(--gold)}
.ha-pot-feed-row.is-me{box-shadow:inset 0 0 0 1px rgba(224,180,92,.4)}
.ha-pot-feed-row.is-win{background:rgba(221,255,77,.08)}
.ha-pot-feed-row.is-win .amt{color:var(--green-soft)}
.ha-pot-feed-row.is-new{animation:ha-pot-in .45s var(--ease) both}
@keyframes ha-pot-in{from{opacity:0;transform:translateX(-10px)}to{opacity:1;transform:none}}
.ha-pot-last-body i{display:inline-block;width:9px;height:9px;border-radius:50%;margin-right:6px;vertical-align:middle}
@media (max-width:900px){.ha-pot-stage{grid-template-columns:1fr}.ha-pot-wheelwrap{max-width:420px;margin:0 auto;width:100%}}
@media (prefers-reduced-motion:reduce){.ha-pot-feed-row.is-new{animation:none}.ha-pot-clockline b.is-hot{animation:none}}
.ha-pot-under{display:flex;flex-direction:column;align-items:center;gap:8px;margin-top:6px}
.ha-pot-clockline{position:static;transform:none;display:flex;align-items:baseline;gap:8px;bottom:auto;left:auto}
.ha-pot-clockline b{font-size:16px}
.ha-pot-splash{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);z-index:3;padding:14px 26px;border-radius:12px;background:rgba(6,7,10,.88);border:1px solid rgba(232,192,122,.55);box-shadow:0 0 40px rgba(232,192,122,.25);text-align:center;pointer-events:none}
.ha-pot-splash-k{display:block;font-family:var(--display);font-size:22px;letter-spacing:.12em;text-transform:uppercase;color:var(--gold)}
.ha-pot-splash b{display:block;margin-top:4px;font-size:14px;color:var(--txt);font-weight:600}
.ha-pot-splash.is-in{animation:ha-pot-splash .5s var(--ease) both}
@keyframes ha-pot-splash{from{opacity:0;transform:translate(-50%,-50%) scale(.7)}to{opacity:1;transform:translate(-50%,-50%) scale(1)}}

/* the pit as an arena card */
.ha-pot-card{animation:none;cursor:default}
.ha-pot-card:hover{transform:none;box-shadow:var(--slab)}
.ha-pot-body{display:grid;grid-template-columns:minmax(220px,1fr) minmax(200px,1fr);gap:0;align-items:center}
.ha-pot-wheelwrap{position:relative;padding:18px 12px 12px 18px}
.ha-pot-lineup{display:flex;flex-direction:column;gap:6px;padding:16px 16px 12px 8px;max-height:420px;overflow:auto}
.ha-pot-seat{display:grid;grid-template-columns:auto minmax(0,1fr) auto;align-items:center;gap:12px;padding:8px 12px;border-radius:12px;background:rgba(255,255,255,.03);border-left:3px solid var(--seat)}
.ha-pot-seat .ha-ava img{width:44px;height:44px}
.ha-pot-seat-id{display:flex;flex-direction:column;align-items:flex-start;gap:4px;min-width:0}
.ha-pot-seat .ha-name{justify-content:flex-start;font-size:var(--fs-3)}
.ha-pot-seat-share{text-align:right;font-family:var(--num);font-variant-numeric:tabular-nums}
.ha-pot-seat-share b{display:block;font-size:var(--fs-6);color:var(--txt)}
.ha-pot-seat-share small{color:var(--txt-dim);font-size:11px}
.ha-pot-seat.is-me{box-shadow:inset 0 0 0 1px rgba(224,180,92,.45)}
.ha-pot-seat.is-winner{background:linear-gradient(90deg,rgba(232,192,122,.16),rgba(232,192,122,.03))}
.ha-pot-seat.ha-lost{opacity:.45;filter:saturate(.4)}
.ha-pot-empty{padding:26px 12px;text-align:center;color:var(--txt-dim)}
.ha-pot-empty b{display:block;font-family:var(--display);letter-spacing:.06em;color:var(--txt);margin-bottom:4px}
.ha-pot-plinth{justify-content:flex-start}
.ha-pot-plinth .ha-pot-clock{margin-left:auto;font-family:var(--num);font-size:var(--fs-6);color:var(--gold);font-variant-numeric:tabular-nums}
.ha-pot-plinth .ha-pot-clock.is-hot{color:#ff6b5a;animation:ha-pot-hot .5s ease-in-out infinite alternate}
.ha-pot-plinth::before{display:none}
.ha-pot-splash{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);z-index:3;display:flex;flex-direction:column;align-items:center;gap:8px;padding:14px 22px;border-radius:12px;background:rgba(6,7,10,.9);border:1px solid rgba(232,192,122,.55);box-shadow:0 0 40px rgba(232,192,122,.25);text-align:center;pointer-events:none}
.ha-pot-splash b{display:block;font-family:var(--display);font-size:16px;letter-spacing:.06em;color:var(--txt);font-weight:700}
@media (max-width:900px){.ha-pot-body{grid-template-columns:1fr}.ha-pot-wheelwrap{max-width:380px;margin:0 auto;width:100%;padding:14px}.ha-pot-lineup{max-height:none;padding:0 12px 12px}}
/* the pit gets the room: the wheel is the game */
.ha-pot-stage{grid-template-columns:minmax(0,1.55fr) minmax(280px,1fr)}
.ha-pot-body{grid-template-columns:minmax(240px,1.15fr) minmax(190px,1fr)}
@media (max-width:900px){.ha-pot-body{grid-template-columns:minmax(0,1fr)}}
.ha-pot-seat .ha-name{font-size:var(--fs-3)}
.ha-pot-seat .ha-name > span{max-width:11ch}
@media (max-width:1100px){.ha-pot-stage{grid-template-columns:1fr}}
/* melee history */
.ha-pot-hist-head{margin-top:var(--s6)}
.ha-pot-history{display:grid;grid-template-columns:repeat(auto-fill,minmax(230px,1fr));gap:12px}
.ha-pot-hcard{animation:none;padding:14px 16px;gap:8px}
.ha-pot-hcard:hover{transform:none}
.ha-pot-hcard-top{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.ha-pot-hcard-top b{font-size:var(--fs-4)}
.ha-pot-hcard-top small{font-family:var(--num);font-size:11px;color:var(--txt-mute)}
.ha-pot-hcard-figs{display:flex;gap:14px;font-size:12px;color:var(--txt-dim);flex-wrap:wrap}
.ha-pot-hcard-figs b{font-family:var(--num);color:var(--txt)}
.ha-pot-hcard-foot{display:flex;justify-content:space-between;align-items:center;gap:8px;font-family:var(--num);font-size:11px;color:var(--txt-mute);margin-top:2px}
.ha-pot-hcard-foot .ha-link{color:var(--gold);background:none;border:0;cursor:pointer;font:inherit;letter-spacing:.08em;text-transform:uppercase}
/* the pit takes the whole card; the seats sit under it like a bench */
.ha-pot-body{grid-template-columns:1fr;gap:0}
.ha-pot-wheelwrap{padding:10px 12px 0}
#ha-pot-wheel{aspect-ratio:16/10}
.ha-pot-lineup{display:grid;grid-template-columns:repeat(auto-fill,minmax(170px,1fr));gap:8px;padding:12px 14px 14px;max-height:none;overflow:visible}
.ha-pot-seat .ha-name > span{max-width:14ch}
.ha-pot-stage{grid-template-columns:minmax(0,1.6fr) minmax(280px,1fr)}
@media (max-width:1100px){.ha-pot-stage{grid-template-columns:1fr}.ha-pot-wheelwrap{max-width:none}}
@media (max-width:640px){.ha-pot-lineup{grid-template-columns:1fr 1fr}#ha-pot-wheel{aspect-ratio:4/3}}
@media (max-width:640px){.ha-pot-lineup{grid-template-columns:1fr}.ha-pot-seat .ha-name > span{max-width:18ch}}

.ha-pot-3d{width:100%;aspect-ratio:16/10;border-radius:12px;overflow:hidden;background:#0a121d;box-shadow:inset 0 0 0 1px rgba(232,192,122,.25)}
@media (max-width:640px){.ha-pot-3d{aspect-ratio:4/3}}
.ha-pot-wheelwrap .ha-pot-splash{top:auto;bottom:22px;transform:translate(-50%,0)}
@keyframes ha-pot-splash{from{opacity:0;transform:translate(-50%,12px) scale(.9)}to{opacity:1;transform:translate(-50%,0) scale(1)}}

.ha-pot-hcard-foot > span + span{display:flex;gap:10px}

.ha-pot-chestnote{margin-top:8px;font-size:12.5px;line-height:1.5;color:var(--txt-dim)}

/* Chest Battle: the case opening */
.cb{display:grid;grid-template-columns:repeat(var(--cols,2),minmax(0,1fr));gap:10px;padding:12px}
.cb-col{position:relative;border-radius:12px;background:linear-gradient(180deg,#151b25,#0d1118);box-shadow:inset 0 0 0 1px rgba(255,255,255,.06);border-top:3px solid var(--seat);padding:10px;min-width:0}
.cb-col.is-me{box-shadow:inset 0 0 0 1px rgba(232,192,122,.45)}
.cb-col.is-winner{box-shadow:0 0 0 1px var(--gold),0 0 30px rgba(232,192,122,.25)}
.cb-col.is-lost{opacity:.5;filter:saturate(.5)}
.cb-head{display:flex;align-items:center;gap:8px;margin-bottom:8px;flex-wrap:nowrap}
.cb-ava{width:34px;height:34px;border-radius:50%;object-fit:cover;background:var(--panel-2,#0f141a);box-shadow:0 0 0 1px rgba(255,255,255,.14),0 0 0 3px rgba(0,0,0,.5)}
.cb-ava-blank{display:inline-block}
.cb-id{min-width:0;flex:1}
.cb-id b{display:block;font-size:13px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.cb-id small{display:block;font-family:var(--num);font-size:10px;color:var(--txt-mute);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.cb-total{text-align:right;font-family:var(--num);font-variant-numeric:tabular-nums}
.cb-total{flex:0 0 auto}
.cb-total b{display:block;font-size:17px;color:var(--gold);transition:transform .2s}
.cb-col.is-landed .cb-total b{transform:scale(1.08)}
.cb-total small{font-size:10px;color:var(--txt-mute)}
.cb-tag{position:absolute;top:-11px;left:50%;transform:translateX(-50%);z-index:4}
.cb-reel{position:relative;height:250px;overflow:hidden;border-radius:10px;background:#07090d;box-shadow:inset 0 0 0 1px rgba(255,255,255,.06)}
.cb-strip{position:absolute;left:0;top:0;width:100%;display:flex;flex-direction:column;will-change:transform}
.cb-tile{flex:0 0 92px;width:100%;box-sizing:border-box;margin:0;padding:6px 8px 6px 10px;display:flex;flex-direction:row;align-items:center;justify-content:flex-start;gap:10px;border-bottom:1px solid rgba(255,255,255,.05);background:linear-gradient(90deg,rgba(255,255,255,.035),transparent 70%);border-left:4px solid var(--tier,#8b95a7)}
.cb-tile img{width:52px;height:52px;flex:0 0 52px;object-fit:contain;filter:drop-shadow(0 3px 4px rgba(0,0,0,.7))}
.cb-tile b{display:block;font-family:var(--num);font-size:15px;color:var(--txt)}
.cb-tile small{display:block;font-size:9px;letter-spacing:.06em;text-transform:uppercase;color:var(--txt-mute);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%}
.cb-tx{display:flex;flex-direction:column;min-width:0;flex:1 1 auto}
.cb-tile[data-tier=mythic]{background:linear-gradient(90deg,rgba(242,193,78,.16),transparent 70%)}
.cb-tile[data-tier=legendary]{background:linear-gradient(90deg,rgba(255,90,74,.14),transparent 70%)}
.cb-tile.is-closed{border-left-color:rgba(232,192,122,.35)}
.cb-tile.is-closed b{font-size:18px;color:var(--gold)}
.cb-chest{flex:0 0 40px}
.cb-chest{width:40px;height:30px;border-radius:5px 5px 3px 3px;background:linear-gradient(180deg,#6b4a1e,#3d2a10);box-shadow:inset 0 2px 0 rgba(255,255,255,.12),0 0 0 1px #8a6323}
.cb-marker{position:absolute;top:50%;left:0;right:0;height:2px;margin-top:-1px;background:var(--gold);z-index:3;box-shadow:0 0 10px rgba(232,192,122,.8)}
.cb-marker::before,.cb-marker::after{content:"";position:absolute;top:-5px;border:6px solid transparent}
.cb-marker::before{left:-2px;border-left:7px solid var(--gold)}
.cb-marker::after{right:-2px;border-right:7px solid var(--gold)}
.cb-shade{position:absolute;inset:0;pointer-events:none;background:linear-gradient(180deg,rgba(7,9,13,.92),transparent 26%,transparent 74%,rgba(7,9,13,.92));z-index:2}
.cb-col.is-landed .cb-reel{box-shadow:inset 0 0 0 2px var(--land,var(--gold)),0 0 24px -6px var(--land,var(--gold));transition:box-shadow .2s}
.cb-log{display:flex;flex-wrap:wrap;gap:5px;margin-top:8px;min-height:26px}
.cb-pull{display:inline-flex;align-items:center;gap:4px;padding:3px 7px;border-radius:999px;background:rgba(255,255,255,.04);border:1px solid var(--tier);font-family:var(--num);font-size:11px;color:var(--txt);animation:ha-pot-in .35s var(--ease) both}
.cb-pull img{width:16px;height:16px;object-fit:contain}
@media (max-width:640px){.cb{grid-template-columns:1fr 1fr;padding:8px;gap:8px}.cb-reel{height:200px}.cb-tile{gap:6px;padding-left:8px}.cb-tile img{width:40px;height:40px;flex-basis:40px}.cb-tile b{font-size:13px}}
@media (max-width:420px){.cb{grid-template-columns:1fr}}

.cb-empty{padding:26px 12px;text-align:center;color:var(--txt-dim)}
.cb-empty b{display:block;font-family:var(--display);letter-spacing:.06em;color:var(--txt);margin-bottom:4px}

/* Controls have their own layout row: never cover a participant or the scene. */
.ca-toolbar { display:flex; align-items:center; justify-content:space-between; gap:12px; padding:10px 12px 10px 20px; border-bottom:1px solid var(--edge); background:var(--bg); flex-shrink:0; }
.ca-toolbar-title { min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; color:var(--txt-mute); font:600 11px/1.4 var(--num); text-transform:uppercase; letter-spacing:.08em; }
.ca-toolbar-actions,.ca-fullscreen-control { display:flex; align-items:center; gap:8px; flex-shrink:0; }
.ca-fullscreen-control:empty { display:none; }
.ca-toolbar .ca-x { position:static; width:44px; height:44px; flex:none; }
.ca-toolbar .ha-btn { min-height:44px; padding:0 12px; font-size:10px; }
.ca-snd svg { width:18px; height:18px; flex:none; }
.ca-toolbar + .ha-bt-head { margin-top:0; padding-right:var(--s4); }
.ca-done .ca-status { display:none; }
@media (max-width:560px) {
  .ca-toolbar { gap:6px; padding:8px; }
  .ca-toolbar-title { font-size:9px; letter-spacing:0; }
  .ca-toolbar-actions { gap:4px; }
  .ca-toolbar .ha-btn { padding:0 8px; font-size:9px; gap:6px; }
  .ca-toolbar + .ha-bt-head { padding-right:var(--s3); }
}


/* The countdown to the next holder payout. */
.ha-stop-next { display: flex; align-items: baseline; gap: 10px; margin: 0 0 8px; }
.ha-stop-next .l { font: 600 10px/1 var(--num); letter-spacing: .14em; text-transform: uppercase; color: var(--txt-mute); }
.ha-stop-next b { font: 700 18px/1 var(--num); color: var(--gold); font-variant-numeric: tabular-nums; }
.ha-stop-next .w { font: 500 11px/1 var(--num); color: var(--txt-mute); }


/* Snapshots this wallet has already been paid, kept in view so a claim that
   worked does not simply vanish. */
.ha-claim-done { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; padding: 10px 12px; margin-bottom: 10px; border-radius: 10px; background: rgba(79, 209, 139, .08); box-shadow: inset 0 0 0 1px rgba(79, 209, 139, .25); }
.ha-claim-done span { font: 600 10px/1 var(--num); letter-spacing: .14em; text-transform: uppercase; color: var(--txt-mute); }
.ha-claim-done b { font: 700 16px/1 var(--num); color: #4fd18b; font-variant-numeric: tabular-nums; }
.ha-claim-done small { margin-left: auto; font: 500 11px/1 var(--num); color: var(--txt-mute); }


/* The cashier says what the escrow may already pull, instead of offering to
   ask for permission it has been given. */
.ha-cash-opt.is-done { display: flex; align-items: center; gap: 7px; margin: 0; color: #4fd18b; font-size: 12px; }
.ha-cash-opt.is-done::before { content: ""; width: 7px; height: 7px; border-radius: 50%; background: currentColor; flex: 0 0 7px; }

/* =============================================================================
   THE CITADEL: the cinematic that follows a decided duel (victory.js).
   Mounted inside .ca-stage over the fight's canvas once the loser has fallen.
   The same hard rule as the battle overlay: no filter and no backdrop-filter
   anywhere near the live canvas; the tray is a plain gradient.
   ============================================================================= */
.ca-cinematic .ca-stage { flex-basis: min(64vh, 560px); min-height: 340px; }
/* The stage makes every non-canvas child click-through (see the invariants
   above), and that rule out-specifies a plain class on the container, so the
   controls themselves opt back in: pointer-events inherits, and the buttons
   are where the clicks are. Nothing else in the cinematic takes a click. */
.ca-vic-actions, .ca-vic-share .inner { pointer-events: auto; }
.ca-victory {
  position: absolute; inset: 0; z-index: 4; overflow: hidden; container-type: inline-size;
  background: #071116; animation: ha-fade .5s ease;
}
.ca-vic-gl-host, .ca-vic-gl { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
.ca-vic-vignette {
  position: absolute; inset: 0; z-index: 2; pointer-events: none;
  background:
    linear-gradient(180deg, rgba(5, 9, 12, .95), transparent 34%, transparent 66%, rgba(5, 9, 13, .96)),
    linear-gradient(90deg, rgba(5, 9, 13, .47), transparent 35%, transparent 70%, rgba(5, 9, 13, .53));
  box-shadow: inset 0 0 100px rgba(5, 7, 11, .47);
}
.ca-vic-frame { position: absolute; inset: 12px; z-index: 3; border: 1px solid rgba(189, 157, 84, .1); pointer-events: none; }
.ca-vic-head { position: absolute; z-index: 4; top: 18px; left: 22px; right: 60px; display: flex; align-items: center; justify-content: space-between; pointer-events: none; }
.ca-vic-head img { width: 56px; height: 36px; object-fit: contain; opacity: .75; }
.ca-vic-head span { font-size: 9px; font-weight: 700; letter-spacing: .18em; color: #b1b9b2; }
.ca-vic-title { position: absolute; z-index: 3; top: 5%; left: 14%; right: 14%; text-align: center; pointer-events: none; }
.ca-vic-orn { display: block; color: #bba36f; font-size: 8px; letter-spacing: .35em; margin-bottom: 4px; }
.ca-vic-kicker { display: block; font-size: 8px; font-weight: 700; letter-spacing: .2em; color: var(--gold); margin-bottom: 4px; }
.ca-vic-title h2 {
  margin: 0; font-family: var(--display); font-weight: 800; font-size: clamp(30px, 4.8cqw, 74px); line-height: 1.05;
  letter-spacing: .13em; color: #efd6a6; text-shadow: 0 3px 24px #000;
}
.ca-vic-name { margin: 5px 0 0; font-weight: 700; font-size: 10px; letter-spacing: .28em; text-transform: uppercase; color: #fff; overflow-wrap: anywhere; }
.ca-vic-tray {
  position: absolute; z-index: 3; bottom: 15%; left: 8%; right: 8%;
  display: flex; align-items: center; justify-content: space-around; gap: 16px; padding: 10px 23px;
  border-top: 1px solid rgba(198, 166, 102, .33); border-bottom: 1px solid rgba(198, 166, 102, .15);
  background: linear-gradient(90deg, transparent, rgba(16, 25, 26, .93) 22%, rgba(16, 25, 26, .93) 78%, transparent);
}
.ca-vic-tray .micro { display: block; font-size: 7px; font-weight: 700; letter-spacing: .14em; text-transform: uppercase; color: #a4afa6; }
.ca-vic-player { display: flex; align-items: center; gap: 11px; min-width: 140px; }
.ca-vic-player img.ava { width: 40px; height: 40px; border-radius: 50%; object-fit: cover; flex-shrink: 0; box-shadow: 0 0 0 1px #8a784d; }
.ca-vic-player strong { display: block; max-width: 160px; font-size: 12px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* the loser: same cell, the red ring the result card gave a lost seat, and
   the name dimmed. No grayscale: a filter over the live canvas is off-limits */
.ca-vic-loser img.ava { opacity: .8; box-shadow: 0 0 0 1px rgba(224, 84, 74, .55); }
.ca-vic-loser strong { color: #b1868a; }
.ca-vic-prize { text-align: center; }
.ca-vic-prize > strong { display: flex; gap: 8px; align-items: center; justify-content: center; margin-top: 4px; font-family: var(--num); font-weight: 700; font-size: 24px; line-height: 1.3; color: #f3d59d; white-space: nowrap; }
.ca-vic-prize > strong .ha-coin { width: 22px; height: 22px; }
.ca-vic-prize small { font-size: 11px; color: #a7b09e; align-self: end; margin-bottom: 4px; }
.ca-vic-prize em { display: block; margin-top: 2px; font-style: normal; font-size: 8px; color: #9da79d; }
.ca-vic-actions { position: absolute; z-index: 3; bottom: 4%; left: 0; right: 0; display: flex; align-items: center; justify-content: center; gap: 12px; }
.ca-vic-actions .ha-btn { min-height:44px; padding:0 18px; font-size:11px; }
.ca-vic-status { position: absolute; z-index: 3; bottom: 0; left: 0; right: 0; margin: 0; padding: 0 0 6px; text-align: center; font-size: var(--fs-2); color: var(--gold); pointer-events: none; }
.ca-vic-status:empty { display: none; }
/* the copy follows the choreography: title after the hold, the tray once the
   weapon is down, the share buttons once the pose has settled */
.ca-vic-title, .ca-vic-tray, .ca-vic-actions { transition: opacity .45s, transform .7s; }
.ca-victory[data-phase="hold"] .ca-vic-title, .ca-victory[data-phase="hold"] .ca-vic-tray, .ca-victory[data-phase="hold"] .ca-vic-actions,
.ca-victory[data-phase="release"] .ca-vic-tray, .ca-victory[data-phase="release"] .ca-vic-actions,
.ca-victory[data-phase="drop"] .ca-vic-actions,
.ca-victory[data-phase="pose"] .ca-vic-actions { opacity: 0; transform: translateY(10px); pointer-events: none; }
.ca-vic-share {
  position: absolute; inset: 0; z-index: 6; display: flex; align-items: center; justify-content: center;
  background: rgba(3, 4, 7, .92); animation: ha-fade .3s ease;
}
.ca-vic-share .inner {
  width: min(560px, 92%); max-height: 100%; overflow: auto; display: flex; flex-direction: column; gap: var(--s3); padding: var(--s4); border-radius: var(--r-lg);
  background: linear-gradient(180deg, #141a22, #0a0d12);
  box-shadow: 0 0 0 1px rgba(232, 192, 122, .34), 0 40px 90px -30px #000;
}
.ca-vic-share h3 { margin: 0; font-size: var(--fs-6); }
.ca-vic-share img { display: block; width: 100%; aspect-ratio: 16 / 9; border-radius: var(--r-xs); box-shadow: 0 0 0 1px rgba(255, 255, 255, .1); }
.ca-vic-share p { margin: 0; font-size: var(--fs-3); color: var(--txt-dim); }
.ca-vic-share .caption { font-size: var(--fs-4); font-style: italic; color: var(--gold); }
.ca-vic-share .actions { display: flex; gap: var(--s3); flex-wrap: wrap; }
.ca-vic-share .actions .ha-btn { flex: 1; min-width: 130px; text-decoration: none; }
@media (max-width: 640px) {
  .ca-cinematic .ca-stage { min-height: 420px; }
  .ca-vic-title { top: 10%; left: 6%; right: 6%; }
  .ca-vic-title h2 { font-size: 10cqw; }
  /* payout across the top, the two seats beneath it */
  .ca-vic-tray { bottom: 17%; left: 5%; right: 5%; gap: 8px 10px; display: grid; grid-template-columns: 1fr 1fr; padding: 10px 12px; }
  .ca-vic-prize { grid-column: 1 / -1; order: -1; }
  .ca-vic-prize > strong { font-size: 19px; }
  .ca-vic-player { min-width: 0; gap: 8px; }
  .ca-vic-player img.ava { width: 30px; height: 30px; }
  .ca-vic-player strong { font-size: 10px; max-width: none; }
  .ca-vic-actions { bottom: 6%; gap: 8px; }
  .ca-vic-actions .ha-btn { min-height:44px; padding:0 14px; font-size:10px; }
}
@media (prefers-reduced-motion: reduce) { .ca-vic-title, .ca-vic-tray, .ca-vic-actions { transition: none; } }
