vole
Clone
Read only, no credentials:
https://rodent.software/git/vole.git
Write over SSH with a registered key:
git clone ssh://git@0.0.0.0:2222/vole.git
A free and open-source forge that lives in your Git repo.
|
796ac8c0
Keenan Nemetz
11d ago
|
1 | /* Everforest: sainnhe's warm, green-based palette, adapted to Vole's tokens. |
| 2 | https://github.com/sainnhe/everforest (MIT) | |
| 3 | ||
| 4 | Six variants share one layout: dark and light, each in hard, medium, and soft | |
| 5 | contrast. This is Vole's permanent theme; the document starts on dark/medium | |
| 6 | and static/theme.js applies a saved account-page choice (or the system's | |
| 7 | light/dark medium default) before the first paint. | |
| 8 | ||
| 9 | The palette is taken from palette.md. The light foreground accents are mixed | |
| 10 | with the dark ground in a few places (links, status text) so small UI type | |
| 11 | keeps its contrast; syntax highlighting uses the published accents as-is. */ | |
| 12 | ||
| 13 | /* ---------- foreground palette ---------- */ | |
| 14 | ||
| 15 | :root[data-theme^="everforest-"] { | |
| 16 | --ef-fg: #d3c6aa; | |
| 17 | --ef-red: #e67e80; | |
| 18 | --ef-orange: #e69875; | |
| 19 | --ef-yellow: #dbbc7f; | |
| 20 | --ef-green: #a7c080; | |
| 21 | --ef-aqua: #83c092; | |
| 22 | --ef-blue: #7fbbb3; | |
| 23 | --ef-purple: #d699b6; | |
| 24 | --ef-grey0: #7a8478; | |
| 25 | --ef-grey1: #859289; | |
| 26 | --ef-grey2: #9da9a0; | |
| 27 | accent-color: var(--accent); | |
| 28 | } | |
| 29 | ||
| 30 | :root[data-theme^="everforest-light"] { | |
| 31 | --ef-fg: #5c6a72; | |
| 32 | --ef-red: #f85552; | |
| 33 | --ef-orange: #f57d26; | |
| 34 | --ef-yellow: #dfa000; | |
| 35 | --ef-green: #8da101; | |
| 36 | --ef-aqua: #35a77c; | |
| 37 | --ef-blue: #3a94c5; | |
| 38 | --ef-purple: #df69ba; | |
| 39 | --ef-grey0: #a6b0a0; | |
| 40 | --ef-grey1: #939f91; | |
| 41 | --ef-grey2: #829181; | |
| 42 | } | |
| 43 | ||
| 44 | /* ---------- background palette ---------- */ | |
| 45 | ||
| 46 | :root[data-theme="everforest-dark-hard"] { | |
| 47 | --ef-bg0: #272e33; | |
| 48 | --ef-bg1: #2e383c; | |
| 49 | --ef-bg2: #374145; | |
| 50 | --ef-bg3: #414b50; | |
| 51 | --ef-bg4: #495156; | |
| 52 | --ef-bg5: #4f5b58; | |
| 53 | --ef-bg-red: #493b40; | |
| 54 | --ef-bg-yellow: #45443c; | |
| 55 | --ef-bg-green: #3c4841; | |
| 56 | --ef-bg-blue: #384b55; | |
| 57 | --ef-bg-purple: #463f48; | |
| 58 | } | |
| 59 | :root[data-theme="everforest-dark-medium"] { | |
| 60 | --ef-bg0: #2d353b; | |
| 61 | --ef-bg1: #343f44; | |
| 62 | --ef-bg2: #3d484d; | |
| 63 | --ef-bg3: #475258; | |
| 64 | --ef-bg4: #4f585e; | |
| 65 | --ef-bg5: #56635f; | |
| 66 | --ef-bg-red: #514045; | |
| 67 | --ef-bg-yellow: #4d4c43; | |
| 68 | --ef-bg-green: #425047; | |
| 69 | --ef-bg-blue: #3a515d; | |
| 70 | --ef-bg-purple: #4a444e; | |
| 71 | } | |
| 72 | :root[data-theme="everforest-dark-soft"] { | |
| 73 | --ef-bg0: #333c43; | |
| 74 | --ef-bg1: #3a464c; | |
| 75 | --ef-bg2: #434f55; | |
| 76 | --ef-bg3: #4d5960; | |
| 77 | --ef-bg4: #555f66; | |
| 78 | --ef-bg5: #5d6b66; | |
| 79 | --ef-bg-red: #59464c; | |
| 80 | --ef-bg-yellow: #55544a; | |
| 81 | --ef-bg-green: #48584e; | |
| 82 | --ef-bg-blue: #3f5865; | |
| 83 | --ef-bg-purple: #4e4953; | |
| 84 | } | |
| 85 | :root[data-theme="everforest-light-hard"] { | |
| 86 | --ef-bg0: #fffbef; | |
| 87 | --ef-bg1: #f8f5e4; | |
| 88 | --ef-bg2: #f2efdf; | |
| 89 | --ef-bg3: #edeada; | |
| 90 | --ef-bg4: #e8e5d5; | |
| 91 | --ef-bg5: #bec5b2; | |
| 92 | --ef-bg-red: #ffe7de; | |
| 93 | --ef-bg-yellow: #fef2d5; | |
| 94 | --ef-bg-green: #f3f5d9; | |
| 95 | --ef-bg-blue: #ecf5ed; | |
| 96 | --ef-bg-purple: #fceced; | |
| 97 | } | |
| 98 | :root[data-theme="everforest-light-medium"] { | |
| 99 | --ef-bg0: #fdf6e3; | |
| 100 | --ef-bg1: #f4f0d9; | |
| 101 | --ef-bg2: #efebd4; | |
| 102 | --ef-bg3: #e6e2cc; | |
| 103 | --ef-bg4: #e0dcc7; | |
| 104 | --ef-bg5: #bdc3af; | |
| 105 | --ef-bg-red: #fde3da; | |
| 106 | --ef-bg-yellow: #faedcd; | |
| 107 | --ef-bg-green: #f0f1d2; | |
| 108 | --ef-bg-blue: #e9f0e9; | |
| 109 | --ef-bg-purple: #fae8e2; | |
| 110 | } | |
| 111 | :root[data-theme="everforest-light-soft"] { | |
| 112 | --ef-bg0: #f3ead3; | |
| 113 | --ef-bg1: #eae4ca; | |
| 114 | --ef-bg2: #e5dfc5; | |
| 115 | --ef-bg3: #ddd8be; | |
| 116 | --ef-bg4: #d8d3ba; | |
| 117 | --ef-bg5: #b9c0ab; | |
| 118 | --ef-bg-red: #fadbd0; | |
| 119 | --ef-bg-yellow: #f1e4c5; | |
| 120 | --ef-bg-green: #e5e6c5; | |
| 121 | --ef-bg-blue: #e1e7dd; | |
| 122 | --ef-bg-purple: #f1ddd4; | |
| 123 | } | |
| 124 | ||
| 125 | /* ---------- dark tokens ---------- */ | |
| 126 | ||
| 127 | :root[data-theme^="everforest-dark"] { | |
| 128 | color-scheme: dark; | |
| 129 | ||
| 130 | --bg: var(--ef-bg0); | |
| 131 | --bg-panel: var(--ef-bg1); | |
| 132 | --bg-raised: var(--ef-bg2); | |
| 133 | --bg-hover: var(--ef-bg3); | |
| 134 | --bg-active: var(--ef-bg4); | |
| 135 | --border: var(--ef-bg4); | |
| 136 | --border-strong: var(--ef-bg5); | |
| 137 | ||
| 138 | --fg: var(--ef-fg); | |
| 139 | --fg-muted: var(--ef-grey2); | |
| 140 | --fg-faint: var(--ef-grey1); | |
| 141 | ||
| 142 | --accent: var(--ef-green); | |
| 143 | --accent-fg: var(--ef-bg0); | |
| 144 | --accent-soft: color-mix(in srgb, var(--ef-green) 16%, transparent); | |
|
3516aef3
Keenan Nemetz
10d ago
|
145 | /* This theme's accent and good are both green, so a running job needs the |
| 146 | palette's blue to stay distinct from one that already finished. */ | |
| 147 | --running: var(--ef-blue); | |
|
796ac8c0
Keenan Nemetz
11d ago
|
148 | --good: var(--ef-green); |
| 149 | --good-soft: var(--ef-bg-green); | |
| 150 | --bad: var(--ef-red); | |
| 151 | --bad-soft: var(--ef-bg-red); | |
| 152 | --warn: var(--ef-yellow); | |
| 153 | --warn-soft: var(--ef-bg-yellow); | |
|
0e35a6a0
Keenan Nemetz
11d ago
|
154 | /* Kept off --accent, which is this theme's green: a merged request must not |
| 155 | look like an open one. The purple is the palette's own. */ | |
| 156 | --merged: var(--ef-purple); | |
| 157 | --merged-soft: var(--ef-bg-purple); | |
|
796ac8c0
Keenan Nemetz
11d ago
|
158 | |
| 159 | --syn-comment: var(--ef-grey1); | |
| 160 | --syn-punctuation: var(--ef-grey2); | |
| 161 | --syn-operator: var(--ef-orange); | |
| 162 | --syn-number: var(--ef-purple); | |
| 163 | --syn-string: var(--ef-green); | |
| 164 | --syn-keyword: var(--ef-red); | |
| 165 | --syn-function: var(--ef-green); | |
| 166 | --syn-type: var(--ef-yellow); | |
| 167 | --syn-variable: var(--ef-fg); | |
| 168 | --syn-added: var(--ef-green); | |
| 169 | --syn-deleted: var(--ef-red); | |
| 170 | } | |
| 171 | ||
| 172 | /* ---------- light tokens ---------- */ | |
| 173 | ||
| 174 | :root[data-theme^="everforest-light"] { | |
| 175 | color-scheme: light; | |
| 176 | ||
| 177 | --bg: var(--ef-bg0); | |
| 178 | --bg-panel: var(--ef-bg1); | |
| 179 | --bg-raised: var(--ef-bg2); | |
| 180 | --bg-hover: var(--ef-bg3); | |
| 181 | --bg-active: var(--ef-bg4); | |
| 182 | --border: var(--ef-bg4); | |
| 183 | --border-strong: var(--ef-bg5); | |
| 184 | ||
| 185 | --fg: var(--ef-fg); | |
| 186 | --fg-muted: #708089; | |
| 187 | --fg-faint: var(--ef-grey2); | |
| 188 | ||
| 189 | /* The published light green is a highlighter on paper. These two shades are | |
| 190 | the same hue mixed toward the dark ground so links and small labels read. */ | |
| 191 | --accent: #677618; | |
| 192 | --accent-fg: #fffbef; | |
| 193 | --accent-soft: rgba(141, 161, 1, 0.14); | |
|
3516aef3
Keenan Nemetz
10d ago
|
194 | --running: var(--ef-blue); |
|
796ac8c0
Keenan Nemetz
11d ago
|
195 | --good: #677618; |
| 196 | --good-soft: var(--ef-bg-green); | |
| 197 | --bad: #bb4b4b; | |
| 198 | --bad-soft: var(--ef-bg-red); | |
| 199 | --warn: #866a1e; | |
| 200 | --warn-soft: var(--ef-bg-yellow); | |
|
0e35a6a0
Keenan Nemetz
11d ago
|
201 | /* The published light purple is a highlighter on paper; this shade keeps the |
| 202 | same hue dark enough for the 11px state label. */ | |
| 203 | --merged: #9b4a86; | |
| 204 | --merged-soft: var(--ef-bg-purple); | |
|
796ac8c0
Keenan Nemetz
11d ago
|
205 | |
| 206 | --syn-comment: var(--ef-grey1); | |
| 207 | --syn-punctuation: var(--ef-grey2); | |
| 208 | --syn-operator: var(--ef-orange); | |
| 209 | --syn-number: var(--ef-purple); | |
| 210 | --syn-string: var(--ef-green); | |
| 211 | --syn-keyword: var(--ef-red); | |
| 212 | --syn-function: var(--ef-green); | |
| 213 | --syn-type: var(--ef-yellow); | |
| 214 | --syn-variable: var(--ef-fg); | |
| 215 | --syn-added: var(--ef-green); | |
| 216 | --syn-deleted: var(--ef-red); | |
| 217 | } | |
| 218 | ||
| 219 | /* ---------- syntax highlighting ---------- */ | |
| 220 | ||
| 221 | /* vole.css colours Prism tokens with a fixed dark palette. Everforest swaps | |
| 222 | those colours for its own accents; the token classes are the same. */ | |
| 223 | :root[data-theme^="everforest-"] :is(.blob, .diff) .token.comment, | |
| 224 | :root[data-theme^="everforest-"] :is(.blob, .diff) .token.prolog, | |
| 225 | :root[data-theme^="everforest-"] :is(.blob, .diff) .token.doctype, | |
| 226 | :root[data-theme^="everforest-"] :is(.blob, .diff) .token.cdata { | |
| 227 | color: var(--syn-comment); | |
| 228 | } | |
| 229 | :root[data-theme^="everforest-"] :is(.blob, .diff) .token.punctuation, | |
| 230 | :root[data-theme^="everforest-"] :is(.blob, .diff) .token.namespace { | |
| 231 | color: var(--syn-punctuation); | |
| 232 | } | |
| 233 | :root[data-theme^="everforest-"] :is(.blob, .diff) .token.operator, | |
| 234 | :root[data-theme^="everforest-"] :is(.blob, .diff) .token.entity, | |
| 235 | :root[data-theme^="everforest-"] :is(.blob, .diff) .token.url { | |
| 236 | color: var(--syn-operator); | |
| 237 | } | |
| 238 | :root[data-theme^="everforest-"] :is(.blob, .diff) .token.boolean, | |
| 239 | :root[data-theme^="everforest-"] :is(.blob, .diff) .token.number, | |
| 240 | :root[data-theme^="everforest-"] :is(.blob, .diff) .token.constant, | |
| 241 | :root[data-theme^="everforest-"] :is(.blob, .diff) .token.symbol { | |
| 242 | color: var(--syn-number); | |
| 243 | } | |
| 244 | :root[data-theme^="everforest-"] :is(.blob, .diff) .token.string, | |
| 245 | :root[data-theme^="everforest-"] :is(.blob, .diff) .token.char, | |
| 246 | :root[data-theme^="everforest-"] :is(.blob, .diff) .token.attr-value, | |
| 247 | :root[data-theme^="everforest-"] :is(.blob, .diff) .token.regex { | |
| 248 | color: var(--syn-string); | |
| 249 | } | |
| 250 | :root[data-theme^="everforest-"] :is(.blob, .diff) .token.atrule, | |
| 251 | :root[data-theme^="everforest-"] :is(.blob, .diff) .token.keyword, | |
| 252 | :root[data-theme^="everforest-"] :is(.blob, .diff) .token.tag, | |
| 253 | :root[data-theme^="everforest-"] :is(.blob, .diff) .token.selector { | |
| 254 | color: var(--syn-keyword); | |
| 255 | } | |
| 256 | :root[data-theme^="everforest-"] :is(.blob, .diff) .token.function, | |
| 257 | :root[data-theme^="everforest-"] :is(.blob, .diff) .token.function-name, | |
| 258 | :root[data-theme^="everforest-"] :is(.blob, .diff) .token.method { | |
| 259 | color: var(--syn-function); | |
| 260 | } | |
| 261 | :root[data-theme^="everforest-"] :is(.blob, .diff) .token.class-name, | |
| 262 | :root[data-theme^="everforest-"] :is(.blob, .diff) .token.builtin, | |
| 263 | :root[data-theme^="everforest-"] :is(.blob, .diff) .token.attr-name, | |
| 264 | :root[data-theme^="everforest-"] :is(.blob, .diff) .token.property, | |
| 265 | :root[data-theme^="everforest-"] :is(.blob, .diff) .token.title { | |
| 266 | color: var(--syn-type); | |
| 267 | } | |
| 268 | :root[data-theme^="everforest-"] :is(.blob, .diff) .token.variable { | |
| 269 | color: var(--syn-variable); | |
| 270 | } | |
| 271 | :root[data-theme^="everforest-"] :is(.blob, .diff) .token.deleted { | |
| 272 | color: var(--syn-deleted); | |
| 273 | } | |
| 274 | :root[data-theme^="everforest-"] :is(.blob, .diff) .token.inserted { | |
| 275 | color: var(--syn-added); | |
| 276 | } |