@jsonresume/jsonresume-theme-tokyo-modernist 1.0.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.
package/.eslintrc.js ADDED
@@ -0,0 +1,8 @@
1
+ /* eslint-disable */
2
+
3
+ module.exports = {
4
+ root: true,
5
+ extends: ['@repo/eslint-config-custom'],
6
+ parser: '@typescript-eslint/parser',
7
+ rules: {},
8
+ };
package/README.md ADDED
@@ -0,0 +1,92 @@
1
+ # Tokyo Modernist Resume Theme
2
+
3
+ A minimal futuristic JSON Resume theme combining geometric precision with expressive typography. Built on an 8pt grid system with clean lines, strong hierarchies, and restrained asymmetry.
4
+
5
+ ## Design Philosophy
6
+
7
+ Tokyo Modernist balances creative tech sensibility with cultural precision. It looks at home in design studios and modern engineering firms alike, featuring:
8
+
9
+ - **Typography**: Outfit variable-width geometric sans serif
10
+ - **Color**: Deep magenta (#c71585) accents with subtle gray subheaders
11
+ - **Layout**: Vertical rhythm built on 8pt grid with tighter line spacing
12
+ - **Style**: Minimal futurism meets typographic focus
13
+
14
+ ## Key Features
15
+
16
+ - **Geometric Precision**: 8px grid-based spacing for perfect alignment
17
+ - **Bold Typography**: Strong uppercase headings with negative letter-spacing
18
+ - **Asymmetric Elements**: Strategic use of geometric shapes and gradients
19
+ - **Minimal Color**: Restrained use of deep magenta for maximum impact
20
+ - **Clean Hierarchy**: Clear visual distinction between heading levels
21
+ - **Print-Optimized**: Designed to look great on screen and paper
22
+
23
+ ## Design Details
24
+
25
+ ### Typography Scale
26
+ - **Name**: 56px, 800 weight, uppercase, -2px letter-spacing
27
+ - **Section Titles**: 32px, 800 weight, uppercase, -1px letter-spacing
28
+ - **Position**: 22px, 700 weight
29
+ - **Company**: 18px, 600 weight, magenta color
30
+ - **Body**: 16-17px, 1.7 line height
31
+
32
+ ### Color Palette
33
+ - **Primary Text**: #1a1d23 (near-black)
34
+ - **Accent**: #c71585 (deep magenta)
35
+ - **Subheader**: #6b7280 (gray)
36
+ - **Body Text**: #4b5563 (medium gray)
37
+ - **Meta Text**: #9ca3af (light gray)
38
+ - **Background**: #fafbfc (off-white)
39
+
40
+ ### Geometric Elements
41
+ - **8pt Grid**: All spacing in multiples of 8px (8, 16, 24, 32, 40, 48, 56)
42
+ - **Triangular Accents**: Clipped diagonal gradients in corners
43
+ - **Diamond Bullets**: Custom bullet points using clip-path
44
+ - **Gradient Bars**: Vertical gradient stripes in skill cards
45
+ - **Hover Effects**: Subtle color transitions and shadow reveals
46
+
47
+ ## Usage
48
+
49
+ Install the theme:
50
+
51
+ ```bash
52
+ npm install @jsonresume/jsonresume-theme-tokyo-modernist
53
+ ```
54
+
55
+ Use with JSON Resume CLI:
56
+
57
+ ```bash
58
+ resume export resume.html --theme tokyo-modernist
59
+ ```
60
+
61
+ Or specify in your resume.json:
62
+
63
+ ```json
64
+ {
65
+ "meta": {
66
+ "theme": "tokyo-modernist"
67
+ }
68
+ }
69
+ ```
70
+
71
+ ## Components Used
72
+
73
+ This theme leverages the @resume/core component library:
74
+
75
+ - **Section**: Semantic section wrapper
76
+ - **SectionTitle**: Heading component
77
+ - **DateRange**: Formatted date ranges with localization
78
+ - **ContactInfo**: Email, phone, location, profiles
79
+
80
+ ## Browser Support
81
+
82
+ - Modern evergreen browsers (Chrome, Firefox, Safari, Edge)
83
+ - Print-optimized for PDF generation
84
+ - Responsive design for mobile viewing
85
+
86
+ ## License
87
+
88
+ MIT
89
+
90
+ ## Credits
91
+
92
+ Created for jsonresume.org - the open source initiative to create a JSON-based standard for resumes.
package/package.json ADDED
@@ -0,0 +1,35 @@
1
+ {
2
+ "private": false,
3
+ "name": "@jsonresume/jsonresume-theme-tokyo-modernist",
4
+ "version": "1.0.0",
5
+ "main": "./src/index.js",
6
+ "license": "MIT",
7
+ "description": "Tokyo Modernist theme - Minimal futurism with geometric precision, built on 8pt grid with Outfit typography and deep magenta accents",
8
+ "keywords": [
9
+ "resume",
10
+ "json-resume",
11
+ "theme",
12
+ "modern",
13
+ "futuristic",
14
+ "geometric",
15
+ "minimalist",
16
+ "tokyo"
17
+ ],
18
+ "devDependencies": {
19
+ "react": "^19.2.0",
20
+ "styled-components": "^6.1.19",
21
+ "@repo/eslint-config-custom": "^0.0.0"
22
+ },
23
+ "peerDependencies": {
24
+ "styled-components": "^6"
25
+ },
26
+ "dependencies": {
27
+ "marked": "^16.3.0",
28
+ "prismjs": "^1.29.0",
29
+ "react-icons": "^5.0.1",
30
+ "@resume/core": "^0.1.0"
31
+ },
32
+ "scripts": {
33
+ "lint": "eslint src || exit 0"
34
+ }
35
+ }
package/src/index.js ADDED
@@ -0,0 +1,90 @@
1
+ import { renderToString } from 'react-dom/server';
2
+ import { ServerStyleSheet } from 'styled-components';
3
+ import Resume from './ui/Resume';
4
+
5
+ export const render = (resume) => {
6
+ const sheet = new ServerStyleSheet();
7
+ const html = renderToString(sheet.collectStyles(<Resume resume={resume} />));
8
+ const styles = sheet.getStyleTags();
9
+ return `<!DOCTYPE html><head>
10
+ <title>${resume.basics.name} - Resume</title>
11
+ <meta charset="utf-8">
12
+ <meta name="viewport" content="width=device-width, initial-scale=1"/>
13
+ <link rel="preconnect" href="https://fonts.googleapis.com">
14
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
15
+ <link href="https://fonts.googleapis.com/css2?family=Outfit:wght@400;500;600;700;800&display=swap" rel="stylesheet">
16
+ <style>
17
+ html {
18
+ font-family: 'Outfit', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
19
+ background: #fafbfc;
20
+ font-size: 16px;
21
+ color: #1a1d23;
22
+ }
23
+
24
+ body {
25
+ margin: 0;
26
+ padding: 0;
27
+ }
28
+
29
+ h1, h2, h3, h4, h5, h6 {
30
+ font-family: 'Outfit', sans-serif;
31
+ margin: 0;
32
+ padding: 0;
33
+ }
34
+
35
+ h2 {
36
+ font-size: 2rem;
37
+ font-weight: 800;
38
+ color: #1a1d23;
39
+ margin-bottom: 1rem;
40
+ }
41
+
42
+ h3 {
43
+ font-size: 1.375rem;
44
+ font-weight: 700;
45
+ color: #1a1d23;
46
+ }
47
+
48
+ p {
49
+ padding: 0;
50
+ margin: 0;
51
+ line-height: 1.7;
52
+ }
53
+
54
+ p, li {
55
+ font-size: 1rem;
56
+ line-height: 1.7;
57
+ }
58
+
59
+ a {
60
+ color: #c71585;
61
+ text-decoration: none;
62
+ transition: color 0.2s ease;
63
+ }
64
+
65
+ a:hover {
66
+ color: #a0115f;
67
+ }
68
+
69
+ ul {
70
+ list-style: none;
71
+ margin: 0;
72
+ padding: 0;
73
+ }
74
+
75
+ *,
76
+ *::before,
77
+ *::after {
78
+ box-sizing: border-box;
79
+ }
80
+
81
+ @media print {
82
+ html {
83
+ background: white;
84
+ }
85
+ }
86
+ </style>
87
+ ${styles}</head><body>${html}</body></html>`;
88
+ };
89
+
90
+ export { Resume };
@@ -0,0 +1,248 @@
1
+ import React from 'react';
2
+ import { Section, DateRange } from '@resume/core';
3
+ import {
4
+ Layout,
5
+ Header,
6
+ Name,
7
+ Label,
8
+ StyledContactInfo,
9
+ Summary,
10
+ StyledSectionTitle,
11
+ WorkItem,
12
+ WorkHeader,
13
+ Position,
14
+ Company,
15
+ DateText,
16
+ WorkSummary,
17
+ Highlights,
18
+ EducationItem,
19
+ Institution,
20
+ Degree,
21
+ EducationDate,
22
+ SkillsGrid,
23
+ SkillCategory,
24
+ SkillName,
25
+ SkillTags,
26
+ ProjectItem,
27
+ } from './styles';
28
+
29
+ // Tokyo Modernist Theme - Minimal futurism with typographic focus
30
+ // Built on 8pt grid system with geometric precision
31
+ // Outfit variable-width geometric sans from Google Fonts
32
+ // Deep magenta accent (#c71585) with subtle gray subheaders
33
+ // Strong headings, clean geometry, restrained asymmetry
34
+
35
+ function Resume({ resume }) {
36
+ const {
37
+ basics = {},
38
+ work = [],
39
+ education = [],
40
+ skills = [],
41
+ projects = [],
42
+ volunteer = [],
43
+ awards = [],
44
+ publications = [],
45
+ languages = [],
46
+ interests = [],
47
+ references = [],
48
+ } = resume;
49
+
50
+ return (
51
+ <Layout>
52
+ <Header>
53
+ {basics.name && <Name>{basics.name}</Name>}
54
+ {basics.label && <Label>{basics.label}</Label>}
55
+ <StyledContactInfo basics={basics} />
56
+ {basics.summary && <Summary>{basics.summary}</Summary>}
57
+ </Header>
58
+
59
+ {work?.length > 0 && (
60
+ <Section>
61
+ <StyledSectionTitle>Experience</StyledSectionTitle>
62
+ {work.map((job, index) => (
63
+ <WorkItem key={index}>
64
+ <WorkHeader>
65
+ <div>
66
+ <Position>{job.position}</Position>
67
+ {job.name && <Company>{job.name}</Company>}
68
+ </div>
69
+ <DateText>
70
+ <DateRange startDate={job.startDate} endDate={job.endDate} />
71
+ </DateText>
72
+ </WorkHeader>
73
+ {job.summary && <WorkSummary>{job.summary}</WorkSummary>}
74
+ {job.highlights?.length > 0 && (
75
+ <Highlights>
76
+ {job.highlights.map((highlight, i) => (
77
+ <li key={i}>{highlight}</li>
78
+ ))}
79
+ </Highlights>
80
+ )}
81
+ </WorkItem>
82
+ ))}
83
+ </Section>
84
+ )}
85
+
86
+ {skills?.length > 0 && (
87
+ <Section>
88
+ <StyledSectionTitle>Skills</StyledSectionTitle>
89
+ <SkillsGrid>
90
+ {skills.map((skill, index) => (
91
+ <SkillCategory key={index}>
92
+ <SkillName>{skill.name}</SkillName>
93
+ {skill.keywords?.length > 0 && (
94
+ <SkillTags>{skill.keywords.join(' • ')}</SkillTags>
95
+ )}
96
+ </SkillCategory>
97
+ ))}
98
+ </SkillsGrid>
99
+ </Section>
100
+ )}
101
+
102
+ {education?.length > 0 && (
103
+ <Section>
104
+ <StyledSectionTitle>Education</StyledSectionTitle>
105
+ {education.map((edu, index) => (
106
+ <EducationItem key={index}>
107
+ <Institution>{edu.institution}</Institution>
108
+ <Degree>
109
+ {edu.studyType} in {edu.area}
110
+ {edu.score && ` • ${edu.score}`}
111
+ </Degree>
112
+ <EducationDate>
113
+ <DateRange startDate={edu.startDate} endDate={edu.endDate} />
114
+ </EducationDate>
115
+ </EducationItem>
116
+ ))}
117
+ </Section>
118
+ )}
119
+
120
+ {projects?.length > 0 && (
121
+ <Section>
122
+ <StyledSectionTitle>Projects</StyledSectionTitle>
123
+ {projects.map((project, index) => (
124
+ <ProjectItem key={index}>
125
+ <Position>{project.name}</Position>
126
+ {project.description && (
127
+ <WorkSummary>{project.description}</WorkSummary>
128
+ )}
129
+ {project.highlights?.length > 0 && (
130
+ <Highlights>
131
+ {project.highlights.map((highlight, i) => (
132
+ <li key={i}>{highlight}</li>
133
+ ))}
134
+ </Highlights>
135
+ )}
136
+ </ProjectItem>
137
+ ))}
138
+ </Section>
139
+ )}
140
+
141
+ {volunteer?.length > 0 && (
142
+ <Section>
143
+ <StyledSectionTitle>Volunteer</StyledSectionTitle>
144
+ {volunteer.map((vol, index) => (
145
+ <WorkItem key={index}>
146
+ <WorkHeader>
147
+ <div>
148
+ <Position>{vol.position}</Position>
149
+ {vol.organization && <Company>{vol.organization}</Company>}
150
+ </div>
151
+ {(vol.startDate || vol.endDate) && (
152
+ <DateText>
153
+ <DateRange
154
+ startDate={vol.startDate}
155
+ endDate={vol.endDate}
156
+ />
157
+ </DateText>
158
+ )}
159
+ </WorkHeader>
160
+ {vol.summary && <WorkSummary>{vol.summary}</WorkSummary>}
161
+ {vol.highlights?.length > 0 && (
162
+ <Highlights>
163
+ {vol.highlights.map((highlight, i) => (
164
+ <li key={i}>{highlight}</li>
165
+ ))}
166
+ </Highlights>
167
+ )}
168
+ </WorkItem>
169
+ ))}
170
+ </Section>
171
+ )}
172
+
173
+ {awards?.length > 0 && (
174
+ <Section>
175
+ <StyledSectionTitle>Awards</StyledSectionTitle>
176
+ {awards.map((award, index) => (
177
+ <EducationItem key={index}>
178
+ <Institution>{award.title}</Institution>
179
+ {award.awarder && <Degree>Awarded by {award.awarder}</Degree>}
180
+ {award.date && <EducationDate>{award.date}</EducationDate>}
181
+ {award.summary && <WorkSummary>{award.summary}</WorkSummary>}
182
+ </EducationItem>
183
+ ))}
184
+ </Section>
185
+ )}
186
+
187
+ {publications?.length > 0 && (
188
+ <Section>
189
+ <StyledSectionTitle>Publications</StyledSectionTitle>
190
+ {publications.map((pub, index) => (
191
+ <EducationItem key={index}>
192
+ <Institution>{pub.name}</Institution>
193
+ {pub.publisher && <Degree>Published by {pub.publisher}</Degree>}
194
+ {pub.releaseDate && (
195
+ <EducationDate>{pub.releaseDate}</EducationDate>
196
+ )}
197
+ {pub.summary && <WorkSummary>{pub.summary}</WorkSummary>}
198
+ </EducationItem>
199
+ ))}
200
+ </Section>
201
+ )}
202
+
203
+ {languages?.length > 0 && (
204
+ <Section>
205
+ <StyledSectionTitle>Languages</StyledSectionTitle>
206
+ <SkillsGrid>
207
+ {languages.map((lang, index) => (
208
+ <SkillCategory key={index}>
209
+ <SkillName>{lang.language}</SkillName>
210
+ {lang.fluency && <SkillTags>{lang.fluency}</SkillTags>}
211
+ </SkillCategory>
212
+ ))}
213
+ </SkillsGrid>
214
+ </Section>
215
+ )}
216
+
217
+ {interests?.length > 0 && (
218
+ <Section>
219
+ <StyledSectionTitle>Interests</StyledSectionTitle>
220
+ <SkillsGrid>
221
+ {interests.map((interest, index) => (
222
+ <SkillCategory key={index}>
223
+ <SkillName>{interest.name}</SkillName>
224
+ {interest.keywords?.length > 0 && (
225
+ <SkillTags>{interest.keywords.join(' • ')}</SkillTags>
226
+ )}
227
+ </SkillCategory>
228
+ ))}
229
+ </SkillsGrid>
230
+ </Section>
231
+ )}
232
+
233
+ {references?.length > 0 && (
234
+ <Section>
235
+ <StyledSectionTitle>References</StyledSectionTitle>
236
+ {references.map((ref, index) => (
237
+ <EducationItem key={index}>
238
+ <Institution>{ref.name}</Institution>
239
+ {ref.reference && <WorkSummary>{ref.reference}</WorkSummary>}
240
+ </EducationItem>
241
+ ))}
242
+ </Section>
243
+ )}
244
+ </Layout>
245
+ );
246
+ }
247
+
248
+ export default Resume;
@@ -0,0 +1,323 @@
1
+ import styled from 'styled-components';
2
+ import { SectionTitle, ContactInfo } from '@resume/core';
3
+
4
+ export const Layout = styled.div`
5
+ max-width: 840px;
6
+ margin: 0 auto;
7
+ padding: 48px 40px;
8
+ background: #fafbfc;
9
+ font-family: 'Outfit', 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI',
10
+ sans-serif;
11
+ color: #1a1d23;
12
+ line-height: 1.6;
13
+
14
+ @media print {
15
+ padding: 40px;
16
+ background: white;
17
+ }
18
+ `;
19
+
20
+ export const Header = styled.header`
21
+ margin-bottom: 56px;
22
+ padding: 40px;
23
+ background: linear-gradient(
24
+ 135deg,
25
+ rgba(199, 21, 133, 0.03) 0%,
26
+ rgba(199, 21, 133, 0.01) 100%
27
+ );
28
+ border-left: 8px solid #c71585;
29
+ position: relative;
30
+
31
+ &:before {
32
+ content: '';
33
+ position: absolute;
34
+ top: 0;
35
+ right: 0;
36
+ width: 120px;
37
+ height: 120px;
38
+ background: linear-gradient(135deg, transparent 50%, #c71585 50%);
39
+ opacity: 0.08;
40
+ clip-path: polygon(100% 0, 100% 100%, 0 0);
41
+ }
42
+ `;
43
+
44
+ export const Name = styled.h1`
45
+ font-size: 56px;
46
+ font-weight: 800;
47
+ color: #1a1d23;
48
+ margin: 0 0 8px 0;
49
+ letter-spacing: -2px;
50
+ line-height: 1.1;
51
+ text-transform: uppercase;
52
+ font-variation-settings: 'wght' 800;
53
+ `;
54
+
55
+ export const Label = styled.div`
56
+ font-size: 20px;
57
+ color: #6b7280;
58
+ margin-bottom: 24px;
59
+ font-weight: 500;
60
+ letter-spacing: 0.5px;
61
+ text-transform: uppercase;
62
+ font-size: 14px;
63
+ `;
64
+
65
+ export const StyledContactInfo = styled(ContactInfo)`
66
+ font-size: 15px;
67
+ display: flex;
68
+ gap: 24px;
69
+ flex-wrap: wrap;
70
+
71
+ a {
72
+ font-size: 15px;
73
+ color: #c71585;
74
+ text-decoration: none;
75
+ font-weight: 600;
76
+ position: relative;
77
+ padding-bottom: 2px;
78
+
79
+ &:after {
80
+ content: '';
81
+ position: absolute;
82
+ bottom: 0;
83
+ left: 0;
84
+ width: 0;
85
+ height: 2px;
86
+ background: #c71585;
87
+ transition: width 0.3s ease;
88
+ }
89
+
90
+ &:hover:after {
91
+ width: 100%;
92
+ }
93
+ }
94
+ `;
95
+
96
+ export const Summary = styled.p`
97
+ font-size: 17px;
98
+ line-height: 1.7;
99
+ color: #4b5563;
100
+ margin: 24px 0 0 0;
101
+ max-width: 680px;
102
+ `;
103
+
104
+ export const StyledSectionTitle = styled(SectionTitle)`
105
+ font-size: 32px;
106
+ font-weight: 800;
107
+ color: #1a1d23;
108
+ margin: 48px 0 32px 0;
109
+ padding-bottom: 16px;
110
+ border-bottom: 3px solid #c71585;
111
+ position: relative;
112
+ text-transform: uppercase;
113
+ letter-spacing: -1px;
114
+ display: inline-block;
115
+ min-width: 280px;
116
+
117
+ &:after {
118
+ content: '';
119
+ position: absolute;
120
+ bottom: -3px;
121
+ right: -40px;
122
+ width: 32px;
123
+ height: 3px;
124
+ background: #e5e7eb;
125
+ }
126
+ `;
127
+
128
+ export const WorkItem = styled.div`
129
+ margin-bottom: 40px;
130
+ padding: 32px;
131
+ background: white;
132
+ border-left: 4px solid #e5e7eb;
133
+ position: relative;
134
+ transition: all 0.3s ease;
135
+
136
+ &:hover {
137
+ border-left-color: #c71585;
138
+ box-shadow: -4px 0 0 0 rgba(199, 21, 133, 0.1);
139
+ }
140
+
141
+ &:before {
142
+ content: '';
143
+ position: absolute;
144
+ top: 32px;
145
+ left: -8px;
146
+ width: 8px;
147
+ height: 8px;
148
+ background: #c71585;
149
+ clip-path: polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%);
150
+ }
151
+
152
+ &:last-child {
153
+ margin-bottom: 0;
154
+ }
155
+ `;
156
+
157
+ export const WorkHeader = styled.div`
158
+ display: grid;
159
+ grid-template-columns: 1fr auto;
160
+ align-items: start;
161
+ margin-bottom: 16px;
162
+ gap: 24px;
163
+
164
+ @media (max-width: 640px) {
165
+ grid-template-columns: 1fr;
166
+ gap: 8px;
167
+ }
168
+ `;
169
+
170
+ export const Position = styled.h3`
171
+ font-size: 22px;
172
+ font-weight: 700;
173
+ color: #1a1d23;
174
+ margin: 0;
175
+ letter-spacing: -0.5px;
176
+ `;
177
+
178
+ export const Company = styled.div`
179
+ font-size: 18px;
180
+ color: #c71585;
181
+ font-weight: 600;
182
+ margin-top: 4px;
183
+ letter-spacing: 0.2px;
184
+ `;
185
+
186
+ export const DateText = styled.div`
187
+ font-size: 13px;
188
+ color: #9ca3af;
189
+ font-weight: 600;
190
+ white-space: nowrap;
191
+ text-transform: uppercase;
192
+ letter-spacing: 0.5px;
193
+ text-align: right;
194
+
195
+ @media (max-width: 640px) {
196
+ text-align: left;
197
+ }
198
+ `;
199
+
200
+ export const WorkSummary = styled.p`
201
+ margin: 16px 0;
202
+ color: #4b5563;
203
+ line-height: 1.7;
204
+ font-size: 16px;
205
+ `;
206
+
207
+ export const Highlights = styled.ul`
208
+ margin: 16px 0 0 0;
209
+ padding: 0;
210
+ list-style-type: none;
211
+ display: grid;
212
+ gap: 12px;
213
+
214
+ li {
215
+ color: #4b5563;
216
+ line-height: 1.7;
217
+ font-size: 15px;
218
+ padding-left: 24px;
219
+ position: relative;
220
+
221
+ &:before {
222
+ content: '';
223
+ position: absolute;
224
+ left: 0;
225
+ top: 10px;
226
+ width: 12px;
227
+ height: 2px;
228
+ background: #c71585;
229
+ }
230
+ }
231
+ `;
232
+
233
+ export const EducationItem = styled.div`
234
+ margin-bottom: 32px;
235
+ padding: 24px 32px;
236
+ background: white;
237
+ border-top: 2px solid #e5e7eb;
238
+ border-bottom: 2px solid #e5e7eb;
239
+
240
+ &:last-child {
241
+ margin-bottom: 0;
242
+ }
243
+ `;
244
+
245
+ export const Institution = styled.h3`
246
+ font-size: 20px;
247
+ font-weight: 700;
248
+ color: #1a1d23;
249
+ margin: 0 0 8px 0;
250
+ letter-spacing: -0.3px;
251
+ `;
252
+
253
+ export const Degree = styled.div`
254
+ font-size: 17px;
255
+ color: #4b5563;
256
+ margin-bottom: 8px;
257
+ font-weight: 500;
258
+ `;
259
+
260
+ export const EducationDate = styled.div`
261
+ font-size: 13px;
262
+ color: #9ca3af;
263
+ font-weight: 600;
264
+ text-transform: uppercase;
265
+ letter-spacing: 0.5px;
266
+ `;
267
+
268
+ export const SkillsGrid = styled.div`
269
+ display: grid;
270
+ grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
271
+ gap: 16px;
272
+ `;
273
+
274
+ export const SkillCategory = styled.div`
275
+ padding: 24px;
276
+ background: white;
277
+ border: 2px solid #e5e7eb;
278
+ position: relative;
279
+ overflow: hidden;
280
+
281
+ &:before {
282
+ content: '';
283
+ position: absolute;
284
+ top: 0;
285
+ left: 0;
286
+ width: 4px;
287
+ height: 100%;
288
+ background: linear-gradient(180deg, #c71585 0%, transparent 100%);
289
+ }
290
+
291
+ &:after {
292
+ content: '';
293
+ position: absolute;
294
+ top: 0;
295
+ right: 0;
296
+ width: 32px;
297
+ height: 32px;
298
+ background: linear-gradient(135deg, transparent 50%, #c71585 50%);
299
+ opacity: 0.08;
300
+ clip-path: polygon(100% 0, 100% 100%, 0 0);
301
+ }
302
+ `;
303
+
304
+ export const SkillName = styled.h4`
305
+ font-size: 16px;
306
+ font-weight: 700;
307
+ color: #1a1d23;
308
+ margin: 0 0 12px 0;
309
+ text-transform: uppercase;
310
+ letter-spacing: 0.3px;
311
+ font-size: 14px;
312
+ `;
313
+
314
+ export const SkillTags = styled.div`
315
+ font-size: 14px;
316
+ color: #6b7280;
317
+ line-height: 1.6;
318
+ font-weight: 500;
319
+ `;
320
+
321
+ export const ProjectItem = styled(WorkItem)`
322
+ background: linear-gradient(135deg, rgba(199, 21, 133, 0.02) 0%, white 100%);
323
+ `;