You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

130 lines
108 KiB

4 years ago
  1. {{/*
  2. Copyright (C) 2019 Josh Habdas <jhabdas@protonmail.com>
  3. This file is part of After Dark.
  4. After Dark is free software: you can redistribute it and/or modify
  5. it under the terms of the GNU Affero General Public License as published by
  6. the Free Software Foundation, either version 3 of the License, or
  7. (at your option) any later version.
  8. After Dark is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU Affero General Public License for more details.
  12. You should have received a copy of the GNU Affero General Public License
  13. along with this program. If not, see <https://www.gnu.org/licenses/>.
  14. This file incorporates work covered by the following copyright and
  15. permission notice:
  16. Copyright (c) 2018 by Simon FREMAUX (https://codepen.io/dievardump/pen/pyOMeN)
  17. Permission to use, copy, modify, and/or distribute this software for any
  18. purpose with or without fee is hereby granted, provided that the above
  19. copyright notice and this permission notice appear in all copies.
  20. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  21. WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  22. MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  23. ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  24. WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  25. ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  26. OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  27. */ -}}
  28. <head>
  29. <meta name="generator" content="{{ with .Site.Data.npm.latest }}{{ .name | humanize | title }} {{ .version }} (Hugo {{ hugo.Version }}){{ else }}Hugo {{ hugo.Version }}{{ end }}">
  30. <meta charset="utf-8">
  31. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  32. <meta name="robots" content="noindex">
  33. <title>404 Error | {{ .Site.Title }}</title>
  34. {{ partial "head/favicon.html" . }}
  35. {{ partial "meta/theme-color.html" . }}
  36. <style media="screen">
  37. @keyframes intro {
  38. 0% { opacity: 0; } 100% { opacity: 1; }
  39. }
  40. @font-face {
  41. font-family: 'Londrina Outline';
  42. src: url(data:application/font-woff2;charset=utf-8;base64,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
  43. url(data:application/font-woff;charset=utf-8;base64,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
  44. font-weight: normal;
  45. font-style: normal;
  46. }
  47. html, body {
  48. overflow: hidden;
  49. animation: intro 3s both;
  50. animation-delay: 0.15s;
  51. }
  52. body {
  53. background-color: black;
  54. margin: 0;
  55. }
  56. canvas {
  57. position: absolute;
  58. overflow: hidden;
  59. top: 0;
  60. left: 0;
  61. z-index: -1;
  62. }
  63. body {
  64. display: flex;
  65. height: 100vh;
  66. align-items: center;
  67. }
  68. header {
  69. font-family: 'Londrina Outline', sans-serif;
  70. text-align: center;
  71. margin: 0 auto;
  72. font-size: 10vw;
  73. }
  74. h1 {
  75. position: relative;
  76. font-weight: 900;
  77. color: white;
  78. opacity: 0.75;
  79. }
  80. header h1 {
  81. text-align: center;
  82. width: 100%;
  83. }
  84. header h1:before {
  85. content: attr(data-letters);
  86. position: absolute;
  87. left: 0;
  88. overflow: hidden;
  89. width: 100%;
  90. height: 50%;
  91. color: black;
  92. text-shadow: 3px -2px 5px black, -3px 3px 4px black;
  93. text-align: center;
  94. }
  95. header h1:after {
  96. content: attr(data-letters);
  97. position: absolute;
  98. left: -10px;
  99. overflow: hidden;
  100. width: 100%;
  101. height: 49%;
  102. color: white;
  103. }
  104. a {
  105. color: rgba(255,255,255,0.75);
  106. text-decoration: none;
  107. }
  108. </style>
  109. </head>
  110. <body>
  111. <canvas id="c"></canvas>
  112. <header>
  113. <a title="Page Not Found" href="{{ .Site.BaseURL }}">
  114. <h1 data-letters="404"><span>404</span></h1>
  115. </a>
  116. </header>
  117. <script>
  118. /*! Copyright (c) 2018 by Simon FREMAUX (https://codepen.io/dievardump/pen/pyOMeN) | @license MIT */
  119. class Dots{constructor(width,height,spacing){this.spacing=spacing;this.dots=[];this.alphaStep=1/10;this.cols=Math.floor(width/spacing);this.rows=Math.floor(height/spacing);const canvas=document.createElement('canvas'),ctx=canvas.getContext('2d');canvas.width=width;canvas.height=height;this.canvas=canvas;this.ctx=ctx;this.draw()}draw(){const ctx=this.ctx,spacing=this.spacing;ctx.fillStyle='rgba(24, 129, 141, .1)';this.dots=Array.apply(null,Array(this.cols)).map((n,x)=>{return Array.apply(null,Array(this.rows)).map((p,y)=>{let dot={opacity:0.1,x:x*spacing,y:y*spacing};ctx.fillRect(dot.x,dot.y,1,1);return dot})})}ghost(){const ghostDots=document.createElement('canvas');ghostDots.width=this.canvas.width;ghostDots.height=this.canvas.height;const dotsCtx=ghostDots.getContext('2d');dotsCtx.fillStyle='rgb(24, 129, 141)';this.dots.forEach(col=>{col.forEach(dot=>{dotsCtx.fillRect(dot.x,dot.y,1,1)})});return ghostDots}}class Circuits{constructor(width,height,size,minLength,maxLength){this.size=size;this.width=width;this.height=height;this.cols= ~~(width/size);this.rows= ~~(height/size);this.scene=Array.apply(null,Array(this.cols)).map(()=>new Col(this.rows));this.collection=[];this.minLength=minLength;this.maxLength=maxLength;this.populate();this.draw()}draw(){const canvas=document.createElement('canvas'),ctx=canvas.getContext('2d'),size=this.size;canvas.width=this.width;canvas.height=this.height;ctx.strokeStyle='rgba(59, 177, 188, 1)';ctx.lineWidth=Math.round(size/10);this.collection.forEach(circuit=>{let point=[circuit.start[0],circuit.start[1]],path=circuit.path;ctx.beginPath();ctx.moveTo(point[0]*size+size/2+path[0][0]*size/4,point[1]*size+size/2+path[0][1]*size/4);path.forEach((dir,index)=>{point[0]+=dir[0];point[1]+=dir[1];if(index===path.length-1){ctx.lineTo(point[0]*size+size/2-dir[0]*size/4,point[1]*size+size/2-dir[1]*size/4)}else{ctx.lineTo(point[0]*size+size/2,point[1]*size+size/2)}});ctx.stroke()});ctx.lineWidth= ~~(this.size/5);ctx.strokeStyle='rgba(59, 177, 188, .6)';this.collection.forEach(circuit=>{ctx.beginPath();ctx.arc(circuit.start[0]*size+size/2,circuit.start[1]*size+size/2,size/4,0,2*Math.PI,false);ctx.stroke();ctx.beginPath();ctx.arc(circuit.end[0]*size+size/2,circuit.end[1]*size+size/2,size/4,0,2*Math.PI,false);ctx.stroke()});this.canvas=canvas}populate(){const size=this.size;let start=null,n=1000,maxLength=this.maxLength,minLength=this.minLength,length=0,dir=null;while((start=this.getStart())&&n--){length=minLength+ ~~(Math.random()*(maxLength-minLength));dir=this.getDir(start);this.setUsed(start[0],start[1]);if(dir[0]!==0||dir[1]!==0){let circuit=new Circuit(start,size),moving=true,path=[start[0],start[1]],coords=[start[0],start[1]];length-=1;while(moving&&length){circuit.path.push(dir);circuit.coords.push([path[0],path[1]]);path[0]+=dir[0];path[1]+=dir[1];this.setUsed(path[0],path[1]);dir=this.getDir(path,dir);if(dir[0]===0&&dir[1]===0){moving=false}length-=1}if(circuit.path.length>=minLength){circuit.end=path;circuit.coords.push([path[0],path[1]]);let speed=Math.random()*0.5+0.5;circuit.things.push(things.create(circuit,speed*1));if(circuit.path.length>maxLength/3){speed=Math.random()*0.5+0.5;circuit.things.push(things.create(circuit,-speed,circuit.path.length*size))}if(circuit.path.length>maxLength/1.5){speed=Math.random()*0.5+0.5*(Math.random()>=0.5?-1:1);circuit.things.push(things.create(circuit,speed,Math.random()*circuit.path.length*size))}circuit.length=circuit.path.length*size;this.collection.push(circuit)}}}}getStart(){let found=false,col=null,row=null,free=[],result=false;const scene=this.scene;scene.forEach((col,index)=>{if(col.free){free.push(index)}});if(free.length){col=this.pickOne(free);free.length=0;scene[col].rows.forEach((row,index)=>{if(row===0){free.push(index)}});row=this.pickOne(free);result=[col,row]}return result}pickOne(array){return array[~~(Math.random()*array.length)]}setUsed(x,y){this.scene[x].rows[y]=1;this.scene[x].free-=1}isAvailable(x,y){const scene=this.scene;let result=false;if(typeof scene[x]!=='undefined'){if(typeof scene[x].rows[y]!=='undefined'){if(scene[x].row
  120. </script>
  121. </body>