@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 +8 -0
- package/README.md +92 -0
- package/package.json +35 -0
- package/src/index.js +90 -0
- package/src/ui/Resume.js +248 -0
- package/src/ui/styles.js +323 -0
package/.eslintrc.js
ADDED
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 };
|
package/src/ui/Resume.js
ADDED
|
@@ -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;
|
package/src/ui/styles.js
ADDED
|
@@ -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
|
+
`;
|