/* paraGRAF — a standalone neo-brutalist skin for the citation-graph explorer.
 * The layout is the one the explorer was born with: the stage is the whole
 * viewport, and the cards (controls, details, API traffic) stand over it and
 * roll up windowshade-style to their own heads. The look is new: hard 3px ink
 * borders, offset block shadows, flat saturated hues, no rounded corners,
 * Archivo Black / Space Grotesk / IBM Plex Mono. */

:root {
  --bg: #f3eee2;          /* warm paper the canvas paints too (app.js reads it) */
  --surf: #fffdf6;        /* card face */
  --surf-2: #f3eee2;
  --surf-3: #e8e1cd;
  --ink: #141414;
  --ink-2: #2b2b28;
  --ink-3: #5c5a4f;
  --ink-4: #8b887a;
  --accent: #ffd23f;      /* marker yellow */
  --accent-2: #ff70a6;
  --line: #141414;        /* every border is ink */
  --sans: "Space Grotesk", system-ui, sans-serif;
  --display: "Archivo Black", "Arial Black", sans-serif;
  --mono: "IBM Plex Mono", ui-monospace, monospace;
}

* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; height: 100%; }
body { font-family: var(--sans); color: var(--ink); background: var(--bg); }
a { color: var(--ink); text-decoration-thickness: 2px;
  text-decoration-color: var(--accent-2); }
a:hover { background: var(--accent); }

.graf { position: relative; height: 100vh; height: 100dvh; overflow: hidden; }

/* -- the cards -- */
.graf-rail { position: absolute; z-index: 15; width: 21.5rem;
  max-width: calc(100% - 1.6rem); display: flex; flex-direction: column;
  background: var(--surf); border: 3px solid var(--line);
  box-shadow: 7px 7px 0 var(--line); }
.graf-rail-l { left: 1rem; top: 1rem; bottom: auto;
  max-height: calc(100% - 2rem); }
.graf-rail-r { right: 1rem; top: 1rem; bottom: 1rem; width: 23rem; }
.graf-rail-t { left: 1rem; top: auto; bottom: 1rem; max-height: 38%; }
/* rolled up: the head is the whole card */
.graf-rail.folded { bottom: auto; }
.graf-rail.folded .graf-railbody { display: none; }
/* the traffic card is anchored at the foot and must keep its bottom edge */
.graf-rail-t.folded { top: auto; bottom: 1rem; }
/* the left card ends where the traffic card begins */
@media (min-height: 560px) {
  .graf-rail-l { max-height: calc(64% - 2rem); }
  .graf-rail-t { max-height: 36%; }
}

.graf-railhead { display: flex; align-items: center; gap: .5rem;
  cursor: pointer; padding: .65rem 1rem;
  border-bottom: 3px solid var(--line); background: var(--surf); }
.graf-rail.folded .graf-railhead { border-bottom: 0; }
.graf-rail-r .graf-railhead, .graf-rail-t .graf-railhead {
  background: var(--accent); }
.graf-fold { flex: none; margin-left: auto; border: 0; background: none;
  cursor: pointer; padding: .25rem; display: flex; align-items: center; }
.graf-fold-chevron { width: .5rem; height: .5rem;
  border-right: 3px solid var(--ink); border-bottom: 3px solid var(--ink);
  transform: rotate(45deg); transition: transform .15s ease; }
.graf-rail.folded .graf-fold-chevron { transform: rotate(-45deg); }
.graf-railbody { flex: 1; min-height: 0; overflow-y: auto;
  padding: .9rem 1rem 1.3rem; }

.graf-wordmark { font-family: var(--display); font-size: 1.5rem;
  font-weight: 400; letter-spacing: -.02em; line-height: 1; margin: 0; }
.graf-wordmark span { background: var(--accent); padding: 0 .12em;
  box-shadow: 2px 2px 0 var(--line); }
.graf-railtitle { font-family: var(--sans); font-weight: 700;
  font-size: 1.02rem; text-transform: uppercase; letter-spacing: .02em;
  line-height: 1.25; margin: 0; min-width: 0; overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap; }
.graf-tagline { font-size: .82rem; line-height: 1.45; margin: 0 0 .8rem; }

/* -- search -- */
.graf-search { position: relative; }
.graf-search input { width: 100%; font-family: var(--mono);
  font-size: .8rem; color: var(--ink); background: var(--surf);
  border: 3px solid var(--line); border-radius: 0;
  padding: .5rem .7rem; outline: none; }
.graf-search input:focus { background: var(--accent);  }
.graf-search input::placeholder { color: var(--ink-3); }
.graf-hits { position: absolute; top: calc(100% + 6px); left: 0; right: 0;
  z-index: 40; background: var(--surf); border: 3px solid var(--line);
  box-shadow: 6px 6px 0 var(--line); max-height: 22rem; overflow-y: auto; }
.graf-hits .hit { display: flex; flex-direction: column; gap: .1rem;
  padding: .45rem .7rem; cursor: pointer; font-size: .8rem; }
.graf-hits .hit + .hit { border-top: 2px solid var(--line); }
.graf-hits .hit.on, .graf-hits .hit:hover { background: var(--accent); }
.graf-hits .lb { font-weight: 700; white-space: nowrap; overflow: hidden;
  text-overflow: ellipsis; }
.graf-hits .ti { color: var(--ink-3); overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap; }

/* -- direction + depth -- */
.graf-row { display: flex; align-items: stretch; gap: .55rem;
  margin-top: .65rem; flex-wrap: wrap; }
.graf-seg, .graf-steps { display: flex; align-items: stretch;
  border: 3px solid var(--line); background: var(--surf); overflow: hidden; }
.graf-seg button, .graf-steps button { font: 700 .7rem var(--sans);
  text-transform: uppercase; letter-spacing: .02em; color: var(--ink);
  background: none; border: 0; padding: .42rem .5rem; cursor: pointer;
  white-space: nowrap; }
.graf-seg button + button { border-left: 3px solid var(--line); }
.graf-seg button.on { background: var(--ink); color: var(--accent); }
.graf-seg button:not(.on):hover, .graf-steps button:hover {
  background: var(--accent); }
.graf-depth { font: 600 .7rem var(--mono); color: var(--ink);
  padding: 0 .45rem; white-space: nowrap; font-variant-numeric: tabular-nums;
  border-left: 3px solid var(--line); border-right: 3px solid var(--line);
  display: flex; align-items: center; justify-content: center; }

/* -- source filter -- */
.graf-legend-h { font: 700 .72rem var(--sans); text-transform: uppercase;
  letter-spacing: .06em; color: var(--ink-3); margin: 1.2rem 0 .3rem; }
.graf-legend { display: flex; flex-direction: column;
  border-top: 2px solid var(--line); }
.graf-src { display: flex; align-items: center; gap: .5rem; width: 100%;
  border: 0; border-bottom: 2px solid var(--line); background: none;
  padding: .3rem .1rem; cursor: pointer; text-align: left;
  font: 500 .78rem var(--sans); color: var(--ink); }
.graf-src:hover { background: var(--accent); }
.graf-src[aria-checked="false"] { opacity: .35; }
/* the switch is a square slider in a hard frame */
.graf-src .sw { flex: none; width: 1.6rem; height: .9rem;
  border: 2px solid var(--line); background: var(--surf);
  position: relative; }
.graf-src .sw::after { content: ""; position: absolute; top: .07rem;
  left: .07rem; width: .5rem; height: .5rem; background: var(--ink);
  transition: transform .15s ease; }
.graf-src[aria-checked="true"] .sw { background: var(--c); }
.graf-src[aria-checked="true"] .sw::after { transform: translateX(.72rem); }
.graf-src .dot { flex: none; width: .6rem; height: .6rem;
  background: var(--c); border: 2px solid var(--line); }
.graf-src .nm { flex: 1; min-width: 0; overflow: hidden; white-space: nowrap;
  text-overflow: ellipsis; }
.graf-src .cnt { flex: none; font: 500 .68rem var(--mono);
  color: var(--ink-3); font-variant-numeric: tabular-nums; }

/* -- the stage -- */
.graf-stage { position: absolute; inset: 0; overflow: hidden;
  background: var(--bg); }
.graf-stage canvas { position: absolute; inset: 0; width: 100%; height: 100%;
  cursor: grab; touch-action: none; }
.graf-stage canvas.dragging { cursor: grabbing; }
.graf-cap { position: absolute; left: 50%; top: 1rem; z-index: 5;
  transform: translateX(-50%); white-space: nowrap;
  font: 500 .7rem var(--mono); color: var(--ink);
  max-width: calc(100% - 2rem); overflow: hidden; text-overflow: ellipsis;
  background: var(--surf); border: 2px solid var(--line);
  box-shadow: 4px 4px 0 var(--line); padding: .22rem .7rem;
  pointer-events: none; }
/* the fetch indicator: standing under the cap note while any API call is in
   flight, with a ratcheting square for a spinner */
.graf-loading { position: absolute; left: 50%; top: 3.4rem; z-index: 6;
  transform: translateX(-50%); display: flex; align-items: center;
  gap: .5rem; font: 500 .7rem var(--mono); color: var(--ink);
  background: var(--surf); border: 2px solid var(--line);
  box-shadow: 4px 4px 0 var(--line); padding: .22rem .7rem;
  pointer-events: none; }
.graf-loading[hidden] { display: none; }  /* display:flex beats the UA rule */
.graf-loading .sq { width: .55rem; height: .55rem; background: var(--accent);
  border: 2px solid var(--line);
  animation: graf-spin .8s steps(8) infinite; }
@keyframes graf-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
  .graf-loading .sq { animation: none; }
}

.graf-hint { position: absolute; left: 50%; bottom: 1rem; z-index: 5;
  transform: translateX(-50%); font: 500 .68rem var(--mono);
  color: var(--ink); white-space: nowrap; pointer-events: none;
  background: var(--surf); border: 2px solid var(--line);
  box-shadow: 4px 4px 0 var(--line); padding: .2rem .7rem; }

/* -- the details card's body -- */
.graf-panel-body .eyebrow { display: flex; align-items: center; gap: .45rem;
  font: 700 .72rem var(--sans); text-transform: uppercase;
  letter-spacing: .05em; margin-bottom: .2rem; }
.graf-panel-body .eyebrow .dot { width: .65rem; height: .65rem;
  border: 2px solid var(--line); }
.graf-panel-body .g-title { font-size: .85rem; color: var(--ink-2);
  margin: .35rem 0 .6rem; line-height: 1.4; }
.graf-panel-body .g-author { font: 500 .76rem var(--mono);
  color: var(--ink-3); margin: -.3rem 0 .6rem; }
.graf-panel-body .g-nums { display: flex; gap: 1.2rem; margin: .7rem 0 .9rem;
  border-top: 3px solid var(--line); border-bottom: 3px solid var(--line);
  padding: .55rem 0; }
.graf-panel-body .g-nums b { display: block; font-family: var(--display);
  font-size: 1.15rem; font-weight: 400;
  font-variant-numeric: tabular-nums; }
.graf-panel-body .g-nums span { font: 500 .64rem var(--sans);
  color: var(--ink-3); text-transform: uppercase; letter-spacing: .05em; }
.graf-panel-body h3 { font: 700 .74rem var(--sans);
  text-transform: uppercase; letter-spacing: .06em; color: var(--ink);
  background: var(--surf-3); padding: .2rem .4rem; margin: 1rem 0 .3rem; }
.graf-panel-body h3 .n { float: right; font: 600 .7rem var(--mono);
  text-transform: none; letter-spacing: 0; color: var(--ink-3);
  font-variant-numeric: tabular-nums; }
.graf-panel-body ul { list-style: none; margin: 0; padding: 0; }
.graf-panel-body li { display: flex; align-items: baseline; gap: .5rem;
  font-size: .8rem; padding: .24rem .1rem; cursor: pointer;
  border-top: 1px solid var(--surf-3); }
.graf-panel-body li:hover { background: var(--accent); }
.graf-panel-body li .dot { flex: none; width: .55rem; height: .55rem;
  border: 2px solid var(--line); align-self: center; }
.graf-panel-body li .lb { font-weight: 700; white-space: nowrap;
  min-width: 0; flex: 0 1 auto; overflow: hidden; text-overflow: ellipsis; }
.graf-panel-body li .ti { color: var(--ink-3); overflow: hidden;
  white-space: nowrap; text-overflow: ellipsis; flex: 1 1 0; min-width: 0; }
.graf-panel-body li .n { flex: none; margin-left: auto; padding-left: .4rem;
  font: 500 .72rem var(--mono); color: var(--ink-3);
  font-variant-numeric: tabular-nums; }
.graf-panel-body .g-more { font: 500 .72rem var(--mono); color: var(--ink-3);
  padding: .3rem 0; }
.graf-panel-body .g-empty { font-size: .85rem; color: var(--ink-3); }
.graf-panel-body .g-actions { display: flex; gap: .6rem; margin-top: 1rem;
  flex-wrap: wrap; }
.graf-panel-body .g-actions a, .graf-panel-body .g-actions button {
  font: 700 .74rem var(--sans); text-transform: uppercase;
  letter-spacing: .02em; border: 3px solid var(--line); border-radius: 0;
  box-shadow: 3px 3px 0 var(--line); padding: .4rem .7rem; cursor: pointer;
  background: var(--surf); color: var(--ink); text-decoration: none; }
.graf-panel-body .g-actions .primary { background: var(--accent); }
.graf-panel-body .g-actions a:hover,
.graf-panel-body .g-actions button:hover {
  transform: translate(1px, 1px); box-shadow: 2px 2px 0 var(--line); }

/* -- the API traffic card -- */
.graf-traffic-sum { font: 600 .68rem var(--mono); text-transform: none;
  letter-spacing: 0; color: var(--ink-2); margin-left: .3rem; }
.graf-traffic-intro { font-size: .76rem; line-height: 1.45;
  margin: 0 0 .6rem; }
.graf-traffic { list-style: none; margin: 0; padding: 0;
  font-family: var(--mono); font-size: .68rem; }
.graf-traffic li { border-top: 1px solid var(--surf-3); }
.graf-traffic a { display: flex; align-items: baseline; gap: .45rem;
  padding: .24rem .1rem; text-decoration: none; }
.graf-traffic .m { flex: none; font-weight: 600; background: var(--ink);
  color: var(--accent); padding: 0 .25rem; }
.graf-traffic .p { flex: 1 1 auto; min-width: 0; white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis; }
.graf-traffic .s { flex: none; font-weight: 600; }
.graf-traffic .s.err { background: var(--accent-2); padding: 0 .2rem; }
.graf-traffic .kb, .graf-traffic .ms { flex: none; color: var(--ink-3);
  font-variant-numeric: tabular-nums; }

/* -- narrow: one column, every card a full-width bar -- */
@media (max-width: 860px) {
  .graf-rail { left: .6rem; right: .6rem; width: auto; max-width: none;
    box-shadow: 4px 4px 0 var(--line); }
  .graf-rail-l { top: .6rem; bottom: auto; max-height: calc(100% - 8rem); }
  .graf-rail-r { top: auto; bottom: .6rem; max-height: 55%; }
  .graf-rail-r.folded { top: auto; bottom: .6rem; }
  /* the traffic bar stacks just above the details bar; with the details card
     open the accordion has folded it, and even its folded bar would stand on
     the open panel's content -- tuck it away until the panel closes */
  .graf-rail-t { top: auto; bottom: 3.6rem; max-height: 45%; }
  .graf-rail-t.folded { top: auto; bottom: 3.6rem; }
  .graf:has(.graf-rail-r:not(.folded)) .graf-rail-t { visibility: hidden; }
  .graf-railhead { padding: .55rem .8rem; }
  .graf-railbody { padding: .8rem .8rem 1.1rem; }
  .graf-hint { display: none; }       /* no pointer to teach it to */
}
