/* ---- src/ui/ui.css */
/* Pepecat Dungeon — HUD, pause, settings and overlay styles.
   One pixel language. --px is one UI art pixel in CSS px, always a whole number of device pixels
   ( round( world scale × UI size ), hud.js layout ), so the kit ( art/ui/, --ui-<name> url()s set by
   hud.js ) and the bitmap fonts ( .txt elements painted by src/ui/bitfont.js ) stay crisp and even.
   Sizes below are kit sizes in art px ( src/ui/kit.js ). --u is one logical playfield pixel ( world
   positions: damage numbers ). The system serif is kept only for small body text in the menus. */

/* Gate 2 screens ( src/ui/screens.js ): inventory, stash, tooltips and comparison, talents, map,
   death, boss card, level-up, save indicator, storage error, floor-loot plates. Imported by ui.css.
   Inside .ui-screens one art px is --spx ( hud.js layout: the largest whole device-px size at which
   the 960 × 540 design still fits, ≤ the HUD's --px ); tooltips and loot plates use --tpx, never
   under 2 device px, so their 5 × 7 bitmap text stays legible at 720p. */

.ui-screens { position: absolute; inset: 0; --px: var( --spx, 2px ); pointer-events: none; }
.ui-screens [hidden] { display: none !important; }
.ui-screens .spr, .front .spr, #hud > .ui-hints .spr { display: block; flex: none; image-rendering: pixelated; background-repeat: no-repeat; background-size: 100% 100%; }
/* Status glyphs ( mark-*, mouse-*, hint-tick ): a 1 px void plate behind the art ( umbra would vanish on
   the umbra panels ), the rim outside the box so no layout moves ( the sprite() helpers in screens.js and front.js add .plate ). */
.spr.plate { background-color: var( --void ); box-shadow: 0 0 0 var( --px ) var( --void ); }
body.ui-screen-open #pause { display: none !important; }

.ui-backdrop { position: absolute; inset: 0; pointer-events: auto; background: linear-gradient( 90deg, rgba( 5, 4, 15, 0.55 ), rgba( 5, 4, 15, 0.35 ) 50%, rgba( 5, 4, 15, 0.55 ) ); }

/* Panels: the big kit frame ( slice 20 ), title in gothic, kit divider. */
.ui-panel { position: absolute; pointer-events: auto; box-sizing: border-box; display: flex; flex-direction: column; align-items: center; gap: calc( 4 * var( --px ) );
  border: calc( 20 * var( --px ) ) solid transparent; border-image: var( --ui-frame ) 20 fill / calc( 20 * var( --px ) ) stretch; image-rendering: pixelated;
  padding: calc( 2 * var( --px ) ) calc( 6 * var( --px ) ) calc( 4 * var( --px ) ); filter: drop-shadow( 0 calc( 3 * var( --px ) ) 0 rgba( 0, 0, 0, 0.6 ) ); }
.ui-title { line-height: 0; margin-top: calc( -2 * var( --px ) ); }
.ui-rule { width: calc( 121 * var( --px ) ); height: calc( 7 * var( --px ) ); background: var( --ui-divider ) 0 0 / 100% 100% no-repeat; image-rendering: pixelated; flex: none; }
.ui-hint { display: flex; justify-content: center; line-height: 0; }
.ui-inv { right: calc( 10 * var( --px ) ); top: max( calc( 14 * var( --px ) ), calc( 30 * var( --hpx, 0px ) ) ); } /* below the icon row ( 27 HUD px ), which slides over it */
.ui-stash { left: calc( 10 * var( --px ) ); top: calc( 14 * var( --px ) ); }

/* Inventory: doll + hero summary over the 10 × 4 pack. */
.ui-inv-top { display: flex; gap: calc( 8 * var( --px ) ); align-items: flex-start; }
.ui-doll { position: relative; width: calc( 192 * var( --px ) ); height: calc( 174 * var( --px ) ); flex: none; }
.ui-socket { position: absolute; border-width: calc( 6 * var( --px ) ); border-image: var( --ui-socket ) 6 fill / calc( 6 * var( --px ) ) stretch; }
.ui-socket.target { border-image-source: var( --ui-socket-hot ); }
.ui-socket.target.bad { border-image-source: var( --ui-socket-bad ); }
.ui-socket-field { position: relative; }
.ui-socket .ui-ghost { position: absolute; inset: 0; width: 100% !important; height: 100% !important; opacity: 0.55; }
.ui-socket-label { position: absolute; left: round( 50%, var( --dpx, 1px ) ); bottom: calc( -9 * var( --px ) ); translate: round( -50%, var( --dpx, 1px ) ) 0; opacity: 0; transition: opacity 0.12s; }
.ui-socket.empty .ui-socket-label, .ui-socket:hover .ui-socket-label { opacity: 1; }
.ui-socket[data-slot='charm'] .ui-socket-label { bottom: auto; top: calc( 100% + 2 * var( --px ) ); }

.ui-hero { width: calc( 92 * var( --px ) ); display: flex; flex-direction: column; gap: calc( 3 * var( --px ) ); padding-top: calc( 2 * var( --px ) ); }
.ui-level { display: flex; align-items: flex-end; justify-content: space-between; line-height: 0; }
.ui-xp { position: relative; height: calc( 5 * var( --px ) ); background: var( --void ); box-shadow: 0 0 0 var( --px ) var( --iron0 ); }
.ui-xp::after { content: ''; position: absolute; inset: 0; right: auto; width: calc( var( --xp ) * 100% ); background: linear-gradient( var( --core ), var( --flame2 ) 40%, var( --flame0 ) ); }
.ui-xp-text { line-height: 0; display: flex; justify-content: flex-end; }
.ui-stat { display: flex; justify-content: space-between; align-items: center; line-height: 0; padding: var( --px ) 0; border-bottom: var( --px ) solid rgba( 91, 101, 124, 0.25 ); }

.ui-grid { border-width: calc( 6 * var( --px ) ); border-image: var( --ui-socket ) 6 fill / calc( 6 * var( --px ) ) stretch; flex: none; }
.ui-grid-field { position: relative; background: var( --ui-cell ) 0 0 / calc( 24 * var( --px ) ) calc( 24 * var( --px ) ) repeat; image-rendering: pixelated; }
.ui-inv-foot { position: relative; align-self: stretch; display: flex; justify-content: space-between; align-items: center; padding: 0 calc( 2 * var( --px ) ); }
/* More pack below ( screens.js scrollCue ): a gilt arrow on a void plaque over the pinned foot, bobbing. */
.ui-scroll-cue { display: none; position: absolute; right: calc( 1 * var( --px ) ); bottom: calc( 100% + 2 * var( --px ) ); line-height: 0; pointer-events: none;
  padding: var( --px ) calc( 3 * var( --px ) ); background: rgba( 21, 15, 38, 0.85 ); box-shadow: 0 0 0 var( --px ) #ffc845, 0 0 calc( 3 * var( --px ) ) rgba( 255, 200, 69, 0.35 ); animation: ui-scroll-bob 1.2s ease-in-out infinite; }
.ui-inv.more .ui-scroll-cue { display: block; }
@keyframes ui-scroll-bob { 50% { translate: 0 var( --px ); } }
/* and a thin ember scrollbar on the panel's edge: it only exists while the pack overflows ( touch.css hides panel bars ) */
#hud:not( .touch ) .ui-panel.ui-inv, #hud.touch .ui-panel.ui-inv { scrollbar-width: thin; scrollbar-color: #b8401c rgba( 21, 15, 38, 0.6 ); }
.ui-gold { display: flex; align-items: center; gap: calc( 3 * var( --px ) ); line-height: 0; }

/* Items: rarity tint behind, the icon, rarity corner brackets on top. Rare / Unique glow. */
.ui-item { position: absolute; left: 0; top: 0; cursor: pointer; }
.ui-item-bg { position: absolute; inset: var( --px ); background: rgba( 5, 4, 15, 0.35 ); }
.ui-item.r-magic .ui-item-bg { background: linear-gradient( rgba( 188, 202, 223, 0.07 ), rgba( 188, 202, 223, 0.07 ) ), rgba( 5, 4, 15, 0.35 ); }
.ui-item.r-rare .ui-item-bg { background: linear-gradient( rgba( 255, 200, 69, 0.09 ), rgba( 255, 200, 69, 0.09 ) ), rgba( 5, 4, 15, 0.35 ); }
.ui-item.r-unique .ui-item-bg { background: radial-gradient( closest-side, rgba( 232, 128, 30, 0.22 ), rgba( 232, 128, 30, 0.07 ) ), rgba( 5, 4, 15, 0.35 ); }
.ui-item-icon { position: absolute; inset: 0; width: 100% !important; height: 100% !important; }
.ui-item-frame { position: absolute; inset: 0; border-width: calc( 5 * var( --px ) ); border-image: var( --ui-rarity-common ) 5 / calc( 5 * var( --px ) ) stretch; opacity: 0.55; }
.ui-item.r-magic .ui-item-frame { border-image-source: var( --ui-rarity-magic ); opacity: 0.8; }
.ui-item.r-rare .ui-item-frame { border-image-source: var( --ui-rarity-rare ); opacity: 1; }
.ui-item.r-unique .ui-item-frame { border-image-source: var( --ui-rarity-unique ); opacity: 1; }
.ui-item.r-rare .ui-item-icon { filter: drop-shadow( 0 0 calc( 2 * var( --px ) ) rgba( 255, 200, 69, 0.35 ) ); }
.ui-item.r-unique .ui-item-icon { animation: unique-glow 2.4s ease-in-out infinite; }
@keyframes unique-glow { 0%, 100% { filter: drop-shadow( 0 0 calc( 2 * var( --px ) ) rgba( 232, 128, 30, 0.45 ) ); } 50% { filter: drop-shadow( 0 0 calc( 4 * var( --px ) ) rgba( 255, 200, 69, 0.7 ) ); } }
.ui-screens.calm .ui-item.r-unique .ui-item-icon { animation: none; filter: drop-shadow( 0 0 calc( 3 * var( --px ) ) rgba( 232, 128, 30, 0.55 ) ); }
.ui-item:hover .ui-item-bg { background: rgba( 240, 230, 198, 0.12 ); }
.ui-item.lifted { opacity: 0.35; }
.ui-place { position: absolute; pointer-events: none; }
.ui-place.ok { background: rgba( 255, 200, 69, 0.2 ); box-shadow: inset 0 0 0 var( --px ) rgba( 255, 200, 69, 0.75 ); } /* gilt: green is Pepecat's */
.ui-place.bad { background: rgba( 138, 26, 43, 0.35 ); box-shadow: inset 0 0 0 var( --px ) rgba( 138, 26, 43, 0.9 ); } /* blood2: the reds are Pepecat's */
.ui-held { position: absolute; left: 0; top: 0; pointer-events: none; filter: drop-shadow( 0 calc( 3 * var( --px ) ) 0 rgba( 0, 0, 0, 0.6 ) ); }
.ui-held .ui-item { position: relative; }

/* Tooltips: --tpx art px; void card with iron frame, gilt corners for Rare / Unique. */
.ui-tips { position: absolute; left: 0; top: 0; display: flex; gap: calc( 3 * var( --tpx ) ); align-items: flex-start; pointer-events: none; --px: var( --tpx, 2px ); z-index: 5; }
.ui-tipcard { border-width: calc( 6 * var( --px ) ); border-image: var( --ui-tip ) 6 fill / calc( 6 * var( --px ) ) stretch; padding: calc( 1 * var( --px ) ) calc( 2 * var( --px ) );
  display: flex; flex-direction: column; align-items: center; gap: calc( 1 * var( --px ) ); min-width: calc( 120 * var( --px ) ); max-width: calc( 184 * var( --px ) ); filter: drop-shadow( 0 calc( 2 * var( --px ) ) 0 rgba( 0, 0, 0, 0.7 ) ); }
.ui-tipcard.r-rare, .ui-tipcard.r-unique { border-image-source: var( --ui-tip-gilt ); }
.ui-tipcard.equipped { filter: drop-shadow( 0 calc( 2 * var( --px ) ) 0 rgba( 0, 0, 0, 0.7 ) ) brightness( 0.82 ); }
.ui-tip-name, .ui-tip-line, .ui-tip-tag { line-height: 0; display: flex; justify-content: center; }
.ui-tip-tag { padding: var( --px ) calc( 4 * var( --px ) ); background: var( --iron0 ); margin-bottom: var( --px ); }
.ui-tip-rule { align-self: stretch; height: var( --px ); margin: calc( 2 * var( --px ) ) calc( 6 * var( --px ) ); background: linear-gradient( 90deg, transparent, var( --iron1 ) 20%, var( --iron1 ) 80%, transparent ); }
.ui-tipcard.talent { align-items: center; }

/* The headline delta: arrow, big signed figures, stat name and the equipped value. */
.ui-headline { display: flex; align-items: center; gap: calc( 3 * var( --px ) ); margin: calc( 3 * var( --px ) ) 0 calc( 1 * var( --px ) ); padding: calc( 2 * var( --px ) ) calc( 5 * var( --px ) ); line-height: 0; }
.ui-headline.up { background: linear-gradient( 90deg, rgba( 188, 202, 223, 0 ), rgba( 188, 202, 223, 0.2 ) 30%, rgba( 188, 202, 223, 0.2 ) 70%, rgba( 188, 202, 223, 0 ) ); } /* cold steel, as the up style: gilt stays with rarity */
.ui-headline.down { background: linear-gradient( 90deg, rgba( 138, 26, 43, 0 ), rgba( 138, 26, 43, 0.45 ) 30%, rgba( 138, 26, 43, 0.45 ) 70%, rgba( 138, 26, 43, 0 ) ); }
.ui-headline-sub { display: flex; flex-direction: column; gap: calc( 2 * var( --px ) ); line-height: 0; }
.ui-arrow.big { width: calc( 14 * var( --px ) ) !important; height: calc( 16 * var( --px ) ) !important; }
.ui-delta { display: flex; align-items: center; gap: calc( 3 * var( --px ) ); line-height: 0; align-self: flex-start; margin-left: calc( 8 * var( --px ) ); }

/* Talents: three branch columns of 132 art px. */
.ui-talents { left: round( 50%, var( --dpx, 1px ) ); top: calc( 12 * var( --px ) ); translate: round( -50%, var( --dpx, 1px ) ) 0; }
.ui-talent-head { align-self: stretch; display: flex; justify-content: space-between; align-items: center; line-height: 0; padding: 0 calc( 4 * var( --px ) ); }
.ui-points { display: flex; align-items: flex-end; gap: calc( 3 * var( --px ) ); padding: calc( 2 * var( --px ) ) calc( 5 * var( --px ) ); }
.ui-points.has { background: linear-gradient( 90deg, rgba( 94, 20, 32, 0 ), rgba( 94, 20, 32, 0.6 ) 25%, rgba( 94, 20, 32, 0.6 ) ); animation: points-glow 1.6s ease-in-out infinite; }
@keyframes points-glow { 50% { filter: brightness( 1.3 ); } }
.ui-screens.calm .ui-points.has { animation: none; }
.ui-branches { display: flex; gap: calc( 10 * var( --px ) ); }
.ui-branch { width: calc( 132 * var( --px ) ); display: flex; flex-direction: column; align-items: center; gap: calc( 2 * var( --px ) ); padding: calc( 4 * var( --px ) ) 0; background: linear-gradient( rgba( 38, 43, 56, 0.55 ), rgba( 38, 43, 56, 0 ) ); }
.ui-branch-name, .ui-branch-pts, .ui-branch-cap { line-height: 0; display: flex; justify-content: center; }
.ui-identity { display: flex; flex-direction: column; gap: var( --px ); min-height: calc( 17 * var( --px ) ); }
.ui-tree { position: relative; width: calc( 132 * var( --px ) ); height: calc( 226 * var( --px ) ); margin-top: calc( 4 * var( --px ) ); }
.ui-link { position: absolute; background: var( --iron0 ); box-shadow: 0 0 0 var( --px ) var( --void ); }
.ui-link.lit { background: var( --flame1 ); }
.ui-node { position: absolute; pointer-events: auto; cursor: pointer; background-image: var( --frame ); background-repeat: no-repeat; background-size: 100% 100%; image-rendering: pixelated; }
.ui-node .ui-node-icon { position: absolute; }
.ui-node.locked { cursor: default; }
.ui-node.can { animation: node-can 1.4s ease-in-out infinite; }
@keyframes node-can { 0%, 100% { filter: drop-shadow( 0 0 0 transparent ); } 50% { filter: drop-shadow( 0 0 calc( 3 * var( --px ) ) rgba( 255, 200, 69, 0.8 ) ); } }
.ui-screens.calm .ui-node.can { animation: none; filter: drop-shadow( 0 0 calc( 2 * var( --px ) ) rgba( 255, 200, 69, 0.6 ) ); }
/* hover and locked are generated in-palette variants ( art/ui/tools/icon-tier.mjs ): the frame's -hot, the icon's -off */
.ui-node:hover { background-image: var( --frame-hot ); }
.ui-ranks { position: absolute; left: round( 50%, var( --dpx, 1px ) ); top: calc( 100% + 2 * var( --px ) ); translate: round( -50%, var( --dpx, 1px ) ) 0; display: flex; gap: var( --px ); }
.ui-node.capstone .ui-ranks { top: calc( 100% - 1 * var( --px ) ); }
.ui-node-selected { position: absolute; right: calc( -6 * var( --px ) ); top: calc( -5 * var( --px ) ); line-height: 0; padding: var( --px ) calc( 2 * var( --px ) ); background: var( --blood1 ); box-shadow: 0 0 0 var( --px ) var( --void ); }
.ui-talent-foot { align-self: stretch; display: flex; justify-content: space-between; align-items: center; padding: calc( 2 * var( --px ) ) calc( 4 * var( --px ) ) 0; border-top: var( --px ) solid var( --iron0 ); }
.ui-foot-row { display: flex; align-items: center; gap: calc( 3 * var( --px ) ); line-height: 0; }
/* The Ascendancy ( M2b ): the page switch, letter placeholders for icons still to draw, and Hellcharge's rank table. */
.ui-talent-page { display: flex; align-items: center; line-height: 0; background: none; cursor: pointer; padding: calc( 1 * var( --px ) ) calc( 4 * var( --px ) );
  border-width: calc( 5 * var( --px ) ); border-image: var( --ui-button ) 5 fill / calc( 5 * var( --px ) ) stretch; }
.ui-talent-page:hover, .ui-talent-page:active { border-image-source: var( --ui-button-hot ); }
.ui-node .ui-node-letter { width: calc( 17 * var( --px ) ); height: calc( 17 * var( --px ) ); display: flex; align-items: center; justify-content: center; line-height: 0; }
.ui-hc-table { display: flex; flex-direction: column; gap: var( --px ); margin: calc( 2 * var( --px ) ) 0; }
.ui-hc-head, .ui-hc-rank { display: grid; grid-template-columns: repeat( 5, auto ); justify-content: space-between; align-items: center; line-height: 0; }
.ui-hc-rank.next { background: rgba( 38, 43, 56, 0.7 ); }
.ui-respec { display: flex; align-items: center; gap: calc( 3 * var( --px ) ); line-height: 0; background: none; padding: calc( 1 * var( --px ) ) calc( 4 * var( --px ) ); cursor: default;
  border-width: calc( 5 * var( --px ) ); border-image: var( --ui-button ) 5 fill / calc( 5 * var( --px ) ) stretch; }
.ui-respec.ok { cursor: pointer; }
.ui-respec.ok:hover, .ui-respec.ok:active { border-image-source: var( --ui-button-hot ); }
/* The pack upgrade ( screens.js packEl ): a full-width band over the foot, the gothic button face. Ready: hot
   gilt edge and a slow ember pulse; blocked: flat, the reason in its line ( short of points or gold: blood ). */
.ui-pack-up { align-self: stretch; display: grid; grid-template-columns: auto 1fr auto; align-items: center; gap: calc( 6 * var( --px ) ); line-height: 0; background: none; cursor: default;
  margin: calc( 2 * var( --px ) ) 0 calc( 1 * var( --px ) ); padding: calc( 1 * var( --px ) ) calc( 4 * var( --px ) );
  border-width: calc( 5 * var( --px ) ); border-image: var( --ui-button ) 5 fill / calc( 5 * var( --px ) ) stretch; }
.ui-pack-up.ok { cursor: pointer; border-image-source: var( --ui-button-hot ); animation: ui-pack-ready 1.6s ease-in-out infinite; }
.ui-pack-up.ok:hover { filter: brightness( 1.12 ); }
.ui-pack-up.ok:active, .ui-pack-up.ok.pressed { translate: 0 var( --px ); border-image-source: var( --ui-button-down ); animation: none; }
.ui-pack-up.level, .ui-pack-up.maxed { opacity: 0.85; }
@keyframes ui-pack-ready { 50% { box-shadow: 0 0 calc( 4 * var( --px ) ) rgba( 232, 128, 30, 0.45 ); } }
.ui-pack-id, .ui-pack-row, .ui-pack-cost, .ui-pack-state { display: flex; align-items: center; gap: calc( 3 * var( --px ) ); line-height: 0; }
.ui-pack-row { justify-content: center; gap: calc( 8 * var( --px ) ); }
.ui-pack-state { justify-content: flex-end; }
.ui-pack-icon { flex: none; }
.ui-pack-up:not( .ok, .maxed ) .ui-pack-icon { filter: grayscale( 0.8 ) brightness( 0.75 ); }
.ui-pack-up .ui-pack-pips { position: static; translate: none; }
/* The inventory's pointer to it: an opened, unbought row. */
.ui-pack-note { display: flex; justify-content: center; align-items: center; gap: calc( 3 * var( --px ) ); line-height: 0; }
/* The inventory's Menu button ( screens.js menuEl ): the gothic button face, as Respec. */
.ui-menu-open { display: flex; align-items: center; line-height: 0; background: none; padding: calc( 1 * var( --px ) ) calc( 4 * var( --px ) ); cursor: pointer;
  border-width: calc( 5 * var( --px ) ); border-image: var( --ui-button ) 5 fill / calc( 5 * var( --px ) ) stretch; }
.ui-menu-open:hover { border-image-source: var( --ui-button-hot ); }

/* Map. */
.ui-map { left: round( 50%, var( --dpx, 1px ) ); top: calc( 20 * var( --px ) ); translate: round( -50%, var( --dpx, 1px ) ) 0; }
.ui-map-area { line-height: 0; }
.ui-map-view { position: relative; margin: calc( 4 * var( --px ) ) calc( 8 * var( --px ) ); }
.ui-map-canvas { display: block; image-rendering: pixelated; }
.ui-map-mark { position: absolute; filter: drop-shadow( 0 var( --px ) 0 var( --void ) ); }
.ui-legend { display: flex; gap: calc( 8 * var( --px ) ); }
.ui-legend-item { display: flex; align-items: center; gap: calc( 3 * var( --px ) ); line-height: 0; }

/* Map zones ( two or more explored ): a row of tabs under the title. */
.ui-map-zones { display: flex; gap: calc( 3 * var( --px ) ); }
.ui-map-zone { display: flex; align-items: center; gap: calc( 3 * var( --px ) ); line-height: 0; background: none; cursor: pointer; padding: calc( 1 * var( --px ) ) calc( 4 * var( --px ) );
  border-width: calc( 5 * var( --px ) ); border-image: var( --ui-button ) 5 fill / calc( 5 * var( --px ) ) stretch; }
.ui-map-zone:hover, .ui-map-zone:focus-visible { border-image-source: var( --ui-button-hot ); outline: none; }
.ui-map-zone.on { border-image-source: var( --ui-button-hot ); cursor: default; }
/* pressed: the gothic buttons' one-pixel push ( .menu-btn:active ), and the lit frame for a held touch */
.ui-wp.ok:not( .here ):active, .ui-wp.ok:not( .here ).pressed, .ui-respec.ok:active, .ui-respec.ok.pressed, .ui-menu-open:active, .ui-menu-open.pressed, .ui-map-zone:not( .on ):active { translate: 0 var( --px ); border-image-source: var( --ui-button-down ); }
.ui-map-none { display: flex; align-items: center; justify-content: center; line-height: 0; min-width: calc( 200 * var( --px ) ); min-height: calc( 90 * var( --px ) ); }

/* Waypoint travel: one row per lit waypoint, the current one marked; unlit rows in cold iron. */
.ui-travel { left: round( 50%, var( --dpx, 1px ) ); top: calc( 40 * var( --px ) ); translate: round( -50%, var( --dpx, 1px ) ) 0; min-width: calc( 220 * var( --px ) ); }
.ui-wp-list { display: flex; flex-direction: column; align-self: stretch; gap: calc( 3 * var( --px ) ); }
.ui-wp-zone { line-height: 0; padding: calc( 2 * var( --px ) ) 0 0 calc( 2 * var( --px ) ); }
.ui-wp { display: grid; grid-template-columns: auto 1fr auto; align-items: center; gap: calc( 6 * var( --px ) ); line-height: 0; background: none; text-align: left; cursor: default;
  padding: calc( 2 * var( --px ) ) calc( 5 * var( --px ) ); border-width: calc( 5 * var( --px ) ); border-image: var( --ui-button ) 5 fill / calc( 5 * var( --px ) ) stretch; }
.ui-wp-mark { width: calc( 18 * var( --px ) ) !important; height: calc( 18 * var( --px ) ) !important; image-rendering: pixelated; }
.ui-wp-text { display: flex; flex-direction: column; gap: calc( 2 * var( --px ) ); }
.ui-wp.ok { cursor: pointer; }
.ui-wp.ok:hover, .ui-wp.ok:focus-visible { border-image-source: var( --ui-button-hot ); outline: none; }
.ui-wp.ok:hover .ui-wp-mark, .ui-wp.ok:focus-visible .ui-wp-mark { filter: drop-shadow( 0 0 calc( 2 * var( --px ) ) rgba( 255, 200, 69, 0.7 ) ); }
.ui-wp.here { border-image-source: var( --ui-button-hot ); }
/* unlit: the disabled text ramp alone ( fading the row too left it unreadable at 1x ) */
.ui-travel .ui-respec { margin-top: calc( -1 * var( --px ) ); }

/* The prompt over an active waypoint while Pepecat stands at it. */
.ui-wp-prompt { position: absolute; left: 0; top: 0; pointer-events: auto; cursor: pointer; display: flex; align-items: center; gap: calc( 3 * var( --px ) ); line-height: 0; background: none;
  padding: calc( 1 * var( --px ) ) calc( 4 * var( --px ) ); border-width: calc( 5 * var( --px ) ); border-image: var( --ui-panel ) 7 fill / calc( 5 * var( --px ) ) stretch; --px: var( --tpx, 2px );
  filter: drop-shadow( 0 var( --px ) 0 var( --void ) ); animation: wp-in 0.3s steps( 3 ) both; }
.ui-wp-prompt:hover, .ui-wp-prompt:focus-visible { border-image-source: var( --ui-button-hot ); outline: none; }
.ui-wp-prompt .ui-wp-mark { width: calc( 9 * var( --px ) ) !important; height: calc( 9 * var( --px ) ) !important; }
@keyframes wp-in { from { opacity: 0; translate: 0 calc( 3 * var( --px ) ); } }

/* Zone title card ( zone_entered ): huge gothic name, a rule, its line and the area level; about 2.5 s. */
.ui-zonecard { position: absolute; left: 0; right: 0; top: round( 22%, var( --dpx, 1px ) ); display: flex; flex-direction: column; align-items: center; gap: calc( 3 * var( --px ) ); filter: drop-shadow( 0 calc( 2 * var( --px ) ) 0 var( --void ) ); opacity: 0; pointer-events: none; }
.ui-zonecard.show { animation: zone-in 3.2s steps( 32 ) both; }
@keyframes zone-in { 0% { opacity: 0; translate: 0 calc( 4 * var( --px ) ); } 12% { opacity: 1; translate: 0 0; } 78% { opacity: 1; } 100% { opacity: 0; } }
.ui-zonecard.hold { animation: none; opacity: 1; }
/* a screen opened on arrival ( I, T ) stands over the card, never under it: the card is mounted after the
   panels, so it stands down while one is open ( as it does under the ascend screen below ) */
body.ui-screen-open .ui-zonecard { visibility: hidden; }
.ui-zonecard-name { margin-bottom: calc( -1 * var( --px ) ); }

/* Death: blood vignette, huge gothic, one card of facts, one action. */
.ui-death { position: absolute; inset: 0; pointer-events: auto; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: calc( 5 * var( --px ) );
  background: radial-gradient( ellipse at 50% 45%, rgba( 58, 13, 22, 0.55 ), rgba( 5, 4, 15, 0.92 ) 75% ); animation: death-in 1.2s ease-out both; }
@keyframes death-in { from { opacity: 0; } }
.ui-death-title { line-height: 0; filter: drop-shadow( 0 calc( 2 * var( --px ) ) 0 var( --void ) ); animation: death-title 1.6s steps( 8 ) both; }
@keyframes death-title { from { opacity: 0; translate: 0 calc( -6 * var( --px ) ); } }
.ui-rule.wide { width: calc( 242 * var( --px ) ); background-size: 100% 100%; }
.ui-death-card { border-width: calc( 6 * var( --px ) ); border-image: var( --ui-tip ) 6 fill / calc( 6 * var( --px ) ) stretch; padding: calc( 3 * var( --px ) ) calc( 8 * var( --px ) ); display: flex; flex-direction: column; align-items: center; gap: calc( 3 * var( --px ) ); --px: var( --tpx, 2px ); }
.ui-death-items { display: grid; grid-template-columns: auto auto auto auto; gap: calc( 2 * var( --px ) ) calc( 6 * var( --px ) ); align-items: center; line-height: 0; }
.ui-death-item { display: contents; }
.ui-death-groups, .ui-death-group { display: flex; flex-direction: column; align-items: center; gap: calc( 3 * var( --px ) ); }
/* short screens ( phones in landscape ): the groups side by side, no rarity column ( the name's colour says it ) */
@media ( max-height: 520px ) {
  .ui-death { gap: calc( 2 * var( --px ) ); }
  .ui-death-groups { flex-direction: row; align-items: flex-start; gap: calc( 10 * var( --px ) ); }
  .ui-death-items { grid-template-columns: auto auto auto; }
  .ui-death-items > .ui-death-item > :nth-child( 4 ) { display: none; }
}
.ui-death-pack { display: grid; grid-template-columns: auto auto auto auto; gap: calc( 1 * var( --px ) ) calc( 4 * var( --px ) ); align-items: center; line-height: 0; }
/* corpse items: the icon fitted to a small square, tinted and outlined in its rarity colour */
.ui-death-icon { position: relative; justify-self: center; cursor: default; outline: var( --px ) solid rgba( 240, 230, 198, 0.25 ); }
.ui-death-icon:not( .ui-item ) { outline: none; width: calc( 12 * var( --px ) ); height: calc( 1 * var( --px ) ); }
.ui-death-icon.r-magic { outline-color: rgba( 188, 202, 223, 0.8 ); }
.ui-death-icon.r-rare { outline-color: rgba( 255, 200, 69, 0.9 ); }
.ui-death-icon.r-unique { outline-color: rgba( 232, 128, 30, 0.95 ); }
.ui-death-icon:hover .ui-item-bg { background: rgba( 5, 4, 15, 0.35 ); }
.ui-death-where, .ui-death-recall { display: flex; align-items: center; gap: calc( 4 * var( --px ) ); line-height: 0; }
.ui-rise { pointer-events: auto; }

/* Boss intro title card. */
.ui-card { position: absolute; left: 0; right: 0; top: 30%; display: flex; flex-direction: column; align-items: center; gap: calc( 4 * var( --px ) ); filter: drop-shadow( 0 calc( 2 * var( --px ) ) 0 var( --void ) ); opacity: 0; }
.ui-card.show { animation: card-in 1.8s steps( 12 ) both; } /* screens.js BOSS_CARD; a shorter intro shortens it inline */
@keyframes card-in { 0% { opacity: 0; translate: 0 calc( 4 * var( --px ) ); } 12% { opacity: 1; translate: 0 0; } 80% { opacity: 1; } 100% { opacity: 0; } }
.ui-card.hold { animation: none; opacity: 1; }
.ui-card-epithet { margin-top: calc( -1 * var( --px ) ); }

/* Level-up toast. */
.ui-levelup { position: absolute; left: 0; right: 0; top: 16%; display: flex; flex-direction: column; align-items: center; gap: calc( 3 * var( --px ) ); filter: drop-shadow( 0 calc( 2 * var( --px ) ) 0 var( --void ) ); opacity: 0; }
.ui-levelup.show { animation: level-in 3s ease-out both; }
@keyframes level-in { 0% { opacity: 0; translate: 0 calc( 6 * var( --px ) ); } 10% { opacity: 1; translate: 0 0; } 75% { opacity: 1; } 100% { opacity: 0; } }
.ui-levelup.hold { animation: none; opacity: 1; }
.ui-level-sub { display: flex; align-items: center; gap: calc( 3 * var( --px ) ); line-height: 0; }
/* Under Hellcharge's held aim: how to cancel it ( screens.js updateAimHint ). */
.ui-aim-hint { position: absolute; left: 0; top: 0; transform: translateX( round( -50%, var( --dpx, 1px ) ) ); pointer-events: none; line-height: 0; --px: var( --tpx, 2px ); filter: drop-shadow( 0 var( --px ) 0 var( --void ) ); }
.ui-aim-hint.above { transform: translate( round( -50%, var( --dpx, 1px ) ), -100% ); } /* touch: its bottom edge sits on the Ability button's top */
/* The Ascendancy reveal ( once ): below the level-up toast, as long as the card holds ( 5 s ). */
.ui-ascend { position: absolute; left: 0; right: 0; top: 34%; display: flex; flex-direction: column; align-items: center; gap: calc( 3 * var( --px ) ); pointer-events: none; filter: drop-shadow( 0 calc( 2 * var( --px ) ) 0 var( --void ) ); opacity: 0; }
.ui-ascend.show { opacity: 1; animation: ascend-in 5s ease-out both; }
@keyframes ascend-in { 0% { opacity: 0; translate: 0 calc( 6 * var( --px ) ); } 8% { opacity: 1; translate: 0 0; } 85% { opacity: 1; } 100% { opacity: 0; } }
.ui-screens.calm .ui-ascend.show { animation: none; }
/* The world dims behind it ( the death vignette at half strength, 0.3 s in and out ), and the other
   overlays stand down while it is up: First Steps, the pickup and screen toasts, the level-up and zone cards
   ( the reload prompt stays: it is play ). */
.ui-ascend-dim { position: absolute; inset: 0; pointer-events: none; opacity: 0; transition: opacity 0.3s ease-out;
  background: radial-gradient( ellipse at 50% 45%, rgba( 58, 13, 22, 0.3 ), rgba( 5, 4, 15, 0.6 ) 75% ); }
.ui-ascend-dim.show { opacity: 1; }
.ui-screens.calm .ui-ascend-dim { transition: none; }
#hud:has( .ui-ascend:not( [hidden] ) ) :is( .ui-hints, .hud-msg, .ui-storage, .ui-levelup, .ui-zonecard ) { visibility: hidden; }
.ui-ascend-trees { display: flex; gap: calc( 10 * var( --px ) ); line-height: 0; }

/* Save indicator ( top right ) and the storage-error toast ( top centre, blood banner ). */
.ui-save { position: absolute; right: calc( 6 * var( --px ) ); top: calc( 6 * var( --px ) ); display: flex; align-items: center; gap: calc( 3 * var( --px ) ); line-height: 0; filter: drop-shadow( 0 var( --px ) 0 var( --void ) ); }
.ui-save.busy .spr { animation: seal-pulse 0.9s steps( 3 ) infinite; }
@keyframes seal-pulse { 50% { filter: brightness( 1.5 ); } }
.ui-screens.calm .ui-save.busy .spr { animation: none; }
.ui-storage { position: absolute; left: round( 50%, var( --dpx, 1px ) ); top: calc( 10 * var( --px ) ); transform: translateX( round( -50%, var( --dpx, 1px ) ) ); --px: var( --tpx, 2px ); }
.ui-storage.error { height: auto; padding: calc( 5 * var( --px ) ) calc( 6 * var( --px ) ) calc( 9 * var( --px ) ); }
.ui-storage-text { display: flex; flex-direction: column; align-items: center; gap: calc( 2 * var( --px ) ); line-height: 0; }

/* Floor-loot plates: hidden until Alt ( or hover / fresh Rare+ ); world-positioned by screens.js. */
.ui-loot { position: absolute; inset: 0; --px: var( --tpx, 2px ); }
.ui-plate { position: absolute; left: 0; top: 0; pointer-events: none; cursor: pointer; line-height: 0; padding: var( --px ) calc( 2 * var( --px ) );
  border-width: calc( 3 * var( --px ) ); border-image: var( --ui-plate ) 3 fill / calc( 3 * var( --px ) ) stretch; opacity: 0; transition: opacity 0.1s; }
.ui-plate.show { opacity: 0.92; pointer-events: auto; }
.ui-plate.hot { opacity: 1; border-image-source: var( --ui-plate-hot ); }
/* desktop: Alt / Shift plates fade in over 150 ms, and every plate hides at once ( a shot clears them ) */
body:not( [data-input='touch'] ) .ui-loot.alt .ui-plate.show { transition: opacity 0.15s ease-out; }
body:not( [data-input='touch'] ) .ui-plate:not( .show ) { transition: none; }
.ui-plate { display: flex; gap: calc( 3 * var( --px ) ); align-items: center; }
.ui-plate .ui-plate-rarity { display: none; }
/* the item level: on the Shift reveal ( held, not firing, 3 s: screens.js .ilvl ) */
.ui-plate .ui-plate-il { display: none; }
.ui-loot.ilvl .ui-plate .ui-plate-il { display: inline-block; }
/* the rarity gem: the name's colour is the level gap, so rarity reads from here ( and the Rare / Unique glow ) */
.ui-plate-gap { flex: none; margin-left: calc( -1 * var( --px ) ); }
.ui-plate-gap.none { display: none; }
.ui-plate-gem { flex: none; width: calc( 4 * var( --px ) ); height: calc( 4 * var( --px ) ); rotate: 45deg; background: #cfbc96; box-shadow: 0 0 0 var( --px ) #150f26; }
.ui-plate.r-magic .ui-plate-gem { background: #6e8fd8; }
.ui-plate.r-rare .ui-plate-gem { background: #ffc845; }
.ui-plate.r-unique .ui-plate-gem { background: #e8801e; box-shadow: 0 0 0 var( --px ) #150f26, 0 0 calc( 2 * var( --px ) ) #e8801e; }
.ui-plate.hot .ui-plate-rarity, .ui-loot.alt .ui-plate.r-unique .ui-plate-rarity, .ui-loot.alt .ui-plate.r-rare .ui-plate-rarity { display: inline-block; }
/* ( no rarity glow on the plate itself: the gem alone carries rarity, clear of the level-gap orange and red ) */

/* Trash slot ( inventory foot ): an iron grate over embers; drop an item on it to sell it to the fire.
   Rare and Unique ask first ( .ui-confirm, Keep focused ); "+N gold" rises from the grate. */
.ui-trash { position: relative; width: calc( 22 * var( --px ) ); height: calc( 22 * var( --px ) ); flex: none; filter: var( --hard-drop ); }
.ui-trash[hidden] { display: none; }
.ui-trash .spr { position: absolute; left: round( 50%, var( --dpx, 1px ) ); top: round( 50%, var( --dpx, 1px ) ); translate: round( -50%, var( --dpx, 1px ) ) round( -50%, var( --dpx, 1px ) ); }
.ui-trash .hot, .ui-trash.on .rest { display: none; }
.ui-trash.on .hot { display: block; }
.ui-confirm { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; background: rgba( 5, 4, 15, 0.6 ); pointer-events: auto; z-index: 8; --px: var( --tpx, 2px ); }
.ui-confirm[hidden] { display: none; }
.ui-confirm-card { display: flex; flex-direction: column; align-items: center; gap: calc( 6 * var( --px ) ); padding: calc( 6 * var( --px ) ) calc( 10 * var( --px ) );
  border-width: calc( 7 * var( --px ) ); border-image: var( --ui-panel ) 7 fill / calc( 7 * var( --px ) ) stretch; }
.ui-confirm-line { display: flex; align-items: flex-end; flex-wrap: wrap; justify-content: center; max-width: calc( 300 * var( --px ) ); }
.ui-confirm-acts { display: flex; gap: calc( 6 * var( --px ) ); }
.ui-gold-float { position: absolute; translate: -50% -100%; pointer-events: none; z-index: 7; --px: var( --tpx, 2px ); animation: gold-rise 1.1s steps( 8 ) both; }
@keyframes gold-rise { 0% { translate: -50% -100%; opacity: 1; } 70% { opacity: 1; } 100% { translate: -50% calc( -100% - 18 * var( --px ) ); opacity: 0; } }
.ui-screens.calm .ui-gold-float { animation-timing-function: steps( 2 ); }

/* The death panel owns the screen: the automap's corner map and chip step aside while it is up. */
#hud:has( .ui-death:not( [hidden] ) ) > .automap-corner, #hud:has( .ui-death:not( [hidden] ) ) > .automap-chip { display: none; }

.ui-loot.quiet .ui-plate { opacity: 0; pointer-events: none; } /* a boss or zone card is playing */
/* a screen is open: the world's labels would only crowd its frame ( they take no input meanwhile ) */
body.ui-screen-open .ui-loot, body.ui-screen-open .ui-wp-prompt { visibility: hidden; }

/* Front door ( src/ui/front.js ): title, loading veil, slice-complete card, first-time hints.
   --fpx is one front art px: the largest whole device px at which the 640 × 360 front grid fits
   ( 3 at 1080p, 2 at 720p ). The backdrop and the particle canvas cover the window at a whole
   multiple of it; the logotype and title buttons are sized in it. Settings / Controls keep the
   pause menu's --px. */

body.ui-front-open #pause { display: none !important; }
/* The HUD is not styled while the front covers it: the boot veil ( ui-boot ) and the title. Hidden
   ( not visibility ), its ~100 nodes skip every style pass of the boot, about 130 ms at CPU ×4 on a
   phone; they are styled once, when the front closes. The end card shows the HUD beneath it. */
body.ui-boot #hud, body.ui-front-open:not( .front-slice ) #hud { display: none; }

.front { position: fixed; inset: 0; z-index: 20; overflow: hidden; cursor: default; color: var( --bone2 ); }
.front[hidden], .front [hidden] { display: none !important; }
.front.scenic { background: var( --void ); }
.front-bg { position: absolute; left: 50%; top: 50%; translate: -50% -50%; background: var( --ui-front-backdrop ) 0 0 / 100% 100% no-repeat; image-rendering: pixelated; }
.front-fx { position: absolute; inset: 0; width: 100%; height: 100%; image-rendering: pixelated; }
/* the sunny title ( front.js setScene ): its backdrop comes with the gilt sheet ( front-sunny.js installGilt ), the void until it lands */
.front[data-scene="sunny"] { --ui-front-backdrop: var( --ui-sunny-backdrop, none ); }

.front-stage { --px: var( --fpx ); position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; padding-top: calc( 22 * var( --px ) ); gap: calc( 10 * var( --px ) ); box-sizing: border-box; }
.front-logo { display: flex; flex-direction: column; align-items: center; gap: calc( 2 * var( --px ) ); filter: drop-shadow( 0 calc( 2 * var( --px ) ) 0 rgba( 5, 4, 15, 0.7 ) ); }
.front-logo-sub { margin-top: calc( 1 * var( --px ) ); }

.front-menu { display: flex; flex-direction: column; align-items: stretch; gap: calc( 4 * var( --px ) ); margin-top: calc( 8 * var( --px ) ); }
.front-btn { flex-direction: column; gap: calc( 1 * var( --px ) ); min-width: calc( 132 * var( --px ) ); }
.front-btn-label { display: flex; }
.front-btn.is-focus .rest { display: none; }
.front-btn.is-focus .hot { display: inline-block; }
.front-btn.is-focus { border-image-source: var( --ui-button-hot ); }
.front-btn.is-focus::before { content: ''; position: absolute; left: calc( -14 * var( --px ) ); top: 50%; width: calc( 7 * var( --px ) ); height: calc( 7 * var( --px ) ); translate: 0 -50%;
  background: var( --ui-fleur ) 0 0 / 100% 100% no-repeat; image-rendering: pixelated; animation: fleur 1.2s steps( 2 ) infinite; }
.front-btn:disabled { cursor: default; border-image-source: var( --ui-button-off ); }
.front-btn:disabled:hover .rest { display: inline-block; }
.front-btn:disabled:hover .hot, .front-btn:disabled .hot { display: none; }
.front-btn:disabled:active { translate: none; }
/* A thumb's target on a phone: at least 44 CSS px tall ( the 9-slice stretches ). */
@media ( pointer: coarse ) { .front-btn { min-height: 44px; } }
.front-foot { position: absolute; bottom: calc( 8 * var( --px ) ); left: 0; right: 0; display: flex; justify-content: center; }

/* New Game confirmation: the pause panel's frame, at the front's pixel size. */
.front-confirm { margin-top: calc( 4 * var( --px ) ); min-width: calc( 220 * var( --px ) ); gap: calc( 4 * var( --px ) ); }
.front-confirm-btns { display: flex; gap: calc( 8 * var( --px ) ); margin-top: calc( 4 * var( --px ) ); }
.front-confirm-btns .front-btn { min-width: calc( 96 * var( --px ) ); }

/* Loading: the logotype, a line of flavour and a forged bar; determinate from main.js's --load-progress, else a sweep. */
.front-loading { display: flex; flex-direction: column; align-items: center; gap: calc( 4 * var( --px ) ); margin-top: calc( 40 * var( --px ) ); }
.front-bar { position: relative; width: calc( 160 * var( --px ) ); height: calc( 11 * var( --px ) ); border-width: calc( 4 * var( --px ) ) calc( 5 * var( --px ) ); border-image: var( --ui-bar-frame ) 4 5 fill / calc( 4 * var( --px ) ) calc( 5 * var( --px ) ) stretch; overflow: hidden; }
.front-bar-fill { position: absolute; top: 0; bottom: 0; left: 0; width: 28%; background: var( --ui-load-fill ) 0 0 / 100% 100% no-repeat; image-rendering: pixelated; animation: front-load 1.6s steps( 24 ) infinite; }
.front-loading.known .front-bar-fill { animation: none; width: calc( var( --load-progress, 0 ) * 100% ); transition: width 0.2s steps( 8 ); }
@keyframes front-load { from { translate: -100% 0; } to { translate: 360% 0; } }

/* Slice complete: a dimmed playfield and a framed card. */
.front-card { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; background: rgba( 8, 5, 14, 0.72 ); --px: var( --fpx ); }
.front-card-panel { min-width: calc( 230 * var( --px ) ); gap: calc( 4 * var( --px ) ); padding-top: calc( 10 * var( --px ) ); }
.front-seal { position: absolute; left: round( 50%, var( --dpx, 1px ) ); top: calc( -36 * var( --px ) ); translate: round( -50%, var( --dpx, 1px ) ) 0; filter: drop-shadow( 0 0 calc( 3 * var( --px ) ) rgba( 232, 128, 30, 0.55 ) ); }
/* A card too tall for the window ( its zone rows and its find's height: front.js fitCard steps data-fit
   up until the seal and the frame are on screen ). 1: a tighter panel set lower, centred with the seal
   over it; 2: the rows close up and the panel's gaps halve, the copy all kept; 3: the closing divider
   and line go; 4 ( seven rows over a tall find ): the find goes unlabelled. */
.front-card[data-fit] { padding-top: calc( 16 * var( --px ) ); }
.front-card[data-fit] .front-card-panel { gap: calc( 2 * var( --px ) ); padding-top: 0; }
.front-card[data-fit] .front-zones { row-gap: calc( 1 * var( --px ) ); }
.front-card[data-fit] .front-stats { margin: 0; }
.front-card:is( [data-fit="2"], [data-fit="3"], [data-fit="4"] ) .front-card-panel { gap: calc( 1 * var( --px ) ); }
.front-card:is( [data-fit="2"], [data-fit="3"], [data-fit="4"] ) .front-zones { row-gap: 0; }
.front-card:is( [data-fit="3"], [data-fit="4"] ) .front-best ~ :not( .front-confirm-btns ) { display: none; }
.front-card[data-fit="4"] .front-best > :first-child { display: none; }
.front-stats { display: grid; grid-template-columns: repeat( 3, auto ); gap: 0 calc( 14 * var( --px ) ); margin: calc( 2 * var( --px ) ) 0; }
.front-stat { display: flex; flex-direction: column; align-items: center; gap: calc( 2 * var( --px ) ); }
/* After the ogre: a row per zone ( name, time, kills ), above the totals. */
.front-zones { display: grid; grid-template-columns: auto auto auto; gap: calc( 2 * var( --px ) ) calc( 12 * var( --px ) ); align-items: center; line-height: 0; margin-top: calc( 1 * var( --px ) ); }
.front-zone-cell.num { justify-self: end; }
.front-best { display: flex; flex-direction: column; align-items: center; gap: calc( 3 * var( --px ) ); }
.front-find { display: flex; align-items: center; gap: calc( 6 * var( --px ) ); }
.front-find-icon { position: relative; flex: none; cursor: default; }
.front-find-text { display: flex; flex-direction: column; gap: calc( 2 * var( --px ) ); }

/* Settings / Controls from the title: the pause menu's panel over the backdrop. */
.front-pages { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; background: rgba( 8, 5, 14, 0.55 ); font-size: max( 15px, calc( 8 * var( --px ) ) ); }

/* First-time controls hints: bottom-centre of the playfield, above the skill tray ( 58 HUD px tall:
   the bottom clears it in --hpx, since the HUD px outgrows --tpx on wide 1440p windows ). */
#hud > .ui-hints { --px: var( --tpx, 2px ); left: round( 50%, var( --dpx, 1px ) ); bottom: max( calc( 60 * var( --px ) ), calc( 62 * var( --hpx, 0px ) ) ); translate: round( -50%, var( --dpx, 1px ) ) 0; display: flex; flex-direction: column; gap: calc( 3 * var( --px ) ); padding: calc( 4 * var( --px ) ) calc( 8 * var( --px ) );
  border-width: calc( 7 * var( --px ) ); border-image: var( --ui-panel ) 7 fill / calc( 7 * var( --px ) ) stretch; filter: var( --hard-drop ); }
#hud > .ui-hints.gone { opacity: 0; transition: opacity 1.2s steps( 4 ) 0.3s; }
/* timed out after 8 s on screen ( front.js stepHints ): a smooth 0.6 s fade that takes no input */
#hud > .ui-hints.timeout { opacity: 0; transition: opacity 0.6s ease-out; pointer-events: none; }
.ui-hints-title { align-self: center; margin-bottom: calc( 1 * var( --px ) ); }
.ui-hint-row { display: grid; grid-template-columns: calc( 44 * var( --px ) ) auto calc( 9 * var( --px ) ); align-items: center; gap: calc( 5 * var( --px ) ); }
.ui-hint-keys { display: flex; align-items: center; justify-content: flex-end; gap: calc( 2 * var( --px ) ); }
.ui-hint-pending { width: calc( 5 * var( --px ) ); height: calc( 5 * var( --px ) ); justify-self: center; background: var( --umbra ); box-shadow: 0 0 0 var( --px ) var( --void ); }
body.ui-screen-open #hud > .ui-hints, #hud > .ui-hints[hidden], #hud:has( .ui-death:not( [hidden] ) ) > .ui-hints { display: none; }
/* a zone or boss title card is playing ( screens.js quietPlates, as the floor plates ): the panel would cross it */
#hud:has( .ui-loot.quiet ) > .ui-hints { visibility: hidden; }
/* the pause menu is up: on a phone its panel would cross the card */
body:has( > #pause:not( [hidden] ) ) #hud.touch > .ui-hints { visibility: hidden; }

/* Touch controls ( src/ui/touch.js ): only for body[data-input=touch]. --cpx is one control art px
   ( a whole number of device px ); controls are placed by translate() from their centre, so each
   box is pulled back by half its size. --hit is a control's hit box ( at least 44 CSS px ). At rest
   the controls sit at --alpha; a pressed control is opaque and swaps to its soul-fire frame. */

.touch-layer { position: fixed; inset: 0; pointer-events: none; --cpx: 2px; --px: var( --cpx ); --alpha: 0.75; touch-action: none; -webkit-user-select: none; -webkit-touch-callout: none; }
.touch-layer[hidden], body:not( [data-input="touch"] ) .touch-layer { display: none; }
.touch-layer .spr, .touch-turn .spr { display: block; flex: none; image-rendering: pixelated; background-repeat: no-repeat; background-size: 100% 100%; }
.touch-layer .hot { display: none; }
.touch-layer .on > .hot, .touch-layer .on > .touch-knob > .hot, .touch-stick.on > .touch-ring.hot { display: block; }
.touch-layer .on > .rest, .touch-layer .on > .touch-knob > .rest, .touch-stick.on > .touch-ring:not( .hot ) { display: none; }

.touch-zone { position: absolute; pointer-events: auto; touch-action: none; }

/* Sticks: the iron ring with its bone knob; the move stick rests as a faint ghost until a thumb lands. */
.touch-stick { position: absolute; left: 0; top: 0; width: calc( 56 * var( --cpx ) ); height: calc( 56 * var( --cpx ) ); margin: calc( -28 * var( --cpx ) ) 0 0 calc( -28 * var( --cpx ) );
  opacity: var( --alpha ); filter: drop-shadow( 0 var( --cpx ) 0 var( --void ) ); }
.touch-stick > .touch-ring { position: absolute; left: 0; top: 0; }
.touch-knob { position: absolute; left: calc( 15 * var( --cpx ) ); top: calc( 15 * var( --cpx ) ); width: calc( 26 * var( --cpx ) ); height: calc( 26 * var( --cpx ) ); }
.touch-stick.move { pointer-events: none; opacity: calc( var( --alpha ) * 0.55 ); }
.touch-stick.on { opacity: 1; }
/* Fire: the big button in the corner ( about 84 CSS px ); held, its soul-fire rim flickers; dragged, it aims by hand. */
.touch-btn.fire.on .hot { animation: touch-fire 0.24s steps( 2 ) infinite; }
.touch-btn.fire .touch-icon { width: calc( 23 * var( --cpx ) ) !important; height: calc( 23 * var( --cpx ) ) !important; }
.touch-btn.aiming .touch-icon { scale: 0.85; }
@keyframes touch-fire { 50% { filter: brightness( 1.25 ); } }
.touch-btn.small { opacity: calc( var( --alpha ) * 0.8 ); }
/* The soft lock on the auto-target ( a tapped lock stays lit ), and the drag-to-aim line from Pepecat. */
.touch-reticle { position: absolute; left: 0; top: 0; pointer-events: none; opacity: 0.8; animation: touch-lock 0.9s steps( 3 ) infinite; }
.touch-reticle.tapped { opacity: 1; animation: none; }
.touch-reticle[hidden], .touch-aim-line[hidden] { display: none; }
@keyframes touch-lock { 50% { scale: 1.12; } }
.touch-aim-line { position: absolute; height: calc( 3 * var( --cpx ) ); margin-top: calc( -1.5 * var( --cpx ) ); transform-origin: 0 50%; pointer-events: none; opacity: 0.85;
  background: var( --ui-touch-aim-dot ) 0 0 / calc( 6 * var( --cpx ) ) 100% repeat-x; image-rendering: pixelated;
  mask-image: linear-gradient( 90deg, transparent calc( 10 * var( --cpx ) ), #000 calc( 14 * var( --cpx ) ), #000 70%, transparent ); }
/* Flask: low health pulses it while a charge is left. */
.touch-btn.low { opacity: 1; animation: touch-low 0.8s steps( 2 ) infinite; }
.touch-btn.low .hot { display: block; }
.touch-btn.low .rest { display: none; }
@keyframes touch-low { 50% { scale: 1.08; } }

/* Thumb buttons: round iron frames ( Dodge the large one ), the pictogram centred, a cooldown sweep. */
.touch-btn { position: absolute; left: 0; top: 0; width: var( --hit ); height: var( --hit ); margin: calc( var( --hit ) / -2 ) 0 0 calc( var( --hit ) / -2 ); border-radius: 50%;
  display: flex; align-items: center; justify-content: center; pointer-events: auto; touch-action: none; opacity: var( --alpha ); filter: drop-shadow( 0 var( --cpx ) 0 var( --void ) ); --cd: 0; }
.touch-btn[hidden] { display: none; }
.touch-btn > .spr { position: absolute; left: round( 50%, var( --dpx, 1px ) ); top: round( 50%, var( --dpx, 1px ) ); translate: round( -50%, var( --dpx, 1px ) ) round( -50%, var( --dpx, 1px ) ); }
.touch-btn.on { opacity: 1; scale: 0.94; }
.touch-cd { position: absolute; left: round( 50%, var( --dpx, 1px ) ); top: round( 50%, var( --dpx, 1px ) ); width: calc( 26 * var( --cpx ) ); height: calc( 26 * var( --cpx ) ); translate: round( -50%, var( --dpx, 1px ) ) round( -50%, var( --dpx, 1px ) ); border-radius: 50%;
  background: conic-gradient( transparent 0 calc( ( 1 - var( --cd ) ) * 360deg ), rgba( 5, 4, 15, 0.8 ) 0 ); pointer-events: none; }
.touch-btn.lg .touch-cd { width: calc( 28 * var( --cpx ) ); height: calc( 28 * var( --cpx ) ); }
.touch-btn.cooling .touch-icon, .touch-btn.empty .touch-icon { filter: brightness( 0.6 ); }
.touch-btn.locked .touch-icon { filter: grayscale( 1 ) brightness( 0.45 ); }
.touch-btn .touch-lock { z-index: 1; }
.touch-btn .touch-lock[hidden] { display: none; }
.touch-btn.busy .touch-icon { animation: touch-busy 0.6s steps( 4 ) infinite; }
@keyframes touch-busy { to { rotate: 1turn; } }
.touch-count { position: absolute; right: calc( 50% - 14 * var( --cpx ) ); bottom: calc( 50% - 14 * var( --cpx ) ); }
.touch-btn[data-ctl="interact"] .touch-icon { animation: touch-beckon 1.2s steps( 2 ) infinite; }
@keyframes touch-beckon { 50% { translate: -50% calc( -50% - var( --cpx ) ); } }

/* Portrait: "Turn your device", over everything, on touch ( or any coarse pointer before a first touch ). */
.touch-turn { display: none; position: fixed; inset: 0; z-index: 40; align-items: center; justify-content: center; background: rgba( 5, 4, 15, 0.94 ); --px: var( --cpx, 2px ); touch-action: none; }
body[data-orientation="portrait"][data-input="touch"] .touch-turn { display: flex; }
@media ( pointer: coarse ) { body[data-orientation="portrait"] .touch-turn { display: flex; } }
.touch-turn-card { display: flex; flex-direction: column; align-items: center; gap: calc( 8 * var( --px ) ); max-width: calc( 100vw - 24px );
  padding: calc( 10 * var( --px ) ) calc( 14 * var( --px ) ); border-width: calc( 7 * var( --px ) ); border-image: var( --ui-panel ) 7 fill / calc( 7 * var( --px ) ) stretch; }
.touch-turn-art { display: flex; align-items: center; gap: calc( 6 * var( --px ) ); }
.touch-turn-from { animation: touch-turn 2.4s steps( 1 ) infinite; }
.touch-turn-arrow { animation: touch-spin 2.4s steps( 8 ) infinite; }
.touch-turn-to { animation: touch-turn 2.4s steps( 1 ) infinite reverse; }
@keyframes touch-turn { 0%, 49% { opacity: 1; } 50%, 100% { opacity: 0.25; } }
@keyframes touch-spin { 0%, 40% { rotate: 0deg; } 60%, 100% { rotate: 90deg; } }
.touch-turn-face { position: relative; width: calc( 60 * var( --px ) ); height: calc( 60 * var( --px ) ); background: var( --umbra ); filter: var( --hard-drop ); }
.touch-turn-face::after { content: ''; position: absolute; inset: 0; background: var( --ui-portrait-frame ) 0 0 / 100% 100% no-repeat; image-rendering: pixelated; }
@media ( prefers-reduced-motion: reduce ) { .touch-turn .spr, .touch-layer .touch-icon { animation: none !important; } }

/* ---- the HUD and the screens under touch ( #hud.touch, set by hud.js layout ) -------------------- */

/* The thumb controls own the bottom corners: the orb moves to the top-left with the powerups under
   it, the magazine along the top edge beside the orb ( out of the floor's lower middle ); the slots ( now thumb buttons ), portrait and plinth go. */
#hud.touch .hud-plinth, #hud.touch .hud-skills, #hud.touch .hud-portrait, #hud.touch .hud-weapon { display: none; }
/* the health orb in the screen's top-left corner ( the user's call; not the letterboxed playfield's ),
   clear of the safe area; its powerup timers under it. The minimap and icon row take the top edge's
   right end ( touch.js publishes them ). */
#hud.touch .hud-left { position: fixed; top: calc( var( --safe-top, 0px ) + 2 * var( --px ) ); bottom: auto; left: calc( var( --safe-left, 0px ) + 2 * var( --px ) ); }
#hud.touch .hud-center { position: fixed; left: calc( var( --safe-left, 0px ) + 4 * var( --px ) ); top: calc( var( --safe-top, 0px ) + 106 * var( --px ) ); bottom: auto; transform: none; align-items: flex-start; }
#hud.touch .hud-right { position: fixed; right: auto; left: calc( var( --safe-left, 0px ) + 101 * var( --px ) ); top: calc( var( --safe-top, 0px ) + 4 * var( --px ) ); bottom: auto; flex-direction: row; align-items: flex-start; gap: calc( 3 * var( --px ) ); }

/* Panels scroll inside the frame; items, nodes and sockets take the finger themselves. */
#hud.touch .ui-panel { max-height: calc( 100% - 8px ); overflow-y: auto; overscroll-behavior: contain; touch-action: pan-y; scrollbar-width: none; }
#hud.touch .ui-item, #hud.touch .ui-node, #hud.touch .ui-socket, #hud.touch .ui-grid-field, #hud.touch .ui-plate { touch-action: none; }
#hud.touch .ui-inv, #hud.touch .ui-talents, #hud.touch .ui-map { top: 4px; }
#hud.touch .ui-travel { top: 4px; }
#hud.touch .ui-wp, #hud.touch .ui-map-zone, #hud.touch .ui-wp-prompt { min-height: 44px; }
#hud.touch .ui-inv { left: round( 50%, var( --dpx, 1px ) ); right: auto; translate: round( -50%, var( --dpx, 1px ) ) 0; }
#hud.touch .with-stash .ui-inv, #hud.touch .with-stash .ui-stash { left: round( 50%, var( --dpx, 1px ) ); right: auto; translate: round( -50%, var( --dpx, 1px ) ) 0; top: calc( 4px + var( --tab-h, 52px ) ); max-height: calc( 100% - 8px - var( --tab-h, 52px ) ); }
#hud.touch .ui-screens[data-tab="pack"] .ui-stash, #hud.touch .ui-screens[data-tab="stash"] .ui-inv { display: none; }
#hud.touch .ui-map { --px: calc( var( --spx ) * 1.5 ); }
#hud.touch .ui-map-view { max-width: 100%; max-height: calc( 100vh - 120px ); overflow: hidden; touch-action: none; }
/* The map view takes what the title, the zone tabs and the legend leave ( it pans by drag ), so the
   zone tabs never squeeze it to a sliver; short phones set the map's text a little smaller. */
#hud.touch .ui-map { overflow: hidden; max-width: calc( 100% - 2 * 60px ); } /* clear of the close X ( 48 px, 4 px in ) on both sides: it stays centred */
#hud.touch .ui-map > * { flex-shrink: 0; }
#hud.touch .ui-map > .ui-map-view { flex: 1 1 auto; min-height: 96px; max-height: none; }
@media ( max-height: 520px ) {
  #hud.touch .ui-map { --px: calc( var( --spx ) * 1.15 ); gap: calc( 2 * var( --px ) ); }
}
.ui-item.selected { outline: calc( 1 * var( --px ) ) solid var( --flame2 ); outline-offset: calc( -1 * var( --px ) ); }

/* The close X: large, in the frame's top-right corner, inside the insets. */
.ui-close { position: absolute; right: 4px; top: 4px; width: 48px; height: 48px; display: flex; align-items: center; justify-content: center; pointer-events: auto; touch-action: none; z-index: 6;
  border-width: calc( 5 * var( --px ) ); border-image: var( --ui-panel ) 7 fill / calc( 7 * var( --px ) ) stretch; box-sizing: border-box; --px: var( --tpx, 2px ); }
.ui-close[hidden] { display: none; }
.ui-close .spr { width: 30px !important; height: 30px !important; }

/* Pack / Stash tabs, top-centre, only when the stash is open. */
.ui-tabs { position: absolute; left: round( 50%, var( --dpx, 1px ) ); top: 4px; translate: round( -50%, var( --dpx, 1px ) ) 0; display: flex; gap: 6px; pointer-events: auto; z-index: 6; --px: var( --tpx, 2px ); }
.ui-tabs[hidden] { display: none; }
.ui-tab { min-width: 96px; min-height: 44px; display: flex; align-items: center; justify-content: center; touch-action: none;
  border-width: calc( 5 * var( --px ) ); border-image: var( --ui-button ) 5 fill / calc( 5 * var( --px ) ) stretch; opacity: 0.7; }
.ui-tab.on { border-image-source: var( --ui-button-hot ); opacity: 1; }

/* The sheet: the tapped item's or node's cards with explicit actions, fixed at the frame's side. */
.ui-sheet { position: absolute; right: 4px; top: 56px; bottom: 4px; max-width: 46%; display: flex; flex-direction: column; gap: 6px; pointer-events: auto; z-index: 6;
  overflow-y: auto; overscroll-behavior: contain; touch-action: pan-y; scrollbar-width: none; --px: var( --tpx, 2px ); padding: 4px; background: rgba( 5, 4, 15, 0.86 ); }
.ui-sheet[hidden] { display: none; }
.ui-sheet-cards { display: flex; flex-direction: column; gap: calc( 3 * var( --px ) ); }
.ui-sheet-acts { position: sticky; top: 0; z-index: 1; display: flex; flex-wrap: wrap; gap: 6px; }
.ui-sheet .ui-act { min-height: 44px; min-width: 88px; }
/* Hellcharge's card ( M2b ): held to the sheet's height, the rank table on top, the text scrolling under it. */
.ui-sheet:has( .ui-tipcard.hc ) { overflow: hidden; }
.ui-sheet:has( .ui-tipcard.hc ) .ui-sheet-cards { flex: 1 1 auto; min-height: 0; }
.ui-tipcard.hc { min-height: 0; flex: 0 1 auto; }
.ui-tipcard.hc .ui-hc-table { flex: none; }
.ui-tip-scroll { min-height: 0; flex: 0 1 auto; overflow-y: auto; overscroll-behavior: contain; touch-action: pan-y; scrollbar-width: none; display: flex; flex-direction: column; align-items: center; gap: calc( 1 * var( --px ) ); }

/* Front door and pause menu: thumb-sized buttons; the panel still scrolls if a page outgrows the screen. */
body[data-input="touch"] .menu-btn, body[data-input="touch"] .menu-ctl, body[data-input="touch"] .front-btn { min-height: 44px; }
body[data-input="touch"] .menu-ctl { min-width: 44px; }
body[data-input="touch"] :is( .menu-group, .menu-touch ) { display: flex; flex-direction: column; gap: 4px; } /* never two row targets closer than 4 px */
body[data-input="touch"] .menu-panel { max-height: calc( 100vh - var( --safe-top, 0px ) - var( --safe-bottom, 0px ) - 8px ); overflow-y: auto; overscroll-behavior: contain; touch-action: pan-y; }
/* The crest and the seal stand above the frame, so those frames never clip: the pause menu's pages scroll inside
   theirs instead ( short-screen settings, crest hidden, below ), and the end card fits itself ( front.js fitCard ). */
body[data-input="touch"] :is( #pause .menu-panel, .front-card-panel ) { overflow: visible; }
body[data-input="touch"] #pause .menu-page:not( [data-page="settings"] ) { min-height: 0; overflow-y: auto; overscroll-behavior: contain; touch-action: pan-y; }
body[data-input="touch"] #pause .menu-page[data-page="controls"] > .menu-footer { position: sticky; bottom: 0; z-index: 1; margin-top: 0; padding-top: calc( 2 * var( --px ) ); background: var( --umbra ); } /* Back stays in view while the rows scroll under it */
/* while more rows lie below ( .more, menu.js ): a 3-step fade into the panel fill above Back, 2 art px a step */
body[data-input="touch"] #pause .menu-page[data-page="controls"] > .menu-footer::before { content: ''; position: absolute; left: 0; right: 0; bottom: 100%; height: calc( 6 * var( --px ) ); pointer-events: none; visibility: hidden;
  background: linear-gradient( to top, var( --umbra ) 0 calc( 2 * var( --px ) ), rgb( 43 37 64 / 0.66 ) 0 calc( 4 * var( --px ) ), rgb( 43 37 64 / 0.33 ) 0 ); }
body[data-input="touch"] #pause .menu-page[data-page="controls"].more > .menu-footer::before { visibility: visible; }
body[data-input="touch"] #pause .menu-panel:not( :has( > [data-page="settings"]:not( [hidden] ) ) ) { max-height: calc( 100vh - var( --safe-top, 0px ) - var( --safe-bottom, 0px ) - 8px - 38 * var( --px ) ); margin-top: calc( 38 * var( --px ) ); } /* room above for the crest ( 38 art px over the frame ), held by the margin so centring keeps it on screen */
body[data-input="touch"] .menu-hint { display: none; }
/* A short desktop window ( at most 500 px tall, a mouse ): the same as touch, the frame unclipped with room
   for the crest and the page scrolling inside it, Back pinned with the fade above it ( menu.js .more ). */
@media ( max-height: 500px ) {
  body:not( [data-input="touch"] ) #pause .menu-panel { overflow: visible; max-height: calc( 100vh - 8px - 38 * var( --px ) ); margin-top: calc( 38 * var( --px ) ); max-width: calc( 100vw - 16px ); } /* the width the two Settings columns need */
  /* the screens' panels ( inventory, stash, compare, map ... ) scroll inside the frame, their foot pinned */
  #hud:not( .touch ) .ui-panel { max-height: calc( 100% - 8px ); overflow-y: auto; overscroll-behavior: contain; scrollbar-width: none; }
  #hud:not( .touch ) :is( .ui-inv, .ui-map ) { top: 4px; }
  #hud .ui-panel > :is( .ui-inv-foot, .ui-hint:last-child ) { position: sticky; bottom: 0; z-index: 1; background: var( --umbra ); }
  body:not( [data-input="touch"] ) #pause .menu-page:not( .menu-main ) { min-height: 0; overflow-y: auto; overscroll-behavior: contain; }
  body:not( [data-input="touch"] ) #pause .menu-page:not( .menu-main ) > .menu-footer { position: sticky; bottom: 0; z-index: 1; margin-top: 0; padding-top: calc( 2 * var( --px ) ); background: var( --umbra ); }
  body:not( [data-input="touch"] ) #pause .menu-page:not( .menu-main ) > .menu-footer::before { content: ''; position: absolute; left: 0; right: 0; bottom: 100%; height: calc( 6 * var( --px ) ); pointer-events: none; visibility: hidden;
    background: linear-gradient( to top, var( --umbra ) 0 calc( 2 * var( --px ) ), rgb( 43 37 64 / 0.66 ) 0 calc( 4 * var( --px ) ), rgb( 43 37 64 / 0.33 ) 0 ); }
  body:not( [data-input="touch"] ) #pause .menu-page.more:not( .menu-main ) > .menu-footer::before { visibility: visible; }
}
/* Settings on touch: three balanced columns ( the groups' headings and rows flow through them, Back
   last ), 4 px between rows ( the whole row is the target, menu.js ), labels may wrap, sliders take
   the row's free width. A short phone ( 844 × 390 ) fits it with no scrolling: rows 36 px, the
   panel the screen's width in a half-width frame, and the crest, title and divider give their
   height to the rows. */
@media ( pointer: coarse ) {
  .menu-panel:has( > [data-page="settings"]:not( [hidden] ) ) { width: min( calc( 100vw - 16px ), 960px ); max-width: none; }
  #pause:has( .menu-page[data-page="settings"]:not( [hidden] ) ) { padding: 0 8px; } /* the screen-wide panel, centred */
  .menu-page[data-page="settings"]:not( [hidden] ) { display: block; columns: 3; column-gap: 12px; }
  .menu-page[data-page="settings"] :is( .menu-cols, .menu-group ) { display: contents; }
  body[data-input="touch"] .menu-page[data-page="settings"] .menu-touch { display: contents; }
  .menu-page[data-page="settings"] .menu-group h2 { break-after: avoid; break-inside: avoid; }
  .menu-page[data-page="settings"] .menu-row { margin-bottom: 4px; break-inside: avoid; }
  .menu-page[data-page="settings"] .menu-row > label.menu-ctl { flex: 1; justify-content: flex-end; }
  .menu-page[data-page="settings"] .menu-range { flex: 1; min-width: 0; }
  .menu-page[data-page="settings"] .menu-label { white-space: normal; line-height: 1.1; }
  .menu-page[data-page="settings"] .menu-footer { break-inside: avoid; margin-top: 0; }
}
@media ( pointer: coarse ) and ( max-height: 500px ) {
  .menu-panel:has( > [data-page="settings"]:not( [hidden] ) ) { gap: 0; padding-top: 0; border-width: calc( 10 * var( --px ) ); border-image-width: calc( 10 * var( --px ) ); }
  .menu-panel:has( > [data-page="settings"]:not( [hidden] ) ) > :is( .menu-crest, .menu-title, .menu-divider ) { display: none; }
  body[data-input="touch"] #pause .menu-panel:has( > [data-page="settings"]:not( [hidden] ) ) { overflow-y: auto; }
  .menu-page[data-page="settings"] .menu-group h2 { margin: 0 0 2px; line-height: 1; }
  .menu-page[data-page="settings"] .menu-row { min-height: 36px; }
  body[data-input="touch"] .menu-page[data-page="settings"] .menu-ctl { min-height: 36px; }
}
body:not( [data-input="touch"] ) .menu-touch { display: none; }
/* Controls page: the rows for the input mode in use ( src/ui/menu.js CONTROLS ) */
body:not( [data-input="touch"] ) .menu-controls-touch, body[data-input="touch"] .menu-controls-kbm { display: none; }
#hud.touch .ui-trash { min-width: 44px; min-height: 44px; touch-action: none; } /* the grate stays crisp, centred in a thumb-sized catch */
#hud.touch .ui-confirm .ui-act { min-height: 44px; min-width: 88px; }
/* First steps: on touch the card would cover Pepecat at the centre; it sits at the top, between the
   orb and the minimap's block ( the chips beside the minimap, above the Fire cluster ). On a short
   phone that block starts a third of the way down: the card drops its title row to stay above it. */
/* under the top band ( the icon row runs along the top edge, touch.js ), and the saved seal below the minimap */
#hud.touch > .ui-hints { top: calc( var( --touch-map-top, 4px ) + var( --touch-chip-hit, 44px ) + 6px ); bottom: auto; }
/* the level-up toast on touch: one slim row at the bottom centre, above the magazine, placed by screens.js placeLevel ( never over the hero, the boss bar or the first-steps panel ) */
#hud.touch .ui-levelup.band { position: fixed; right: auto; width: max-content; flex-direction: row; align-items: center; gap: 8px; }
#hud.touch .ui-levelup.band.stack { flex-direction: column; gap: 2px; }
#hud.touch .ui-save { position: fixed; top: calc( var( --touch-map-top, 4px ) + var( --touch-map-height, 80px ) + 6px ); right: calc( var( --safe-right, 0px ) + 6px ); }
/* Talents on a short screen, touch or mouse ( screens.js compactTalents: at most 500 px tall ): the packed tree;
   on touch the art px sized to the height ( 281 art px with the frame, below ) but never under 1.34 CSS px, so a
   27 px node stays at least 36 CSS px; no title, divider, branch blurb, capstone line or right-mouse row. */
#hud .ui-talents.compact { top: 4px; gap: calc( 2 * var( --px ) ); } /* --px: below, with the head */
#hud .ui-talents.compact > .ui-title, #hud .ui-talents.compact > .ui-rule, #hud .ui-talents.compact .ui-identity,
#hud .ui-talents.compact .ui-branch-cap, #hud .ui-talents.compact .ui-foot-row { display: none; }
#hud .ui-talents.compact .ui-tree { height: calc( 164 * var( --px ) ); margin-top: 0; } /* the deep tier's row included ( screens.js DEEP_AT_COMPACT ) */
#hud .ui-talents.compact .ui-branch { padding: calc( 2 * var( --px ) ) 0; }
#hud .ui-talents.compact .ui-talent-foot { justify-content: flex-end; }
#hud .ui-talents.compact .ui-respec { min-height: 36px; }
#hud.touch .ui-talent-page { min-height: 36px; }
/* Hellcharge's aim armed to cancel: the finger is back on Ability ( src/ui/touch.js aimCancelArmed ) */
.touch-btn.cancel .touch-icon { filter: grayscale( 1 ) brightness( 0.45 ); }
/* On a phone the level and the points counter sit in the foot, left of the page switch and Respec ( clear of the
   close X and Menu, top right ), so the deep tier's row fits: 281 art px tall with the frame. */
#hud.touch .ui-talents.compact { --px: max( 1.34px, min( var( --spx ), calc( ( 100vh - 8px ) / 281 ) ) ); } /* touch: finger-sized nodes; a mouse keeps the whole art px */
#hud .ui-talents.compact .ui-talent-foot > .ui-talent-head { margin-right: auto; align-items: center; gap: calc( 6 * var( --px ) ); }
/* Ascended: the columns 14 art px narrower each ( the tree overhangs its empty margins ) so Nightstalker clears Menu. */
#hud .ui-talents.compact.ascended .ui-branches { gap: calc( 6 * var( --px ) ); }
#hud .ui-talents.compact.ascended .ui-branch { width: calc( 118 * var( --px ) ); }
#hud .ui-talents.compact.ascended .ui-tree { margin: 0 calc( -7 * var( --px ) ); }
#hud.touch .ui-ascend { top: 40%; } /* below the first-steps hints ( front.js ) */
/* Menu under the close X: the pause route on touch, a full thumb target ( screens.js layer.menu ) */
.ui-menu-corner { position: absolute; right: 4px; top: 58px; min-height: 44px; min-width: 64px; justify-content: center; z-index: 6; pointer-events: auto; touch-action: none; --px: var( --tpx, 2px ); }
.ui-menu-corner[hidden] { display: none; }
@media ( max-height: 400px ) { #hud.touch > .ui-hints > .ui-hints-title { display: none; } }

/* Automap ( src/ui/automap.js ): the corner minimap, the full-screen overlay and the touch chip.
   Art px are --px, like the HUD; the canvases are drawn in art px and shown pixelated. */

:root { --automap-css: 1; }

/* Overlay: over the world, under every HUD cluster ( inserted right after the vignette ). */
#hud > .automap-overlay { position: absolute; inset: 0; pointer-events: none; }
#hud > .automap-overlay[hidden], #hud > .automap-corner[hidden], #hud > .automap-chip[hidden] { display: none; }
.automap-overlay-canvas { display: block; image-rendering: pixelated; }

/* Corner: 160 × 110 art px in the kit's iron panel 9-slice ( 7 px ), top-right. A tap toggles. */
#hud > .automap-corner {
  position: absolute; right: calc( 4 * var( --px ) ); top: calc( 4 * var( --px ) );
  width: calc( 160 * var( --px ) ); height: calc( 110 * var( --px ) ); min-width: 44px; min-height: 44px;
  border-width: calc( 7 * var( --px ) ); border-image: var( --ui-panel ) 7 / calc( 7 * var( --px ) ) stretch;
  background: rgba( 21, 15, 38, 0.86 ); background-clip: padding-box;
  filter: var( --hard-drop ); pointer-events: auto; touch-action: none; cursor: pointer;
}
.automap-corner-canvas { display: block; width: calc( 146 * var( --px ) ); height: calc( 96 * var( --px ) ); image-rendering: pixelated; }
/* Short screens with a mouse ( automap.js dock, SMALL ): half size, 80 × 55; its canvas is sized inline. */
#hud > .automap-corner.small { width: calc( 80 * var( --px ) ); height: calc( 55 * var( --px ) ); }
/* Touch, docked ( automap.js dock ): fixed in the block above the Fire cluster that the touch
   controls publish; its box and canvas size are set inline ( viewport px ). */
#hud > .automap-corner.docked, #hud > .automap-chip.docked { position: fixed; right: auto; }
#hud > .automap-corner.docked { min-width: 0; min-height: 0; }

/* Touch, overlay mode: a map chip where the corner sits, to bring it back. */
#hud > .automap-chip {
  position: absolute; right: calc( 4 * var( --px ) ); top: calc( 4 * var( --px ) );
  width: max( 44px, calc( 23 * var( --px ) ) ); height: max( 44px, calc( 23 * var( --px ) ) );
  display: flex; align-items: center; justify-content: center;
  background: var( --ui-touch-chip ) center / 100% 100% no-repeat; image-rendering: pixelated;
  filter: var( --hard-drop ); pointer-events: auto; touch-action: none; cursor: pointer;
}
.automap-chip-glyph { width: calc( 9 * var( --px ) * 2 ); height: calc( 9 * var( --px ) * 2 ); image-rendering: pixelated; }


:root {
  --void: #05040f; --umbra: #2b2540; --iron0: #262b38; --iron1: #5b657c; --iron2: #bccadf;
  --bone0: #7f7774; --bone1: #a8987c; --bone2: #cfbc96; --bone3: #f0e6c6;
  --flame0: #b8401c; --flame1: #e8801e; --flame2: #ffc845; --core: #fff4c2;
  --blood0: #3a0d16; --blood1: #5e1420; --blood2: #8a1a2b; --red2: #ff7d66;
  --serif: 'Palatino Linotype', 'Book Antiqua', Palatino, 'Goudy Old Style', Georgia, serif;
  --px: 2px;
  --hard-drop: drop-shadow( 0 var( --px ) 0 var( --void ) ); /* every cluster: one hard 1-art-px drop */
}
html, body { margin: 0; height: 100%; background: #000; overflow: hidden; }
body { font-family: var( --serif ); color: var( --bone2 ); user-select: none; }
#view { position: fixed; inset: 0; width: 100%; height: 100%; display: block; cursor: crosshair; touch-action: none; }

.px { image-rendering: pixelated; background-repeat: no-repeat; background-size: 100% 100%; }
.txt { display: inline-block; flex: none; image-rendering: pixelated; background-repeat: no-repeat; background-size: 100% 100%; vertical-align: bottom; }
.nine { border-style: solid; border-color: transparent; image-rendering: pixelated; box-sizing: border-box; }

/* ---- HUD ------------------------------------------------------------------------------- */

#hud { position: fixed; pointer-events: none; --u: 1px; overflow: hidden; }
#hud > div { position: absolute; }
.hud-vignette { inset: 0; opacity: 0; background: radial-gradient( ellipse at center, transparent 45%, rgba( 120, 10, 20, 0.55 ) 80%, rgba( 70, 0, 10, 0.85 ) 100% ); }
/* Plinth: a banded void strip that seats the bottom clusters on busy floors. */
.hud-plinth { left: 0; right: 0; bottom: 0; height: calc( 32 * var( --px ) );
  background: linear-gradient( to top, rgba( 5, 4, 15, 0.58 ) 0 calc( 8 * var( --px ) ), rgba( 5, 4, 15, 0.42 ) 0 calc( 16 * var( --px ) ), rgba( 5, 4, 15, 0.26 ) 0 calc( 24 * var( --px ) ), rgba( 5, 4, 15, 0.12 ) 0 ); }

/* Key cap: kit 9-slice ( 2 / 2 / 3 / 2 ) around a small-caps label. */
.hud-key { display: inline-flex; border-width: calc( 2 * var( --px ) ) calc( 2 * var( --px ) ) calc( 3 * var( --px ) ); border-image: var( --ui-keycap ) 2 2 3 fill / calc( 2 * var( --px ) ) calc( 2 * var( --px ) ) calc( 3 * var( --px ) ) stretch; }
.hud-key .txt { margin: calc( -1 * var( --px ) ) 0; }

/* Health orb, bottom-left: socket 97×104 with the 63 px glass at ( 17, 21 ). */
.hud-left { left: calc( 4 * var( --px ) ); bottom: calc( 2 * var( --px ) ); display: flex; align-items: flex-end; }
.hud-orb { position: relative; width: calc( 97 * var( --px ) ); height: calc( 104 * var( --px ) ); filter: var( --hard-drop ); }
.hud-orb-glass { position: absolute; left: calc( 17 * var( --px ) ); top: calc( 21 * var( --px ) ); width: calc( 63 * var( --px ) ); height: calc( 63 * var( --px ) ); background-image: var( --ui-orb-glass ); clip-path: circle( 50% ); }
.hud-orb-liquid { position: absolute; inset: 0; background-image: var( --ui-orb-liquid ); clip-path: inset( calc( var( --drain, 0 ) * var( --px ) ) 0 0 0 ); transition: clip-path 0.22s steps( 6 ); }
.hud-orb-surface { position: absolute; left: 0; width: 100%; height: calc( 2 * var( --px ) ); top: calc( var( --drain, 0 ) * var( --px ) ); background-image: var( --ui-orb-surface ); transition: top 0.22s steps( 6 ); }
.hud-orb-surface[hidden] { display: none; }
.hud-orb-gloss { position: absolute; inset: 0; background-image: var( --ui-orb-gloss ); }
.hud-orb-socket { position: absolute; inset: 0; background-image: var( --ui-orb ); }
/* The orb's and the slots' numbers sit inside drop-shadow filters, where Chrome does not snap a half
   pixel left by flex centring: they are centred on the glass / window by a translate rounded to whole
   CSS px ( 1/3 px at DPR 3 lands a 1/64 LayoutUnit off ). */
.hud-orb-text { position: absolute; left: round( calc( 48.5 * var( --px ) ), 1px ); top: round( calc( 52.5 * var( --px ) ), 1px ); translate: round( -50%, 1px ) round( -50%, 1px ); display: flex; align-items: flex-start; }
.hud-orb-text .hud-hp-max { margin: calc( 5 * var( --px ) ) 0 0 calc( -1 * var( --px ) ); }
/* The one-shot keyframes below ( orb-hit, liquid-hit, slot-ready, pip-pop, pip-pop-calm ) are played by hud.js restart()
   with the Web Animations API, timings and calm rules there; no class carries them. */
@keyframes orb-hit {
  0% { translate: 0 0; } 15% { translate: calc( 2 * var( --shake, 1 ) * var( --px ) ) calc( -1 * var( --shake, 1 ) * var( --px ) ); }
  30% { translate: calc( -2 * var( --shake, 1 ) * var( --px ) ) 0; } 45% { translate: calc( 1 * var( --shake, 1 ) * var( --px ) ) var( --px ); }
  60% { translate: calc( -1 * var( --shake, 1 ) * var( --px ) ) 0; } 100% { translate: 0 0; }
}
@keyframes liquid-hit { 0%, 40% { filter: brightness( 1.6 ); } 100% { filter: none; } }
/* Heartbeat below 30 %: double-beat glow; gentler and without the bright pulse under reduced flash. */
.hud-orb.low .hud-orb-liquid { animation: heartbeat 1s ease-out infinite; }
.hud-orb.low { animation: heart-glow 1s ease-out infinite; }
@keyframes heartbeat { 0%, 30%, 100% { filter: none; } 10%, 40% { filter: brightness( 1.45 ) saturate( 1.2 ); } }
@keyframes heart-glow { 0%, 30%, 100% { filter: var( --hard-drop ); } 10%, 40% { filter: var( --hard-drop ) drop-shadow( 0 0 calc( 5 * var( --px ) ) rgba( 220, 47, 48, 0.75 ) ); } }
.hud-orb.low.calm .hud-orb-liquid { animation: heartbeat-calm 1.6s ease-in-out infinite; }
.hud-orb.low.calm { animation: none; }
@keyframes heartbeat-calm { 50% { filter: brightness( 1.15 ); } }

/* Portrait: the 48×48 expression strip ( art/ui/portrait/ ) in a 60×60 steel medallion. */
.hud-portrait, .menu-portrait { position: relative; width: calc( 60 * var( --px ) ); height: calc( 60 * var( --px ) ); background: var( --umbra ); filter: var( --hard-drop ); flex: none; }
.hud-portrait { margin: 0 0 calc( 4 * var( --px ) ) calc( -6 * var( --px ) ); }
.hud-portrait[hidden] { display: none; }
.hud-face { position: absolute; left: calc( 6 * var( --px ) ); top: calc( 6 * var( --px ) ); width: calc( 48 * var( --px ) ); height: calc( 48 * var( --px ) );
  background-image: var( --ui-portrait ); background-size: calc( 288 * var( --px ) ) calc( 48 * var( --px ) ); background-position: calc( var( --face, 0 ) * -48 * var( --px ) ) 0; }
.hud-portrait::after, .menu-portrait::after { content: ''; position: absolute; inset: 0; background: var( --ui-portrait-frame ) 0 0 / 100% 100% no-repeat; image-rendering: pixelated; }

/* Centre column: powerup timers above the dodge / ability / flask slots ( 41×48, window 31 at 5, 12 ). */
.hud-center { left: round( 50%, var( --dpx, 1px ) ); bottom: calc( 3 * var( --px ) ); transform: translateX( round( -50%, var( --dpx, 1px ) ) ); display: flex; flex-direction: column; align-items: center; gap: calc( 3 * var( --px ) ); }
/* Short screens ( #hud.short, automap.js dock ): the column leaves the middle of the floor for the bottom
   edge, just right of the portrait. */
#hud.short .hud-center { left: calc( 160 * var( --px ) ); bottom: 0; transform: none; align-items: flex-start; }
.hud-skills { display: flex; gap: calc( 5 * var( --px ) ); filter: var( --hard-drop ); }
.hud-slot { position: relative; width: calc( 41 * var( --px ) ); height: calc( 52 * var( --px ) ); --cd: 0; }
.hud-slot-frame { position: absolute; left: 0; top: 0; width: calc( 41 * var( --px ) ); height: calc( 48 * var( --px ) ); background-image: var( --ui-slot ); }
.hud-slot.ready .hud-slot-frame { background-image: var( --ui-slot-ready ); }
.hud-slot-icon { position: absolute; left: calc( 8 * var( --px ) ); top: calc( 15 * var( --px ) ); width: calc( 25 * var( --px ) ); height: calc( 25 * var( --px ) ); }
.hud-slot-sweep { position: absolute; left: calc( 5 * var( --px ) ); top: calc( 12 * var( --px ) ); width: calc( 31 * var( --px ) ); height: calc( 31 * var( --px ) );
  background: conic-gradient( transparent 0 calc( ( 1 - var( --cd ) ) * 360deg ), rgba( 5, 4, 15, 0.8 ) 0 ); }
.hud-slot-time { position: absolute; left: round( calc( 20.5 * var( --px ) ), 1px ); top: round( calc( 27.5 * var( --px ) ), 1px ); translate: round( -50%, 1px ) round( -50%, 1px ); display: flex; }
.hud-slot-count { position: absolute; left: calc( 5 * var( --px ) ); top: calc( 30 * var( --px ) ); }
.hud-slot .hud-key { position: absolute; right: calc( -3 * var( --px ) ); top: calc( 39 * var( --px ) ); }
.hud-slot-lock { position: absolute; left: calc( 15 * var( --px ) ); top: calc( 21 * var( --px ) ); width: calc( 11 * var( --px ) ); height: calc( 13 * var( --px ) ); background-image: var( --ui-icon-lock ); }
.hud-slot-lock[hidden] { display: none; }
.hud-slot.locked .hud-slot-icon { filter: grayscale( 1 ) brightness( 0.45 ); }
.hud-slot.cooling .hud-slot-icon { filter: brightness( 0.7 ); }
@keyframes slot-ready { 0% { filter: brightness( 1.9 ); } 100% { filter: none; } }
.hud-slot.glow .hud-slot-icon { animation: flask-glow 1.8s ease-in-out infinite; }
@keyframes flask-glow { 0%, 100% { filter: drop-shadow( 0 0 calc( 1 * var( --px ) ) rgba( 255, 125, 102, 0.5 ) ); } 50% { filter: drop-shadow( 0 0 calc( 4 * var( --px ) ) rgba( 255, 200, 69, 0.85 ) ); } }
.hud-slot.glow.calm .hud-slot-icon { animation: none; filter: drop-shadow( 0 0 calc( 2 * var( --px ) ) rgba( 255, 200, 69, 0.6 ) ); }
.hud-slot.empty .hud-slot-icon { filter: brightness( 0.6 ); }

/* Powerups: only active timers show; the coloured ring drains clockwise from twelve o'clock. */
.hud-powerups { display: flex; gap: calc( 4 * var( --px ) ); filter: var( --hard-drop ); }
.hud-power { position: relative; width: calc( 29 * var( --px ) ); height: calc( 38 * var( --px ) ); --left: 1; }
.hud-power[hidden] { display: none; }
.hud-power-ring, .hud-power-fill { position: absolute; left: 0; top: 0; width: calc( 29 * var( --px ) ); height: calc( 29 * var( --px ) ); }
.hud-power-ring { background-image: var( --ui-ring ); }
.hud-power-fill { -webkit-mask: conic-gradient( #000 0 calc( var( --left ) * 360deg ), transparent 0 ); mask: conic-gradient( #000 0 calc( var( --left ) * 360deg ), transparent 0 ); }
.hud-power-icon { position: absolute; left: calc( 7 * var( --px ) ); top: calc( 7 * var( --px ) ); width: calc( 15 * var( --px ) ); height: calc( 15 * var( --px ) ); }
.hud-power-time { position: absolute; left: 0; right: 0; top: calc( 27 * var( --px ) ); display: flex; justify-content: center; }
.hud-power.ending .hud-power-fill, .hud-power.ending .hud-power-icon { animation: power-end 0.33s steps( 1 ) infinite; }
@keyframes power-end { 50% { opacity: 0.2; } }
.hud-power.ending.calm .hud-power-fill, .hud-power.ending.calm .hud-power-icon { animation: power-end-calm 1s ease-in-out infinite; }
@keyframes power-end-calm { 50% { opacity: 0.55; } }

/* Magazine, bottom-right: count, pip tray ( rows of 15, a gap every 5 ), weapon plaque. */
.hud-right { right: calc( 5 * var( --px ) ); bottom: calc( 3 * var( --px ) ); display: flex; flex-direction: column; align-items: flex-end; gap: calc( 1 * var( --px ) ); filter: var( --hard-drop ); }
.hud-mag-count { display: flex; align-items: flex-end; padding-right: calc( 2 * var( --px ) ); }
.hud-mag-count .hud-mag-size { margin: 0 0 calc( 1 * var( --px ) ) calc( -1 * var( --px ) ); }
.hud-tray { border-width: calc( 5 * var( --px ) ); border-image: var( --ui-panel ) 7 fill / calc( 7 * var( --px ) ) stretch; }
.hud-pips { display: flex; flex-direction: column; gap: calc( 2 * var( --px ) ); }
.hud-pip-row { display: flex; gap: calc( 1 * var( --px ) ); }
.hud-pip-row i { width: calc( 5 * var( --px ) ); height: calc( 11 * var( --px ) ); background: var( --ui-pip-full ) 0 0 / 100% 100% no-repeat; image-rendering: pixelated; }
.hud-pip-row i:nth-child( 5n + 1 ):not( :first-child ) { margin-left: calc( 1 * var( --px ) ); }
.hud-pip-row i.spent { background-image: var( --ui-pip-spent ); }
.hud-pip-row i.empty { background-image: var( --ui-pip-empty ); }
.hud-pip-row i.hot { background-image: var( --ui-pip-hot ); }
.hud-pip-row i.dry { background-image: var( --ui-pip-dry ); }
.hud-pip-row i.load { background-image: var( --ui-pip-load ); }
.hud-right.unarmed .hud-mag-count, .hud-right.unarmed .hud-tray { display: none; } /* no magazine yet: never show '/0' */
.hud-pip-row i.blink { animation: pip-blink 0.5s steps( 1 ) infinite; }
@keyframes pip-blink { 50% { background-image: var( --ui-pip-hot ); } }
.calm .hud-pip-row i.blink { animation: none; background-image: var( --ui-pip-hot ); }
@keyframes pip-pop { 0% { translate: 0 calc( -3 * var( --px ) ); filter: brightness( 1.8 ); } 100% { translate: 0 0; filter: none; } }
@keyframes pip-pop-calm { 0% { translate: 0 calc( -3 * var( --px ) ); } 100% { translate: 0 0; } }
.hud-right.dry .hud-tray { animation: tray-dry 0.6s steps( 1 ) infinite; }
@keyframes tray-dry { 50% { filter: brightness( 1.35 ) saturate( 1.3 ); } }
.calm .hud-right.dry .hud-tray { animation: none; }
.hud-weapon { display: flex; align-items: flex-end; /* not centre: a half pixel inside .hud-right's filter */ gap: calc( 3 * var( --px ) ); padding-right: calc( 1 * var( --px ) ); }

/* Toasts: kit blood-cloth banner ( 23 art px tall, 14 px tails ) around small-caps text. */
.hud-toast { height: calc( 23 * var( --px ) ); border-width: 0 calc( 14 * var( --px ) ); border-image: var( --ui-banner ) 0 14 fill / 0 calc( 14 * var( --px ) ) stretch;
  display: flex; align-items: center; justify-content: center; padding: 0 calc( 3 * var( --px ) ) calc( 3 * var( --px ) );
  opacity: 0; translate: 0 calc( 3 * var( --px ) ); transition: opacity 0.12s, translate 0.12s steps( 3 ); filter: var( --hard-drop ); }
.hud-toast.show { opacity: 1; translate: 0 0; }
.hud-msg { left: round( 50%, var( --dpx, 1px ) ); top: 36%; transform: translateX( round( -50%, var( --dpx, 1px ) ) ); }
.hud-reload { position: absolute; right: 0; bottom: calc( 100% + 2 * var( --px ) ); }

/* Big centre banner ( 'Wave 2', 'You died' ): gothic caps between ornamental rules. */
.hud-banner { left: 0; right: 0; top: 22%; display: flex; flex-direction: column; align-items: center; gap: calc( 3 * var( --px ) ); opacity: 0; transition: opacity 0.3s; filter: var( --hard-drop ); }
.hud-banner.show { opacity: 1; }
.hud-banner .rule, .menu-divider { display: block; width: calc( 121 * var( --px ) ); height: calc( 7 * var( --px ) ); background: var( --ui-divider ) 0 0 / 100% 100% no-repeat; image-rendering: pixelated; }

/* Boss bar, top centre: gothic name, horned kit rail ( 9-slice 33 × 15 ), blood fill over a gilt
   trail that lags behind each hit, phase ticks, epithet. */
.hud-target { left: round( 50%, var( --dpx, 1px ) ); top: calc( 6 * var( --px ) ); transform: translateX( round( -50%, var( --dpx, 1px ) ) ); width: calc( 236 * var( --px ) ); display: flex; flex-direction: column; align-items: center; gap: calc( 1 * var( --px ) ); filter: var( --hard-drop ); }
.hud-target[hidden] { display: none; }
.hud-target-bar { position: relative; align-self: stretch; height: calc( 15 * var( --px ) ); border-width: calc( 5 * var( --px ) ) calc( 12 * var( --px ) ); border-image: var( --ui-boss-bar ) 5 12 fill / calc( 5 * var( --px ) ) calc( 12 * var( --px ) ) stretch; }
.hud-target-fill, .hud-target-trail { position: absolute; left: 0; right: 0; top: 0; height: calc( 5 * var( --px ) ); background: var( --ui-boss-fill ) 0 0 / 100% 100% no-repeat; image-rendering: pixelated; transition: clip-path 0.12s; }
.hud-target-trail { background-image: var( --ui-boss-trail ); transition: clip-path 0.6s 0.35s ease-in; }
.hud-target-ticks { position: absolute; inset: 0; }
/* STAGGERED ( hud.js, boss_stagger ): 2 Hz, half on and half off; steady under reduced flash or OS reduced motion. */
.hud-target-epithet.stagger { animation: stagger-blink 0.5s steps( 1 ) infinite; }
.calm .hud-target-epithet.stagger { animation: none; }
@media ( prefers-reduced-motion: reduce ) { .hud-target-epithet.stagger { animation: none; } }
@keyframes stagger-blink { 50% { opacity: 0; } }
.hud-target-ticks i { position: absolute; top: calc( -1 * var( --px ) ); bottom: calc( -1 * var( --px ) ); width: var( --px ); background: var( --bone3 ); box-shadow: var( --px ) 0 0 var( --void ); }

.hud-numbers { left: 0; top: 0; }
.hud-numbers span { position: absolute; left: 0; top: 0; translate: round( -50%, var( --dpx, 1px ) ) -100%; image-rendering: pixelated; background-repeat: no-repeat; background-size: 100% 100%; }
.hud-perf { left: calc( 3 * var( --px ) ); top: calc( 3 * var( --px ) ); font: max( 10px, calc( 9 * var( --u ) ) ) / 1.35 Consolas, 'Courier New', monospace; color: #b8f0a0; background: rgba( 0, 0, 0, 0.6 ); padding: calc( 4 * var( --u ) ) calc( 6 * var( --u ) ); white-space: pre; }
.hud-perf[hidden] { display: none; }

/* ---- overlays: pause / settings / controls, error ----------------------------------------- */

.overlay { position: fixed; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 12px; background: rgba( 8, 5, 14, 0.7 ); color: var( --bone3 ); }
.overlay[hidden] { display: none; }
/* The panel sits right of centre: Pepecat stands left of centre in the arena framing. */
#pause { cursor: default; align-items: flex-end; padding: 0 round( max( 4vw, calc( 24 * var( --px ) ) ), var( --dpx, 1px ) ); box-sizing: border-box;
  background: linear-gradient( 90deg, rgba( 8, 5, 14, 0.35 ), rgba( 8, 5, 14, 0.82 ) 70% ); font-size: max( 15px, calc( 8 * var( --px ) ) ); }
#error { font-size: 18px; letter-spacing: 0.05em; white-space: pre-wrap; text-align: center; color: var( --red2 ); }
#error button { font: inherit; font-variant: small-caps; letter-spacing: 0.1em; color: var( --bone3 ); background: none; cursor: pointer; padding: 4px 18px; border: 10px solid transparent; border-image: var( --ui-button ) 5 fill / 10px stretch; image-rendering: pixelated; }

.menu-panel {
  position: relative; min-width: calc( 200 * var( --px ) ); max-width: 62vw; box-sizing: border-box;
  border-style: solid; border-color: transparent; border-width: calc( 20 * var( --px ) ); border-image: var( --ui-frame ) 20 fill / calc( 20 * var( --px ) ) stretch;
  padding: calc( 2 * var( --px ) ) calc( 8 * var( --px ) ) calc( 4 * var( --px ) ); display: flex; flex-direction: column; align-items: center; gap: calc( 4 * var( --px ) );
  filter: drop-shadow( 0 calc( 3 * var( --px ) ) 0 rgba( 0, 0, 0, 0.6 ) );
}
.menu-crest { position: absolute; left: round( 50%, var( --dpx, 1px ) ); top: calc( -38 * var( --px ) ); width: calc( 41 * var( --px ) ); height: calc( 27 * var( --px ) ); translate: round( -50%, var( --dpx, 1px ) ) 0; background: var( --ui-crest ) 0 0 / 100% 100% no-repeat; image-rendering: pixelated; }
.menu-title { margin: calc( 6 * var( --px ) ) 0 0; line-height: 0; }
.menu-page { display: flex; flex-direction: column; align-items: stretch; gap: calc( 3 * var( --px ) ); width: 100%; }
.menu-page[hidden] { display: none; }
.menu-main { flex-direction: row; align-items: center; justify-content: center; gap: calc( 10 * var( --px ) ); padding: calc( 2 * var( --px ) ) 0; }
.menu-buttons { display: flex; flex-direction: column; gap: calc( 3 * var( --px ) ); }
.menu-hint { margin: 0; font-size: max( 12px, calc( 6 * var( --px ) ) ); font-variant: small-caps; letter-spacing: 0.12em; color: var( --bone0 ); text-shadow: 0 var( --px ) 0 var( --void ); }

.menu-btn {
  position: relative; display: flex; justify-content: center; align-items: center; min-width: calc( 96 * var( --px ) ); background: none; cursor: pointer; outline: none;
  padding: calc( 2 * var( --px ) ) calc( 8 * var( --px ) ); border: calc( 5 * var( --px ) ) solid transparent; border-image: var( --ui-button ) 5 fill / calc( 5 * var( --px ) ) stretch; image-rendering: pixelated;
}
.menu-btn.small { min-width: 0; align-self: center; }
.menu-btn .hot, .menu-btn:focus .rest, .menu-btn:hover .rest { display: none; }
.menu-btn:focus .hot, .menu-btn:hover .hot { display: inline-block; }
.menu-btn:focus, .menu-btn:hover { border-image-source: var( --ui-button-hot ); }
.menu-btn:active { translate: 0 var( --px ); border-image-source: var( --ui-button-down ); }
.menu-btn:focus::before, .menu-row:focus-within::before {
  content: ''; position: absolute; left: calc( -14 * var( --px ) ); top: 50%; width: calc( 7 * var( --px ) ); height: calc( 7 * var( --px ) ); translate: 0 -50%;
  background: var( --ui-fleur ) 0 0 / 100% 100% no-repeat; image-rendering: pixelated; animation: fleur 1.2s steps( 2 ) infinite;
}
@keyframes fleur { 50% { translate: calc( 1 * var( --px ) ) -50%; } }

.menu-cols { display: grid; grid-template-columns: 1fr 1fr; gap: 0 calc( 12 * var( --px ) ); width: 100%; }
.menu-group { display: flex; flex-direction: column; gap: calc( 2 * var( --px ) ); }
.menu-group h2 { margin: calc( 3 * var( --px ) ) 0 calc( 1 * var( --px ) ); font-weight: normal; font-size: max( 13px, calc( 7 * var( --px ) ) ); font-variant: small-caps; letter-spacing: 0.2em; color: var( --bone1 ); text-shadow: 0 var( --px ) 0 var( --void ); border-bottom: var( --px ) solid var( --iron0 ); }
.menu-row { position: relative; display: flex; align-items: center; justify-content: space-between; gap: calc( 6 * var( --px ) ); min-height: max( 26px, calc( 13 * var( --px ) ) ); padding: 0 calc( 3 * var( --px ) ); margin-left: calc( 10 * var( --px ) ); }
.menu-row:focus-within, .menu-row:hover { background: linear-gradient( 90deg, rgba( 94, 20, 32, 0.55 ), rgba( 94, 20, 32, 0 ) ); }
.menu-row:focus-within .menu-label { color: var( --core ); }
.menu-row::before { left: calc( -11 * var( --px ) ) !important; }
.menu-row.off { opacity: 0.45; }
.menu-label { font-size: max( 14px, calc( 7.5 * var( --px ) ) ); font-variant: small-caps; letter-spacing: 0.08em; color: var( --bone2 ); text-shadow: 0 var( --px ) 0 var( --void ); white-space: nowrap; }
.menu-ctl { display: flex; align-items: center; gap: calc( 3 * var( --px ) ); font-size: max( 13px, calc( 7 * var( --px ) ) ); color: var( --bone3 ); font-variant-numeric: lining-nums tabular-nums; outline: none; background: none; border: 0; font-family: inherit; cursor: pointer; padding: 0; }
.menu-ctl output { min-width: 3.2em; text-align: right; }
.menu-toggle { width: calc( 11 * var( --px ) ); height: calc( 11 * var( --px ) ); background: var( --ui-check-off ) 0 0 / 100% 100% no-repeat; image-rendering: pixelated; }
[aria-checked='true'] > .menu-toggle { background-image: var( --ui-check-on ); }
.menu-choice { font-size: max( 13px, calc( 7 * var( --px ) ) ); font-variant: small-caps; letter-spacing: 0.1em; color: var( --bone3 ); }
.menu-choice::before { content: '‹'; color: var( --flame1 ); margin-right: 0.5em; }
.menu-choice::after { content: '›'; color: var( --flame1 ); margin-left: 0.5em; }
.menu-range { -webkit-appearance: none; appearance: none; width: calc( 64 * var( --px ) ); height: calc( 13 * var( --px ) ); background: transparent; margin: 0; cursor: pointer; outline: none; }
.menu-range::-webkit-slider-runnable-track { height: calc( 7 * var( --px ) ); border: calc( 3 * var( --px ) ) solid transparent; border-image: var( --ui-track ) 3 fill / calc( 3 * var( --px ) ) stretch; image-rendering: pixelated; box-sizing: border-box;
  background: linear-gradient( 90deg, var( --flame0 ) var( --fill, 0% ), transparent 0 ) content-box; }
.menu-range::-webkit-slider-thumb { -webkit-appearance: none; width: calc( 7 * var( --px ) ); height: calc( 13 * var( --px ) ); margin-top: calc( -6 * var( --px ) + 0.5px ); background: var( --ui-thumb ) 0 0 / 100% 100% no-repeat; image-rendering: pixelated; border: 0; }
.menu-range::-moz-range-track { height: calc( 7 * var( --px ) ); border: calc( 3 * var( --px ) ) solid transparent; border-image: var( --ui-track ) 3 fill / calc( 3 * var( --px ) ) stretch; box-sizing: border-box; }
.menu-range::-moz-range-thumb { width: calc( 7 * var( --px ) ); height: calc( 13 * var( --px ) ); background: var( --ui-thumb ) 0 0 / 100% 100% no-repeat; image-rendering: pixelated; border: 0; border-radius: 0; }
.menu-note { margin: 0 0 0 calc( 10 * var( --px ) ); font-size: max( 12px, calc( 6 * var( --px ) ) ); font-style: italic; color: var( --bone0 ); }

.menu-controls { display: grid; grid-template-columns: auto 1fr; gap: calc( 3 * var( --px ) ) calc( 8 * var( --px ) ); align-items: center; margin: 0 calc( 4 * var( --px ) ); }
.menu-controls dt { justify-self: end; display: flex; gap: calc( 2 * var( --px ) ); align-items: center; font-size: max( 12px, calc( 6 * var( --px ) ) ); color: var( --bone1 ); }
.menu-controls dd { margin: 0; font-size: max( 14px, calc( 7.5 * var( --px ) ) ); color: var( --bone2 ); text-shadow: 0 var( --px ) 0 var( --void ); }
.menu-footer { display: flex; gap: calc( 6 * var( --px ) ); justify-content: center; margin-top: calc( 2 * var( --px ) ); }

/* Threat readability ( threats.js ): ember rings where lobs land, the imp's hand flare, swarm pips. */
.hud-threats { position: absolute; inset: 0; pointer-events: none; }
.hud-lob-ring { position: absolute; left: 0; top: 0; opacity: 0.85; }
.hud-lob-ring canvas { display: block; width: 100%; height: 100%; image-rendering: pixelated; }
.hud-lob-ring.boulder { opacity: 0.7; }
/* The exit pointer ( src/ui/exit-pointer.js ): a 21 px cell at 2 × --px at the edge, toward the zone's exit. It
   fades in and out ( .on ); open it pulses in two steps, 0.4 s each ( full, then dimmer and nudged toward the exit:
   --nx, --ny, its direction ), barred it holds steady, as under reduced flashing ( .calm ) and reduced motion. */
.hud-exit { position: absolute; left: 0; top: 0; width: calc( 42 * var( --px ) ); height: calc( 42 * var( --px ) ); pointer-events: none; opacity: 0; transition: opacity 0.3s ease-out; }
.hud-exit.on { opacity: 1; }
/* the glyph steps toward the exit and back; its glow ( the canvas behind ) pulses with it, the glyph stays full */
.hud-exit canvas { position: absolute; inset: 0; display: block; width: 100%; height: 100%; image-rendering: pixelated; animation: exit-nudge 0.8s steps( 1, end ) infinite; }
.hud-exit canvas.glow { animation-name: exit-glow; }
.hud-exit.barred canvas, .calm .hud-exit canvas, .hud-exit.barred canvas.glow, .calm .hud-exit canvas.glow { animation: none; }
@keyframes exit-nudge { 0% { translate: 0 0; } 50% { translate: calc( var( --nx, 0 ) * 2 * var( --px ) ) calc( var( --ny, 0 ) * 2 * var( --px ) ); } }
@keyframes exit-glow { 0% { opacity: 1; translate: 0 0; } 50% { opacity: 0.2; translate: calc( var( --nx, 0 ) * 2 * var( --px ) ) calc( var( --ny, 0 ) * 2 * var( --px ) ); } }
@media ( prefers-reduced-motion: reduce ) { .hud-exit canvas, .hud-exit canvas.glow { animation: none; } .hud-exit { transition: none; } }
/* one art frame of flame: a 5 × 5 star in logical px ( --u ), core, arms and tips */
.hud-lob-flare { position: absolute; left: 0; top: 0; width: var( --u ); height: var( --u ); background: #fff4c2;
  box-shadow: var( --u ) 0 0 #ffc845, calc( -1 * var( --u ) ) 0 0 #ffc845, 0 var( --u ) 0 #ffc845, 0 calc( -1 * var( --u ) ) 0 #ffc845,
    calc( 2 * var( --u ) ) 0 0 #e8801e, calc( -2 * var( --u ) ) 0 0 #e8801e, 0 calc( 2 * var( --u ) ) 0 #e8801e, 0 calc( -2 * var( --u ) ) 0 #e8801e,
    var( --u ) var( --u ) 0 #b8401c, calc( -1 * var( --u ) ) var( --u ) 0 #b8401c, var( --u ) calc( -1 * var( --u ) ) 0 #b8401c, calc( -1 * var( --u ) ) calc( -1 * var( --u ) ) 0 #b8401c; }
.hud-swarm { left: round( 50%, var( --dpx, 1px ) ); top: calc( 8 * var( --px ) ); transform: translateX( round( -50%, var( --dpx, 1px ) ) ); display: flex; align-items: center; gap: calc( 3 * var( --px ) ); line-height: 0; filter: var( --hard-drop ); }
.hud-swarm[hidden] { display: none; }
.hud-swarm.below-boss { top: calc( 60 * var( --px ) ); }
.hud-swarm-pips { display: flex; gap: var( --px ); }
.hud-swarm-pip { width: calc( 4 * var( --px ) ); height: calc( 4 * var( --px ) ); background: #e8801e; box-shadow: inset 0 0 0 var( --px ) #b8401c; }
.hud-swarm-pip.out { background: #262b38; box-shadow: inset 0 0 0 var( --px ) #5b657c; }
.hud-swarm-more[hidden] { display: none; }

/* The HUD's art px, kept for layers that run on their own --px ( screens, hints ) but must clear HUD parts. */
#hud { --hpx: var( --px ); }

/* Icon row ( iconrow.js ): talents, map, inventory, immediately left of the corner minimap and
   top-aligned with it ( automap.css: right 4, top 4, 160 wide ); flush right while the corner is
   hidden. Hover lights a chip and shows its key under it; a press sinks it one art px. */
#hud > .ui-iconrow { --chip: calc( 23 * var( --px ) ); position: absolute; top: calc( 4 * var( --px ) ); right: calc( 168 * var( --px ) ); display: flex; gap: calc( 2 * var( --px ) ); pointer-events: none; filter: var( --hard-drop ); }
#hud:has( > .automap-corner[hidden] ) > .ui-iconrow:not( .docked ) { right: calc( 4 * var( --px ) ); }
#hud.short > .ui-iconrow:not( .docked ) { right: calc( 88 * var( --px ) ); } /* beside the half-size corner */
#hud > .ui-iconrow[hidden] { display: none; }
.ui-chip { position: relative; width: var( --chip ); height: var( --chip ); pointer-events: auto; touch-action: none; cursor: pointer; }
.ui-chip .spr { display: block; background-repeat: no-repeat; background-size: 100% 100%; image-rendering: pixelated; }
.ui-chip > .spr { position: absolute; left: round( 50%, var( --dpx, 1px ) ); top: round( 50%, var( --dpx, 1px ) ); translate: round( -50%, var( --dpx, 1px ) ) round( -50%, var( --dpx, 1px ) ); }
.ui-chip > .hot { visibility: hidden; }
.ui-chip:hover > .hot, .ui-chip.on > .hot { visibility: visible; }
.ui-chip > .down { visibility: hidden; }
.ui-chip.on > .down { visibility: visible; } /* pressed ( .on, iconrow.js pointerdown ): the hot frame a step darker */
.ui-chip.on > .ui-chip-icon { translate: round( -50%, var( --dpx, 1px ) ) calc( round( -50%, var( --dpx, 1px ) ) + var( --px ) ); }
/* disabled ( nothing disables a chip yet ): the inventory chip's dulled icon, no hover or press */
.ui-chip.off { pointer-events: none; }
.ui-chip.off > .ui-chip-icon[ style*='icon-bag' ] { background-image: var( --ui-icon-bag-off ) !important; }
.ui-chip-tip { --px: var( --tpx ); position: absolute; top: calc( 100% + 2 * var( --px ) ); right: 0; padding: calc( 2 * var( --px ) ) calc( 3 * var( --px ) ); line-height: 0; white-space: nowrap;
  border-width: calc( 3 * var( --px ) ); border-style: solid; border-image: var( --ui-panel ) 7 fill / calc( 3 * var( --px ) ) stretch; visibility: hidden; pointer-events: none; z-index: 1; }
.ui-chip:hover > .ui-chip-tip { visibility: visible; }
.ui-chip-badge { position: absolute; right: calc( -2 * var( --px ) ); top: calc( -2 * var( --px ) ); width: calc( 11 * var( --px ) ); height: calc( 11 * var( --px ) ); display: flex; align-items: center; justify-content: center; }
.ui-chip-badge > .spr { position: absolute; inset: 0; }
.ui-chip-badge > .txt { position: relative; }
/* 10+ points: the 19 px lozenge, grown leftward over the chip ( right-anchored: clear of the next chip ) */
.ui-chip-badge.wide { width: calc( 19 * var( --px ) ); }
.ui-chip-badge.wide > .one, .ui-chip-badge:not( .wide ) > .two { display: none; }
/* the pack-full burst in the inventory chip's top-right corner */
.ui-chip > .ui-chip-full { left: auto; top: 0; right: 0; translate: none; }
.ui-chip-badge[hidden], .ui-chip > .ui-chip-full[hidden] { display: none; }
/* Unspent talent points: the tome's chip glows, a soft flame2 ember pulse at 1 Hz behind the icon
   ( opacity only: the compositor runs it, no JS per frame ). Reduced flashing ( #hud.calm ) or
   reduced motion: a steady glow. Off the moment the points are spent ( .has-points, iconrow.js ). */
.ui-chip.has-points::before { content: ''; position: absolute; inset: calc( -3 * var( --px ) ); border-radius: 50%; pointer-events: none;
  background: radial-gradient( closest-side, rgba( 255, 200, 69, 0.75 ), rgba( 232, 128, 30, 0.35 ) 55%, rgba( 232, 128, 30, 0 ) );
  animation: chip-points 0.5s ease-in-out infinite alternate; }
@keyframes chip-points { from { opacity: 0.25; } to { opacity: 1; } }
#hud.calm .ui-chip.has-points::before { animation: none; opacity: 0.7; }
@media ( prefers-reduced-motion: reduce ) { .ui-chip.has-points::before { animation: none; opacity: 0.7; } }
/* Touch: docked beside the minimap's block above the Fire cluster ( touch.js publishes it on :root ),
   at the controls' art size, every chip a 44 CSS px target, no hover tooltips. */
#hud > .ui-iconrow.docked { --px: var( --touch-cpx, 2px ); --chip: var( --touch-chip-hit, 44px ); position: fixed; top: var( --touch-map-top ); left: var( --touch-chips-left, auto ); right: var( --touch-chips-right, auto ); gap: 4px; filter: drop-shadow( 0 var( --px ) 0 var( --void ) ); }
#hud > .ui-iconrow.docked > .ui-chip { opacity: var( --touch-alpha, 0.75 ); }
#hud > .ui-iconrow.docked > .ui-chip.on, #hud > .ui-iconrow.docked > .ui-chip.has-points { opacity: 1; }
#hud.touch .ui-chip-tip { display: none; }

/* ---- src/boot.css */
/* Boot and flow fallbacks ( main.js ): shown until the UI's own screens take over ( engine.ui ). */
#loading { background: #08050e; font: 18px Georgia, serif; letter-spacing: 0.08em; color: #cbbfa6; }
#loading .bar { width: min( 320px, 60vw ); height: 6px; background: #1d1424; border: 1px solid #4a3a4c; }
#loading .bar i { display: block; height: 100%; width: 0; background: #b2482c; transition: width 0.2s; }
#loading small { font-size: 13px; opacity: 0.7; }
.flow { font: 20px Georgia, serif; letter-spacing: 0.06em; color: #cbbfa6; background: rgba( 8, 5, 14, 0.86 ); }
.flow h1 { margin: 0 0 12px; font-weight: normal; font-size: 34px; letter-spacing: 0.12em; color: #e3c27a; }
.flow button { font: inherit; font-variant: small-caps; letter-spacing: 0.1em; color: #e8dcc0; background: #1d1424; border: 1px solid #6a5260; padding: 6px 28px; min-width: 220px; cursor: pointer; }
.flow button:hover:not( :disabled ) { border-color: #e3c27a; }
.flow button:disabled { opacity: 0.4; cursor: default; }
.flow small { font-size: 14px; opacity: 0.75; }
/* Touch devices ( CONTRACT.md "Mobile" ): no page scroll, rubber-band bounce, pinch or double-tap
   zoom, long-press callout or selection ( #view is touch-action: none; UI lists may still pan ). The safe-area probe's padding is read by main.js into
   the letterbox and the --safe-top / --safe-right / --safe-bottom / --safe-left vars. */
html, body { overscroll-behavior: none; touch-action: manipulation; -webkit-touch-callout: none; -webkit-user-select: none; -webkit-tap-highlight-color: transparent; -webkit-text-size-adjust: 100%; }
#safe-probe { position: fixed; left: 0; top: 0; width: 0; height: 0; visibility: hidden; pointer-events: none;
  padding: env( safe-area-inset-top, 0px ) env( safe-area-inset-right, 0px ) env( safe-area-inset-bottom, 0px ) env( safe-area-inset-left, 0px ); }
/* A newer deploy replaced this build ( main.js staleBuild ): a quiet prompt, play goes on until the tap. */
#update { position: fixed; left: 50%; bottom: calc( 16px + env( safe-area-inset-bottom, 0px ) ); transform: translateX( -50% ); z-index: 60; }
#update button { font: 15px Georgia, serif; letter-spacing: 0.06em; color: #e8dcc0; background: rgba( 8, 5, 14, 0.88 ); border: 1px solid #6a5260; padding: 8px 20px; cursor: pointer; }
#update button:hover { border-color: #e3c27a; }
/* Over everything, the UI's front ( z-index 20 ) included: a failed boot never stalls behind the title backdrop. */
#error { z-index: 80; }
