/* ═══════════════════════════════════════════════════════════════
   NEXUS — Board Display System (Design Bible v8)
   The canvas shows the graph. The hover shows the card.
   ═══════════════════════════════════════════════════════════════ */

.board{
  position:relative;
  overflow:hidden;
  background:
    radial-gradient(ellipse 1200px 800px at 50% 40%, #181a2c 0%, #101120 60%, #0b0c18 100%);
  cursor:grab;
  touch-action:none;
  user-select:none;
  width:100%;height:100%;
}
body.day .board{
  background:radial-gradient(ellipse 1200px 800px at 50% 40%, #ece8dc 0%, #e0dccc 60%, #d6d2c2 100%);
}
.board.panning{cursor:grabbing;}
.board.connecting{cursor:crosshair;}

/* Subtle dot grid that moves with the world */
.board-grid{
  position:absolute;inset:-50%;pointer-events:none;z-index:0;
  background-image:radial-gradient(circle, rgba(201,185,122,.13) 1px, transparent 1px);
  background-size:48px 48px;
}
body.day .board-grid{
  background-image:radial-gradient(circle, rgba(90,80,40,.18) 1px, transparent 1px);
}

.world{
  position:absolute;left:0;top:0;width:0;height:0;
  transform-origin:0 0;
  z-index:1;
}
/* the replay camera: eased ONLY while zoomToFit(…, glide) is settling —
   manual pan/zoom never carries this class, so dragging stays instant */
.world.cam-glide{transition:transform .55s cubic-bezier(.4,0,.2,1);}

/* ── EDGES ── */
.edge-svg{position:absolute;left:0;top:0;width:1px;height:1px;overflow:visible;pointer-events:none;}
.edge-line{
  stroke:rgba(201,185,122,.6);
  stroke-width:2;
  transition:stroke .2s, opacity .18s, stroke-width .18s;
}
/* Hover a card → its connections light up, the rest fade, so a crossing
   tangle becomes readable. */
.world.edge-focus .edge-line{opacity:.1;}
.world.edge-focus .edge-line.edge-lit{opacity:1;stroke-width:3.25;}
.world.edge-focus .edge-label{opacity:0 !important;}
.world.edge-focus .edge-label.edge-lit{opacity:1 !important;}
.world.edge-focus .bnode:not(.node-linked){opacity:.4;transition:opacity .18s;}
.world.edge-focus .bnode.node-linked{opacity:1;}
.edge-line.dissimilar{stroke:rgba(210,80,64,.65);stroke-dasharray:6 4;}
/* pivot palette edges — negative claims (precludes) dash like RED;
   positive claims stay solid in their frame color */
.edge-line.pv-contains{stroke:rgba(201,185,122,.7);}
.edge-line.pv-precludes{stroke:rgba(155,126,192,.7);stroke-dasharray:6 4;}
.edge-line.pv-begets{stroke:rgba(111,159,216,.7);}
.edge-line.pv-caused_by{stroke:rgba(111,159,216,.7);}
.edge-line.pv-becomes{stroke:rgba(216,163,92,.7);}
.edge-line.pv-mirrors{stroke:rgba(111,192,192,.7);}
.edge-line.pv-stands_for{stroke:rgba(192,126,166,.7);}
body.day .edge-line{stroke:rgba(122,104,48,.7);}
body.day .edge-line.dissimilar{stroke:rgba(160,50,40,.7);}
body.day .edge-line.pv-contains{stroke:rgba(146,120,40,.75);}
body.day .edge-line.pv-precludes{stroke:rgba(110,80,150,.75);}
body.day .edge-line.pv-begets{stroke:rgba(60,100,160,.75);}
body.day .edge-line.pv-becomes{stroke:rgba(160,110,40,.75);}
body.day .edge-line.pv-mirrors{stroke:rgba(50,130,130,.75);}
body.day .edge-line.pv-stands_for{stroke:rgba(150,80,120,.75);}
.edge-hit{stroke:transparent;stroke-width:14;pointer-events:stroke;cursor:pointer;}

/* Rationale — "stored permanently, displayed at the midpoint" (v8) */
.edge-label{
  position:absolute;
  transform:translate(-50%,-50%);
  width:max-content;
  max-width:360px;
  font-family:'Cormorant Garamond',serif;
  font-style:italic;
  font-size:14.5px;
  line-height:1.45;
  color:rgba(232,228,214,.85);
  background:rgba(12,12,24,.88);
  border:.5px solid rgba(201,185,122,.28);
  border-radius:8px;
  padding:8px 14px;
  text-align:center;
  pointer-events:none;
  opacity:0;
  transition:opacity .25s;
  z-index:7;   /* above cards (z5) and ghosts (z6) — a shown rationale must be readable */
}
body.day .edge-label{
  color:#3a3240;
  background:rgba(250,248,240,.92);
  border-color:rgba(90,80,40,.3);
}
.world.show-rationales .edge-label,
.edge-label.hover{opacity:1;}

/* ── NODES ──
   .bnode sits at the simulation point (zero size).
   Each form (circle / card / label) self-centers on that point —
   exactly ONE translate(-50%,-50%) per form, so edges and labels
   always anchor to the visual center. */
.bnode{
  position:absolute;left:0;top:0;
  z-index:5;
  cursor:pointer;
}
.bnode-inner{position:absolute;left:0;top:0;width:0;height:0;}

/* Circle form */
.bnode-circle{
  position:absolute;left:0;top:0;
  transform:translate(-50%,-50%);
  border-radius:50%;
  display:flex;align-items:center;justify-content:center;
  transition:filter .25s, width .3s, height .3s;
}
.bnode-glyph{
  line-height:1;
  color:#ece8da;   /* text glyphs (△ ∑ ƒ ∴) need light ink on the dark node face */
  filter:drop-shadow(0 1px 3px rgba(0,0,0,.9));
  pointer-events:none;
}
/* Genesis inner marker (v8: "Genesis cards carry a small inner marker") */
.bnode-genesis{
  position:absolute;
  bottom:14%;left:50%;transform:translateX(-50%);
  width:4px;height:4px;border-radius:50%;
  background:#c9b97a;
  box-shadow:0 0 5px rgba(201,185,122,.8);
  pointer-events:none;
}

/* Sacred tier: slow breathing ring pulse */
.bnode.tier-sacred .bnode-circle{animation:sacredNodeBreath 3.5s ease-in-out infinite;}
@keyframes sacredNodeBreath{
  0%,100%{filter:brightness(1);}
  50%{filter:brightness(1.28);}
}

/* Nexus status — degree: warm gold glow (v8).
   The glow used to live ONLY inside the animation keyframes — paused/throttled
   animations (reduced motion, background tabs) left NO glow at all, and the
   translucent gold vanished on the day parchment (user 7/10 "are nexus cards
   glowing?"). Now: a static ring + base glow always shows; animation breathes. */
.bnode.nexus-degree .bnode-circle{
  outline:3px solid rgba(201,185,122,.9);outline-offset:3px;border-radius:50%;
  filter:drop-shadow(0 0 12px rgba(201,185,122,.75)) drop-shadow(0 0 34px rgba(201,185,122,.3));
  animation:nexusGold 2.6s ease-in-out infinite;
}
@keyframes nexusGold{
  0%,100%{filter:drop-shadow(0 0 10px rgba(201,185,122,.65)) drop-shadow(0 0 30px rgba(201,185,122,.25));}
  50%{filter:drop-shadow(0 0 20px rgba(201,185,122,.95)) drop-shadow(0 0 52px rgba(201,185,122,.45));}
}
body.day .bnode.nexus-degree .bnode-circle{
  outline-color:rgba(146,110,10,.95);
  filter:drop-shadow(0 0 8px rgba(146,110,10,.8)) drop-shadow(0 0 26px rgba(146,110,10,.4));
  animation-name:nexusGoldDay;
}
@keyframes nexusGoldDay{
  0%,100%{filter:drop-shadow(0 0 6px rgba(146,110,10,.7)) drop-shadow(0 0 22px rgba(146,110,10,.35));}
  50%{filter:drop-shadow(0 0 14px rgba(146,110,10,1)) drop-shadow(0 0 40px rgba(146,110,10,.55));}
}
/* Betweenness: cool electric blue glow (v8 — Intermediate) */
.bnode.nexus-between .bnode-circle{
  outline:3px solid rgba(80,170,255,.85);outline-offset:3px;border-radius:50%;
  filter:drop-shadow(0 0 12px rgba(80,170,255,.7)) drop-shadow(0 0 34px rgba(80,170,255,.28));
  animation:nexusBlue 2.6s ease-in-out infinite;
}
@keyframes nexusBlue{
  0%,100%{filter:drop-shadow(0 0 10px rgba(80,170,255,.6)) drop-shadow(0 0 30px rgba(80,170,255,.22));}
  50%{filter:drop-shadow(0 0 20px rgba(80,170,255,.9)) drop-shadow(0 0 52px rgba(80,170,255,.4));}
}
body.day .bnode.nexus-between .bnode-circle{
  outline-color:rgba(20,90,200,.9);
  filter:drop-shadow(0 0 8px rgba(20,90,200,.75)) drop-shadow(0 0 26px rgba(20,90,200,.35));
  animation-name:nexusBlueDay;
}
@keyframes nexusBlueDay{
  0%,100%{filter:drop-shadow(0 0 6px rgba(20,90,200,.65)) drop-shadow(0 0 22px rgba(20,90,200,.3));}
  50%{filter:drop-shadow(0 0 14px rgba(20,90,200,.95)) drop-shadow(0 0 40px rgba(20,90,200,.5));}
}

/* Node title label — top is set by JS to half the visual height */
.bnode-label{
  position:absolute;
  left:0;transform:translateX(-50%);
  font-family:'Spectral',serif;
  font-size:12px;
  font-weight:600;
  color:rgba(232,228,214,.92);
  text-shadow:0 1px 4px rgba(0,0,0,.95);
  white-space:nowrap;
  max-width:190px;overflow:hidden;text-overflow:ellipsis;
  pointer-events:none;
  text-align:center;
}
body.day .bnode-label{color:#2c2836;text-shadow:0 1px 3px rgba(255,255,255,.6);}
.bnode.nexus-degree .bnode-label{color:#d4c070;}
body.day .bnode.nexus-degree .bnode-label{color:#8a7020;}

/* Card form (Card / Hybrid view) — full forge card, scaled.
   translate + scale set inline (single centering transform). */
.bnode-cardholder{
  position:absolute;left:0;top:0;
  transform-origin:0 0;
  pointer-events:auto;
}
/* player ring — who played this card */
.bnode-cardholder .nx{
  outline:4px solid var(--pring, transparent);
  outline-offset:4px;
}
/* board scale: card text is illegible — drop the whole body, let the
   image fill the card. The full text lives in the click-to-zoom lightbox. */
.bnode-cardholder .body-zone{display:none;}
.bnode-cardholder .img-win{height:auto !important;flex:1;margin-bottom:9px;}
/* bias the crop toward the top so portraits keep their heads */
.bnode-cardholder .img-win img{object-position:50% 10% !important;}
.bnode-cardholder .fa-text,
.bnode-cardholder .fa-bot{display:none;}
/* let the header grow so long names wrap fully instead of clipping */
.bnode-cardholder .hdr-band{height:auto !important;min-height:44px;padding-top:5px;padding-bottom:5px;align-items:center;}
.bnode-cardholder .card-title{
  font-size:22px !important;line-height:1.12;font-weight:600;
  /* wrap at spaces only — fitCardTitle() shrinks the font when a single
     word (Technology) is wider than the title area; never break mid-word */
  white-space:normal;overflow-wrap:normal;word-break:normal;
  display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden;
  /* the lil' box: a dark plate so the title reads over ANY art */
  background:rgba(6,4,16,.66);
  -webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);
  border-radius:6px;padding:3px 8px;
  box-shadow:0 1px 6px rgba(0,0,0,.35);
}
/* bigger fallback glyph when a card has no image (the medallion gives contrast) */
.bnode-cardholder .img-win > div,.bnode-cardholder .nx-art-glyph{font-size:110px !important;}
.bnode.selected .bnode-circle{outline:2px solid rgba(201,185,122,.85);outline-offset:4px;border-radius:50%;}
.bnode.selected .bnode-cardholder{outline:2px solid rgba(201,185,122,.85);outline-offset:4px;}

/* Nexus in Card / Hybrid view — the SAME halo technique as the node circles
   (filter drop-shadow on the holder — the Chairman confirmed node glow reads
   on his machine, so cards get the identical recipe; the outline stays as
   the static base for paused-animation environments). 7/10: "you've just put
   the word nexus above the card rather than having it glow like the nodes
   do" — the chip is retired, the glow is the marker. */
.bnode.nexus-degree .bnode-cardholder .nx{
  outline:3px solid rgba(201,185,122,.9) !important;
}
.bnode.nexus-degree .bnode-cardholder{
  filter:drop-shadow(0 0 14px rgba(201,185,122,.85)) drop-shadow(0 0 42px rgba(201,185,122,.4));
  animation:nexusGoldCard 2.6s ease-in-out infinite;
}
@keyframes nexusGoldCard{
  0%,100%{filter:drop-shadow(0 0 12px rgba(201,185,122,.75)) drop-shadow(0 0 36px rgba(201,185,122,.3));}
  50%{filter:drop-shadow(0 0 24px rgba(201,185,122,1)) drop-shadow(0 0 64px rgba(201,185,122,.55));}
}
body.day .bnode.nexus-degree .bnode-cardholder .nx{
  outline-color:rgba(146,110,10,.95) !important;
}
body.day .bnode.nexus-degree .bnode-cardholder{
  filter:drop-shadow(0 0 10px rgba(146,110,10,.85)) drop-shadow(0 0 32px rgba(146,110,10,.45));
  animation-name:nexusGoldCardDay;
}
@keyframes nexusGoldCardDay{
  0%,100%{filter:drop-shadow(0 0 9px rgba(146,110,10,.75)) drop-shadow(0 0 28px rgba(146,110,10,.38));}
  50%{filter:drop-shadow(0 0 18px rgba(146,110,10,1)) drop-shadow(0 0 52px rgba(146,110,10,.6));}
}
/* betweenness Nexus, card view — cool electric blue, same halo */
.bnode.nexus-between .bnode-cardholder .nx{
  outline:3px solid rgba(120,170,232,.9) !important;
}
.bnode.nexus-between .bnode-cardholder{
  filter:drop-shadow(0 0 14px rgba(80,170,255,.75)) drop-shadow(0 0 42px rgba(80,170,255,.32));
  animation:nexusBlueCard 2.6s ease-in-out infinite;
}
@keyframes nexusBlueCard{
  0%,100%{filter:drop-shadow(0 0 12px rgba(80,170,255,.65)) drop-shadow(0 0 36px rgba(80,170,255,.26));}
  50%{filter:drop-shadow(0 0 24px rgba(80,170,255,.95)) drop-shadow(0 0 64px rgba(80,170,255,.48));}
}
body.day .bnode.nexus-between .bnode-cardholder .nx{
  outline-color:rgba(20,90,200,.9) !important;
}
body.day .bnode.nexus-between .bnode-cardholder{
  filter:drop-shadow(0 0 10px rgba(20,90,200,.75)) drop-shadow(0 0 32px rgba(20,90,200,.38));
  animation-name:nexusBlueCardDay;
}
@keyframes nexusBlueCardDay{
  0%,100%{filter:drop-shadow(0 0 9px rgba(20,90,200,.65)) drop-shadow(0 0 28px rgba(20,90,200,.32));}
  50%{filter:drop-shadow(0 0 18px rgba(20,90,200,.95)) drop-shadow(0 0 52px rgba(20,90,200,.55));}
}

/* ── GHOST CARDS — the roads not taken (spectate) ── */
.ghost-card{
  opacity:.32;filter:grayscale(.35);cursor:zoom-in;
  transition:opacity .2s, filter .2s;z-index:6;   /* above real cards (z5) so they never hide */
}
.ghost-card:hover{opacity:.9;filter:grayscale(0);z-index:8;}
.ghost-card .nx{outline-style:dashed !important;outline-width:2px !important;}
.ghost-lbl{
  position:absolute;left:50%;bottom:-52px;transform:translateX(-50%);
  font-family:'Cinzel',serif;font-size:18px;letter-spacing:2px;
  color:rgba(232,228,214,.9);text-shadow:0 1px 4px rgba(0,0,0,.95);
  white-space:nowrap;pointer-events:none;text-transform:uppercase;
  text-align:center;
}
.ghost-lbl .gl-base{
  display:block;font-family:'Cormorant Garamond',serif;font-size:13px;
  letter-spacing:.5px;text-transform:none;color:rgba(210,205,190,.75);
  margin-top:2px;
}
body.day .ghost-lbl{color:rgba(60,54,40,.9);text-shadow:none;}
body.day .ghost-lbl .gl-base{color:rgba(90,84,64,.8);}
/* tether: inline stroke carries the BASE's domain color; hover lights the way home */
.ghost-edge{stroke:rgba(200,200,220,.35);stroke-width:1.5;stroke-dasharray:3 6;opacity:.55;transition:opacity .15s;}
.ghost-edge.hot{opacity:1;stroke-width:2.5;}
.bnode.ghost-origin .bnode-cardholder .nx{outline:3px dashed rgba(201,185,122,.9) !important;outline-offset:3px;}
.bnode.ghost-origin .bnode-circle{outline:3px dashed rgba(201,185,122,.9);outline-offset:4px;border-radius:50%;}

/* ── HOVER PREVIEW (screen-space overlay) ── */
.board-preview{
  position:absolute;
  z-index:60;
  pointer-events:none;
  animation:previewIn .18s ease-out;
}
@keyframes previewIn{from{opacity:0;transform:scale(.92);}to{opacity:1;transform:scale(1);}}

/* ── HUD bits ── */
.board-hud{
  position:absolute;right:14px;bottom:12px;z-index:50;
  font-family:'Cinzel',serif;font-size:9px;letter-spacing:1.5px;
  color:rgba(224,220,206,.35);
  pointer-events:none;
}
body.day .board-hud{color:rgba(60,50,30,.4);}
