{"version":3,"sources":["nav-ui.mjs"],"sourcesContent":["// THE NAVIGATION CHROME'S OWN RULES (the owner's Navigation Overhaul, confirmed Oct 7, part 2: the breadcrumb in the\n// dock pill, the edge arrow to your avatar, the Nearby list folded into the info panel, Search as a menu panel, the\n// on-demand map, the screen-reader announcements, and \"outside scout the avatar should always be 'with' the player\").\n// The chrome is drawn in app.js; what it DECIDES lives here, pure, so tests/nav-ui.test.mjs can hold each decision to\n// what was picked without a browser: which crumbs a view has and where each one goes, where on the screen's edge the\n// arrow to an off-screen avatar stands, when looking somewhere has left the avatar behind, what a search matches and in\n// which order, what is announced, and how a map's points fit its box.\n//\n// No imports and no DOM: this file runs in the page, in node for the tests, and on Safari 15 (the iPad Air 2 floor),\n// so nothing newer than the rest of the game may appear in it.\n\n// ---- ADDRESSES -------------------------------------------------------------------------------------------------------\n// galaxy.system.star.planet.moon, with the a/b of a binary pair and the c<N> of a transient (whereabouts.mjs ADDR_RE),\n// and galaxy.system.v<id>, a player-built vessel (the owner's spec, Oct 12).\nexport const NAV_ADDR_RE = /^(?:[0-9]+[ab]?(\\.c?[0-9]+[ab]?)*|[0-9]+\\.[0-9]+\\.v[1-9][0-9]{0,11})$/;\n// A TRAILING .0 IS A FRAMING, NOT A PLACE (whereabouts.mjs): x.0 is x seen with its moons, g.s.0 the system seen whole.\nexport const placeOf = (a) => { const s = String(a == null ? '' : a).trim(); return /\\.0$/.test(s) ? s.slice(0, -2) : s; };\nconst partsOf = (a) => { const s = placeOf(a); return s ? s.split('.') : []; };\nconst num = (s) => String(parseInt(s, 10));\n\n// ---- A LINK TO SOMEWHERE THAT IS NOT THERE (QA F-109) -----------------------------------------------------------------\n// A mistyped or broken ?pos used to open SOMEWHERE without a word: 721008.99999 (the galaxy has 9,988 systems) opened the\n// galaxy's card, 721008.3201.9.9 the system's, \"abc\" an unrelated galaxy while the readout said \"abc\". This says what is\n// wrong with an address as far as the address alone can tell, and the nearest real place to show instead: null when it is\n// a place (or might be, below the system, where only the generated system knows), else { fix, what } — `fix` the address\n// to open (null: there is nothing to keep, open the player's own place) and `what` the kind of place `fix` is. `starsIn`\n// is galaxy-shape's, handed in so this file keeps no imports. Body ordinals are the system view's to check (it alone has\n// the system built); this catches the shapes no system has: a star segment other than the primary (1), the companion (2),\n// a close pair's shared planets (0) or a passing rock (cN), and anything below a moon, which nothing orbits.\nexport function linkPlaceProblem(addr, starsIn) {\n  const raw = String(addr == null ? '' : addr).trim();\n  if (!raw) return null;\n  let s = raw; while (/\\.0$/.test(s)) s = s.slice(0, -2);                   // framings collapse to the place they frame\n  if (!NAV_ADDR_RE.test(s)) return { fix: null, what: null };\n  const p = s.split('.');\n  if (!/^[0-9]+$/.test(p[0]) || !(Number(p[0]) >= 1)) return { fix: null, what: null };\n  if (p.length === 1) return null;\n  const n = Number(p[1]), most = typeof starsIn === 'function' ? Number(starsIn(p[0])) : Infinity;\n  if (!/^[0-9]+$/.test(p[1]) || !(n >= 1 && n <= most)) return { fix: p[0], what: 'galaxy' };\n  if (p.length === 2) return null;\n  const sys = p[0] + '.' + p[1];\n  if (/^c[0-9]+[ab]?$/.test(p[2])) return p.length === 3 ? null : { fix: sys, what: 'system' };\n  if (/^v[1-9][0-9]*$/.test(p[2])) return null;   // a vessel: only its record knows whether it is there (the system view says when it is not)\n  if (p[2] !== '0' && p[2] !== '1' && p[2] !== '2') return { fix: sys, what: 'system' };   // 0: a close binary's shared planets (system-view tagHosted)\n  if (p.length > 5 || p.slice(3).some((x) => !/^[0-9]+[ab]?$/.test(x))) return { fix: sys, what: 'system' };\n  return null;\n}\n\n// ---- THE BREADCRUMB: \"Inside the dock pill\" (breadcrumb = pill) --------------------------------------------------------\n// The levels above the one you are looking at, each a crumb that goes there; the place itself is the pill's own first\n// segment, which already names it. `view` is the camera's level: 'universe', 'galaxy', 'system' or 'foot'. `pos` is the\n// camera's address. In the galaxy view a selected star is the subject, so the galaxy is a level above it; in a system\n// a focused body is, so the system is. On foot the world is below its orbit, which is a level you can go back up to.\n// `compact` (a phone) keeps only the nearest level up, as \"‹ that\".\nexport const NAV_VIEWS = Object.freeze(['universe', 'galaxy', 'system', 'foot']);\nexport function crumbTrail({ view, pos, compact, nameOf } = {}) {\n  const p = partsOf(pos);\n  const g = p[0] || null, s = p[1] ? num(p[1]) : null, body = p.length >= 3 ? p.join('.') : null;\n  const named = (addr, fallback) => { try { const n = nameOf && addr ? nameOf(addr) : null; return n ? String(n) : fallback; } catch (e) { return fallback; } };\n  const U = { level: 'universe', label: 'Universe', title: 'The universe: every galaxy near this one' };\n  const G = g ? { level: 'galaxy', label: g, title: 'Galaxy ' + g, addr: g } : null;\n  const S = (g && s) ? { level: 'system', label: s, title: 'System ' + s, addr: g + '.' + s } : null;\n  let up = [], here = null;\n  if (view === 'universe' || !g) { up = []; here = { level: 'universe', label: 'Universe' }; }\n  else if (view === 'galaxy') {\n    if (S) { up = [U, G]; here = { level: 'system', label: 'System ' + s, addr: S.addr }; }\n    else { up = [U]; here = { level: 'galaxy', label: 'Galaxy ' + g, addr: g }; }\n  } else if (view === 'system') {\n    if (body && S) { up = [U, G, S]; here = { level: 'world', label: named(body, body), addr: body }; }\n    else if (S) { up = [U, G]; here = { level: 'system', label: 'System ' + s, addr: S.addr }; }\n    else { up = [U]; here = { level: 'galaxy', label: 'Galaxy ' + g, addr: g }; }\n  } else if (view === 'foot') {\n    const W = body ? { level: 'world', label: 'Orbit', title: 'Back up to orbit over ' + named(body, body), addr: body } : null;\n    up = [U, G, S, W].filter(Boolean);\n    here = { level: 'foot', label: named(body, body || 'On foot'), addr: body };\n  }\n  up = up.filter(Boolean);\n  if (compact && up.length) up = [up[up.length - 1]];\n  return { up, here };\n}\n// THE CARD'S BREADCRUMB (the owner's play review, Oct 23, u4: \"\\\"Up a level\\\" and \\\"Back\\\" live only on the card, beside a\n// breadcrumb (Galaxy › System › Planet › Moon) that jumps anywhere\"). The levels above what the card is about, each one a\n// place to jump to, and the card's own place last (`here`). From the card's subject: its kind (the card's: 'galaxy',\n// 'star', 'sys', 'starBody', 'planetSys', 'body' or 'vessel') and address. A star of the system is not a level of its\n// own (the example names none); a vessel hangs from the body it orbits (`host`). `nameOf(addr)` gives a world's name\n// where it has one; a planet or a moon is otherwise called by its kind and number.\n//   → [{ level: 'universe'|'galaxy'|'system'|'body', label, addr, here? }, …]\nexport function cardCrumbs({ kind, addr, host = null, nameOf = null, galaxyId = null } = {}) {\n  const p = partsOf(addr);\n  const named = (a, fallback) => { try { const n = nameOf && a ? nameOf(a) : null; return n ? String(n) : fallback; } catch (e) { return fallback; } };\n  const g = kind === 'galaxy' ? String(galaxyId != null ? galaxyId : (p[0] || '')) : (p[0] || null);\n  const out = [];\n  if (kind === 'galaxy') { out.push({ level: 'universe', label: 'Universe' }, { level: 'galaxy', label: 'Galaxy ' + g, addr: g, here: true }); return out; }\n  if (!g) return out;\n  out.push({ level: 'galaxy', label: 'Galaxy ' + g, addr: g });\n  if (p.length < 2) { out[0].here = true; return out; }\n  const sys = g + '.' + p[1];\n  out.push({ level: 'system', label: 'System ' + num(p[1]), addr: sys });\n  if (kind === 'star' || kind === 'sys' || p.length < 3) { out[1].here = true; return out; }\n  if (kind === 'vessel') {\n    const hp = partsOf(host);\n    if (hp.length >= 4) out.push({ level: 'body', label: named(hp.join('.'), (hp.length >= 5 ? 'Moon ' : 'Planet ') + num(hp[hp.length - 1])), addr: hp.join('.') });\n    out.push({ level: 'body', label: named(p.join('.'), 'Station'), addr: p.join('.'), here: true });\n    return out;\n  }\n  if (kind === 'starBody' || p.length === 3) { out.push({ level: 'body', label: named(p.join('.'), 'Star ' + num(p[2])), addr: p.join('.'), here: true }); return out; }\n  const planet = p.slice(0, 4).join('.');\n  if (kind === 'planetSys') { out.push({ level: 'body', label: named(planet, 'Planet ' + num(p[3])) + ' and its moons', addr: planet + '.0', here: true }); return out; }\n  out.push({ level: 'body', label: named(planet, 'Planet ' + num(p[3])), addr: planet });\n  if (p.length >= 5) { const moon = p.slice(0, 5).join('.'); out.push({ level: 'body', label: named(moon, 'Moon ' + num(p[4])), addr: moon }); }\n  out[out.length - 1].here = true;\n  return out;\n}\n\n// \"Up a level\" (Esc in flight): the nearest crumb above, or null at the top.\nexport function levelAbove(view, pos) {\n  const { up } = crumbTrail({ view, pos });\n  return up.length ? up[up.length - 1] : null;\n}\n\n// ---- OUTSIDE SCOUT THE AVATAR IS WITH YOU (home = today, with the owner's note) ----------------------------------------\n// Whereabouts are a system, or a world once you land (whereabouts.mjs), and looking is free. So the camera can look\n// somewhere the avatar is not, and the owner's rule is that outside scout it never does: looking somewhere ELSE is\n// scouting. \"Somewhere else\" is another galaxy, or another system than the one you are in. The galaxy you are in, seen\n// whole, is not elsewhere (the figure stands on its star in it), and neither is any body of your own system (landing in\n// your own system is free, so the figure follows the focus there: system-view hereBodyAt).\nexport function apartFromAvatar(viewAddr, at) {\n  const v = partsOf(viewAddr), a = partsOf(at);\n  if (!v.length || !a.length) return false;            // nothing to compare: nothing to say they are apart\n  if (num(v[0]) !== num(a[0])) return true;            // another galaxy\n  if (v.length < 2) return false;                      // this galaxy, seen whole\n  return a.length < 2 || num(v[1]) !== num(a[1]);      // another system (or any, when you are between stars)\n}\n\n// ---- THE EDGE ARROW: \"Marker plus an edge arrow\" (avatar = edge) -------------------------------------------------------\n// Where the arrow to an off-screen avatar stands: on the edge of the screen inset by `inset`, along the line from the\n// screen's centre toward the avatar, and which way it points (radians, 0 = right, y down as the screen has it). `p` is\n// the avatar's screen position in CSS pixels from the viewport's top-left, and `behind` when it is behind the camera,\n// where a projection lands mirrored through the centre — so the line is turned round. Null while it is on screen.\nexport function edgeArrowAt(p, w, h, inset = 28) {\n  if (!p || !Number.isFinite(p.x) || !Number.isFinite(p.y) || !(w > 0) || !(h > 0)) return null;\n  const cx = w / 2, cy = h / 2, hw = cx - inset, hh = cy - inset;\n  if (!(hw > 0) || !(hh > 0)) return null;\n  let dx = p.x - cx, dy = p.y - cy;\n  if (p.behind) { dx = -dx; dy = -dy; if (Math.abs(dx) < 1e-9 && Math.abs(dy) < 1e-9) dy = 1; }\n  else if (p.x >= inset && p.x <= w - inset && p.y >= inset && p.y <= h - inset) return null;   // on screen: the marker says it\n  const kx = Math.abs(dx) > 1e-9 ? hw / Math.abs(dx) : Infinity, ky = Math.abs(dy) > 1e-9 ? hh / Math.abs(dy) : Infinity;\n  const k = Math.min(kx, ky);\n  if (!Number.isFinite(k)) return null;\n  const x = cx + dx * k, y = cy + dy * k;\n  const side = kx <= ky ? (dx < 0 ? 'left' : 'right') : (dy < 0 ? 'top' : 'bottom');\n  return { x, y, angle: Math.atan2(dy, dx), side };\n}\n\n// ---- SEARCH: \"One search field\" (search = omni, as a new tab in the menu) ----------------------------------------------\n// What was typed, read as a place where it can be one: a share or game link (anything carrying pos=), a full address\n// (875150.6561.1.2), \"galaxy 875150\" or \"system 6561\", or a bare number, which may be either. Always the text too.\nexport function parseNavQuery(q) {\n  const s = String(q == null ? '' : q).trim();\n  const out = { text: s.toLowerCase(), addr: null, link: null, num: null, kind: null };\n  if (!s) return out;\n  const m = /[?&](?:pos|position)=([^&#\\s]+)/i.exec(s);\n  if (m) {\n    let v = m[1]; try { v = decodeURIComponent(v); } catch (e) { /* the raw text, then */ }\n    v = placeOf(v);\n    if (NAV_ADDR_RE.test(v)) { out.link = v; out.addr = v; return out; }\n  }\n  const named = /^(galaxy|system|star)\\s*#?\\s*([0-9]+)$/i.exec(s);\n  if (named) { out.num = num(named[2]); out.kind = named[1].toLowerCase() === 'galaxy' ? 'galaxy' : 'system'; return out; }\n  if (/^[0-9]+$/.test(s)) { out.num = num(s); return out; }\n  if (s.includes('.') && NAV_ADDR_RE.test(placeOf(s))) out.addr = placeOf(s);\n  return out;\n}\n// The places a query names by itself, before any list is searched: the address or link, or for a number the system of\n// that number in the galaxy you are looking at (when it has that many) and the galaxy of that number.\nexport function queryPlaces(parsed, ctx = {}) {\n  const p = parsed || {}, out = [];\n  if (p.addr) {\n    const d = p.addr.split('.').length;\n    out.push({ kind: p.link ? 'link' : 'address', name: d === 1 ? 'Galaxy ' + p.addr : d === 2 ? 'System ' + p.addr.split('.')[1] : p.addr,\n               addr: p.addr, sub: p.link ? 'from the link' : 'address' });\n  } else if (p.num) {\n    const n = parseInt(p.num, 10), g = ctx.galaxy ? String(ctx.galaxy) : null;\n    const fits = !(ctx.starCount > 0) || n <= ctx.starCount;\n    if (g && p.kind !== 'galaxy' && n > 0 && fits) out.push({ kind: 'system', name: 'System ' + n, addr: g + '.' + n, sub: 'in galaxy ' + g });\n    if (p.kind !== 'system' && n > 0) out.push({ kind: 'galaxy', name: 'Galaxy ' + n, addr: String(n), sub: 'galaxy' });\n  }\n  return out;\n}\n// Which kind of result leads when two match equally well: what you hold, then what you kept, then people.\nexport const SEARCH_KINDS = Object.freeze(['address', 'link', 'system', 'galaxy', 'claim', 'bookmark', 'friend', 'friend-world', 'world']);\n// How well one entry matches the text: its name exactly, then from its start, then a word in it from its start, then\n// anywhere in it; then its address from its start, then anywhere; then its other words (an owner, a note). 0 is no match.\nexport function searchScore(text, e) {\n  const t = String(text || '').trim().toLowerCase();\n  if (!t || !e) return 0;\n  const name = String(e.name || '').toLowerCase(), addr = String(e.addr || '').toLowerCase();\n  const also = String((e.also || '') + ' ' + (e.sub || '')).toLowerCase();\n  if (name === t) return 100;\n  if (name.startsWith(t)) return 80;\n  if (name.split(/[\\s·.,'’-]+/).some((w) => w && w.startsWith(t))) return 60;\n  if (addr && addr === t) return 95;\n  if (addr && addr.startsWith(t)) return 50;\n  if (name.includes(t)) return 40;\n  if (addr && addr.includes(t)) return 30;\n  if (also.includes(t)) return 20;\n  return 0;\n}\n// THE RESULTS, best first, one per place: the query's own places lead, then every entry that matches, ranked by\n// searchScore, then by kind (SEARCH_KINDS), then by name. A place reached two ways (a bookmark of your own claim) is\n// listed once, as the better of the two; a friend with nowhere to go (offline) is listed by name. At most `limit`.\nexport function rankSearch(q, entries, ctx = {}, limit = 20) {\n  const parsed = parseNavQuery(q);\n  const kindAt = (k) => { const i = SEARCH_KINDS.indexOf(k); return i < 0 ? SEARCH_KINDS.length : i; };\n  const own = queryPlaces(parsed, ctx).map((e) => ({ ...e, score: 1000 }));\n  const found = [];\n  for (const e of entries || []) {\n    if (!e || !(e.name || e.addr)) continue;\n    const s = searchScore(parsed.text, e);\n    if (s > 0) found.push({ ...e, score: s });\n  }\n  found.sort((a, b) => (b.score - a.score) || (kindAt(a.kind) - kindAt(b.kind)) || String(a.name || '').localeCompare(String(b.name || '')));\n  const seen = new Set(), out = [];\n  for (const e of own.concat(found)) {\n    const key = e.addr ? 'a:' + placeOf(e.addr) : 'n:' + e.kind + ':' + String(e.name || '').toLowerCase();\n    if (seen.has(key)) continue;\n    seen.add(key);\n    out.push(e);\n    if (out.length >= limit) break;\n  }\n  return out;\n}\n\n// ---- THE NEARBY LIST: folded into the info panel (nearby = drawer, with the owner's note) ------------------------------\n// The n nearest of a list that carries its distance as `d`, nearest first, ties by name; the origin itself (d 0) leads.\nexport function nearestRows(rows, n = 12) {\n  return (rows || []).filter((r) => r && Number.isFinite(r.d))\n    .sort((a, b) => (a.d - b.d) || String(a.name || '').localeCompare(String(b.name || ''))).slice(0, n);\n}\n// A fare as the list shows it: one decimal, with the bolt; \"here\" for nowhere to go, nothing when unknown.\nexport const fareText = (cost) => (cost == null || !Number.isFinite(cost)) ? '' : cost <= 0 ? 'here' : (Math.round(cost * 10) / 10) + '⚡';\n\n// ---- SCREEN READER: \"Names, announcements and real buttons\" (sr = live) ------------------------------------------------\n// What the polite live region says when the view changes level, and when the subject changes within a level.\nexport function announceView(view, label) {\n  const l = String(label || '').trim();\n  if (view === 'universe') return 'Universe view' + (l && l !== 'Universe' ? ', ' + l : '');\n  if (view === 'foot') return 'On foot' + (l ? ' on ' + l : '');\n  return l || (view === 'system' ? 'System view' : 'Galaxy view');\n}\nexport function announceSelection(label, cost, here) {\n  const l = String(label || '').trim();\n  if (!l) return '';\n  if (here) return l + ' selected, you are here';\n  if (cost == null || !Number.isFinite(cost)) return l + ' selected';\n  return l + ' selected, ' + (Math.round(cost * 10) / 10) + ' energy to travel';\n}\n\n// ---- TEXT ON A TINTED LABEL (QA F-114) -------------------------------------------------------------------------------\n// Black or white text on a world's, a star's or a galaxy's own colour, WHICHEVER HAS MORE CONTRAST BY WCAG'S MEASURE\n// (relative luminance in linear light, contrast (L1 + 0.05) / (L2 + 0.05)). The pill and the labels used a perceived-\n// brightness cut at 0.6, so most mid-tones took white: white on a sage world's rgb(118,150,108) was 3.3:1 where #111 is\n// 5.7:1, and a saturated orange-red 2.9:1 against 6.5:1. One rule for the dock pill, the labels (tintLabel) and the card's\n// main button. `hex` is '#rrggbb' or 'rrggbb'; anything else gets the light ink, as an untinted label has. `dark` and\n// `light` are the two inks to choose between (#111 and #fff unless the caller wears its own).\nconst _lin = (c) => { const s = c / 255; return s <= 0.04045 ? s / 12.92 : Math.pow((s + 0.055) / 1.055, 2.4); };\nexport function relLuminance(hex) {\n  let h = String(hex == null ? '' : hex).replace(/^#/, '');\n  if (/^[0-9a-f]{3}$/i.test(h)) h = h.replace(/./g, '$&$&');           // #111 is #111111\n  if (!/^[0-9a-f]{6}$/i.test(h)) return null;\n  const n = parseInt(h, 16);\n  return 0.2126 * _lin((n >> 16) & 255) + 0.7152 * _lin((n >> 8) & 255) + 0.0722 * _lin(n & 255);\n}\nexport const contrastRatio = (la, lb) => (Math.max(la, lb) + 0.05) / (Math.min(la, lb) + 0.05);\n// AND AA EVERYWHERE (QA F-59): between #111 and #fff a mid tone (L ≈ 0.19, where the two inks tie) only reaches about\n// 4.35 : 1, under the 4.5 : 1 that small text needs. There, and wherever the caller's own pair falls short, the ink goes\n// to pure black or pure white on the same side, and one of those always clears 4.58 : 1. Callers that switch other\n// styling on which side was picked (a text shadow, a class) ask isDarkInk(ink), never compare against one spelling.\nexport function inkOn(hex, dark = '#111', light = '#fff') {\n  const L = relLuminance(hex);\n  if (L == null) return light;\n  const cd = contrastRatio(L, relLuminance(dark)), cl = contrastRatio(L, relLuminance(light));\n  if (Math.max(cd, cl) >= 4.5) return cd >= cl ? dark : light;\n  return contrastRatio(L, 0) >= contrastRatio(L, 1) ? '#000000' : '#ffffff';\n}\nexport const isDarkInk = (ink) => { const L = relLuminance(ink); return L != null && L < 0.5; };\n// The contrast of two colours as WCAG measures it, for tests and callers that hold hex strings.\nexport const contrastOf = (a, b) => contrastRatio(relLuminance(a), relLuminance(b));\n"],"mappings":"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","names":[],"file":"nav-ui.mjs"}