/* build: fork1-v204 442da2c48ca7 */
/* explorer-app.css — GENERATED by build.js from the deployed build.
 * Three global selectors scoped for the WordPress embed (P1, BUI-42).
 * Do not edit; edit the source prototype and rebuild. */
#gd-explorer-stage{--gd-build:"fork1-v204 442da2c48ca7"}
#gd-explorer-stage{
  --paper:#F5F3EF; --ink:#0E0E12; --red:#C13B35; --global:#88817A;
  --serif:'Fraunces',Georgia,serif; --sans:'Instrument Sans',system-ui,sans-serif;
}
#gd-explorer-stage,#gd-explorer-stage *{box-sizing:border-box;margin:0;padding:0}
.gd-explorer-page{overflow:hidden}
#gd-explorer-stage{height:100dvh;background:var(--paper);color:var(--ink);font-family:var(--sans)}
/* ============ v1.99 — INPUT MODE (BUI-148, Design Record §5z) ============
   Three modes, decided by what the reader points with and how much screen
   there is, never by what the device claims to be:
     phone   — compact: 760px wide or less, or a touch screen 500px tall or
               less (a landscape phone is as wide as a tablet but not as tall)
     tablet  — touch, not compact
     desktop — everything else (a touchscreen laptop reports a fine pointer)
   The media queries below are the ONLY place the thresholds live. The JS
   reads the answer from --gdmode on #top via gdMode(), so CSS and JS cannot
   disagree, and both follow rotation and resize live. The four earlier
   tests (two CSS widths, a load-time isMobile constant and scattered
   innerWidth<=760 checks) disagreed, which is how a landscape phone and an
   iPad in portrait ended up in a half-desktop layout with a dead Dive tab. */
#top{--gdmode:desktop}
@media (max-width:760px), (pointer:coarse) and (max-height:500px){#top{--gdmode:phone}}
@media (pointer:coarse) and (min-width:761px) and (min-height:501px){#top{--gdmode:tablet}}
#top{position:fixed;inset:0 0 auto 0;height:52px;display:flex;align-items:center;gap:14px;
  padding:0 14px;background:linear-gradient(var(--paper) 78%,rgba(242,238,228,0));z-index:30}
/* v0.88: the wordmark is gone. On the site the explorer sits inside the
   normal page furniture, and the navigation menu already says which page the
   reader is on, so a title inside the frame repeated it. Removing it lets the
   Map/Dive tabs and the relationship toggles sit hard left where the eye
   arrives, instead of starting a third of the way across the bar. */
#tabs{display:flex;border:1px solid rgba(14,14,18,.25);border-radius:999px;overflow:hidden}
#edgetogs{display:flex;border:1px solid rgba(14,14,18,.25);border-radius:999px;overflow:hidden;margin-left:10px;position:static;z-index:auto;gap:0}
/* v0.83: no labels — each swatch is centered under its own toggle button
   by JS, so position:fixed with no layout box needed beyond the svg itself */
#edgelegend{position:fixed;z-index:0;pointer-events:none}
#edgelegend svg{position:fixed;display:block}
#edgetogs button{border:0;border-right:1px solid rgba(14,14,18,.12);background:transparent;font:500 12px var(--sans);padding:6px 12px;color:var(--ink);cursor:pointer;border-radius:0}
#edgetogs button:last-child{border-right:0}
#edgetogs button.on{background:var(--ink);color:var(--paper)}
#tabs button{border:0;background:transparent;font:500 12.5px var(--sans);padding:7px 15px;color:var(--ink);cursor:pointer}
#tabs button.on{background:var(--ink);color:var(--paper)}
#searchwrap{position:relative;margin-left:auto;max-width:46vw}
#search{width:200px;max-width:100%;border:1px solid rgba(14,14,18,.25);background:rgba(255,255,255,.55);
  border-radius:999px;padding:7px 13px;font:400 13px var(--sans);color:var(--ink);outline:none}
#search:focus{border-color:var(--ink)}
/* v1.99 (BUI-24): iOS Safari zooms the whole page into any input under 16px
   when it takes focus. The prototype hid this with maximum-scale=1; the
   WordPress page rightly does not use it (it kills pinch-zoom on Android). */
@media (max-width:760px), (pointer:coarse){#search{font-size:16px}}
#hits{position:absolute;top:40px;right:0;left:0;background:var(--paper);border:1px solid rgba(14,14,18,.18);
  border-radius:10px;box-shadow:0 8px 22px rgba(14,14,18,.12);overflow:hidden;display:none;z-index:40}
#hits div{padding:9px 13px;font-size:13px;cursor:pointer;display:flex;align-items:center;gap:8px}
#hits div:hover{background:rgba(14,14,18,.06)}
#hits i{width:8px;height:8px;border-radius:50%;flex:none}
/* ============ v1.55 — METHODOLOGY OVERLAY (BUI-118) ============ */
#methodbtn{display:flex;align-items:center;justify-content:center;
  width:34px;height:34px;flex:none;border:1px solid rgba(14,14,18,.25);
  border-radius:999px;background:rgba(255,255,255,.55);cursor:pointer;padding:0;
  margin-right:-6px;order:0}
#methodbtn svg{width:22px;height:22px;fill:none;stroke:var(--ink);stroke-width:2;
  stroke-linecap:round;stroke-linejoin:round}
#methodbtn:hover{background:rgba(255,255,255,.85)}
#method-overlay{display:none;position:fixed;inset:0;z-index:100;
  background:rgba(14,14,18,.45);align-items:center;justify-content:center}
#method-overlay.open{display:flex}
#method-box{position:relative;width:min(680px,90vw);max-height:min(80vh,700px);
  background:var(--paper);border:1px solid rgba(14,14,18,.18);
  border-radius:14px;box-shadow:0 16px 48px rgba(14,14,18,.22);
  overflow:hidden;display:flex;flex-direction:column}
#method-scroll{overflow-y:auto;overscroll-behavior:contain;padding:36px 38px 32px;flex:1}
#method-scroll::-webkit-scrollbar{width:7px}
#method-scroll::-webkit-scrollbar-thumb{background:rgba(14,14,18,.18);border-radius:99px}
#method-close{position:absolute;top:10px;right:10px;width:30px;height:30px;
  display:flex;align-items:center;justify-content:center;
  border:1px solid rgba(14,14,18,.18);border-radius:999px;
  background:var(--paper);cursor:pointer;padding:0;z-index:1}
#method-close svg{width:15px;height:15px;stroke:var(--ink);stroke-width:2.2;
  stroke-linecap:round}
#method-close:hover{background:rgba(14,14,18,.06)}
#method-box h2{font:600 20px/1.3 var(--serif);margin:0 0 6px;color:var(--ink);padding-right:30px}
#method-box h3{font:600 15px/1.4 var(--sans);margin:20px 0 6px;color:var(--ink)}
#method-box p{font:400 14px/1.65 var(--sans);color:rgba(14,14,18,.82);margin:0 0 12px}
#method-box p:last-child{margin-bottom:0}
#method-box .method-sub{font:500 13px/1.5 var(--sans);color:rgba(14,14,18,.5);
  margin:0 0 18px;letter-spacing:.02em}
#method-box a{color:var(--ink);text-decoration:underline;text-underline-offset:2px}
#method-box a:hover{color:var(--red)}
/* v1.99: touch usability section, first in the overlay on phone and tablet */
#gdhelp{margin:0 0 26px;padding-bottom:22px;border-bottom:1px solid rgba(14,14,18,.12)}
#gdhelp p{margin:0 0 8px}
#gdhelp p:last-child{margin-bottom:0}
#fambtn{align-items:center;justify-content:center;padding:0;margin-right:2px}
#fambtn svg{width:16px;height:16px;fill:none;stroke:var(--ink);stroke-width:1.8;stroke-linejoin:round;display:block}
@media (max-width:760px), (pointer:coarse) and (max-height:500px){
  #method-box{width:94vw;max-height:85vh;border-radius:12px}
  #method-scroll{padding:28px 22px 24px}
  #method-box h2{font-size:18px}
  #method-box p{font-size:13.5px}
}
#stage{position:absolute;inset:0}
#map2d,#dive3d{position:absolute;inset:0;touch-action:none}
/* E9 (BUI-39, v1.80): first-open Dive loading state. Lives inside #dive3d so it
   shows and hides with the view; paper ground, ink text, red on failure. */
#diveload{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;
  background:var(--paper);color:var(--ink);font:400 14px var(--sans);text-align:center;padding:0 24px;z-index:5}
#diveload.fail{color:var(--red)}
#map2d svg{width:100%;height:100%;display:block;cursor:grab}
#map2d svg:active{cursor:grabbing}
.hidden{display:none!important}
.pillrow{position:fixed;z-index:25;display:flex;gap:6px}
.pillrow button{border:1px solid rgba(14,14,18,.25);background:rgba(242,238,228,.85);border-radius:999px;
  padding:6px 13px;font:500 12px var(--sans);cursor:pointer;color:var(--ink)}
.pillrow button.on{background:var(--ink);color:var(--paper);border-color:var(--ink)}
#divemodes{top:62px;left:14px}
/* ---------- family navigation strip (Map view) ---------- */
#famnav{position:fixed;left:0;right:0;bottom:0;z-index:24;display:flex;align-items:center;gap:4px;
  padding:8px 8px calc(8px + env(safe-area-inset-bottom));
  background:linear-gradient(rgba(242,238,228,0),var(--paper) 55%)}
#famnav button{border:1px solid rgba(14,14,18,.25);background:rgba(242,238,228,.9);border-radius:999px;
  font:600 15px var(--sans);width:32px;height:32px;flex:none;cursor:pointer;color:var(--ink);line-height:1}
#famchips{display:flex;gap:6px;overflow-x:auto;scrollbar-width:none;-webkit-overflow-scrolling:touch;padding:2px}
#famchips::-webkit-scrollbar{display:none}
#famchips button{width:auto;height:auto;padding:6px 13px;font:500 12px var(--sans);white-space:nowrap;
  display:inline-flex;align-items:center;gap:7px}
#famchips button i{width:8px;height:8px;border-radius:50%;flex:none}
#famchips button.on{background:var(--ink);color:var(--paper);border-color:var(--ink)}
/* v0.49: the hint sits BELOW the nav cluster, across the full width. It used
   to be pinned at bottom:56 with a 52vw cap, so the panel covered it and the
   line wrapped; the panel now starts above it and the cap is gone.
   v2.04 (BUI-149): the hint had run UNDER the family strip since the strip was
   moved beside the frame — cut off after "Drag to pan" at every desktop width,
   because the strip starts at the frame's right edge whatever the window size.
   The strip now rises instead: layoutMapNav() pads it so its buttons sit level
   with the frame's bottom edge, its paper runs on to the screen edge, and the
   hint reads on that paper. z-index 25 puts the hint above the strip (24) and
   below the frames (26); it takes no pointer events, so it blocks nothing. The
   hint stays in the same place in the Map and the Dive. */
#hint{position:fixed;left:14px;right:250px;bottom:14px;font-size:11px;
  color:rgba(14,14,18,.45);z-index:25;pointer-events:none}
/* 250px on the right keeps the line clear of #legend (224px, bottom:14) */
@media(max-width:620px){#hint{right:14px;bottom:auto;top:96px}}
/* ---------- Flight navigation cluster: pan + rotate + zoom + universe, one frame ---------- */
#flightnav{position:fixed;left:14px;bottom:44px;z-index:26;display:flex;align-items:flex-end;gap:12px;
  background:rgba(242,238,228,.92);border:1px solid rgba(14,14,18,.16);border-radius:14px;
  box-shadow:0 6px 20px rgba(14,14,18,.12);padding:10px 12px;backdrop-filter:blur(2px)}
#navctrls{display:flex;flex-direction:column;align-items:center;gap:6px}
#dpad{display:flex;flex-direction:column;align-items:center;gap:5px}
#dpad .dpad-mid{display:flex;gap:5px;align-items:center}
/* v0.45: turn and roll stack directly under the pad, sharing its column width */
.ctlrow{display:flex;align-items:center;justify-content:center;gap:5px;margin-top:5px}
.ctlrow .rlabel{width:14px;text-align:center;font:600 9.5px var(--sans);
  letter-spacing:.06em;text-transform:uppercase;color:rgba(14,14,18,.42)}
/* v0.46: every nav glyph is now an SVG on one grid, one stroke weight and one
   size — the roll and home glyphs were text characters, which rendered far
   smaller than the drawn turn icons however the font-size was set. */
/* inline icons in the hint line, sized to the running text */
.hintico{width:1.05em;height:1.05em;fill:none;stroke:currentColor;stroke-width:1.9;
  stroke-linecap:round;stroke-linejoin:round;vertical-align:-0.2em;margin:0 1px}
.navbtn svg{width:23px;height:23px;fill:none;stroke:currentColor;stroke-width:1.85;
  stroke-linecap:round;stroke-linejoin:round;display:block}
.navbtn,#dpad button{width:38px;height:38px;border:1px solid rgba(14,14,18,.22);background:rgba(242,238,228,.9);
  border-radius:10px;font-size:13px;color:var(--ink);cursor:pointer;line-height:1;
  display:flex;align-items:center;justify-content:center;-webkit-user-select:none;user-select:none;touch-action:none}
.navbtn:hover,#dpad button:hover{background:var(--ink);color:var(--paper);border-color:var(--ink)}
.navbtn:active,#dpad button:active{background:var(--red);color:var(--paper);border-color:var(--red)}
#rotrow{display:flex;gap:6px;align-items:center}
#rotrow .navbtn{font-size:16px}
#rotrow .rlabel{font:600 10px var(--sans);color:rgba(14,14,18,.5)}
/* vertical zoom slider with A/Z key hints */
#zoomcol{display:flex;flex-direction:column;align-items:center;gap:5px;height:150px;justify-content:space-between}
#zoomcol .zlabel{font:600 10px var(--sans);color:rgba(14,14,18,.5)}
#zoomrange{-webkit-appearance:none;appearance:none;writing-mode:vertical-lr;direction:rtl;
  width:6px;height:110px;background:rgba(14,14,18,.14);border-radius:4px;cursor:pointer}
#zoomrange::-webkit-slider-thumb{-webkit-appearance:none;width:16px;height:16px;border-radius:50%;
  background:var(--ink);cursor:pointer;border:2px solid var(--paper)}
#zoomrange::-moz-range-thumb{width:16px;height:16px;border-radius:50%;background:var(--ink);cursor:pointer;border:2px solid var(--paper)}
/* ---------- minimap / universe key (inside the nav frame) ---------- */
/* v0.45: with the distribution picker gone the key fills the frame height and
   takes whatever width its 5:4 viewBox needs — #flightnav is align-items:
   flex-end, so the panel has to stretch before the svg can grow into it. */
#minimap{align-self:stretch;display:flex;flex-direction:column}
#minimapwrap{flex:1;min-height:0}
#minimaptitle{font:600 9.5px var(--sans);letter-spacing:.11em;text-transform:uppercase;
  color:rgba(14,14,18,.5);margin:0 2px 5px}
#minimapsvg{width:100%;height:100%;display:block;cursor:pointer}


@media(max-width:620px){#minimap{width:120px} #minimapsvg{width:100%;height:auto} #zoomcol{height:132px}}
/* ---------- Map navigation frame (mirrors #flightnav; pan + zoom, no rotate) ---------- */
#mapnav{position:fixed;left:14px;bottom:44px;z-index:26;display:flex;align-items:flex-end;gap:12px;
  background:rgba(242,238,228,.92);border:1px solid rgba(14,14,18,.16);border-radius:14px;
  box-shadow:0 6px 20px rgba(14,14,18,.12);padding:10px 12px;backdrop-filter:blur(2px)}
#mapnav.hidden{display:none}
#mapnavctrls{display:flex;flex-direction:column;align-items:center;gap:6px}
#mapdpad{display:flex;flex-direction:column;align-items:center;gap:5px}
#mapdpad .dpad-mid{display:flex;gap:5px;align-items:center}
#mapdpad button{width:38px;height:38px;border:1px solid rgba(14,14,18,.22);background:rgba(242,238,228,.9);
  border-radius:10px;font-size:13px;color:var(--ink);cursor:pointer;line-height:1;
  display:flex;align-items:center;justify-content:center;-webkit-user-select:none;user-select:none;touch-action:none}
#mapdpad button:hover{background:var(--ink);color:var(--paper);border-color:var(--ink)}
#mapdpad button:active{background:var(--red);color:var(--paper);border-color:var(--red)}
#mapzoomcol{display:flex;flex-direction:column;align-items:center;gap:5px;height:150px;justify-content:space-between}
#mapzoomcol .zlabel{font:600 10px var(--sans);color:rgba(14,14,18,.5)}
#mapzoomrange{-webkit-appearance:none;appearance:none;writing-mode:vertical-lr;direction:rtl;
  width:6px;height:110px;background:rgba(14,14,18,.14);border-radius:4px;cursor:pointer}
#mapzoomrange::-webkit-slider-thumb{-webkit-appearance:none;width:16px;height:16px;border-radius:50%;
  background:var(--ink);cursor:pointer;border:2px solid var(--paper)}
#mapzoomrange::-moz-range-thumb{width:16px;height:16px;border-radius:50%;background:var(--ink);cursor:pointer;border:2px solid var(--paper)}
@media(max-width:620px){#mapzoomcol{height:132px}}
/* ---------- Map minimap (now inside the Map nav frame, lower-left) ---------- */
/* v0.41: #mapnav is align-items:flex-end, which bottom-aligned this whole
   panel — title low, map strip on the floor of the frame. Stretching the panel
   to the frame height puts the caption at the top and lets the map sit in the
   middle of the space that's left. */
#mapmini{width:172px;align-self:stretch;display:flex;flex-direction:column}
#mapminiwrap{flex:1;display:flex;align-items:center;min-height:0}
#mapminititle{font:600 9.5px var(--sans);letter-spacing:.11em;text-transform:uppercase;
  color:rgba(14,14,18,.5);margin:0 2px 5px}
#mapminisvg{width:100%;height:auto;display:block;cursor:pointer}
@media(max-width:620px){#mapmini{width:120px}}
/* ============ v1.94 — STOWING THE NAV FRAME ============
   A genre with many children (Punk, fourteen of them) fans them out across
   the whole width, and the bottom-left corner of that fan sits behind this
   frame; the only way to see it was to drag the map out from under the
   controls. The frame can now be stowed: everything in it goes except the
   home button and an expand control, so it shrinks to a two-button stub in
   the corner. One state serves both frames, it persists until the reader
   expands it again, and M toggles it from the keyboard. The horizontal
   centring fix for the card is in mapViewCentre(); this stub is what handles
   the corner the card fix cannot reach.
   v1.95: the expand control moved from inside the stub to the stub's own
   top-right corner, matching where the stow control sits on the frame, and
   the glyphs briefly became diagonal arrows.
   v1.96: chevrons restored (left to stow, right to expand). The "pan right"
   reading was caused by the expand control sitting beside the home button
   in the v1.94 stub, not by the chevron itself; on the corner it is fine. */
.navtog{position:absolute;top:-9px;right:-9px;width:22px;height:22px;padding:0;box-shadow:0 2px 6px rgba(14,14,18,.14);
  border:1px solid rgba(14,14,18,.22);background:rgba(242,238,228,.9);border-radius:50%;
  color:var(--ink);cursor:pointer;display:flex;align-items:center;justify-content:center}
.navtog svg{width:14px;height:14px;fill:none;stroke:currentColor;stroke-width:2;
  stroke-linecap:round;stroke-linejoin:round;display:block}
.navtog:hover{background:var(--ink);color:var(--paper);border-color:var(--ink)}
.navstub{display:none;gap:6px;align-items:center}
#mapnav.stowed>*:not(.navstub),#flightnav.stowed>*:not(.navstub){display:none}
#mapnav.stowed .navstub,#flightnav.stowed .navstub{display:flex}

/* desktop defaults for controls the phone layout switches on (v1.99: bases
   rather than min-width:761 queries, so there is one threshold, not two) */
#cardgrip{display:none}
#searchbtn{display:none}
#fambtn{display:none}
#gdhelp{display:none}
/* ============ v1.20 — MOBILE INTERFACE ============
   Screen space is the scarce resource and there is no keyboard, so the controls
   that exist to substitute for one go. Pinch and drag already do pan and zoom
   natively and more precisely than a d-pad. What stays is what a gesture cannot
   give you: the minimap for orientation, the family strip for stepping between
   territories, and Back to the whole map — pinching out across 10,800px of map
   is a great many gestures, so the one-tap return is worth its space.

   Media queries rather than the isMobile constant: isMobile is evaluated once
   from innerWidth at load and never re-read, so a rotation leaves it stale.
   Anything that is layout belongs in CSS. */
@media (max-width:760px), (pointer:coarse) and (max-height:500px){
  /* the four pan arrows go; the home button in the middle of the d-pad stays */
  #mapdpad button[data-dx]{display:none}
  #mapdpad{gap:0}
  #mapzoomcol{display:none}
  /* v1.99 (BUI-24): the minimap goes on phones — at 120px nobody can aim at
     it. The family picker is the usable small map, one tap away on the grid
     button in the strip. What is left of the frame is the home button, so
     the frame itself goes and home floats on its own; stowing has nothing
     left to hide. */
  #mapmini,#mapnav .navtog,#mapnav .navstub,#mapnav.stowed .navstub{display:none}
  #mapnav.stowed>#mapnavctrls{display:flex}
  #mapnav{padding:0;gap:0;background:none;border:0;box-shadow:none;backdrop-filter:none}
  #maphomebtn{border-radius:999px;background:rgba(242,238,228,.96);box-shadow:0 3px 10px rgba(14,14,18,.16)}
  #fambtn{display:flex}
  /* the hint goes: its content lives first in the (i) overlay (Paul, 21 Sep 2026) */
  #hint{display:none}
  #gdhelp{display:block}
  .gdh-tablet{display:none}

  /* The card is short by default — head plus about four lines of description —
     because at 58% it covered the very genre it describes. The rest is reached
     by scrolling inside it, or by dragging the handle up to resize. */
  /* v1.99: the collapsed height is MEASURED when a card opens — header plus
     four description lines (setCardCollapsed). The 186px arithmetic did not
     survive the live page, whose header renders about 18px taller than the
     prototype's; on-device it showed two and a half lines (BUI-24). */
  #card{height:var(--cardh,var(--cardcollapsed,186px));max-height:88%;transition:height .18s ease}
  #card.dragging{transition:none}
  #cardgrip{display:block;flex:none;height:22px;cursor:grab;touch-action:none;
    position:relative;background:transparent}
  #cardgrip::before{content:'';position:absolute;left:50%;top:9px;width:36px;height:4px;
    margin-left:-18px;border-radius:2px;background:rgba(14,14,18,.22)}
  #cardgrip:active{cursor:grabbing}
  #cardhead{padding-top:4px}
  /* v1.19 leaves this footer empty on mobile — an empty flex row with 24px of
     padding and a border was costing space for nothing */
  #cactions:empty{display:none}
}

/* ============ v1.22 — MOBILE TOP BAR AND STRIP ============
   At 390px the search field, the view tabs and the three relationship toggles
   cannot all sit in one row: the field was overlapping Fusion and Influence,
   which are the controls a reader actually needs. Search collapses to its icon
   and expands over the bar when tapped; the Map/Dive tabs go, since mobile has
   only one view to be in (§1, now confirmed by trial rather than assumed). */
@media (max-width:760px), (pointer:coarse) and (max-height:500px){
  #tabs{display:none}
  #edgetogs{margin-left:0}
  #edgetogs button{padding:6px 10px;font-size:11.5px}
  #searchwrap{margin-left:auto;max-width:none}
  #searchbtn{display:flex;align-items:center;justify-content:center;
    width:34px;height:34px;flex:none;border:1px solid rgba(14,14,18,.25);
    border-radius:999px;background:rgba(255,255,255,.55);cursor:pointer;padding:0}
  #searchbtn svg{width:17px;height:17px;fill:none;stroke:var(--ink);stroke-width:2;
    stroke-linecap:round}
  #search{display:none}
  /* expanded: the field takes the bar, the toggles yield for the moment */
  #searchwrap.open{position:absolute;left:14px;right:14px;top:11px;max-width:none}
  #searchwrap.open #search{display:block;width:100%}
  #searchwrap.open #searchbtn{display:none}
  #top.searching #edgetogs{visibility:hidden}

  /* the authoring row is desktop-only — it was bleeding through the family
     strip, which is not overlaid on itself as it appeared, but overlapped by
     these. They leave the deployed build entirely (Delivery Plan F). */
  #wbbar{display:none}
}
#exitbtn{display:none}
@media (max-width:760px), (pointer:coarse) and (max-height:500px){
  #exitbtn{display:flex;align-items:center;justify-content:center;
    width:34px;height:34px;flex:none;margin-right:8px;padding:0;cursor:pointer;
    border:1px solid rgba(14,14,18,.25);border-radius:999px;background:rgba(255,255,255,.55)}
  #exitbtn svg{width:18px;height:18px;fill:none;stroke:var(--ink);stroke-width:2;
    stroke-linecap:round;stroke-linejoin:round}
  #top.searching #exitbtn{visibility:hidden}
}
/* a drag that runs out inside the explorer must not chain to the page: without
   this the map occasionally escapes mid-pan and the page scrolls instead.
   v1.99: every touch screen, not only phones */
@media (max-width:760px), (pointer:coarse){#stage,#map2d,#dive,#dive3d{overscroll-behavior:contain}}
/* ============ v1.99 — TABLET (BUI-148) ============
   Desktop layout (side card, full search field, minimap), touch everywhere
   else: no pan arrows or zoom slider (gestures do both better), no tabs
   (Map only until Tablet Dive, BUI-47), touch wording in the hint, and the
   usability section first in the (i) overlay. The page header stays, so no
   exit-to-top button. */
@media (pointer:coarse) and (min-width:761px) and (min-height:501px){
  #tabs{display:none}
  #edgetogs{margin-left:0}
  #mapdpad button[data-dx]{display:none}
  #mapdpad{gap:0}
  #mapzoomcol{display:none}
  #gdhelp{display:block}
  .gdh-phone{display:none}
  /* v2.00: the hint goes on tablets as well (Paul, 23 Sep 2026): on the iPad
     it ran under the family strip and was cut off mid-sentence, and the (i)
     overlay already carries the touch help, first. */
  #hint{display:none}
}
/* the tour is desktop-only: on touch screens the (i) overlay carries the help */
@media (max-width:760px), (pointer:coarse){#fampickfoot #fampickTour{display:none}}
/* ---------- Flight edge toggle position ---------- */
/* edge toggles unified into #edgetogs in the header bar */
/* ---- v0.63 layout-rules panel ---- */
/* v0.86 — family order editor */
.fotier{padding:6px 0;border-top:1px solid rgba(14,14,18,.08)}
.fotier h6{font:600 10px var(--sans);letter-spacing:.08em;text-transform:uppercase;
  color:rgba(14,14,18,.45);margin:0 0 4px}
.fochips{display:flex;flex-wrap:wrap;gap:4px}
.fochip{display:inline-flex;align-items:center;gap:3px;border:1px solid rgba(14,14,18,.22);
  border-radius:999px;padding:2px 4px 2px 8px;font:500 11px var(--sans);background:rgba(255,255,255,.5)}
.fochip i{font-style:normal}
.fochip button{border:0;background:transparent;cursor:pointer;font-size:11px;line-height:1;
  padding:2px 3px;color:rgba(14,14,18,.55);border-radius:50%}
.fochip button:hover{background:var(--ink);color:var(--paper)}
/* v0.86 — conflict audit highlight */
path.lk-conflict{stroke:#C13B35!important;stroke-width:2.6!important;stroke-opacity:1!important}
#editToggle.on{background:var(--ink);color:var(--paper);border-color:var(--ink)}
/* ---------- v0.18: the scene introduces itself ---------- */
#welcome,#mapwelcome{position:fixed;inset:0;z-index:40;display:flex;align-items:center;justify-content:center;
  background:rgba(14,14,18,.18);backdrop-filter:blur(2px)}
#welcome.hidden,#mapwelcome.hidden{display:none}
#welcomecard,#mapwelcomecard{background:var(--paper);border:1px solid rgba(14,14,18,.16);border-radius:16px;
  max-width:440px;margin:20px;padding:26px 28px;box-shadow:0 18px 50px rgba(14,14,18,.25)}
#welcomecard h2,#mapwelcomecard h2{font-family:"Fraunces",serif;font-weight:600;font-size:26px;margin:0 0 10px;color:var(--ink)}
#welcomecard p,#mapwelcomecard p{font:15px/1.55 var(--sans);color:rgba(14,14,18,.75);margin:0 0 18px}
#welcomecard .row,#mapwelcomecard .row{display:flex;gap:10px}
#welcomecard button,#mapwelcomecard button{flex:1;padding:11px 10px;border-radius:10px;font:600 14px var(--sans);cursor:pointer;
  border:1px solid rgba(14,14,18,.25);background:transparent;color:var(--ink)}
#welcomecard button.primary,#mapwelcomecard button.primary{background:var(--ink);color:var(--paper);border-color:var(--ink)}
#welcomecard button.primary:hover,#mapwelcomecard button.primary:hover{background:var(--red);border-color:var(--red)}
#tourcap,#maptourcap{position:fixed;left:50%;bottom:88px;transform:translateX(-50%);z-index:38;max-width:430px;
  width:calc(100vw - 40px);background:rgba(242,238,228,.97);border:1px solid rgba(14,14,18,.16);
  border-radius:14px;padding:14px 16px;box-shadow:0 10px 34px rgba(14,14,18,.2)}
#tourcap.hidden,#maptourcap.hidden{display:none}
#tourcap p,#maptourcap p{font:14.5px/1.55 var(--sans);margin:0 0 10px;color:var(--ink)}
#tourcap .row,#maptourcap .row{display:flex;gap:8px;justify-content:flex-end;align-items:center}
#tourcap button,#maptourcap button{padding:7px 14px;border-radius:9px;font:600 13px var(--sans);cursor:pointer;
  border:1px solid rgba(14,14,18,.25);background:transparent;color:var(--ink)}
#tourcap button.primary,#maptourcap button.primary{background:var(--ink);color:var(--paper);border-color:var(--ink)}
/* ---------- v1.56 (BUI-117): Map onboarding tour + family picker ---------- */
#maptourcap .step,#tourcap .step{font:600 10px var(--sans);letter-spacing:.11em;text-transform:uppercase;
  color:rgba(14,14,18,.5);margin-right:auto}
/* the ring that points at a UI element during a tour stop: fixed, sized to the
   target's screen rect by JS, never intercepts input */
#tourring{position:fixed;z-index:39;pointer-events:none;border:2px solid var(--red);border-radius:14px;
  box-shadow:0 0 0 4px rgba(193,59,53,.16),0 0 0 9999px rgba(14,14,18,.06);
  transition:left .35s ease,top .35s ease,width .35s ease,height .35s ease}
#tourring.hidden{display:none}
@media(prefers-reduced-motion:reduce){#tourring{transition:none}}
/* family picker: the tour's last screen and every return visit's first */
#fampick{position:fixed;inset:0;z-index:40;display:flex;align-items:center;justify-content:center;
  background:rgba(14,14,18,.18);backdrop-filter:blur(2px)}
#fampick.hidden{display:none}
#fampickcard{background:var(--paper);border:1px solid rgba(14,14,18,.16);border-radius:16px;
  width:min(760px,calc(100vw - 32px));max-height:calc(100vh - 32px);margin:16px;padding:22px 24px 18px;
  box-shadow:0 18px 50px rgba(14,14,18,.25);display:flex;flex-direction:column;overflow:auto}
#fampickcard h2{font-family:"Fraunces",serif;font-weight:600;font-size:24px;margin:0 0 6px;color:var(--ink)}
#fampickcard p{font:14px/1.5 var(--sans);color:rgba(14,14,18,.72);margin:0 0 14px}
#fampickmap{position:relative;width:100%;margin:0 auto 14px;border-radius:10px;
  background:rgba(14,14,18,.03);border:1px dashed rgba(14,14,18,.14)}
#fampickmap button{position:absolute;display:flex;align-items:center;justify-content:center;gap:6px;
  padding:0 10px;border-radius:9px;border:1px solid rgba(14,14,18,.14);cursor:pointer;
  font:600 12.5px var(--sans);color:var(--ink);white-space:nowrap;box-sizing:border-box;
  transition:transform .12s ease,box-shadow .12s ease}
#fampickmap button i{width:9px;height:9px;border-radius:3px;flex:none}
#fampickmap button:hover,#fampickmap button:focus-visible{transform:translateY(-1px);
  box-shadow:0 6px 16px rgba(14,14,18,.16);outline:none;border-color:var(--ink)}
#fampickfoot{display:flex;justify-content:space-between;align-items:center;gap:10px;flex-wrap:wrap}
#fampickfoot button{padding:7px 12px;border-radius:9px;font:600 13px var(--sans);cursor:pointer;
  border:1px solid rgba(14,14,18,.25);background:transparent;color:var(--ink)}
#fampickfoot button.link{border-color:transparent;text-decoration:underline;text-underline-offset:3px;
  color:rgba(14,14,18,.6);padding-left:0}
#fampickfoot button.link:hover{color:var(--red)}
@media(max-width:620px){#fampickcard{padding:16px 14px 12px}#fampickcard h2{font-size:20px}
  #fampickmap button{font-size:11.5px;padding:0 7px}}
#legend{position:fixed;right:14px;bottom:14px;z-index:26;width:224px;background:rgba(242,238,228,.94);
  border:1px solid rgba(14,14,18,.16);border-radius:12px;padding:10px 12px;box-shadow:0 6px 20px rgba(14,14,18,.12)}
#legend.hidden{display:none}
#legend h4{font:600 9.5px var(--sans);letter-spacing:.11em;text-transform:uppercase;color:rgba(14,14,18,.5);
  margin:0;display:flex;justify-content:space-between;cursor:pointer;-webkit-user-select:none;user-select:none}
#legend ul{list-style:none;margin:8px 0 0;padding:0;font:12px/1.45 var(--sans);color:rgba(14,14,18,.82)}
#legend li{display:flex;gap:8px;align-items:flex-start;margin-bottom:7px}
#legend li:last-child{margin-bottom:0}
#legend .sw{flex:0 0 16px;margin-top:2px;text-align:center}
#legend.collapsed ul{display:none}
@media (max-width:760px), (pointer:coarse) and (max-height:500px){#legend{bottom:70px}}
/* ---------- 2D pills ---------- */
.node{cursor:pointer}
/* v1.14 4.3: dim state is a pre-blended colour, not group opacity. Custom
   properties are written once in paint2dColours; paint2dFocus toggles only
   the .dim class, so a navigation costs zero extra attribute writes. */
.node rect{fill:var(--pf);stroke:var(--ps)}
.node circle{fill:var(--pc)}
.node.dim rect{fill:var(--pfd);stroke:var(--psd)}
.node.dim text{fill:var(--ptd)}
.node.dim circle{fill:var(--pcd)}
.node text{font-family:var(--sans);pointer-events:none;fill:var(--pt)}
/* v1.14 4.3: .node.dim{opacity:.14} removed — opacity on a <g> forces an
   offscreen transparency buffer per node. Colour is pre-blended instead. */
.node.oos{display:none}
path.oos{display:none}
.gd-edges{pointer-events:none}   /* v1.14 4.5: edge paths carry no handlers */
.famlabel{font:700 22.5px var(--sans);letter-spacing:.14em;text-transform:uppercase;fill:rgba(14,14,18,.50);pointer-events:none}
/* drafting-style dimension lines: a rule across each family's territory, broken
   for the caption, with end ticks and extension lines dropping to the pills */
/* no `stroke` here on purpose: it is set per-family as an attribute, and a CSS
   stroke would win over that attribute and grey every rule out again (the bug
   in v0.62-63). Weight matches the 700/22.5px caption's stem. */
.famdim{stroke-width:3.1;stroke-linecap:square;fill:none;pointer-events:none}
.fambg{pointer-events:none}
#arrtoggle{top:96px;left:14px}
#arrtoggle .rowlab{font:600 9.5px var(--sans);letter-spacing:.1em;text-transform:uppercase;
  color:rgba(14,14,18,.42);align-self:center;padding:0 6px 0 2px}
.famext{stroke-opacity:.30;stroke-width:1.6;stroke-dasharray:2 5;fill:none;pointer-events:none}
/* v0.81 — descent and fusion get distinct, legible hues on the paper ground.
   Deep indigo vs. burnt rust: dark enough at a 1.1px stroke to register
   without shouting, and far enough apart on the blue-orange axis to still
   read as different under red-green colour-blindness, which a same-family
   pair of hues would not. Opacity checked against the actual paper colour
   (#F5F3EF) via WCAG contrast math rather than picked by eye: an initial .62
   left fusion at 2.95:1 against paper — under the 3:1 minimum for graphical
   objects — once the stroke-opacity blend was accounted for. .85 clears both
   with real margin (descent 5.89:1, fusion 4.80:1) without going fully
   opaque. Influence keeps its original neutral dashed treatment — Paul
   asked for descent and fusion specifically. */
/* v0.81: Descent and Fusion now use clearly distinct hues (deep blue vs deep
   rust) rather than colors close enough to read as uniform grey at 1.1px.
   The previous pair (#2E4374 / #8B3F2A) was dark enough in isolation — but
   rendered at .85 opacity, blending with the cream paper dropped their
   effective contrast from ~8-9:1 to ~6:1, and at a 1.1px anti-aliased
   stroke that's thin enough to read as neutral grey rather than a hue,
   especially once compressed in a screenshot. Full opacity restores the
   solid contrast (9.4:1 / 8.5:1 against the paper), and the two hues sit on
   opposite sides of the color wheel (blue vs red-orange) rather than
   differing mainly in how dark they are, which is what makes them tell
   apart from each other, not just from the background. */
.lk-descent{fill:none;stroke:#3B5C99;stroke-opacity:1;stroke-width:1.1}
.lk-fusion{fill:none;stroke:#944A2E;stroke-opacity:1;stroke-width:1.1}
.lk-influence{fill:none;stroke:rgba(14,14,18,.22);stroke-width:1;stroke-dasharray:4 5}
.lk-lit{stroke:rgba(14,14,18,.62)!important;stroke-width:1.6!important}
.lk-descent.lk-lit{stroke:#3B5C99!important;stroke-opacity:1!important;stroke-width:1.6!important}
.lk-fusion.lk-lit{stroke:#944A2E!important;stroke-opacity:1!important;stroke-width:1.6!important}
path.dim{stroke-opacity:.10}   /* v1.14 4.4: was opacity — fill is none, so identical, but creates no stacking context */
/* ---------- detail card ---------- */
#card{position:fixed;z-index:35;background:var(--paper);border:1px solid rgba(14,14,18,.14);
  box-shadow:0 14px 40px rgba(14,14,18,.16);display:none;flex-direction:column;overflow:hidden}
#card.open{display:flex}
#card{top:64px;right:14px;width:330px;max-height:calc(100% - 86px);border-radius:16px}
/* v1.99: the old 58% cap came after the v1.20 88% rule and silently won, so a
   dragged sheet stopped at 58% while the drag code allowed 88%. Dropped. */
@media (max-width:760px), (pointer:coarse) and (max-height:500px){#card{top:auto;left:0;right:0;bottom:0;width:auto;border-radius:18px 18px 0 0}}
#cardhead{padding:16px 18px 10px;border-bottom:1px solid rgba(14,14,18,.08);position:relative}
#cx{position:absolute;top:10px;right:10px;border:0;background:transparent;font-size:20px;line-height:1;
  color:rgba(14,14,18,.5);cursor:pointer;padding:6px}
#cname{font-family:var(--serif);font-weight:600;font-size:22px;line-height:1.15;padding-right:26px}
#cmeta{display:flex;align-items:center;gap:8px;margin-top:7px;font-size:12px;color:rgba(14,14,18,.72)}
#cmeta i{width:9px;height:9px;border-radius:50%;flex:none}
#cbody{overflow-y:auto;padding:12px 18px 16px}
#cbody .csec{margin:10px 0 2px;font:600 10.5px var(--sans);letter-spacing:.09em;text-transform:uppercase;color:rgba(14,14,18,.5)}
#card .cdesc{margin:10px 0 4px;font:400 13px/1.5 var(--sans);color:rgba(14,14,18,.82)}
#card .cwiki{display:inline-block;margin:2px 0 6px;font:500 12px var(--sans);color:rgba(14,14,18,.62);text-decoration:underline;text-underline-offset:2px}
.cwiki:hover{color:var(--ink)}
#card .cep{display:block;padding:9px 11px;margin:6px 0;border:1px solid rgba(14,14,18,.14);border-radius:10px;
  text-decoration:none;color:var(--ink);font-size:13px;line-height:1.35}
.cep b{font-family:var(--serif);font-weight:600}
#card .cep small{display:block;color:rgba(14,14,18,.6);font-size:11.5px;margin-top:2px}
#card .note{font-size:12px;color:rgba(14,14,18,.6);margin:4px 0}
#cbody .chip{display:inline-flex;align-items:center;gap:6px;border:1px solid rgba(14,14,18,.18);border-radius:999px;
  padding:5px 11px 5px 8px;margin:3px 4px 3px 0;font-size:12px;cursor:pointer;background:rgba(255,255,255,.4)}
#cbody .chip:hover{border-color:var(--ink)}
#cbody .chip i{width:8px;height:8px;border-radius:50%;flex:none}
#cactions{display:flex;gap:8px;padding:10px 18px 14px;border-top:1px solid rgba(14,14,18,.08)}
#cactions button{flex:1;border:1px solid rgba(14,14,18,.3);background:transparent;border-radius:999px;
  padding:8px 0;font:500 12.5px var(--sans);cursor:pointer;color:var(--ink)}
#cactions button:hover{background:var(--ink);color:var(--paper)}
