threadnote 0.5.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,3 +1,7 @@
1
+ <p align="center">
2
+ <img src="./docs/threadnote-logo.svg" alt="Threadnote logo" width="200">
3
+ </p>
4
+
1
5
  # Threadnote
2
6
 
3
7
  `threadnote` is a safe local workflow for using [OpenViking](https://openviking.ai/) as shared, agent-neutral context for development work.
@@ -33736,6 +33736,8 @@ var TEAMS_FILE_VERSION = 1;
33736
33736
  var SHARED_SEGMENT = "shared";
33737
33737
  var DEFAULT_GIT_REMOTE_NAME = "origin";
33738
33738
  var SCRUBBER_PATTERNS = [
33739
+ // Credentials: never redactable. Blocking is the only safe response —
33740
+ // automated redaction risks false negatives that leave material in git.
33739
33741
  { name: "private key", regex: /-----BEGIN [A-Z ]*PRIVATE KEY-----/ },
33740
33742
  { name: "API key (sk-...)", regex: /\bsk-[A-Za-z0-9_-]{16,}/ },
33741
33743
  { name: "GitHub token", regex: /\bgh[pousr]_[A-Za-z0-9_]{16,}/ },
@@ -33748,8 +33750,35 @@ var SCRUBBER_PATTERNS = [
33748
33750
  { name: "AWS access key", regex: /\bAKIA[0-9A-Z]{16}\b/ },
33749
33751
  // Slack tokens: xoxa/xoxb/xoxc (configuration)/xoxd (legacy user cookie)/
33750
33752
  // xoxe (refresh)/xoxp/xoxr/xoxs, with optional -N- segment for the workspace tier.
33751
- { name: "Slack token", regex: /\bxox[abcdeprs](?:-\d-)?[A-Za-z0-9._-]{10,}/i }
33753
+ { name: "Slack token", regex: /\bxox[abcdeprs](?:-\d-)?[A-Za-z0-9._-]{10,}/i },
33754
+ // Soft leaks: block by default (so the agent sees them and decides), but
33755
+ // allow opt-in redaction so curated memories with incidental matches can
33756
+ // ship without a manual rewrite. Local home paths are the recurring
33757
+ // real-world leak; the regexes greedily consume the whole path segment
33758
+ // (including subdirectories) up to whitespace or common closing punctuation
33759
+ // so redaction collapses an entire path to a single placeholder rather than
33760
+ // leaving the subpath visible.
33761
+ { name: "macOS home path", placeholder: "<local-path>", regex: /\/Users\/[^\s)>"'`,]+/ },
33762
+ { name: "linux home path", placeholder: "<local-path>", regex: /\b\/home\/[^\s)>"'`,]+/ }
33752
33763
  ];
33764
+ function applyScrubber(content, { redact }) {
33765
+ let cleaned = content;
33766
+ const redactions = [];
33767
+ for (const pattern of SCRUBBER_PATTERNS) {
33768
+ if (!pattern.regex.test(cleaned)) {
33769
+ continue;
33770
+ }
33771
+ if (!pattern.placeholder || !redact) {
33772
+ return { blocker: pattern.name, cleaned: content, redactions: [] };
33773
+ }
33774
+ const flags = pattern.regex.flags.includes("g") ? pattern.regex.flags : `${pattern.regex.flags}g`;
33775
+ const globalRegex = new RegExp(pattern.regex.source, flags);
33776
+ const matches = cleaned.match(globalRegex) ?? [];
33777
+ cleaned = cleaned.replace(globalRegex, pattern.placeholder);
33778
+ redactions.push({ count: matches.length, name: pattern.name });
33779
+ }
33780
+ return { cleaned, redactions };
33781
+ }
33753
33782
  function normalizeTeamName(input) {
33754
33783
  const candidate = (input ?? "default").trim();
33755
33784
  if (!candidate) {
@@ -33852,8 +33881,26 @@ function vikingUriToWorktreeRelative(config2, uri, team) {
33852
33881
  }
33853
33882
  return uri.slice(prefix.length);
33854
33883
  }
33855
- function scrubberBlocker(content) {
33856
- return SCRUBBER_PATTERNS.find((pattern) => pattern.regex.test(content))?.name;
33884
+ function stripPersonalProvenance(content) {
33885
+ const lines = content.split("\n");
33886
+ let headerEnd = lines.length;
33887
+ for (let index = 0; index < lines.length; index += 1) {
33888
+ if (lines[index].trim() === "") {
33889
+ headerEnd = index;
33890
+ break;
33891
+ }
33892
+ }
33893
+ const cleaned = [];
33894
+ for (let index = 0; index < headerEnd; index += 1) {
33895
+ if (/^(?:supersedes|archived_from):\s/.test(lines[index])) {
33896
+ continue;
33897
+ }
33898
+ cleaned.push(lines[index]);
33899
+ }
33900
+ for (let index = headerEnd; index < lines.length; index += 1) {
33901
+ cleaned.push(lines[index]);
33902
+ }
33903
+ return cleaned.join("\n");
33857
33904
  }
33858
33905
  async function ensureSharedDirectoryChain(config2, ov, memoryUri, dryRun) {
33859
33906
  const directoryUri = parentUri(memoryUri);
@@ -34230,15 +34277,19 @@ function registerTools(server, config2) {
34230
34277
  "share_publish",
34231
34278
  {
34232
34279
  annotations: { readOnlyHint: false, destructiveHint: true },
34233
- description: "Publish a personal memory into a team's shared memories git repo. Reads the memory, refuses publish if it matches secret patterns, copies it into the shared subtree, removes the personal original, and commits/pushes. Default team is used unless team is provided.",
34280
+ description: "Publish a personal memory into a team's shared memories git repo. Reads the memory, strips local-only provenance frontmatter (supersedes:, archived_from:), refuses publish if it matches secret patterns, copies it into the shared subtree, removes the personal original, and commits/pushes. Default team is used unless team is provided. Pass preview=true to return the would-be-published bytes without writing or committing.",
34234
34281
  inputSchema: {
34235
34282
  message: external_exports.string().optional().describe('Commit message override; defaults to "share: publish <path>"'),
34283
+ preview: external_exports.boolean().optional().describe(
34284
+ "Return the bytes that would land in the shared git repo (after frontmatter strip and redaction) without writing or committing. Use this to inspect the body before publishing."
34285
+ ),
34236
34286
  push: external_exports.boolean().optional().describe("Push to remote after committing; defaults to true"),
34287
+ redact: external_exports.boolean().optional().describe("Replace soft-leak matches (local paths) with placeholders and continue; credentials still block."),
34237
34288
  team: external_exports.string().optional().describe("Team name; defaults to the configured default team"),
34238
34289
  uri: external_exports.string().optional().describe("Required viking:// memory URI to publish")
34239
34290
  }
34240
34291
  },
34241
- async ({ message, push, team, uri }) => {
34292
+ async ({ message, preview, push, redact, team, uri }) => {
34242
34293
  const checkedUri = requiredVikingUri(
34243
34294
  uri,
34244
34295
  "share_publish",
@@ -34247,7 +34298,7 @@ function registerTools(server, config2) {
34247
34298
  if (!checkedUri.ok) {
34248
34299
  return checkedUri.error;
34249
34300
  }
34250
- return runSharePublishTool(config2, checkedUri.value, { message, push, team });
34301
+ return runSharePublishTool(config2, checkedUri.value, { message, preview, push, redact, team });
34251
34302
  }
34252
34303
  );
34253
34304
  }
@@ -34408,16 +34459,14 @@ function registerStoreTool(server, config2, name, description) {
34408
34459
  project: normalizeOptionalMetadata(project),
34409
34460
  sourceAgentClient: sourceAgentClient ?? "mcp",
34410
34461
  status: status ?? "active",
34411
- supersedes: checkedReplaceUri.value,
34412
34462
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
34413
34463
  topic: normalizeOptionalMetadata(topic)
34414
34464
  };
34415
- return writeDurableMemory(
34416
- config2,
34417
- formatMemoryDocument("MEMORY", metadata, checkedText.value),
34465
+ return writeDurableMemory(config2, {
34466
+ bodyText: checkedText.value,
34418
34467
  metadata,
34419
- checkedReplaceUri.value
34420
- );
34468
+ replaceUri: checkedReplaceUri.value
34469
+ });
34421
34470
  }
34422
34471
  );
34423
34472
  }
@@ -34458,12 +34507,10 @@ function registerArchiveTool(server, config2, name, description) {
34458
34507
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
34459
34508
  topic: normalizeOptionalMetadata(topic)
34460
34509
  };
34461
- const archiveResult = await writeDurableMemory(
34462
- config2,
34463
- formatMemoryDocument("MEMORY", metadata, ["Archived original Threadnote memory.", "", original].join("\n")),
34464
- metadata,
34465
- void 0
34466
- );
34510
+ const archiveResult = await writeDurableMemory(config2, {
34511
+ bodyText: ["Archived original Threadnote memory.", "", original].join("\n"),
34512
+ metadata
34513
+ });
34467
34514
  if (archiveResult.isError === true) {
34468
34515
  return archiveResult;
34469
34516
  }
@@ -34486,13 +34533,18 @@ Archive stored, but original memory is still processing. Retry later with forget
34486
34533
  }
34487
34534
  );
34488
34535
  }
34489
- async function writeDurableMemory(config2, memory, metadata, replaceUri) {
34536
+ async function writeDurableMemory(config2, params) {
34490
34537
  try {
34491
34538
  const ov = await requiredOpenVikingCli();
34492
- const directoryUri = memoryDirectoryUri(config2, metadata);
34539
+ const directoryUri = memoryDirectoryUri(config2, params.metadata);
34493
34540
  await ensureMemoryDirectory(ov, config2, directoryUri);
34494
- const memoryUri = memoryUriFor(config2, memory, metadata);
34495
- const writeMode = await memoryWriteMode(ov, config2, memoryUri, metadata);
34541
+ const candidateMetadata = { ...params.metadata, supersedes: params.replaceUri };
34542
+ const candidateMemory = formatMemoryDocument("MEMORY", candidateMetadata, params.bodyText);
34543
+ const memoryUri = memoryUriFor(config2, candidateMemory, candidateMetadata);
34544
+ const isInPlaceUpdate = params.replaceUri !== void 0 && params.replaceUri === memoryUri;
34545
+ const finalMetadata = isInPlaceUpdate ? { ...params.metadata, supersedes: void 0 } : candidateMetadata;
34546
+ const memory = isInPlaceUpdate ? formatMemoryDocument("MEMORY", finalMetadata, params.bodyText) : candidateMemory;
34547
+ const writeMode = await memoryWriteMode(ov, config2, memoryUri, finalMetadata);
34496
34548
  const result = await runOpenVikingWriteWithRetry(
34497
34549
  ov,
34498
34550
  config2,
@@ -34510,12 +34562,12 @@ async function writeDurableMemory(config2, memory, metadata, replaceUri) {
34510
34562
  ])
34511
34563
  );
34512
34564
  const messages = [`Stored memory: ${memoryUri}`];
34513
- if (replaceUri && replaceUri !== memoryUri) {
34514
- const removedReplacedMemory = await removeVikingResourceWithRetry(ov, config2, replaceUri);
34565
+ if (params.replaceUri && !isInPlaceUpdate) {
34566
+ const removedReplacedMemory = await removeVikingResourceWithRetry(ov, config2, params.replaceUri);
34515
34567
  messages.push(
34516
- removedReplacedMemory ? `Forgot replaced memory: ${replaceUri}` : `Replacement stored, but superseded memory is still processing. Retry later with forget: ${replaceUri}`
34568
+ removedReplacedMemory ? `Forgot replaced memory: ${params.replaceUri}` : `Replacement stored, but superseded memory is still processing. Retry later with forget: ${params.replaceUri}`
34517
34569
  );
34518
- } else if (replaceUri === memoryUri) {
34570
+ } else if (isInPlaceUpdate) {
34519
34571
  messages.push(`Updated existing memory in place: ${memoryUri}`);
34520
34572
  }
34521
34573
  const text = [result.stdout.trim(), result.stderr.trim()].filter(Boolean).join("\n");
@@ -34732,14 +34784,31 @@ async function runSharePublishTool(config2, sourceUri, options) {
34732
34784
  isError: true
34733
34785
  };
34734
34786
  }
34735
- const content = readResult.stdout;
34736
- const blocker = scrubberBlocker(content);
34737
- if (blocker) {
34787
+ const stripped = stripPersonalProvenance(readResult.stdout);
34788
+ const scrub = applyScrubber(stripped, { redact: options.redact === true });
34789
+ const targetUri = sharedUriFor(config2, sourceUri, resolved.name);
34790
+ if (options.preview === true) {
34791
+ const previewLines = [`PREVIEW source: ${sourceUri}`, `PREVIEW destination: ${targetUri}`];
34792
+ if (scrub.blocker) {
34793
+ previewLines.push(
34794
+ `PREVIEW BLOCKED: ${scrub.blocker}. Strip the sensitive value or pass redact=true for soft-leak patterns.`
34795
+ );
34796
+ return { content: [{ type: "text", text: previewLines.join("\n") }] };
34797
+ }
34798
+ for (const redaction of scrub.redactions) {
34799
+ previewLines.push(`PREVIEW redact: ${redaction.count}\xD7 ${redaction.name}`);
34800
+ }
34801
+ previewLines.push("-----BEGIN PREVIEW-----");
34802
+ previewLines.push(scrub.cleaned);
34803
+ previewLines.push("-----END PREVIEW-----");
34804
+ return { content: [{ type: "text", text: previewLines.join("\n") }] };
34805
+ }
34806
+ if (scrub.blocker) {
34738
34807
  return argumentError(
34739
- `Refusing to publish ${sourceUri}: possible ${blocker}. Strip the sensitive value, then retry.`
34808
+ `Refusing to publish ${sourceUri}: possible ${scrub.blocker}. Strip the sensitive value or pass redact=true for soft-leak patterns.`
34740
34809
  );
34741
34810
  }
34742
- const targetUri = sharedUriFor(config2, sourceUri, resolved.name);
34811
+ const content = scrub.cleaned;
34743
34812
  if (await vikingResourceExists(ov, config2, targetUri)) {
34744
34813
  return argumentError(
34745
34814
  `Refusing to publish: ${targetUri} already exists in the shared namespace. Inspect it via threadnote read; if it should be replaced, forget the existing shared copy first.`
@@ -34766,6 +34835,9 @@ async function runSharePublishTool(config2, sourceUri, options) {
34766
34835
  };
34767
34836
  }
34768
34837
  const messages = [`Published ${sourceUri} -> ${targetUri}`];
34838
+ for (const redaction of scrub.redactions) {
34839
+ messages.push(`Redacted ${redaction.count}\xD7 ${redaction.name} before publish.`);
34840
+ }
34769
34841
  const relativePath = vikingUriToWorktreeRelative(config2, targetUri, resolved.name);
34770
34842
  const commitMessage = options.message ?? `share: publish ${relativePath}`;
34771
34843
  const gitMessages = await gitPublishWorkflow(
@@ -7240,12 +7240,16 @@ async function runRemember(config, options) {
7240
7240
  project: normalizeOptionalMetadata(options.project),
7241
7241
  sourceAgentClient: options.sourceAgentClient ?? "codex",
7242
7242
  status: options.status ?? "active",
7243
- supersedes: options.replace,
7244
7243
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
7245
7244
  topic: normalizeOptionalMetadata(options.topic)
7246
7245
  };
7247
- const memory = formatMemoryDocument("MEMORY", metadata, text.trim());
7248
- await storeMemory(config, memory, { dryRun: options.dryRun === true, metadata, replaceUri: options.replace });
7246
+ await storeMemory(config, {
7247
+ bodyText: text.trim(),
7248
+ dryRun: options.dryRun === true,
7249
+ metadata,
7250
+ replaceUri: options.replace,
7251
+ title: "MEMORY"
7252
+ });
7249
7253
  }
7250
7254
  async function runMigrateMemories(config, options) {
7251
7255
  const dryRun = options.dryRun === true;
@@ -7418,8 +7422,14 @@ async function runList(config, uri, options) {
7418
7422
  await maybeRun(options.dryRun === true, ov, withIdentity(config, args));
7419
7423
  }
7420
7424
  async function runHandoff(config, options) {
7421
- const { handoff, metadata } = await buildHandoff(options);
7422
- await storeMemory(config, handoff, { dryRun: options.dryRun === true, metadata, replaceUri: options.replace });
7425
+ const { bodyText, metadata } = await buildHandoff(options);
7426
+ await storeMemory(config, {
7427
+ bodyText,
7428
+ dryRun: options.dryRun === true,
7429
+ metadata,
7430
+ replaceUri: options.replace,
7431
+ title: "HANDOFF"
7432
+ });
7423
7433
  }
7424
7434
  async function runArchive(config, uri, options) {
7425
7435
  assertVikingUri(uri);
@@ -7436,12 +7446,12 @@ async function runArchive(config, uri, options) {
7436
7446
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
7437
7447
  topic: normalizeOptionalMetadata(options.topic)
7438
7448
  };
7439
- const archiveMemory2 = formatMemoryDocument(
7440
- "MEMORY",
7441
- fallbackMetadata,
7442
- ["Archived original Threadnote memory.", "", "<original memory content would be read here>"].join("\n")
7443
- );
7444
- await storeMemory(config, archiveMemory2, { dryRun: true, metadata: fallbackMetadata });
7449
+ await storeMemory(config, {
7450
+ bodyText: ["Archived original Threadnote memory.", "", "<original memory content would be read here>"].join("\n"),
7451
+ dryRun: true,
7452
+ metadata: fallbackMetadata,
7453
+ title: "MEMORY"
7454
+ });
7445
7455
  console.log(formatShellCommand(ov, withIdentity(config, ["rm", uri])));
7446
7456
  return;
7447
7457
  }
@@ -7458,12 +7468,12 @@ async function runArchive(config, uri, options) {
7458
7468
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
7459
7469
  topic: normalizeOptionalMetadata(options.topic) ?? inferredMetadata.topic
7460
7470
  };
7461
- const archiveMemory = formatMemoryDocument(
7462
- "MEMORY",
7471
+ await storeMemory(config, {
7472
+ bodyText: ["Archived original Threadnote memory.", "", original].join("\n"),
7473
+ dryRun: false,
7463
7474
  metadata,
7464
- ["Archived original Threadnote memory.", "", original].join("\n")
7465
- );
7466
- await storeMemory(config, archiveMemory, { dryRun: false, metadata });
7475
+ title: "MEMORY"
7476
+ });
7467
7477
  const removedOriginal = await removeVikingResourceWithRetry(ov, config, uri);
7468
7478
  if (removedOriginal) {
7469
7479
  console.log(`Archived original memory: ${uri}`);
@@ -7544,14 +7554,19 @@ async function printExactMemoryMatches(config, ov, query, options) {
7544
7554
  console.log("\nExact durable memory matches:");
7545
7555
  console.log(outputs.join("\n\n"));
7546
7556
  }
7547
- async function storeMemory(config, memory, options) {
7557
+ async function storeMemory(config, options) {
7548
7558
  if (options.replaceUri) {
7549
7559
  assertVikingUri(options.replaceUri);
7550
7560
  }
7551
7561
  const ov = await openVikingCliForMode(options.dryRun);
7552
7562
  const memoryPath = (0, import_node_path4.join)(config.agentContextHome, "last-memory.txt");
7553
- const memoryUri = memoryUriFor(config, memory, options.metadata);
7554
- const writeMode = await memoryWriteMode(ov, config, memoryUri, options.metadata);
7563
+ const candidateMetadata = { ...options.metadata, supersedes: options.replaceUri };
7564
+ const candidateMemory = formatMemoryDocument(options.title, candidateMetadata, options.bodyText);
7565
+ const memoryUri = memoryUriFor(config, candidateMemory, candidateMetadata);
7566
+ const isInPlaceUpdate = options.replaceUri !== void 0 && options.replaceUri === memoryUri;
7567
+ const finalMetadata = isInPlaceUpdate ? { ...options.metadata, supersedes: void 0 } : candidateMetadata;
7568
+ const memory = isInPlaceUpdate ? formatMemoryDocument(options.title, finalMetadata, options.bodyText) : candidateMemory;
7569
+ const writeMode = await memoryWriteMode(ov, config, memoryUri, finalMetadata);
7555
7570
  if (options.dryRun) {
7556
7571
  console.log(memory);
7557
7572
  console.log("\nWould run:");
@@ -7571,17 +7586,17 @@ async function storeMemory(config, memory, options) {
7571
7586
  ])
7572
7587
  )
7573
7588
  );
7574
- if (options.replaceUri && options.replaceUri !== memoryUri) {
7589
+ if (options.replaceUri && !isInPlaceUpdate) {
7575
7590
  console.log(formatShellCommand(ov, withIdentity(config, ["rm", options.replaceUri])));
7576
7591
  }
7577
7592
  return;
7578
7593
  }
7579
7594
  await (0, import_promises4.writeFile)(memoryPath, memory, { encoding: "utf8", mode: 384 });
7580
7595
  await (0, import_promises4.chmod)(memoryPath, 384);
7581
- await ensureMemoryDirectory(ov, config, memoryDirectoryUri(config, options.metadata));
7596
+ await ensureMemoryDirectory(ov, config, memoryDirectoryUri(config, finalMetadata));
7582
7597
  await writeDurableMemoryFile(ov, config, memoryUri, memoryPath, writeMode);
7583
7598
  console.log(`Stored memory: ${memoryUri}`);
7584
- if (options.replaceUri && options.replaceUri !== memoryUri) {
7599
+ if (options.replaceUri && !isInPlaceUpdate) {
7585
7600
  const removedReplacedMemory = await removeVikingResourceWithRetry(ov, config, options.replaceUri);
7586
7601
  if (removedReplacedMemory) {
7587
7602
  console.log(`Forgot replaced memory: ${options.replaceUri}`);
@@ -7590,7 +7605,7 @@ async function storeMemory(config, memory, options) {
7590
7605
  `Replacement stored, but the superseded memory is still processing. Retry later: threadnote forget ${options.replaceUri}`
7591
7606
  );
7592
7607
  }
7593
- } else if (options.replaceUri === memoryUri) {
7608
+ } else if (isInPlaceUpdate) {
7594
7609
  console.log(`Updated existing memory in place: ${memoryUri}`);
7595
7610
  }
7596
7611
  }
@@ -8043,11 +8058,10 @@ async function buildHandoff(options) {
8043
8058
  project: normalizeOptionalMetadata(options.project) ?? repoName,
8044
8059
  sourceAgentClient: options.sourceAgentClient ?? "codex",
8045
8060
  status: "active",
8046
- supersedes: options.replace,
8047
8061
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
8048
8062
  topic: normalizeOptionalMetadata(options.topic)
8049
8063
  };
8050
- const body = [
8064
+ const bodyText = [
8051
8065
  `repo: ${repoName}`,
8052
8066
  `repo_path: ${repoRoot}`,
8053
8067
  `branch: ${branch || "unknown"}`,
@@ -8071,7 +8085,7 @@ async function buildHandoff(options) {
8071
8085
  "next_step:",
8072
8086
  options.nextStep ?? "- inspect the current repo state and continue from this handoff"
8073
8087
  ].join("\n");
8074
- return { handoff: formatMemoryDocument("HANDOFF", metadata, body), metadata };
8088
+ return { bodyText, metadata };
8075
8089
  }
8076
8090
  async function gitTouchedFiles(cwd) {
8077
8091
  const changedFiles = await gitValue(["diff", "--name-only", "HEAD"], cwd);
@@ -8609,6 +8623,8 @@ var SHARED_SEGMENT = "shared";
8609
8623
  var SHAREABLE_MEMORY_KIND_DIRS = ["durable"];
8610
8624
  var DEFAULT_GIT_REMOTE_NAME = "origin";
8611
8625
  var SCRUBBER_PATTERNS = [
8626
+ // Credentials: never redactable. Blocking is the only safe response —
8627
+ // automated redaction risks false negatives that leave material in git.
8612
8628
  { name: "private key", regex: /-----BEGIN [A-Z ]*PRIVATE KEY-----/ },
8613
8629
  { name: "API key (sk-...)", regex: /\bsk-[A-Za-z0-9_-]{16,}/ },
8614
8630
  { name: "GitHub token", regex: /\bgh[pousr]_[A-Za-z0-9_]{16,}/ },
@@ -8621,8 +8637,35 @@ var SCRUBBER_PATTERNS = [
8621
8637
  { name: "AWS access key", regex: /\bAKIA[0-9A-Z]{16}\b/ },
8622
8638
  // Slack tokens: xoxa/xoxb/xoxc (configuration)/xoxd (legacy user cookie)/
8623
8639
  // xoxe (refresh)/xoxp/xoxr/xoxs, with optional -N- segment for the workspace tier.
8624
- { name: "Slack token", regex: /\bxox[abcdeprs](?:-\d-)?[A-Za-z0-9._-]{10,}/i }
8640
+ { name: "Slack token", regex: /\bxox[abcdeprs](?:-\d-)?[A-Za-z0-9._-]{10,}/i },
8641
+ // Soft leaks: block by default (so the agent sees them and decides), but
8642
+ // allow opt-in redaction so curated memories with incidental matches can
8643
+ // ship without a manual rewrite. Local home paths are the recurring
8644
+ // real-world leak; the regexes greedily consume the whole path segment
8645
+ // (including subdirectories) up to whitespace or common closing punctuation
8646
+ // so redaction collapses an entire path to a single placeholder rather than
8647
+ // leaving the subpath visible.
8648
+ { name: "macOS home path", placeholder: "<local-path>", regex: /\/Users\/[^\s)>"'`,]+/ },
8649
+ { name: "linux home path", placeholder: "<local-path>", regex: /\b\/home\/[^\s)>"'`,]+/ }
8625
8650
  ];
8651
+ function applyScrubber(content, { redact }) {
8652
+ let cleaned = content;
8653
+ const redactions = [];
8654
+ for (const pattern of SCRUBBER_PATTERNS) {
8655
+ if (!pattern.regex.test(cleaned)) {
8656
+ continue;
8657
+ }
8658
+ if (!pattern.placeholder || !redact) {
8659
+ return { blocker: pattern.name, cleaned: content, redactions: [] };
8660
+ }
8661
+ const flags = pattern.regex.flags.includes("g") ? pattern.regex.flags : `${pattern.regex.flags}g`;
8662
+ const globalRegex = new RegExp(pattern.regex.source, flags);
8663
+ const matches = cleaned.match(globalRegex) ?? [];
8664
+ cleaned = cleaned.replace(globalRegex, pattern.placeholder);
8665
+ redactions.push({ count: matches.length, name: pattern.name });
8666
+ }
8667
+ return { cleaned, redactions };
8668
+ }
8626
8669
  async function runShareInit(config, remoteUrl, options) {
8627
8670
  if (!remoteUrl.trim()) {
8628
8671
  throw new Error("Provide a git remote URL for the shared memories repo.");
@@ -8787,16 +8830,41 @@ async function runSharePublish(config, sourceUri, options) {
8787
8830
  assertVikingUri(sourceUri);
8788
8831
  const team = await resolveTeam(config, options.team);
8789
8832
  const dryRun = options.dryRun === true;
8833
+ const preview = options.preview === true;
8790
8834
  if (isInSharedNamespace(config, sourceUri)) {
8791
8835
  throw new Error(`Memory ${sourceUri} is already in the shared namespace.`);
8792
8836
  }
8793
8837
  const ov = await openVikingCliForMode(dryRun);
8794
- const content = await readMemoryContent(config, ov, sourceUri, dryRun);
8795
- const blocker = scrubberBlocker(content);
8796
- if (blocker) {
8797
- throw new Error(`Refusing to publish ${sourceUri}: possible ${blocker}. Strip the sensitive value, then retry.`);
8798
- }
8838
+ const rawContent = await readMemoryContent(config, ov, sourceUri, dryRun);
8839
+ const stripped = stripPersonalProvenance(rawContent);
8840
+ const scrub = applyScrubber(stripped, { redact: options.redact === true });
8799
8841
  const targetUri = sharedUriFor(config, sourceUri, team.name);
8842
+ if (preview) {
8843
+ console.log(`PREVIEW source: ${sourceUri}`);
8844
+ console.log(`PREVIEW destination: ${targetUri}`);
8845
+ if (scrub.blocker) {
8846
+ console.log(
8847
+ `PREVIEW BLOCKED: ${scrub.blocker}. Strip the sensitive value or rerun with --redact for soft-leak patterns.`
8848
+ );
8849
+ return;
8850
+ }
8851
+ for (const redaction of scrub.redactions) {
8852
+ console.log(`PREVIEW redact: ${redaction.count}\xD7 ${redaction.name}`);
8853
+ }
8854
+ console.log("-----BEGIN PREVIEW-----");
8855
+ console.log(scrub.cleaned);
8856
+ console.log("-----END PREVIEW-----");
8857
+ return;
8858
+ }
8859
+ if (scrub.blocker) {
8860
+ throw new Error(
8861
+ `Refusing to publish ${sourceUri}: possible ${scrub.blocker}. Strip the sensitive value or pass --redact for soft-leak patterns.`
8862
+ );
8863
+ }
8864
+ for (const redaction of scrub.redactions) {
8865
+ console.log(`Redacted ${redaction.count}\xD7 ${redaction.name} before publish.`);
8866
+ }
8867
+ const content = scrub.cleaned;
8800
8868
  if (!dryRun && await vikingResourceExists2(ov, config, targetUri)) {
8801
8869
  throw new Error(
8802
8870
  `Refusing to publish: ${targetUri} already exists in the shared namespace. Inspect it via threadnote read; if it should be replaced, forget the existing shared copy first.`
@@ -9092,8 +9160,26 @@ function vikingUriToWorktreeRelative(config, uri, team) {
9092
9160
  }
9093
9161
  return uri.slice(prefix.length);
9094
9162
  }
9095
- function scrubberBlocker(content) {
9096
- return SCRUBBER_PATTERNS.find((pattern) => pattern.regex.test(content))?.name;
9163
+ function stripPersonalProvenance(content) {
9164
+ const lines = content.split("\n");
9165
+ let headerEnd = lines.length;
9166
+ for (let index = 0; index < lines.length; index += 1) {
9167
+ if (lines[index].trim() === "") {
9168
+ headerEnd = index;
9169
+ break;
9170
+ }
9171
+ }
9172
+ const cleaned = [];
9173
+ for (let index = 0; index < headerEnd; index += 1) {
9174
+ if (/^(?:supersedes|archived_from):\s/.test(lines[index])) {
9175
+ continue;
9176
+ }
9177
+ cleaned.push(lines[index]);
9178
+ }
9179
+ for (let index = headerEnd; index < lines.length; index += 1) {
9180
+ cleaned.push(lines[index]);
9181
+ }
9182
+ return cleaned.join("\n");
9097
9183
  }
9098
9184
  async function readMemoryContent(config, ov, uri, dryRun) {
9099
9185
  const args = withIdentity(config, ["read", uri]);
@@ -10911,7 +10997,13 @@ async function main() {
10911
10997
  share.command("sync").description("Pull, reindex, and push the shared memories repo for a team").option("--team <name>", "Team name; defaults to the configured default team").option("--message <text>", "Commit message when auto-committing local edits").option("--no-auto-commit", "Refuse to sync if there are uncommitted local changes").option("--no-push", "Skip the push step after pulling and reindexing").option("--dry-run", "Print actions without running them").action(async (options) => {
10912
10998
  await runShareSync(getRuntimeConfig(program2), options);
10913
10999
  });
10914
- share.command("publish").description("Move a personal memory into the shared team namespace, commit and push").argument("<viking-uri>", "viking:// memory URI to publish").option("--team <name>", "Team name; defaults to the configured default team").option("--message <text>", "Commit message override").option("--no-push", "Skip the push step").option("--dry-run", "Print actions without running them").action(async (uri, options) => {
11000
+ share.command("publish").description("Move a personal memory into the shared team namespace, commit and push").argument("<viking-uri>", "viking:// memory URI to publish").option("--team <name>", "Team name; defaults to the configured default team").option("--message <text>", "Commit message override").option("--no-push", "Skip the push step").option("--dry-run", "Print actions without running them").option(
11001
+ "--preview",
11002
+ "Print the exact bytes that would land in the shared git repo (after frontmatter strip and scrubber redaction) without writing, committing, or pushing"
11003
+ ).option(
11004
+ "--redact",
11005
+ "Replace soft-leak matches (local paths) with placeholders and continue; credentials still block"
11006
+ ).action(async (uri, options) => {
10915
11007
  await runSharePublish(getRuntimeConfig(program2), uri, options);
10916
11008
  });
10917
11009
  share.command("unpublish").description("Pull a shared memory back into the personal namespace, commit removal and push").argument("<viking-uri>", "viking:// memory URI inside a team shared subtree").option("--team <name>", "Team name; defaults to the configured default team").option("--message <text>", "Commit message override").option("--no-push", "Skip the push step").option("--dry-run", "Print actions without running them").action(async (uri, options) => {
package/docs/index.html CHANGED
@@ -10,6 +10,18 @@
10
10
  content="Threadnote is a safe local workflow for using OpenViking as shared, agent-neutral context for development work — across Codex, Claude, Cursor, and Copilot."
11
11
  />
12
12
 
13
+ <link rel="icon" type="image/svg+xml" href="threadnote-logo.svg" />
14
+
15
+ <meta property="og:title" content="Threadnote — shared local context for development agents" />
16
+ <meta
17
+ property="og:description"
18
+ content="One shared memory for Codex, Claude, Cursor, and Copilot. Local-first, cross-session, cross-agent."
19
+ />
20
+ <meta property="og:image" content="threadnote-logo.svg" />
21
+ <meta property="og:type" content="website" />
22
+ <meta name="twitter:card" content="summary" />
23
+ <meta name="twitter:image" content="threadnote-logo.svg" />
24
+
13
25
  <link rel="preconnect" href="https://fonts.googleapis.com" />
14
26
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
15
27
  <link
@@ -210,30 +222,29 @@
210
222
  align-items: flex-start;
211
223
  }
212
224
 
213
- .brand {
214
- display: inline-flex;
215
- align-items: center;
216
- gap: 0.6rem;
217
- margin-bottom: 1.5rem;
225
+ .page-logo {
226
+ position: fixed;
227
+ top: 1.5rem;
228
+ left: 1.5rem;
229
+ width: 220px;
230
+ height: 220px;
231
+ z-index: 40;
232
+ pointer-events: none;
218
233
  }
219
234
 
220
- .brand-mark {
221
- width: 32px;
222
- height: 32px;
223
- border-radius: 8px;
224
- background: linear-gradient(135deg, var(--accent), #7c8cff);
225
- display: grid;
226
- place-items: center;
227
- color: #0a0a0d;
228
- font-family: var(--font-mono);
229
- font-weight: 700;
230
- font-size: 14px;
235
+ .page-logo img {
236
+ width: 100%;
237
+ height: 100%;
238
+ display: block;
231
239
  }
232
240
 
233
- .brand-name {
234
- font-family: var(--font-mono);
235
- font-size: 0.95rem;
236
- color: var(--muted);
241
+ @media (max-width: 720px) {
242
+ .page-logo {
243
+ width: 120px;
244
+ height: 120px;
245
+ top: 1rem;
246
+ left: 1rem;
247
+ }
237
248
  }
238
249
 
239
250
  .hero-title-gradient {
@@ -684,6 +695,10 @@
684
695
  <body>
685
696
  <div class="progress"><div class="progress-bar" id="progressBar"></div></div>
686
697
 
698
+ <div class="page-logo" aria-hidden="true">
699
+ <img src="threadnote-logo-inverted.svg" alt="" />
700
+ </div>
701
+
687
702
  <nav class="deck-nav" aria-label="Section progress">
688
703
  <a href="#hero" data-label="Intro"><span>Intro</span></a>
689
704
  <a href="#problem" data-label="Problem"><span>Problem</span></a>
@@ -704,10 +719,6 @@
704
719
  <!-- 1. HERO -->
705
720
  <section id="hero" class="slide">
706
721
  <div class="slide-inner">
707
- <div class="brand">
708
- <div class="brand-mark">t</div>
709
- <span class="brand-name">threadnote</span>
710
- </div>
711
722
  <h1 class="hero-title-gradient">
712
723
  Shared local context<br />for <em class="hero-accent">development agents</em>.
713
724
  </h1>
package/docs/share.md CHANGED
@@ -48,9 +48,17 @@ threadnote share status --team friends
48
48
 
49
49
  ```bash
50
50
  # 1. Identify the personal URI you want to publish (use recall/list as usual).
51
- # 2. Publish:
51
+ # 2. Preview the would-be-published bytes before committing:
52
+ threadnote share publish viking://user/you/memories/durable/projects/foo/bar.md --preview
53
+ # 3. Publish:
52
54
  threadnote share publish viking://user/you/memories/durable/projects/foo/bar.md
53
- # Optional flags: --team <name>, --message "...", --no-push, --dry-run.
55
+ # Optional flags:
56
+ # --preview Read + strip + scrub the memory and print the exact bytes
57
+ # that would land in git; no writes, no commits, no pushes.
58
+ # Use this before any publish to catch leaks by inspection.
59
+ # --redact Replace soft-leak matches (local home paths) with
60
+ # placeholders and continue. Credentials still block.
61
+ # --team <name>, --message "...", --no-push, --dry-run.
54
62
  ```
55
63
 
56
64
  `share publish` moves the memory from your personal namespace into the team's
@@ -58,6 +66,11 @@ shared subtree, commits with the message
58
66
  `share: publish <relative-path>`, and pushes. The memory's recall path becomes
59
67
  `viking://user/you/memories/shared/<team>/durable/projects/foo/bar.md`.
60
68
 
69
+ Before writing, `share publish` strips `supersedes:` and `archived_from:`
70
+ lines from the memory's header block. Those pointers only resolve on the
71
+ publisher's machine — teammates pull via git and cannot dereference them — so
72
+ keeping them would just leak local-only provenance into team git history.
73
+
61
74
  ### Pull teammates' updates
62
75
 
63
76
  ```bash
@@ -113,8 +126,14 @@ otherwise unpublished work is lost.
113
126
  - Slack tokens (`xoxa`, `xoxb`, `xoxc`, `xoxd`, `xoxe`, `xoxp`, `xoxr`,
114
127
  `xoxs`, with optional `-N-` segment markers — covers bot, user,
115
128
  configuration, legacy cookie, refresh, app, and similar shapes)
129
+ - `share publish` also blocks on soft-leak patterns that show up routinely in
130
+ curated memories. These are redactable: pass `--redact` to replace each
131
+ match with a generic placeholder and continue. Credentials always block
132
+ regardless of `--redact`.
133
+ - macOS home paths (`/Users/<you>/...`) → `<local-path>`
134
+ - linux home paths (`/home/<you>/...`) → `<local-path>`
116
135
  - The scrubber complements but does not replace human review. Strip the value,
117
- then retry.
136
+ preview with `--preview`, and then publish.
118
137
  - Only the `durable/` kind is shareable. `handoffs/`, `preferences/`,
119
138
  `incidents/`, and other lifecycle kinds stay local by construction — both
120
139
  the initial ingest (`share init`) and the sync-pull reindex (`share sync`)
@@ -145,7 +164,9 @@ Each user clones into their own user-namespaced path. A memory authored on
145
164
  machine A as `viking://user/alice/memories/shared/team/durable/projects/foo/bar.md`
146
165
  shows up on machine B as
147
166
  `viking://user/bob/memories/shared/team/durable/projects/foo/bar.md`. The file
148
- content (including any `supersedes:` URIs that reference the original author) is
149
- identical, but explicit URI cross-references will point at the author's
167
+ content is identical. `supersedes:` / `archived_from:` lines are stripped at
168
+ the publish boundary so cross-machine URI references don't pollute team git
169
+ history; explicit `viking://` references inside the body will point at the
170
+ author's
150
171
  namespace. For now, prefer narrative references ("see the foo memory under
151
172
  shared/team") over URI links in shared content.
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="2048" height="2048" fill="none" viewBox="0 0 2048 2048"><g stroke="#b8a49a" clip-path="url(#a)"><path fill="#b8a49a" d="M931 491h2v1h3v-1h5v1h3v-1h1v1h1v-1h3v1h3v-1h8v1h4v-1h1v1h7v-1h1v1h23v-1h1v1h67v-1h1v1h2v-1h2v1h3v-1h12v1h1v-1h13v1h3v-1h16v1h1v-1h2v1h41v1h10v1h6v1h4v1h4v1h4v1h2v1h3v1h2v1h3v1h2v1h2v1h2v1h2v1h1v1h2v1h2v1h1v1h1v1h1v1h2v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v2h2v1h1v1h1v1h1v1h1v1h1v1h1v2h2v2h2v1h1v1h1v2h2v2h1v1h2v2h2v1h1v1h1v1h1v1h1v2h2v2h2v1h1v2h2v2h2v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v2h1v1h1v1h1v1h1v2h1v1h1v2h1v1h1v2h1v1h1v2h1v2h1v2h1v2h1v2h1v2h1v2h1v3h1v3h1v3h1v4h1v4h1v6h1v10h1v427h-1v8h-1v5h-1v3h-1v3h-1v3h-1v2h-1v2h-1v2h-1v2h-1v2h-1v1h-1v1h-1v2h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-2v1h-1v1h-2v1h-1v1h-2v1h-3v1h-1v1h-3v1h-3v1h-2v1h-4v1h-5v1h-11v1h-1v-1h-3v1h-2v-1h-1v1h-2v-1h-1v1h-1v-1h-1v1h-6v-1h-4v1h-1v-1h-1v1h-1v-1h-1v1h-3v-1h-1v1h-1v-1h-3v1h-1v-1h-1v1h-1v-1h-3v1h-1v-1h-7v1h-1v-1h-69v1h-2v-1H902v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-2h1v-1h1v-2h1v-1h1v-1h1v-2h2v-1h1v-1h392v-1h3v-1h3v-1h2v-1h3v-1h1v-1h2v-1h2v-2h2v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-2h1v-2h1v-1h1v-1h1v-2h1v-3h1v-2h1v-4h1v-5h1V709h-1v-1h1v-1h-1v-7h-1v-4h-1v-3h-1v-2h-1v-2h-1v-2h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-2v-1h-1v-1h-2v-1h-2v-1h-4v-1h-4v-1h-70v-1h-10v-1h-6v-1h-3v-1h-4v-1h-2v-1h-3v-1h-1v-1h-3v-1h-1v-1h-3v-1h-1v-1h-1v-1h-2v-1h-1v-1h-1v-1h-1v-1h-2v-1h-1v-1h-1v-1h-1v-1h-1v-2h-2v-2h-1v-1h-1v-1h-1v-1h-1v-2h-1v-2h-1v-2h-1v-1h-1v-2h-1v-2h-1v-2h-1v-3h-1v-3h-1v-4h-1v-5h-1v-68h-1v-10h-1v-5h-1v-3h-1v-2h-1v-2h-1v-2h-1v-1h-1v-2h-1v-1h-1v-1h-1v-1h-2v-1h-1v-1h-2v-1h-2v-1h-2v-1h-3v-1h-5v-1H863v1h-6v1h-3v1h-3v1h-2v1h-2v1h-1v1h-2v1h-1v1h-1v1h-2v1h-1v1h-1v1h-1v2h-1v1h-1v1h-1v2h-1v2h-1v1h-1v3h-1v3h-1v4h-1v5h-1v230h1v-1h6v-1h10v-1h2v1h9v-1h2v1h34v-1h7v-1h4v-1h3v-1h2v-1h3v-1h2v-1h2v-1h1v-1h2v-1h1v-1h2v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h2v-2h1v-1h1v-1h1v-1h1v-1h1v-2h1v-1h1v-2h1v-1h1v-2h1v-2h1v-2h1v-2h1v-2h1v-2h1v-3h1v-2h1v-3h1v-2h1v-3h1v-3h1v-3h1v-2h1v-3h1v-2h1v-2h1v-2h1v-1h1v-2h1v-2h1v-1h1v-1h1v-2h2v-2h2v-1h1v-1h1v-1h2v-1h2v-1h2v-1h4v-1h8v1h5v1h3v1h2v1h1v1h1v1h2v1h1v2h1v1h1v1h1v2h1v1h1v2h1v3h1v3h1v4h1v8h1v30h1v1h-1v1h1v4h1v5h1v2h1v2h1v2h1v1h2v1h1v1h5v-1h1v-1h2v-1h1v-1h1v-1h1v-1h1v-2h1v-1h1v-2h1v-1h1v-2h1v-1h1v-2h1v-1h1v-2h1v-1h1v-2h1v-1h1v-2h1v-1h1v-2h1v-1h1v-1h1v-2h1v-1h1v-1h1v-1h1v-2h1v-1h1v-1h1v-1h1v-1h2v-1h1v-1h2v-2h2v-1h3v-1h3v-1h6v-1h2v1h7v1h3v1h2v1h2v1h2v1h1v1h1v1h2v2h2v2h1v1h1v2h2v2h1v2h1v1h1v2h1v1h1v2h1v2h1v2h1v2h1v2h1v1h1v2h1v1h1v1h1v1h2v1h1v1h1v1h6v-1h2v-1h1v-1h2v-1h1v-2h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-2h2v-1h1v-1h1v-2h1v-1h2v-1h1v-1h2v-2h3v-1h2v-1h2v-1h2v-1h2v-1h6v-1h13v1h5v1h4v1h2v1h3v1h2v1h2v1h2v1h2v1h1v1h2v1h2v1h1v1h2v1h2v1h2v1h1v1h3v1h2v1h3v1h2v1h3v1h1v-1h1v1h12v-1h5v-1h2v-1h3v-1h2v-1h1v-1h1v-1h2v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h2v-1h1v-1h3v-1h5v1h2v1h1v1h2v2h1v1h1v2h1v4h-1v3h-1v2h-1v1h-1v1h-1v2h-2v1h-1v2h-2v1h-1v1h-1v1h-1v1h-1v1h-2v1h-1v1h-2v1h-2v1h-2v1h-3v1h-2v1h-3v1h-5v1h-21v-1h-4v-1h-4v-1h-3v-1h-3v-1h-2v-1h-2v-1h-2v-1h-2v-1h-2v-1h-1v-1h-2v-1h-2v-1h-1v-1h-2v-1h-2v-1h-2v-1h-1v-1h-2v-1h-3v-1h-2v-1h-5v-1h-8v1h-2v1h-3v1h-2v1h-1v1h-1v1h-1v1h-1v1h-2v1h-1v1h-1v1h-1v2h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-2v1h-1v1h-1v1h-2v1h-2v1h-2v1h-3v1h-5v1h-4v-1h-1v1h-1v-1h-4v-1h-3v-1h-2v-1h-2v-1h-1v-1h-2v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-2h-1v-1h-1v-1h-1v-2h-1v-2h-1v-1h-1v-2h-1v-2h-1v-2h-1v-2h-1v-1h-1v-2h-1v-1h-1v-2h-1v-2h-1v-1h-1v-1h-1v-1h-2v-1h-6v1h-3v1h-1v1h-1v1h-1v1h-1v1h-1v2h-1v1h-1v1h-1v2h-1v1h-1v1h-1v2h-1v1h-1v2h-1v1h-1v2h-1v1h-1v2h-1v1h-1v2h-1v1h-1v2h-1v1h-1v2h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-2v1h-1v1h-2v1h-2v1h-2v1h-4v1h-10v-1h-4v-1h-3v-1h-2v-1h-1v-1h-2v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-2h-1v-1h-1v-2h-1v-2h-1v-2h-1v-2h-1v-3h-1v-4h-1v-4h-1v-6h-1v-26h1v-1h-1v-12h-1v-2h-1v-1h-1v-1h-1v-1h-5v1h-1v1h-1v1h-1v2h-1v1h-1v3h-1v3h-1v2h-1v3h-1v3h-1v3h-1v3h-1v2h-1v3h-1v2h-1v2h-1v2h-1v2h-1v2h-1v2h-1v1h-1v2h-1v2h-1v1h-1v2h-1v2h-1v1h-1v2h-1v1h-1v1h-1v2h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-2v1h-1v1h-1v1h-2v1h-1v1h-2v1h-1v1h-2v1h-2v1h-2v1h-2v1h-2v1h-3v1h-3v1h-3v1h-4v1h-5v1h-6v1h-54v1h-8v1h-4v121h-3v-2h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-2h-1v-1h-1v-1h-1v-1h-1v-1h-1v-2h-1v-1h-1v-2h-1v-1h-1v-2h-1v-2h1v-1h-1v-1h1v-1h-1v-84h-2v1h-2v1h-1v1h-2v1h-1v1h-1v1h-2v1h-1v1h-1v1h-1v2h-1v1h-1v1h-1v1h-1v2h-1v1h-1v2h-1v1h-1v3h-1v2h-1v2h-1v3h-1v4h-1v6h-1v12h1v7h1v5h1v3h1v4h1v3h1v3h1v2h1v2h1v2h1v2h1v2h1v1h1v2h1v2h1v1h1v2h1v1h1v2h1v1h1v2h1v1h1v1h1v1h1v2h1v1h1v1h1v2h1v1h1v1h1v1h1v2h1v1h1v1h1v1h1v2h1v1h1v1h1v1h1v1h1v2h1v1h1v1h1v1h1v1h1v1h1v1h1v2h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v2h1v1h2v2h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v2h2v2h2v1h1v2h1v1h1v1h1v1h1v2h1v1h1v1h1v1h1v1h1v2h1v1h1v1h1v1h1v2h1v2h1v1h1v2h1v1h1v2h1v1h1v2h1v1h1v2h1v1h1v2h1v1h1v2h1v1h1v1h6v-1h3v-1h3v-1h3v-1h3v-1h2v-1h1v-1h3v-1h2v-1h2v-2h3v-1h1v-1h1v-1h1v-1h1v-1h2v-1h1v-2h2v-1h1v-1h1v-1h1v-1h1v-2h2v-2h1v-1h1v-2h1v-1h1v-1h1v-1h1v-2h1v-1h1v-2h1v-2h1v-1h1v-2h1v-1h1v-2h1v-2h1v-1h1v-1h1v-2h1v-1h1v-2h1v-2h1v-1h1v-2h1v-1h1v-2h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h2v-1h1v-1h2v-1h1v-1h3v-1h4v-1h11v1h3v1h3v1h2v1h1v1h2v1h2v2h1v1h1v1h1v1h1v1h1v1h1v3h1v1h1v2h1v2h1v3h1v4h1v3h1v5h1v4h1v5h1v3h1v4h1v3h1v2h1v2h1v2h2v1h1v1h4v-1h2v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-2h1v-2h1v-1h1v-2h1v-2h1v-1h1v-1h1v-2h1v-1h1v-1h1v-2h1v-1h1v-1h1v-2h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h2v-1h1v-1h2v-1h1v-1h3v-1h1v-1h4v-1h13v1h3v1h2v1h2v1h2v1h2v1h1v1h1v1h1v1h1v1h1v2h2v2h1v2h1v1h1v1h1v1h1v2h1v1h1v2h1v1h1v1h1v2h2v2h1v1h1v1h2v1h1v1h7v-1h3v-1h2v-1h2v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h2v-1h1v-1h1v-1h1v-1h2v-1h1v-1h2v-1h2v-1h2v-1h3v-1h5v-1h5v-1h1v1h1v-1h4v1h2v-1h1v1h5v1h4v1h4v1h3v1h2v1h2v1h2v1h3v1h2v1h2v1h3v1h3v1h3v1h4v1h4v1h13v-1h4v-1h2v-1h3v-1h3v-1h1v-1h2v-1h1v-1h2v-1h1v-1h1v-1h2v-2h2v-1h1v-2h1v-1h1v-1h1v-1h1v-2h1v-1h1v-1h1v-2h1v-2h1v-2h1v-2h1v-4h1v-3h1v-3h1v-9h1v-1h-1v-1h1v-2h-1v-2h1v-1h-1v-8h-1v-4h-1v-4h-1v-3h-1v-2h-1v-2h-1v-2h-1v-3h-1v-1h-1v-1h-1v-2h-1v-1h-1v-1h-1v-1h-1v-2h-1v-1h-1v-1h-1v-1h-2v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-2v-1h-2v-1h-1v-1h-1v-1h-2v-1h-3v-1h-2v-1h-2v-1h-4v-1h-3v-1h-5v-1h-11v-1h-3v1h-1v-1h-2v1h-11v1h-4v1h-4v1h-3v1h-3v1h-2v1h-3v1h-1v1h-2v1h-2v1h-1v1h-2v1h-2v1h-1v1h-1v1h-2v1h-1v1h-2v1h-1v1h-1v1h-1v1h-1v1h-1v1h-2v1h-1v1h-1v1h-1v1h-1v1h-2v1h-1v1h-2v1h-2v1h-2v1h-3v1h-3v1h-5v1h-2v-1h-3v1h-1v-1h-6v-1h-4v-1h-1v-1h-2v-1h-2v-1h-2v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-2h-1v-2h-1v-1h-1v-2h-1v-1h-1v-2h-1v-2h-1v-2h-1v-2h-1v-2h-1v-2h-1v-2h-1v-2h-1v-2h-1v-2h-1v-2h-1v-2h-1v-2h-1v-2h-1v-1h-1v-1h-1v-1h-1v-1h-2v-1h-7v1h-2v1h-1v1h-1v1h-1v1h-1v1h-1v2h-1v2h-1v1h-1v2h-1v1h-1v3h-1v1h-1v2h-1v1h-1v2h-1v2h-1v1h-1v2h-1v2h-1v1h-1v2h-1v2h-1v1h-1v1h-1v2h-2v2h-1v1h-2v2h-2v1h-1v1h-1v1h-1v1h-2v1h-2v1h-3v1h-5v1h-1v-1h-1v1h-1v-1h-6v-1h-3v-1h-2v-1h-1v-1h-2v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-2h-1v-1h-1v-2h-1v-1h-1v-2h-1v-2h-1v-2h-1v-2h-1v-2h-1v-1h-1v-2h-1v-3h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-2v-1h-2v1h-3v1h-1v1h-2v1h-1v1h-1v1h-1v1h-1v1h-1v2h-1v1h-1v1h-1v2h-1v1h-1v1h-1v1h-1v1h-1v2h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-2v1h-1v1h-1v1h-2v1h-1v1h-2v1h-2v1h-2v1h-2v1h-3v1h-5v1h-9v-1h-2v-1h-2v-1h-1v-1h-1v-1h-1v-1h-1v-3h-1v-5h1v-3h1v-1h1v-1h1v-1h2v-1h3v-1h6v-1h5v-1h3v-1h1v-1h2v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-2h1v-1h1v-2h1v-1h1v-1h1v-1h1v-2h1v-1h1v-1h1v-1h1v-1h1v-1h1v-2h2v-1h1v-1h1v-1h3v-1h2v-1h1v-1h5v-1h11v1h4v1h2v1h2v1h2v1h1v1h2v1h1v1h1v2h1v1h1v1h1v1h1v2h1v2h1v2h1v2h1v2h1v1h1v2h1v2h1v2h1v3h1v1h1v2h1v1h1v1h3v1h4v-1h2v-1h1v-1h1v-2h1v-2h1v-1h1v-2h1v-1h1v-1h1v-3h1v-1h1v-2h1v-1h1v-2h1v-3h1v-1h1v-2h1v-1h1v-3h1v-1h1v-2h1v-1h1v-1h1v-2h1v-1h1v-2h2v-1h1v-2h2v-1h1v-1h2v-1h1v-1h1v-1h3v-1h2v-1h4v-1h10v1h4v1h4v1h2v1h1v1h2v1h1v1h1v1h2v1h1v2h1v1h1v2h2v3h1v1h1v1h1v3h1v2h1v2h1v1h1v2h1v3h1v2h1v2h1v2h1v2h1v2h1v1h1v2h1v2h1v1h1v1h1v1h1v1h1v1h1v1h2v1h3v1h1v-1h4v-1h1v-1h2v-1h2v-1h2v-2h2v-1h1v-1h1v-1h2v-2h2v-1h1v-1h1v-1h2v-2h2v-1h1v-1h2v-1h2v-1h1v-1h2v-1h1v-1h2v-1h2v-1h1v-1h2v-1h2v-1h3v-1h2v-1h2v-1h2v-1h5v-1h4v-1h5v-1h4v-1h28v1h5v1h5v1h4v1h3v1h3v1h2v1h3v1h2v1h2v1h1v1h2v1h2v1h2v1h2v1h1v1h1v1h1v1h2v1h1v1h2v2h2v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v2h1v1h1v2h2v2h1v1h1v2h1v1h1v2h1v2h1v3h1v2h1v2h1v2h1v4h1v4h1v4h1v8h1v16h-1v6h-1v4h-1v4h-1v3h-1v3h-1v3h-1v2h-1v2h-1v2h-1v3h-1v1h-1v2h-1v2h-1v1h-1v1h-1v1h-1v2h-1v1h-1v1h-1v2h-1v1h-1v1h-1v1h-1v1h-1v1h-2v1h-1v1h-1v1h-1v1h-2v1h-1v1h-2v1h-1v1h-2v1h-2v1h-1v1h-3v1h-2v1h-3v1h-4v1h-4v1h-10v1h-1v-1h-1v1h-1v-1h-11v-1h-4v-1h-4v-1h-3v-1h-3v-1h-2v-1h-2v-1h-3v-1h-2v-1h-2v-1h-2v-1h-3v-1h-2v-1h-2v-1h-3v-1h-13v1h-3v1h-2v1h-2v1h-1v1h-1v1h-1v1h-2v1h-1v1h-1v1h-2v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-2v1h-1v1h-2v1h-1v1h-2v1h-2v1h-2v1h-2v1h-4v1h-15v-1h-2v-1h-3v-1h-2v-1h-2v-1h-1v-1h-2v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-2h-1v-1h-1v-1h-1v-2h-1v-1h-1v-2h-1v-2h-1v-1h-1v-1h-1v-2h-1v-1h-1v-1h-2v-1h-1v-1h-6v1h-2v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v2h-1v1h-1v2h-1v1h-1v1h-1v2h-1v2h-1v1h-1v1h-1v2h-1v1h-1v1h-1v2h-1v1h-1v1h-1v1h-1v1h-1v2h-1v1h-1v1h-1v1h-1v1h-2v1h-1v1h-1v1h-1v1h-2v1h-2v1h-2v1h-4v1h-7v-1h-5v-1h-3v-1h-2v-1h-2v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-2h-1v-1h-1v-2h-1v-2h-1v-2h-1v-3h-1v-3h-1v-2h-1v-5h-1v-4h-1v-6h-1v-4h-1v-5h-1v-3h-1v-2h-1v-2h-1v-2h-1v-1h-2v-1h-3v-1h-2v1h-2v1h-2v1h-1v1h-1v2h-1v1h-1v2h-1v1h-1v2h-1v2h-1v1h-1v2h-1v1h-1v2h-1v1h-1v2h-1v2h-1v1h-1v2h-1v1h-1v1h-1v2h-1v2h-1v1h-1v2h-1v1h-1v1h-1v2h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-2v1h-1v1h-1v1h-2v1h-1v1h-2v1h-1v1h-2v1h-1v1h-2v1h-2v1h-2v1h-3v1h-2v1h-2v1h-3v1h-3v1h-3v1h-3v2h1v3h1v2h1v3h1v3h1v2h1v3h1v3h1v3h1v4h1v3h1v4h1v4h1v4h1v4h1v6h1v6h1v7h1v25h-1v1h1v1h-1v6h-1v5h-1v3h-1v4h-1v2h-1v2h-1v2h-1v3h-1v2h-1v1h-1v2h-1v1h-1v2h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-2v1h-1v1h-2v1h-2v1h-1v1h-2v1h-3v1h-2v1h-3v1h-3v1h-8v1h-2v-1h-8v-1h-4v-1h-3v-1h-3v-1h-2v-1h-2v-1h-2v-1h-2v-1h-1v-1h-2v-1h-1v-1h-2v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-2h-1v-1h-1v-2h-1v-1h-1v-2h-1v-2h-1v-2h-1v-3h-1v-2h-1v-4h-1v-4h-1v-11h-1v-18h1v-2h-1v-2h1v-69h-1v-11h-1v-1h-2v-1h-2v-1h-2v-1h-2v-1h-2v-1h-2v-1h-2v-1h-1v-1h-2v-1h-2v-1h-1v-1h-2v-1h-2v-1h-1v-1h-1v-1h-2v-1h-1v-1h-2v-1h-1v-1h-1v-1h-1v-1h-2v-1h-1v-1h-1v-1h-2v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-2v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-2h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-2h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-2h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-2h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-2h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-2h-2v-2h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-2v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-2v-1h-1v-1h-1v-1h-1v-1h-2v-1h-1v-1h-1v-1h-2v-1h-1v-1h-1v-1h-2v-1h-1v-1h-2v-1h-1v-1h-2v-1h-1v-1h-2v-1h-1v-1h-2v-1h-2v-1h-2v-1h-1v-1h-2v-1h-2v-1h-2v-1h-2v-1h-2v-1h-2v-1h-3v-1h-2v-1h-3v-1h-2v-1h-3v-1h-3v-1h-3v-1h-3v-1h-3v-1h-4v-1h-3v-1h-5v-1h-5v-1h-5v-1h-8v-1h-12v-1h-1v1h-2v-1h-3v1h-1v-1h-1v1h-1v-1h-1v1h-1v-1h-1v1h-12v1h-8v1h-6v1h-4v1h-5v1h-4v1h-3v1h-4v1h-3v1h-3v1h-3v1h-3v1h-3v1h-3v1h-2v1h-3v1h-2v1h-3v1h-2v1h-2v1h-2v1h-3v1h-1v1h-3v1h-1v1h-2v1h-2v1h-2v1h-2v1h-2v1h-2v1h-1v1h-2v1h-1v1h-2v1h-2v1h-1v1h-2v1h-1v1h-1v1h-2v1h-2v1h-1v1h-1v1h-2v1h-1v1h-1v1h-2v1h-1v1h-2v1h-1v1h-1v1h-2v1h-2v1h-2v1h-4v-1h-3v-1h-1v-1h-2v-1h-1v-2h-1v-2h-1v-5h1v-3h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h2v-1h1v-1h1v-1h2v-1h1v-1h2v-1h1v-1h2v-1h1v-1h1v-1h2v-1h1v-1h2v-1h1v-1h2v-1h2v-1h1v-1h2v-1h1v-1h2v-1h2v-1h1v-1h2v-1h2v-1h2v-1h2v-1h2v-1h2v-1h1v-1h3v-1h2v-1h2v-1h2v-1h2v-1h2v-1h2v-1h3v-1h2v-1h3v-1h3v-1h2v-1h3v-1h4v-1h3v-1h3v-1h3v-1h4v-1h3v-1h5v-1h4v-1h7v-1h5v-1h8v-1h15v-1h3v1h6v-1h2v1h15v1h8v1h6v1h6v1h4v1h5v1h3v1h4v1h3v1h3v1h3v1h3v1h3v1h3v1h2v1h3v1h1v1h3v1h2v1h2v1h2v1h2v1h2v1h2v1h2v1h1v1h2v1h2v1h2v1h1v1h2v1h1v1h2v1h1v1h2v1h1v1h2v1h1v1h1v1h2v1h1v1h1v1h2v1h1v1h1v1h1v1h2v1h1v1h1v1h1v1h1v1h1v1h1v1h2v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v2h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v2h2v2h1v1h1v1h1v1h1v1h1v1h1v1h1v2h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v2h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v2h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v2h2v2h1v1h2v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h2v1h1v1h1v1h1v1h1v1h1v1h2v1h1v1h1v1h2v1h1v1h1v1h2v1h1v1h2v1h2v1h1v1h2v1h2v1h1v1h3v-13h-1v-1h1v-4h-1v-7h3v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h2v2h1v16h2v1h3v1h3v1h3v1h3v1h1v1h1v1h1v1h1v1h1v1h1v2h1v1h1v1h1v2h1v1h1v2h1v2h1v1h1v2h1v3h-10v-1h-6v-1h-5v-1h-4v-1h-4v95h1v6h1v4h1v3h1v2h1v2h1v2h1v1h1v1h1v2h2v2h2v1h1v1h1v1h2v1h1v1h2v1h3v1h3v1h12v-1h3v-1h2v-1h3v-1h1v-1h1v-1h2v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-2h1v-2h1v-1h1v-3h1v-2h1v-4h1v-3h1v-7h1v-18h-1v-10h-1v-6h-1v-5h-1v-4h-1v-4h-1v-4h-1v-4h-1v-3h-1v-3h-1v-3h-1v-2h-1v-3h-1v-3h-1v-2h-1v-3h-1v-2h-1v-3h-1v-2h-1v-2h-1v-2h-1v-2h-1v-2h-1v-2h-1v-2h-1v-1h-1v-2h-1v-2h-1v-1h-1v-2h-1v-1h-1v-2h-1v-1h-1v-2h-1v-1h-1v-2h-1v-1h-1v-1h-1v-2h-1v-1h-1v-2h-1v-1h-1v-1h-1v-1h-1v-2h-1v-1h-1v-1h-1v-1h-1v-2h-1v-1h-1v-1h-1v-1h-1v-1h-1v-2h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-2h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-2h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-2h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-2h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-2h-1v-1h-1v-1h-1v-1h-1v-1h-1v-2h-1v-1h-1v-1h-1v-2h-1v-1h-1v-1h-1v-2h-1v-1h-1v-2h-1v-1h-1v-2h-1v-1h-1v-2h-1v-1h-1v-2h-1v-1h-1v-2h-1v-2h-1v-2h-1v-1h-1v-2h-1v-2h-1v-2h-1v-2h-1v-2h-1v-2h-1v-3h-1v-3h-1v-3h-1v-3h-1v-4h-1v-5h-1v-6h-1v-20h1v-6h1v-4h1v-3h1v-3h1v-3h1v-2h1v-2h1v-2h1v-2h1v-2h1v-2h1v-1h1v-2h1v-1h1v-1h1v-2h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h2v-1h1v-1h1v-1h1v-1h2v-1h1v-1h2v-1h2v-1h1v-1h2v-1h2v-1h2v-1h3v-1h2V555h1v-10h1v-5h1v-4h1v-4h1v-2h1v-2h1v-3h1v-1h1v-2h1v-1h1v-2h1v-1h1v-2h1v-1h1v-1h1v-1h1v-2h1v-1h1v-1h1v-1h1v-1h1v-1h2v-1h1v-1h2v-1h1v-1h2v-1h1v-1h2v-1h2v-1h2v-1h2v-1h3v-1h5v-1h3v-1h10v-1h66zm271 40v2h1v3h1v9h1v68h1v5h1v5h1v2h1v2h1v3h1v1h1v2h1v2h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h2v1h2v1h1v1h2v1h2v1h3v1h3v1h5v1h13v1h1v-1h1v1h3v-1h1v1h1v-1h1v1h3v-1h1v1h2v-1h6v1h5v-1h1v1h2v-1h3v1h2v-1h15v1h2v-1h1v1h1v-1h1v1h10v1h8v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-2h-2v-1h-1v-2h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-2v-2h-1v-1h-1v-1h-2v-2h-1v-1h-1v-1h-2v-2h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-2v-2h-1v-1h-1v-1h-2v-2h-2v-2h-2v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-2h-2v-2h-1v-1h-1v-1h-2v-2h-2v-1h-1v-1h-1v-1h-1v-2h-2v-2h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-2v-1h-1v-2h-2v-2h-2v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-2h-2v-2h-2v-1h-1v-1h-1v-2h-1v-1h-1v-1h-2v-2h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-2v-2h-2v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1z" opacity=".9"/><path fill="#e6c9bb" d="M544 1290h2v1h1v-1h1v2h1v53h-1v4h1v-1h1v-1h1v-1h2v-1h1v-1h1v-1h2v-1h1v-1h2v-1h2v-1h2v-1h3v-1h4v-1h6v-1h16v1h5v1h4v1h2v1h3v1h2v1h2v1h1v1h1v1h2v1h1v1h1v1h1v1h1v1h1v1h1v1h1v2h1v1h1v2h1v2h1v2h1v2h1v3h1v3h1v4h1v5h1v11h1v2h-1v1h1v69h-1v1h-33v-69h-1v-7h-1v-4h-1v-3h-1v-2h-1v-1h-1v-2h-1v-1h-1v-1h-1v-1h-2v-1h-2v-1h-2v-1h-3v-1h-11v1h-4v1h-2v1h-2v1h-2v1h-1v1h-1v1h-1v1h-1v2h-1v1h-1v2h-1v2h-1v3h-1v3h-1v4h-1v69h-1v1h-33v-168h1v-2h28zM1130 1290h1v1h1v169h-1v1h-32v-11h-1v1h-1v1h-1v1h-1v1h-2v1h-1v1h-2v1h-1v1h-3v1h-2v1h-2v1h-3v1h-5v1h-20v-1h-5v-1h-4v-1h-3v-1h-2v-1h-3v-1h-2v-1h-1v-1h-2v-1h-1v-1h-2v-1h-1v-1h-1v-1h-2v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-2h-1v-1h-1v-1h-1v-2h-1v-1h-1v-2h-1v-2h-1v-2h-1v-2h-1v-3h-1v-2h-1v-4h-1v-3h-1v-5h-1v-24h1v-5h1v-4h1v-3h1v-3h1v-3h1v-1h1v-3h1v-2h1v-2h1v-1h1v-2h1v-1h1v-2h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h2v-1h1v-1h1v-1h2v-1h1v-1h2v-1h2v-1h2v-1h2v-1h3v-1h4v-1h5v-1h19v1h5v1h3v1h3v1h2v1h2v1h2v1h1v1h2v1h1v1h1v1h1v1h2v-55h1v-1h31zm-68 75v1h-3v1h-3v1h-2v1h-2v1h-1v1h-2v1h-1v2h-1v1h-1v2h-1v2h-1v2h-1v2h-1v2h-1v4h-1v5h-1v9h1v7h1v3h1v2h1v3h1v1h1v2h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h2v1h2v1h3v1h5v1h9v-1h4v-1h3v-1h2v-1h2v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-2h1v-2h1v-2h1v-3h1v-5h1v-14h-1v-5h-1v-3h-1v-2h-1v-3h-1v-1h-1v-2h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-2v-1h-1v-1h-2v-1h-2v-1h-4v-1h-12ZM429 1306h33v2h1v18h-1v3h1v5h-1v3h29v29h-29v2h1v56h1v3h1v1h1v2h1v1h2v1h2v1h5v1h1v-1h7v-1h2v-1h2v-1h2v1h1v3h1v2h1v4h1v2h1v4h1v3h1v2h1v3h1v2h-2v1h-1v1h-1v1h-2v1h-2v1h-3v1h-4v1h-6v1h-1v-1h-1v1h-8v-1h-7v-1h-4v-1h-3v-1h-3v-1h-2v-1h-2v-1h-2v-1h-1v-1h-1v-1h-1v-1h-2v-1h-1v-2h-1v-1h-1v-1h-1v-2h-1v-1h-1v-2h-1v-3h-1v-2h-1v-4h-1v-4h-1v-64h-18v-29h18v-31Z" opacity=".9"/><path fill="#b8a49a" d="M1446 1306h34v31h29v2h1v2h-1v1h1v23h-1v1h-29v59h1v2h1v2h1v1h1v1h1v1h2v1h3v1h6v-1h4v-1h3v-1h2v-1h2v2h1v2h1v3h1v3h1v3h1v3h1v2h1v3h1v3h1v1h-1v1h-1v1h-1v1h-1v1h-2v1h-3v1h-2v1h-5v1h-7v1h-10v-1h-8v-1h-3v-1h-3v-1h-3v-1h-2v-1h-1v-1h-2v-1h-1v-1h-1v-1h-2v-1h-1v-1h-1v-2h-1v-1h-1v-1h-1v-2h-1v-1h-1v-3h-1v-3h-1v-2h-1v-5h-1v-5h-1v-1h1v-1h-1v-59h-18v-1h-1v-4h1v-2h-1v-1h1v-18h-1v-1h1v-2h19v-5h-1v-1h1v-3h-1v-9h1v-1h-1v-1h1v-11Z" opacity=".9"/><path fill="#e6c9bb" d="M719 1335h12v34h-18v1h-3v1h-2v1h-2v1h-1v1h-1v1h-2v1h-1v1h-1v2h-1v1h-1v2h-1v1h-1v3h-1v3h-1v3h-1v4h-1v65h-34v-123h1v-1h32v9h-1v1h1v1h-1v3h2v-1h1v-2h2v-1h1v-1h1v-1h1v-1h2v-1h1v-1h2v-1h2v-1h2v-1h2v-1h2v-1h3v-1h5zM793 1335h16v1h7v1h4v1h3v1h3v1h2v1h2v1h2v1h1v1h2v1h1v1h1v1h2v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v2h1v1h1v2h1v1h1v2h1v2h1v2h1v2h1v2h1v3h1v3h1v4h1v4h1v8h1v16h-1v1h-10v1h-3v-1h-1v1h-72v2h1v4h1v1h1v2h1v2h1v1h1v1h1v1h1v1h1v1h1v1h1v1h2v1h2v1h3v1h6v1h17v-1h4v-1h3v-1h2v-1h2v-1h2v-1h1v-1h1v-1h2v-1h1v-1h3v1h1v1h1v1h1v1h1v1h1v1h1v2h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v3h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-2v1h-1v1h-1v1h-2v1h-2v1h-1v1h-2v1h-3v1h-3v1h-2v1h-4v1h-4v1h-11v1h-1v-1h-16v-1h-5v-1h-3v-1h-3v-1h-3v-1h-2v-1h-3v-1h-2v-1h-1v-1h-2v-1h-1v-1h-2v-1h-1v-1h-2v-1h-1v-1h-1v-1h-1v-1h-2v-1h-1v-1h-1v-2h-1v-1h-1v-1h-1v-1h-1v-2h-1v-1h-1v-2h-1v-2h-1v-2h-1v-2h-1v-2h-1v-3h-1v-3h-1v-5h-1v-5h-1v-21h1v-5h1v-4h1v-4h1v-2h1v-3h1v-2h1v-2h1v-2h1v-2h1v-2h1v-1h1v-1h1v-2h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h2v-1h1v-1h2v-1h1v-1h2v-1h2v-1h2v-1h2v-1h3v-1h2v-1h5v-1h7zm4 28v1h-5v1h-3v1h-2v1h-2v1h-1v1h-2v1h-1v1h-1v1h-1v2h-1v1h-1v2h-1v2h-1v3h-1v4h-1v1h54v-4h-1v-4h-1v-2h-1v-2h-1v-2h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-2v-1h-2v-1h-2v-1h-3v-1h-5v-1h-7ZM919 1335h20v1h8v1h4v1h3v1h3v1h2v1h2v1h2v1h1v1h2v1h1v1h1v1h2v1h1v1h1v1h1v1h1v2h1v1h1v1h1v2h1v1h1v3h1v2h1v2h1v3h1v3h1v5h1v7h1v78h-31v-11h-1v1h-1v1h-1v1h-1v1h-1v1h-2v1h-1v1h-2v1h-2v1h-2v1h-2v1h-2v1h-4v1h-7v1h-11v-1h-6v-1h-5v-1h-3v-1h-2v-1h-2v-1h-2v-1h-2v-1h-2v-1h-1v-1h-2v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-2h-1v-1h-1v-2h-1v-1h-1v-2h-1v-3h-1v-3h-1v-8h-1v-1h1v-8h1v-4h1v-2h1v-3h1v-2h1v-1h1v-2h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h2v-1h1v-1h2v-1h2v-1h3v-1h3v-1h4v-1h4v-1h6v-1h35v-6h-1v-4h-1v-2h-1v-2h-1v-1h-1v-1h-1v-1h-1v-1h-2v-1h-1v-1h-3v-1h-3v-1h-8v-1h-1v1h-10v1h-5v1h-4v1h-2v1h-3v1h-2v1h-1v1h-2v1h-2v1h-1v1h-2v-1h-1v-1h-1v-3h-1v-2h-1v-2h-1v-2h-1v-2h-1v-3h-1v-2h-1v-2h-1v-2h-1v-3h1v-1h1v-1h2v-1h1v-1h2v-1h2v-1h2v-1h2v-1h3v-1h3v-1h3v-1h3v-1h6v-1h7zm6 73v1h-5v1h-2v1h-2v1h-2v1h-1v1h-1v1h-1v2h-1v2h-1v9h1v2h1v2h1v1h1v1h2v1h1v1h2v1h4v1h14v-1h2v-1h2v-1h2v-1h1v-1h2v-1h1v-1h1v-1h1v-1h1v-1h1v-2h1v-5h1v-13h-27Z" opacity=".9"/><path fill="#b8a49a" d="M1218 1335h17v1h5v1h3v1h3v1h2v1h2v1h2v1h1v1h2v1h1v1h1v1h2v2h1v1h1v1h1v1h1v2h1v1h1v1h1v3h1v1h1v3h1v2h1v4h1v5h1v6h1v1h-1v1h1v80h-3v1h-1v-1h-8v1h-2v-1h-1v1h-1v-1h-18v-72h-1v-1h1v-1h-1v-5h-1v-3h-1v-3h-1v-1h-1v-2h-1v-1h-1v-1h-1v-1h-1v-1h-2v-1h-3v-1h-3v-1h-10v1h-4v1h-2v1h-2v1h-1v1h-1v1h-2v1h-1v1h-1v2h-1v2h-1v1h-1v2h-1v4h-1v2h-1v7h-1v66h-1v1h-1v1h-1v-1h-10v1h-2v-1h-18v-1h-1v-123h32v12h2v-1h1v-1h1v-1h1v-1h1v-1h2v-1h2v-1h1v-1h2v-1h2v-1h2v-1h2v-1h4v-1h6zM1348 1335h19v1h6v1h4v1h3v1h2v1h3v1h2v1h2v1h2v1h1v1h3v1h1v1h1v1h2v2h2v1h1v1h1v1h1v1h1v1h1v1h1v1h1v2h1v1h1v2h1v1h1v2h1v1h1v3h1v2h1v2h1v3h1v3h1v5h1v5h1v21h-1v6h-1v3h-1v4h-1v2h-1v3h-1v2h-1v2h-1v1h-1v2h-1v2h-1v1h-1v1h-1v1h-1v2h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-2v1h-1v1h-1v1h-1v1h-2v1h-2v1h-2v1h-2v1h-1v1h-3v1h-3v1h-2v1h-4v1h-5v1h-6v1h-1v-1h-1v1h-10v-1h-8v-1h-5v-1h-3v-1h-4v-1h-2v-1h-2v-1h-2v-1h-2v-1h-2v-1h-2v-1h-1v-1h-2v-1h-1v-1h-2v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-2h-1v-1h-1v-2h-1v-1h-1v-2h-1v-2h-1v-2h-1v-3h-1v-2h-1v-3h-1v-4h-1v-4h-1v-7h-1v-13h1v-6h1v-4h1v-4h1v-3h1v-3h1v-2h1v-2h1v-1h1v-2h1v-2h1v-1h1v-2h1v-1h1v-2h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h2v-1h1v-1h1v-1h1v-1h2v-1h2v-1h1v-1h3v-1h1v-1h2v-1h3v-1h3v-1h5v-1h7zm3 30v1h-4v1h-3v1h-2v1h-2v1h-1v1h-2v1h-1v1h-1v2h-1v1h-1v1h-1v2h-1v1h-1v2h-1v3h-1v2h-1v4h-1v16h1v5h1v2h1v3h1v1h1v2h1v2h2v2h1v1h2v2h2v1h1v1h2v1h2v1h3v1h4v1h9v-1h6v-1h3v-1h2v-1h2v-2h2v-1h1v-1h1v-1h1v-1h1v-1h1v-2h1v-1h1v-2h1v-2h1v-3h1v-3h1v-8h1v-3h-1v-9h-1v-4h-1v-2h-1v-2h-1v-2h-1v-2h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-2v-1h-1v-1h-1v-1h-2v-1h-3v-1h-4v-1h-11ZM1577 1335h13v1h7v1h5v1h3v1h2v1h3v1h2v1h2v1h1v1h2v1h1v1h2v1h1v1h2v2h1v1h2v1h1v2h1v1h1v1h1v1h1v1h1v2h1v1h1v2h1v1h1v3h1v2h1v2h1v4h1v3h1v4h1v5h1v1h-1v1h1v21h-87v4h1v3h1v1h1v2h1v2h2v2h1v1h1v1h2v1h1v1h2v1h2v1h1v1h3v1h5v1h14v-1h5v-1h3v-1h3v-1h2v-1h1v-1h1v-1h2v-1h1v-1h1v-1h1v-1h3v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v4h-1v1h-1v1h-1v1h-1v1h-1v1h-2v2h-2v1h-1v1h-1v1h-2v1h-2v1h-1v1h-2v1h-3v1h-2v1h-2v1h-4v1h-5v1h-9v1h-9v-1h-10v-1h-5v-1h-4v-1h-3v-1h-3v-1h-2v-1h-2v-1h-2v-1h-2v-1h-2v-1h-1v-1h-2v-1h-1v-1h-2v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-2h-1v-1h-1v-1h-1v-2h-1v-1h-1v-2h-1v-2h-1v-2h-1v-1h-1v-3h-1v-3h-1v-3h-1v-5h-1v-6h-1v-13h1v-7h1v-5h1v-3h1v-3h1v-4h1v-2h1v-2h1v-2h1v-2h1v-1h1v-2h1v-2h1v-1h1v-1h1v-2h2v-2h1v-1h1v-1h1v-1h1v-1h2v-2h2v-1h1v-1h2v-1h1v-1h1v-1h3v-1h1v-1h3v-1h1v-1h3v-1h2v-1h5v-1h9zm2 28v1h-5v1h-2v1h-3v1h-2v1h-1v1h-1v1h-2v1h-1v2h-1v1h-1v1h-1v2h-1v2h-1v2h-1v4h-1v2h54v-5h-1v-2h-1v-3h-1v-2h-1v-1h-1v-1h-1v-1h-1v-2h-2v-1h-1v-1h-1v-1h-2v-1h-2v-1h-3v-1h-4v-1z" opacity=".9"/></g><defs><clipPath id="a"><path fill="#000" d="M0 0h2048v2048H0z"/></clipPath></defs></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="2048" height="2048" fill="none" viewBox="0 0 2048 2048"><g stroke="#475b65" clip-path="url(#a)"><path fill="#475b65" d="M931 491h2v1h3v-1h5v1h3v-1h1v1h1v-1h3v1h3v-1h8v1h4v-1h1v1h7v-1h1v1h23v-1h1v1h67v-1h1v1h2v-1h2v1h3v-1h12v1h1v-1h13v1h3v-1h16v1h1v-1h2v1h41v1h10v1h6v1h4v1h4v1h4v1h2v1h3v1h2v1h3v1h2v1h2v1h2v1h2v1h1v1h2v1h2v1h1v1h1v1h1v1h2v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v2h2v1h1v1h1v1h1v1h1v1h1v1h1v2h2v2h2v1h1v1h1v2h2v2h1v1h2v2h2v1h1v1h1v1h1v1h1v2h2v2h2v1h1v2h2v2h2v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v2h1v1h1v1h1v1h1v2h1v1h1v2h1v1h1v2h1v1h1v2h1v2h1v2h1v2h1v2h1v2h1v2h1v3h1v3h1v3h1v4h1v4h1v6h1v10h1v427h-1v8h-1v5h-1v3h-1v3h-1v3h-1v2h-1v2h-1v2h-1v2h-1v2h-1v1h-1v1h-1v2h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-2v1h-1v1h-2v1h-1v1h-2v1h-3v1h-1v1h-3v1h-3v1h-2v1h-4v1h-5v1h-11v1h-1v-1h-3v1h-2v-1h-1v1h-2v-1h-1v1h-1v-1h-1v1h-6v-1h-4v1h-1v-1h-1v1h-1v-1h-1v1h-3v-1h-1v1h-1v-1h-3v1h-1v-1h-1v1h-1v-1h-3v1h-1v-1h-7v1h-1v-1h-69v1h-2v-1H902v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-2h1v-1h1v-2h1v-1h1v-1h1v-2h2v-1h1v-1h392v-1h3v-1h3v-1h2v-1h3v-1h1v-1h2v-1h2v-2h2v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-2h1v-2h1v-1h1v-1h1v-2h1v-3h1v-2h1v-4h1v-5h1V709h-1v-1h1v-1h-1v-7h-1v-4h-1v-3h-1v-2h-1v-2h-1v-2h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-2v-1h-1v-1h-2v-1h-2v-1h-4v-1h-4v-1h-70v-1h-10v-1h-6v-1h-3v-1h-4v-1h-2v-1h-3v-1h-1v-1h-3v-1h-1v-1h-3v-1h-1v-1h-1v-1h-2v-1h-1v-1h-1v-1h-1v-1h-2v-1h-1v-1h-1v-1h-1v-1h-1v-2h-2v-2h-1v-1h-1v-1h-1v-1h-1v-2h-1v-2h-1v-2h-1v-1h-1v-2h-1v-2h-1v-2h-1v-3h-1v-3h-1v-4h-1v-5h-1v-68h-1v-10h-1v-5h-1v-3h-1v-2h-1v-2h-1v-2h-1v-1h-1v-2h-1v-1h-1v-1h-1v-1h-2v-1h-1v-1h-2v-1h-2v-1h-2v-1h-3v-1h-5v-1H863v1h-6v1h-3v1h-3v1h-2v1h-2v1h-1v1h-2v1h-1v1h-1v1h-2v1h-1v1h-1v1h-1v2h-1v1h-1v1h-1v2h-1v2h-1v1h-1v3h-1v3h-1v4h-1v5h-1v230h1v-1h6v-1h10v-1h2v1h9v-1h2v1h34v-1h7v-1h4v-1h3v-1h2v-1h3v-1h2v-1h2v-1h1v-1h2v-1h1v-1h2v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h2v-2h1v-1h1v-1h1v-1h1v-1h1v-2h1v-1h1v-2h1v-1h1v-2h1v-2h1v-2h1v-2h1v-2h1v-2h1v-3h1v-2h1v-3h1v-2h1v-3h1v-3h1v-3h1v-2h1v-3h1v-2h1v-2h1v-2h1v-1h1v-2h1v-2h1v-1h1v-1h1v-2h2v-2h2v-1h1v-1h1v-1h2v-1h2v-1h2v-1h4v-1h8v1h5v1h3v1h2v1h1v1h1v1h2v1h1v2h1v1h1v1h1v2h1v1h1v2h1v3h1v3h1v4h1v8h1v30h1v1h-1v1h1v4h1v5h1v2h1v2h1v2h1v1h2v1h1v1h5v-1h1v-1h2v-1h1v-1h1v-1h1v-1h1v-2h1v-1h1v-2h1v-1h1v-2h1v-1h1v-2h1v-1h1v-2h1v-1h1v-2h1v-1h1v-2h1v-1h1v-2h1v-1h1v-1h1v-2h1v-1h1v-1h1v-1h1v-2h1v-1h1v-1h1v-1h1v-1h2v-1h1v-1h2v-2h2v-1h3v-1h3v-1h6v-1h2v1h7v1h3v1h2v1h2v1h2v1h1v1h1v1h2v2h2v2h1v1h1v2h2v2h1v2h1v1h1v2h1v1h1v2h1v2h1v2h1v2h1v2h1v1h1v2h1v1h1v1h1v1h2v1h1v1h1v1h6v-1h2v-1h1v-1h2v-1h1v-2h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-2h2v-1h1v-1h1v-2h1v-1h2v-1h1v-1h2v-2h3v-1h2v-1h2v-1h2v-1h2v-1h6v-1h13v1h5v1h4v1h2v1h3v1h2v1h2v1h2v1h2v1h1v1h2v1h2v1h1v1h2v1h2v1h2v1h1v1h3v1h2v1h3v1h2v1h3v1h1v-1h1v1h12v-1h5v-1h2v-1h3v-1h2v-1h1v-1h1v-1h2v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h2v-1h1v-1h3v-1h5v1h2v1h1v1h2v2h1v1h1v2h1v4h-1v3h-1v2h-1v1h-1v1h-1v2h-2v1h-1v2h-2v1h-1v1h-1v1h-1v1h-1v1h-2v1h-1v1h-2v1h-2v1h-2v1h-3v1h-2v1h-3v1h-5v1h-21v-1h-4v-1h-4v-1h-3v-1h-3v-1h-2v-1h-2v-1h-2v-1h-2v-1h-2v-1h-1v-1h-2v-1h-2v-1h-1v-1h-2v-1h-2v-1h-2v-1h-1v-1h-2v-1h-3v-1h-2v-1h-5v-1h-8v1h-2v1h-3v1h-2v1h-1v1h-1v1h-1v1h-1v1h-2v1h-1v1h-1v1h-1v2h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-2v1h-1v1h-1v1h-2v1h-2v1h-2v1h-3v1h-5v1h-4v-1h-1v1h-1v-1h-4v-1h-3v-1h-2v-1h-2v-1h-1v-1h-2v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-2h-1v-1h-1v-1h-1v-2h-1v-2h-1v-1h-1v-2h-1v-2h-1v-2h-1v-2h-1v-1h-1v-2h-1v-1h-1v-2h-1v-2h-1v-1h-1v-1h-1v-1h-2v-1h-6v1h-3v1h-1v1h-1v1h-1v1h-1v1h-1v2h-1v1h-1v1h-1v2h-1v1h-1v1h-1v2h-1v1h-1v2h-1v1h-1v2h-1v1h-1v2h-1v1h-1v2h-1v1h-1v2h-1v1h-1v2h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-2v1h-1v1h-2v1h-2v1h-2v1h-4v1h-10v-1h-4v-1h-3v-1h-2v-1h-1v-1h-2v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-2h-1v-1h-1v-2h-1v-2h-1v-2h-1v-2h-1v-3h-1v-4h-1v-4h-1v-6h-1v-26h1v-1h-1v-12h-1v-2h-1v-1h-1v-1h-1v-1h-5v1h-1v1h-1v1h-1v2h-1v1h-1v3h-1v3h-1v2h-1v3h-1v3h-1v3h-1v3h-1v2h-1v3h-1v2h-1v2h-1v2h-1v2h-1v2h-1v2h-1v1h-1v2h-1v2h-1v1h-1v2h-1v2h-1v1h-1v2h-1v1h-1v1h-1v2h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-2v1h-1v1h-1v1h-2v1h-1v1h-2v1h-1v1h-2v1h-2v1h-2v1h-2v1h-2v1h-3v1h-3v1h-3v1h-4v1h-5v1h-6v1h-54v1h-8v1h-4v121h-3v-2h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-2h-1v-1h-1v-1h-1v-1h-1v-1h-1v-2h-1v-1h-1v-2h-1v-1h-1v-2h-1v-2h1v-1h-1v-1h1v-1h-1v-84h-2v1h-2v1h-1v1h-2v1h-1v1h-1v1h-2v1h-1v1h-1v1h-1v2h-1v1h-1v1h-1v1h-1v2h-1v1h-1v2h-1v1h-1v3h-1v2h-1v2h-1v3h-1v4h-1v6h-1v12h1v7h1v5h1v3h1v4h1v3h1v3h1v2h1v2h1v2h1v2h1v2h1v1h1v2h1v2h1v1h1v2h1v1h1v2h1v1h1v2h1v1h1v1h1v1h1v2h1v1h1v1h1v2h1v1h1v1h1v1h1v2h1v1h1v1h1v1h1v2h1v1h1v1h1v1h1v1h1v2h1v1h1v1h1v1h1v1h1v1h1v1h1v2h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v2h1v1h2v2h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v2h2v2h2v1h1v2h1v1h1v1h1v1h1v2h1v1h1v1h1v1h1v1h1v2h1v1h1v1h1v1h1v2h1v2h1v1h1v2h1v1h1v2h1v1h1v2h1v1h1v2h1v1h1v2h1v1h1v2h1v1h1v1h6v-1h3v-1h3v-1h3v-1h3v-1h2v-1h1v-1h3v-1h2v-1h2v-2h3v-1h1v-1h1v-1h1v-1h1v-1h2v-1h1v-2h2v-1h1v-1h1v-1h1v-1h1v-2h2v-2h1v-1h1v-2h1v-1h1v-1h1v-1h1v-2h1v-1h1v-2h1v-2h1v-1h1v-2h1v-1h1v-2h1v-2h1v-1h1v-1h1v-2h1v-1h1v-2h1v-2h1v-1h1v-2h1v-1h1v-2h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h2v-1h1v-1h2v-1h1v-1h3v-1h4v-1h11v1h3v1h3v1h2v1h1v1h2v1h2v2h1v1h1v1h1v1h1v1h1v1h1v3h1v1h1v2h1v2h1v3h1v4h1v3h1v5h1v4h1v5h1v3h1v4h1v3h1v2h1v2h1v2h2v1h1v1h4v-1h2v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-2h1v-2h1v-1h1v-2h1v-2h1v-1h1v-1h1v-2h1v-1h1v-1h1v-2h1v-1h1v-1h1v-2h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h2v-1h1v-1h2v-1h1v-1h3v-1h1v-1h4v-1h13v1h3v1h2v1h2v1h2v1h2v1h1v1h1v1h1v1h1v1h1v2h2v2h1v2h1v1h1v1h1v1h1v2h1v1h1v2h1v1h1v1h1v2h2v2h1v1h1v1h2v1h1v1h7v-1h3v-1h2v-1h2v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h2v-1h1v-1h1v-1h1v-1h2v-1h1v-1h2v-1h2v-1h2v-1h3v-1h5v-1h5v-1h1v1h1v-1h4v1h2v-1h1v1h5v1h4v1h4v1h3v1h2v1h2v1h2v1h3v1h2v1h2v1h3v1h3v1h3v1h4v1h4v1h13v-1h4v-1h2v-1h3v-1h3v-1h1v-1h2v-1h1v-1h2v-1h1v-1h1v-1h2v-2h2v-1h1v-2h1v-1h1v-1h1v-1h1v-2h1v-1h1v-1h1v-2h1v-2h1v-2h1v-2h1v-4h1v-3h1v-3h1v-9h1v-1h-1v-1h1v-2h-1v-2h1v-1h-1v-8h-1v-4h-1v-4h-1v-3h-1v-2h-1v-2h-1v-2h-1v-3h-1v-1h-1v-1h-1v-2h-1v-1h-1v-1h-1v-1h-1v-2h-1v-1h-1v-1h-1v-1h-2v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-2v-1h-2v-1h-1v-1h-1v-1h-2v-1h-3v-1h-2v-1h-2v-1h-4v-1h-3v-1h-5v-1h-11v-1h-3v1h-1v-1h-2v1h-11v1h-4v1h-4v1h-3v1h-3v1h-2v1h-3v1h-1v1h-2v1h-2v1h-1v1h-2v1h-2v1h-1v1h-1v1h-2v1h-1v1h-2v1h-1v1h-1v1h-1v1h-1v1h-1v1h-2v1h-1v1h-1v1h-1v1h-1v1h-2v1h-1v1h-2v1h-2v1h-2v1h-3v1h-3v1h-5v1h-2v-1h-3v1h-1v-1h-6v-1h-4v-1h-1v-1h-2v-1h-2v-1h-2v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-2h-1v-2h-1v-1h-1v-2h-1v-1h-1v-2h-1v-2h-1v-2h-1v-2h-1v-2h-1v-2h-1v-2h-1v-2h-1v-2h-1v-2h-1v-2h-1v-2h-1v-2h-1v-2h-1v-1h-1v-1h-1v-1h-1v-1h-2v-1h-7v1h-2v1h-1v1h-1v1h-1v1h-1v1h-1v2h-1v2h-1v1h-1v2h-1v1h-1v3h-1v1h-1v2h-1v1h-1v2h-1v2h-1v1h-1v2h-1v2h-1v1h-1v2h-1v2h-1v1h-1v1h-1v2h-2v2h-1v1h-2v2h-2v1h-1v1h-1v1h-1v1h-2v1h-2v1h-3v1h-5v1h-1v-1h-1v1h-1v-1h-6v-1h-3v-1h-2v-1h-1v-1h-2v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-2h-1v-1h-1v-2h-1v-1h-1v-2h-1v-2h-1v-2h-1v-2h-1v-2h-1v-1h-1v-2h-1v-3h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-2v-1h-2v1h-3v1h-1v1h-2v1h-1v1h-1v1h-1v1h-1v1h-1v2h-1v1h-1v1h-1v2h-1v1h-1v1h-1v1h-1v1h-1v2h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-2v1h-1v1h-1v1h-2v1h-1v1h-2v1h-2v1h-2v1h-2v1h-3v1h-5v1h-9v-1h-2v-1h-2v-1h-1v-1h-1v-1h-1v-1h-1v-3h-1v-5h1v-3h1v-1h1v-1h1v-1h2v-1h3v-1h6v-1h5v-1h3v-1h1v-1h2v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-2h1v-1h1v-2h1v-1h1v-1h1v-1h1v-2h1v-1h1v-1h1v-1h1v-1h1v-1h1v-2h2v-1h1v-1h1v-1h3v-1h2v-1h1v-1h5v-1h11v1h4v1h2v1h2v1h2v1h1v1h2v1h1v1h1v2h1v1h1v1h1v1h1v2h1v2h1v2h1v2h1v2h1v1h1v2h1v2h1v2h1v3h1v1h1v2h1v1h1v1h3v1h4v-1h2v-1h1v-1h1v-2h1v-2h1v-1h1v-2h1v-1h1v-1h1v-3h1v-1h1v-2h1v-1h1v-2h1v-3h1v-1h1v-2h1v-1h1v-3h1v-1h1v-2h1v-1h1v-1h1v-2h1v-1h1v-2h2v-1h1v-2h2v-1h1v-1h2v-1h1v-1h1v-1h3v-1h2v-1h4v-1h10v1h4v1h4v1h2v1h1v1h2v1h1v1h1v1h2v1h1v2h1v1h1v2h2v3h1v1h1v1h1v3h1v2h1v2h1v1h1v2h1v3h1v2h1v2h1v2h1v2h1v2h1v1h1v2h1v2h1v1h1v1h1v1h1v1h1v1h1v1h2v1h3v1h1v-1h4v-1h1v-1h2v-1h2v-1h2v-2h2v-1h1v-1h1v-1h2v-2h2v-1h1v-1h1v-1h2v-2h2v-1h1v-1h2v-1h2v-1h1v-1h2v-1h1v-1h2v-1h2v-1h1v-1h2v-1h2v-1h3v-1h2v-1h2v-1h2v-1h5v-1h4v-1h5v-1h4v-1h28v1h5v1h5v1h4v1h3v1h3v1h2v1h3v1h2v1h2v1h1v1h2v1h2v1h2v1h2v1h1v1h1v1h1v1h2v1h1v1h2v2h2v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v2h1v1h1v2h2v2h1v1h1v2h1v1h1v2h1v2h1v3h1v2h1v2h1v2h1v4h1v4h1v4h1v8h1v16h-1v6h-1v4h-1v4h-1v3h-1v3h-1v3h-1v2h-1v2h-1v2h-1v3h-1v1h-1v2h-1v2h-1v1h-1v1h-1v1h-1v2h-1v1h-1v1h-1v2h-1v1h-1v1h-1v1h-1v1h-1v1h-2v1h-1v1h-1v1h-1v1h-2v1h-1v1h-2v1h-1v1h-2v1h-2v1h-1v1h-3v1h-2v1h-3v1h-4v1h-4v1h-10v1h-1v-1h-1v1h-1v-1h-11v-1h-4v-1h-4v-1h-3v-1h-3v-1h-2v-1h-2v-1h-3v-1h-2v-1h-2v-1h-2v-1h-3v-1h-2v-1h-2v-1h-3v-1h-13v1h-3v1h-2v1h-2v1h-1v1h-1v1h-1v1h-2v1h-1v1h-1v1h-2v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-2v1h-1v1h-2v1h-1v1h-2v1h-2v1h-2v1h-2v1h-4v1h-15v-1h-2v-1h-3v-1h-2v-1h-2v-1h-1v-1h-2v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-2h-1v-1h-1v-1h-1v-2h-1v-1h-1v-2h-1v-2h-1v-1h-1v-1h-1v-2h-1v-1h-1v-1h-2v-1h-1v-1h-6v1h-2v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v2h-1v1h-1v2h-1v1h-1v1h-1v2h-1v2h-1v1h-1v1h-1v2h-1v1h-1v1h-1v2h-1v1h-1v1h-1v1h-1v1h-1v2h-1v1h-1v1h-1v1h-1v1h-2v1h-1v1h-1v1h-1v1h-2v1h-2v1h-2v1h-4v1h-7v-1h-5v-1h-3v-1h-2v-1h-2v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-2h-1v-1h-1v-2h-1v-2h-1v-2h-1v-3h-1v-3h-1v-2h-1v-5h-1v-4h-1v-6h-1v-4h-1v-5h-1v-3h-1v-2h-1v-2h-1v-2h-1v-1h-2v-1h-3v-1h-2v1h-2v1h-2v1h-1v1h-1v2h-1v1h-1v2h-1v1h-1v2h-1v2h-1v1h-1v2h-1v1h-1v2h-1v1h-1v2h-1v2h-1v1h-1v2h-1v1h-1v1h-1v2h-1v2h-1v1h-1v2h-1v1h-1v1h-1v2h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-2v1h-1v1h-1v1h-2v1h-1v1h-2v1h-1v1h-2v1h-1v1h-2v1h-2v1h-2v1h-3v1h-2v1h-2v1h-3v1h-3v1h-3v1h-3v2h1v3h1v2h1v3h1v3h1v2h1v3h1v3h1v3h1v4h1v3h1v4h1v4h1v4h1v4h1v6h1v6h1v7h1v25h-1v1h1v1h-1v6h-1v5h-1v3h-1v4h-1v2h-1v2h-1v2h-1v3h-1v2h-1v1h-1v2h-1v1h-1v2h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-2v1h-1v1h-2v1h-2v1h-1v1h-2v1h-3v1h-2v1h-3v1h-3v1h-8v1h-2v-1h-8v-1h-4v-1h-3v-1h-3v-1h-2v-1h-2v-1h-2v-1h-2v-1h-1v-1h-2v-1h-1v-1h-2v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-2h-1v-1h-1v-2h-1v-1h-1v-2h-1v-2h-1v-2h-1v-3h-1v-2h-1v-4h-1v-4h-1v-11h-1v-18h1v-2h-1v-2h1v-69h-1v-11h-1v-1h-2v-1h-2v-1h-2v-1h-2v-1h-2v-1h-2v-1h-2v-1h-1v-1h-2v-1h-2v-1h-1v-1h-2v-1h-2v-1h-1v-1h-1v-1h-2v-1h-1v-1h-2v-1h-1v-1h-1v-1h-1v-1h-2v-1h-1v-1h-1v-1h-2v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-2v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-2h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-2h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-2h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-2h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-2h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-2h-2v-2h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-2v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-2v-1h-1v-1h-1v-1h-1v-1h-2v-1h-1v-1h-1v-1h-2v-1h-1v-1h-1v-1h-2v-1h-1v-1h-2v-1h-1v-1h-2v-1h-1v-1h-2v-1h-1v-1h-2v-1h-2v-1h-2v-1h-1v-1h-2v-1h-2v-1h-2v-1h-2v-1h-2v-1h-2v-1h-3v-1h-2v-1h-3v-1h-2v-1h-3v-1h-3v-1h-3v-1h-3v-1h-3v-1h-4v-1h-3v-1h-5v-1h-5v-1h-5v-1h-8v-1h-12v-1h-1v1h-2v-1h-3v1h-1v-1h-1v1h-1v-1h-1v1h-1v-1h-1v1h-12v1h-8v1h-6v1h-4v1h-5v1h-4v1h-3v1h-4v1h-3v1h-3v1h-3v1h-3v1h-3v1h-3v1h-2v1h-3v1h-2v1h-3v1h-2v1h-2v1h-2v1h-3v1h-1v1h-3v1h-1v1h-2v1h-2v1h-2v1h-2v1h-2v1h-2v1h-1v1h-2v1h-1v1h-2v1h-2v1h-1v1h-2v1h-1v1h-1v1h-2v1h-2v1h-1v1h-1v1h-2v1h-1v1h-1v1h-2v1h-1v1h-2v1h-1v1h-1v1h-2v1h-2v1h-2v1h-4v-1h-3v-1h-1v-1h-2v-1h-1v-2h-1v-2h-1v-5h1v-3h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h2v-1h1v-1h1v-1h2v-1h1v-1h2v-1h1v-1h2v-1h1v-1h1v-1h2v-1h1v-1h2v-1h1v-1h2v-1h2v-1h1v-1h2v-1h1v-1h2v-1h2v-1h1v-1h2v-1h2v-1h2v-1h2v-1h2v-1h2v-1h1v-1h3v-1h2v-1h2v-1h2v-1h2v-1h2v-1h2v-1h3v-1h2v-1h3v-1h3v-1h2v-1h3v-1h4v-1h3v-1h3v-1h3v-1h4v-1h3v-1h5v-1h4v-1h7v-1h5v-1h8v-1h15v-1h3v1h6v-1h2v1h15v1h8v1h6v1h6v1h4v1h5v1h3v1h4v1h3v1h3v1h3v1h3v1h3v1h3v1h2v1h3v1h1v1h3v1h2v1h2v1h2v1h2v1h2v1h2v1h2v1h1v1h2v1h2v1h2v1h1v1h2v1h1v1h2v1h1v1h2v1h1v1h2v1h1v1h1v1h2v1h1v1h1v1h2v1h1v1h1v1h1v1h2v1h1v1h1v1h1v1h1v1h1v1h1v1h2v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v2h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v2h2v2h1v1h1v1h1v1h1v1h1v1h1v1h1v2h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v2h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v2h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v2h2v2h1v1h2v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h2v1h1v1h1v1h1v1h1v1h1v1h2v1h1v1h1v1h2v1h1v1h1v1h2v1h1v1h2v1h2v1h1v1h2v1h2v1h1v1h3v-13h-1v-1h1v-4h-1v-7h3v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h2v2h1v16h2v1h3v1h3v1h3v1h3v1h1v1h1v1h1v1h1v1h1v1h1v2h1v1h1v1h1v2h1v1h1v2h1v2h1v1h1v2h1v3h-10v-1h-6v-1h-5v-1h-4v-1h-4v95h1v6h1v4h1v3h1v2h1v2h1v2h1v1h1v1h1v2h2v2h2v1h1v1h1v1h2v1h1v1h2v1h3v1h3v1h12v-1h3v-1h2v-1h3v-1h1v-1h1v-1h2v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-2h1v-2h1v-1h1v-3h1v-2h1v-4h1v-3h1v-7h1v-18h-1v-10h-1v-6h-1v-5h-1v-4h-1v-4h-1v-4h-1v-4h-1v-3h-1v-3h-1v-3h-1v-2h-1v-3h-1v-3h-1v-2h-1v-3h-1v-2h-1v-3h-1v-2h-1v-2h-1v-2h-1v-2h-1v-2h-1v-2h-1v-2h-1v-1h-1v-2h-1v-2h-1v-1h-1v-2h-1v-1h-1v-2h-1v-1h-1v-2h-1v-1h-1v-2h-1v-1h-1v-1h-1v-2h-1v-1h-1v-2h-1v-1h-1v-1h-1v-1h-1v-2h-1v-1h-1v-1h-1v-1h-1v-2h-1v-1h-1v-1h-1v-1h-1v-1h-1v-2h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-2h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-2h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-2h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-2h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-2h-1v-1h-1v-1h-1v-1h-1v-1h-1v-2h-1v-1h-1v-1h-1v-2h-1v-1h-1v-1h-1v-2h-1v-1h-1v-2h-1v-1h-1v-2h-1v-1h-1v-2h-1v-1h-1v-2h-1v-1h-1v-2h-1v-2h-1v-2h-1v-1h-1v-2h-1v-2h-1v-2h-1v-2h-1v-2h-1v-2h-1v-3h-1v-3h-1v-3h-1v-3h-1v-4h-1v-5h-1v-6h-1v-20h1v-6h1v-4h1v-3h1v-3h1v-3h1v-2h1v-2h1v-2h1v-2h1v-2h1v-2h1v-1h1v-2h1v-1h1v-1h1v-2h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h2v-1h1v-1h1v-1h1v-1h2v-1h1v-1h2v-1h2v-1h1v-1h2v-1h2v-1h2v-1h3v-1h2V555h1v-10h1v-5h1v-4h1v-4h1v-2h1v-2h1v-3h1v-1h1v-2h1v-1h1v-2h1v-1h1v-2h1v-1h1v-1h1v-1h1v-2h1v-1h1v-1h1v-1h1v-1h1v-1h2v-1h1v-1h2v-1h1v-1h2v-1h1v-1h2v-1h2v-1h2v-1h2v-1h3v-1h5v-1h3v-1h10v-1h66zm271 40v2h1v3h1v9h1v68h1v5h1v5h1v2h1v2h1v3h1v1h1v2h1v2h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h2v1h2v1h1v1h2v1h2v1h3v1h3v1h5v1h13v1h1v-1h1v1h3v-1h1v1h1v-1h1v1h3v-1h1v1h2v-1h6v1h5v-1h1v1h2v-1h3v1h2v-1h15v1h2v-1h1v1h1v-1h1v1h10v1h8v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-2h-2v-1h-1v-2h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-2v-2h-1v-1h-1v-1h-2v-2h-1v-1h-1v-1h-2v-2h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-2v-2h-1v-1h-1v-1h-2v-2h-2v-2h-2v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-2h-2v-2h-1v-1h-1v-1h-2v-2h-2v-1h-1v-1h-1v-1h-1v-2h-2v-2h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-2v-1h-1v-2h-2v-2h-2v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-2h-2v-2h-2v-1h-1v-1h-1v-2h-1v-1h-1v-1h-2v-2h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-2v-2h-2v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1z" opacity=".9"/><path fill="#193644" d="M544 1290h2v1h1v-1h1v2h1v53h-1v4h1v-1h1v-1h1v-1h2v-1h1v-1h1v-1h2v-1h1v-1h2v-1h2v-1h2v-1h3v-1h4v-1h6v-1h16v1h5v1h4v1h2v1h3v1h2v1h2v1h1v1h1v1h2v1h1v1h1v1h1v1h1v1h1v1h1v1h1v2h1v1h1v2h1v2h1v2h1v2h1v3h1v3h1v4h1v5h1v11h1v2h-1v1h1v69h-1v1h-33v-69h-1v-7h-1v-4h-1v-3h-1v-2h-1v-1h-1v-2h-1v-1h-1v-1h-1v-1h-2v-1h-2v-1h-2v-1h-3v-1h-11v1h-4v1h-2v1h-2v1h-2v1h-1v1h-1v1h-1v1h-1v2h-1v1h-1v2h-1v2h-1v3h-1v3h-1v4h-1v69h-1v1h-33v-168h1v-2h28zM1130 1290h1v1h1v169h-1v1h-32v-11h-1v1h-1v1h-1v1h-1v1h-2v1h-1v1h-2v1h-1v1h-3v1h-2v1h-2v1h-3v1h-5v1h-20v-1h-5v-1h-4v-1h-3v-1h-2v-1h-3v-1h-2v-1h-1v-1h-2v-1h-1v-1h-2v-1h-1v-1h-1v-1h-2v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-2h-1v-1h-1v-1h-1v-2h-1v-1h-1v-2h-1v-2h-1v-2h-1v-2h-1v-3h-1v-2h-1v-4h-1v-3h-1v-5h-1v-24h1v-5h1v-4h1v-3h1v-3h1v-3h1v-1h1v-3h1v-2h1v-2h1v-1h1v-2h1v-1h1v-2h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h2v-1h1v-1h1v-1h2v-1h1v-1h2v-1h2v-1h2v-1h2v-1h3v-1h4v-1h5v-1h19v1h5v1h3v1h3v1h2v1h2v1h2v1h1v1h2v1h1v1h1v1h1v1h2v-55h1v-1h31zm-68 75v1h-3v1h-3v1h-2v1h-2v1h-1v1h-2v1h-1v2h-1v1h-1v2h-1v2h-1v2h-1v2h-1v2h-1v4h-1v5h-1v9h1v7h1v3h1v2h1v3h1v1h1v2h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h2v1h2v1h3v1h5v1h9v-1h4v-1h3v-1h2v-1h2v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-2h1v-2h1v-2h1v-3h1v-5h1v-14h-1v-5h-1v-3h-1v-2h-1v-3h-1v-1h-1v-2h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-2v-1h-1v-1h-2v-1h-2v-1h-4v-1h-12ZM429 1306h33v2h1v18h-1v3h1v5h-1v3h29v29h-29v2h1v56h1v3h1v1h1v2h1v1h2v1h2v1h5v1h1v-1h7v-1h2v-1h2v-1h2v1h1v3h1v2h1v4h1v2h1v4h1v3h1v2h1v3h1v2h-2v1h-1v1h-1v1h-2v1h-2v1h-3v1h-4v1h-6v1h-1v-1h-1v1h-8v-1h-7v-1h-4v-1h-3v-1h-3v-1h-2v-1h-2v-1h-2v-1h-1v-1h-1v-1h-1v-1h-2v-1h-1v-2h-1v-1h-1v-1h-1v-2h-1v-1h-1v-2h-1v-3h-1v-2h-1v-4h-1v-4h-1v-64h-18v-29h18v-31Z" opacity=".9"/><path fill="#475b65" d="M1446 1306h34v31h29v2h1v2h-1v1h1v23h-1v1h-29v59h1v2h1v2h1v1h1v1h1v1h2v1h3v1h6v-1h4v-1h3v-1h2v-1h2v2h1v2h1v3h1v3h1v3h1v3h1v2h1v3h1v3h1v1h-1v1h-1v1h-1v1h-1v1h-2v1h-3v1h-2v1h-5v1h-7v1h-10v-1h-8v-1h-3v-1h-3v-1h-3v-1h-2v-1h-1v-1h-2v-1h-1v-1h-1v-1h-2v-1h-1v-1h-1v-2h-1v-1h-1v-1h-1v-2h-1v-1h-1v-3h-1v-3h-1v-2h-1v-5h-1v-5h-1v-1h1v-1h-1v-59h-18v-1h-1v-4h1v-2h-1v-1h1v-18h-1v-1h1v-2h19v-5h-1v-1h1v-3h-1v-9h1v-1h-1v-1h1v-11Z" opacity=".9"/><path fill="#193644" d="M719 1335h12v34h-18v1h-3v1h-2v1h-2v1h-1v1h-1v1h-2v1h-1v1h-1v2h-1v1h-1v2h-1v1h-1v3h-1v3h-1v3h-1v4h-1v65h-34v-123h1v-1h32v9h-1v1h1v1h-1v3h2v-1h1v-2h2v-1h1v-1h1v-1h1v-1h2v-1h1v-1h2v-1h2v-1h2v-1h2v-1h2v-1h3v-1h5zM793 1335h16v1h7v1h4v1h3v1h3v1h2v1h2v1h2v1h1v1h2v1h1v1h1v1h2v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v2h1v1h1v2h1v1h1v2h1v2h1v2h1v2h1v2h1v3h1v3h1v4h1v4h1v8h1v16h-1v1h-10v1h-3v-1h-1v1h-72v2h1v4h1v1h1v2h1v2h1v1h1v1h1v1h1v1h1v1h1v1h1v1h2v1h2v1h3v1h6v1h17v-1h4v-1h3v-1h2v-1h2v-1h2v-1h1v-1h1v-1h2v-1h1v-1h3v1h1v1h1v1h1v1h1v1h1v1h1v2h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v3h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-2v1h-1v1h-1v1h-2v1h-2v1h-1v1h-2v1h-3v1h-3v1h-2v1h-4v1h-4v1h-11v1h-1v-1h-16v-1h-5v-1h-3v-1h-3v-1h-3v-1h-2v-1h-3v-1h-2v-1h-1v-1h-2v-1h-1v-1h-2v-1h-1v-1h-2v-1h-1v-1h-1v-1h-1v-1h-2v-1h-1v-1h-1v-2h-1v-1h-1v-1h-1v-1h-1v-2h-1v-1h-1v-2h-1v-2h-1v-2h-1v-2h-1v-2h-1v-3h-1v-3h-1v-5h-1v-5h-1v-21h1v-5h1v-4h1v-4h1v-2h1v-3h1v-2h1v-2h1v-2h1v-2h1v-2h1v-1h1v-1h1v-2h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h2v-1h1v-1h2v-1h1v-1h2v-1h2v-1h2v-1h2v-1h3v-1h2v-1h5v-1h7zm4 28v1h-5v1h-3v1h-2v1h-2v1h-1v1h-2v1h-1v1h-1v1h-1v2h-1v1h-1v2h-1v2h-1v3h-1v4h-1v1h54v-4h-1v-4h-1v-2h-1v-2h-1v-2h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-2v-1h-2v-1h-2v-1h-3v-1h-5v-1h-7ZM919 1335h20v1h8v1h4v1h3v1h3v1h2v1h2v1h2v1h1v1h2v1h1v1h1v1h2v1h1v1h1v1h1v1h1v2h1v1h1v1h1v2h1v1h1v3h1v2h1v2h1v3h1v3h1v5h1v7h1v78h-31v-11h-1v1h-1v1h-1v1h-1v1h-1v1h-2v1h-1v1h-2v1h-2v1h-2v1h-2v1h-2v1h-4v1h-7v1h-11v-1h-6v-1h-5v-1h-3v-1h-2v-1h-2v-1h-2v-1h-2v-1h-2v-1h-1v-1h-2v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-2h-1v-1h-1v-2h-1v-1h-1v-2h-1v-3h-1v-3h-1v-8h-1v-1h1v-8h1v-4h1v-2h1v-3h1v-2h1v-1h1v-2h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h2v-1h1v-1h2v-1h2v-1h3v-1h3v-1h4v-1h4v-1h6v-1h35v-6h-1v-4h-1v-2h-1v-2h-1v-1h-1v-1h-1v-1h-1v-1h-2v-1h-1v-1h-3v-1h-3v-1h-8v-1h-1v1h-10v1h-5v1h-4v1h-2v1h-3v1h-2v1h-1v1h-2v1h-2v1h-1v1h-2v-1h-1v-1h-1v-3h-1v-2h-1v-2h-1v-2h-1v-2h-1v-3h-1v-2h-1v-2h-1v-2h-1v-3h1v-1h1v-1h2v-1h1v-1h2v-1h2v-1h2v-1h2v-1h3v-1h3v-1h3v-1h3v-1h6v-1h7zm6 73v1h-5v1h-2v1h-2v1h-2v1h-1v1h-1v1h-1v2h-1v2h-1v9h1v2h1v2h1v1h1v1h2v1h1v1h2v1h4v1h14v-1h2v-1h2v-1h2v-1h1v-1h2v-1h1v-1h1v-1h1v-1h1v-1h1v-2h1v-5h1v-13h-27Z" opacity=".9"/><path fill="#475b65" d="M1218 1335h17v1h5v1h3v1h3v1h2v1h2v1h2v1h1v1h2v1h1v1h1v1h2v2h1v1h1v1h1v1h1v2h1v1h1v1h1v3h1v1h1v3h1v2h1v4h1v5h1v6h1v1h-1v1h1v80h-3v1h-1v-1h-8v1h-2v-1h-1v1h-1v-1h-18v-72h-1v-1h1v-1h-1v-5h-1v-3h-1v-3h-1v-1h-1v-2h-1v-1h-1v-1h-1v-1h-1v-1h-2v-1h-3v-1h-3v-1h-10v1h-4v1h-2v1h-2v1h-1v1h-1v1h-2v1h-1v1h-1v2h-1v2h-1v1h-1v2h-1v4h-1v2h-1v7h-1v66h-1v1h-1v1h-1v-1h-10v1h-2v-1h-18v-1h-1v-123h32v12h2v-1h1v-1h1v-1h1v-1h1v-1h2v-1h2v-1h1v-1h2v-1h2v-1h2v-1h2v-1h4v-1h6zM1348 1335h19v1h6v1h4v1h3v1h2v1h3v1h2v1h2v1h2v1h1v1h3v1h1v1h1v1h2v2h2v1h1v1h1v1h1v1h1v1h1v1h1v1h1v2h1v1h1v2h1v1h1v2h1v1h1v3h1v2h1v2h1v3h1v3h1v5h1v5h1v21h-1v6h-1v3h-1v4h-1v2h-1v3h-1v2h-1v2h-1v1h-1v2h-1v2h-1v1h-1v1h-1v1h-1v2h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-2v1h-1v1h-1v1h-1v1h-2v1h-2v1h-2v1h-2v1h-1v1h-3v1h-3v1h-2v1h-4v1h-5v1h-6v1h-1v-1h-1v1h-10v-1h-8v-1h-5v-1h-3v-1h-4v-1h-2v-1h-2v-1h-2v-1h-2v-1h-2v-1h-2v-1h-1v-1h-2v-1h-1v-1h-2v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-2h-1v-1h-1v-2h-1v-1h-1v-2h-1v-2h-1v-2h-1v-3h-1v-2h-1v-3h-1v-4h-1v-4h-1v-7h-1v-13h1v-6h1v-4h1v-4h1v-3h1v-3h1v-2h1v-2h1v-1h1v-2h1v-2h1v-1h1v-2h1v-1h1v-2h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h2v-1h1v-1h1v-1h1v-1h2v-1h2v-1h1v-1h3v-1h1v-1h2v-1h3v-1h3v-1h5v-1h7zm3 30v1h-4v1h-3v1h-2v1h-2v1h-1v1h-2v1h-1v1h-1v2h-1v1h-1v1h-1v2h-1v1h-1v2h-1v3h-1v2h-1v4h-1v16h1v5h1v2h1v3h1v1h1v2h1v2h2v2h1v1h2v2h2v1h1v1h2v1h2v1h3v1h4v1h9v-1h6v-1h3v-1h2v-1h2v-2h2v-1h1v-1h1v-1h1v-1h1v-1h1v-2h1v-1h1v-2h1v-2h1v-3h1v-3h1v-8h1v-3h-1v-9h-1v-4h-1v-2h-1v-2h-1v-2h-1v-2h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-2v-1h-1v-1h-1v-1h-2v-1h-3v-1h-4v-1h-11ZM1577 1335h13v1h7v1h5v1h3v1h2v1h3v1h2v1h2v1h1v1h2v1h1v1h2v1h1v1h2v2h1v1h2v1h1v2h1v1h1v1h1v1h1v1h1v2h1v1h1v2h1v1h1v3h1v2h1v2h1v4h1v3h1v4h1v5h1v1h-1v1h1v21h-87v4h1v3h1v1h1v2h1v2h2v2h1v1h1v1h2v1h1v1h2v1h2v1h1v1h3v1h5v1h14v-1h5v-1h3v-1h3v-1h2v-1h1v-1h1v-1h2v-1h1v-1h1v-1h1v-1h3v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v1h1v4h-1v1h-1v1h-1v1h-1v1h-1v1h-2v2h-2v1h-1v1h-1v1h-2v1h-2v1h-1v1h-2v1h-3v1h-2v1h-2v1h-4v1h-5v1h-9v1h-9v-1h-10v-1h-5v-1h-4v-1h-3v-1h-3v-1h-2v-1h-2v-1h-2v-1h-2v-1h-2v-1h-1v-1h-2v-1h-1v-1h-2v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-1h-1v-2h-1v-1h-1v-1h-1v-2h-1v-1h-1v-2h-1v-2h-1v-2h-1v-1h-1v-3h-1v-3h-1v-3h-1v-5h-1v-6h-1v-13h1v-7h1v-5h1v-3h1v-3h1v-4h1v-2h1v-2h1v-2h1v-2h1v-1h1v-2h1v-2h1v-1h1v-1h1v-2h2v-2h1v-1h1v-1h1v-1h1v-1h2v-2h2v-1h1v-1h2v-1h1v-1h1v-1h3v-1h1v-1h3v-1h1v-1h3v-1h2v-1h5v-1h9zm2 28v1h-5v1h-2v1h-3v1h-2v1h-1v1h-1v1h-2v1h-1v2h-1v1h-1v1h-1v2h-1v2h-1v2h-1v4h-1v2h54v-5h-1v-2h-1v-3h-1v-2h-1v-1h-1v-1h-1v-1h-1v-2h-2v-1h-1v-1h-1v-1h-2v-1h-2v-1h-3v-1h-4v-1z" opacity=".9"/></g><defs><clipPath id="a"><path fill="#fff" d="M0 0h2048v2048H0z"/></clipPath></defs></svg>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "threadnote",
3
- "version": "0.5.0",
3
+ "version": "0.6.0",
4
4
  "type": "commonjs",
5
5
  "main": "dist/threadnote.cjs",
6
6
  "description": "Shared local context and handoffs for development agents",