/* pz.css - Project Zomboid detail page.
   Loaded after g-base.css (design tokens) and srv.css (shared server-page
   layer), and only by zomboid.php. Everything tints from --accent, which
   .srv-body sets to --g-pz.

   The look is a field dossier: hairline rules, uppercase micro-labels, stamped
   status chips, tabular figures. Nothing here overrides srv.css; it adds. */

/* This page leans hard on 9-10px uppercase micro-labels - the quad captions,
   the dossier row keys, the section rules. At the global --g-text-4 (#43454f)
   those measure 1.89:1 against the card surface, which is unreadable on a dim
   screen and well under the 4.5:1 that small text needs. Lifted here rather
   than in g-base.css so the change is scoped to the page that has the problem;
   #8a8c99 measures 4.8:1 on --g-surf-2 and still reads as a quiet label. */
.srv-body { --g-text-4: #8a8c99; }

/* Wide sections that break out of the two-column .srv-grid. */
.pz-wide { display: flex; flex-direction: column; gap: 18px; }

/* ------------------------------------------------------------------ hero */
.pz-hero {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 18px;
  align-items: center;
  padding: 16px 18px;
  border-radius: 12px;
  border: 1px solid color-mix(in srgb, var(--accent) 26%, var(--g-border));
  background:
    radial-gradient(700px 220px at 12% 0%, color-mix(in srgb, var(--accent) 13%, transparent), transparent 70%),
    var(--g-surf);
}
.pz-hero-main { display: flex; flex-direction: column; gap: 10px; min-width: 0; }
.pz-hero-top { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; }

.pz-live {
  display: inline-flex; align-items: center; gap: 7px;
  font-size: 11px; font-weight: 800; letter-spacing: 1.3px;
  color: var(--accent);
}
.pz-live-dot {
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 0 0 color-mix(in srgb, var(--accent) 65%, transparent);
  animation: pz-ping 2s infinite;
}
.pz-live-dot.is-off { background: var(--g-text-4); animation: none; box-shadow: none; }
@keyframes pz-ping {
  70%  { box-shadow: 0 0 0 9px transparent; }
  100% { box-shadow: 0 0 0 0 transparent; }
}

.pz-facts { display: flex; gap: 10px; flex-wrap: wrap; align-items: baseline; }
.pz-fact { font-size: 12.5px; color: var(--g-text-3); }
.pz-fact strong {
  color: var(--g-text); font-weight: 700;
  font-family: ui-monospace, Consolas, monospace;
  font-variant-numeric: tabular-nums;
}
.pz-sep { color: var(--g-border); }

.pz-motd { font-size: 12.5px; color: var(--g-text-3); }

/* ----------------------------------------------------------- world clock */
.pz-clock { display: grid; grid-template-columns: auto 1fr; gap: 12px; align-items: center; }
.pz-dial {
  position: relative;
  width: 54px; height: 54px; border-radius: 50%;
  border: 1px solid var(--g-border);
  /* Night wraps midnight, so it is two stops rather than one band. */
  background: conic-gradient(from 180deg,
      #17202c 0deg 75deg,
      #2b3a4a 75deg 105deg,
      #3d5570 105deg 255deg,
      #2b3a4a 255deg 285deg,
      #17202c 285deg 360deg);
  flex: none;
}
.pz-dial::after {
  content: ''; position: absolute; inset: 9px;
  border-radius: 50%; background: var(--g-surf);
  border: 1px solid var(--g-border);
}
.pz-hand {
  position: absolute; left: 50%; top: 50%;
  width: 2px; height: 21px; margin-left: -1px;
  transform-origin: 50% 100%;
  transform: translateY(-100%) rotate(var(--pz-ang, 0deg));
  background: var(--accent);
  border-radius: 2px;
  z-index: 1;
  transition: transform .5s linear;
}
.pz-dial-ico {
  position: absolute; inset: 0; display: grid; place-items: center; z-index: 2;
}
.pz-dial-ico .ico { width: 15px; height: 15px; color: var(--g-text-3); }

.pz-clock-read { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.pz-clock-label {
  font-size: 10px; letter-spacing: 1px; text-transform: uppercase; color: var(--g-text-4);
}
.pz-clock-time {
  font-family: ui-monospace, Consolas, monospace;
  font-size: 21px; font-weight: 800; letter-spacing: -0.5px;
  font-variant-numeric: tabular-nums;
  color: var(--g-text);
}
.pz-clock-date { font-size: 12px; color: var(--g-text-3); }
.pz-clock.is-paused .pz-hand { animation: none; }
.pz-clock.is-paused .pz-clock-time { color: var(--g-text-3); }

/* ---------------------------------------------------------------- totals */
.pz-totals {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(126px, 1fr));
  gap: 1px;
  background: var(--g-border);
  border: 1px solid var(--g-border);
  border-radius: 12px;
  overflow: hidden;
}
.pz-total { padding: 13px 15px; background: var(--g-surf); }
.pz-total-num {
  display: block;
  font-family: ui-monospace, Consolas, monospace;
  font-size: 22px; font-weight: 800; letter-spacing: -0.8px;
  font-variant-numeric: tabular-nums;
  color: var(--accent);
}
.pz-total-lbl {
  display: block; margin-top: 2px;
  font-size: 10px; letter-spacing: 0.9px; text-transform: uppercase;
  color: var(--g-text-3);
}

/* ------------------------------------------------------------- dossiers */
.pz-dossiers {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(330px, 1fr));
  gap: 18px;
}

.pz-card {
  display: flex; flex-direction: column;
  background: var(--g-surf);
  border: 1px solid var(--g-border);
  border-radius: 12px;
  overflow: hidden;
  transition: border-color .18s, transform .18s;
}
.pz-card:hover { border-color: color-mix(in srgb, var(--accent) 40%, var(--g-border)); }
.pz-card.is-focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--accent) 45%, transparent);
}
.pz-card.is-dead { background: color-mix(in srgb, var(--g-surf) 92%, #000); }

.pz-card-h {
  display: grid; grid-template-columns: 46px 1fr auto;
  gap: 12px; align-items: center;
  padding: 14px 16px;
  border-bottom: 1px solid var(--g-border);
  background: var(--g-surf-2);
}

/* Avatar: initials on a hue derived from the survivor's own name, so two
   characters never collide by accident and the same person keeps their colour
   across a wipe. --pz-hue is set inline by PHP. */
.pz-ava {
  position: relative;
  width: 46px; height: 46px; border-radius: 10px;
  display: grid; place-items: center;
  font-family: ui-monospace, Consolas, monospace;
  font-size: 15px; font-weight: 800; letter-spacing: -0.5px;
  color: hsl(var(--pz-hue, 0) 55% 82%);
  background: hsl(var(--pz-hue, 0) 32% 22%);
  border: 1px solid hsl(var(--pz-hue, 0) 34% 34%);
}
/* With a headshot in it the tile is just a frame, so the hue drops back to a
   tint behind the transparent corners rather than a solid block. */
.pz-ava.has-head {
  overflow: hidden;
  background: hsl(var(--pz-hue, 0) 24% 16%);
  border-color: hsl(var(--pz-hue, 0) 26% 28%);
}
.pz-ava.has-head img {
  display: block; width: 100%; height: 100%;
  object-fit: cover; object-position: 50% 22%;
  /* Downscaled from 128px, so smoothing is right here - unlike the item icons,
     which are pixel art shown at native size. */
  image-rendering: auto;
}
/* Desaturated rather than greyscale, so the initials stay legible under the
   cross and the survivor keeps a hint of their own colour. */
.pz-card.is-dead .pz-ava { filter: saturate(.28); }
.pz-ava-x {
  position: absolute; inset: -1px; border-radius: 10px;
  background:
    linear-gradient(to bottom right, transparent calc(50% - 1px),
      color-mix(in srgb, var(--g-pz) 62%, transparent) calc(50% - 1px),
      color-mix(in srgb, var(--g-pz) 62%, transparent) calc(50% + 1px), transparent calc(50% + 1px)),
    linear-gradient(to bottom left, transparent calc(50% - 1px),
      color-mix(in srgb, var(--g-pz) 62%, transparent) calc(50% - 1px),
      color-mix(in srgb, var(--g-pz) 62%, transparent) calc(50% + 1px), transparent calc(50% + 1px));
}

.pz-who { min-width: 0; }
.pz-name {
  margin: 0; font-size: 15.5px; font-weight: 800; letter-spacing: -0.25px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.pz-handle {
  display: block; margin-top: 1px;
  font-family: ui-monospace, Consolas, monospace;
  font-size: 11.5px; color: var(--g-text-3);
}

.pz-stamp {
  align-self: start;
  padding: 3px 8px; border-radius: 5px;
  font-size: 9.5px; font-weight: 800; letter-spacing: 1.1px;
  border: 1px solid;
}
.pz-stamp.alive {
  color: var(--g-green, #4ade80);
  border-color: color-mix(in srgb, var(--g-green, #4ade80) 45%, transparent);
  background: color-mix(in srgb, var(--g-green, #4ade80) 12%, transparent);
}
.pz-stamp.dead {
  color: var(--g-pz);
  border-color: color-mix(in srgb, var(--g-pz) 50%, transparent);
  background: color-mix(in srgb, var(--g-pz) 12%, transparent);
}

.pz-card-b { padding: 14px 16px; display: flex; flex-direction: column; gap: 14px; }

/* --- sprites cut from the game's own texture packs --- */
/* One rule for both atlases: --x/--y/--w/--h address a rect, and the element
   sizes itself to that rect. Nothing here knows what it is drawing. */
/* --k scales a sprite by also scaling the backdrop, which is the only way to
   resize one tile of an atlas without cropping its neighbours; --aw/--ah are
   the atlas dimensions, set per atlas below. */
.pz-sp {
  --k: 1;
  display: inline-block; flex: none;
  width: calc(var(--w) * var(--k) * 1px);
  height: calc(var(--h) * var(--k) * 1px);
  background-repeat: no-repeat;
  background-size: calc(var(--aw) * var(--k) * 1px) calc(var(--ah) * var(--k) * 1px);
  background-position: calc(var(--x) * var(--k) * -1px) calc(var(--y) * var(--k) * -1px);
  /* Pixel art: never let the browser smooth it. */
  image-rendering: pixelated;
}
.pz-ic {
  background-image: var(--pz-items);
  --aw: var(--pz-items-w); --ah: var(--pz-items-h);
  vertical-align: -3px;
}
/* A profession badge is drawn much larger than an inventory icon, so it needs
   bringing back in line with the row it sits in. */
.pz-row-ic .pz-ic { --k: .58; }

/* --- the figure column: 3D avatar or health panel --- */
.pz-viz { display: flex; flex-direction: column; gap: 7px; flex: none; }
.pz-viz-stage { position: relative; }
/* One or the other, never both. The 3D view is default when it exists. */
.pz-viz .pz-fig { display: none; }
.pz-viz.no-3d .pz-fig,
.pz-viz.show-hp .pz-fig { display: block; }
.pz-viz.show-hp .pz-av { display: none; }
/* If WebGL is missing or an asset fails, fall back rather than showing a hole. */
.pz-viz .pz-av.is-failed { display: none; }
.pz-viz .pz-av.is-failed ~ .pz-fig { display: block; }

.pz-av {
  position: relative;
  width: calc(var(--fw, 123) * var(--fs, .72) * 1px);
  height: calc(var(--fh, 302) * var(--fs, .72) * 1px);
  border-radius: 9px;
  background:
    radial-gradient(70% 50% at 50% 30%, color-mix(in srgb, var(--accent) 12%, transparent), transparent 72%),
    var(--g-surf-2);
  border: 1px solid var(--g-border);
  overflow: hidden;
  cursor: grab;
  touch-action: pan-y;
}
.pz-av.is-drag { cursor: grabbing; }
.pz-av canvas { display: block; width: 100%; height: 100%; }
.pz-viz-tabs { display: flex; gap: 4px; }
.pz-vt {
  flex: 1; padding: 3px 0; border-radius: 6px;
  font: inherit; font-size: 10px; font-weight: 700; letter-spacing: .4px;
  color: var(--g-text-4); background: var(--g-surf-2);
  border: 1px solid var(--g-border); cursor: pointer;
}
.pz-vt:hover { color: var(--accent); }
.pz-vt[aria-pressed="true"] {
  color: var(--accent); border-color: color-mix(in srgb, var(--accent) 50%, var(--g-border));
  background: color-mix(in srgb, var(--accent) 12%, var(--g-surf-2));
}

.pz-split { display: grid; grid-template-columns: auto 1fr; gap: 14px; align-items: start; }
.pz-split-r { display: flex; flex-direction: column; gap: 12px; min-width: 0; }

.pz-fig {
  width: calc(var(--fw) * var(--fs) * 1px);
  height: calc(var(--fh) * var(--fs) * 1px);
  flex: none;
  border-radius: 9px;
  background:
    radial-gradient(60% 45% at 50% 34%, color-mix(in srgb, var(--accent) 10%, transparent), transparent 70%),
    var(--g-surf-2);
  border: 1px solid var(--g-border);
  overflow: hidden;
}
.pz-fig-in {
  position: relative;
  width: calc(var(--fw) * 1px); height: calc(var(--fh) * 1px);
  transform: scale(var(--fs)); transform-origin: top left;
}
.pz-fig-base { background-image: var(--pz-body); display: block;
  --aw: var(--pz-body-w); --ah: var(--pz-body-h); }
.pz-fig-ov {
  background-image: var(--pz-body);
  --aw: var(--pz-body-w); --ah: var(--pz-body-h);
  position: absolute;
  left: calc(var(--ox) * 1px); top: calc(var(--oy) * 1px);
}
.pz-card.is-dead .pz-fig { border-color: color-mix(in srgb, var(--g-pz) 28%, var(--g-border)); }

.pz-quad {
  display: grid; grid-template-columns: repeat(4, 1fr);
  gap: 1px; background: var(--g-border);
  border: 1px solid var(--g-border); border-radius: 8px; overflow: hidden;
}
.pz-q { padding: 9px 10px; background: var(--g-surf-2); text-align: center; }
.pz-q-num {
  display: block;
  font-family: ui-monospace, Consolas, monospace;
  font-size: 15px; font-weight: 800; font-variant-numeric: tabular-nums;
  color: var(--g-text);
}
.pz-q-lbl {
  display: block; margin-top: 1px;
  font-size: 9px; letter-spacing: 0.6px; text-transform: uppercase; color: var(--g-text-4);
}

.pz-rows { display: flex; flex-direction: column; gap: 7px; }
.pz-row {
  display: flex; align-items: baseline; justify-content: space-between; gap: 10px;
  font-size: 12.5px;
}
.pz-row dt { color: var(--g-text-4); }
.pz-row dd {
  margin: 0; color: var(--g-text-2, var(--g-text)); text-align: right;
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

.pz-sub {
  font-size: 9.5px; letter-spacing: 1.1px; text-transform: uppercase;
  color: var(--g-text-4);
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
}
.pz-sub::after {
  content: ''; flex: 1; height: 1px; background: var(--g-border);
}
.pz-sub > span { flex: none; }

/* --- skill bars --- */
.pz-skills { display: flex; flex-direction: column; gap: 6px; }
.pz-skill { display: grid; grid-template-columns: 84px 1fr 18px; gap: 9px; align-items: center; }
.pz-skill-n { font-size: 11.5px; color: var(--g-text-3); white-space: nowrap;
              overflow: hidden; text-overflow: ellipsis; }
.pz-pips { display: grid; grid-template-columns: repeat(10, 1fr); gap: 2px; }
.pz-pip { height: 6px; border-radius: 1.5px; background: var(--g-surf-2);
          border: 1px solid var(--g-border); }
.pz-pip.on {
  background: color-mix(in srgb, var(--accent) 78%, transparent);
  border-color: color-mix(in srgb, var(--accent) 78%, transparent);
  /* Filled left to right when the card scrolls into view. */
  transform: scaleX(0); transform-origin: left;
  transition: transform .32s cubic-bezier(.2,.7,.3,1);
}
.pz-card.is-seen .pz-pip.on { transform: scaleX(1); }
.pz-skill-v {
  font-family: ui-monospace, Consolas, monospace;
  font-size: 11.5px; font-weight: 700; text-align: right;
  font-variant-numeric: tabular-nums; color: var(--g-text);
}
@media (prefers-reduced-motion: reduce) {
  .pz-pip.on { transform: scaleX(1); transition: none; }
}

/* --- full skill breakdown --- */
.pz-more { border-top: 1px solid var(--g-border); padding-top: 10px; }
.pz-more > summary {
  list-style: none; cursor: pointer;
  display: flex; align-items: center; gap: 8px;
  font-size: 11px; letter-spacing: .6px; text-transform: uppercase;
  color: var(--g-text-4);
}
.pz-more > summary::-webkit-details-marker { display: none; }
.pz-more > summary:hover { color: var(--accent); }
.pz-more > summary::after {
  content: '+'; margin-left: auto;
  font-family: ui-monospace, Consolas, monospace; font-size: 14px; line-height: 1;
}
.pz-more[open] > summary::after { content: '−'; }
.pz-more-n {
  font-family: ui-monospace, Consolas, monospace;
  padding: 1px 6px; border-radius: 4px;
  background: var(--g-surf-2); border: 1px solid var(--g-border);
}
.pz-allskills { display: flex; flex-direction: column; gap: 10px; margin-top: 11px; }
.pz-sg { display: flex; flex-wrap: wrap; gap: 5px; align-items: center; }
.pz-sg-h {
  flex: 0 0 100%;
  font-size: 9.5px; letter-spacing: 1px; text-transform: uppercase; color: var(--g-text-4);
}
.pz-sk {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 2px 7px; border-radius: 5px;
  font-size: 11px; color: var(--g-text-4);
  background: var(--g-surf-2); border: 1px solid var(--g-border);
}
.pz-sk b {
  font-family: ui-monospace, Consolas, monospace; font-weight: 700;
  color: var(--g-text-4);
}
.pz-sk.on { color: var(--g-text); border-color: color-mix(in srgb, var(--accent) 38%, var(--g-border)); }
.pz-sk.on b { color: var(--accent); }

/* --- gear --- */
.pz-gear { display: flex; flex-wrap: wrap; gap: 6px; }
.pz-gi {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 3px 8px; border-radius: 5px;
  font-size: 11px; color: var(--g-text-3);
  background: var(--g-surf-2); border: 1px solid var(--g-border);
}
.pz-gi.has-ic { padding-left: 4px; color: var(--g-text-2, var(--g-text)); }
.pz-gi .pz-ic { vertical-align: 0; }
.pz-row-ic { display: inline-flex; align-items: center; gap: 6px; justify-content: flex-end; }

/* --- last death note --- */
.pz-obit {
  padding: 10px 12px; border-radius: 8px;
  background: color-mix(in srgb, var(--g-pz) 8%, var(--g-surf-2));
  border: 1px solid color-mix(in srgb, var(--g-pz) 25%, var(--g-border));
  font-size: 12.5px; color: var(--g-text-3);
}
.pz-obit strong { color: var(--g-text); font-weight: 700; }

.pz-card-f {
  margin-top: auto;
  display: flex; gap: 8px; flex-wrap: wrap;
  padding: 12px 16px; border-top: 1px solid var(--g-border);
  background: var(--g-surf-2);
}
.pz-btn {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 6px 11px; border-radius: 7px;
  font: inherit; font-size: 11.5px; font-weight: 600;
  color: var(--g-text-3);
  background: var(--g-surf); border: 1px solid var(--g-border);
  cursor: pointer;
}
.pz-btn:hover { color: var(--accent); border-color: var(--accent); }
.pz-btn .ico { width: 13px; height: 13px; }
.pz-btn[aria-pressed="true"] {
  color: var(--accent); border-color: var(--accent);
  background: color-mix(in srgb, var(--accent) 12%, var(--g-surf));
}
.pz-btn[disabled] { opacity: .4; cursor: default; }
.pz-btn[disabled]:hover { color: var(--g-text-3); border-color: var(--g-border); }

/* ------------------------------------------------------------------- map */
.pz-mapwrap {
  position: relative;
  background: #0c1016;
  border-top: 1px solid var(--g-border);
  border-bottom: 1px solid var(--g-border);
  overflow: hidden;
  touch-action: none;
  cursor: grab;
}
.pz-mapwrap.is-drag { cursor: grabbing; }
.pz-mapwrap svg.km { display: block; width: 100%; height: auto; }

/* Colours live here rather than in the asset so the map follows the site
   palette and the file stays pure geometry. */
.km-bg          { fill: #0c1016; }
.km-water       { fill: #16293a; }
.km-r           { fill: #39424f; }
.km-r-trail     { fill: #242c37; }
.km-r-tertiary  { fill: #333c49; }
.km-r-secondary { fill: #454f5e; }
.km-r-primary   { fill: #6a7484; }
.km-rail        { fill: #2f3542; }
.km-b-res       { fill: #454d5c; }
.km-b-ind       { fill: #544d44; }
.km-b-com       { fill: #544b5b; }
.km-b-civ       { fill: #3d525a; }

.pz-ovl { position: absolute; inset: 0; pointer-events: none; }

.pz-lbl {
  position: absolute; transform: translate(-50%, -50%);
  font-size: 10px; font-weight: 800; letter-spacing: .15em;
  color: #97a3b6; text-shadow: 0 1px 3px #000, 0 0 8px #000;
  white-space: nowrap; pointer-events: none;
  transition: opacity .2s;
}
.pz-lbl.water  { color: #6193bd; font-weight: 600; font-style: italic; letter-spacing: .18em; }
.pz-lbl.forest { color: #62876a; font-weight: 600; letter-spacing: .18em; font-size: 9px; }
.pz-lbl.place  { color: #7b8593; font-weight: 600; letter-spacing: .03em; font-size: 9px;
                 text-transform: none; }
.pz-lbl.is-hidden { opacity: 0; }

.pz-mk {
  position: absolute; transform: translate(-50%, -50%);
  pointer-events: auto; cursor: pointer;
  width: 16px; height: 16px;
}
.pz-mk-dot {
  position: absolute; inset: 3px; border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 0 2px #0c1016, 0 0 12px 2px color-mix(in srgb, var(--accent) 60%, transparent);
}
.pz-mk.alive .pz-mk-dot { animation: pz-ping 2.4s infinite; }
.pz-mk.dead .pz-mk-dot {
  inset: 4px; border-radius: 1px; background: transparent;
  box-shadow: none;
  border: 0;
}
.pz-mk.dead::before, .pz-mk.dead::after {
  content: ''; position: absolute; left: 50%; top: 3px;
  width: 2px; height: 10px; margin-left: -1px;
  background: #97a3b6; border-radius: 2px;
}
.pz-mk.dead::before { transform: rotate(45deg); }
.pz-mk.dead::after  { transform: rotate(-45deg); }

/* Cluster markers: a hollow ring whose size carries the population, so they
   read as areas rather than competing with the survivor pins. */
.pz-mk.horde .pz-mk-dot {
  inset: 0; border-radius: 50%;
  background: color-mix(in srgb, #e0b341 16%, transparent);
  border: 1.5px solid color-mix(in srgb, #e0b341 72%, transparent);
  box-shadow: none;
  animation: none;
}
.pz-mk.horde .pz-mk-tag {
  color: #e6c163; background: rgba(12,16,22,.9);
  border-color: color-mix(in srgb, #e0b341 40%, var(--g-border));
}
.pz-mk.horde.is-focus .pz-mk-dot {
  border-color: #f0c95a;
  box-shadow: 0 0 0 0 color-mix(in srgb, #e0b341 60%, transparent);
  animation: pz-horde-ping 1.2s ease-out 3;
}
@keyframes pz-horde-ping {
  0%   { box-shadow: 0 0 0 0 color-mix(in srgb, #e0b341 60%, transparent); }
  100% { box-shadow: 0 0 0 26px transparent; }
}

/* --- zombie density, drawn as map geometry --- */
.km-z1 { fill: rgba(224, 179, 65, .20); }
.km-z2 { fill: rgba(224, 149, 65, .34); }
.km-z3 { fill: rgba(219, 106, 58, .48); }
.km-z4 { fill: rgba(214, 69, 60, .66); }

/* Coarse blocks when the county is on screen, 8-tile squares once zoomed in.
   Neither granularity works at both ends: the fine grid is sub-pixel from far
   out, and the blocks are meaningless up close. */
.km-zed-fine   { display: none; }
.is-zoomed .km-zed-fine   { display: block; }
.is-zoomed .km-zed-coarse { display: none; }
.km-zed-coarse path { filter: blur(6px); }

/* Cluster labels would pile into an unreadable smear at low zoom. */
.pz-mk.horde .pz-mk-tag { opacity: 0; transition: opacity .2s; }
.is-zoomed .pz-mk.horde .pz-mk-tag,
.pz-mk.horde:hover .pz-mk-tag { opacity: 1; }

/* --- horde tracker --- */
.pz-hordes { display: flex; flex-direction: column; gap: 6px; margin-top: 14px; }
.pz-horde {
  display: grid; grid-template-columns: 42px 1fr auto;
  gap: 11px; align-items: center; width: 100%;
  padding: 9px 11px; border-radius: 8px;
  font: inherit; text-align: left; cursor: pointer;
  background: var(--g-surf-2); border: 1px solid var(--g-border);
}
.pz-horde:hover { border-color: color-mix(in srgb, #e0b341 45%, var(--g-border)); }
.pz-horde-n {
  font-family: ui-monospace, Consolas, monospace;
  font-size: 16px; font-weight: 800; color: #e6c163;
  font-variant-numeric: tabular-nums; text-align: right;
}
.pz-horde-m { min-width: 0; display: flex; flex-direction: column; gap: 5px; }
.pz-horde-m strong {
  font-size: 12.5px; font-weight: 600; color: var(--g-text);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.pz-horde-bar {
  height: 4px; border-radius: 3px; overflow: hidden;
  background: var(--g-surf); border: 1px solid var(--g-border);
}
.pz-horde-bar i {
  display: block; height: 100%;
  background: linear-gradient(90deg, #e0b341, var(--g-pz));
}
.pz-horde-s {
  font-family: ui-monospace, Consolas, monospace;
  font-size: 10.5px; color: var(--g-text-4); white-space: nowrap;
}
.pz-mk.is-focus .pz-mk-dot { animation: pz-focus 1.1s ease-out 3; }
@keyframes pz-focus {
  0%   { box-shadow: 0 0 0 2px #0c1016, 0 0 0 0 color-mix(in srgb, var(--accent) 70%, transparent); }
  100% { box-shadow: 0 0 0 2px #0c1016, 0 0 0 22px transparent; }
}
.pz-mk-tag {
  position: absolute; left: 50%; top: 100%; transform: translateX(-50%);
  margin-top: 3px; padding: 1px 6px;
  font-size: 9.5px; font-weight: 700; letter-spacing: .04em; white-space: nowrap;
  color: var(--g-text); background: rgba(12,16,22,.86);
  border: 1px solid var(--g-border); border-radius: 4px;
}
.pz-mk.dead .pz-mk-tag { color: var(--g-text-3); }

.pz-mapbar {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  padding: 11px 16px;
}
.pz-mapbar-r { margin-left: auto; display: flex; gap: 6px; }
.pz-zoom {
  display: inline-flex; align-items: center; justify-content: center;
  width: 28px; height: 28px; padding: 0;
  font: inherit; font-size: 15px; line-height: 1;
  color: var(--g-text-3); background: var(--g-surf-2);
  border: 1px solid var(--g-border); border-radius: 7px; cursor: pointer;
}
.pz-zoom:hover { color: var(--accent); border-color: var(--accent); }

.pz-legend { display: flex; gap: 14px; flex-wrap: wrap; padding: 0 16px 13px;
             font-size: 11px; color: var(--g-text-4); }
.pz-lg { display: inline-flex; align-items: center; gap: 6px; }
.pz-lg i { width: 9px; height: 9px; border-radius: 50%; background: var(--accent); }
.pz-lg.x i { border-radius: 1px; background: #97a3b6; transform: rotate(45deg); }
.pz-lg.town i { border-radius: 2px; background: #454d5c; }
.pz-lg.z1 i { border-radius: 2px; background: rgba(224, 179, 65, .5); }
.pz-lg.z4 i { border-radius: 2px; background: rgba(214, 69, 60, .85); }
.pz-lg.wood i { border-radius: 2px; background: #2c4231; }
.pz-lg.water i { border-radius: 2px; background: #16293a; }

/* -------------------------------------------------------------- timeline */
.pz-tl { display: flex; flex-direction: column; }
.pz-tl-i {
  display: grid; grid-template-columns: 22px 1fr auto;
  gap: 11px; align-items: baseline;
  padding: 9px 0;
  border-bottom: 1px solid var(--g-border);
  font-size: 12.5px;
}
.pz-tl-i:last-child { border-bottom: 0; padding-bottom: 0; }
.pz-tl-k {
  display: grid; place-items: center;
  width: 22px; height: 22px; border-radius: 6px;
  background: var(--g-surf-2); border: 1px solid var(--g-border);
  align-self: center;
}
.pz-tl-k .ico { width: 11px; height: 11px; color: var(--g-text-3); }
.pz-tl-i.death .pz-tl-k {
  border-color: color-mix(in srgb, var(--g-pz) 45%, var(--g-border));
  background: color-mix(in srgb, var(--g-pz) 14%, var(--g-surf-2));
}
.pz-tl-i.death .pz-tl-k .ico { color: var(--g-pz); }
.pz-tl-t { min-width: 0; color: var(--g-text-3); }
.pz-tl-t strong { color: var(--g-text); font-weight: 700; }
.pz-tl-w {
  font-family: ui-monospace, Consolas, monospace;
  font-size: 11px; color: var(--g-text-4); white-space: nowrap;
}

/* ---------------------------------------------------------- death records */
.pz-obits { display: flex; flex-direction: column; gap: 8px; }
.pz-ob {
  border: 1px solid var(--g-border); border-radius: 9px;
  background: var(--g-surf-2); overflow: hidden;
}
.pz-ob > summary {
  list-style: none; cursor: pointer;
  display: grid; grid-template-columns: 1fr auto auto;
  gap: 12px; align-items: center;
  padding: 11px 13px;
  font-size: 13px;
}
.pz-ob > summary::-webkit-details-marker { display: none; }
.pz-ob > summary:hover { background: var(--g-surf); }
.pz-ob-who { font-weight: 700; }
.pz-ob-who span { font-weight: 400; color: var(--g-text-3); }
.pz-ob-num {
  font-family: ui-monospace, Consolas, monospace; font-size: 12px;
  color: var(--g-text-3); white-space: nowrap;
}
.pz-ob-chev { color: var(--g-text-4); transition: transform .18s; }
.pz-ob-chev .ico { width: 14px; height: 14px; display: block; }
.pz-ob[open] .pz-ob-chev { transform: rotate(90deg); }
.pz-ob-body {
  padding: 0 13px 13px;
  display: grid; gap: 12px;
}
.pz-vitals { display: grid; grid-template-columns: repeat(auto-fit, minmax(96px, 1fr)); gap: 8px; }
.pz-vital {
  padding: 8px 10px; border-radius: 7px;
  background: var(--g-surf); border: 1px solid var(--g-border);
}
.pz-vital b {
  display: block;
  font-family: ui-monospace, Consolas, monospace;
  font-size: 13.5px; font-weight: 700; color: var(--g-text);
  font-variant-numeric: tabular-nums;
}
.pz-vital span {
  display: block; margin-top: 1px;
  font-size: 9.5px; letter-spacing: .7px; text-transform: uppercase; color: var(--g-text-4);
}
/* Traits. Only the live mod knows them - the save file never yielded them - so
   the block is absent entirely for a survivor it has not seen, rather than
   showing an empty rail that would read as "no traits". */
.pz-traits { display: flex; flex-wrap: wrap; gap: 5px; }
.pz-trait {
  font-size: 11px; line-height: 1;
  padding: 4px 7px; border-radius: 3px;
  color: var(--g-text-3);
  background: var(--g-surf-2);
  border: 1px solid var(--g-border);
}

.pz-wounds { display: flex; flex-direction: column; gap: 6px; }
.pz-wd {
  display: grid; grid-template-columns: 96px 1fr 84px;
  gap: 10px; align-items: center; font-size: 12px;
}
.pz-wd-p { color: var(--g-text); font-weight: 600; }
.pz-wd-w { color: var(--g-text-3); }
.pz-wd-h { display: flex; align-items: center; gap: 5px; justify-content: flex-end; }
.pz-wd-bar {
  flex: 1; height: 5px; border-radius: 3px;
  background: var(--g-surf); border: 1px solid var(--g-border); overflow: hidden;
}
/* The bar shows health REMAINING, so a short bar reads as a bad limb. The hue
   is driven by --h (0-100) rather than a gradient, because a gradient would be
   squeezed into whatever width the bar happens to be and a nearly-dead limb
   would still show green. */
.pz-wd-bar i {
  display: block; height: 100%;
  background: hsl(calc(var(--h, 100) * 1.15) 52% 48%);
}
.pz-wd-n {
  font-family: ui-monospace, Consolas, monospace; font-size: 10.5px;
  color: var(--g-text-4); font-variant-numeric: tabular-nums;
}

/* --------------------------------------------------------------- rules */
.pz-rules { display: grid; grid-template-columns: repeat(auto-fit, minmax(168px, 1fr)); gap: 10px; }
.pz-rule {
  padding: 11px 12px; border-radius: 9px;
  background: var(--g-surf-2); border: 1px solid var(--g-border);
}
.pz-rule-k {
  display: flex; align-items: center; gap: 6px;
  font-size: 10px; letter-spacing: .8px; text-transform: uppercase; color: var(--g-text-4);
}
.pz-rule-k .ico { width: 12px; height: 12px; color: var(--g-text-4); }
.pz-rule-v { margin-top: 4px; font-size: 13px; font-weight: 600; }
.pz-rule.hot { border-color: color-mix(in srgb, var(--g-pz) 30%, var(--g-border)); }
.pz-rule.hot .pz-rule-k .ico, .pz-rule.hot .pz-rule-v { color: var(--g-pz); }

/* ----------------------------------------------------------------- mods */
.pz-modcols { columns: 4 208px; column-gap: 26px; margin-top: 14px; }
.pz-modgroup { break-inside: avoid; margin: 0 0 18px; }
.pz-modgroup h4 {
  display: flex; align-items: baseline; justify-content: space-between; gap: 8px;
  margin: 0 0 6px; padding-bottom: 5px;
  border-bottom: 1px solid var(--g-border);
  font-size: 10.5px; font-weight: 700; letter-spacing: .09em;
  text-transform: uppercase; color: var(--g-pz);
}
.pz-modgroup h4 span {
  font-family: ui-monospace, Consolas, monospace;
  font-size: 10px; font-weight: 600; letter-spacing: 0; color: var(--g-text-4);
}
.pz-modrow { display: block; padding: 3px 0; text-decoration: none; }
.pz-modrow b {
  display: block; font-size: 12px; font-weight: 600;
  line-height: 1.3; color: var(--g-text);
}
.pz-modrow em {
  display: block; font-style: normal; font-size: 10.5px;
  line-height: 1.3; color: var(--g-text-3);
}
a.pz-modrow:hover b { color: var(--accent); }

/* a single 208px column on a phone puts the list back to 4000px tall */
@media (max-width: 700px) {
  .pz-modcols { columns: 2 138px; column-gap: 16px; }
  .pz-modgroup { margin-bottom: 14px; }
  .pz-modrow b  { font-size: 11.5px; }
  .pz-modrow em { font-size: 10px; }
}

/* ---------------------------------------------------------- responsive */
@media (max-width: 900px) {
  .pz-hero { grid-template-columns: 1fr; }
  .pz-dossiers { grid-template-columns: 1fr; }
  .pz-horde { grid-template-columns: 38px 1fr auto; }
  .pz-skill { grid-template-columns: 74px 1fr 18px; }
  .pz-ob > summary { grid-template-columns: 1fr auto; }
  .pz-ob-num { grid-column: 1 / -1; }
  .pz-wd { grid-template-columns: 84px 1fr; }
  .pz-wd-h { grid-column: 1 / -1; }
}
@media (max-width: 640px) {
  .pz-quad { grid-template-columns: repeat(2, 1fr); }
  /* The figure keeps its place on a phone but shrinks, because dropping it
     below the stats would push the numbers off the first screen. */
  .pz-fig { --fs: .52 !important; }
  .pz-split { gap: 10px; }
  .pz-lbl.place, .pz-lbl.forest { display: none; }
  .pz-mk-tag { display: none; }
  /* A 3:2 map is only ~250px tall on a phone, which is unusable. */
  .pz-mapwrap { aspect-ratio: 1 / 1 !important; }
  .pz-lbl { font-size: 9px !important; letter-spacing: .08em; }
  .pz-lbl.water { font-size: 8.5px !important; }
  .pz-mapbar { gap: 6px; }
  .pz-mapbar-r { margin-left: 0; width: 100%; justify-content: flex-end; }
}

/* ======================================================== in-game window ==
   The survivor dossier renders as Project Zomboid's own character window.

   Every colour, size and gradient below is a value the game actually draws,
   read out of media/lua/client/ISUI/ and the UI texture packs rather than
   eyeballed from a screenshot. The citations stay because they are the only
   way to tell a deliberate value from a guess later:

     ISCollapsableWindow.lua:373-374  body rgba(0,0,0,.8), border #666
     ISCollapsableWindow.lua:298-300  title bar height max(16, FONT_HGT_SMALL+1)
     Panel_TitleBar.png               the title gradient, 14 rows
     ISTabPanel.lua:642-647           tab height, padding, 1px gap
     tab_selected/unselected.png      the two tab gradients, 19 rows each
     ISInventoryPane.lua:32-41        header 17px, icon strip 35px, columns
     ISInventoryPane.lua:16,2496      item name #B3B3B3
     ISInventoryPane.lua:2533         category #9999CC
     ISInventoryPane.lua:2440-2442    row stripes white 2% / black 20%
     ISInventoryPane.lua:2402         hover white 5%
     ISInventoryPane.lua:2454         expanded child black 40%
     ISInventoryPane.lua:2460-2465    equipped divider white 20%
     Panel_StatusBar.png              the bottom strip gradient, 6 rows

   The UI font is Noto Sans SemiBold (media/fonts/EN/fonts.txt:93-97). It is not
   shipped with the page, so the stack falls back to the closest system faces at
   the same weight. */
.pzw {
  --pzw-line: #666;
  --pzw-name: #b3b3b3;
  --pzw-cat: #9c9ccc;
  font-family: "Noto Sans", "Segoe UI", system-ui, -apple-system, sans-serif;
  font-weight: 600;
  background: rgba(0, 0, 0, .8);
  border: 1px solid var(--pzw-line);
  overflow: hidden;
  /* The window is pixel furniture: rounded corners are the one thing that
     instantly reads as website chrome rather than game window. */
  border-radius: 0;
}

/* --- title bar --- */
.pzw-tt {
  position: relative;
  display: flex; align-items: center; gap: 6px;
  height: 17px; padding: 0 2px;
  border-bottom: 1px solid var(--pzw-line);
  background: linear-gradient(#3d3d3d, #363636 14%, #2e2e2e 21%, #272727 29%,
                              #1f1f1f 36%, #1a1a1a 43%, #151515 50%,
                              #151515 71%, #171717 79%, #1f1f1f 86%);
}
.pzw-tt-n {
  position: absolute; left: 0; right: 0; top: 0;
  text-align: center; line-height: 17px;
  font-size: 11.5px; color: #fff; letter-spacing: .2px;
  pointer-events: none;
  overflow: hidden; white-space: nowrap; text-overflow: ellipsis;
  padding: 0 62px;
}
/* Right-aligned in the title bar, exactly where the game puts the carried
   weight (ISInventoryPage.lua:637), drawn plain white: the game applies no
   threshold colouring here at all. */
.pzw-tt-w {
  position: relative; z-index: 1; margin-left: auto;
  font-size: 10.5px; color: #fff;
  font-variant-numeric: tabular-nums;
  padding-right: 2px;
}
.pzw-b {
  position: relative; z-index: 1;
  width: 15px; height: 15px; flex: none;
  background-image: var(--pz-ui);
  background-repeat: no-repeat;
  image-rendering: pixelated;
  opacity: .85;
}

/* --- tabs --- */
.pzw-tabs {
  display: flex; gap: 1px; padding: 0 1px;
  background: #000;
}
.pzw-tab {
  flex: 1 1 0; min-width: 0;
  height: 21px; padding: 0 6px;
  border: 0; cursor: pointer;
  font: inherit; font-size: 11px; color: #fff;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  background: linear-gradient(#141414, #1b1b1b 5%, #232323 11%, #2a2a2a 16%,
                              #2a2a2a 26%, #292929 32%, #282828 37%, #262626 42%,
                              #232323 47%, #202020 53%, #1d1d1d 58%, #191919 63%,
                              #161616 68%, #121212 74%, #101010 79%, #0e0e0e 84%,
                              #0c0c0c 89%, #0b0b0b 100%);
}
.pzw-tab[aria-selected="true"] {
  background: linear-gradient(#343434, #434343 5%, #5a5a5a 11%, #696969 16%,
                              #696969 26%, #676767 32%, #646464 37%, #606060 42%,
                              #5a5a5a 47%, #515151 53%, #484848 58%, #404040 63%,
                              #373737 68%, #2f2f2f 74%, #292929 79%, #222222 84%,
                              #1d1d1d 89%, #1c1c1c 100%);
}
/* The game cross-fades tab_selected in at 20% on hover; same effect, one rule. */
.pzw-tab:hover:not([aria-selected="true"]) { filter: brightness(1.55); }
.pzw-tab:focus-visible { outline: 1px solid #33ffff; outline-offset: -2px; }

/* --- body --- */
.pzw-body { border-top: 1px solid var(--pzw-line); }
.pzw-pane { display: none; }
.pzw-pane.is-on { display: block; }

/* --- bottom status strip, with the game's own resize grip --- */
.pzw-foot {
  display: flex; justify-content: flex-end; align-items: center;
  height: 13px;
  border-top: 1px solid var(--pzw-line);
  background: linear-gradient(#282828, #282828 17%, #202020 34%, #171717 50%,
                              #101010 67%, #070707 100%);
}
.pzw-grip {
  width: 11px; height: 11px; margin-right: 1px;
  background-image: var(--pz-ui);
  background-repeat: no-repeat;
  image-rendering: pixelated;
  opacity: .6;
}

/* ---------------------------------------------------------- inventory ---
   Two columns, as B42 draws them: an icon strip, the item name, and the
   localised category. The game has no weight column and neither does this; the
   total sits in the title bar where the game puts it. */
.pzi { font-size: 11.5px; display: flex; align-items: stretch; }
.pzi-main { flex: 1 1 auto; min-width: 0; }

/* The container side-bar. B42 puts it on the RIGHT edge, 32 px wide, with its
   own black backing and border (ISInventoryPage.lua:118-124, :619, :967). One
   button per container the survivor is wearing, plus their own inventory. */
.pzi-side {
  flex: none; width: 32px;
  display: flex; flex-direction: column;
  background: rgba(0, 0, 0, .8);
  border-left: 1px solid var(--pzw-line);
  overflow-y: auto; overflow-x: hidden;
  scrollbar-width: none;
}
.pzi-side::-webkit-scrollbar { display: none; }
.pzi-cb {
  all: unset;
  box-sizing: border-box;
  width: 32px; height: 32px; flex: none;
  display: flex; align-items: center; justify-content: center;
  cursor: pointer;
  /* -1 px so consecutive buttons share a border, as the game stacks them. */
  margin-bottom: -1px;
  border: 1px solid rgba(179, 179, 179, .35);
}
.pzi-cb:hover { background: #4d4d4d; }
/* The game fills the selected button solid #B3B3B3, which is why its icon then
   reads as a dark silhouette rather than a lit one. */
.pzi-cb[aria-selected="true"] { background: #b3b3b3; }
.pzi-cb:focus-visible { outline: 1px solid #33ffff; outline-offset: -2px; }
.pzi-cb .pz-ic { --k: .82; vertical-align: 0; }
.pzi-cb-i {
  background-image: var(--pz-ui);
  background-repeat: no-repeat;
  image-rendering: pixelated;
}

.pzi-hd {
  display: grid; grid-template-columns: 35px 1fr 128px;
  height: 17px; align-items: stretch;
  background: #000;
}
.pzi-hd > span {
  line-height: 15px;
  color: #fff; font-size: 10.5px;
  border: 1px solid rgba(179, 179, 179, .2);
  text-align: center;
  overflow: hidden; white-space: nowrap;
}
.pzi-hd > span:first-child { border: 0; }
.pzi-hd button {
  all: unset; display: block; width: 100%; height: 100%;
  cursor: pointer; text-align: center; line-height: 15px;
}
.pzi-hd button:hover { background: #4d4d4d; }
.pzi-hd button:focus-visible { outline: 1px solid #33ffff; outline-offset: -2px; }

.pzi-list {
  display: none;
  max-height: 341px;               /* 11 rows; the pane scrolls past that */
  overflow-y: auto; overflow-x: hidden;
  /* The icon strip is painted black 60% for the full height of the pane, under
     every row, which is why it survives the row stripes. */
  background:
    linear-gradient(rgba(0, 0, 0, .6), rgba(0, 0, 0, .6)) left top / 35px 100% no-repeat;
  scrollbar-width: thin;
  scrollbar-color: #4b4b4b #000;
}
.pzi-list.is-on { display: block; }
.pzi-list::-webkit-scrollbar { width: 13px; }
.pzi-list::-webkit-scrollbar-track { background: #000; border-left: 1px solid var(--pzw-line); }
.pzi-list::-webkit-scrollbar-thumb {
  background: linear-gradient(90deg, #606060, #4b4b4b 12%, #4b4b4b 45%,
                              #454545 55%, #3f3f3f 78%, #565656 100%);
  border: 2px solid transparent; background-clip: padding-box;
}

/* A shelf heading. The game has no equivalent: it folds worn, held and stowed
   into a single equipped block and sorts it to the bottom. A dossier is read
   rather than played, and what a survivor is WEARING is the part worth pulling
   out. The rule above it is the game's own equipped divider. */
.pzi-sh {
  display: flex; align-items: center; gap: 8px;
  height: 19px; padding: 0 8px 0 43px;
  font-size: 9.5px; letter-spacing: .12em; text-transform: uppercase;
  color: #8f8f8f;
  border-top: 1px solid rgba(255, 255, 255, .2);
  background: rgba(0, 0, 0, .55);
}
.pzi-sh:first-child { border-top: 0; }
.pzi-sh b { margin-left: auto; color: #6f6f6f; font-weight: 600; }

.pzi-r {
  display: grid; grid-template-columns: 35px 1fr 128px;
  align-items: center;
  height: 31px;
  background: rgba(0, 0, 0, .2);
}
.pzi-r.alt { background: rgba(255, 255, 255, .02); }
.pzi-r:hover { background: rgba(255, 255, 255, .05); }

.pzi-ic {
  position: relative;
  width: 35px; height: 31px;
  display: flex; align-items: center; justify-content: center;
}
.pzi-ic .pz-ic { --k: .9; vertical-align: 0; }
/* Types with no sprite still occupy the cell, so the columns never jump. */
.pzi-no {
  width: 17px; height: 17px;
  border: 1px solid rgba(255, 255, 255, .14);
}
/* Equipped / hotbar markers, bottom-right of the icon cell as in the game. */
.pzi-bd {
  position: absolute; right: 2px; bottom: 3px;
  background-image: var(--pz-ui);
  background-repeat: no-repeat;
  image-rendering: pixelated;
}

.pzi-n {
  padding-left: 8px; padding-right: 6px;
  color: var(--pzw-name);
  overflow: hidden; white-space: nowrap; text-overflow: ellipsis;
}
/* The game appends the stack count to the name rather than giving it a column. */
.pzi-n i {
  font-style: normal; color: #7d7d7d;
  font-variant-numeric: tabular-nums;
}
.pzi-c {
  padding-right: 8px; padding-left: 8px;
  color: var(--pzw-cat); font-size: 10.5px;
  overflow: hidden; white-space: nowrap; text-overflow: ellipsis;
}

/* ------------------------------------------------------------- skills ---
   The XP panel: one row per perk, ten units, drawn from the game's own
   SkillUnit_border and SkillUnit_fill textures. */
/* Capped to the same height as the inventory list. Without it a survivor with
   all 35 perks makes their card two and a half times taller than the one next
   to it in the grid. */
.pzs {
  padding: 8px 10px 10px; display: flex; flex-direction: column; gap: 9px;
  max-height: 341px; overflow-y: auto;
  scrollbar-width: thin;
  scrollbar-color: #4b4b4b #000;
}
.pzs::-webkit-scrollbar { width: 13px; }
.pzs::-webkit-scrollbar-track { background: #000; border-left: 1px solid var(--pzw-line); }
.pzs::-webkit-scrollbar-thumb {
  background: linear-gradient(90deg, #606060, #4b4b4b 12%, #4b4b4b 45%,
                              #454545 55%, #3f3f3f 78%, #565656 100%);
  border: 2px solid transparent; background-clip: padding-box;
}
.pzs-g { display: flex; flex-direction: column; gap: 2px; }
.pzs-gh {
  font-size: 9.5px; letter-spacing: .12em; text-transform: uppercase;
  color: #8f8f8f; padding: 3px 0 2px;
  border-bottom: 1px solid rgba(255, 255, 255, .08);
  margin-bottom: 3px;
}
.pzs-r {
  display: grid; grid-template-columns: 1fr auto auto;
  align-items: center; gap: 8px;
  height: 19px;
}
.pzs-n {
  font-size: 11px; color: var(--pzw-name);
  overflow: hidden; white-space: nowrap; text-overflow: ellipsis;
}
.pzs-r.lvl0 .pzs-n { color: #6b6b6b; }
.pzs-u { display: flex; gap: 1px; }
.pzs-p {
  width: 9px; height: 9px;
  background-image: var(--pz-ui);
  background-repeat: no-repeat;
  image-rendering: pixelated;
}
.pzs-v {
  min-width: 14px; text-align: right;
  font-size: 10.5px; color: #7d7d7d;
  font-variant-numeric: tabular-nums;
}
.pzs-r.lvl0 .pzs-v { color: #4f4f4f; }
/* Progress through the CURRENT level. The save only ever yields the integer
   level, so this line exists solely when the live mod has seen the survivor;
   rows without it simply have no bar rather than an empty one, which would
   read as "no progress" instead of "not known". Greyscale on purpose: the
   surrounding chrome is the game's own window and a new accent hue here would
   look like it meant something. */
.pzs-r { position: relative; }
.pzs-b {
  position: absolute; left: 0; right: 0; bottom: 0;
  height: 2px; background: rgba(255, 255, 255, .06);
}
.pzs-b i {
  display: block; height: 100%; width: var(--p, 0%);
  background: rgba(179, 179, 179, .55);
}

/* ------------------------------------------------------- info + health --- */
.pzw-info { padding: 11px; display: flex; flex-direction: column; gap: 13px; }
.pzw-hp {
  padding: 10px; display: flex; justify-content: center;
  gap: 14px; align-items: flex-start; flex-wrap: wrap;
}

/* Live vitals. Present only where the CakcanState mod has actually seen the
   survivor - the save yields none of this - so the pane falls back to the bare
   figure rather than to a row of zeroes pretending to be a reading. */
.pz-vit { flex: 1 1 200px; min-width: 0; display: flex; flex-direction: column; gap: 10px; }
.pz-vit-h { display: flex; align-items: baseline; gap: 16px; }
.pz-vit-n { display: flex; flex-direction: column; gap: 1px; }
.pz-vit-num {
  font-size: 21px; font-weight: 700; line-height: 1;
  color: var(--pzw-name); font-variant-numeric: tabular-nums;
}
.pz-vit-num.is-bad { color: #c5563f; }
.pz-vit-lbl {
  font-size: 9px; letter-spacing: .1em; text-transform: uppercase; color: #7d7d7d;
}
.pz-vit-inf {
  margin-left: auto; align-self: center;
  font-size: 9.5px; letter-spacing: .1em; font-weight: 700;
  color: #d2694f; border: 1px solid #6d3325; background: #2a1512;
  padding: 3px 6px; border-radius: 3px;
}

.pz-st { display: flex; flex-direction: column; gap: 3px; }
.pz-st-r { display: grid; grid-template-columns: 1fr 1.15fr 20px; gap: 7px; align-items: center; }
.pz-st-n {
  font-size: 10.5px; color: #9a9a9a;
  overflow: hidden; white-space: nowrap; text-overflow: ellipsis;
}
.pz-st-b {
  height: 5px; background: rgba(255, 255, 255, .06);
  border: 1px solid rgba(255, 255, 255, .07); overflow: hidden;
}
.pz-st-b i { display: block; height: 100%; background: rgba(179, 179, 179, .5); }
/* Red is reserved for the ones that mean harm. Wetness at 80% is not the same
   news as zombie infection at 80%. */
.pz-st-b i.is-bad { background: #a84a37; }
.pz-st-v {
  font-size: 10px; text-align: right; color: #6f6f6f;
  font-variant-numeric: tabular-nums;
}

.pz-wounds-live { gap: 4px; }
.pz-wounds-live .pz-wd { grid-template-columns: 74px 1fr 62px; gap: 7px; font-size: 10.5px; }
.pzw-hp .pz-viz { align-items: center; }

/* An empty pane still has to hold the window open, or switching tabs makes the
   whole card jump. */
.pzw-none {
  padding: 26px 10px; text-align: center;
  font-size: 11px; color: #6b6b6b;
}

@media (max-width: 560px) {
  .pzi-hd,
  .pzi-r { grid-template-columns: 30px 1fr 92px; }
  .pzi-ic { width: 30px; }
  .pzi-list { background-size: 30px 100%; }
  .pzi-sh { padding-left: 38px; }
}

/* ------------------------------------------------------ zombies by town ==
   Counts come only from cells a player has streamed at least once, so this is
   "what the world has shown us", not a census. The delta column is blank, not
   zero, when history does not reach back far enough to compare. */
.pz-towns { display: flex; flex-direction: column; gap: 7px; margin-top: 14px; }
.pz-town {
  display: grid; grid-template-columns: 92px 1fr 54px 52px;
  align-items: center; gap: 10px;
  font-size: 12.5px;
}
.pz-town-n { color: var(--g-text-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pz-town-bar {
  height: 7px; border-radius: 4px;
  background: var(--g-surf-2);
  overflow: hidden;
}
.pz-town-bar i {
  display: block; height: 100%;
  background: color-mix(in srgb, var(--accent) 68%, transparent);
}
.pz-town-v {
  text-align: right; font-variant-numeric: tabular-nums;
  font-family: ui-monospace, Consolas, monospace;
}
.pz-town-d {
  text-align: right; font-size: 11.5px;
  font-variant-numeric: tabular-nums;
  color: var(--g-text-4);
}
.pz-town-d.up   { color: var(--g-red); }
.pz-town-d.down { color: var(--g-green); }

@media (max-width: 560px) {
  .pz-town { grid-template-columns: 74px 1fr 46px 44px; gap: 7px; }
}

/* --------------------------------------------------------- migration ==
   The field and the arrows are styled to read as different kinds of claim.
   Arrivals and departures are flat translucent fills - arithmetic, no opinion.
   An arrow is a statement that a particular horde walked somewhere, so it is
   drawn solid and deliberately looks authored. */
.km-mig-in  { fill: #f0713a; stroke: none; }
.km-mig-in.b1 { fill-opacity: .16; }
.km-mig-in.b2 { fill-opacity: .34; }
.km-mig-in.b3 { fill-opacity: .58; }
.km-mig-out { fill: #4a7fd0; stroke: none; }
.km-mig-out.b1 { fill-opacity: .13; }
.km-mig-out.b2 { fill-opacity: .26; }
.km-mig-out.b3 { fill-opacity: .44; }

.km-mig-line {
  stroke: #ffd24a; fill: none;
  stroke-linecap: round;
  opacity: .92;
}
.km-mig-head { fill: #ffd24a; opacity: .95; }

.pz-lg.mig-in i  { background: #f0713a; }
.pz-lg.mig-out i { background: #4a7fd0; }

/* --- the window picker --- */
.pz-migbar {
  display: flex; align-items: center; gap: 7px; flex-wrap: wrap;
  margin-top: 10px;
}
.pz-migbar-l {
  font-size: 10px; letter-spacing: .8px; text-transform: uppercase;
  color: var(--g-text-4);
}
.pz-migbar-n {
  font-size: 11.5px; color: var(--g-text-3);
  margin-left: auto; text-align: right;
}
.pz-mini {
  font: inherit; font-size: 11.5px; font-weight: 600;
  color: var(--g-text-3); background: transparent;
  border: 1px solid var(--g-border); border-radius: 6px;
  padding: 3px 9px; cursor: pointer;
}
.pz-mini:hover { color: var(--g-text); border-color: var(--g-text-3); }
.pz-mini[aria-pressed="true"] {
  color: var(--g-text);
  border-color: color-mix(in srgb, var(--accent) 55%, var(--g-border));
  background: color-mix(in srgb, var(--accent) 14%, transparent);
}

@media (max-width: 560px) {
  .pz-migbar-n { margin-left: 0; width: 100%; text-align: left; }
}

/* ------------------------------------------------------------- vardiya --- */
/* Browser-side shifts. Site palette rather than the in-game window chrome:
   this is a page you use at work, not a recreation of the character screen. */
.vd-flash {
  margin: 0 0 12px; padding: 9px 12px; border-radius: 8px;
  font-size: 12.5px; color: var(--g-text-3);
  background: var(--g-surf-2); border: 1px solid var(--g-border);
}
.vd-flash.is-err { color: #d08a72; border-color: #5c3226; background: #2a1613; }

.vd-run {
  display: flex; align-items: center; justify-content: space-between;
  gap: 14px; flex-wrap: wrap;
  padding: 16px; margin-top: 14px; border-radius: 10px;
  background: var(--g-surf-2); border: 1px solid var(--g-border);
}
.vd-run.is-ready { border-color: color-mix(in srgb, var(--accent) 55%, var(--g-border)); }
.vd-run-n { font-size: 15px; font-weight: 700; color: var(--g-text); }
.vd-count {
  font-family: ui-monospace, Consolas, monospace;
  font-size: 21px; font-variant-numeric: tabular-nums;
  color: var(--accent);
}
.vd-form { margin: 0; }

.vd-grid {
  display: grid; gap: 9px; margin-top: 14px;
  /* 208 rather than 232 so a full-width working column fits four across
     instead of three. Fifteen shifts is four rows here and eight in the old
     760px stack, which is the difference between a board and a list. */
  grid-template-columns: repeat(auto-fill, minmax(208px, 1fr));
  /* Each card is its own height. Stretching a row to its tallest member left
     the short ones with a band of nothing above their footer, because the
     footer is bottom-pinned; a card with one loot line looked broken next to
     one with six. */
  align-items: start;
}
.vd-card {
  display: flex; flex-direction: column; gap: 8px;
  padding: 11px 12px; border-radius: 9px;
  background: var(--g-surf-2); border: 1px solid var(--g-border);
}
/* Dimmed, not hidden: seeing the shifts you cannot take is how you learn that
   position and gear decide what is on offer. */
.vd-card.is-off { opacity: .5; }
.vd-recipe.is-off { opacity: .5; }
.vd-card-h { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }
.vd-card-n { font-size: 13px; font-weight: 700; color: var(--g-text); }
.vd-card-t {
  font-size: 11px; color: var(--g-text-4); font-variant-numeric: tabular-nums; flex: none;
}
.vd-card-b { display: flex; flex-wrap: wrap; gap: 4px; }
/* Labels the loose item names, which read as noise without one. */
.vd-loot-l {
  width: 100%; margin-top: 2px;
  font-size: 9px; letter-spacing: .09em; text-transform: uppercase;
  color: var(--g-text-4);
}
.vd-with {
  display: inline-flex; align-items: center; gap: 4px;
  width: 100%; margin-top: 3px;
  font-size: 10.5px; color: var(--g-green);
}
.vd-with .ico { width: 11px; height: 11px; }
/* The one shift that wants you somewhere dangerous. */
.vd-card.is-patrol { border-color: color-mix(in srgb, #d06a52 30%, var(--g-border)); }

.vd-xp, .vd-loot {
  font-size: 10.5px; padding: 3px 6px; border-radius: 3px;
  border: 1px solid var(--g-border); color: var(--g-text-3); background: var(--g-surf);
}
.vd-xp b { color: var(--accent); font-weight: 700; }
.vd-loot { color: var(--g-text-4); }
.vd-card-f {
  display: flex; align-items: center; justify-content: space-between;
  gap: 8px; margin-top: 2px;
}
.vd-risk {
  font-size: 9.5px; letter-spacing: .08em; text-transform: uppercase;
  color: #7f8a6f;
  white-space: nowrap;   /* "DÜŞÜK RİSK" broke across two lines at 208px */
}
.vd-risk.r2, .vd-risk.r3 { color: #b8964f; }
.vd-no { font-size: 10.5px; color: var(--g-text-4); }
.vd-go {
  font: inherit; font-size: 11.5px; font-weight: 700;
  padding: 5px 12px; border-radius: 6px; cursor: pointer;
  color: #10120f; background: var(--accent); border: 1px solid var(--accent);
}
.vd-go:hover { filter: brightness(1.08); }

.vd-pend { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 14px; }
.vd-pend-i {
  display: inline-flex; align-items: center; gap: 3px;
  font-size: 11.5px; padding: 4px 8px; border-radius: 4px;
  color: var(--g-text-3); background: var(--g-surf-2); border: 1px solid var(--g-border);
}
.vd-pend-i b { color: var(--accent); font-weight: 700; margin-left: 3px; }

/* A kasa row is a button: the whole chip sends that stack to the game. */
.kasa-row { display: contents; }
button.vd-pend-i.is-send { font: inherit; font-size: 11.5px; cursor: pointer; }
button.vd-pend-i.is-send .ico {
  width: 11px; height: 11px; opacity: 0; margin-left: 1px;
  transition: opacity .14s;
}
button.vd-pend-i.is-send:hover {
  color: var(--g-text);
  border-color: color-mix(in srgb, var(--accent) 55%, var(--g-border));
}
button.vd-pend-i.is-send:hover .ico { opacity: .8; }
/* Already asked for and on its way: nothing left to press. */
.vd-pend-i.is-transit { opacity: .62; }
.kasa-all { margin-top: 12px; }
/* siginak.php's link through to Vardiya. */
.sgk-nav { margin: 0 0 18px; }
.vd-sub {
  margin: 16px 0 6px;
  font-size: 9.5px; letter-spacing: 1.1px; text-transform: uppercase;
  color: var(--g-text-4);
}

/* Context strip: where you are, what season it is, how busy the dead are. */
.vd-ctx { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 14px; }
.vd-ctx-i {
  font-size: 10.5px; padding: 3px 8px; border-radius: 3px;
  color: var(--g-text-3); background: var(--g-surf-2); border: 1px solid var(--g-border);
}
/* Only the crowded state earns a warning colour. A handful of wanderers is the
   normal condition of Knox County and should not read as an alarm. */
.vd-ctx-i.is-warm { color: #b8964f; border-color: #4a3c22; }
.vd-ctx-i.is-hot  { color: #d08a72; border-color: #5c3226; background: #2a1613; }

.vd-craft { display: flex; flex-direction: column; gap: 6px; }
.vd-recipe {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  margin: 0; padding: 8px 10px; border-radius: 8px;
  background: var(--g-surf-2); border: 1px solid var(--g-border);
}
.vd-recipe-n { font-size: 12px; font-weight: 700; color: var(--g-text); }
.vd-recipe-io { font-size: 11px; color: var(--g-text-4); flex: 1; min-width: 0; }

/* ------------------------------------------------------------------- iz */
/* A trail in progress is the only thing on the page that is a scene rather
   than a table, so it gets room to be read. */
.iz-run {
  padding: 14px 16px; border-radius: 10px; margin-top: 14px;
  background: var(--g-surf-2); border: 1px solid var(--g-border);
}
.iz-run-h {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 10px; margin-bottom: 10px;
}
.iz-run-t { font-size: 15px; font-weight: 700; color: var(--g-text); }
.iz-step {
  font-size: 10.5px; color: var(--g-text-4);
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
.iz-text {
  margin: 0 0 14px; font-size: 14.5px; line-height: 1.6;
  color: var(--g-text-2); max-width: 62ch;
}
.iz-wait { margin: 0 0 6px; font-size: 13px; color: var(--g-text-3); }

.iz-choices { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.iz-choice {
  display: flex; flex-direction: column; align-items: flex-start; gap: 3px;
  font: inherit; text-align: left; cursor: pointer;
  padding: 9px 13px; border-radius: 8px;
  color: var(--g-text); background: var(--g-surf);
  border: 1px solid var(--g-border);
  transition: border-color .14s, background .14s;
}
.iz-choice:hover {
  border-color: color-mix(in srgb, var(--accent) 60%, var(--g-border));
  background: color-mix(in srgb, var(--accent) 8%, var(--g-surf));
}
.iz-choice-n { font-size: 13.5px; font-weight: 600; }
/* r0..r10 is round(risk * 10), so r2 and up is the genuinely risky end. */
.iz-choice-r {
  font-size: 9.5px; letter-spacing: .08em; text-transform: uppercase;
  color: #7f8a6f;
}
.iz-choice-r.r2 { color: #b8964f; }
.iz-choice-r.r3, .iz-choice-r.r4, .iz-choice-r.r5 { color: #d08a72; }

.iz-foot {
  display: flex; flex-wrap: wrap; align-items: center; gap: 10px;
  margin-top: 14px; padding-top: 12px;
  border-top: 1px solid var(--g-border);
}
.iz-haul { display: flex; flex-wrap: wrap; gap: 5px; flex: 1; min-width: 0; }
.iz-haul .vd-pend-i { margin: 0; }

.iz-grid {
  display: grid; gap: 9px; margin-top: 14px; align-items: start;
  grid-template-columns: repeat(auto-fill, minmax(196px, 1fr));
}
.iz-card {
  display: flex; flex-direction: column; gap: 7px;
  padding: 11px 12px; border-radius: 9px;
  background: var(--g-surf-2); border: 1px solid var(--g-border);
}
.iz-card.is-off { opacity: .5; }
.iz-card-h { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }
.iz-card-n { font-size: 13px; font-weight: 700; color: var(--g-text); }
.iz-card-c { font-size: 10px; color: var(--g-text-4); white-space: nowrap; }
.iz-card-b { display: flex; flex-wrap: wrap; gap: 5px; }
.iz-beats, .iz-mins {
  font-size: 10.5px; padding: 2px 7px; border-radius: 4px;
  color: var(--g-text-3); background: var(--g-surf); border: 1px solid var(--g-border);
}
.iz-card-f { display: flex; align-items: center; justify-content: space-between; gap: 8px; }

.vd-hist { display: flex; flex-direction: column; gap: 3px; }
.vd-hist-r {
  display: grid; grid-template-columns: 130px 1fr auto;
  gap: 10px; align-items: baseline;
  padding: 5px 0; border-bottom: 1px solid var(--g-border);
  font-size: 11.5px;
}
.vd-hist-r:last-child { border-bottom: 0; }
.vd-hist-n { color: var(--g-text-3); font-weight: 600; }
.vd-hist-w { color: var(--g-text-4); }
.vd-hist-bad { color: #b8964f; }
.vd-hist-t { color: var(--g-text-4); font-size: 10.5px; font-variant-numeric: tabular-nums; }

@media (max-width: 560px) {
  .vd-hist-r { grid-template-columns: 1fr; gap: 2px; }
}

/* =========================================================
   Phone pass (2026-08-12)
   Tap sizes are keyed to the pointer, so a touch device gets
   them at any width; the type floors are keyed to width, so a
   narrowed desktop window reads the same as a phone.
   ========================================================= */
@media (pointer: coarse) {
  .vd-go { padding: 9px 16px; }
  button.vd-pend-i.is-send { padding: 8px 10px; }
  .pzw-tab { height: 30px; }
}
@media (max-width: 640px) {
  /* 9px uppercase micro-labels are legible under a desk lamp and not on a
     phone on the bus. Floor, not restyle: the hierarchy stays. */
  .vd-loot-l { font-size: 10px; }
  .vd-risk   { font-size: 10.5px; }
  .vd-sub    { font-size: 10.5px; }
  .pz-stamp  { font-size: 10.5px; }
}

/* =========================================================
   Public page: time-lapse + Sığınak window (2026-08-13)
   ========================================================= */
.pz-lapsebar .pz-lapse-r {
  flex: 1; min-width: 120px; max-width: 340px; accent-color: var(--accent);
  align-self: center;
}
.pz-lapsebar.is-empty .pz-lapse-r, .pz-lapsebar.is-empty [data-pz-lapse-live] { display: none; }
/* Horde rings are "now" markers; the past has no business wearing them. */
.pz-lapse-on .pz-mk.horde { display: none; }

.pz-sgkwin {
  display: flex; align-items: center; gap: 18px; flex-wrap: wrap;
  margin: 0 0 22px; padding: 12px 16px; border-radius: 10px;
  border: 1px solid color-mix(in srgb, var(--accent) 30%, var(--g-border));
  background: color-mix(in srgb, var(--accent) 6%, var(--g-surf));
}
.pz-sgkwin-h {
  display: flex; align-items: baseline; gap: 8px; text-decoration: none;
}
.pz-sgkwin-h .ico { width: 15px; height: 15px; color: var(--accent); align-self: center; }
.pz-sgkwin-h b {
  font-size: 13px; letter-spacing: 1.8px; text-transform: uppercase;
  color: var(--accent); font-weight: 800;
}
.pz-sgkwin-h span { font-size: 11px; color: var(--g-text-4); }
.pz-sgkwin-h:hover b { filter: brightness(1.15); }
.pz-sgkwin-p { display: flex; align-items: center; gap: 9px; flex: 1; min-width: 200px; }
.pz-sgkwin-n { font-size: 12px; color: var(--g-text-2); white-space: nowrap; }
.pz-sgkwin-bar {
  flex: 1; max-width: 220px; height: 5px; border-radius: 3px; overflow: hidden;
  background: var(--g-surf-2); border: 1px solid var(--g-border);
}
.pz-sgkwin-bar i { display: block; height: 100%; background: var(--accent); }
.pz-sgkwin-v { font-size: 11px; color: var(--g-text-3); font-variant-numeric: tabular-nums; }
.pz-sgkwin-w { display: flex; align-items: center; gap: 7px; flex-wrap: wrap; }
.pz-sgkwin-wt { font-size: 9.5px; letter-spacing: 1.5px; color: #c25353; font-weight: 800; }
.pz-sgkwin-wn {
  font-size: 11px; padding: 2px 9px; border-radius: 999px;
  border: 1px dashed color-mix(in srgb, #c25353 45%, var(--g-border));
  color: var(--g-text-2);
}

.pz-town-rank {
  width: 18px; flex: none; text-align: right; font-size: 10.5px;
  color: var(--g-text-4); font-variant-numeric: tabular-nums; font-weight: 700;
}

/* The window grew a voice: the pitch line and a proper door. */
.pz-sgkwin { align-items: center; }
.pz-sgkwin-l { flex: 1; min-width: 260px; display: flex; flex-direction: column; gap: 8px; }
.pz-sgkwin-pitch { margin: 0; font-size: 12.5px; line-height: 1.55; color: var(--g-text-2); max-width: 640px; }
.pz-sgkwin-cta {
  flex: none; align-self: center;
  background: var(--accent); color: #14100e; border-color: var(--accent);
  font-weight: 700;
}
.pz-sgkwin-cta:hover { filter: brightness(1.08); }
.pz-sgkwin-cta .ico { color: inherit; }

/* ============================================================= god-view
   pzadmin.php only; the public page never emits these class names. Colors
   follow the site tokens; no left-accent borders by house rule. */

.pz-mk.pk-ppl .pz-mk-dot {
  background: var(--accent); width: 10px; height: 10px;
  animation: pz-ping 2.4s infinite;
}
.pz-mk.pk-off .pz-mk-dot {
  background: #8a8578; width: 8px; height: 8px; opacity: .75;
}
.pz-mk.pk-rip .pz-mk-dot {
  background: #c25b4e; width: 8px; height: 8px; border-radius: 1px;
  transform: rotate(45deg);
}
.pz-mk.pk-safe-lbl .pz-mk-tag,
.pz-mk.pk-zone-lbl .pz-mk-tag { background: rgba(20,16,14,.82); }

.km-safe rect {
  fill: rgba(224,181,107,.14); stroke: var(--accent);
  stroke-width: 3; vector-effect: non-scaling-stroke;
}
.km-zone rect {
  fill: rgba(127,176,214,.10); stroke: #7fb0d6;
  stroke-width: 2; stroke-dasharray: 6 4; vector-effect: non-scaling-stroke;
}

/* ---------------------------------------------------- movement trails ---
   Route geometry only. The per-player colour arrives as a `stroke` attribute
   from the renderer, so there is no `.tr-N` colour table any more - the old
   one carried `fill` alongside `stroke` at a specificity that beat both
   `fill:none` rules, and every trail rendered as a filled polygon. */
.km-trails polyline, .km-trails path { fill: none; }
.km-tr-leg { stroke-linejoin: round; stroke-linecap: round; }
.km-tr-leg.is-walk  { stroke-width: 2.5; }
.km-tr-leg.is-drive { stroke-width: 4; }
.km-tr-chev { stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.km-tr-gap  { stroke-width: 1.5; stroke-dasharray: 3 7; }

/* A stop: a ring sized by how long they stayed, with the duration under it.
   An overlay element, not SVG, so it holds its size at every zoom. */
.pzm-stop {
  position: absolute; transform: translate(-50%, -50%);
  border-radius: 50%; cursor: default;
  border: 2px solid currentColor;
  background: color-mix(in srgb, currentColor 18%, transparent);
}
/* A bare ring reads as decoration; a dot in the middle reads as a place. */
.pzm-stop u {
  position: absolute; left: 50%; top: 50%;
  width: 3px; height: 3px; margin: -1.5px 0 0 -1.5px;
  border-radius: 50%; background: currentColor; opacity: .9;
}
/* Under the ring, never inside it: a 16 px ring cannot hold "1 sa 3 dk".
   Visibility is arbitrated per frame in placeStopLabels(). */
.pzm-stop b {
  position: absolute; left: 50%; top: 100%; transform: translateX(-50%);
  margin-top: 3px; padding: 1px 5px; white-space: nowrap;
  font-size: 9.5px; font-weight: 700; letter-spacing: .03em;
  color: var(--g-text); background: rgba(12, 16, 22, .88);
  border: 1px solid var(--g-border); border-radius: 4px;
  font-variant-numeric: tabular-nums;
}

.pzm-head {
  position: absolute; transform: translate(-50%, -50%);
  display: flex; flex-direction: column; align-items: center; gap: 2px;
}
.pzm-head i {
  width: 13px; height: 13px; border-radius: 50%; background: currentColor;
  box-shadow: 0 0 0 2.5px #14100e,
              0 0 12px color-mix(in srgb, currentColor 70%, transparent);
}
.pzm-head b {
  padding: 1px 6px; border-radius: 4px; white-space: nowrap;
  font-size: 9.5px; font-weight: 700; letter-spacing: .04em;
  color: var(--g-text); background: rgba(12, 16, 22, .9);
  border: 1px solid var(--g-border);
  /* Survivor names run long ("Kenny \"Fucking\" Powers"); an unbounded tag
     smears across half a town at county zoom. */
  max-width: 108px; overflow: hidden; text-overflow: ellipsis;
}
.pzm-head.is-live i { animation: pzm-pulse 1.9s ease-out infinite; }
@keyframes pzm-pulse {
  0%   { box-shadow: 0 0 0 2.5px #14100e,
                     0 0 0 0 color-mix(in srgb, currentColor 60%, transparent); }
  100% { box-shadow: 0 0 0 2.5px #14100e, 0 0 0 16px transparent; }
}
@media (prefers-reduced-motion: reduce) {
  .pzm-head.is-live i { animation: none; }
}

/* ------------------------------------------------ floating map controls ---
   Layer list and zoom sit ON the map. They used to occupy two of the four
   control rows stacked around it. */
.pzm-float { position: absolute; z-index: 6; display: flex; gap: 6px; }
/* Anchored top AND bottom so the column has a definite height: the panel's
   max-height is a percentage of it, and a percentage against an auto height
   resolves to nothing - which let the panel outgrow the map and get clipped by
   .pz-mapwrap's overflow:hidden, stranding the world layers off-screen.
   The column itself must not eat map drags, so only its children take events. */
.pzm-float.tl {
  top: 10px; left: 10px; bottom: 10px;
  flex-direction: column; align-items: flex-start;
  pointer-events: none;
}
.pzm-float.tl > * { pointer-events: auto; }
.pzm-float.br { bottom: 10px; right: 10px; align-items: center; }

.pzm-pill {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 6px 10px; border-radius: 8px;
  font: inherit; font-size: 11.5px; font-weight: 600;
  color: var(--g-text-3); cursor: pointer;
  background: rgba(20, 16, 14, .88);
  border: 1px solid var(--g-border);
  -webkit-backdrop-filter: blur(3px); backdrop-filter: blur(3px);
}
.pzm-pill:hover { color: var(--accent); border-color: var(--accent); }
.pzm-pill .ico { width: 13px; height: 13px; }
.pzm-pill[aria-expanded="true"] { color: var(--accent); border-color: var(--accent); }
.pzm-zbtn { width: 30px; height: 30px; padding: 0; justify-content: center;
            font-size: 16px; line-height: 1; }
.pzm-zlvl {
  padding: 6px 8px; font-size: 11px; color: var(--g-text-4);
  background: rgba(20, 16, 14, .88); border: 1px solid var(--g-border);
  border-radius: 8px; font-variant-numeric: tabular-nums;
}

.pzm-panel {
  width: 236px; padding: 6px;
  flex: 0 1 auto; min-height: 0; overflow-y: auto;
  overscroll-behavior: contain;
  background: rgba(20, 16, 14, .94);
  border: 1px solid var(--g-border); border-radius: 10px;
  -webkit-backdrop-filter: blur(4px); backdrop-filter: blur(4px);
  box-shadow: 0 8px 26px rgba(0, 0, 0, .5);
}
.pzm-sec {
  padding: 7px 8px 3px;
  font-size: 9.5px; letter-spacing: .9px; text-transform: uppercase;
  color: var(--g-text-4); font-weight: 700;
}
.pzm-row {
  display: flex; align-items: center; gap: 9px;
  width: 100%; padding: 6px 8px; border-radius: 7px;
  font: inherit; font-size: 12.5px; color: var(--g-text-3);
  background: transparent; border: 0; cursor: pointer; text-align: left;
}
.pzm-row:hover { background: color-mix(in srgb, var(--accent) 9%, transparent);
                 color: var(--g-text); }
.pzm-row[aria-pressed="true"] { color: var(--g-text); }
.pzm-row[aria-pressed="false"] { color: var(--g-text-4); }
.pzm-row[aria-pressed="false"] .pzm-sw { opacity: .22; }
/* Each row carries its own swatch, which is what retires the legend strip. */
.pzm-sw { width: 11px; height: 11px; border-radius: 50%; flex: none;
          background: var(--accent); }
.pzm-sw.sq   { border-radius: 2px; }
.pzm-sw.dia  { border-radius: 1px; transform: rotate(45deg); }
.pzm-sw.ring { background: transparent; border: 2px solid var(--accent); }
.pzm-n { margin-left: auto; font-size: 11px; color: var(--g-text-4);
         font-variant-numeric: tabular-nums; }
/* pz.js disables the Göç row when the server has no history to compare. */
.pzm-row[disabled] { opacity: .4; cursor: default; }
.pzm-row[disabled]:hover { background: transparent; color: var(--g-text-4); }
/* Parameters belong to their layer, not to a control bar of their own. */
.pzm-sub { display: flex; gap: 4px; flex-wrap: wrap; padding: 2px 8px 8px 28px; }
/* An author `display` outranks the user-agent `[hidden] { display: none }`
   rule, so without this the hidden attribute on a sub-row does nothing. */
.pzm-sub[hidden] { display: none; }

.pzm-chip {
  font: inherit; font-size: 10.5px; font-weight: 600;
  color: var(--g-text-4); background: transparent;
  border: 1px solid var(--g-border); border-radius: 5px;
  padding: 2px 7px; cursor: pointer;
}
.pzm-chip:hover { color: var(--g-text); border-color: var(--g-text-3); }
.pzm-chip[aria-pressed="true"] {
  color: var(--accent);
  border-color: color-mix(in srgb, var(--accent) 55%, var(--g-border));
  background: color-mix(in srgb, var(--accent) 14%, transparent);
}

/* ------------------------------------------------------- the one timeline */
.pzm-time {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 12px 16px; border-top: 1px solid var(--g-border);
}
.pzm-play, .pzm-step {
  display: inline-flex; align-items: center; justify-content: center;
  flex: none; padding: 0; border-radius: 8px; cursor: pointer;
  color: var(--g-text); background: var(--g-surf-2);
  border: 1px solid var(--g-border);
}
.pzm-play { width: 32px; height: 32px; }
.pzm-step { width: 26px; height: 26px; }
.pzm-play:hover, .pzm-step:hover { color: var(--accent); border-color: var(--accent); }
.pzm-play .ico { width: 14px; height: 14px; }
.pzm-step .ico { width: 11px; height: 11px; }

.pzm-speed { display: inline-flex; flex: none; }
.pzm-speed .pzm-chip {
  border-radius: 0; margin-left: -1px; padding: 4px 8px; font-size: 11px;
}
.pzm-speed .pzm-chip:first-child { border-radius: 6px 0 0 6px; margin-left: 0; }
.pzm-speed .pzm-chip:last-child  { border-radius: 0 6px 6px 0; }
.pzm-speed .pzm-chip[aria-pressed="true"] { position: relative; z-index: 1; }

.pzm-scrub { flex: 1 1 220px; min-width: 150px; position: relative; }
.pzm-range { width: 100%; margin: 0; display: block; accent-color: var(--accent);
             background: transparent; }
/* Where there is anything to watch, before you press play. */
.pzm-bands { position: absolute; left: 0; right: 0; pointer-events: none; }
.pzm-band  { position: absolute; height: 3px; border-radius: 2px; opacity: .8; }

.pzm-clock {
  font-size: 12px; color: var(--g-text); font-weight: 600;
  font-variant-numeric: tabular-nums; flex: none;
  min-width: 96px; text-align: right;
}
.pzm-clock small { display: block; font-size: 10px; font-weight: 400;
                   color: var(--g-text-4); }
.pzm-time.is-empty .pzm-speed,
.pzm-time.is-empty .pzm-scrub,
.pzm-time.is-empty .pzm-play,
.pzm-time.is-empty .pzm-step { display: none; }

/* --------------------------------------------------- who chips + stops --- */
.pzm-who { display: flex; gap: 5px; flex-wrap: wrap; padding: 0 16px 10px; }
.pzm-who-c { display: inline-flex; align-items: center; gap: 5px;
             padding: 3px 9px; font-size: 11.5px; }
.pzm-who-c i { width: 8px; height: 8px; border-radius: 50%;
               background: currentColor; flex: none; }

.pzm-trips { padding: 0 16px 14px; }
.pzm-trip {
  display: grid; grid-template-columns: 10px 54px 1fr auto;
  gap: 10px; align-items: baseline; width: 100%; text-align: left;
  padding: 7px 0; font: inherit; font-size: 12.5px; cursor: pointer;
  color: var(--g-text-3); background: none;
  border: 0; border-bottom: 1px solid var(--g-border);
}
.pzm-trip:last-child { border-bottom: 0; }
.pzm-trip:hover { color: var(--g-text); }
.pzm-trip i { width: 9px; height: 9px; border-radius: 50%;
              background: currentColor; align-self: center; }
.pzm-trip time { color: var(--g-text-4); font-size: 11.5px;
                 font-variant-numeric: tabular-nums; }
.pzm-trip strong { font-weight: 600; color: inherit; }
.pzm-trip span span { color: var(--g-text-4); font-size: 11.5px; }
.pzm-trip em { font-style: normal; color: var(--g-text-4); font-size: 11.5px;
               font-variant-numeric: tabular-nums; }

/* A panel wider than the map it describes helps nobody. */
@media (max-width: 560px) {
  .pzm-panel { width: 200px; }
  .pzm-clock { min-width: 0; }
  .pzm-time  { gap: 8px; }
}

.pz-mk.fac-0 .pz-mk-dot { box-shadow: 0 0 0 3px #e0b56b55; }
.pz-mk.fac-1 .pz-mk-dot { box-shadow: 0 0 0 3px #7fb0d655; }
.pz-mk.fac-2 .pz-mk-dot { box-shadow: 0 0 0 3px #9ad67f55; }
.pz-mk.fac-3 .pz-mk-dot { box-shadow: 0 0 0 3px #d67f7f55; }
.pz-mk.fac-4 .pz-mk-dot { box-shadow: 0 0 0 3px #b78fd655; }
.pz-mk.fac-5 .pz-mk-dot { box-shadow: 0 0 0 3px #d6cd7f55; }

.pz-lg.ppl i  { background: var(--accent); }
.pz-lg.off i  { background: #8a8578; }
.pz-lg.rip i  { background: #c25b4e; }
.pz-lg.safe i { background: rgba(224,181,107,.35); border: 1px solid var(--accent); }

.pza-now { display: flex; flex-direction: column; gap: 6px; margin-top: 10px; }
.pza-nowrow {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  padding: 8px 12px; border: 1px solid rgba(138,133,120,.25);
  border-radius: 8px; background: rgba(224,181,107,.05);
}
.pza-nowrow span { color: #8a8578; font-size: 13px; }
.pza-hp {
  width: 90px; height: 6px; border-radius: 3px;
  background: rgba(194,91,78,.25); overflow: hidden; display: inline-block;
}
.pza-hp i { display: block; height: 100%; background: #9ad67f; }

.pza-heat { display: flex; flex-direction: column; gap: 3px; margin-top: 12px; }
.pza-heatrow { display: flex; gap: 3px; align-items: center; }
.pza-heatlbl { width: 30px; font-size: 11px; color: #8a8578; }
.pza-heatrow i {
  flex: 1; aspect-ratio: 1; border-radius: 2px;
  background: rgba(138,133,120,.12); min-width: 6px;
}
.pza-heatrow i.h1 { background: rgba(224,181,107,.35); }
.pza-heatrow i.h2 { background: rgba(224,181,107,.55); }
.pza-heatrow i.h3 { background: rgba(224,181,107,.75); }
.pza-heatrow i.h4 { background: var(--accent); }

.pza-table { overflow-x: auto; margin-top: 12px; }
.pza-table table { width: 100%; border-collapse: collapse; font-size: 13px; }
.pza-table th, .pza-table td {
  text-align: left; padding: 7px 10px;
  border-bottom: 1px solid rgba(138,133,120,.2);
}
.pza-table th { color: #8a8578; font-weight: 600; }

.pza-chart { margin-top: 12px; min-height: 230px; }
.pz-tl-pl { color: #8a8578; font-size: 12.5px; display: block; }
