/* SARAH showcase — neural home canvas, legend and dock.
   Ported from the SARAH app: app/client/src/NeuralHome.jsx
   Same 160x100 field and the same hub as the app, but this canvas now carries
   EIGHT bubbles in FOUR group colours (it used to be fifteen in five — Casper
   cut it back, see lib/neural.php), with the same drag-to-move / click-to-open /
   hub-pan / cursor-zoom behaviour.
   Palette is the Midnight Purple theme, shared with site.css. */

:root{
  /* app-shell tokens the window manager expects (Panel.jsx names).
     Values are the Midnight Purple theme, matching site.css and the SARAH app. */
  /* Alpha is deliberately high: backdrop-filter gives the frost where it is
     supported, but text must stay readable even where it is not (older
     Firefox, software rendering, some mobile GPUs). */
  --surface:rgba(43,10,61,.94);
  --surface-solid:#2b0a3d;
  --border:rgba(150,90,255,.28);
  --border-strong:rgba(168,107,255,.45);
  --text:#f3eaff;
  --text-soft:#ddcff0;
  --muted:#c9b9dd;
  --faint:#9a87b3;
  --accent:#00f048;
  --accent-glow:rgba(0,240,72,.28);
  --topbar-bg:rgba(23,1,33,.88);
  --shadow:0 18px 48px rgba(0,0,0,.62);
  --shadow-soft:0 10px 30px rgba(0,0,0,.42);
  /* the four node groups, exactly as sarah_neural_groups() defines them.
     These were five (agents/#2da44e) and are now four — see lib/neural.php. */
  --nh-workspace:#ffb454;
  --nh-core:#4fd6e8;
  --nh-systems:#a86bff;
  --nh-tools:#ff6ec7;
}

/* ---------- accessible-only text ---------- */
.sr-only{
  position:absolute!important;width:1px;height:1px;padding:0;margin:-1px;
  overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0;
}

/* ---------- full-viewport app shell (home page only) ---------- */
body.is-app{display:flex;flex-direction:column;height:100vh;height:100dvh;overflow:hidden}
body.is-app main#main{flex:1;min-height:0;display:flex;position:relative}
body.is-app .skip:focus{position:fixed}
.app-canvas{position:relative;flex:1;min-width:0;min-height:0;overflow:hidden;background:var(--space)}

#neural{
  position:absolute;inset:0;width:100%;height:100%;display:block;
  touch-action:none;cursor:default;
  /* the app lets you drag the graph past the edges; keep it off the page scroll */
  user-select:none;-webkit-user-select:none;
}
#neural.is-panning{cursor:grabbing}

/* ---------- top bar: replaces the old nav menu ---------- */
.masthead--app{position:relative;top:auto;z-index:30;flex-shrink:0}
.app-topbar__in{display:flex;align-items:center;gap:.7rem;padding:.4rem .8rem;flex-wrap:wrap}
.brand--mini{gap:.5rem;margin-right:0}
.brand--mini img{width:44px;height:30px}
.brand--mini .brand__text strong{font-size:1.05rem;letter-spacing:.1em}
.brand--mini .brand__text small{display:none}
.app-topbar__hint{
  font-family:var(--mono);font-size:.72rem;color:var(--faint);
  margin-right:auto;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}
.app-tools{display:flex;align-items:center;gap:.35rem;flex-wrap:wrap}
.tool-btn{
  font:inherit;font-size:.8rem;font-weight:600;cursor:pointer;
  background:transparent;border:1px solid var(--border);color:var(--muted);
  border-radius:8px;padding:.28rem .55rem;white-space:nowrap;
}
.tool-btn:hover{color:#fff;border-color:var(--border-strong)}
.tool-btn.is-on{color:var(--accent);border-color:var(--accent);font-weight:700}
.tool-btn:focus-visible{outline:3px solid var(--gold);outline-offset:1px}

/* ---------- legend (bottom-left, collapsible — app behaviour) ---------- */
.nh-legend{
  position:absolute;left:16px;bottom:16px;z-index:4;
  background:var(--surface);border:1px solid var(--border);border-radius:14px;
  backdrop-filter:blur(16px) saturate(1.2);-webkit-backdrop-filter:blur(16px) saturate(1.2);
  box-shadow:var(--shadow-soft);color:var(--muted);
  max-width:min(240px,calc(100vw - 32px));
}
.nh-legend__pill{
  display:flex;align-items:center;gap:.5rem;cursor:pointer;
  background:transparent;border:0;color:var(--muted);
  font:inherit;font-size:.68rem;font-weight:800;letter-spacing:.14em;
  padding:.5rem .85rem;border-radius:14px;
}
.nh-legend__pill:hover{color:#fff}
.nh-legend__panel{padding:.6rem .75rem;max-height:min(420px,60vh);overflow-y:auto}
.nh-legend__head{display:flex;align-items:center;gap:.5rem;margin-bottom:.35rem}
.nh-legend__head span{font-size:.68rem;font-weight:800;letter-spacing:.14em;color:var(--muted)}
.nh-legend__head button{
  margin-left:auto;background:transparent;border:0;color:var(--muted);
  cursor:pointer;font:inherit;font-size:.72rem;font-weight:700;padding:.1rem .25rem;
}
.nh-legend__rows{border-top:1px solid var(--border);padding-top:.35rem;display:flex;flex-direction:column;gap:.1rem}
.nh-row{display:flex;align-items:center;gap:.45rem;font-size:.78rem;padding:.12rem 0}
.nh-dot{
  width:13px;height:13px;border-radius:50%;flex:0 0 auto;padding:0;cursor:pointer;border:0;
}
.nh-dot[data-off="1"]{background:var(--border)!important;box-shadow:none!important;border:1px solid var(--faint);opacity:.5}
.nh-row__label{
  background:transparent;border:0;padding:0;cursor:pointer;display:flex;align-items:center;gap:.35rem;
  flex:1;min-width:0;text-align:left;font:inherit;font-size:.78rem;color:var(--text-soft);font-weight:600;
}
.nh-row__label[data-off="1"]{color:var(--faint);text-decoration:line-through}
.nh-row__count{margin-left:auto;color:var(--muted);font-size:.68rem;font-weight:400}
.nh-row__chev{color:var(--faint);font-size:.6rem}
.nh-sub{padding-left:1.1rem;padding-bottom:.25rem;display:flex;flex-direction:column;gap:.05rem}
.nh-sub label{display:flex;align-items:center;gap:.4rem;font-size:.73rem;cursor:pointer;color:var(--text-soft)}
.nh-sub label[data-hid="1"]{color:var(--faint)}
.nh-sub input{margin:0;width:12px;height:12px;cursor:pointer}
/* one row per item: visibility checkbox + the keyboard route to its window */
.nh-subitem{display:flex;align-items:center;gap:.3rem}
.nh-subitem label{flex:1;min-width:0}
.nh-open{
  flex:0 0 auto;font:inherit;font-size:.62rem;font-weight:700;letter-spacing:.04em;
  text-transform:uppercase;cursor:pointer;
  background:transparent;border:1px solid var(--border);color:var(--faint);
  border-radius:5px;padding:.05rem .3rem;
}
.nh-open:hover,.nh-open:focus-visible{color:var(--accent);border-color:var(--accent);outline:none}
.nh-reset{
  margin-top:.5rem;width:100%;background:var(--border);border:1px solid var(--border-strong);
  color:var(--muted);border-radius:8px;padding:.3rem .5rem;cursor:pointer;font:inherit;font-size:.7rem;font-weight:600;
}
.nh-reset:hover{color:#fff}
.nh-hint{margin-top:.4rem;font-size:.63rem;color:var(--faint);line-height:1.35}

/* ---------- node info card (hover/focus feedback, no JS tooltips) ---------- */
.nh-tip{
  position:absolute;z-index:5;pointer-events:none;
  background:var(--surface);border:1px solid var(--border);border-radius:10px;
  padding:.4rem .6rem;font-size:.78rem;color:var(--text);
  backdrop-filter:blur(14px);-webkit-backdrop-filter:blur(14px);
  box-shadow:var(--shadow-soft);max-width:16rem;
}
.nh-tip[hidden]{display:none}
.nh-tip b{display:block;font-weight:700}
.nh-tip span{color:var(--muted);font-size:.72rem}

/* ---------- screens panel: grid inside a window ---------- */
.pn-figs{display:grid;grid-template-columns:repeat(auto-fill,minmax(180px,1fr));gap:.7rem;margin:0;padding:0;list-style:none}
.pn-figs img{aspect-ratio:16/10;object-fit:cover;width:100%;border:1px solid var(--border);border-radius:8px;background:#111}

/* ---------- responsive ---------- */
@media(max-width:820px){
  /* The hint is a MOUSE hint. On a phone it described gestures that do not
     exist there ("scroll to zoom"), so it was replaced with tap-accurate wording
     in JS — see sarahTouchHint(). Hidden here only if that swap has not run. */
  .app-topbar__hint{display:none}
  .app-topbar__hint--touch{display:block}
  .nh-legend{left:8px;bottom:8px}
  .app-tools .tool-btn{padding:.3rem .45rem;font-size:.74rem}

  /* Keep the toolbar to TWO rows on a phone.
     Left as-is it wrapped to three (brand / hint / buttons = 126px), which is
     over a fifth of an 820px-tall screen spent on chrome before the map even
     starts. Trimming the padding and letting the hint run to one line brings it
     back down; the hint is the least important row, so it is the one that gives
     way (it truncates with an ellipsis rather than wrapping). */
  .app-topbar__in{padding:.3rem .5rem;gap:.35rem}
  /* Brand and hint share the first row. The hint used to claim a whole line of
     its own purely because the brand's `margin-right:auto` pushed it, costing
     ~19px of a short screen for a sentence nobody needs twice. nowrap on the row
     means one of them has to give, and the hint truncates. */
  .app-topbar__in{flex-wrap:wrap;flex-direction:row;align-items:center}
  .brand--mini{margin-right:.4rem}
  .app-topbar__hint--touch{
    font-size:.66rem;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
    flex:1 1 6rem;min-width:0;margin-right:0;
  }
  .app-tools{flex:1 1 100%;gap:.25rem}
}

/* On the narrowest phones the hint is more noise than help — the gestures are
   discoverable by trying them, and the space is worth more than the sentence. */
@media(max-width:430px){
  .app-topbar__hint--touch{display:none}
}
@media(max-width:520px){
  /* Keep the buttons that act on windows; drop the ones that cannot work. */
  .tool-btn[data-compact="hide"]{display:none}
}

/* ---------- touch devices: the desktop hint is wrong ----------
   html.is-touch is set by panels.js from the REAL capability (any-pointer:
   coarse, hover: none, ontouchstart, maxTouchPoints) rather than from the window
   width, because those are different questions: a narrow desktop window still
   has a mouse, and a big tablet still has a touchscreen. The media query in the
   rule below stays as the no-JavaScript fallback. */
.app-topbar__hint--touch{display:none}
html.is-touch .app-topbar__hint{display:none}
html.is-touch .app-topbar__hint--touch{display:block}
html.is-mouse .app-topbar__hint{display:block}
html.is-mouse .app-topbar__hint--touch{display:none}
@media(hover:none){
  .app-topbar__hint{display:none}
  .app-topbar__hint--touch{display:block}
}
/* A mouse has no pinch, so do not advertise it. */
html.is-mouse .app-topbar__hint--touch{display:none!important}
@media(prefers-reduced-motion:reduce){
  .nh-dot,.nh-legend__pill{transition:none}
}

/* ---------- the map yields to an open sheet (phones) ----------
   A sheet covers the viewport, so anything floating over the map is either
   hidden behind it or pokes out at the edges. Hide those while a sheet is open,
   and let them return the moment it closes. Desktop is unaffected: windows there
   are smaller than the canvas, and the legend is useful beside them. */
@media(max-width:820px){
  body.has-open-window .nh-legend{display:none}
}

/* ---- free download counts, in the legend ----
   Two numbers and a date, tucked under the group rows. Deliberately quiet: it is
   a stat to glance at, not a headline, so it uses the same faint type as the
   hint text rather than competing with the node list above it. */
.nh-dl{margin:.55rem 0 .1rem;padding-top:.5rem;border-top:1px solid var(--border)}
.nh-dl__head{
  font-family:var(--mono);font-size:.6rem;font-weight:700;letter-spacing:.14em;
  text-transform:uppercase;color:var(--accent);
  display:flex;align-items:baseline;gap:.4rem;margin:0 0 .3rem;
}
.nh-dl__total{margin-left:auto;font-weight:400;letter-spacing:.04em;color:var(--faint);text-transform:none}
.nh-dl__row{display:flex;align-items:baseline;gap:.45rem;font-size:.72rem;line-height:1.7}
.nh-dl__name{color:var(--muted);min-width:4.2rem}
.nh-dl__n{font-family:var(--mono);font-weight:700;color:var(--text);min-width:2.4rem}
.nh-dl__when{color:var(--faint);font-size:.66rem;margin-left:auto}

/* ---------- free-floating social bubbles ----------
   The four bubbles are drawn on the canvas (assets/js/neural.js) and need almost
   no CSS: their fill, edge and glow are SVG attributes because they zoom with the
   viewBox. Only two things are styled here.

   1. The focus ring. The bubbles are <a> elements, so they are reachable with
      Tab and activated with Enter. The SVG default focus ring is nearly
      invisible on this dark ground, so a keyboard user gets an explicit white
      ring instead — the same visual language the feature bubbles use on hover.
   2. The legend list, which spells out the four destinations as text. */
#nh-socials a{cursor:pointer;outline:none}
#nh-socials a:focus-visible .nh-soc-edge{
  stroke:#fff;stroke-width:.3;
}
#nh-socials a:focus-visible .nh-soc-glow{opacity:1}

.nh-socs{margin:.55rem 0 .1rem;padding-top:.5rem;border-top:1px solid var(--border)}
.nh-socs__head{
  font-family:var(--mono);font-size:.6rem;font-weight:700;letter-spacing:.14em;
  text-transform:uppercase;color:#b14dff;
  margin:0 0 .3rem;
}
.nh-socs__row{
  display:flex;align-items:center;gap:.35rem;
  font-size:.72rem;color:var(--text-soft);text-decoration:none;
  padding:.18rem .3rem;border-radius:6px;
}
.nh-socs__row span{margin-left:auto;color:var(--faint);font-size:.65rem}
.nh-socs__row:hover,.nh-socs__row:focus-visible{
  color:#fff;background:rgba(177,77,255,.16);outline:none;
}
.nh-socs__row:hover span,.nh-socs__row:focus-visible span{color:#d9a6ff}
