/* ============================================================
   home.css — the homepage's own skin. index.html ONLY.

   Loads after tokens.css -> main.css -> redesign.css and owns two things:

     1. A scoped token override on `body.hp-page`. redesign.css maps
        --site-* onto --bg / --surface / --accent for .site-page, so
        repainting those tokens here re-skins every main.css selector
        that reads them without touching main.css or any other page.
        Nothing in tokens.css :root is repainted. The viewer and the
        other eight .site-page pages keep their navy.

     2. Every .hp-* homepage component: hero band, race stage, drop
        plate, toolbar, popovers, and the re-tones of the rail, the
        pillar strip and the footer.

   The register is Warcraft III's own: earthy, muted, heraldic. Carved
   stone and tarnished bronze, hard black outlines, one struck highlight
   pixel, inset shadows. Chamfer, never radius, on anything that reads
   as a plate. NOTHING here glows: no shadow halo, no text-shadow blur,
   no filter: brightness above ~1.1. The reference implementations are
   .dom-bar in dominance.css and .site-build-card in main.css.

   Race colour is DATA. It identifies a race and nothing else, and is
   never the button, focus, link or selected colour. The chrome accent
   is bronze.
   ============================================================ */


/* ══════════════════════════════════════════════════════════════
   TOKENS
   ══════════════════════════════════════════════════════════════ */

body.hp-page {
  /* Surfaces: dark stone and umber, lighter = higher. */
  --bg-deep:   #16110c;
  --bg:        #221b14;
  --surface:   #2e2519;
  --surface-2: #3a2f20;
  --surface-3: #473929;
  --surface-4: #564632;

  /* Borders and washes carry a little warmth so a hairline on stone
     reads as a lit edge rather than a grey line. */
  --border:   rgba(226,200,146,0.13);
  --border-2: rgba(226,200,146,0.22);
  --border-3: rgba(226,200,146,0.32);
  --wash:     rgba(226,200,146,0.06);

  /* Parchment ink. --text-muted clears 7:1 on --bg. */
  --text:       #f2e7cf;
  --text-muted: #c0ae8c;
  --text-dim:   #9a8a6c;

  /* Chrome accent: tarnished bronze. Deliberately redder than the pro
     plate's old gold (--dom-gold #C9A227) so "this is pro" and "this
     is a button" stay two different metals. */
  --accent:         #C0873A;
  --accent-strong:  #D9A252;
  --accent-deep:    #8A5F21;
  --accent-soft:    rgba(192,135,58,0.15);
  --accent-ring:    rgba(217,162,82,0.60);
  --text-on-accent: #1d1405;

  /* Carved-chrome helpers. Every plate on the page is built from these. */
  --hp-outline: #0a0704;
  --hp-strike:  rgba(240,214,158,0.17);
  --hp-lip:     rgba(163,134,80,0.32);
  --hp-chamfer: 8px;
  --hp-grain:
    repeating-linear-gradient(114deg, rgba(226,200,146,0.016) 0 2px, rgba(0,0,0,0.024) 2px 4px),
    repeating-linear-gradient(23deg,  rgba(226,200,146,0.011) 0 3px, rgba(0,0,0,0.018) 3px 6px);

  /* Ground: the real tileset textures, cut to a seamless cell by
     tools/gen-home-tiles.js. Served from R2 like every other game
     texture; a 404 just leaves the gradient underneath. */
  --hp-ground: url("/assets/textures/home/tile-base.png");

  /* Default zone mood, replaced per race below. */
  --mood-a:   #5a4a33;
  --mood-b:   #241c13;
  --mood-rim: rgba(200,172,120,0.32);
  --mood-ink: #e9dcbe;
}

/* Tileset moods. These are the mood of a ZONE, not a race colour: the
   race's own --race / --race-ink from tokens.css still carry the data
   inside the zone. Lordaeron summer, Barrens, Ashenvale, Northrend. */
body.hp-page [data-race="H"] {
  --mood-a: #4c6636; --mood-b: #22301a; --mood-rim: rgba(154,184,104,0.34); --mood-ink: #d8e4bc;
  --hp-ground: url("/assets/textures/home/tile-h.png");
}
body.hp-page [data-race="O"] {
  --mood-a: #7a5527; --mood-b: #3a2813; --mood-rim: rgba(204,152,82,0.34); --mood-ink: #ecd7ab;
  --hp-ground: url("/assets/textures/home/tile-o.png");
}
body.hp-page [data-race="E"] {
  --mood-a: #305a52; --mood-b: #182e2c; --mood-rim: rgba(112,172,160,0.34); --mood-ink: #cbe4dd;
  --hp-ground: url("/assets/textures/home/tile-e.png");
}
body.hp-page [data-race="U"] {
  --mood-a: #5a6676; --mood-b: #282e37; --mood-rim: rgba(172,186,202,0.34); --mood-ink: #e2e6ec;
  --hp-ground: url("/assets/textures/home/tile-u.png");
}

/* Page backdrop. The tile is the ground the whole page sits on, held
   down under a heavy wash so it reads as material and never as
   pattern; the parchment light at the top is what keeps the fold from
   going flat. */
body.hp-page {
  background:
    var(--hp-grain),
    radial-gradient(ellipse 78% 34% at 50% 0%, rgba(240,214,158,0.09), transparent 62%),
    linear-gradient(180deg, rgba(34,27,20,0.90), rgba(34,27,20,0.965)),
    var(--hp-ground) repeat 0 0 / 224px 224px,
    var(--bg);
}


/* ══════════════════════════════════════════════════════════════
   SHARED PLATE RECIPE
   Chamfered corners on an eight-point clip, a hard black outline and
   one struck highlight along the top. clip-path drops outer shadows,
   so every edge here is inset. Two metals: stone at rest, bronze for
   the page's one primary action.
   ══════════════════════════════════════════════════════════════ */

.hp-plate {
  position: relative;
  border: 0;
  border-radius: 0;
  clip-path: polygon(
    var(--hp-chamfer) 0, calc(100% - var(--hp-chamfer)) 0,
    100% var(--hp-chamfer), 100% calc(100% - var(--hp-chamfer)),
    calc(100% - var(--hp-chamfer)) 100%, var(--hp-chamfer) 100%,
    0 calc(100% - var(--hp-chamfer)), 0 var(--hp-chamfer));
  background:
    var(--hp-grain),
    linear-gradient(180deg, var(--surface-2), var(--surface) 62%, var(--bg-deep));
  box-shadow:
    inset 0 0 0 1px var(--hp-outline),
    inset 0 1px 0 var(--hp-strike),
    inset 0 -10px 16px -12px rgba(0,0,0,0.7);
  color: var(--text);
  font-family: inherit;
}
.hp-plate:hover {
  background:
    var(--hp-grain),
    linear-gradient(180deg, var(--surface-3), var(--surface-2) 62%, var(--bg-deep));
}

/* Bronze. Same geometry, struck brighter, dark ink on top. */
.hp-plate-bronze {
  background:
    var(--hp-grain),
    linear-gradient(180deg,
      var(--accent-strong) 0, var(--accent-strong) 1px,
      var(--accent) 1px, var(--accent) 46%,
      var(--accent-deep) 100%);
  box-shadow:
    inset 0 0 0 1px var(--hp-outline),
    inset 0 1px 0 rgba(255,240,196,0.45),
    inset 0 -2px 0 rgba(0,0,0,0.34);
  color: var(--text-on-accent);
}
.hp-plate-bronze:hover {
  background:
    var(--hp-grain),
    linear-gradient(180deg,
      #e6b163 0, #e6b163 1px,
      var(--accent-strong) 1px, var(--accent-strong) 46%,
      var(--accent) 100%);
}

/* Engraved lettering: a serif face, tracked wide, with the lit pixel
   BELOW the glyphs so the words read as struck into the stone rather
   than raised off it. Same trick as .dom-label in dominance.css. */
.hp-engrave {
  font-family: Georgia, 'Times New Roman', serif;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: #cbb78d;
  text-shadow: 0 1px 0 rgba(240,214,158,0.16);
}

/* Icon button: a stone plate at a 44px target with a 36px glyph in it.
   Every icon-only control on this page is one of these, and every one
   of them carries an aria-label and a title. */
.hp-icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: var(--hit-min);
  height: var(--hit-min);
  padding: 0;
  cursor: pointer;
  color: var(--text-muted);
  transition: color var(--dur-fast) var(--ease);
}
.hp-icon-btn:hover { color: var(--text); }
.hp-icon-btn svg { width: 22px; height: 22px; }
.hp-icon-btn[aria-expanded="true"] {
  color: var(--text);
  box-shadow:
    inset 0 0 0 1px var(--accent),
    inset 0 1px 0 var(--hp-strike);
}


/* ══════════════════════════════════════════════════════════════
   HERO BAND
   Nav, then this: the proposition, the one primary action, and the
   four heroes that ARE the race filter. A patch of Warcraft III
   ground with the page's content standing on it.
   ══════════════════════════════════════════════════════════════ */

.hp-hero {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  width: 100%;
  /* body is a flex column (main.css, for viewer.html's #app). `overflow:
     hidden` zeroes a flex item's automatic minimum size, so with the page
     taller than the viewport the column shrank this band to its border:
     1px, content and all. Never let it shrink. */
  flex: 0 0 auto;
  background:
    linear-gradient(180deg, var(--mood-a), var(--mood-b));
  transition: background 420ms var(--ease);
}

/* The ground itself, then the wash that holds it down. Both are
   pseudo-elements under the content: the tile at low strength, a
   vignette pulling the edges dark, and a parchment light at the top
   left so the band has a direction to it. */
.hp-hero::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background:
    var(--hp-grain),
    radial-gradient(ellipse 62% 84% at 16% 0%, rgba(240,214,158,0.15), transparent 62%),
    /* The scrim. The copy column sits on the left, and a tileset is not
       free to be any lightness it likes underneath it: Northrend snow put
       the sub-line at 3.1:1, under AA, while Barrens dirt was at 6.9.
       Weighting the dim to the left holds every mood to the same reading
       and gives the band a direction at the same time. */
    linear-gradient(90deg, rgba(10,7,4,0.78) 0%, rgba(10,7,4,0.62) 38%, rgba(10,7,4,0.10) 74%, transparent 100%),
    radial-gradient(ellipse 128% 104% at 50% 54%, transparent 28%, rgba(10,7,4,0.86) 100%),
    linear-gradient(180deg, rgba(14,10,6,0.44), rgba(14,10,6,0.62)),
    var(--hp-ground) repeat 0 0 / 224px 224px;
}


.hp-hero-inner {
  position: relative;
  z-index: 1;
  max-width: var(--page-max);
  margin: 0 auto;
  padding: var(--sp-4) var(--page-gutter);
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(430px, 44%);
  align-items: center;
  gap: var(--sp-6);
}

.hp-hero-copy {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--sp-2);
  min-width: 0;
}

.hp-hero-tagline {
  margin: 0;
  font-size: clamp(1.45rem, 2.2vw, 1.95rem);
  font-weight: 800;
  line-height: 1.2;
  color: var(--text);
  /* No ellipsis: this wraps on narrow screens (house rule). */
  overflow-wrap: anywhere;
  text-shadow: 0 2px 0 rgba(0,0,0,0.55);
}
.hp-hero-tagline em {
  font-style: normal;
  color: #f3d79a;
}

.hp-hero-sub {
  margin: 0;
  font-size: var(--fs-lg);
  line-height: 1.4;
  color: var(--text-muted);
  text-shadow: 0 1px 0 rgba(0,0,0,0.5);
}

/* Drop zone. The dashed frame is the drag target; the bronze plate
   inside it is the button. */
.hp-drop {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  width: 100%;
  padding: var(--sp-2);
  border: 1.5px dashed rgba(226,200,146,0.28);
  background: rgba(12,9,6,0.42);
  transition: border-color var(--dur) var(--ease), background var(--dur) var(--ease);
}
.hp-drop.hero-tile-dragover {
  border-style: solid;
  border-color: var(--accent);
  background: var(--accent-soft);
}

.hp-drop-cta {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  min-height: var(--hit-min);
  padding: var(--sp-2) var(--sp-4);
  cursor: pointer;
  text-align: left;
  font-size: var(--fs-base);
  font-weight: 800;
  transition: transform var(--dur-fast) var(--ease);
}
.hp-drop-cta:active { transform: translateY(1px); }
.hp-drop-cta svg { flex-shrink: 0; }
.hp-drop-label { min-width: 0; overflow-wrap: anywhere; }
.hp-drop-status {
  margin-left: auto;
  font-size: var(--fs-min);
  font-weight: 600;
  opacity: 0.8;
}
.hp-drop-status:empty { display: none; }

/* The privacy guarantee, as a glyph. The sentence it replaces was
   always-on explanatory text; the promise itself is in the label and
   the title, and it stays reachable by keyboard. */
.hp-drop-shield {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: var(--hit-min);
  height: var(--hit-min);
  color: var(--privacy);
  cursor: help;
}
.hp-drop-shield svg { width: 22px; height: 22px; }

.hp-hero-bands {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--sp-2) var(--sp-4);
}

/* The Build Finder signpost. One line, where a full-width banner used
   to sit. */
.hp-new-link {
  font-size: var(--fs-label);
  color: var(--text-muted);
  text-decoration: underline;
  text-underline-offset: 3px;
  white-space: nowrap;
}
.hp-new-link:hover { color: var(--text); }


/* ══════════════════════════════════════════════════════════════
   DESKTOP BAND
   One row: the name, three claims and the button, all centred on
   the same line. Every item is single-line by construction, which
   is the whole point — the version this replaced stacked a note
   under each claim and centred each mark on its own block, so the
   three labels sat at three different heights.

   Glyphs are stroke SVGs at the weight the rest of the page's
   controls use. No unit art here: Blizzard icons identify a game
   thing, and "overlay for OBS" is not one.
   ══════════════════════════════════════════════════════════════ */

.hp-app {
  position: relative;
  width: 100%;
  /* body is a flex column: same trap as .hp-hero, never let it shrink. */
  flex: 0 0 auto;
  /* COOL, on a warm page, and on purpose. Two earlier tries painted this
     strip in the page's own browns and then in a copper wash, which put
     bronze on bronze on brown: the whole fold went one hue and the band
     had nothing to stand against.

     The slate is not a new colour. It is tokens.css :root, the site
     chrome the viewer and the other eight pages wear, so warm bronze over
     cool slate is a relationship this product already has. It is also the
     one dark hue that cannot be read as data: blue, red, green and purple
     each name a race, and navy is what the site uses for chrome precisely
     because it names none of them.

     The values are inlined rather than taken from :root, because :root is
     repainted warm under body.hp-page. */
  background:
    var(--hp-grain),
    linear-gradient(180deg, #363c58, #262b41 46%, #1b1f30 80%, #12131f);
  border-top: 1px solid var(--hp-outline);
  border-bottom: 1px solid var(--hp-outline);
  box-shadow:
    inset 0 1px 0 rgba(190,205,240,0.20),
    0 1px 0 var(--hp-strike);
}

.hp-app-inner {
  max-width: var(--page-max);
  margin: 0 auto;
  padding: var(--sp-2) var(--page-gutter);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-2) var(--sp-4);
  min-height: 60px;
}

/* Name and terms, one line. The button says Download and nothing
   else, so the two facts that answer "should I" live here. */
.hp-app-id {
  display: flex;
  /* centre, not baseline: the mark is a 36px box and a baseline row
     would hang it off the text. */
  align-items: center;
  flex-wrap: wrap;
  gap: var(--sp-1) var(--sp-2);
  margin: 0;
  min-width: 0;
}
/* The mark. Same metal as the button at the other end of the strip,
   so the two bronze objects bracket the claims between them. */
.hp-app-mark {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 36px;
  height: 36px;
  --hp-chamfer: 6px;
}
.hp-app-mark svg { width: 22px; height: 22px; }

.hp-app-name {
  font-size: var(--fs-lg);
  font-weight: 800;
  color: var(--accent-strong);
  white-space: nowrap;
}
.hp-app-free {
  font-size: var(--fs-label);
  /* --text-dim clears only 4.0 on the lighter plate; this is 5.9. */
  color: var(--text-muted);
  white-space: nowrap;
}

/* The three claims. Equal-width columns were what made this ragged:
   the labels are 15 to 32 characters, so a fixed column left one
   label touching the next glyph and another with 80px of air. Auto
   widths with one gap and a carved groove between them reads as a
   list instead. */
.hp-app-points {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-2) 0;
  flex: 1 1 460px;
  list-style: none;
  margin: 0;
  padding: 0;
  min-width: 0;
}
.hp-app-point {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  padding: 0 var(--sp-3);
  min-width: 0;
  font-size: var(--fs-label);
  font-weight: 700;
  color: var(--text);
  /* A claim is atomic: it wraps as a whole item or not at all. Letting
     the words break put "Overlay for OBS" on a second line under the
     first claim with no groove in front of it, which read as a fault. */
  white-space: nowrap;
}
.hp-app-point:first-child { padding-left: 0; }
/* A groove, the vertical twin of .hp-pop-rule: one dark line, one
   struck highlight beside it. */
.hp-app-point + .hp-app-point {
  border-left: 1px solid var(--hp-outline);
  box-shadow: inset 1px 0 0 var(--hp-strike);
}
.hp-app-glyph {
  width: 24px;
  height: 24px;
  flex-shrink: 0;
  color: var(--accent-strong);
}

/* Stone, not bronze: the drop zone is the page's one primary action. */
.hp-app-cta {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  margin-left: auto;
  min-height: var(--hit-min);
  padding: var(--sp-2) var(--sp-4);
  font-size: var(--fs-base);
  font-weight: 800;
  color: var(--text-on-accent);
  white-space: nowrap;
  text-decoration: none;
}
.hp-app-cta:hover { color: var(--text-on-accent); text-decoration: none; }
.hp-app-cta svg { width: 22px; height: 22px; flex-shrink: 0; }
.hp-app-version {
  font-size: var(--fs-label);
  font-weight: 700;
  color: rgba(29, 20, 5, 0.66);
}


/* ══════════════════════════════════════════════════════════════
   RACE STAGE
   Four heroes on a slab. HeroStage.js draws into the canvas and
   toggles data-state / .is-loaded; the buttons under it are the hit
   targets, the accessibility surface and the fallback, and they work
   identically whether or not a single model ever arrives.
   ══════════════════════════════════════════════════════════════ */

.hp-stage {
  position: relative;
  /* HeroStage reads this box with a ResizeObserver and frames the camera
     from it, so the height is free to tune here and the models follow. */
  height: clamp(210px, 26vh, 288px);
  min-width: 0;
}

.hp-stage-canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  z-index: 0;
}
.hp-stage[data-state="fallback"] .hp-stage-canvas,
.hp-stage[data-state="off"] .hp-stage-canvas { visibility: hidden; }

.hp-stage-slots {
  position: absolute;
  inset: 0;
  z-index: 1;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--sp-2);
}

.hp-stage-slot {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-end;
  gap: var(--sp-2);
  min-width: 0;
  min-height: var(--hit-min);
  padding: var(--sp-2) 0;
  border: 0;
  background: none;
  cursor: pointer;
  font-family: inherit;
  color: var(--mood-ink);
}
.hp-stage-slot:focus-visible {
  outline: 2px solid var(--race);
  outline-offset: -3px;
}

/* The portrait plate: the picker before any model lands, and the whole
   picker forever on a phone or without WebGL. Chamfered stone with the
   race's own ground under the portrait. */
.hp-stage-plate {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 76px;
  height: 76px;
  transition: opacity 360ms var(--ease), box-shadow var(--dur) var(--ease);
  clip-path: polygon(9px 0, calc(100% - 9px) 0, 100% 9px, 100% calc(100% - 9px),
                     calc(100% - 9px) 100%, 9px 100%, 0 calc(100% - 9px), 0 9px);
  background:
    linear-gradient(180deg, rgba(20,15,10,0.35), rgba(10,8,5,0.72)),
    var(--hp-ground) repeat 0 0 / 96px 96px;
  box-shadow:
    inset 0 0 0 1px var(--hp-outline),
    inset 0 0 0 2px var(--mood-rim),
    inset 0 1px 0 var(--hp-strike);
}
.hp-stage-portrait {
  width: 56px;
  height: 56px;
  object-fit: cover;
}
/* Once that slot's model is on the canvas, the portrait steps aside. */
.hp-stage-slot.is-loaded .hp-stage-plate { opacity: 0; }

.hp-stage-slot-label {
  font-size: var(--fs-label);
  font-weight: 700;
  letter-spacing: 0.04em;
  color: var(--mood-ink);
  text-shadow: 0 1px 0 rgba(0,0,0,0.75);
  white-space: nowrap;
}

/* Selected. Bronze ring on the plate, the label lifts to full ink.
   The other three step back rather than the selected one lighting up. */
.hp-stage-slot.is-selected .hp-stage-plate {
  box-shadow:
    inset 0 0 0 1px var(--hp-outline),
    inset 0 0 0 2px var(--accent),
    inset 0 1px 0 rgba(255,240,196,0.30);
}
.hp-stage-slot.is-selected .hp-stage-slot-label { color: var(--text); }
.hp-stage:not([data-selected=""]) .hp-stage-slot:not(.is-selected) .hp-stage-plate { opacity: 0.55; }
.hp-stage:not([data-selected=""]) .hp-stage-slot:not(.is-selected) .hp-stage-slot-label { opacity: 0.6; }
.hp-stage:not([data-selected=""]) .hp-stage-slot.is-loaded:not(.is-selected) .hp-stage-plate { opacity: 0; }

.hp-stage-slot:hover:not(.is-selected) .hp-stage-plate {
  box-shadow:
    inset 0 0 0 1px var(--hp-outline),
    inset 0 0 0 2px var(--mood-rim),
    inset 0 1px 0 var(--hp-strike),
    inset 0 0 24px rgba(0,0,0,0.5);
}

.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}


/* ══════════════════════════════════════════════════════════════
   LIBRARY HEAD + TOOLBAR
   One row: the engraved title and its counts on the left, three
   controls on the right. The two filter rows this replaced spent
   ~90px of the fold on chips most visitors never touch.
   ══════════════════════════════════════════════════════════════ */

body.hp-page .site-pros-head {
  border-bottom: 1px solid var(--hp-outline);
  box-shadow: 0 1px 0 var(--hp-strike);
  padding-bottom: var(--sp-2);
}

/* The two gaps stacked either side of the library head. 16px above it
   and 12px under it put the first card row 28px lower for no reason a
   reader can see. */
body.hp-page .site-content { padding-top: var(--sp-2); }
body.hp-page .site-pros { gap: var(--sp-2); }

body.hp-page .site-pros-title,
body.hp-page .site-mine-title {
  font-size: var(--fs-h3);
}

.hp-toolbar {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  margin-left: auto;
  flex-wrap: wrap;
}

/* Matchup picks. Only reachable once a race is chosen, and only ever
   opponent races that some build in the library actually plays. */
.hp-matchups { display: flex; align-items: center; gap: var(--sp-2); }
.hp-matchups[hidden] { display: none; }
.hp-matchups .pfb-chips { display: flex; align-items: center; gap: var(--sp-1); }

.hp-vs {
  font-family: var(--mono);
  font-size: var(--fs-min);
  font-weight: 700;
  color: var(--text-dim);
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.hp-mu {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--hit-min);
  height: var(--hit-min);
  padding: 0;
  cursor: pointer;
}
.hp-mu img {
  width: 36px;
  height: 36px;
  object-fit: cover;
  box-shadow: inset 0 0 0 1px var(--hp-outline);
  opacity: 0.72;
  transition: opacity var(--dur-fast) var(--ease);
}
.hp-mu:hover img { opacity: 1; }
.hp-mu.active img { opacity: 1; }
.hp-mu.active {
  box-shadow:
    inset 0 0 0 1px var(--hp-outline),
    inset 0 0 0 2px var(--race),
    inset 0 1px 0 var(--hp-strike);
}

/* Menus. The button carries the state; the panel is a chamfered slab
   pinned under its right edge. */
.hp-menu { position: relative; }

.hp-badge {
  position: absolute;
  top: 2px;
  right: 2px;
  min-width: 18px;
  height: 18px;
  padding: 0 4px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-family: var(--mono);
  font-size: var(--fs-min);
  font-weight: 700;
  line-height: 1;
  color: var(--text-on-accent);
  background: linear-gradient(180deg, var(--accent-strong), var(--accent-deep));
  box-shadow: inset 0 0 0 1px var(--hp-outline);
}
.hp-badge[hidden] { display: none; }

.hp-pop {
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  z-index: 60;
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
  width: max-content;
  max-width: min(92vw, 30rem);
  padding: var(--sp-4);
  background:
    var(--hp-grain),
    linear-gradient(180deg, var(--surface), var(--bg-deep));
  box-shadow:
    inset 0 0 0 1px var(--hp-outline),
    inset 0 1px 0 var(--hp-strike),
    var(--shadow-2);
}
/* .hp-pop sets its own display, so the UA sheet's [hidden] rule loses
   without this. Every hidden-toggled element on this page needs it. */
.hp-pop[hidden] { display: none; }

/* Label over chips, never beside them. A fixed label gutter with wrapping
   chips beside it left some rows inline and some stacked, depending purely
   on how many chips that axis happened to have. */
.hp-pop-row {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
}
.hp-pop-row .pfb-pop-chips,
.hp-pop-row .bclass-chips,
.hp-pop-row .bclass-actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-start;
  gap: var(--sp-1);
}
.hp-pop-label {
  font-size: var(--fs-min);
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-dim);
}
.hp-pop-rule {
  height: 1px;
  margin: var(--sp-1) 0;
  background: var(--hp-outline);
  box-shadow: 0 1px 0 var(--hp-strike);
}

/* Upgrades: a switch, because it is on or off for the whole grid. */
.hp-switch {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-4);
  width: 100%;
  min-height: var(--hit-min);
  padding: var(--sp-2) var(--sp-3);
  cursor: pointer;
  font-size: var(--fs-sm);
  font-weight: 600;
}
.hp-switch-track {
  position: relative;
  flex-shrink: 0;
  width: 40px;
  height: 20px;
  background: var(--bg-deep);
  box-shadow: inset 0 0 0 1px var(--hp-outline), inset 0 1px 3px rgba(0,0,0,0.7);
}
.hp-switch-track::after {
  content: '';
  position: absolute;
  top: 3px;
  left: 3px;
  width: 14px;
  height: 14px;
  background: linear-gradient(180deg, var(--surface-4), var(--surface-2));
  box-shadow: inset 0 0 0 1px var(--hp-outline), inset 0 1px 0 var(--hp-strike);
  transition: transform var(--dur) var(--ease), background var(--dur) var(--ease);
}
.hp-switch[aria-checked="true"] .hp-switch-track::after {
  transform: translateX(20px);
  background: linear-gradient(180deg, var(--accent-strong), var(--accent-deep));
}

/* The advanced-search row inside the More filters panel. */
.hp-pop-wide {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  width: 100%;
  min-height: var(--hit-min);
  padding: 0 var(--sp-4);
  cursor: pointer;
  font-size: var(--fs-sm);
  font-weight: 700;
}


/* ══════════════════════════════════════════════════════════════
   RAIL, PILLARS, FOOTER
   ══════════════════════════════════════════════════════════════ */

body.hp-page .site-mine-head { }

.hp-rail-tools {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
}
body.hp-page .mine-sort-select {
  min-height: 36px;
  background: var(--bg-deep);
  color: var(--text);
  box-shadow: inset 0 0 0 1px var(--hp-outline), inset 0 1px 0 var(--hp-strike);
  border: 0;
  border-radius: 0;
}
body.hp-page .mine-toolbar-count { color: var(--text-dim); margin-left: auto; }

body.hp-page .site-mine-empty {
  border: 1.5px dashed rgba(226,200,146,0.24);
  border-radius: 0;
  background: rgba(12,9,6,0.42);
}

/* Pillars: always under the grid now, and thinner. They are a summary
   of what the site does, so they sit after the product rather than
   claiming a column beside it. */
body.hp-page .hp-pillars {
  border-top: 1px solid var(--hp-outline);
  box-shadow: 0 1px 0 var(--hp-strike);
  background: transparent;
  margin-top: var(--sp-5);
}
body.hp-page .hp-pillars-inner {
  max-width: none;
  padding: var(--sp-5) 0 0;
}
body.hp-page .hp-pillars-track {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--sp-4);
}
body.hp-page .hp-pillar {
  background:
    var(--hp-grain),
    linear-gradient(180deg, var(--surface), var(--bg-deep));
  border: 0;
  border-radius: 0;
  box-shadow: inset 0 0 0 1px var(--hp-outline), inset 0 1px 0 var(--hp-strike);
}
body.hp-page .hp-pillar:hover {
  transform: none;
  box-shadow:
    inset 0 0 0 1px var(--hp-outline),
    inset 0 0 0 2px var(--hp-lip),
    inset 0 1px 0 var(--hp-strike);
}
body.hp-page .hp-pillar-media {
  max-height: 128px;
  object-fit: cover;
  object-position: 50% 0;
  border-bottom: 1px solid var(--hp-outline);
}
body.hp-page .hp-pillar-body { padding: var(--sp-3) var(--sp-4) var(--sp-4); }
body.hp-page .hp-pillar-lib .hp-pillar-label { color: #d9c07a; }
body.hp-page .hp-pillar-sim .hp-pillar-label { color: #9fc0c8; }
body.hp-page .hp-pillar-app .hp-pillar-label { color: #c3a8cd; }

body.hp-page .site-footer {
  background: var(--bg-deep);
  border-top: 1px solid var(--hp-outline);
  box-shadow: 0 1px 0 var(--hp-strike);
}


/* ══════════════════════════════════════════════════════════════
   RESPONSIVE
   ══════════════════════════════════════════════════════════════ */

/* The terms go first when the row runs short. Without this the three
   claims had 8px of slack at 1280, which is no slack at all: one font
   substitution and the last claim drops to a second line. */
@media (max-width: 1439px) {
  .hp-app-free { display: none; }
}

/* Narrower than this the claims cannot share a line with the name and
   the button, so they take their own. A wrapped flex row put the third
   claim under the first with a groove hanging off its left edge, which
   read as a bug rather than a layout. */
@media (max-width: 1160px) {
  .hp-app-points { flex: 1 1 100%; order: 3; }
  /* The claims are off this line now, so the terms fit again. They are
     hidden only in the 1161-1439 band, where the row is tight. */
  .hp-app-free { display: inline; }
}

@media (max-width: 1024px) {
  .hp-stage { height: 196px; }
  .hp-stage-plate { width: 68px; height: 68px; }
  .hp-stage-portrait { width: 48px; height: 48px; }
}

/* One column. The stage becomes a plain 4-up row of portraits under
   the copy. Still the race picker, just no longer a diorama. */
@media (max-width: 900px) {
  .hp-hero-inner { grid-template-columns: minmax(0, 1fr); gap: var(--sp-4); }
  .hp-stage { height: auto; }
  .hp-stage-canvas { display: none; }
  .hp-stage-slots { position: static; gap: var(--sp-3); }
  .hp-stage-slot { flex-direction: row; justify-content: flex-start; padding: 0; gap: var(--sp-3); }
  .hp-stage-plate { width: 56px; height: 56px; }
  .hp-stage-portrait { width: 40px; height: 40px; }
  .hp-stage-slot.is-loaded .hp-stage-plate { opacity: 1; }
  body.hp-page .hp-pillars-track { grid-template-columns: 1fr; }
}

@media (max-width: 720px) {
  .hp-hero-inner { padding: var(--sp-4) var(--page-gutter); }
  .hp-drop { flex-wrap: wrap; }
  .hp-drop-cta { flex: 1 1 100%; }
  .hp-stage-slots { grid-template-columns: repeat(2, 1fr); }
  .hp-toolbar { margin-left: 0; }
}

@media (max-width: 640px) {
  .hp-hero-inner { padding-inline: var(--sp-3); }
  .hp-hero-tagline { font-size: 1.35rem; }
  .hp-hero-sub { font-size: var(--fs-base); }
  /* The app is Windows only, so a phone gets the name, the terms and
     the button. Three stacked claims were 90px of band nobody there
     can act on, and /download carries all three. */
  .hp-app-inner { padding-inline: var(--sp-3); }
  .hp-app-points { display: none; }
  .hp-app-cta { width: 100%; justify-content: center; margin-left: 0; }
}

@media (max-width: 480px) {
  .hp-stage-slot-label { font-size: var(--fs-min); }
}

/* Decoration only: a visitor who asks for less motion loses nothing
   here but the fades. */
@media (prefers-reduced-motion: reduce) {
  .hp-hero,
  .hp-stage-plate,
  .hp-switch-track::after { transition: none; }
}
