jekyll-theme-resume 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/403.html +6 -0
- data/404.html +6 -0
- data/500.html +6 -0
- data/CHANGELOG.md +498 -0
- data/CODE_OF_CONDUCT.md +92 -0
- data/LICENSE.txt +22 -0
- data/README.md +184 -0
- data/SECURITY.md +30 -0
- data/_config.sample.yml +329 -0
- data/_data/locales/ar.yml +85 -0
- data/_data/locales/de.yml +86 -0
- data/_data/locales/en.yml +84 -0
- data/_data/locales/es.yml +86 -0
- data/_data/locales/fr.yml +86 -0
- data/_data/locales/ur.yml +86 -0
- data/_data/social_networks.yml +83 -0
- data/_includes/analytics-body.html +12 -0
- data/_includes/analytics-head.html +36 -0
- data/_includes/avatar.html +84 -0
- data/_includes/dark-mode-toggle.html +202 -0
- data/_includes/data-loader.html +42 -0
- data/_includes/date-formatter.html +63 -0
- data/_includes/grouped-item-list.html +53 -0
- data/_includes/hreflang.html +58 -0
- data/_includes/language-switcher.html +72 -0
- data/_includes/print-social-links.html +23 -0
- data/_includes/resume-section.html +547 -0
- data/_includes/safe-url.html +21 -0
- data/_includes/shared-head.html +51 -0
- data/_includes/social-links.html +54 -0
- data/_includes/vendors/svg-icons/ATTRIBUTION.md +34 -0
- data/_includes/vendors/svg-icons/dev.svg +3 -0
- data/_includes/vendors/svg-icons/dribbble-symbol.svg +3 -0
- data/_includes/vendors/svg-icons/envelope.svg +4 -0
- data/_includes/vendors/svg-icons/facebook.svg +3 -0
- data/_includes/vendors/svg-icons/flickr.svg +4 -0
- data/_includes/vendors/svg-icons/github.svg +3 -0
- data/_includes/vendors/svg-icons/globe-1.svg +3 -0
- data/_includes/vendors/svg-icons/instagram.svg +4 -0
- data/_includes/vendors/svg-icons/linkedin.svg +3 -0
- data/_includes/vendors/svg-icons/medium.svg +3 -0
- data/_includes/vendors/svg-icons/phone.svg +13 -0
- data/_includes/vendors/svg-icons/pinterest.svg +3 -0
- data/_includes/vendors/svg-icons/postcard.svg +14 -0
- data/_includes/vendors/svg-icons/telegram.svg +3 -0
- data/_includes/vendors/svg-icons/whatsapp.svg +3 -0
- data/_includes/vendors/svg-icons/x.svg +3 -0
- data/_includes/vendors/svg-icons/youtube.svg +3 -0
- data/_layouts/default.html +65 -0
- data/_layouts/error.html +138 -0
- data/_layouts/profile.html +123 -0
- data/_layouts/resume.html +238 -0
- data/_plugins/error_pages_generator.rb +71 -0
- data/_plugins/json_resume_generator.rb +79 -0
- data/_plugins/resume_pages_generator.rb +71 -0
- data/_plugins/resume_validator.rb +40 -0
- data/_sass/_all-pages.scss +335 -0
- data/_sass/_base.scss +130 -0
- data/_sass/_dark-mode.scss +387 -0
- data/_sass/_layout.scss +116 -0
- data/_sass/_mixins.scss +136 -0
- data/_sass/_normalize.scss +379 -0
- data/_sass/_profile-page.scss +60 -0
- data/_sass/_resume-ltr.scss +436 -0
- data/_sass/_resume-rtl.scss +91 -0
- data/_sass/_variables.scss +45 -0
- data/assets/css/cv-ltr.scss +31 -0
- data/assets/css/cv-rtl.scss +36 -0
- data/assets/css/main.scss +8 -0
- data/assets/css/profile.scss +9 -0
- data/assets/favicon/resume/about.txt +6 -0
- data/assets/favicon/resume/android-chrome-192x192.png +0 -0
- data/assets/favicon/resume/android-chrome-512x512.png +0 -0
- data/assets/favicon/resume/apple-touch-icon.png +0 -0
- data/assets/favicon/resume/favicon-16x16.png +0 -0
- data/assets/favicon/resume/favicon-32x32.png +0 -0
- data/assets/favicon/resume/favicon.ico +0 -0
- data/assets/favicon/resume/site.webmanifest +1 -0
- data/bin/validate-resume +89 -0
- data/bin/verify +27 -0
- data/docs/README.md +89 -0
- data/docs/explanation/accessibility-decisions.md +27 -0
- data/docs/explanation/architecture.md +44 -0
- data/docs/explanation/dark-mode-approach.md +25 -0
- data/docs/explanation/data-driven-model.md +25 -0
- data/docs/explanation/multilingual-and-rtl-design.md +40 -0
- data/docs/how-to/add-a-language.md +57 -0
- data/docs/how-to/add-a-section.md +35 -0
- data/docs/how-to/add-a-social-platform.md +32 -0
- data/docs/how-to/add-a-test.md +34 -0
- data/docs/how-to/create-a-custom-layout.md +64 -0
- data/docs/how-to/enable-dark-mode.md +43 -0
- data/docs/how-to/link-translations-with-hreflang.md +25 -0
- data/docs/how-to/migrate-v0.9-to-v1.0.md +46 -0
- data/docs/how-to/override-locale-strings.md +51 -0
- data/docs/how-to/override-sass-partials.md +26 -0
- data/docs/how-to/proof-built-html.md +22 -0
- data/docs/how-to/publish-json-resume.md +38 -0
- data/docs/how-to/show-language-proficiency-in-header.md +13 -0
- data/docs/how-to/switch-resume-versions.md +42 -0
- data/docs/how-to/troubleshoot-builds.md +39 -0
- data/docs/how-to/validate-in-ci.md +38 -0
- data/docs/how-to/verify-accessibility.md +28 -0
- data/docs/reference/accessibility-coverage.md +39 -0
- data/docs/reference/config.md +378 -0
- data/docs/reference/data-schemas.md +529 -0
- data/docs/reference/glossary.md +39 -0
- data/docs/reference/includes.md +197 -0
- data/docs/reference/json-resume-fields.md +148 -0
- data/docs/reference/layouts.md +144 -0
- data/docs/reference/locale-keys.md +76 -0
- data/docs/reference/repository-map.md +83 -0
- data/docs/reference/sass-tokens.md +279 -0
- data/docs/reference/testing-suites.md +62 -0
- data/docs/reference/validator-cli.md +203 -0
- data/docs/tutorials/getting-started.md +173 -0
- data/lib/jekyll-theme-resume/json_resume_exporter.rb +334 -0
- data/lib/jekyll-theme-resume/resume_validator.rb +853 -0
- data/lib/jekyll-theme-resume/schemas/LICENSE.md +21 -0
- data/lib/jekyll-theme-resume/schemas/json_resume_v1.0.0.json +500 -0
- data/lib/jekyll-theme-resume.rb +21 -0
- metadata +371 -0
|
@@ -0,0 +1,387 @@
|
|
|
1
|
+
// ==========================================================================
|
|
2
|
+
// Dark Mode System Tokens & Overrides
|
|
3
|
+
// jekyll-theme-resume
|
|
4
|
+
//
|
|
5
|
+
// Single source of truth for design tokens, color variables, and dark mode mechanics.
|
|
6
|
+
// Defines CSS Custom Properties on :root for light mode, system dark mode auto-detection,
|
|
7
|
+
// forced user preference overrides, paper-friendly print resets, and floating toggle UI.
|
|
8
|
+
// All tokens satisfy WCAG 2.2 AA contrast requirements (minimum 4.5:1 for normal text).
|
|
9
|
+
// ==========================================================================
|
|
10
|
+
|
|
11
|
+
:root {
|
|
12
|
+
// Informs the browser engine that the document supports both color schemes,
|
|
13
|
+
// enabling native dark styling on system scrollbars and form controls.
|
|
14
|
+
color-scheme: light dark;
|
|
15
|
+
|
|
16
|
+
// --- Background & Primary Typography ---
|
|
17
|
+
// Baseline light mode values: #333 on #ffffff yields a 12.6:1 contrast ratio (exceeds WCAG AAA).
|
|
18
|
+
--bg-color: #ffffff;
|
|
19
|
+
--text-color: #333;
|
|
20
|
+
--text-muted: #999;
|
|
21
|
+
--text-light: #646464;
|
|
22
|
+
--border-color: #c7c7c7;
|
|
23
|
+
--card-bg: #efefef;
|
|
24
|
+
|
|
25
|
+
// --- Links & Navigation ---
|
|
26
|
+
--link-color: #333;
|
|
27
|
+
--link-hover: #9c9c9c;
|
|
28
|
+
--link-hover-color: var(--link-hover);
|
|
29
|
+
|
|
30
|
+
// --- Accent & Brand Colors ---
|
|
31
|
+
--accent-color: #3064a9;
|
|
32
|
+
--accent-contrast-text: #ffffff;
|
|
33
|
+
--accent-hover: #307EA9;
|
|
34
|
+
--accent-hover-color: var(--accent-hover);
|
|
35
|
+
--social-hover-color: var(--accent-hover);
|
|
36
|
+
--about-color: var(--text-light);
|
|
37
|
+
|
|
38
|
+
// --- Footer ---
|
|
39
|
+
--footer-text-color: var(--text-muted);
|
|
40
|
+
--footer-link-color: var(--link-color);
|
|
41
|
+
|
|
42
|
+
// --- Icons & Graphics ---
|
|
43
|
+
--icon-fill: #333;
|
|
44
|
+
--icon-fill-muted: #555555;
|
|
45
|
+
--icon-fill-dark: #000;
|
|
46
|
+
--icon-hover-fill: var(--icon-fill-dark);
|
|
47
|
+
--header-icon-fill: var(--icon-fill-dark);
|
|
48
|
+
|
|
49
|
+
// --- Buttons (.contact-button, .cv-button) ---
|
|
50
|
+
--button-bg: #efefef;
|
|
51
|
+
--button-text: #333;
|
|
52
|
+
--button-hover-bg: #333;
|
|
53
|
+
--button-hover-text: #fff;
|
|
54
|
+
|
|
55
|
+
// --- Text Selection ---
|
|
56
|
+
--selection-bg: rgba(51, 51, 51, .8);
|
|
57
|
+
--selection-color: #fff;
|
|
58
|
+
|
|
59
|
+
// --- Dark Mode Toggle Component Tokens ---
|
|
60
|
+
--toggle-btn-bg: transparent;
|
|
61
|
+
--toggle-btn-border: var(--border-color);
|
|
62
|
+
--toggle-btn-color: var(--text-color);
|
|
63
|
+
--toggle-btn-hover-bg: var(--button-bg);
|
|
64
|
+
--toggle-btn-focus-ring: var(--accent-color);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// --------------------------------------------------------------------------
|
|
68
|
+
// Automatic System Dark Mode (@media prefers-color-scheme)
|
|
69
|
+
// --------------------------------------------------------------------------
|
|
70
|
+
// Tier 1 Activation: Automatically detects host OS dark mode preference.
|
|
71
|
+
// The :not([data-color-scheme="light"]):not([data-theme="light"]) guard ensures
|
|
72
|
+
// this media query yields if the user has explicitly pinned light mode via the toggle button.
|
|
73
|
+
// Contrast ratios: #e0e0e0 on #121212 = 13.8:1; #888888 on #121212 = 5.3:1 (passes WCAG AA).
|
|
74
|
+
@media (prefers-color-scheme: dark) {
|
|
75
|
+
:root:not([data-color-scheme="light"]):not([data-theme="light"]) {
|
|
76
|
+
--bg-color: #121212;
|
|
77
|
+
--text-color: #e0e0e0;
|
|
78
|
+
--text-muted: #888888;
|
|
79
|
+
--text-light: #aaaaaa;
|
|
80
|
+
--border-color: #333333;
|
|
81
|
+
--card-bg: #1e1e1e;
|
|
82
|
+
|
|
83
|
+
--link-color: #e0e0e0;
|
|
84
|
+
--link-hover: #ffffff;
|
|
85
|
+
--link-hover-color: var(--link-hover);
|
|
86
|
+
|
|
87
|
+
--accent-color: #6ba4e8;
|
|
88
|
+
--accent-contrast-text: #121212;
|
|
89
|
+
--accent-hover: #8cbcf3;
|
|
90
|
+
--accent-hover-color: var(--accent-hover);
|
|
91
|
+
--social-hover-color: var(--accent-hover);
|
|
92
|
+
--about-color: var(--text-light);
|
|
93
|
+
|
|
94
|
+
--footer-text-color: var(--text-muted);
|
|
95
|
+
--footer-link-color: var(--link-color);
|
|
96
|
+
|
|
97
|
+
--icon-fill: #e0e0e0;
|
|
98
|
+
--icon-fill-muted: #888888;
|
|
99
|
+
--icon-fill-dark: #ffffff;
|
|
100
|
+
--icon-hover-fill: var(--icon-fill-dark);
|
|
101
|
+
--header-icon-fill: var(--icon-fill-dark);
|
|
102
|
+
|
|
103
|
+
--button-bg: #2a2a2a;
|
|
104
|
+
--button-text: #e0e0e0;
|
|
105
|
+
--button-hover-bg: #444444;
|
|
106
|
+
--button-hover-text: #ffffff;
|
|
107
|
+
|
|
108
|
+
--selection-bg: rgba(107, 164, 232, .5);
|
|
109
|
+
--selection-color: #ffffff;
|
|
110
|
+
|
|
111
|
+
--toggle-btn-border: var(--border-color);
|
|
112
|
+
--toggle-btn-color: var(--text-color);
|
|
113
|
+
--toggle-btn-hover-bg: var(--button-bg);
|
|
114
|
+
--toggle-btn-focus-ring: var(--accent-color);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// --------------------------------------------------------------------------
|
|
119
|
+
// Forced Dark Override (Pinned via toggle or explicit attribute)
|
|
120
|
+
// --------------------------------------------------------------------------
|
|
121
|
+
// Tier 2 Activation: Explicit user selection persisted in localStorage and set
|
|
122
|
+
// via data-theme="dark", data-color-scheme="dark", or class="dark".
|
|
123
|
+
:root[data-color-scheme="dark"],
|
|
124
|
+
:root[data-theme="dark"],
|
|
125
|
+
[data-color-scheme="dark"],
|
|
126
|
+
[data-theme="dark"],
|
|
127
|
+
html.dark {
|
|
128
|
+
color-scheme: dark;
|
|
129
|
+
--bg-color: #121212;
|
|
130
|
+
--text-color: #e0e0e0;
|
|
131
|
+
--text-muted: #888888;
|
|
132
|
+
--text-light: #aaaaaa;
|
|
133
|
+
--border-color: #333333;
|
|
134
|
+
--card-bg: #1e1e1e;
|
|
135
|
+
|
|
136
|
+
--link-color: #e0e0e0;
|
|
137
|
+
--link-hover: #ffffff;
|
|
138
|
+
--link-hover-color: var(--link-hover);
|
|
139
|
+
|
|
140
|
+
--accent-color: #6ba4e8;
|
|
141
|
+
--accent-contrast-text: #121212;
|
|
142
|
+
--accent-hover: #8cbcf3;
|
|
143
|
+
--accent-hover-color: var(--accent-hover);
|
|
144
|
+
--social-hover-color: var(--accent-hover);
|
|
145
|
+
--about-color: var(--text-light);
|
|
146
|
+
|
|
147
|
+
--footer-text-color: var(--text-muted);
|
|
148
|
+
--footer-link-color: var(--link-color);
|
|
149
|
+
|
|
150
|
+
--icon-fill: #e0e0e0;
|
|
151
|
+
--icon-fill-muted: #888888;
|
|
152
|
+
--icon-fill-dark: #ffffff;
|
|
153
|
+
--icon-hover-fill: var(--icon-fill-dark);
|
|
154
|
+
--header-icon-fill: var(--icon-fill-dark);
|
|
155
|
+
|
|
156
|
+
--button-bg: #2a2a2a;
|
|
157
|
+
--button-text: #e0e0e0;
|
|
158
|
+
--button-hover-bg: #444444;
|
|
159
|
+
--button-hover-text: #ffffff;
|
|
160
|
+
|
|
161
|
+
--selection-bg: rgba(107, 164, 232, .5);
|
|
162
|
+
--selection-color: #ffffff;
|
|
163
|
+
|
|
164
|
+
--toggle-btn-border: var(--border-color);
|
|
165
|
+
--toggle-btn-color: var(--text-color);
|
|
166
|
+
--toggle-btn-hover-bg: var(--button-bg);
|
|
167
|
+
--toggle-btn-focus-ring: var(--accent-color);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// --------------------------------------------------------------------------
|
|
171
|
+
// Forced Light Override (Pinned via toggle on dark OS)
|
|
172
|
+
// --------------------------------------------------------------------------
|
|
173
|
+
// Overrides dark host OS settings when the user manually toggles the site to light mode.
|
|
174
|
+
:root[data-color-scheme="light"],
|
|
175
|
+
:root[data-theme="light"],
|
|
176
|
+
[data-color-scheme="light"],
|
|
177
|
+
[data-theme="light"],
|
|
178
|
+
html.light {
|
|
179
|
+
color-scheme: light;
|
|
180
|
+
--bg-color: #ffffff;
|
|
181
|
+
--text-color: #333;
|
|
182
|
+
--text-muted: #999;
|
|
183
|
+
--text-light: #646464;
|
|
184
|
+
--border-color: #c7c7c7;
|
|
185
|
+
--card-bg: #efefef;
|
|
186
|
+
|
|
187
|
+
--link-color: #333;
|
|
188
|
+
--link-hover: #9c9c9c;
|
|
189
|
+
--link-hover-color: var(--link-hover);
|
|
190
|
+
|
|
191
|
+
--accent-color: #3064a9;
|
|
192
|
+
--accent-hover: #307EA9;
|
|
193
|
+
--accent-hover-color: var(--accent-hover);
|
|
194
|
+
--social-hover-color: var(--accent-hover);
|
|
195
|
+
--about-color: var(--text-light);
|
|
196
|
+
|
|
197
|
+
--footer-text-color: var(--text-muted);
|
|
198
|
+
--footer-link-color: var(--link-color);
|
|
199
|
+
|
|
200
|
+
--icon-fill: #333;
|
|
201
|
+
--icon-fill-muted: #555555;
|
|
202
|
+
--icon-fill-dark: #000;
|
|
203
|
+
--icon-hover-fill: var(--icon-fill-dark);
|
|
204
|
+
--header-icon-fill: var(--icon-fill-dark);
|
|
205
|
+
|
|
206
|
+
--button-bg: #efefef;
|
|
207
|
+
--button-text: #333;
|
|
208
|
+
--button-hover-bg: #333;
|
|
209
|
+
--button-hover-text: #fff;
|
|
210
|
+
|
|
211
|
+
--selection-bg: rgba(51, 51, 51, .8);
|
|
212
|
+
--selection-color: #fff;
|
|
213
|
+
|
|
214
|
+
--toggle-btn-border: var(--border-color);
|
|
215
|
+
--toggle-btn-color: var(--text-color);
|
|
216
|
+
--toggle-btn-hover-bg: var(--button-bg);
|
|
217
|
+
--toggle-btn-focus-ring: var(--accent-color);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// --------------------------------------------------------------------------
|
|
221
|
+
// Print Media Override (Always clean light background for printing)
|
|
222
|
+
// --------------------------------------------------------------------------
|
|
223
|
+
// Forces paper-friendly styling during physical printing or PDF generation, regardless
|
|
224
|
+
// of whether the user was viewing the site in light or dark mode. Conserves printer ink
|
|
225
|
+
// and guarantees crisp black text on white paper.
|
|
226
|
+
@media print {
|
|
227
|
+
:root,
|
|
228
|
+
:root[data-color-scheme="dark"],
|
|
229
|
+
:root[data-color-scheme="light"],
|
|
230
|
+
:root[data-theme="dark"],
|
|
231
|
+
:root[data-theme="light"],
|
|
232
|
+
[data-color-scheme="dark"],
|
|
233
|
+
[data-theme="dark"],
|
|
234
|
+
html.dark,
|
|
235
|
+
html.light {
|
|
236
|
+
color-scheme: light !important;
|
|
237
|
+
--bg-color: #ffffff !important;
|
|
238
|
+
--text-color: #000000 !important;
|
|
239
|
+
--text-muted: #666 !important;
|
|
240
|
+
--text-light: #444 !important;
|
|
241
|
+
--border-color: #c7c7c7 !important;
|
|
242
|
+
--card-bg: #fff !important;
|
|
243
|
+
|
|
244
|
+
--link-color: #000 !important;
|
|
245
|
+
--link-hover: #000 !important;
|
|
246
|
+
--link-hover-color: #000 !important;
|
|
247
|
+
|
|
248
|
+
--accent-color: #000 !important;
|
|
249
|
+
--accent-hover: #000 !important;
|
|
250
|
+
--accent-hover-color: #000 !important;
|
|
251
|
+
--social-hover-color: #000 !important;
|
|
252
|
+
--about-color: #444 !important;
|
|
253
|
+
|
|
254
|
+
--footer-text-color: #666 !important;
|
|
255
|
+
--footer-link-color: #000 !important;
|
|
256
|
+
|
|
257
|
+
--icon-fill: #000 !important;
|
|
258
|
+
--icon-fill-muted: #666 !important;
|
|
259
|
+
--icon-fill-dark: #000 !important;
|
|
260
|
+
--icon-hover-fill: #000 !important;
|
|
261
|
+
--header-icon-fill: #000 !important;
|
|
262
|
+
|
|
263
|
+
--button-bg: #fff !important;
|
|
264
|
+
--button-text: #000 !important;
|
|
265
|
+
--button-hover-bg: #fff !important;
|
|
266
|
+
--button-hover-text: #000 !important;
|
|
267
|
+
|
|
268
|
+
--selection-bg: transparent !important;
|
|
269
|
+
--selection-color: #000 !important;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
html,
|
|
273
|
+
body {
|
|
274
|
+
background-color: #fff !important;
|
|
275
|
+
color: #000 !important;
|
|
276
|
+
-webkit-print-color-adjust: exact;
|
|
277
|
+
print-color-adjust: exact;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
// The interactive toggle button is omitted from printed output.
|
|
281
|
+
.dark-mode-toggle,
|
|
282
|
+
#dark-mode-toggle {
|
|
283
|
+
display: none !important;
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
// --------------------------------------------------------------------------
|
|
288
|
+
// Toggle Button Component Styling
|
|
289
|
+
// --------------------------------------------------------------------------
|
|
290
|
+
// Floating circular action button fixed to the top-right viewport corner.
|
|
291
|
+
.dark-mode-toggle {
|
|
292
|
+
position: fixed;
|
|
293
|
+
top: 1.25rem;
|
|
294
|
+
right: 1.25rem;
|
|
295
|
+
z-index: 1000;
|
|
296
|
+
display: inline-flex;
|
|
297
|
+
align-items: center;
|
|
298
|
+
justify-content: center;
|
|
299
|
+
width: 2.5rem;
|
|
300
|
+
height: 2.5rem;
|
|
301
|
+
padding: 0;
|
|
302
|
+
background: var(--bg-color);
|
|
303
|
+
color: var(--toggle-btn-color);
|
|
304
|
+
border: 1px solid var(--toggle-btn-border);
|
|
305
|
+
border-radius: 50%;
|
|
306
|
+
cursor: pointer;
|
|
307
|
+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
|
308
|
+
transition: background-color 0.2s ease, border-color 0.2s ease, transform 0.2s ease;
|
|
309
|
+
|
|
310
|
+
&:hover {
|
|
311
|
+
background-color: var(--toggle-btn-hover-bg);
|
|
312
|
+
transform: scale(1.05);
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
// Accessible keyboard focus ring (WCAG 2.2 Level AA).
|
|
316
|
+
&:focus-visible {
|
|
317
|
+
outline: 2px solid var(--toggle-btn-focus-ring);
|
|
318
|
+
outline-offset: 2px;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
.dark-mode-icon {
|
|
322
|
+
width: 1.25rem;
|
|
323
|
+
height: 1.25rem;
|
|
324
|
+
fill: none !important;
|
|
325
|
+
stroke: currentColor;
|
|
326
|
+
transition: transform 0.3s ease;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
// Baseline Light Mode: Show Moon, Hide Sun
|
|
330
|
+
// Pure CSS state machine: in light mode, shows the Moon icon prompting switch to dark.
|
|
331
|
+
.dark-mode-icon-sun {
|
|
332
|
+
display: none;
|
|
333
|
+
}
|
|
334
|
+
.dark-mode-icon-moon {
|
|
335
|
+
display: block;
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
// Media Query System Dark Mode (when not overridden to Light)
|
|
340
|
+
// Shows Sun icon prompting switch to light mode when operating under system dark mode.
|
|
341
|
+
@media (prefers-color-scheme: dark) {
|
|
342
|
+
:root:not([data-color-scheme="light"]):not([data-theme="light"]) {
|
|
343
|
+
.dark-mode-toggle {
|
|
344
|
+
.dark-mode-icon-sun {
|
|
345
|
+
display: block;
|
|
346
|
+
}
|
|
347
|
+
.dark-mode-icon-moon {
|
|
348
|
+
display: none;
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
// Pinned Dark Override: Show Sun, Hide Moon
|
|
355
|
+
// Displays Sun icon when dark mode is explicitly pinned.
|
|
356
|
+
:root[data-color-scheme="dark"],
|
|
357
|
+
:root[data-theme="dark"],
|
|
358
|
+
[data-color-scheme="dark"],
|
|
359
|
+
[data-theme="dark"],
|
|
360
|
+
html.dark {
|
|
361
|
+
.dark-mode-toggle {
|
|
362
|
+
.dark-mode-icon-sun {
|
|
363
|
+
display: block;
|
|
364
|
+
}
|
|
365
|
+
.dark-mode-icon-moon {
|
|
366
|
+
display: none;
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
// Pinned Light Override: Show Moon, Hide Sun
|
|
372
|
+
// Displays Moon icon when light mode is explicitly pinned.
|
|
373
|
+
:root[data-color-scheme="light"],
|
|
374
|
+
:root[data-theme="light"],
|
|
375
|
+
[data-color-scheme="light"],
|
|
376
|
+
[data-theme="light"],
|
|
377
|
+
html.light {
|
|
378
|
+
.dark-mode-toggle {
|
|
379
|
+
.dark-mode-icon-sun {
|
|
380
|
+
display: none;
|
|
381
|
+
}
|
|
382
|
+
.dark-mode-icon-moon {
|
|
383
|
+
display: block;
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
|
data/_sass/_layout.scss
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
// Layout styles
|
|
2
|
+
// ---------------------------------------/
|
|
3
|
+
// jekyll-theme-resume
|
|
4
|
+
// Floating language switcher component. (The Primer-derived grid system formerly
|
|
5
|
+
// here - .container, .columns, .one-third, etc. - was removed: zero usages in this
|
|
6
|
+
// theme's own layouts/includes or the demo site. See docs/COMPLETED_AUDIT.md.)
|
|
7
|
+
// ---------------------------------------/
|
|
8
|
+
|
|
9
|
+
// --------------------------------------------------------------------------
|
|
10
|
+
// Language Switcher Component (Feature 1.2; dropdown redesign Feature 2.12)
|
|
11
|
+
// --------------------------------------------------------------------------
|
|
12
|
+
// <details>/<summary> disclosure fixed to the top-left viewport corner.
|
|
13
|
+
// The trigger (.language-switcher-trigger) mirrors the visual language of
|
|
14
|
+
// .dark-mode-toggle (same pill shape, shadow, and transition); the opened
|
|
15
|
+
// panel (.language-switcher-panel) lists every other configured language.
|
|
16
|
+
// --------------------------------------------------------------------------
|
|
17
|
+
|
|
18
|
+
.language-switcher {
|
|
19
|
+
position: fixed;
|
|
20
|
+
top: 1.25rem;
|
|
21
|
+
left: 1.25rem;
|
|
22
|
+
z-index: 1000;
|
|
23
|
+
|
|
24
|
+
// <summary> gets a default disclosure marker in most browsers; suppress it since the
|
|
25
|
+
// trigger already renders its own icon + label.
|
|
26
|
+
.language-switcher-trigger {
|
|
27
|
+
display: inline-flex;
|
|
28
|
+
align-items: center;
|
|
29
|
+
justify-content: center;
|
|
30
|
+
gap: 0.35rem;
|
|
31
|
+
height: 2.5rem;
|
|
32
|
+
padding: 0 0.85rem;
|
|
33
|
+
background: var(--bg-color, #ffffff);
|
|
34
|
+
color: var(--text-color, #333333);
|
|
35
|
+
border: 1px solid var(--toggle-btn-border, #e0e0e0);
|
|
36
|
+
border-radius: 9999px;
|
|
37
|
+
cursor: pointer;
|
|
38
|
+
list-style: none;
|
|
39
|
+
text-decoration: none;
|
|
40
|
+
font-size: 0.85rem;
|
|
41
|
+
font-weight: 700;
|
|
42
|
+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
|
43
|
+
transition: background-color 0.2s ease, border-color 0.2s ease, transform 0.2s ease;
|
|
44
|
+
|
|
45
|
+
&::-webkit-details-marker {
|
|
46
|
+
display: none;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
&:hover {
|
|
50
|
+
background-color: var(--toggle-btn-hover-bg, #f5f5f5);
|
|
51
|
+
border-color: var(--accent-color, #007acc);
|
|
52
|
+
transform: scale(1.05);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
&:focus-visible {
|
|
56
|
+
outline: 2px solid var(--accent-color, #007acc);
|
|
57
|
+
outline-offset: 2px;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
&[open] .language-switcher-trigger {
|
|
62
|
+
border-color: var(--accent-color, #007acc);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
.language-switcher-panel {
|
|
66
|
+
display: flex;
|
|
67
|
+
flex-direction: column;
|
|
68
|
+
gap: 0.25rem;
|
|
69
|
+
min-width: 10rem;
|
|
70
|
+
margin-top: 0.5rem;
|
|
71
|
+
padding: 0.5rem;
|
|
72
|
+
background: var(--bg-color, #ffffff);
|
|
73
|
+
border: 1px solid var(--toggle-btn-border, #e0e0e0);
|
|
74
|
+
border-radius: 0.75rem;
|
|
75
|
+
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
.lang-switch-btn {
|
|
79
|
+
display: inline-flex;
|
|
80
|
+
align-items: center;
|
|
81
|
+
gap: 0.5rem;
|
|
82
|
+
padding: 0.5rem 0.75rem;
|
|
83
|
+
color: var(--text-color, #333333);
|
|
84
|
+
text-decoration: none;
|
|
85
|
+
font-size: 0.85rem;
|
|
86
|
+
font-weight: 600;
|
|
87
|
+
border-radius: 0.5rem;
|
|
88
|
+
transition: background-color 0.2s ease;
|
|
89
|
+
|
|
90
|
+
&:hover {
|
|
91
|
+
background-color: var(--toggle-btn-hover-bg, #f5f5f5);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
&:focus-visible {
|
|
95
|
+
outline: 2px solid var(--accent-color, #007acc);
|
|
96
|
+
outline-offset: 2px;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
.lang-icon {
|
|
101
|
+
font-size: 1rem;
|
|
102
|
+
line-height: 1;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
.lang-label-target {
|
|
106
|
+
font-family: 'Inter', 'Cairo', sans-serif;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Print: explicit safety net — .no-print on the element already handles most cases
|
|
111
|
+
@media print {
|
|
112
|
+
.language-switcher {
|
|
113
|
+
display: none !important;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
data/_sass/_mixins.scss
ADDED
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
// Mixins
|
|
2
|
+
// ---------------------------------------/
|
|
3
|
+
// jekyll-theme-resume
|
|
4
|
+
// Reusable SASS mixins for cross-browser vendor prefixing, micro-clearfix,
|
|
5
|
+
// responsive breakpoint queries, font stack utilities, and section divider borders.
|
|
6
|
+
// ---------------------------------------/
|
|
7
|
+
|
|
8
|
+
// Clearfix
|
|
9
|
+
//
|
|
10
|
+
// Clears floats via mixin (avoid using as a class).
|
|
11
|
+
// Generates pseudo-elements before and after to contain floated children without overflow hacks.
|
|
12
|
+
@mixin clearfix {
|
|
13
|
+
&:before {
|
|
14
|
+
display: table;
|
|
15
|
+
content: "";
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
&:after {
|
|
19
|
+
display: table;
|
|
20
|
+
clear: both;
|
|
21
|
+
content: "";
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// media querie tools
|
|
26
|
+
// Responsive viewport breakpoint mixins. Standard mobile threshold is 600px.
|
|
27
|
+
|
|
28
|
+
// Custom maximum-width media query.
|
|
29
|
+
@mixin media_max($screen_width) {
|
|
30
|
+
@media (max-width: $screen_width) {
|
|
31
|
+
@content;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Custom minimum-width media query.
|
|
36
|
+
@mixin media_min($screen_width) {
|
|
37
|
+
@media (min-width: $screen_width) {
|
|
38
|
+
@content;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Desktop & tablet viewports (600px and wider).
|
|
43
|
+
@mixin media_larger_than_mobile {
|
|
44
|
+
@media (min-width: 600px) {
|
|
45
|
+
@content;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Mobile viewports (600px and narrower).
|
|
50
|
+
@mixin media_mobile {
|
|
51
|
+
@media (max-width: 600px) {
|
|
52
|
+
@content;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// type utilities
|
|
57
|
+
// Typography mixins: standardizes font families and weights across sections.
|
|
58
|
+
|
|
59
|
+
// Primary sans-serif stack (Open Sans).
|
|
60
|
+
@mixin sans {
|
|
61
|
+
font-family: "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
@mixin sans_light {
|
|
65
|
+
@include sans;
|
|
66
|
+
font-weight: 300;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
@mixin sans_regular {
|
|
70
|
+
@include sans;
|
|
71
|
+
font-weight: 400;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
@mixin sans_bold {
|
|
75
|
+
@include sans;
|
|
76
|
+
font-weight: 700;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
@mixin sans_extrabold {
|
|
80
|
+
@include sans;
|
|
81
|
+
font-weight: 800;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Editorial serif stack (Lora).
|
|
85
|
+
@mixin serif {
|
|
86
|
+
font-family: "Lora", "Minion Pro", Palatino, Georgia, serif;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
@mixin serif_regular {
|
|
90
|
+
@include serif;
|
|
91
|
+
font-weight: 400;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
@mixin serif_bold {
|
|
95
|
+
@include serif;
|
|
96
|
+
font-weight: 700;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// layout
|
|
100
|
+
// Section divider border helpers using theme CSS custom property tokens.
|
|
101
|
+
|
|
102
|
+
// Standard section divider: double-line border (4px top, 2px bottom).
|
|
103
|
+
@mixin section_border {
|
|
104
|
+
border-top: 4px solid var(--border-color, #c7c7c7);
|
|
105
|
+
border-bottom: 2px solid var(--border-color, #c7c7c7);
|
|
106
|
+
padding: .2rem 0 .4rem;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Compact hairline border for print media (1px top, 1px bottom).
|
|
110
|
+
@mixin section_border_thin {
|
|
111
|
+
border-top: 1px solid var(--border-color, #c7c7c7);
|
|
112
|
+
border-bottom: 1px solid var(--border-color, #c7c7c7);
|
|
113
|
+
padding: .2rem 0 .2rem;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// buttons
|
|
117
|
+
// Shared pill-button skin for .contact-button (resume) and .cv-button (profile page).
|
|
118
|
+
// Callers add their own font-family/font-weight and width modifiers on top.
|
|
119
|
+
@mixin cv-button-base {
|
|
120
|
+
border-radius: 3px;
|
|
121
|
+
background-color: var(--button-bg, #efefef);
|
|
122
|
+
text-decoration: none;
|
|
123
|
+
text-align: center;
|
|
124
|
+
display: block;
|
|
125
|
+
margin: 1.5rem auto;
|
|
126
|
+
width: 220px;
|
|
127
|
+
font-size: 1.375rem;
|
|
128
|
+
color: var(--button-text, #333);
|
|
129
|
+
line-height: 55px;
|
|
130
|
+
transition: all .2s ease;
|
|
131
|
+
|
|
132
|
+
&:hover {
|
|
133
|
+
background-color: var(--button-hover-bg, #333);
|
|
134
|
+
color: var(--button-hover-text, #fff);
|
|
135
|
+
}
|
|
136
|
+
}
|