/* CoreBridge Intelligence: Knowledge Map, the overlay stylesheet.
   styles.css (the estate family sheet) loads first and owns every token.
   This file defines only what the family sheet lacks: the map stage, the
   radial canvas, the detail rail, the mobile drill and the map toolbar.
   No hex values and no font names beyond the family sheet's own live here;
   every colour reads var(...). */

/* Fonts, redeclared with map-relative URLs (11 Aug 2026). The copied family
   sheet points at ../fonts/, which resolves above this page's folder on the
   deployed path and 404s, so the live map fell back to system faces. Same
   family names and weights as the family sheet's own rules; this sheet loads
   second, so these src lists win. */
@font-face { font-family: "Hanken Grotesk"; src: url("fonts/HankenGrotesk-VariableFont_wght.woff2") format("woff2-variations"); font-weight: 100 900; font-style: normal; font-display: swap; }
@font-face { font-family: "Spectral"; src: url("fonts/Spectral-Regular.woff2") format("woff2"); font-weight: 400; font-style: normal; font-display: swap; }
@font-face { font-family: "Spectral"; src: url("fonts/Spectral-Medium.woff2") format("woff2"); font-weight: 500; font-style: normal; font-display: swap; }
@font-face { font-family: "Spectral"; src: url("fonts/Spectral-SemiBold.woff2") format("woff2"); font-weight: 600; font-style: normal; font-display: swap; }
@font-face { font-family: "Spectral"; src: url("fonts/Spectral-Bold.woff2") format("woff2"); font-weight: 700; font-style: normal; font-display: swap; }

/* ---------------------------------------------------------------- shell */
.map-page-main { max-width: var(--col-max); margin: 0 auto; padding: 0 var(--col-pad) 40px; }

.map-toolbar {
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
  padding: 12px 0 10px; border-bottom: 1px solid var(--rule-soft);
}
.map-crumbs { display: flex; align-items: center; gap: 4px; flex-wrap: wrap; min-height: 30px; }
.map-crumbs .crumb {
  font: 600 12.5px/1.2 var(--display); letter-spacing: .01em;
  color: var(--accent-ink); background: none; border: 0; cursor: pointer;
  padding: 5px 7px; border-radius: var(--r-chip);
}
.map-crumbs .crumb:hover { background: var(--accent-wash); }
.map-crumbs .crumb[aria-current="page"] { color: var(--ink); cursor: default; background: none; }
.map-crumbs .crumb-sep { color: var(--ink-4); font-size: 11px; }

.map-search { position: relative; margin-left: auto; }
.map-search input {
  font: 500 13px/1.2 var(--display); color: var(--ink);
  background: var(--paper-bright); border: 1px solid var(--rule);
  border-radius: var(--r-ctl); padding: 8px 12px; width: min(300px, 74vw);
}
.map-search input:focus { outline: 2px solid var(--accent-control); outline-offset: 1px; }
.map-search-list {
  position: absolute; top: calc(100% + 4px); right: 0; z-index: 40;
  width: min(360px, 86vw); max-height: 320px; overflow: auto;
  background: var(--paper-bright); border: 1px solid var(--rule);
  border-radius: var(--r-ctl); box-shadow: 0 10px 28px rgba(0,0,0,.14);
  margin: 0; padding: 4px; list-style: none;
}
.map-search-list[hidden] { display: none; }
.map-search-list li {
  padding: 8px 10px; border-radius: var(--r-chip); cursor: pointer;
  font: 500 13px/1.35 var(--display); color: var(--ink);
  display: flex; justify-content: space-between; gap: 10px; align-items: baseline;
}
.map-search-list li .ms-fig { font: 600 12px/1.2 var(--mono); font-variant-numeric: tabular-nums; color: var(--accent-ink); white-space: nowrap; }
.map-search-list li .ms-sys { color: var(--ink-3); font-weight: 400; font-size: 11.5px; }
.map-search-list li[aria-selected="true"], .map-search-list li:hover { background: var(--accent-wash); }
.map-search-list .ms-none { color: var(--ink-3); cursor: default; }

/* ---------------------------------------------------------------- full-bleed stage (desktop) */
@media (min-width: 768px) {
  .map-stage {
    position: relative;
    width: 100vw; margin-left: calc(50% - 50vw);
    background: var(--surface);
    border-block: 1px solid var(--rule-hairline);
    min-height: 560px;
  }
  .map-stage .map-toolbar {
    position: absolute; top: 10px; left: 18px; right: 64px; z-index: 30;
    border: 0; padding: 0; pointer-events: none;
  }
  .map-stage .map-toolbar > * { pointer-events: auto; }
  .map-stage .map-crumbs {
    background: color-mix(in srgb, var(--paper-bright) 88%, transparent);
    backdrop-filter: blur(5px); border: 1px solid var(--rule-hairline);
    border-radius: var(--r-ctl); padding: 3px 8px;
  }
  .map-stage .map-search { margin-right: 6px; }
  .map-stage .map-figure { position: absolute; inset: 0; border: 0; overflow: hidden; }
  .map-stage .map-figure svg { width: 100%; height: 100%; touch-action: none; }
  .map-stage .map-canvas-note {
    position: absolute; left: 18px; bottom: 8px; border: 0; padding: 0;
    background: color-mix(in srgb, var(--surface) 78%, transparent); border-radius: var(--r-chip);
  }
  /* the rail rides OVER the canvas as a glass paper panel, collapsible */
  .map-stage .map-rail {
    position: absolute; top: 58px; right: 14px; z-index: 25;
    width: 360px; max-height: calc(100% - 78px); overflow: auto;
    background: var(--paper-bright);
    background: color-mix(in srgb, var(--paper-bright) 92%, transparent);
    backdrop-filter: blur(7px);
    border: 1px solid var(--rule-hairline);
    box-shadow: 0 14px 34px rgba(0, 0, 0, .13);
  }
  .map-stage.rail-closed .map-rail { display: none; }
  .rail-toggle {
    position: absolute; top: 12px; right: 14px; z-index: 31;
    width: 34px; height: 34px; display: grid; place-items: center;
    background: var(--paper-bright); border: 1px solid var(--rule);
    border-radius: var(--r-ctl); cursor: pointer; color: var(--ink-2);
  }
  .rail-toggle:hover { border-color: var(--accent-control); color: var(--accent-ink); }
  .rail-toggle svg { transition: none; }
  .map-stage.rail-closed .rail-toggle svg { transform: scaleX(-1); }
}
@media (max-width: 767px) {
  .rail-toggle { display: none; }
}

/* ---------------------------------------------------------------- canvas */
.map-figure {
  background: var(--surface); border: 1px solid var(--rule-hairline);
  border-radius: var(--r-card); position: relative; overflow: hidden;
}
.map-figure svg { display: block; width: 100%; height: auto; }
.map-figure:focus-within { outline: 2px solid var(--accent-control); outline-offset: -2px; }
.map-canvas-note {
  margin: 0; padding: 8px 14px 12px; font: 400 12px/1.5 var(--text); color: var(--ink-3);
  border-top: 1px solid var(--rule-soft);
}

/* node groups. Position rides on the group's transform; the inner .mn-b
   wrapper carries the idle breathing so the two transforms never fight.
   Each node's --sys custom property is a var() reference to its system's
   token in the family sheet, set by map.js from the bundle's token NAMES. */
.mn { cursor: pointer; --sys: var(--accent); }
.mn.is-neutral { --sys: var(--ink-3); }   /* equity and access: neutral ink, no verdict colouring */
.mn-b { transform-box: fill-box; transform-origin: center; }
.mn circle.mn-hit { fill: transparent; stroke: none; pointer-events: all; }
.mn circle.mn-dot { fill: var(--paper-bright); stroke: var(--sys); stroke-width: 1.6; }
/* The estate core wears the accent bright — the one solid-accent circle on the
   map — so the way home is unmistakable (11 Aug 2026, per direction). */
.mn[data-kind="root"] circle.mn-dot { fill: var(--accent); stroke: var(--accent); }
.mn[data-kind="system"] circle.mn-dot { fill: var(--sys); stroke: var(--sys); }
.mn[data-kind="theme"] circle.mn-dot, .mn[data-kind="cluster"] circle.mn-dot {
  fill: var(--sys); fill-opacity: .16; stroke: var(--sys); }
.mn[data-kind="leaf"] circle.mn-dot { fill: var(--sys); fill-opacity: .1; stroke: var(--sys); stroke-width: 1.4; }
.mn[data-kind="uni"] circle.mn-dot, .mn[data-kind="market"] circle.mn-dot { fill: var(--sys); fill-opacity: .34; stroke: var(--sys); stroke-width: 1.2; }
.mn[data-kind="family"] circle.mn-dot { fill: var(--sys); fill-opacity: .2; stroke: var(--sys); stroke-width: 1.3; }
.mn[data-kind="market"] text .mn-name { font-size: 10.5px; font-weight: 620; }
.mn[data-kind="market"] text .mn-fig { font-size: 10px; }
.mn.is-focus circle.mn-dot { stroke-width: 2.4; }
.mn circle.mn-ring { fill: none; stroke: var(--sys); stroke-width: 1.4; opacity: 0; }
.mn.is-focus circle.mn-ring { opacity: .6; }
.mn.is-active circle.mn-ring { opacity: 1; stroke-dasharray: 3 3; }
.mn:focus { outline: none; }
.mn:focus-visible circle.mn-ring { opacity: 1; stroke-dasharray: 3 3; }
.mn circle.mn-pulse { fill: none; stroke-width: 1.6; opacity: 0; }
.mn circle.mn-pulse.pulse-good { stroke: var(--success); }
.mn circle.mn-pulse.pulse-bad { stroke: var(--danger); }

.mn text { font-family: var(--display); fill: var(--ink); paint-order: stroke; stroke: var(--surface); stroke-width: 3px; stroke-linejoin: round; }
.mn text .mn-name { font-size: 12.5px; font-weight: 650; letter-spacing: .005em; }
.mn[data-kind="leaf"] text .mn-name { font-size: 11.5px; font-weight: 600; }
.mn[data-kind="uni"] text .mn-name { font-size: 10.5px; font-weight: 620; }
.mn text .mn-fig { font-size: 11px; font-weight: 560; fill: var(--accent-ink); font-variant-numeric: tabular-nums; }
.mn[data-kind="uni"] text .mn-fig { font-size: 10px; }
.mn[data-kind="root"] text .mn-name, .mn[data-kind="system"] text .mn-name { font-size: 13.5px; }
.mn line.mn-leader { stroke: var(--rule); stroke-width: 1; opacity: .55; }
.mn.is-ghost { opacity: .13; pointer-events: none; }
.mn.is-ghost text { display: none; }
.mn.is-ghost circle.mn-pulse { display: none; }
.medge.is-ghost, .mxedge.is-ghost { opacity: .05; animation: none; }

/* Connection weight (11 Aug 2026, per direction): every line is a hairline; the major
   ones stay just as fine and carry the emphasis in COLOUR, never in width. */
.medge { fill: none; stroke: var(--rule); stroke-width: .55; }
.medge.is-dim { stroke: var(--rule-soft); }
.medge.is-branch { stroke: var(--accent); stroke-width: .8; opacity: .95; }
.medge.is-uni { stroke-width: .4; opacity: .4; }
.mxedge { fill: none; stroke: var(--accent); stroke-width: .9; stroke-dasharray: 6 5; opacity: .9; }
.mxedge[data-kind="pipeline"] { stroke: var(--accent-deep); }

/* Motion, all of it behind the reduced-motion gate. Three tiers: a gentle
   idle breathe on every node; slow, faint travelling dashes on every visible
   edge; and the focused node's cross edges as the loud tier. Direction
   pulses ripple a success or danger ring on measure leaves whose latest move
   is known; the rail carries the same fact as text, so nothing is
   motion-only. Entry geometry is instant; only opacity staggers in. */
@media (prefers-reduced-motion: no-preference) {
  .mn { transition: opacity var(--dur-3) var(--ease-out); }
  .medge, .mxedge { transition: opacity var(--dur-3) var(--ease-out); }
  /* idle drift comes from the spring field simulation (map.js), which never
     runs under this gate; CSS carries the dash travel and the pulses */
  .medge { stroke-dasharray: 4 7; animation: cbmap-travel 5.2s linear infinite; }
  .medge.is-uni { animation-duration: 7s; }
  .mxedge { animation: cbmap-travel 3.6s linear infinite; }
  .mxedge.is-focus { animation: cbmap-travel 1.3s linear infinite; stroke-width: 1.1; stroke: var(--accent-deep); opacity: 1; }
  @keyframes cbmap-travel { from { stroke-dashoffset: 22; } to { stroke-dashoffset: 0; } }
  .mn circle.mn-pulse { animation: cbmap-pulse 2.7s var(--ease-out) infinite; animation-delay: calc(var(--mn-i, 0) * -0.6s); transform-box: fill-box; transform-origin: center; }
  @keyframes cbmap-pulse {
    0% { opacity: .75; transform: scale(1); }
    58% { opacity: 0; transform: scale(1.85); }
    100% { opacity: 0; transform: scale(1.85); }
  }
  .map-entry .mn { animation: cbmap-in var(--dur-4) var(--ease-out) both; animation-delay: calc(var(--mn-i, 0) * 14ms); }
  @keyframes cbmap-in { from { opacity: 0; } to { opacity: 1; } }
}

/* ---------------------------------------------------------------- rail */
.map-rail {
  position: sticky; top: 12px;
  background: var(--surface); border: 1px solid var(--rule-hairline);
  border-radius: var(--r-card); padding: var(--pad-card);
  max-height: calc(100vh - 24px); overflow: auto;
}
.map-rail .rail-kind { font: 650 10.5px/1 var(--display); letter-spacing: .1em; text-transform: uppercase; color: var(--ink-3); margin: 0 0 6px; }
.map-rail h2 { font: 650 19px/1.25 var(--display); color: var(--ink); margin: 0 0 8px; letter-spacing: -.01em; }
.map-rail .rail-figure { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; margin: 0 0 4px; }
.map-rail .rail-figure b { font: 700 27px/1.1 var(--display); color: var(--accent-ink); letter-spacing: -.015em; font-variant-numeric: tabular-nums; }
.map-rail .rail-figure .rail-year { font: 600 12px/1 var(--mono); color: var(--ink-3); background: var(--paper-2); border-radius: var(--r-chip); padding: 4px 7px; }
.map-rail .rail-move { font: 600 12px/1.4 var(--display); margin: 0 0 6px; }
.map-rail .rail-move.is-good { color: var(--success); }
.map-rail .rail-move.is-bad { color: var(--danger); }
.map-rail .rail-unit { font: 400 12.5px/1.45 var(--text); color: var(--ink-2); margin: 0 0 10px; }
.map-rail .rail-basis { font: 400 13px/1.55 var(--serif); color: var(--ink-2); margin: 0 0 12px; }
.map-rail .rail-sec { font: 650 12px/1.3 var(--display); color: var(--ink); margin: 14px 0 6px; padding-top: 10px; border-top: 1px solid var(--rule-soft); }
.map-rail ul.rail-edges, .map-rail ul.rail-list { list-style: none; margin: 0; padding: 0; }
.map-rail ul.rail-edges li { padding: 7px 0; border-bottom: 1px dashed var(--rule-soft); }
.map-rail ul.rail-edges li:last-child { border-bottom: 0; }
.map-rail .re-label { font: 600 12.5px/1.35 var(--display); color: var(--ink); display: block; }
.map-rail .re-label button { font: inherit; color: var(--accent-ink); background: none; border: 0; padding: 0; cursor: pointer; text-decoration: underline; text-underline-offset: 2px; }
.map-rail .re-vals { font: 500 12px/1.5 var(--mono); font-variant-numeric: tabular-nums; color: var(--ink-2); display: block; margin-top: 2px; }
.map-rail .re-basis { font: 400 11.5px/1.5 var(--text); color: var(--ink-3); display: block; margin-top: 2px; }
.map-rail ul.rail-list li { font: 500 12.5px/1.7 var(--display); color: var(--ink-2); }
.map-rail ul.rail-stats { list-style: none; margin: 0; padding: 0; }
.map-rail ul.rail-stats li {
  display: flex; align-items: baseline; gap: 8px; padding: 6px 0;
  border-bottom: 1px dashed var(--rule-soft);
}
.map-rail ul.rail-stats li:last-child { border-bottom: 0; }
.map-rail ul.rail-stats .rst-l { flex: 1 1 auto; font: 500 12.5px/1.4 var(--display); color: var(--ink-2); }
.map-rail ul.rail-stats b { font: 650 13.5px/1.2 var(--display); color: var(--accent-ink); font-variant-numeric: tabular-nums; white-space: nowrap; }
.map-rail ul.rail-stats i { font: 500 11px/1 var(--mono); font-style: normal; color: var(--ink-3); }
.map-rail ul.rail-unilist {
  list-style: none; margin: 0; padding: 0; max-height: 300px; overflow: auto;
  border: 1px solid var(--rule-soft); border-radius: var(--r-ctl);
}
.map-rail ul.rail-unilist li { margin: 0; }
.map-rail ul.rail-unilist button {
  display: flex; justify-content: space-between; align-items: baseline; gap: 10px;
  width: 100%; text-align: left; cursor: pointer; background: none; border: 0;
  border-bottom: 1px solid var(--rule-soft); padding: 7px 10px;
  font: 500 12.5px/1.35 var(--display); color: var(--ink);
}
.map-rail ul.rail-unilist li:last-child button { border-bottom: 0; }
.map-rail ul.rail-unilist button:hover { background: var(--accent-wash); }
.map-rail ul.rail-unilist b { font: 600 12px/1.2 var(--mono); font-variant-numeric: tabular-nums; color: var(--accent-ink); white-space: nowrap; }
.map-rail .rail-against { font: 600 12.5px/1.5 var(--display); color: var(--ink); margin: 0 0 6px; }
.map-rail .rail-note { font: 400 11.5px/1.5 var(--text); color: var(--ink-3); margin: 0 0 4px; }
.map-rail ul.rail-deep { max-height: 340px; }
.map-rail .rail-attr { font: 400 10.5px/1.5 var(--text); color: var(--ink-3); margin: 12px 0 0; padding-top: 8px; border-top: 1px solid var(--rule-soft); }
.map-rail .rail-open {
  display: inline-block; margin-top: 12px; font: 650 13px/1 var(--display);
  color: var(--paper-on-ink); background: var(--accent-deep);
  padding: 11px 15px; border-radius: var(--r-ctl); text-decoration: none;
}
.map-rail .rail-open:hover { background: var(--accent); }
.map-rail .rail-children { margin-top: 4px; }
.map-rail .rail-children button {
  font: 600 12px/1.2 var(--display); color: var(--accent-ink);
  background: var(--accent-wash); border: 0; border-radius: var(--r-chip);
  padding: 6px 9px; margin: 0 6px 6px 0; cursor: pointer;
}
.map-rail .rail-children button:hover { background: var(--accent-soft); }
.map-rail .rail-elided { font: 400 11.5px/1.5 var(--text); color: var(--ink-3); margin: 8px 0 0; }

/* start-here scene (root focus) */
.rail-start { list-style: none; margin: 0; padding: 0; }
.rail-start li { margin: 0 0 8px; }
.rail-start button {
  display: block; width: 100%; text-align: left; cursor: pointer;
  background: var(--paper-tint); border: 1px solid var(--rule-soft);
  border-radius: var(--r-ctl); padding: 11px 12px;
}
.rail-start button:hover { border-color: var(--accent-control); background: var(--accent-wash); }
.rail-start .rs-label { font: 650 13.5px/1.35 var(--display); color: var(--ink); display: block; }
.rail-start .rs-note { font: 400 12px/1.5 var(--text); color: var(--ink-3); display: block; margin-top: 3px; }

/* ---------------------------------------------------------------- tree list (mobile) */
.map-tree { display: none; }
.map-tree ul { list-style: none; margin: 0; padding: 0; }
.map-tree ul ul { padding-left: 16px; border-left: 2px solid var(--rule-soft); margin-left: 9px; }
.map-tree li { margin: 0; }
.map-tree .tn {
  display: flex; align-items: center; gap: 10px; width: 100%;
  background: var(--surface); border: 1px solid var(--rule-hairline);
  border-radius: var(--r-ctl); padding: 12px; margin: 6px 0; cursor: pointer;
  text-align: left; min-height: 48px;
}
.map-tree .tn:hover { border-color: var(--accent-control); }
.map-tree .tn.is-focus { border-color: var(--accent-deep); box-shadow: inset 3px 0 0 var(--accent-deep); }
.map-tree .tn .tn-caret { flex: 0 0 auto; width: 18px; color: var(--ink-3); font: 600 12px/1 var(--display); }
.map-tree .tn .tn-body { flex: 1 1 auto; min-width: 0; }
.map-tree .tn .tn-name { font: 640 13.5px/1.3 var(--display); color: var(--ink); display: block; }
.map-tree .tn .tn-fig { font: 560 12px/1.3 var(--mono); font-variant-numeric: tabular-nums; color: var(--accent-ink); display: block; margin-top: 1px; }
.map-tree .tn:focus-visible { outline: 2px solid var(--accent-control); outline-offset: 1px; }
.map-tree .tree-detail { margin: 2px 0 10px; }
.map-tree .tree-detail .map-rail { position: static; max-height: none; }

/* ---------------------------------------------------------------- cross-links band + footer */
.map-links-band { border-top: 1px solid var(--rule-soft); margin-top: 26px; padding: 18px 0 4px; }
.map-links-band h2 { font: 650 15px/1.35 var(--display); margin: 0 0 10px; color: var(--ink); }
.map-links-band ul { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: 10px; }
.map-links-band a.hub-card {
  display: block; background: var(--surface); border: 1px solid var(--rule-hairline);
  border-radius: var(--r-card); padding: 13px 14px; text-decoration: none;
}
.map-links-band a.hub-card:hover { border-color: var(--accent-control); }
.map-links-band .hc-name { font: 650 13.5px/1.3 var(--display); color: var(--ink); display: block; }
.map-links-band .hc-note { font: 400 12px/1.5 var(--text); color: var(--ink-3); display: block; margin-top: 2px; }
.map-links-band .hc-method { font: 600 12px/1.3 var(--display); color: var(--accent-ink); display: inline-block; margin-top: 6px; }

/* ---------------------------------------------------------------- responsive */
@media (max-width: 767px) {
  .map-stage { min-height: 0; }
  .map-figure, .map-rail { display: none; }

  /* The living map is the phone's front door (per direction, 11 Aug 2026): a fixed
     full-viewport stage below the site header, sized from the visual viewport
     so collapsing browser chrome never breaks it; the drill waits behind the
     "See it as a list" control. */
  .map-stage.m-open { position: fixed; left: 0; right: 0; top: var(--mhead, 56px); bottom: 0;
    z-index: 70; background: var(--surface); border-top: 1px solid var(--rule-hairline); }
  .map-stage.m-open .map-figure { display: block; position: absolute; inset: 0; border: 0; overflow: hidden; }
  .map-stage.m-open .map-figure svg { width: 100%; height: 100%; touch-action: none; }
  .map-stage.m-open .map-canvas-note { display: none; }
  .map-stage.m-open .map-toolbar { position: absolute; top: 8px; left: 12px; right: 12px; z-index: 73;
    border: 0; padding: 0; pointer-events: none; }
  .map-stage.m-open .map-toolbar > * { pointer-events: auto; }
  .map-stage.m-open .map-crumbs { display: none; }
  .map-stage.m-open .map-search { margin-left: 120px; }
  .m-back { position: absolute; top: 8px; left: 12px; z-index: 74; min-height: 40px;
    font: 650 12.5px/1 var(--display); color: var(--accent-ink); background: var(--paper-bright);
    border: 1px solid var(--rule); border-radius: var(--r-ctl); padding: 0 12px; cursor: pointer; }
  .map-sheet { position: absolute; left: 0; right: 0; bottom: 0; z-index: 75; max-height: 46%;
    overflow: auto; background: var(--paper-bright); border-top: 3px solid var(--accent-deep);
    box-shadow: 0 -12px 30px rgba(0, 0, 0, .18); padding: 14px 16px 18px; }
  .map-sheet[hidden] { display: none; }
  .map-sheet .map-rail { display: block; position: static; border: 0; padding: 0;
    background: transparent; max-height: none; box-shadow: none; overflow: visible; }
  .map-sheet .rail-open { display: inline-block; margin-top: 12px; min-height: 44px; line-height: 44px;
    padding: 0 16px; background: var(--accent-deep); color: var(--paper-bright);
    font: 640 13px var(--display); text-decoration: none; }
  .map-sheet-close { position: sticky; top: 0; float: right; z-index: 76; min-height: 34px;
    font: 650 12px/1 var(--display); color: var(--ink-2); background: var(--paper-2);
    border: 1px solid var(--rule-soft); border-radius: var(--r-ctl); padding: 0 10px; cursor: pointer; }
  body.m-map-lock { overflow: hidden; }
  body.m-map-lock .map-tree, body.m-map-lock .map-links-band { display: none; }
  .drill-map-toggle { display: flex; align-items: center; justify-content: center; width: 100%;
    min-height: 48px; margin: 0 0 10px; font: 650 13.5px/1 var(--display);
    color: var(--paper-bright); background: var(--accent-deep); border: 0;
    border-radius: var(--r-ctl); cursor: pointer; }
  .map-tree { display: block; margin-top: 10px; }
  .map-search { margin-left: 0; width: 100%; }
  .map-search input { width: 100%; }

  /* The drill (11 Aug 2026): one focused card, then a flat list of what is inside it. The
     focused card reuses the rail's own markup and styles, so the rail wrapper inside it must
     escape the blanket mobile hiding rule above. */
  .drill-head { display: block; background: var(--paper-bright); border: 1px solid var(--rule-soft);
    border-left: 3px solid var(--accent-deep); padding: 16px 16px 14px; box-shadow: var(--shadow-card, none); }
  .drill-head .map-rail { display: block; position: static; width: auto; max-height: none;
    border: 0; padding: 0; background: transparent; box-shadow: none; overflow: visible; }
  .drill-head .rail-open { display: inline-block; margin-top: 12px; min-height: 44px; line-height: 44px;
    padding: 0 16px; background: var(--accent-deep); color: var(--paper-bright); font: 640 13px var(--display);
    text-decoration: none; }
  .drill-lbl { margin: 18px 2px 6px; font: 600 11px var(--mono); letter-spacing: .14em;
    text-transform: uppercase; color: var(--ink-3); }
  .drill-list { list-style: none; margin: 0; padding: 0; border-top: 1px solid var(--rule-soft); }
  .drill-list li { margin: 0; }
  .drill-row { display: flex; align-items: center; gap: 10px; width: 100%; min-height: 52px;
    padding: 8px 4px 8px 10px; background: transparent; border: 0; border-bottom: 1px solid var(--rule-soft);
    text-align: left; cursor: pointer; }
  .drill-row:active { background: var(--paper-2, rgba(3,22,2,.04)); }
  .drill-row .tn-body { flex: 1 1 auto; min-width: 0; display: flex; align-items: baseline;
    justify-content: space-between; gap: 12px; }
  .drill-row .tn-name { font: 640 14px/1.3 var(--display); color: var(--ink); }
  .drill-row .tn-fig { font: 560 12px/1.3 var(--mono); font-variant-numeric: tabular-nums;
    color: var(--accent-ink); white-space: nowrap; }
  .drill-row .tn-go { flex: 0 0 auto; font: 600 18px/1 var(--display); color: var(--ink-3); padding-right: 2px; }
}
@media (min-width: 768px) {
  .map-tree { display: none !important; }
}

/* ---------------------------------------------------------------- embed mode
   The landing page frames the live field (?embed=1). Only the canvas shows;
   the frame is decorative, so nothing here takes the pointer (the host also
   sets pointer-events: none on the iframe: belt and braces on both sides). */
html.is-embed body { overflow: hidden; }
html.is-embed .site-head, html.is-embed .drawer, html.is-embed .page-hero,
html.is-embed .map-toolbar, html.is-embed .rail-toggle, html.is-embed .map-rail,
html.is-embed .map-canvas-note, html.is-embed .map-tree,
html.is-embed .map-links-band, html.is-embed footer.site { display: none !important; }
html.is-embed .map-page-main { max-width: none; margin: 0; padding: 0; }
html.is-embed .map-stage { position: fixed; inset: 0; width: 100vw; margin: 0;
  border: 0; background: var(--surface); pointer-events: none; min-height: 0; }
html.is-embed .map-stage .map-figure { display: block; position: absolute; inset: 0;
  border: 0; overflow: hidden; pointer-events: none; }
html.is-embed .map-stage .map-figure svg { width: 100%; height: 100%; }

/* Depth-progressive simplification (11 Aug 2026): the field starts whole and simplifies as the
   focus moves into the data. Mid keeps the constellation readable and clickable; ghost keeps
   drifting (the field stays alive) but drops labels, pulses and pointer events. Opacity
   transitions carry the change; reduced-motion snaps. */
.mn, .medge, .mxedge { transition: opacity .35s ease; }
@media (prefers-reduced-motion: reduce) { .mn, .medge, .mxedge { transition: none; } }
.mn.t-mid { opacity: .38; }
.mn.t-mid text { opacity: .75; }
.mn.t-mid circle.mn-pulse { display: none; }
.mn.t-ghost { opacity: .14; pointer-events: none; }
.mn.t-ghost text { display: none; }
.mn.t-ghost circle.mn-pulse { display: none; }
.medge.t-mid, .mxedge.t-mid { opacity: .3; }
.medge.t-ghost, .mxedge.t-ghost { opacity: .06; animation: none; }

/* The four dashboard cards under the map: one grid, equal boxes (per direction, 11 Aug 2026). */
.map-links-band ul { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px; list-style: none; margin: 16px 0 0; padding: 0; }
@media (min-width: 1020px) { .map-links-band ul { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
@media (max-width: 560px) { .map-links-band ul { grid-template-columns: minmax(0, 1fr); } }
.map-links-band li { margin: 0; display: flex; }
.hub-card { display: flex; flex-direction: column; gap: 6px; height: 100%; box-sizing: border-box; }
.hub-card .hc-note { flex: 1 1 auto; }

/* The living transition (11 Aug 2026, per direction): new dots grow out of their
   parent as the field re-arranges; departing dots fade where they stood. */
.mn-born .mn-b { animation: mnBorn .5s cubic-bezier(.22, .8, .36, 1) .18s both; }
@keyframes mnBorn { from { opacity: 0; transform: scale(.25); } to { opacity: 1; transform: scale(1); } }
.mn-exit { pointer-events: none; animation: mnExit .4s ease both; }
@keyframes mnExit { to { opacity: 0; } }
@media (prefers-reduced-motion: reduce) {
  .mn-born .mn-b { animation: none; }
  .mn-exit { display: none; }
}

/* Group pods: pod labels on the canvas, and the rail's arrange-by control. */
.mgrp { font: 700 11px/1 var(--display); fill: var(--ink-3); letter-spacing: .07em;
        text-transform: uppercase; pointer-events: none; transition: opacity .35s ease .1s; }
.in-transit .mgrp { opacity: 0; transition: none; }
@media (prefers-reduced-motion: reduce) { .mgrp { transition: none; } }
.rail-arrange { display: flex; gap: 6px; flex-wrap: wrap; margin: 4px 0 10px; }
.rail-arrange button { font: 600 12px/1.2 var(--display); color: var(--accent-ink);
  background: var(--paper-bright); border: 1px solid var(--rule); border-radius: var(--r-chip);
  padding: 6px 10px; cursor: pointer; }
.rail-arrange button:hover { border-color: var(--accent-control); }
.rail-arrange button[aria-pressed="true"] { background: var(--accent-wash); border-color: var(--accent-control); color: var(--ink); }

/* Zoom controls. Desktop sits above the canvas note, clear of the rail;
   the phone keeps them thumb-side, clear of the list-view control. */
#mapSvg { touch-action: none; }
.map-zoomctl { position: absolute; left: 14px; bottom: 44px; z-index: 26; display: flex; flex-direction: column; gap: 6px; }
.map-zoomctl button { width: 34px; height: 34px; display: grid; place-items: center;
  font: 600 17px/1 var(--display); color: var(--ink-2); background: var(--paper-bright);
  border: 1px solid var(--rule); border-radius: var(--r-ctl); cursor: pointer; }
.map-zoomctl button:hover { border-color: var(--accent-control); color: var(--accent-ink); }
.map-zoomctl button:disabled { opacity: .38; cursor: default; }
@media (max-width: 767px) { .map-zoomctl { left: auto; right: 12px; bottom: 64px; } }

/* Core beacons: the estate core and the four systems carry a second ring and a
   slow always-on pulse — the fixed reference points of a moving map. */
.mn-ring2 { fill: none; stroke: var(--sys); stroke-width: .8; opacity: .55; }
@media (prefers-reduced-motion: no-preference) {
  .mn-beacon { fill: none; stroke: var(--sys); stroke-width: 1.6;
    animation: cbmap-beacon 3.8s var(--ease-out) infinite;
    transform-box: fill-box; transform-origin: center; }
  .mn[data-kind="system"] .mn-beacon { animation-duration: 5.6s; animation-delay: calc(var(--mn-i, 0) * -1.3s); }
  @keyframes cbmap-beacon {
    0% { opacity: .55; transform: scale(1); }
    62% { opacity: 0; transform: scale(2.05); }
    100% { opacity: 0; transform: scale(2.05); }
  }
}
@media (prefers-reduced-motion: reduce) { .mn-beacon { display: none; } }

/* Line weight follows scarcity: crowds fade to grey texture, rare links read bold.
   stroke-opacity composes with the depth-tier element opacity, so the two never fight. */
.medge.e-many { stroke: var(--rule-soft); stroke-opacity: .55; }
.medge.e-few { stroke-opacity: .95; }
.mxedge.x-common:not(.is-focus) { stroke: var(--ink-4); stroke-width: .65; stroke-opacity: .5; }
.mxedge.x-unique:not(.is-focus) { stroke: var(--accent-deep); stroke-width: 1.15; stroke-opacity: 1; }

/* The approach to a circle: hover swells it gently, the press answers at once —
   feedback lands before the field starts to move. The scale lives on the CIRCLES,
   never the .mn-b group: the group's transform box includes the label, so scaling
   it slid labelled dots up to 19px out from under the cursor and killed the click
   (fixed 11 Aug 2026). The hit circle never transforms — the target stays put. */
@media (prefers-reduced-motion: no-preference) {
  .mn .mn-dot, .mn .mn-ring, .mn .mn-ring2 {
    transform-box: fill-box; transform-origin: center;
    transition: transform .16s var(--ease-out);
  }
  /* the hover lens: small dots magnify hard so they become legible objects,
     structural circles swell gently; the press always exceeds the hover */
  .mn:hover .mn-dot, .mn:hover .mn-ring { transform: scale(1.18); }
  .mn[data-kind="uni"]:hover .mn-dot, .mn[data-kind="uni"]:hover .mn-ring,
  .mn[data-kind="market"]:hover .mn-dot, .mn[data-kind="market"]:hover .mn-ring,
  .mn[data-kind="leaf"]:hover .mn-dot, .mn[data-kind="leaf"]:hover .mn-ring { transform: scale(1.45); }
  .mn.is-pressed .mn-dot, .mn.is-pressed .mn-ring { transform: scale(1.24); transition-duration: .08s; }
  .mn[data-kind="uni"].is-pressed .mn-dot, .mn[data-kind="uni"].is-pressed .mn-ring,
  .mn[data-kind="market"].is-pressed .mn-dot, .mn[data-kind="market"].is-pressed .mn-ring,
  .mn[data-kind="leaf"].is-pressed .mn-dot, .mn[data-kind="leaf"].is-pressed .mn-ring { transform: scale(1.55); transition-duration: .08s; }
}

/* The glass identity chip: what a circle is, before you commit the click.
   Anchored to the stage, tracked to the live dot each frame. */
.map-stage { position: relative; }
.map-hovercard {
  position: absolute; z-index: 42; pointer-events: none; max-width: 260px;
  background: color-mix(in srgb, var(--paper-bright) 78%, transparent);
  backdrop-filter: blur(9px); -webkit-backdrop-filter: blur(9px);
  border: 1px solid var(--rule-hairline); border-radius: var(--r-ctl);
  box-shadow: 0 10px 28px rgba(0, 0, 0, .16);
  padding: 8px 11px;
  opacity: 0; transform: translateY(4px);
  transition: opacity .14s ease, transform .14s ease;
}
.map-hovercard.on { opacity: 1; transform: translateY(0); }
.map-hovercard .hc-kind { display: block; font: 700 11px/1.3 var(--display); letter-spacing: .06em;
  text-transform: uppercase; color: var(--ink-3); }
.map-hovercard .hc-name { display: block; font: 600 13px/1.35 var(--display); color: var(--ink); margin-top: 1px; }
.map-hovercard .hc-fig { display: block; font: 600 12px/1.4 var(--mono); font-variant-numeric: tabular-nums;
  color: var(--accent-ink); margin-top: 2px; }
@media (prefers-reduced-motion: reduce) { .map-hovercard { transition: none; } }

/* Staged reveal (Heer & Robertson: move first, read after): while the field is in
   transit, labels and pod captions hold back and the cross-edge dashes pause; the
   type fades in as the dots land. The focused node keeps its label throughout. */
.mn text, .mn .mn-leader { transition: opacity .3s ease .06s; }
.in-transit .mn:not(.is-focus) text, .in-transit .mn:not(.is-focus) .mn-leader { opacity: 0; transition: none; }
.in-transit .mxedge { animation-play-state: paused; }
@media (prefers-reduced-motion: reduce) { .mn text, .mn .mn-leader { transition: none; } }

/* Mission-compact excerpt on a university's panel. */
.rail-compact { margin: 4px 0 8px; font: 400 13px/1.55 var(--text); color: var(--ink-2); }
.rail-targets { margin-top: 2px; }

/* Phone canvas type: everything steps to the 11px estate floor so labels stop
   dominating a 345px-wide field; the label diet in map.js does the rest. */
@media (max-width: 767px) {
  .mn text .mn-name { font-size: 11.5px; }
  .mn text .mn-fig { font-size: 11px; }
  .mn[data-kind="uni"] text .mn-name, .mn[data-kind="market"] text .mn-name,
  .mn[data-kind="leaf"] text .mn-name { font-size: 11px; }
  .mgrp { font-size: 11px; }
}

/* The phone's two-step tap: the ARMED circle. First tap arms — the circle swells,
   its colour crossfades to its system hue with a deep-accent ring, and the ring
   pulses the invitation to tap again; the chip carries the commit hint. Tapping
   anywhere else just moves the preview. */
.mn circle.mn-dot { transition: transform .16s var(--ease-out), fill .3s ease, fill-opacity .3s ease, stroke .3s ease, stroke-width .3s ease; }
.mn.is-armed .mn-dot { fill: var(--sys); fill-opacity: .28; stroke: var(--accent-deep); stroke-width: 2.2; }
.mn.is-armed .mn-dot, .mn.is-armed .mn-ring { transform: scale(1.18); }
.mn[data-kind="uni"].is-armed .mn-dot, .mn[data-kind="uni"].is-armed .mn-ring,
.mn[data-kind="market"].is-armed .mn-dot, .mn[data-kind="market"].is-armed .mn-ring,
.mn[data-kind="leaf"].is-armed .mn-dot, .mn[data-kind="leaf"].is-armed .mn-ring { transform: scale(1.5); }
@media (prefers-reduced-motion: no-preference) {
  .mn.is-armed .mn-ring {
    animation: cbmap-armed 1.5s var(--ease-out) infinite;
    transform-box: fill-box; transform-origin: center;
    stroke: var(--accent-deep);
  }
  @keyframes cbmap-armed {
    0% { opacity: .85; transform: scale(1.15); }
    60% { opacity: 0; transform: scale(2.05); }
    100% { opacity: 0; transform: scale(2.05); }
  }
}
@media (prefers-reduced-motion: reduce) { .mn circle.mn-dot { transition: none; } }
.map-hovercard .hc-hint { display: block; font: 600 11px/1.4 var(--display); color: var(--ink-3); margin-top: 4px; }

/* The heart's spokes: the focused circle's direct connections wear its system
   hue and a quicker travelling dash — the lines re-declare the centre on every
   click. The ancestor path home stays accent (is-branch). */
.medge.is-spoke { stroke: var(--sys, var(--accent-mid)); stroke-width: .75; stroke-opacity: .85; }
@media (prefers-reduced-motion: no-preference) {
  .medge.is-spoke { stroke-dasharray: 4 6; animation: cbmap-travel 2.2s linear infinite; }
  .medge.is-branch { animation-duration: 3.2s; }
}
