/* map.css :: the wall chart page. Everything that is not the chart stays quiet. */

.map-head {
  display: flex; align-items: flex-end; justify-content: space-between;
  gap: 24px; flex-wrap: wrap; padding-top: 28px;
}
.chart-title {
  font-size: clamp(20px, min(3vw, 4.6vh), 38px); font-weight: 800;
  letter-spacing: -0.02em; font-variation-settings: 'wdth' 116; margin-top: 6px;
}
.chart-honesty { max-width: 44ch; text-align: right; }
@media (max-width: 700px) { .chart-honesty { text-align: left; } }

/* --------------------------------------------------------------- rail */
.map-rail { margin-top: 16px; display: grid; gap: 8px; }
.rail-row { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.rail-group { display: inline-flex; gap: 6px; flex-wrap: wrap; }
.rail-label {
  font-family: var(--font-mono); font-size: 10.5px; font-weight: 600;
  letter-spacing: .1em; text-transform: uppercase; color: var(--muted);
  margin-right: 2px;
}
.rail-label:not(:first-child) { margin-left: 10px; }
.rail-text {
  font-family: var(--font-mono); font-size: 12px;
  background: var(--paper-2); border: 1px solid var(--rule);
  border-radius: var(--r-pill); padding: 5px 12px; width: 150px;
}
.rail-text:focus { border-color: var(--cyan-text); }
.rail-spacer { flex: 1; }
.rail-export .chip { border-radius: var(--r-chip); }
#filter-state { min-height: 18px; }

/* --------------------------------------------------------------- stage */
.poster-stage { position: relative; margin-top: 12px; }
.poster-viewport {
  position: relative; overflow: hidden;
  background: var(--paper);
  border: 1px solid var(--rule); border-radius: var(--r-card);
  /* The frame takes the chart's own aspect so fit-zoom fills it edge to edge,
     capped at three quarters of the window. */
  width: 100%; height: auto; aspect-ratio: 1.4;
  max-height: 75vh; max-height: 75dvh; min-height: 420px;
  /* Inline, touch scrolls and pinches over the chart like any other content;
     full screen flips this to none so JS gets the raw gestures (see the
     fullscreen rules below). A mouse can always drag-pan, hence the grab. */
  touch-action: pan-y pinch-zoom; contain: layout paint;
  cursor: grab;
}
.poster-viewport:active { cursor: grabbing; }
/* The chart sits in the same column as everything else. The full-bleed breakout
   went: it left no margin to scroll past, so every wheel gesture over the page
   became a zoom. The gutters give the page back its scroll lane. */
#map-shell {
  max-width: var(--col); margin-inline: auto;
  padding-inline: clamp(16px, 4vw, 32px);
}
.poster-viewport:focus-visible { outline-offset: -3px; }
@media (max-width: 859px) {
  /* the phone frame hugs the chart's aspect instead of letterboxing it */
  .poster-viewport { min-height: 0; }
}
#poster { width: 100%; height: 100%; display: block; }

/* SVG chip states. Filtering and selection dim, never reflow. */
#poster [data-chip] { transition: opacity 160ms, transform 180ms ease; cursor: pointer; }
#poster.has-sel [data-chip], #poster.has-sel .district-shell,
#poster.has-sel .medallion-shell { opacity: .5; }
#poster.has-sel [data-chip].lit { opacity: 1; }
#poster [data-chip].dimmed { opacity: .38; }
#poster.has-sel [data-chip].dimmed:not(.lit) { opacity: .28; }
/* State strokes are screen-pixel, not poster-unit: at full-chart view a scaled
   stroke would be a fraction of a pixel and hover/selection would be invisible. */
#poster [data-chip]:hover .chip-body,
#poster [data-chip].kbd-focus .chip-body {
  stroke: var(--cyan-text); stroke-width: 2px; vector-effect: non-scaling-stroke;
}
#poster [data-chip].sel .chip-body {
  stroke: var(--cyan-text); stroke-width: 3px; vector-effect: non-scaling-stroke;
}
/* A selected company's partners answer with a ring of their own, so the other
   end of every tether is findable at the default zoom, not just less dim. */
#poster.has-sel [data-chip].lit:not(.sel) .chip-body {
  stroke: var(--cyan-text); stroke-width: 2px; vector-effect: non-scaling-stroke;
}
/* A tile leans forward when you rest on it or pick it — a lean, not a bounce.
   Each tile is inset inside its own cell, so it has room to grow without
   touching its neighbours. */
#poster [data-chip] { transform-box: fill-box; transform-origin: center; }
#poster [data-chip]:hover, #poster [data-chip].kbd-focus { transform: scale(1.02); }
#poster [data-chip].sel { transform: scale(1.03); }
#poster [data-chip]:focus { outline: none; }

/* A layer answers as one piece: its whole room takes the layer's own colour, its
   border lights up, and the room itself leans forward a little.

   The rooms share their borders, so a room that grows has nowhere to grow into
   and would sit on top of its neighbours. Rather than push each neighbour away —
   which needs an adjacency map and a direction per pair, and moves things by a
   fixed distance that would look different at every zoom — the other rooms simply
   give a little. Everything here is a relative scale, so the effect is the same
   proportion of each shape whether the whole plate is in view or one tile is.

   The lit district is also raised above its neighbours so its outline is not
   half-covered by theirs. */
/* Borders keep a constant weight on screen at every zoom, so a highlighted
   district reads the same whether the whole plate is in view or one tile is. */
#poster .plate, #poster .d-edge, #poster .d-glow, #poster .oct-edge { vector-effect: non-scaling-stroke; }
#poster .plate { stroke-width: 1.5px; }
#poster .d-edge { stroke-width: 1.2px; }
#poster .d-glow { stroke-width: 3px; }
#poster .oct-edge { stroke-width: 3px; }
#poster .d-glow, #poster .d-wash { transition: opacity 200ms ease; }
#poster .district.hot .d-glow { opacity: .95; }
#poster .district.hot .d-wash { opacity: .13; }
/* The octagon used to answer hover by inflating its border from 3px to 26px, the
   only district on the chart that moved its border at all. Now every room answers
   the same way. */
#poster .district { transform-box: fill-box; transform-origin: center; }
#poster.hot-on .district { transition: transform 220ms ease; }
#poster.hot-on .district.hot { transform: scale(1.01); }
#poster.hot-on .district:not(.hot) { transform: scale(.994); }
/* The tethers went quiet once and nobody could find them again, so they are
   back at full voice: solid, bright, and heavy enough to follow across the
   plate at a glance. */
#poster .links path {
  fill: none; stroke: var(--cyan-text); opacity: .85;
  vector-effect: non-scaling-stroke; stroke-width: 2.2px;
}

/* --------------------------------------------------------------- card */
/* The card opens beside the company it belongs to and follows it while the
   camera moves; poster.js writes left/top. */
#company-card {
  position: absolute; left: 16px; top: 16px; z-index: 30;
  width: min(440px, calc(100vw - 32px));
  max-height: min(640px, calc(100% - 28px)); overflow: auto; overscroll-behavior: contain;
  background: var(--paper-2); border: 1px solid var(--rule);
  border-radius: var(--r-card); padding: 18px;
  box-shadow: 0 18px 48px rgba(18, 19, 15, .2);
  /* One label rail for every block on the card, so HQ, LEADERSHIP and each
     partnership kind all start their values at the same left edge. */
  --cc-label: 96px;
}
#company-card .cc-top { display: flex; align-items: flex-start; gap: 12px; }
#company-card .cc-logo { width: 44px; height: 44px; flex: none; font-size: 16px; border-radius: 9px; }
#company-card .cc-id { min-width: 0; }
/* Body-copy scale throughout: the card is a reading surface, not a headline. */
#company-card h2 { font-size: 17px; font-weight: 800; font-variation-settings: 'wdth' 112; line-height: 1.2; }
#company-card .cc-close { margin-left: auto; color: var(--muted); font-size: 20px; line-height: 1; padding: 2px 6px; }
#company-card .cc-close:hover { color: var(--alert); }
#company-card .cc-layer { font-family: var(--font-mono); font-size: 12px; line-height: 1.5; color: var(--muted); margin-top: 6px; }
#company-card .cc-layer .dot { display: inline-block; vertical-align: -1px; width: 10px; height: 10px; border-radius: 3px; margin-right: 6px; }
#company-card .cc-sub { font-size: var(--fs-base); color: var(--ink-2); margin-top: 12px; line-height: 1.5; }
#company-card .cc-site { margin-top: 11px; font-size: var(--fs-sm); }
#company-card .cc-site a, #company-card .cc-lead a.li {
  display: inline; color: var(--cyan-text);
}
#company-card .cc-lead { margin-top: 12px; font-size: var(--fs-sm); line-height: 1.6; }
#company-card .cc-lead .pk { display: inline-block; min-width: var(--cc-label); }
/* Spoken with directly is the most expensive fact on this site to acquire, so
   it is stated, not hinted at with a dot. */
#company-card .cc-facts {
  display: grid; grid-template-columns: var(--cc-label) 1fr; gap: 5px 12px;
  margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--rule);
  font-size: var(--fs-sm); line-height: 1.45;
}
#company-card .cc-facts dt { font-family: var(--font-mono); font-size: 12px; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); padding-top: 2px; }
#company-card .cc-facts dd { color: var(--ink-2); }
#company-card .cc-partners, #company-card .cc-src {
  margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--rule); font-size: var(--fs-sm);
}
/* Partners are read HERE now, not off the chart: each one a labelled logo
   chip on the same label rail as the facts above it. */
#company-card .pg-row { display: grid; grid-template-columns: var(--cc-label) 1fr; gap: 4px 12px; margin-top: 8px; }
#company-card .pg-row .pk { padding-top: 7px; }
#company-card .pg-chips { display: flex; flex-wrap: wrap; gap: 6px; }
#company-card .cc-partner {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 5px 11px 5px 6px; font-size: 13px; text-align: left;
  background: var(--paper); border: 1px solid var(--rule); border-radius: var(--r-pill);
  transition: border-color 120ms;
}
#company-card .cc-partner:hover { border-color: var(--cyan-text); }
/* A resolvable partner is a link into the chart, and reads like one. */
#company-card .cc-partner:hover span:last-child {
  color: var(--cyan-text); text-decoration: underline; text-underline-offset: 2px;
}
#company-card .cc-partner .cp-logo { width: 26px; height: 26px; font-size: 10px; border-radius: 7px; flex: none; }
#company-card .cc-partner.is-plain { border-style: dashed; color: var(--ink-2); }
#company-card .cc-mail { margin-top: 10px; }
#company-card .pk { color: var(--muted); font-family: var(--font-mono); font-size: 12px; letter-spacing: .06em; }
#company-card .cc-src div { margin-top: 6px; }
#company-card .cc-actions { display: flex; gap: 8px; margin-top: 16px; flex-wrap: wrap; }
#company-card .cc-actions a { font-size: 11px; }
#company-card.sheet {
  position: fixed; left: 50%; top: auto; transform: translateX(-50%);
  right: auto; bottom: 12px; z-index: 350;
  width: min(420px, calc(100vw - 24px)); max-height: 60vh;
}
/* in full screen the sheet must leave the chart visible behind it */
#map-shell:fullscreen #company-card.sheet,
body.fs-pseudo #company-card.sheet { max-height: 44vh; }

/* ---------------------------------------------------------- full screen */
/* Native full screen where the browser allows a div; a fixed overlay where it
   does not, which is every iPhone. The rail travels with the chart either way,
   so the filters stay reachable; the overlay buttons carry exit and fit. */
#map-shell:fullscreen, #map-shell:-webkit-full-screen, body.fs-pseudo #map-shell {
  display: flex; flex-direction: column; background: var(--paper);
  padding: 8px 0 0; max-width: none;
}
body.fs-pseudo #map-shell { position: fixed; inset: 0; z-index: 300; }
body.fs-pseudo { overflow: hidden; }
/* The rail travels into full screen, but on a phone the filter chips would eat
   the screen they were meant to free, so it is capped and scrolls instead. */
#map-shell:fullscreen .map-rail, body.fs-pseudo #map-shell .map-rail {
  flex: 0 1 auto; margin-top: 0; padding: 0 14px; max-width: none;
  max-height: 26vh; overflow-y: auto; overscroll-behavior: contain;
}
@media (max-width: 760px) {
  #map-shell:fullscreen .rail-export .chip:not(#x-full),
  body.fs-pseudo #map-shell .rail-export .chip:not(#x-full) { display: none; }
  /* one line per filter group, scrolled sideways, so the rail costs three rows
     of height instead of ten */
  #map-shell:fullscreen .rail-row, body.fs-pseudo #map-shell .rail-row,
  #map-shell:fullscreen .rail-group, body.fs-pseudo #map-shell .rail-group {
    flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none;
  }
  #map-shell:fullscreen .rail-row .chip, body.fs-pseudo #map-shell .rail-row .chip,
  #map-shell:fullscreen .rail-text, body.fs-pseudo #map-shell .rail-text { flex: none; }
  #map-shell:fullscreen #filter-state, body.fs-pseudo #map-shell #filter-state { display: none; }
}
#map-shell:fullscreen .poster-stage, body.fs-pseudo #map-shell .poster-stage {
  flex: 1 1 auto; min-height: 0; margin-top: 8px;
}
#map-shell:fullscreen .poster-viewport, body.fs-pseudo #map-shell .poster-viewport {
  aspect-ratio: auto; max-height: none; max-width: none; height: 100%; border: 0;
  min-height: 0;
  /* full screen owns the gestures: pinch zooms the chart, drag pans it */
  touch-action: none; cursor: grab;
}
#map-shell:fullscreen .poster-viewport:active,
body.fs-pseudo #map-shell .poster-viewport:active { cursor: grabbing; }
body.fs-pseudo { overscroll-behavior: none; }

/* The persistent full-screen chrome: an exit that never leaves the top-left
   corner and a way back to the whole chart top-right. CSS-only visibility —
   they exist in the markup at all times and appear with the mode. */
.fs-overlay {
  display: none; position: absolute; top: 10px; z-index: 60;
  min-height: 40px; align-items: center;
  box-shadow: 0 6px 20px rgba(18, 19, 15, .22);
}
#fs-exit { left: 10px; }
#fs-fit { right: 10px; }
#map-shell:fullscreen .fs-overlay,
#map-shell:-webkit-full-screen .fs-overlay,
body.fs-pseudo #map-shell .fs-overlay { display: inline-flex; }
/* --------------------------------------------------------------- legend */
/* The key folds away by default: the chart explains most of itself, and the
   reader who wants the fine print opens it once. */
.map-legend { margin-top: 24px; padding-bottom: 8px; }
.map-key > summary {
  display: inline-flex; align-items: center; gap: 7px; cursor: pointer;
  list-style: none; font-family: var(--font-mono); font-size: 12px;
  font-weight: 600; letter-spacing: .08em; text-transform: uppercase;
  border: 1px solid var(--rule); border-radius: var(--r-chip);
  padding: 7px 13px; background: var(--paper-2); user-select: none;
}
.map-key > summary::-webkit-details-marker { display: none; }
.map-key > summary:hover { border-color: var(--cyan-text); }
.map-key .pk-caret { font-size: 10px; transition: transform 160ms ease; }
.map-key[open] .pk-caret { transform: rotate(180deg); }
.map-key[open] > summary { margin-bottom: 16px; }
#legend-layers { display: flex; gap: 8px 16px; flex-wrap: wrap; }
#legend-layers .lg {
  display: inline-flex; align-items: center; gap: 7px;
  font-size: 12.5px; color: var(--ink-2);
}
#legend-layers .lg .sw { width: 14px; height: 14px; border-radius: 4px; flex: none; }
#legend-layers .lg .n { font-family: var(--font-mono); font-size: 11px; color: var(--muted); }
.legend-marks { display: flex; gap: 8px 22px; flex-wrap: wrap; margin-top: 12px; }
.legend-marks > span { display: inline-flex; align-items: center; gap: 7px; }
.pip-demo { display: inline-flex; gap: 2px; }
.pip-demo::before, .pip-demo::after {
  content: ""; width: 7px; height: 7px; border-radius: 50%; display: inline-block;
  background: oklch(var(--layer-l) var(--layer-c) 150);
}
.pip-demo::after { background: oklch(var(--layer-l) var(--layer-c) 20); }

/* --------------------------------------------------------------- print */
@media print {
  /* the full-roster chart is more than twice as tall as it is wide, so the
     sheet stands upright and the chart fills its width */
  @page { size: A0 portrait; margin: 0; }
  body.print-a1 { }
  .map-head, .map-rail, .map-legend, #company-card, .fs-overlay { display: none !important; }
  .poster-viewport {
    aspect-ratio: auto; max-height: none; overflow: visible;
    border: 0; width: 100%; height: auto;
  }
  #poster { width: 100%; height: auto; }
  #poster.has-sel [data-chip], #poster [data-chip].dimmed,
  #poster.has-sel .district-shell, #poster.has-sel .medallion-shell { opacity: 1 !important; }
  #poster .district, #poster .district.hot { transform: none !important; }
  #poster .links { display: none; }
}

/* Remote logos fade in over their monogram tile, so a slow favicon never
   shows as a blank square. */

/* The chart's other motion is gated in JS by reducedMotion(). The hover and
   selection lifts are CSS, so they are gated here. Colour and weight still
   answer, so nothing becomes unusable — it just stops moving. */
@media (prefers-reduced-motion: reduce) {
  #poster [data-chip], #poster.hot-on .district { transition: none; }
  #poster [data-chip]:hover, #poster [data-chip].kbd-focus,
  #poster [data-chip].sel,
  #poster.hot-on .district.hot, #poster.hot-on .district:not(.hot) { transform: none; }
}

/* ------------------------------------------------ filter dropdowns */
/* Layers / Region / Maturity as checkbox menus, the ledger's picker idiom. */
.map-rail .picker { position: relative; }
.map-rail .picker summary { list-style: none; display: inline-flex; align-items: center; gap: 6px; }
.map-rail .picker summary::-webkit-details-marker { display: none; }
.map-rail .picker[open] summary { border-color: var(--cyan-text); color: var(--ink); }
.map-rail .pk-caret { font-size: 9px; transition: transform 140ms ease; }
.map-rail .picker[open] .pk-caret { transform: rotate(180deg); }
.map-rail .pk-n {
  min-width: 16px; padding: 1px 5px; border-radius: var(--r-pill);
  background: var(--cyan); color: #12130F; font-weight: 700; font-size: 10px;
  text-align: center;
}
.map-rail .pop {
  position: absolute; top: calc(100% + 6px); left: 0; z-index: 140;
  background: var(--paper-2); border: 1px solid var(--rule); border-radius: 10px;
  box-shadow: 0 14px 40px rgba(18, 19, 15, .16);
  padding: 10px 12px; min-width: 250px; max-height: 340px; overflow: auto;
}
.map-rail .pop label {
  display: flex; align-items: center; gap: 8px; padding: 5px 0;
  font-size: 13px; cursor: pointer; white-space: nowrap;
}
.map-rail .pop label .dot { width: 9px; height: 9px; border-radius: 3px; flex: none; }
.map-rail .pop label .n { margin-left: auto; font-family: var(--font-mono); font-size: 10.5px; color: var(--muted); }
.map-rail .pop input { accent-color: var(--cyan-text); }
