/* =========================================================================
   CITY RIVALS — the board tile
   -------------------------------------------------------------------------
   Extends the tile rules in styles.css. Everything here has the same
   specificity as the rule it replaces, so this file MUST be linked AFTER
   styles.css (and after styles/cities.css, which only supplies variables).

   It is also NOT OPTIONAL. js/ui.js emits three elements — .tile-rent,
   .tile-house/.tile-hotel and .tile-mult — whose entire appearance is defined
   here. Ship the JS without this file linked and every owned district prints
   its rent permanently at body font size. One <link> in index.html, last of
   the stylesheets.

   Three things a real board does that ours did not:

     1  A building is one mark and a count. Rendering N discrete 4px pips
        meant that at a 33px phone tile "three houses" and "four houses" were
        the same green smear. One glyph plus x3 reads identically at 33px and
        at 130px, and the hotel keeps a silhouette and a colour of its own so
        it is a different building, not a fifth house.

     2  Rent is on the board, on hover and on keyboard focus. Permanently
        would mean 36 numbers competing with 36 names; on demand it costs
        nothing until asked. Never on touch, where hover is a lie.

     3  The set band carries the game and is sized accordingly. See the note
        above THE BAND below — it is the one judgement call in this file.

   Sizes scale off the board's container query (cqw), the same way the tile's
   type already does, so nothing here is tied to a breakpoint.
   ========================================================================= */

/* -------------------------------------------------------------------------
   THE BAND, AND WHO OWNS THE TILE  —  the one judgement call in this file

   Before: the set band was a 12% strip with a 6px floor on the inner edge,
   and ownership was a 4px bar on the outer edge plus a 13% face wash. On a
   real board those two marks measured:

       1440   tile 72px   band 8.4px   owner 4px    2.1 : 1
       1024   tile 48px   band 6.0px   owner 4px    1.5 : 1
        390   tile 32px   band 6.0px   owner 4px    1.5 : 1

   At 1024 and 390 they are the same mark. Same species (a flat colour bar),
   same weight, on opposite edges of a small square — and below 420px, where
   the district name is hidden, they are the ENTIRE tile. Which one is the set
   and which is the owner could only be answered by knowing the convention,
   never by looking. Meanwhile ownership was stated twice (bar AND wash) while
   the set — which is the whole game; every rule about rent, building and
   trading is a rule about sets — was stated once, quietly, and at its
   thinnest exactly where the name had already gone.

   So: the split stays, the ratio changes. The split is right — set faces the
   middle, owner faces the rim, so a lap of the board reads the same from all
   four sides, and the rim bars of one player form a continuous rail down a
   side they have taken. What was wrong is that the two marks were the same
   size. The band becomes a block at 24% with a 9px floor, the proportion a
   physical board uses; the owner bar becomes a rim line of 3-4px:

       1440   band 16.8px   owner 4px    4.2 : 1
       1024   band 11.0px   owner 3px    3.7 : 1
        390   band  9.0px   owner 3px    3.0 : 1

   Size now answers "which is which" before position has to, and the ring
   vocabulary stays free: an outline on a tile still means only two things,
   you-are-here (--city-accent) and inspecting-this (--info). Ownership keeps
   the wash, which is the part that survives when a pile of tokens covers the
   rim of the tile they are standing on.
   ------------------------------------------------------------------------- */
.tile.bottom .tile-band{height:24%;min-height:9px}
.tile.top    .tile-band{height:24%;min-height:9px}
.tile.left   .tile-band{width:24%;min-width:9px}
.tile.right  .tile-band{width:24%;min-width:9px}
/* the same max() so the face always clears the band, floor included */
.tile.bottom{padding-top:calc(max(24%,9px) + 3px)}
.tile.top{padding-bottom:calc(max(24%,9px) + 3px)}
.tile.left{padding-right:calc(max(24%,9px) + 3px)}
.tile.right{padding-left:calc(max(24%,9px) + 3px)}

.tile.bottom .tile-owner,.tile.corner .tile-owner{height:clamp(3px,.55cqw,4px)}
.tile.top    .tile-owner{height:clamp(3px,.55cqw,4px)}
.tile.left   .tile-owner{width:clamp(3px,.55cqw,4px)}
.tile.right  .tile-owner{width:clamp(3px,.55cqw,4px)}

/* The price line is --tile-sub, a token cities.css designs to 3:1 on a bare
   tile face. Measured on an OWNED face — the same token under a 13% wash of
   an arbitrary player colour — it lands at 2.85:1 in Harbour Bay dark and
   4.07:1 in Harbour Bay light. Across six cities, two themes and three widths,
   167 price lines measured under 4.5 and nothing else on the tile did. That is
   a pre-existing failure this file inherits rather than causes, and it is cheap
   to close: on an owned tile the price takes the tile's proper ink. It stays
   subordinate to the district name through size and weight, not through a
   contrast deficit. Worst case afterwards: 5.26:1. */
.tile.is-owned .tile-price{color:var(--tile-ink)}
/* the transit / utility glyph is the same --tile-sub token and the only mark
   those tiles carry below 420px, where the name is hidden; it measured 3.9:1
   on an owned face. It is decoration (aria-hidden, and the name repeats it),
   so 3:1 would be defensible — but it costs nothing to hold it to the same
   bar as everything else on the tile, and it makes ownership read on a hub. */
.tile.is-owned .tile-icon{color:var(--tile-ink)}

/* -------------------------------------------------------------------------
   BUILDINGS — one mark, one count
   The row reserves its own height whether or not anything is built, so the
   district name does not jump down the tile the moment a house goes up.
   ------------------------------------------------------------------------- */
.tile-build{
  gap:clamp(1px,.28cqw,3px);
  min-height:clamp(6px,1.15cqw,11px);
}
/* a house: square with a roof. Flat --positive fill, no outline, no shadow */
.tile-house{
  width:clamp(5px,.95cqw,9px);
  height:clamp(6px,1.15cqw,11px);
  border-radius:0;
  background:var(--positive);
  clip-path:polygon(50% 0,100% 40%,100% 100%,0 100%,0 40%);
}
/* a hotel: a stepped block, wider and taller-shouldered than a house, in
   --gold. Different shape AND different colour, so it never reads as "the
   houses again" under a colour-blind filter. */
.tile-hotel{
  width:clamp(10px,1.85cqw,18px);
  height:clamp(6px,1.15cqw,11px);
  border-radius:0;
  background:var(--gold);
  clip-path:polygon(0 100%,0 34%,36% 34%,36% 0,100% 0,100% 100%);
}
/* The count is text on the tile face, so it takes the tile's own ink rather
   than the building's colour: --positive on a light tile under a dark owner
   wash lands near 4:1, and this has to clear 4.5:1 on every city and both
   themes. --tile-ink is the token that is guaranteed to. */
.tile-mult{
  font-family:var(--font-display);
  font-variant-numeric:tabular-nums;
  font-size:clamp(7px,1.15cqw,11px);
  font-weight:700;
  line-height:1;
  letter-spacing:-.02em;
  color:var(--tile-ink);
}
/* the pop belongs to the glyph (styles.css already animates .just-built on
   it); the count is part of the same building, so it goes up with it */
.tile-house.just-built + .tile-mult,
.tile-hotel.just-built + .tile-mult{animation:build-pop 260ms var(--ease)}

/* -------------------------------------------------------------------------
   RENT ON DEMAND
   An opaque chip rather than bare text. The face underneath is one of six
   city surfaces in one of two themes carrying a 13% wash of any of eight
   player colours; bare text would have to be legible on all of them. A chip
   brings its own ground, so --ink on --surface is the only pairing that
   matters, and it measures 15.4:1 dark and 17.4:1 light everywhere.
   ------------------------------------------------------------------------- */
/* ui.js also puts the `hidden` attribute on this element, so that a build in
   which this file has not been linked yet does not print a rent figure across
   every owned district. The rules below are author-origin and therefore beat
   the UA's [hidden] rule when the tile is actually pointed at. */
.tile-rent{
  display:none;
  position:absolute;left:50%;top:50%;
  transform:translate(-50%,-50%);
  z-index:1;
  max-width:calc(100% - 4px);
  padding:1px clamp(2px,.42cqw,5px);
  border-radius:var(--r-sm);
  background:var(--surface);
  border:1px solid var(--line);
  /* the chip is not in the layout — it sits ON the tile for as long as you
     point at it — so it may cast, and --e1 is the smallest thing that says so */
  box-shadow:var(--e1);
  color:var(--ink);
  font-family:var(--font-display);
  font-variant-numeric:tabular-nums;
  font-size:clamp(7px,1.2cqw,12px);
  font-weight:700;
  line-height:1.25;
  white-space:nowrap;
  overflow:hidden;text-overflow:ellipsis;
  pointer-events:none;
}
/* A mortgaged district earns nothing, and its centre already carries the MTG
   stamp — so there is no chip to show and nothing to collide with.

   The name and price go invisible (not display:none — nothing may shift) for
   as long as the chip is up. A chip parked over the middle of a word leaves
   the first and last letters poking out either side, which reads as damage;
   and while you are asking what a square costs, its price and its name are
   the two facts you are least short of. */
.tile.is-owned:not(.tile-mortgaged):focus-visible .tile-rent{display:block}
.tile.is-owned:not(.tile-mortgaged):focus-visible .tile-name,
.tile.is-owned:not(.tile-mortgaged):focus-visible .tile-price{visibility:hidden}
@media (hover:hover) and (pointer:fine){
  .tile.is-owned:not(.tile-mortgaged):hover .tile-rent{display:block}
  .tile.is-owned:not(.tile-mortgaged):hover .tile-name,
  .tile.is-owned:not(.tile-mortgaged):hover .tile-price{visibility:hidden}
}

/* -------------------------------------------------------------------------
   REDUCED MOTION — the building pop is a game event, and game events stop
   ------------------------------------------------------------------------- */
@media (prefers-reduced-motion:reduce){
  .tile-house.just-built + .tile-mult,
  .tile-hotel.just-built + .tile-mult{animation:none}
}
body.no-anim .tile-house.just-built + .tile-mult,
body.no-anim .tile-hotel.just-built + .tile-mult{animation:none}
