fuzzyworld-tools / files / server / site / _icons.css
_icons.css
510a1337 2026-10-28 Pavel Safronov | 1 | /* ============================================================================= |
| 2 | FuzzyWorld Icon System | |
| 3 | ||
| 4 | Icon classes using inline SVG data URIs. | |
| 5 | All icons are self-contained and work without external dependencies. | |
| 6 | ||
| 7 | Usage: | |
| 8 | <span class="icon icon-vscode"></span> | |
| 9 | <a href="..." class="icon-link icon-github">GitHub</a> | |
| 10 | ||
| 11 | For links that go to external sites: | |
| 12 | <a href="https://..." class="external">Link text</a> | |
| 13 | This will automatically add the external icon via ::after | |
| 14 | ============================================================================= */ | |
| 15 | ||
| 16 | /* --------------------------------------------------------------------- | |
| 17 | Icon Base Styles | |
| 18 | --------------------------------------------------------------------- */ | |
| 19 | ||
| 20 | .icon { | |
| 21 | display: inline-block; | |
| 22 | width: 1em; | |
| 23 | height: 1em; | |
| 24 | vertical-align: -0.125em; | |
| 25 | fill: currentColor; | |
| 26 | flex-shrink: 0; | |
| 27 | background-size: contain; | |
| 28 | background-repeat: no-repeat; | |
| 29 | background-position: center; | |
| 30 | } | |
| 31 | ||
| 32 | /* Icon with text - adds proper spacing */ | |
| 33 | .icon-text { | |
| 34 | display: inline-flex; | |
| 35 | align-items: center; | |
| 36 | gap: 0.25em; | |
| 37 | } | |
| 38 | ||
| 39 | .icon-text .icon { | |
| 40 | width: 0.9em; | |
| 41 | height: 0.9em; | |
| 42 | } | |
| 43 | ||
| 44 | /* --------------------------------------------------------------------- | |
| 45 | External Link Indicator | |
| 46 | Automatically added to external links (not fuzzyworld.net) | |
| 47 | --------------------------------------------------------------------- */ | |
| 48 | ||
| 49 | a[href^="http"]:not([href*="fuzzyworld.net"]):not(.no-external)::after, | |
| 50 | a[href^="mailto:"]::after, | |
| 51 | a[href^="vscode://"]::after { | |
| 52 | content: " "; | |
| 53 | display: inline-block; | |
| 54 | width: 0.8em; | |
| 55 | height: 0.8em; | |
| 56 | vertical-align: 0.05em; | |
| 57 | background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6'/%3E%3Cpolyline points='15 3 21 3 21 9'/%3E%3Cline x1='10' y1='14' x2='21' y2='3'/%3E%3C/svg%3E"); | |
| 58 | opacity: 0.6; | |
| 59 | } | |
| 60 | ||
| 61 | /* Disable external icon for specific links */ | |
| 62 | .no-external::after { | |
| 63 | content: none; | |
| 64 | } | |
| 65 | ||
| 66 | /* --------------------------------------------------------------------- | |
| 67 | Brand & Platform Icons | |
| 68 | --------------------------------------------------------------------- */ | |
| 69 | ||
| 70 | /* FuzzyWorld logo placeholder */ | |
| 71 | .icon-fuzzyworld::before { | |
| 72 | content: "f"; | |
| 73 | font-weight: 700; | |
| 74 | font-size: 1.2em; | |
| 75 | letter-spacing: -0.02em; | |
| 76 | } | |
| 77 | ||
| 78 | /* VS Code Icon - Simple V in a diamond */ | |
| 79 | .icon-vscode { | |
| 80 | background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='currentColor' d='M12 2L2 7l10 5 10-5-10-5zM2 17l10 5 10-5M2 12l10 5 10-5'/%3E%3C/svg%3E"); | |
| 81 | } | |
| 82 | ||
| 83 | /* GitHub Octocat Icon */ | |
| 84 | .icon-github { | |
| 85 | background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='currentColor'%3E%3Cpath d='M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.163.798-.254.798-.554 0-.297-.006-.597-.006-.898 0-.297.006-.597.006-.898.598-.162.797-.66 7.983-1.178.708-.518 1.116-1.357 1.116-2.272 0-.298-.006-.598-.006-.898 0-.298.006-.598.006-.898.598-.163.797-.662 7.983-1.179.708-.518 1.116-1.356 1.116-2.272 0-.897-.006-1.796-.006-2.694 0-.298-.006-.598-.006-.898 0-.298.006-.598.006-.898.598-.163.797-.662 7.983-1.179.708-.518 1.116-1.357 1.116-2.272 0-.897-.006-1.796-.006-2.694 0-.297-.006-.597-.006-.897 0-.297.006-.597.006-.897.598-.162.797-.66 7.983-1.178.708-.518 1.116-1.357 1.116-2.272 0-.898-.006-1.797-.006-2.695C13.438 1.6 14 0 12 0zm0 2.157c6.626 0 12 5.373 12 12s-5.374 12-12 12S0 17.373 0 12 5.374 0 12 0zm-3.35 15.257l-2.077-2.077-1.116 1.116 2.077 2.077 1.116-1.116zm1.116-2.592l-1.116-1.116-1.116 1.116 1.116 1.116 1.116-1.116z'/%3E%3C/svg%3E"); | |
| 86 | } | |
| 87 | ||
| 88 | /* Git Icon */ | |
| 89 | .icon-git { | |
| 90 | background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='currentColor'%3E%3Cpath d='M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.163.798-.254.798-.554 0-.297-.006-.597-.006-.898 0-.297.006-.597.006-.898.598-.162.797-.66 7.983-1.178.708-.518 1.116-1.357 1.116-2.272 0-.298-.006-.598-.006-.898 0-.298.006-.598.006-.898.598-.163.797-.662 7.983-1.179.708-.518 1.116-1.356 1.116-2.272 0-.897-.006-1.796-.006-2.694 0-.298-.006-.598-.006-.898 0-.298.006-.598.006-.898.598-.163.797-.662 7.983-1.179.708-.518 1.116-1.357 1.116-2.272C6.811 2.57 5.373 1.5 12 1.5c6.626 0 12 5.373 12 12s-5.374 12-12 12z'/%3E%3C/svg%3E"); | |
| 91 | } | |
| 92 | ||
| 93 | /* Code Icon */ | |
| 94 | .icon-code { | |
| 95 | background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='currentColor'%3E%3Cpath d='m15.5 10.5-2-2-2 2-2-2-2 2-2-2-2 2 2 2-2-2 2 2 2-2 2-2 2-2-2 2 2z'/%3E%3C/svg%3E"); | |
| 96 | } | |
| 97 | ||
| 98 | /* --------------------------------------------------------------------- | |
| 99 | File & Directory Icons | |
| 100 | --------------------------------------------------------------------- */ | |
| 101 | ||
| 102 | /* Folder Icon */ | |
| 103 | .icon-folder { | |
| 104 | background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='currentColor'%3E%3Cpath d='M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2-3h9a2 2 0 0 1 2 2z'/%3E%3C/svg%3E"); | |
| 105 | } | |
| 106 | ||
| 107 | /* File Icon */ | |
| 108 | .icon-file { | |
| 109 | background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='currentColor'%3E%3Cpath d='M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z'/%3E%3Cpolyline points='14 2 14 8 20 8'/%3E%3Cline x1='16' y1='13' x2='8' y2='13'/%3E%3Cline x1='16' y1='17' x2='8' y2='17'/%3E%3Cpath d='M10 20h4'/%3E%3C/svg%3E"); | |
| 110 | } | |
| 111 | ||
| 112 | /* File Code Icon */ | |
| 113 | .icon-file-code { | |
| 114 | background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='currentColor'%3E%3Cpath d='M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2V8z'/%3E%3Cpolyline points='14 2 14 8 20 8'/%3E%3Cline x1='16' y1='13' x2='8' y2='13'/%3E%3Cline x1='16' y1='17' x2='8' y2='17'/%3E%3Cpolyline points='10 9 9 9 8 9'/%3E%3Cpolyline points='17 9 18 9 19 9'/%3E%3C/svg%3E"); | |
| 115 | } | |
| 116 | ||
| 117 | /* Image Icon */ | |
| 118 | .icon-image { | |
| 119 | background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='currentColor'%3E%3Cpath d='M23 19a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h18a2 2 0 0 1 2 2v14zM10 15l5-5-5-5v10z'/%3E%3C/svg%3E"); | |
| 120 | } | |
| 121 | ||
| 122 | /* Markdown Icon */ | |
| 123 | .icon-markdown { | |
| 124 | background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='currentColor'%3E%3Cpath d='M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z'/%3E%3Cpolyline points='14 2 14 8 20 8'/%3E%3Cline x1='16' y1='13' x2='8' y2='13'/%3E%3Cline x1='16' y1='17' x2='8' y2='17'/%3E%3Cpolyline points='10 9 9 9 8 9'/%3E%3Cpolyline points='17 9 18 9 19 9'/%3E%3C/svg%3E"); | |
| 125 | } | |
| 126 | ||
| 127 | /* --------------------------------------------------------------------- | |
| 128 | UI & Status Icons | |
| 129 | --------------------------------------------------------------------- */ | |
| 130 | ||
| 131 | /* Checkmark / Success Icon */ | |
| 132 | .icon-check { | |
| 133 | background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'/%3E%3C/svg%3E"); | |
| 134 | } | |
| 135 | ||
| 136 | /* X / Error Icon */ | |
| 137 | .icon-x { | |
| 138 | background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cline x1='18' y1='6' x2='6' y2='18'/%3E%3Cline x1='6' y1='6' x2='18' y2='18'/%3E%3C/svg%3E"); | |
| 139 | } | |
| 140 | ||
| 141 | /* Circle / Running Icon (spinner-like) */ | |
| 142 | .icon-circle { | |
| 143 | background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='currentColor'%3E%3Ccircle cx='12' cy='12' r='10'/%3E%3C/svg%3E"); | |
| 144 | } | |
| 145 | ||
| 146 | /* Alert / Warning Icon */ | |
| 147 | .icon-alert { | |
| 148 | background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'/%3E%3Cline x1='12' y1='8' x2='12' y2='12'/%3E%3Cline x1='12' y1='16' x2='12.01' y2='16'/%3E%3C/svg%3E"); | |
| 149 | } | |
| 150 | ||
| 151 | /* Clock / Time Icon */ | |
| 152 | .icon-clock { | |
| 153 | background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'/%3E%3Cpolyline points='12 6 12 12 16 14'/%3E%3C/svg%3E"); | |
| 154 | } | |
| 155 | ||
| 156 | /* Arrow Right (for navigation) */ | |
| 157 | .icon-arrow-right { | |
| 158 | background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cline x1='5' y1='12' x2='19' y2='12'/%3E%3Cpolyline points='12 5 19 12 12 19'/%3E%3C/svg%3E"); | |
| 159 | } | |
| 160 | ||
| 161 | /* Arrow Up Right (external link style) */ | |
| 162 | .icon-arrow-up-right { | |
| 163 | background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cline x1='7' y1='17' x2='17' y2='7'/%3E%3Cpolyline points='7 7 17 7 17 17'/%3E%3C/svg%3E"); | |
| 164 | } | |
| 165 | ||
| 166 | /* --------------------------------------------------------------------- | |
| 167 | Application Icons | |
| 168 | --------------------------------------------------------------------- */ | |
| 169 | ||
| 170 | /* App Icon (generic) */ | |
| 171 | .icon-app { | |
| 172 | background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='currentColor'%3E%3Cpath d='M6 2L3 6v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V6l-3-4z'/%3E%3Cpath d='M12 6l4 4-4 4-4-4 4-4z'/%3E%3C/svg%3E"); | |
| 173 | } | |
| 174 | ||
| 175 | /* Web Icon */ | |
| 176 | .icon-web { | |
| 177 | background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='currentColor'%3E%3Ccircle cx='12' cy='12' r='10'/%3E%3Cline x1='2' y1='12' x2='22' y2='12'/%3E%3Cpath d='M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z'/%3E%3C/svg%3E"); | |
| 178 | } | |
| 179 | ||
| 180 | /* --------------------------------------------------------------------- | |
| 181 | Helper Classes for Icon + Text Combinations | |
| 182 | --------------------------------------------------------------------- */ | |
| 183 | ||
| 184 | /* VS Code link with icon */ | |
| 185 | .vscode-link { | |
| 186 | display: inline-flex; | |
| 187 | align-items: center; | |
| 188 | gap: 0.35em; | |
| 189 | } | |
| 190 | ||
| 191 | .vscode-link::before { | |
| 192 | content: ""; | |
| 193 | display: inline-block; | |
| 194 | width: 1em; | |
| 195 | height: 1em; | |
| 196 | background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='currentColor' d='M12 2L2 7l10 5 10-5-10-5zM2 17l10 5 10-5M2 12l10 5 10-5'/%3E%3C/svg%3E"); | |
| 197 | background-size: contain; | |
| 198 | background-repeat: no-repeat; | |
| 199 | background-position: center; | |
| 200 | } | |
| 201 | ||
| 202 | /* Clone command icon */ | |
| 203 | .clone-icon::before { | |
| 204 | content: ""; | |
| 205 | display: inline-block; | |
| 206 | width: 1em; | |
| 207 | height: 1em; | |
| 208 | background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='currentColor'%3E%3Cpath d='M16 22s2-4-2-4-2 4-2 4-4-2-2-4-2 4-2 4-4-2-2 4-6-4 2-2 4 2 2 6-4-2-2 4 6-2 4 2 2 4 6 4'/%3E%3C/svg%3E"); | |
| 209 | background-size: contain; | |
| 210 | background-repeat: no-repeat; | |
| 211 | background-position: center; | |
| 212 | } |