/* ==========================================================================
   Office network
   --------------------------------------------------------------------------
   A dark band holding two things: a globe, and a card deck of the offices on
   it. The flat SVG world map in here is what the server sends and what a
   reader without JavaScript keeps; assets/js/globe.js swaps it for the globe.
   ========================================================================== */

/* --------------------------------------------------------------------------
   World map — the two countries FAME is registered in
   --------------------------------------------------------------------------
   Four thousand dots in a single stroked path. Because they are stroked rather
   than filled, dot size is stroke-width and dot colour is stroke; the geometry
   file carries no colour of its own, which is what lets the same paths sit on a
   light surface later without regenerating anything.
   -------------------------------------------------------------------------- */

/* --------------------------------------------------------------------------
   Globe
   --------------------------------------------------------------------------
   The flat map ships in the markup and the globe replaces it, so the swap is
   one class: nothing is hidden until the script has confirmed it can render
   something better.
   -------------------------------------------------------------------------- */

.fame-globe {
  margin: 0 0 var(--s-7);
}

.fame-globe--live .fame-globe__flat { display: none; }

.fame-globe__stage {
  position: relative;
  display: flex;
  justify-content: center;
}

.fame-globe canvas {
  display: block;
  max-width: 100%;

  /* grab/grabbing, and touch-action so a horizontal drag spins the globe
     instead of scrolling the page out from under it. */
  cursor: grab;
  touch-action: pan-y;
}

.fame-globe.is-dragging canvas { cursor: grabbing; }

.fame-globe__bar {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  margin-top: var(--s-4);
}

.fame-globe__toggle {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  min-height: 36px;
  padding: 0 var(--s-4);
  border: 1px solid var(--border-hair);
  border-radius: 999px;
  background: none;
  color: var(--muted);
  font-family: var(--font-mono);
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: var(--tr-label);
  text-transform: uppercase;
  cursor: pointer;
  transition: border-color .16s ease, color .16s ease;
}

.fame-globe__toggle::before {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--cyan);
  content: "";
}

.fame-globe__toggle:hover,
.fame-globe__toggle:focus-visible {
  border-color: var(--accent);
  color: var(--on-dark);
}

.fame-globe.is-paused .fame-globe__toggle::before { background: var(--muted); }

.fame-world {
  margin: 0;
}

.fame-world__svg {
  display: block;
  width: 100%;
  height: auto;
  overflow: visible;
}

.fame-world__dots {
  fill: none;
  stroke: rgba(199, 220, 229, .26);   /* --on-dark-2, held well back */
  stroke-width: 2.3;
  stroke-linecap: round;
}

/* The two countries, lit in the brand cyan. */
.fame-world__lit {
  fill: none;
  stroke: var(--cyan);
  stroke-width: 3;
  stroke-linecap: round;
}

.fame-world__route {
  fill: none;
  stroke: var(--cyan-l);
  stroke-width: 1.6;
  stroke-dasharray: 7 9;
  stroke-linecap: round;
  opacity: .55;
}

/* The route draws itself, once, slowly. It is the only motion on the site and
   it earns its place by being the thing the frame is about — 11,000km between
   one firm's two offices. prefers-reduced-motion removes it entirely. */
@media (prefers-reduced-motion: no-preference) {
  .fame-world__route {
    animation: fame-route 2.4s ease-out both;
  }
}

@keyframes fame-route {
  from { stroke-dashoffset: 1200; opacity: 0; }
  to   { stroke-dashoffset: 0; opacity: .55; }
}

.fame-world__hit   { fill: transparent; }
.fame-world__dot   { fill: var(--paper); }

.fame-world__pulse {
  fill: var(--cyan);
  opacity: .30;
  transition: opacity .2s ease;
}

.fame-world__node { cursor: pointer; }
.fame-world__node:focus { outline: none; }

.fame-world__node.is-active .fame-world__pulse,
.fame-world__node:focus-visible .fame-world__pulse { opacity: .75; }

.fame-world__label {
  font-family: var(--font-mono);
  font-size: 13px;
  font-weight: 600;
  letter-spacing: .06em;
  text-anchor: middle;
  fill: var(--on-dark);
  paint-order: stroke;
  stroke: var(--ink);
  stroke-width: 4px;
  stroke-linejoin: round;
}

.fame-world__sub {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: .1em;
  text-anchor: middle;
  text-transform: uppercase;
  fill: var(--cyan-l);
  paint-order: stroke;
  stroke: var(--ink);
  stroke-width: 3.5px;
  stroke-linejoin: round;
}


/* --------------------------------------------------------------------------
   Layout: globe left, office deck right
   --------------------------------------------------------------------------
   The dotted city plot that used to sit here is gone on FAME's instruction.
   Everything it showed — every office, its province, its role — is on the globe
   and in the deck beside it, so it was a third rendering of the same thirteen
   records paying for itself in vertical space.
   -------------------------------------------------------------------------- */

.fame-omap__layout {
  display: grid;
  grid-template-columns: minmax(0, 1.15fr) minmax(320px, 0.85fr);
  gap: clamp(var(--s-6), 4vw, var(--s-8));
  align-items: center;
}

/* --------------------------------------------------------------------------
   Deck — one card per group of offices
   -------------------------------------------------------------------------- */

.fame-deck {
  position: relative;
  min-width: 0;
}

/* The [hidden] attribute is how the deck hides a card, and a bare display rule
   on the class beats the user-agent's [hidden] { display: none } on
   specificity — so all five cards rendered stacked down the page. Any component
   that sets display and is hidden by attribute needs this pair. */
.fame-deck__card[hidden] { display: none; }

.fame-deck__card {
  display: flex;
  flex-direction: column;
  padding: clamp(var(--s-5), 3vw, var(--s-6));
  border: 1px solid var(--border-hair);
  border-radius: var(--r-lg);
  background: linear-gradient(165deg, rgba(255, 255, 255, .07) 0%, rgba(255, 255, 255, .02) 100%);
  backdrop-filter: blur(2px);

  /* A fixed floor so the card does not jump height between a group of one and
     a group of six — the pager sits under it and would move on every advance. */
  min-height: 430px;
}

.fame-deck__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s-4);
}

.fame-deck__kicker,
.fame-deck__count {
  margin: 0;
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: var(--tr-label);
  text-transform: uppercase;
  color: var(--muted);
}

.fame-deck__count { font-variant-numeric: tabular-nums; }

.fame-deck__title {
  display: flex;
  align-items: center;
  gap: var(--s-4);
  margin: var(--s-5) 0 var(--s-5);
  padding-bottom: var(--s-5);
  border-bottom: 1px solid var(--border-hair);
}

/* The two-letter mark. Set in the brand cyan on a tinted disc rather than as
   flat type: at this size it is the card's only piece of colour and it is what
   tells one card from the next at a glance. */
.fame-deck__badge {
  display: grid;
  flex: none;
  place-items: center;
  width: 54px;
  height: 54px;
  border-radius: var(--r-md);
  background: rgba(0, 169, 206, .14);
  color: var(--brand-300);
  font-family: var(--font-mono);
  font-size: 19px;
  font-weight: 600;
  letter-spacing: .04em;
}

.fame-deck__name {
  margin: 0;
  font-size: clamp(20px, 2.4vw, 26px);
  font-weight: var(--w-medium);
  letter-spacing: var(--tr-head);
  line-height: 1.15;
  color: var(--on-dark);
}

.fame-deck__meta {
  margin: 5px 0 0;
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--muted);
}

.fame-deck__list {
  flex: 1;
  margin: 0;
  padding: 0;
  list-style: none;
}

.fame-deck__row {
  display: grid;
  grid-template-columns: 26px minmax(0, 1fr) auto;
  align-items: baseline;
  gap: var(--s-3);
  width: 100%;
  min-height: 44px;
  padding: 9px var(--s-3);
  margin-inline: calc(var(--s-3) * -1);
  border: 0;
  border-radius: var(--r-sm);
  background: none;
  font: inherit;
  color: inherit;
  text-align: left;
  cursor: pointer;
  transition: background-color .15s ease;
}

.fame-deck__row + .fame-deck__row { border-top: 1px solid var(--border-hair); }
.fame-deck__list li + li .fame-deck__row { border-top: 1px solid var(--border-hair); }

.fame-deck__index {
  font-family: var(--font-mono);
  font-size: 10px;
  font-variant-numeric: tabular-nums;
  color: var(--brand-300);
}

.fame-deck__city {
  font-size: clamp(15px, 1.6vw, 18px);
  font-weight: var(--w-medium);
  letter-spacing: -.01em;
  color: var(--on-dark);
  overflow-wrap: break-word;
}

.fame-deck__region {
  font-family: var(--font-mono);
  font-size: 9.5px;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--muted);
  white-space: nowrap;
}

.fame-deck__row:hover,
.fame-deck__row.is-active {
  background: rgba(255, 255, 255, .07);
}

.fame-deck__row.is-active { box-shadow: inset 2px 0 0 var(--brand-500); }

/* The office the globe is actually sitting on.
   Separate from .is-active, which officemap.js drives from the pointer and
   clears on mouseleave — the tour's own state has to survive the reader moving
   their mouse out of the band. It is also the louder of the two on purpose: it
   answers "which of these thirteen am I looking at", so it has to be findable
   in a list of six without hunting, and a background tint alone is not. */
.fame-deck__row.is-current {
  background: rgba(0, 169, 206, .16);
  box-shadow: inset 3px 0 0 var(--brand-400);
}

.fame-deck__row.is-current .fame-deck__city  { color: var(--paper); font-weight: var(--w-bold); }
.fame-deck__row.is-current .fame-deck__index { color: var(--brand-300); }
.fame-deck__row.is-current .fame-deck__region { color: var(--on-dark-2); }

/* A dot on the leading edge, so the current row is still identifiable where the
   tint is not — forced-colours mode, and print. */
.fame-deck__row.is-current .fame-deck__index::before {
  display: inline-block;
  width: 5px;
  height: 5px;
  margin-right: 5px;
  border-radius: 50%;
  background: var(--brand-400);
  vertical-align: middle;
  content: "";
}

.fame-deck__foot {
  display: grid;
  grid-template-columns: 1fr 1fr;
  margin-top: var(--s-5);
  border: 1px solid var(--border-hair);
  border-radius: var(--r-md);
  overflow: hidden;
}

.fame-deck__cell { padding: var(--s-3) var(--s-4); }
.fame-deck__cell + .fame-deck__cell { border-left: 1px solid var(--border-hair); }

.fame-deck__celllabel {
  margin: 0 0 3px;
  font-family: var(--font-mono);
  font-size: 9px;
  font-weight: 600;
  letter-spacing: var(--tr-label);
  text-transform: uppercase;
  color: var(--muted);
}

.fame-deck__cellvalue {
  margin: 0;
  font-size: var(--t-sm);
  font-weight: var(--w-medium);
  color: var(--on-dark);
}

/* --------------------------------------------------------------------------
   Pager
   -------------------------------------------------------------------------- */

.fame-deck__pager {
  display: flex;
  gap: 6px;
  margin-top: var(--s-5);
}

/* A wide, low bar rather than a dot: it is a bigger target, it shows how many
   groups there are without counting, and the current one can lengthen rather
   than just change colour. */
.fame-deck__dot {
  flex: 1;
  height: 44px;                 /* the target; the bar inside is the mark */
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
}

.fame-deck__dot::before {
  display: block;
  height: 3px;
  border-radius: 3px;
  background: rgba(255, 255, 255, .18);
  transition: background-color .2s ease;
  content: "";
}

.fame-deck__dot:hover::before { background: rgba(255, 255, 255, .38); }
.fame-deck__dot.is-current::before { background: var(--brand-400); }

.fame-omap__more {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-top: var(--s-5);
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .12em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--accent-text);
}

.fame-omap__more::after { content: "→"; }
.fame-omap__more:hover  { text-decoration: underline; text-underline-offset: .3em; }

/* --------------------------------------------------------------------------
   Tablet and phone
   -------------------------------------------------------------------------- */

@media (max-width: 1040px) {
  /* Globe over deck. Below this the globe cannot be both large enough to read
     and narrow enough to leave the card a usable column. */
  .fame-omap__layout { grid-template-columns: 1fr; gap: var(--s-6); }
  .fame-globe { margin-bottom: 0; }
  .fame-deck__card { min-height: 0; }
}

@media (max-width: 620px) {
  .fame-deck__card { padding: var(--s-4); }

  .fame-deck__title {
    gap: var(--s-3);
    margin-block: var(--s-4);
    padding-bottom: var(--s-4);
  }

  .fame-deck__badge { width: 44px; height: 44px; font-size: 15px; }

  /* Region drops below the city rather than fighting it for a 340px row. */
  .fame-deck__row {
    grid-template-columns: 24px minmax(0, 1fr);
    row-gap: 2px;
  }

  .fame-deck__region { grid-column: 2; white-space: normal; }

  .fame-deck__foot { grid-template-columns: 1fr; }

  .fame-deck__cell + .fame-deck__cell {
    border-left: 0;
    border-top: 1px solid var(--border-hair);
  }
}
