PageSourceSearch

https://newart.city/blog

html newart.city collected 2026-10-01 12:31:38 UTC 22,658 bytes, 736 lines download raw bytes

1<!DOCTYPE html>
2<html>
3
4
5
6
7
8<head>
9  <meta charset="utf-8">
10  <title>New Art City Blog</title>
11
12  <link rel="stylesheet" href="/styles/main.nac.css?v=19419.596413969175">
13  <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
14
15  <!-- opengraph metadata -->
16  <meta property="og:title" content="New Art City Blog">
17  <meta property="og:description" content="Multiplayer Exhibition Space for New Media Art">
18  <meta property="og:image" content="https://newart.city/img/top-show/nac-festival-grounds.jpg">  <!-- http-urls-on-this-line-allowed-in-world-export-test -->
19  
20  <meta name="twitter:card" content="summary_large_image">
21  <meta property="og:site_name" content="New Art City • Virtual Art Space">
22  <!-- end opengraph metadata -->
23
24  <!-- favicon metadata -->
25  <link rel="apple-touch-icon" sizes="180x180" href="/img/favicon/apple-touch-icon.png">
26  <link rel="icon" type="image/png" sizes="32x32" href="/img/favicon/favicon-32x32.png">
27  <link rel="icon" type="image/png" sizes="16x16" href="/img/favicon/favicon-16x16.png">
28  <link rel="manifest" href="/img/favicon/site.webmanifest">
29  <link rel="mask-icon" href="/img/favicon/safari-pinned-tab.svg" color="#5bbad5">
30  <link rel="shortcut icon" href="/img/favicon/favicon.ico">
31  <meta name="msapplication-TileColor" content="#00aba9">
32  <meta name="msapplication-config" content="/img/favicon/browserconfig.xml">
33  <meta name="theme-color" content="#ffffff">
34  <!-- end favicon metadata -->
35
36  
37    <link rel="stylesheet" href="https://use.typekit.net/nvo2aai.css">
38  
39
40  
41
42</head>
43
44<body class="blog">
45
46  
46<script src="https://code.jquery.com/jquery-3.6.3.min.js"></script>
46
47  
47<script src='/js/vendor/micromodal/micromodal.min.js'></script>
47
48
49  <div class="public-header-2023">
50  <div class="header-content">
51
52    <a class="logo-container" aria-label="New Art City logo" href="/"> <!-- http-urls-on-this-line-allowed-in-world-export-test -->
53  <div class="double">
54    <span class='logo-text'>New<br>Art<br>City</span>
55    <div class="logo"></div>
56  </div>
57  <span class="subtitle">Virtual Art Space</span>
58</a>
59
60
61
62
63
64  
64<script src="https://ga.jspm.io/npm:[email protected]/dist/es-module-shims.js"></script>
64
65
66  
66<script type="importmap">
67    {
68      "imports": {
69        "three": "https://cdn.jsdelivr.net/npm/[email protected]/build/three.module.js",
70        "three/addons/": "https://cdn.jsdelivr.net/npm/[email protected]/examples/jsm/"
71      }
72    }
73  </script>
73
74
75
76
77<script type="text/javascript">
78
79  window.dynamicImport = async (path) => {
80    // This import doesn't require an import map, so we can use the normal import
81    if (path.startsWith('.') || path.startsWith('/')) {
82      return import(path)
83    }
84    
85    // importShim will automatically pass-through to the native dynamic import or polyfill as necessary
86    // https ://www.npmjs.com/package/es-module-shims
87    return importShim(path)
88
89  }
90</script>
90
91
92
93<script type="module">
94  // setup
95    var camera    = null
96    var cameraFar = 150
97    var scene     = null
98    var renderer  = null
99    var cube      = null
100    var small     = false
101    
102    // Find the element that will host the canvas.
103    var canvasCtn = document.querySelector('.logo')
104    
105    // render small logo when inside dash-nav
106    if( canvasCtn.closest('.dash-nav') !== null ){
107      small = true
108      document.querySelector('.logo-container').classList.add('logo-small')
109    }
110
111    await initLogo()
112    animateLogo()
113
114
115    async function initLogo() {
116
117      // Ensure three is imported
118      const THREE = await dynamicImport(`three`)
119
120      // init scene
121
122      var width  = 80
123      var height = 80
124      
125      if( small ) width = height = 55
126
127      // Add canvas to the document element.
128      renderer = new THREE.WebGLRenderer({ 
129        alpha: true, 
130        antialias: false,
131      })
132      renderer.setSize(width, height )
133      renderer.setClearColor(0xededed, 0)
134
135      renderer.autoClear = false
136
137      canvasCtn.appendChild(renderer.domElement)
138
139      camera = new THREE.PerspectiveCamera( 75, width/height, 1, cameraFar );
140      camera.position.y = 0;
141      camera.position.x = 0;
142      camera.position.z = 0;
143
144      scene = new THREE.Scene();  
145
146      var geometry = new THREE.BoxGeometry(4,4,4)      
147      var material = new THREE.MeshNormalMaterial({wireframe:true})
148
149      cube = new THREE.Mesh( geometry, material );
150      cube.position.z = 7
151
152      scene.add(camera)
153      scene.add(cube)
154
155      camera.lookAt(cube.position)
156
157    }
158
159    function animateLogo(){
160
161      requestAnimationFrame( animateLogo )
162
163      cube.rotation.y += 0.002
164      cube.rotation.x -= 0.002
165      cube.rotation.z -= 0.002
166
167      renderer.render( scene, camera )
168
169    }
170</script>
170
171    
172    <div class="menu-ctn">
173      <button class='menu-btn'>
174        <img src="/img/icons/menu.png">
175      </button>
176      <div class="menu-dropdown">
177        <a href="/">Home / Gallery</a>
178        <a href="/join">Join</a>
179        <a href="https://info.newart.city/about">About</a>
180        <a href="#" class='open-contact-modal'>Contact</a>
181        <a href="https://info.newart.city/">Features &amp; Documentation</a>
182        <a href="/blog">Blog</a>
183        <a href="/support">Support New Art City</a>
184        
185          <a href='/login'>Log In &rarr;</a>
186        
187        <div class="social-links">
188          <a href="https://www.instagram.com/newart.city/" target="_blank">
189            <img src="/img/icons/instagram.svg" class='icon' alt='Instagram icon'>
190          </a>
191          <a href="https://twitter.com/new_art_city" target="_blank">
192            <img src="/img/icons/twitter.svg" class='icon' alt='Twitter icon'>
193          </a>
194          <a href="https://www.youtube.com/channel/UCe11QowUMjLtO8h2db1tX5g" target="_blank">
195            <img src="/img/icons/youtube.svg" class='icon' alt='Youtube icon'>
196          </a>
197          <a href="https://www.are.na/new-art-city" target="_blank">
198            <img src="/img/icons/arena.svg" class='icon' alt='Arena icon'>
199          </a>
200        </div>
201      </div>        
202    </div>
203  </div>
204</div>
205
206<!-- Modal: Contact -->
207<div class="modal micromodal-slide" id="modal-contact" aria-hidden="true">
208  <div class="modal__overlay" tabindex="-1">
209    <div class="modal__container">
210      <div class="close-modal" data-micromodal-close>&times;</div>
211
212      <h2>Contact</h2>
213
214      <form class='contact-form'>
215
216        <label for='contact-message'>
217          <span class='form-label'>Message</span>
218          <span class="helper-text">What's on your mind?</span>
219          <textarea name='contact-message' id='contact-message'></textarea>
220        </label>
221
222        <label for='contact-email'>
223          <span class='form-label'>Email Address</span>
224          <span class="helper-text">So we can reply to you.</span>
225          <input type="email" name="contact-email" id='contact-email'>
226        </label>
227
228        <div id="contact-turnstile" class="cf-turnstile" data-sitekey="0x4AAAAAAErMkbqOubmlELot" data-theme="light" data-size="flexible" data-response-field-name="turnstileToken"></div>
229
230        <input type="hidden" name="message-type" value="New Art City contact message">
231        <input type="hidden" name="contact-form" value="public-header-2023">
232        <input type="submit" name="submit-contact" value="Send Message">
233
234      </form>
235
236
237    </div>
238  </div>
239</div>
240
241<!-- Modal: Confirmation -->
242<div class="modal micromodal-slide" id="modal-confirmation" aria-hidden="true">
243  <div class="modal__overlay" tabindex="-1">
244    <div class="modal__container">
245      <div class="close-modal" data-micromodal-close>&times;</div>
246      <h2 class='confirmation-headline'>Thanks!</h2>
247      <p class='confirmation-message'>We will get back to you as soon as possible.</p>
248    </div>
249  </div>
250</div>
251
252<script>
253
254  // jquery and micromodal must be included at the top of any page this appears on.
255
256  // menu button
257  $('.menu-btn').click((e) => {
258    $('.menu-ctn').toggleClass('active')
259  })
260
261  // close menu when anything else is clickec
262  $('body').click((e) => {
263    if( $(e.target).closest('.menu-ctn').length == 0 ){
264      $('.menu-ctn').removeClass('active')
265    }
266  })
267
268  // open contact modal
269  $('body').on('click', '.open-contact-modal, [href="#contact"]', function(e) {
270    e.preventDefault()
271    $('.close-modal').click() // close any already open modal
272    MicroModal.show('modal-contact')
273  })
274
275  // submit contact 
276  $('.contact-form').submit(async function(e) {
277    
278    e.preventDefault()
279    $('body').addClass('loading')
280
281    let contactResponse = await fetch('/api/messages/submit-contact', {
282      method: 'POST',
283      headers: { 'Content-type': 'application/json' },
284      body: JSON.stringify({
285        'contact-email': $('#contact-email').val(),
286        'contact-message': $('#contact-message').val(),
287        'turnstileToken': $('.contact-form [name=turnstileToken]').val(),
288        'contact-form': $('.contact-form [name=contact-form]').val()
289      })
290    })
291
292    $('body').removeClass('loading')
293
294    // handle error
295    if (!contactResponse.ok) {
296      // A token is single-use. Reset the widget so the visitor can try again.
297      if (window.turnstile) window.turnstile.reset('#contact-turnstile')
298      alert(await contactResponse.text())
299      return
300    }
301
302    // success
303    document.querySelector('.contact-form').reset()
304    if (window.turnstile) window.turnstile.reset('#contact-turnstile')
305    $('.close-modal').click()
306    document.querySelector('.confirmation-headline').innerHTML = "Thanks!"
307    document.querySelector('.confirmation-message').innerHTML = "We will get back to you as soon as possible."
308    MicroModal.show('modal-confirmation')
309  })
310  
311</script>
311
312
313<!--
314  Loads the Cloudflare Turnstile widget script.
315
316  Include this partial on any page that renders a `cf-turnstile` div. The guard
317  makes a second include harmless, because two contact forms or a contact form
318  and the signup form can appear on one page.
319
320  The script is async, thus it finds and renders every widget on the page after
321  it loads. The order of the script and the widget does not matter.
322-->
323<script>
324  if (!document.querySelector('script[data-turnstile-api]')) {
325    var turnstileApiScript = document.createElement('script')
326    turnstileApiScript.src = 'https://challenges.cloudflare.com/turnstile/v0/api.js'
327    turnstileApiScript.async = true
328    turnstileApiScript.defer = true
329    turnstileApiScript.setAttribute('data-turnstile-api', '')
330    document.head.appendChild(turnstileApiScript)
331  }
332</script>
332
333
334
335
336  <style type="text/css">
337  #wire-terrain {
338    width: 100vw;
339    height: 100vh;
340    position: fixed;
341    top: 0px;
342    pointer-events: none;
343    z-index: -3;
344  }
345</style>
346
347<canvas id='wire-terrain'></canvas>
348
349
350
351  
351<script src="https://ga.jspm.io/npm:[email protected]/dist/es-module-shims.js"></script>
351
352
353  
353<script type="importmap">
354    {
355      "imports": {
356        "three": "https://cdn.jsdelivr.net/npm/[email protected]/build/three.module.js",
357        "three/addons/": "https://cdn.jsdelivr.net/npm/[email protected]/examples/jsm/"
358      }
359    }
360  </script>
360
361
362
363
364<script type="text/javascript">
365
366  window.dynamicImport = async (path) => {
367    // This import doesn't require an import map, so we can use the normal import
368    if (path.startsWith('.') || path.startsWith('/')) {
369      return import(path)
370    }
371    
372    // importShim will automatically pass-through to the native dynamic import or polyfill as necessary
373    // https ://www.npmjs.com/package/es-module-shims
374    return importShim(path)
375
376  }
377</script>
377
378
379
380<script type="module">
381
382  var random = function(max){
383    return Math.floor(Math.random()*max)
384  }
385
386  var isResizing = false
387  var resizeStop = function(callback,msBuffer){
388    if(!msBuffer) msBuffer = 250
389    window.addEventListener('resize', function(){
390      window.clearTimeout( isResizing )
391      isResizing = setTimeout(callback, msBuffer)
392    }, false)
393  }
394  
395  // Wire Terrain Three Scene
396  function WireTerrain() {
397
398    this.$el
399    this.width
400    this.height
401    this.scene
402    this.camera
403    this.renderer
404    this.mesh
405    this.group
406    this.boxMeshes = []
407    this.avatarMeshes = []
408    this.spinSpeed = 0.00001
409    this.xAngle = -1.3
410
411    this.loopNum = 0
412
413    this.init = async function(){
414      
415      this.$el = document.querySelector('#wire-terrain')
416      if( !this.$el ) return
417
418      this.width  = Math.floor(this.$el.offsetWidth)
419      this.height = Math.floor(this.$el.offsetHeight)
420
421      // Ensure three is imported
422      const THREE = await dynamicImport(`three`)
423
424      // init scene
425      this.scene = new THREE.Scene()
426      
427      // init camera
428      var FOV         = 0.5
429      var aspectRatio = this.width / this.height
430      var nearClip    = 1
431      var farClip     = 1000
432      this.camera     = new THREE.PerspectiveCamera(FOV,aspectRatio,nearClip,farClip)
433
434      this.camera.position.x = 0
435      this.camera.position.y = 0
436      this.camera.position.z = 280
437
438      // init renderer
439      this.renderer = new THREE.WebGLRenderer({
440        alpha:true,
441        canvas: this.$el
442      })
443      this.renderer.setSize( this.width, this.height )
444
445      // init objects in scene
446
447      var planeWidth     = 2
448      var planeHeight    = 2
449      var widthSegments  = 60
450      var heightSegments = 60
451
452      var geometry = new THREE.PlaneGeometry(planeWidth,planeHeight,widthSegments,heightSegments)
453      var material = new THREE.MeshBasicMaterial({
454        // color:     'rgb(180,180,255)',
455        color:     'rgb(220,220,240)',
456        wireframe: true
457      })
458
459      this.mesh = new THREE.Mesh( geometry, material )
460      
461      this.group = new THREE.Group()
462      this.group.add(this.mesh)
463
464
465      this.group.rotation.x = this.xAngle
466      this.group.rotation.y = 0
467      this.group.rotation.z = 2.4
468      
469      this.group.position.y = -0.02
470
471      // add minature objects
472      var boxGeometry = new THREE.BoxGeometry(1,1,1)
473      var boxMaterial = new THREE.MeshNormalMaterial({wireframe:true})
474      for (var i = 0; i < 10; i++) {
475        var boxMesh     = new THREE.Mesh(boxGeometry,boxMaterial)
476        boxMesh.position.z = 0.025
477        boxMesh.scale.x = 0.03
478        boxMesh.scale.y = 0.03
479        boxMesh.scale.z = 0.03
480        boxMesh.rotation.y = 0.78
481        boxMesh.rotation.x = random(100)
482        this.boxMeshes.push(boxMesh)
483        this.group.add(boxMesh)         
484      }
485
486      this.boxMeshes[0].position.x = -0.3
487      this.boxMeshes[0].position.y = -0.6
488
489      this.boxMeshes[1].position.x = -0.8
490      this.boxMeshes[1].position.y = 0.7
491
492      this.boxMeshes[2].position.x = 0.2
493      this.boxMeshes[2].position.y = 0.6
494
495      this.boxMeshes[3].position.x = 0.0
496      this.boxMeshes[3].position.y = 0.0
497
498      this.boxMeshes[4].position.x = 0.8
499      this.boxMeshes[4].position.y = 0.3
500
501      this.boxMeshes[5].position.x = 0.8
502      this.boxMeshes[5].position.y = -0.8
503
504      this.boxMeshes[6].position.x = 0.6
505      this.boxMeshes[6].position.y = 0.1
506
507      // !
508      this.boxMeshes[7].position.x = 0.0
509      this.boxMeshes[7].position.y = -0.5
510      
511      this.boxMeshes[8].position.x = 0.9
512      this.boxMeshes[8].position.y = 0.8
513
514      this.boxMeshes[9].position.x = -0.7
515      this.boxMeshes[9].position.y = -0.7
516      
517      // make some avatars
518      var avatarGeometry = new THREE.SphereGeometry( 2, 2, 2 )
519      var avatarMaterial = new THREE.MeshBasicMaterial({ color:'#32CD32'})
520      for (i = 0; i < 5; i++) {
521        var avatarMesh  = new THREE.Mesh(avatarGeometry, avatarMaterial)
522        avatarMesh.scale.x = 0.007
523        avatarMesh.scale.y = 0.007
524        avatarMesh.scale.z = 0.007
525        avatarMesh.position.z = 0.025
526        avatarMesh.timer = random(100)
527        this.avatarMeshes.push(avatarMesh)
528        this.group.add(avatarMesh)
529      }
530
531      this.avatarMeshes[0].position.x = 0.4
532      this.avatarMeshes[0].position.y = -0.7
533
534      this.avatarMeshes[1].position.x = 0.4
535      this.avatarMeshes[1].position.y = 0
536
537      this.avatarMeshes[2].position.x = -0.8
538      this.avatarMeshes[2].position.y = 0
539
540      this.avatarMeshes[3].position.x = -0.2
541      this.avatarMeshes[3].position.y = 0.3
542
543      this.avatarMeshes[4].position.x = 0.7
544      this.avatarMeshes[4].position.y = 0.7
545
546      this.scene.add( this.group )
547      
548    }
549
550    this.onResize = function(){
551
552      if( !this.$el ) return
553
554      // remove inline height/width set by three
555      this.$el.setAttribute('style','')
556
557      this.width  = Math.floor(this.$el.offsetWidth)
558      this.height = Math.floor(this.$el.offsetHeight)
559
560      this.renderer.setSize(this.width,this.height)
561      this.camera.aspect = this.width / this.height
562      this.camera.updateProjectionMatrix()
563
564    }
565
566    this.draw = function(){
567
568      if( !this.$el ) return
569
570      var Ztarget  = (window.scrollY * -0.175) + 100
571      var Zcurrent = this.camera.position.z
572
573      if (Ztarget < 20) {
574        Ztarget = 20
575      }
576
577      var Zdifference = Ztarget - Zcurrent
578      var Zincrement = Zdifference * 0.1
579      
580      this.camera.position.z += Zincrement  
581      
582      this.renderer.render( this.scene, this.camera )
583
584      
585      var rotZ = 10 * this.spinSpeed || 0
586      this.group.rotation.z += rotZ
587        
588      var Xtarget  = (window.scrollY * -0.00025) + this.xAngle
589      var Xcurrent = this.group.rotation.x
590      var Xdifference = Xtarget - Xcurrent
591      var Xincrement = Xdifference * 0.1
592      this.group.rotation.x += Xincrement
593      if (this.group.rotation.x < -1.55 ) {
594        this.group.rotation.x = -1.55
595      }
596
597
598      for (var i = 0; i < this.boxMeshes.length; i++) {
599        this.boxMeshes[i].rotation.x+= 0.001
600        this.boxMeshes[i].rotation.y+= 0.001
601        this.boxMeshes[i].rotation.z+= 0.001
602      }
603
604      // do avatar movement
605      for (var i = 0; i < this.avatarMeshes.length; i++) {
606        
607        if( this.avatarMeshes[i].timer > 0 ){
608          this.avatarMeshes[i].timer--
609          continue;
610        }
611
612        // set destinations
613        if( this.avatarMeshes[i].destination == null ){
614          this.avatarMeshes[i].destination = {
615            x: (( random(200) - 100) * 0.01 ),
616            y: (( random(200) - 100) * 0.01 )
617          }
618        }
619
620        if( this.avatarMeshes[i].position.x > this.avatarMeshes[i].destination.x ) this.avatarMeshes[i].position.x -= 0.001
621        if( this.avatarMeshes[i].position.x < this.avatarMeshes[i].destination.x ) this.avatarMeshes[i].position.x += 0.001
622
623        if( this.avatarMeshes[i].position.y > this.avatarMeshes[i].destination.y ) this.avatarMeshes[i].position.y -= 0.001
624        if( this.avatarMeshes[i].position.y < this.avatarMeshes[i].destination.y ) this.avatarMeshes[i].position.y += 0.001
625
626        var differenceX = this.avatarMeshes[i].position.x - this.avatarMeshes[i].destination.x
627        var differenceY = this.avatarMeshes[i].position.y - this.avatarMeshes[i].destination.y
628
629        if( differenceY < 0.1 && differenceY > -0.1 && differenceX < 0.1 && differenceX > -0.1 ){
630          this.avatarMeshes[i].destination = null
631          this.avatarMeshes[i].timer = random(500)
632        }
633
634      }
635    }
636  }
637
638  // Only activate wire terrain on desktop devices
639  if (window.innerWidth > 700) {
640    var wireTerrain = new WireTerrain()
641    await wireTerrain.init()
642    resizeStop(function(){
643      wireTerrain.onResize()
644    })
645    function loop(){
646      wireTerrain.draw()
647      requestAnimationFrame(loop)
648    }
649
650    loop()
651  }
652
653</script>
653
654
655  <div class="blog-ctn">
656    <div class="big-panel">
657      <h1>New Art City Blog</h1>
658      <div class="horizontal-line"></div>
659      <div class="blog-posts">
660        
661                  
662          <div class="blog-post-excerpt">
663            <a href="/blog/electric-spirits" class='thumbnail'>
664              <img src="../media/electric-spirits/national-grid-thumb.jpg">
665            </a>
666            <div class="content">
667              <div class="date-and-author">
668                <img class="calendar-icon" src="/img/icons/mini-calendar.png">
669                <span>JUN 30 2024 · bathtubsailing</span>
670              </div>
671              <h2 class="title">
672                <a href="/blog/electric-spirits">Electric Spirits: Sonic Shadows</a>
673              </h2>
674              <p class="description">Farhad Mirza strolls through &#34;Antithesis&#34; by Disinformation and considers some of the aesthetic ancestors of virtual representation</p>
675              <a class="read-more-row" href="/blog/electric-spirits">
676                <span class="read-more">Read More</span>
677                <span class='read-more-arrow'>▸</span>
678              </a>
679            </div>
680          </div>
681
682                  
683          <div class="blog-post-excerpt">
684            <a href="/blog/virtual-hybrid-exhibitions" class='thumbnail'>
685              <img src="../media/virtual-hybrid-exhibitions/virtual-hybrid-exhibitions-thumb.jpg">
686            </a>
687            <div class="content">
688              <div class="date-and-author">
689                <img class="calendar-icon" src="/img/icons/mini-calendar.png">
690                <span>DEC 20 2023 · d0nxyz</span>
691              </div>
692              <h2 class="title">
693                <a href="/blog/virtual-hybrid-exhibitions">Building Community with Virtual Hybrid Exhibitions</a>
694              </h2>
695              <p class="description">Research on presenting digital art in physical spaces</p>
696              <a class="read-more-row" href="/blog/virtual-hybrid-exhibitions">
697                <span class="read-more">Read More</span>
698                <span class='read-more-arrow'>▸</span>
699              </a>
700            </div>
701          </div>
702
703                  
704          <div class="blog-post-excerpt">
705            <a href="/blog/world-export" class='thumbnail'>
706              <img src="../media/world-export/world-export-thumb.jpg">
707            </a>
708            <div class="content">
709              <div class="date-and-author">
710                <img class="calendar-icon" src="/img/icons/mini-calendar.png">
711                <span>NOV 28 2023 · bennlich</span>
712              </div>
713              <h2 class="title">
714                <a href="/blog/world-export">Export your world for exhibition, self-hosting, and archiving</a>
715              </h2>
716              <p class="description">A step towards easily archiveable new media art</p>
717              <a class="read-more-row" href="/blog/world-export">
718                <span class="read-more">Read More</span>
719                <span class='read-more-arrow'>▸</span>
720              </a>
721            </div>
722          </div>
723
724        
725
726      </div>
727    </div>    
728  </div>  
729
730  
730<script src="https://cdn.usefathom.com/script.js" data-site="EKBJVRUJ" defer></script>
730
731
732
733
734</body>
735
736</html>

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.