|
8 | 8 | *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; } |
9 | 9 |
|
10 | 10 | :root { |
11 | | - --bg: #0f172a; |
12 | | - --surface: #1e293b; |
13 | | - --border: #334155; |
14 | | - --accent: #38bdf8; |
15 | | - --accent-2: #818cf8; |
16 | | - --text: #f1f5f9; |
17 | | - --muted: #94a3b8; |
18 | | - --red: #f87171; |
19 | | - --radius: 10px; |
| 11 | + --bg: #0d1117; |
| 12 | + --surface: #161b22; |
| 13 | + --border: #30363d; |
| 14 | + --text: #e6edf3; |
| 15 | + --muted: #7d8590; |
| 16 | + --red: #f85149; |
| 17 | + --cyan: #79c0ff; |
| 18 | + --mono: "JetBrains Mono", "Fira Code", "Cascadia Code", ui-monospace, "SF Mono", Menlo, Consolas, monospace; |
20 | 19 | } |
21 | 20 |
|
| 21 | + html, body { height: 100%; } |
| 22 | + |
22 | 23 | body { |
23 | | - font-family: "Outfit", ui-rounded, system-ui, -apple-system, sans-serif; |
| 24 | + font-family: var(--mono); |
24 | 25 | background: var(--bg); |
25 | 26 | color: var(--text); |
26 | | - min-height: 100vh; |
| 27 | + font-size: 14px; |
| 28 | + line-height: 1.6; |
| 29 | + padding: 40px 24px; |
27 | 30 | display: flex; |
28 | 31 | flex-direction: column; |
29 | | - align-items: center; |
| 32 | + align-items: flex-start; |
30 | 33 | justify-content: center; |
31 | | - padding: 40px 20px; |
32 | | - position: relative; |
33 | | - overflow-x: hidden; |
| 34 | + min-height: 100vh; |
| 35 | + max-width: 720px; |
| 36 | + margin: 0 auto; |
34 | 37 | } |
35 | 38 |
|
36 | | - body::before { |
37 | | - content: ""; |
38 | | - position: fixed; |
39 | | - inset: 0; |
40 | | - background: |
41 | | - radial-gradient(ellipse 70% 45% at 50% -5%, rgba(248,113,113,.09) 0%, transparent 70%), |
42 | | - radial-gradient(ellipse 55% 35% at 85% 85%, rgba(129,140,248,.07) 0%, transparent 60%); |
43 | | - pointer-events: none; |
44 | | - z-index: 0; |
| 39 | + .line { |
| 40 | + display: flex; |
| 41 | + align-items: baseline; |
| 42 | + gap: 10px; |
| 43 | + min-height: 1.6em; |
45 | 44 | } |
46 | 45 |
|
47 | | - body::after { |
48 | | - content: ""; |
49 | | - position: fixed; |
50 | | - inset: 0; |
51 | | - background-image: radial-gradient(rgba(148,163,184,.1) 1px, transparent 1px); |
52 | | - background-size: 28px 28px; |
53 | | - pointer-events: none; |
54 | | - z-index: 0; |
55 | | - } |
| 46 | + .line + .line { margin-top: 2px; } |
| 47 | + .spacer { margin-top: 20px; } |
56 | 48 |
|
57 | | - .card { |
58 | | - position: relative; |
59 | | - z-index: 1; |
| 49 | + .prompt { color: var(--muted); user-select: none; } |
| 50 | + .err { color: var(--red); } |
| 51 | + .dim { color: var(--muted); } |
| 52 | + |
| 53 | + .block { |
60 | 54 | background: var(--surface); |
61 | 55 | border: 1px solid var(--border); |
62 | | - border-radius: 16px; |
63 | | - padding: 44px 48px; |
64 | | - max-width: 560px; |
| 56 | + border-left: 3px solid var(--red); |
| 57 | + border-radius: 6px; |
| 58 | + padding: 16px 20px; |
| 59 | + margin-top: 24px; |
65 | 60 | width: 100%; |
66 | | - box-shadow: 0 24px 64px rgba(0,0,0,.4); |
67 | | - text-align: center; |
68 | 61 | } |
69 | 62 |
|
70 | | - .code { |
71 | | - font-size: clamp(4rem, 18vw, 7rem); |
72 | | - font-weight: 800; |
73 | | - line-height: 1; |
74 | | - background: linear-gradient(135deg, var(--red) 0%, rgba(248,113,113,.5) 100%); |
75 | | - -webkit-background-clip: text; |
76 | | - background-clip: text; |
77 | | - -webkit-text-fill-color: transparent; |
78 | | - margin-bottom: 16px; |
79 | | - letter-spacing: -.03em; |
| 63 | + .block-title { |
| 64 | + color: var(--muted); |
| 65 | + font-size: 11px; |
| 66 | + letter-spacing: .08em; |
| 67 | + text-transform: uppercase; |
| 68 | + margin-bottom: 12px; |
80 | 69 | } |
81 | 70 |
|
82 | | - h1 { |
83 | | - font-size: 1.3rem; |
84 | | - font-weight: 600; |
85 | | - margin-bottom: 10px; |
| 71 | + .kv { |
| 72 | + display: flex; |
| 73 | + gap: 12px; |
| 74 | + line-height: 1.9; |
86 | 75 | } |
87 | 76 |
|
88 | | - .sub { |
| 77 | + .key { |
89 | 78 | color: var(--muted); |
90 | | - font-size: .92rem; |
91 | | - line-height: 1.65; |
92 | | - margin-bottom: 36px; |
| 79 | + flex-shrink: 0; |
| 80 | + min-width: 80px; |
| 81 | + } |
| 82 | + |
| 83 | + .val { color: var(--text); } |
| 84 | + |
| 85 | + .path-val { |
| 86 | + color: var(--red); |
| 87 | + word-break: break-all; |
93 | 88 | } |
94 | 89 |
|
95 | 90 | .actions { |
96 | 91 | display: flex; |
97 | | - align-items: center; |
98 | | - justify-content: center; |
| 92 | + gap: 12px; |
99 | 93 | flex-wrap: wrap; |
100 | | - gap: 10px; |
| 94 | + margin-top: 24px; |
101 | 95 | } |
102 | 96 |
|
103 | 97 | .btn { |
104 | 98 | display: inline-flex; |
105 | 99 | align-items: center; |
106 | | - gap: 7px; |
107 | | - border-radius: 9px; |
108 | | - padding: 10px 20px; |
109 | | - font-size: .87rem; |
110 | | - font-weight: 600; |
| 100 | + gap: 6px; |
| 101 | + border: 1px solid var(--border); |
| 102 | + border-radius: 6px; |
| 103 | + padding: 7px 14px; |
| 104 | + font-family: var(--mono); |
| 105 | + font-size: 13px; |
| 106 | + color: var(--text); |
111 | 107 | text-decoration: none; |
| 108 | + background: var(--surface); |
112 | 109 | cursor: pointer; |
113 | | - border: none; |
114 | | - transition: opacity .15s, background .15s, border-color .15s; |
115 | | - font-family: inherit; |
116 | | - } |
117 | | - |
118 | | - .btn-primary { |
119 | | - background: var(--accent); |
120 | | - color: #0f172a; |
| 110 | + transition: border-color .12s, color .12s; |
121 | 111 | } |
122 | 112 |
|
123 | | - .btn-primary:hover { opacity: .88; } |
124 | | - |
125 | | - .btn-ghost { |
126 | | - background: transparent; |
127 | | - color: var(--muted); |
128 | | - border: 1px solid var(--border); |
| 113 | + .btn:hover { |
| 114 | + border-color: var(--cyan); |
| 115 | + color: var(--cyan); |
129 | 116 | } |
130 | 117 |
|
131 | | - .btn-ghost:hover { |
132 | | - border-color: var(--accent); |
133 | | - color: var(--accent); |
134 | | - } |
135 | | - |
136 | | - .divider { |
| 118 | + .section-divider { |
137 | 119 | border: none; |
138 | 120 | border-top: 1px solid var(--border); |
139 | | - margin: 32px 0 24px; |
| 121 | + margin: 28px 0; |
| 122 | + width: 100%; |
140 | 123 | } |
141 | 124 |
|
142 | | - .brand { |
143 | | - display: inline-flex; |
144 | | - align-items: center; |
145 | | - gap: 8px; |
146 | | - font-size: .82rem; |
| 125 | + .footer-line { |
147 | 126 | color: var(--muted); |
148 | | - text-decoration: none; |
| 127 | + font-size: 12px; |
149 | 128 | } |
150 | 129 |
|
151 | | - .brand-logo { |
152 | | - width: 20px; |
153 | | - height: 20px; |
154 | | - border-radius: 5px; |
155 | | - background: linear-gradient(135deg, var(--accent), var(--accent-2)); |
156 | | - display: flex; |
157 | | - align-items: center; |
158 | | - justify-content: center; |
159 | | - font-weight: 800; |
160 | | - font-size: .6rem; |
161 | | - color: #0f172a; |
162 | | - letter-spacing: -.5px; |
163 | | - flex-shrink: 0; |
| 130 | + a.plain { |
| 131 | + color: var(--cyan); |
| 132 | + text-decoration: none; |
164 | 133 | } |
165 | 134 |
|
166 | | - .brand:hover { color: var(--text); } |
| 135 | + a.plain:hover { text-decoration: underline; } |
167 | 136 |
|
168 | | - @media (max-width: 500px) { |
169 | | - .card { padding: 32px 24px; } |
| 137 | + @media (max-width: 540px) { |
| 138 | + body { font-size: 13px; padding: 24px 16px; } |
170 | 139 | } |
171 | 140 | </style> |
172 | 141 | </head> |
173 | 142 | <body> |
174 | | - <div class="card"> |
175 | | - <div class="code">404</div> |
176 | | - <h1>Page not found</h1> |
177 | | - <p class="sub"> |
178 | | - The page you're looking for doesn't exist or has been moved.<br> |
179 | | - Double-check the URL or head back home. |
180 | | - </p> |
181 | | - |
182 | | - <div class="actions"> |
183 | | - <a href="/" class="btn btn-primary"> |
184 | | - <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"> |
185 | | - <path d="M3 9l9-7 9 7v11a2 2 0 01-2 2H5a2 2 0 01-2-2z"/><polyline points="9 22 9 12 15 12 15 22"/> |
186 | | - </svg> |
187 | | - Go home |
188 | | - </a> |
189 | | - <button class="btn btn-ghost" onclick="history.back()"> |
190 | | - <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"> |
191 | | - <polyline points="15 18 9 12 15 6"/> |
192 | | - </svg> |
193 | | - Go back |
194 | | - </button> |
195 | | - </div> |
196 | 143 |
|
197 | | - <hr class="divider" /> |
| 144 | + <div class="line"> |
| 145 | + <span class="prompt">$</span> |
| 146 | + <span>GET <span id="req-path" class="path-val">/</span></span> |
| 147 | + </div> |
198 | 148 |
|
199 | | - <a href="https://21no.de" class="brand"> |
200 | | - <div class="brand-logo">21</div> |
201 | | - <span>Served by static-web — BackendStack21</span> |
| 149 | + <div class="line spacer"> |
| 150 | + <span class="err">✗</span> |
| 151 | + <span><strong>404</strong> — resource not found</span> |
| 152 | + </div> |
| 153 | + |
| 154 | + <div class="block"> |
| 155 | + <div class="block-title">// error details</div> |
| 156 | + <div class="kv"> |
| 157 | + <span class="key">status</span> |
| 158 | + <span class="val err">404 Not Found</span> |
| 159 | + </div> |
| 160 | + <div class="kv"> |
| 161 | + <span class="key">path</span> |
| 162 | + <span class="val path-val" id="err-path">/</span> |
| 163 | + </div> |
| 164 | + <div class="kv"> |
| 165 | + <span class="key">hint</span> |
| 166 | + <span class="val dim">the file does not exist or was moved</span> |
| 167 | + </div> |
| 168 | + </div> |
| 169 | + |
| 170 | + <div class="actions"> |
| 171 | + <a href="/" class="btn"> |
| 172 | + <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> |
| 173 | + <path d="M3 9l9-7 9 7v11a2 2 0 01-2 2H5a2 2 0 01-2-2z"/><polyline points="9 22 9 12 15 12 15 22"/> |
| 174 | + </svg> |
| 175 | + ~/ |
202 | 176 | </a> |
| 177 | + <button class="btn" onclick="history.back()"> |
| 178 | + <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> |
| 179 | + <polyline points="15 18 9 12 15 6"/> |
| 180 | + </svg> |
| 181 | + go back |
| 182 | + </button> |
| 183 | + </div> |
| 184 | + |
| 185 | + <hr class="section-divider" /> |
| 186 | + |
| 187 | + <div class="footer-line"> |
| 188 | + Powered by <a class="plain" href="https://github.com/BackendStack21/static-web">static-web</a> |
| 189 | + — <a class="plain" href="https://21no.de">BackendStack21</a> |
203 | 190 | </div> |
| 191 | + |
| 192 | + <script> |
| 193 | + var p = window.location.pathname; |
| 194 | + document.getElementById('req-path').textContent = p; |
| 195 | + document.getElementById('err-path').textContent = p; |
| 196 | + </script> |
| 197 | + |
204 | 198 | </body> |
205 | 199 | </html> |
0 commit comments