├── .eslintrc ├── .gitignore ├── .npmrc ├── .stackblitzrc ├── .vscode ├── extensions.json └── settings.json ├── README.md ├── app.vue ├── assets ├── css │ ├── style.css │ └── tailwind.css └── js │ └── script.js ├── components ├── CookieBar.vue ├── DarkToggle.vue ├── LangSwitcher.vue ├── LangSwitcher2.vue ├── LoadingPage.vue ├── Navbar.vue ├── ServiceItem.vue └── Sidebar.vue ├── composables ├── cookie.js └── locale.js ├── html.d.ts ├── layouts ├── README.md ├── default.vue └── home.vue ├── locales ├── en.json └── tr.json ├── netlify.toml ├── nuxt.config.ts ├── package.json ├── pages ├── 404.vue ├── blog │ └── index.vue ├── contact.vue ├── index.vue ├── portfolio.vue └── resume.vue ├── plugins ├── cookies.js ├── i18n.ts └── primevue.js ├── pnpm-lock.yaml ├── public ├── afsakar-logo.png ├── flags │ ├── en.png │ └── tr.png ├── images │ ├── avatar-1.png │ ├── avatar-2.png │ ├── avatar-3.png │ ├── avatar-4.png │ ├── blog-1.jpg │ ├── blog-2.jpg │ ├── blog-3.jpg │ ├── blog-4.jpg │ ├── blog-5.jpg │ ├── blog-6.jpg │ ├── icon-app.svg │ ├── icon-design.svg │ ├── icon-dev.svg │ ├── icon-photo.svg │ ├── icon-quote.svg │ ├── logo-1-color.png │ ├── logo-2-color.png │ ├── logo-3-color.png │ ├── logo-4-color.png │ ├── logo-5-color.png │ ├── logo-6-color.png │ ├── logo.ico │ ├── logo.svg │ ├── my-avatar.png │ ├── project-1.jpg │ ├── project-2.png │ ├── project-3.jpg │ ├── project-4.png │ ├── project-5.png │ ├── project-6.png │ ├── project-7.png │ ├── project-8.jpg │ └── project-9.png ├── nuxt.png └── vite.png ├── server └── api │ ├── categories.js │ ├── projects.js │ ├── services.js │ └── testimonials.js ├── tailwind.config.js └── tsconfig.json /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@antfu" 3 | } 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | *.log 3 | dist 4 | .output 5 | .nuxt 6 | .env 7 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | shamefully-hoist=true 2 | strict-peer-dependencies=false 3 | -------------------------------------------------------------------------------- /.stackblitzrc: -------------------------------------------------------------------------------- 1 | { 2 | "installDependencies": true, 3 | "startCommand": "npm run dev" 4 | } 5 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "antfu.iconify", 4 | "antfu.unocss", 5 | "antfu.goto-alias", 6 | "csstools.postcss", 7 | "dbaeumer.vscode-eslint", 8 | "vue.volar" 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "prettier.enable": false, 3 | "editor.codeActionsOnSave": { 4 | "source.fixAll.eslint": true 5 | }, 6 | "files.associations": { 7 | "*.css": "postcss" 8 | }, 9 | "editor.formatOnSave": false, 10 | "i18n-ally.localesPaths": [ 11 | "locales" 12 | ], 13 | "i18n-ally.keystyle": "nested" 14 | } 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | vCard Portfolio Nuxt 3 Template
4 | (extends from [codewithsadee](https://github.com/codewithsadee/vcard-personal-portfolio)) 5 | 6 |


7 | 8 |
 9 | 🧪 Working in Progress
10 | 
11 | 12 | ![vCard Desktop Demo](https://github.com/codewithsadee/vcard-personal-portfolio/raw/master/website-demo-image/desktop.png) 13 | ![vCard Mobile Demo](https://github.com/codewithsadee/vcard-personal-portfolio/raw/master/website-demo-image/mobile.png) 14 | 15 | ## Features 16 | 17 | - [💚 Nuxt 3](https://v3.nuxtjs.org) - SSR, ESR, File-based routing, components auto importing, modules, etc. 18 | 19 | - ⚡️ Vite - Instant HMR 20 | 21 | - 🎨 [Tailwind CSS](https://github.com/tailwindcss) - A utility-first CSS framework packed. 22 | 23 | - :eight_spoked_asterisk: [PrimeVue](https://www.primefaces.org/primevue/) - PrimeVue is a rich set of open source native components for Vue. 24 | 25 | - 🔥 The ` 21 | 22 | 29 | 30 | 39 | -------------------------------------------------------------------------------- /assets/css/style.css: -------------------------------------------------------------------------------- 1 | /*-----------------------------------*\ 2 | #style.css 3 | \*-----------------------------------*/ 4 | 5 | 6 | /** 7 | * copyright 2022 @codewithsadee 8 | */ 9 | 10 | 11 | 12 | 13 | 14 | /*-----------------------------------*\ 15 | #CUSTOM PROPERTY 16 | \*-----------------------------------*/ 17 | 18 | :root { 19 | 20 | /** 21 | * colors 22 | */ 23 | 24 | /* gradient */ 25 | 26 | --bg-gradient-onyx: linear-gradient( 27 | to bottom right, 28 | hsl(240, 1%, 25%) 3%, 29 | hsl(0, 0%, 19%) 97% 30 | ); 31 | --bg-gradient-jet: linear-gradient( 32 | to bottom right, 33 | hsla(240, 1%, 18%, 0.251) 0%, 34 | hsla(240, 2%, 11%, 0) 100% 35 | ), hsl(240, 2%, 13%); 36 | --bg-gradient-yellow-1: linear-gradient( 37 | to bottom right, 38 | hsl(45, 100%, 71%) 0%, 39 | hsla(36, 100%, 69%, 0) 50% 40 | ); 41 | --bg-gradient-yellow-2: linear-gradient( 42 | 135deg, 43 | hsla(45, 100%, 71%, 0.251) 0%, 44 | hsla(35, 100%, 68%, 0) 59.86% 45 | ), hsl(240, 2%, 13%); 46 | --border-gradient-onyx: linear-gradient( 47 | to bottom right, 48 | hsl(0, 0%, 25%) 0%, 49 | hsla(0, 0%, 25%, 0) 50% 50 | ); 51 | --text-gradient-yellow: linear-gradient( 52 | to right, 53 | hsl(45, 100%, 72%), 54 | hsl(35, 100%, 68%) 55 | ); 56 | 57 | /* solid */ 58 | 59 | --jet: hsl(0, 0%, 22%); 60 | --onyx: hsl(210, 11%, 15%); 61 | --eerie-black-1: hsl(240, 2%, 13%); 62 | --eerie-black-2: hsl(240, 2%, 12%); 63 | --smoky-black: hsl(0, 0%, 7%); 64 | --white-1: hsl(0, 0%, 100%); 65 | --white-2: hsl(0, 0%, 98%); 66 | --orange-yellow-crayola: hsl(45, 100%, 72%); 67 | --vegas-gold: hsl(37, 90%, 51%); 68 | --light-gray: hsl(0, 0%, 84%); 69 | --light-gray-70: hsla(0, 0%, 84%, 0.7); 70 | --bittersweet-shimmer: hsl(0, 43%, 51%); 71 | --text-gradient-yellow: hsl(37, 90%, 51%); 72 | 73 | /** 74 | * typography 75 | */ 76 | 77 | /* font-family */ 78 | --ff-poppins: 'Poppins', sans-serif; 79 | 80 | /* font-size */ 81 | --fs-1: 24px; 82 | --fs-2: 18px; 83 | --fs-3: 17px; 84 | --fs-4: 16px; 85 | --fs-5: 15px; 86 | --fs-6: 14px; 87 | --fs-7: 13px; 88 | --fs-8: 11px; 89 | 90 | /* font-weight */ 91 | --fw-300: 300; 92 | --fw-400: 400; 93 | --fw-500: 500; 94 | --fw-600: 600; 95 | 96 | /** 97 | * shadow 98 | */ 99 | 100 | --shadow-1: -4px 8px 24px hsla(0, 0%, 0%, 0.25); 101 | --shadow-2: 0 16px 30px hsla(0, 0%, 0%, 0.25); 102 | --shadow-3: 0 16px 40px hsla(0, 0%, 0%, 0.25); 103 | --shadow-4: 0 25px 50px hsla(0, 0%, 0%, 0.15); 104 | --shadow-5: 0 24px 80px hsla(0, 0%, 0%, 0.25); 105 | 106 | /** 107 | * transition 108 | */ 109 | 110 | --transition-1: 0.25s ease; 111 | --transition-2: 0.5s ease-in-out; 112 | 113 | } 114 | 115 | 116 | 117 | 118 | 119 | /*-----------------------------------*\ 120 | #RESET 121 | \*-----------------------------------*/ 122 | 123 | *, *::before, *::after { 124 | margin: 0; 125 | padding: 0; 126 | box-sizing: border-box; 127 | } 128 | 129 | a { text-decoration: none; } 130 | 131 | li { list-style: none; } 132 | 133 | img, ion-icon, a, button, time, span { display: block; } 134 | 135 | button { 136 | font: inherit; 137 | background: none; 138 | border: none; 139 | text-align: left; 140 | cursor: pointer; 141 | } 142 | 143 | input, textarea { 144 | display: block; 145 | width: 100%; 146 | background: none; 147 | font: inherit; 148 | } 149 | 150 | ::selection { 151 | background: var(--vegas-gold); 152 | color: var(--smoky-black); 153 | } 154 | 155 | :focus { outline-color: var(--vegas-gold); } 156 | 157 | html { font-family: var(--ff-poppins); } 158 | 159 | body { background: var(--smoky-black); } 160 | 161 | 162 | 163 | 164 | 165 | /*-----------------------------------*\ 166 | #REUSED STYLE 167 | \*-----------------------------------*/ 168 | 169 | .sidebar, 170 | article { 171 | background: var(--eerie-black-2); 172 | border: 1px solid var(--jet); 173 | border-radius: 20px; 174 | padding: 15px; 175 | box-shadow: var(--shadow-1); 176 | z-index: 1; 177 | } 178 | 179 | .separator { 180 | width: 100%; 181 | height: 1px; 182 | background: var(--jet); 183 | margin: 16px 0; 184 | } 185 | 186 | .icon-box { 187 | position: relative; 188 | background: var(--border-gradient-onyx); 189 | width: 30px; 190 | height: 30px; 191 | border-radius: 8px; 192 | display: flex; 193 | justify-content: center; 194 | align-items: center; 195 | font-size: 16px; 196 | color: var(--vegas-gold); 197 | box-shadow: var(--shadow-1); 198 | z-index: 1; 199 | } 200 | 201 | .icon-box::before { 202 | content: ""; 203 | position: absolute; 204 | inset: 1px; 205 | background: var(--eerie-black-1); 206 | border-radius: inherit; 207 | z-index: -1; 208 | } 209 | 210 | .icon-box ion-icon { --ionicon-stroke-width: 35px; } 211 | 212 | article { display: none; } 213 | 214 | article.active { 215 | display: block; 216 | animation: fade 0.5s ease backwards; 217 | } 218 | 219 | @keyframes fade { 220 | 0% { opacity: 0; } 221 | 100% { opacity: 1; } 222 | } 223 | 224 | .h2, 225 | .h3, 226 | .h4, 227 | .h5 { 228 | color: var(--white-2); 229 | text-transform: capitalize; 230 | } 231 | 232 | .h2 { font-size: var(--fs-1); } 233 | 234 | .h3 { font-size: var(--fs-2); } 235 | 236 | .h4 { font-size: var(--fs-4); } 237 | 238 | .h5 { 239 | font-size: var(--fs-7); 240 | font-weight: var(--fw-500); 241 | } 242 | 243 | .article-title { 244 | position: relative; 245 | padding-bottom: 7px; 246 | } 247 | 248 | .article-title::after { 249 | content: ""; 250 | position: absolute; 251 | bottom: 0; 252 | left: 0; 253 | width: 30px; 254 | height: 3px; 255 | background: var(--text-gradient-yellow); 256 | border-radius: 3px; 257 | } 258 | 259 | .has-scrollbar::-webkit-scrollbar { 260 | width: 5px; /* for vertical scrollbar */ 261 | height: 5px; /* for horizontal scrollbar */ 262 | } 263 | 264 | .has-scrollbar::-webkit-scrollbar-track { 265 | background: var(--onyx); 266 | border-radius: 5px; 267 | } 268 | 269 | .has-scrollbar::-webkit-scrollbar-thumb { 270 | background: var(--vegas-gold); 271 | border-radius: 5px; 272 | } 273 | 274 | .has-scrollbar::-webkit-scrollbar-button { width: 20px; } 275 | 276 | .content-card { 277 | position: relative; 278 | background: var(--border-gradient-onyx); 279 | padding: 15px; 280 | padding-top: 45px; 281 | border-radius: 14px; 282 | box-shadow: var(--shadow-2); 283 | cursor: pointer; 284 | z-index: 1; 285 | } 286 | 287 | .content-card::before { 288 | content: ""; 289 | position: absolute; 290 | inset: 1px; 291 | background: var(--bg-gradient-jet); 292 | border-radius: inherit; 293 | z-index: -1; 294 | } 295 | 296 | 297 | 298 | 299 | 300 | /*-----------------------------------*\ 301 | #MAIN 302 | \*-----------------------------------*/ 303 | 304 | main { 305 | margin: 15px 12px; 306 | margin-bottom: 75px; 307 | min-width: 259px; 308 | } 309 | 310 | 311 | 312 | 313 | 314 | /*-----------------------------------*\ 315 | #SIDEBAR 316 | \*-----------------------------------*/ 317 | 318 | .sidebar { 319 | margin-bottom: 15px; 320 | max-height: 112px; 321 | overflow: hidden; 322 | transition: var(--transition-2); 323 | } 324 | 325 | .sidebar.active { max-height: 405px; } 326 | 327 | .sidebar-info { 328 | position: relative; 329 | display: flex; 330 | justify-content: flex-start; 331 | align-items: center; 332 | gap: 15px; 333 | } 334 | 335 | .avatar-box { 336 | background: var(--bg-gradient-onyx); 337 | border-radius: 20px; 338 | } 339 | 340 | .info-content .name { 341 | color: var(--white-2); 342 | font-size: var(--fs-3); 343 | font-weight: var(--fw-500); 344 | letter-spacing: -0.25px; 345 | margin-bottom: 10px; 346 | } 347 | 348 | .info-content .title { 349 | color: var(--white-1); 350 | background: var(--onyx); 351 | font-size: var(--fs-8); 352 | font-weight: var(--fw-300); 353 | width: max-content; 354 | padding: 3px 12px; 355 | border-radius: 8px; 356 | } 357 | 358 | .info_more-btn { 359 | position: absolute; 360 | top: -15px; 361 | right: -15px; 362 | border-radius: 0 15px; 363 | font-size: 13px; 364 | color: var(--vegas-gold); 365 | background: var(--border-gradient-onyx); 366 | padding: 10px; 367 | box-shadow: var(--shadow-2); 368 | transition: var(--transition-1); 369 | z-index: 1; 370 | } 371 | 372 | .info_more-btn::before { 373 | content: ""; 374 | position: absolute; 375 | inset: 1px; 376 | border-radius: inherit; 377 | background: var(--bg-gradient-jet); 378 | transition: var(--transition-1); 379 | z-index: -1; 380 | } 381 | 382 | .info_more-btn:hover, 383 | .info_more-btn:focus { background: var(--bg-gradient-yellow-1); } 384 | 385 | .info_more-btn:hover::before, 386 | .info_more-btn:focus::before { background: var(--bg-gradient-yellow-2); } 387 | 388 | .info_more-btn span { display: none; } 389 | 390 | .sidebar-info_more { 391 | opacity: 0; 392 | visibility: hidden; 393 | transition: var(--transition-2); 394 | } 395 | 396 | .sidebar.active .sidebar-info_more { 397 | opacity: 1; 398 | visibility: visible; 399 | } 400 | 401 | .contacts-list { 402 | display: grid; 403 | grid-template-columns: 1fr; 404 | gap: 16px; 405 | } 406 | 407 | .contact-item { 408 | min-width: 100%; 409 | display: flex; 410 | align-items: center; 411 | gap: 16px; 412 | } 413 | 414 | .contact-info { 415 | max-width: calc(100% - 46px); 416 | width: calc(100% - 46px); 417 | } 418 | 419 | .contact-title { 420 | color: var(--light-gray-70); 421 | font-size: var(--fs-8); 422 | text-transform: uppercase; 423 | margin-bottom: 2px; 424 | } 425 | 426 | .contact-info :is(.contact-link, time, address) { 427 | color: var(--white-2); 428 | font-size: var(--fs-7); 429 | } 430 | 431 | .contact-info address { font-style: normal; } 432 | 433 | .social-list { 434 | display: flex; 435 | justify-content: flex-start; 436 | align-items: center; 437 | gap: 15px; 438 | padding-bottom: 4px; 439 | padding-left: 7px; 440 | } 441 | 442 | .social-item .social-link { 443 | color: var(--light-gray-70); 444 | font-size: 18px; 445 | } 446 | 447 | 448 | .social-item .social-link:hover { color: var(--light-gray); } 449 | 450 | 451 | 452 | 453 | 454 | /*-----------------------------------*\ 455 | #NAVBAR 456 | \*-----------------------------------*/ 457 | 458 | .navbar { 459 | position: fixed; 460 | bottom: 0; 461 | left: 0; 462 | width: 100%; 463 | background: hsla(240, 1%, 17%, 0.75); 464 | backdrop-filter: blur(10px); 465 | border: 1px solid var(--jet); 466 | border-radius: 12px 12px 0 0; 467 | box-shadow: var(--shadow-2); 468 | z-index: 5; 469 | } 470 | 471 | .navbar-list { 472 | display: flex; 473 | flex-wrap: wrap; 474 | justify-content: center; 475 | align-items: center; 476 | padding: 0 10px; 477 | } 478 | 479 | .navbar-link { 480 | color: var(--light-gray); 481 | font-size: var(--fs-8); 482 | padding: 20px 7px; 483 | transition: color var(--transition-1); 484 | } 485 | 486 | .navbar-link:hover, 487 | .navbar-link:focus { color: var(--light-gray-70); } 488 | 489 | .navbar-link.active { color: var(--vegas-gold); } 490 | 491 | 492 | 493 | 494 | 495 | /*-----------------------------------*\ 496 | #ABOUT 497 | \*-----------------------------------*/ 498 | 499 | .about .article-title { margin-bottom: 15px; } 500 | 501 | .about-text { 502 | color: var(--light-gray); 503 | font-size: var(--fs-6); 504 | font-weight: var(--fw-300); 505 | line-height: 1.6; 506 | } 507 | 508 | .about-text p { margin-bottom: 15px; } 509 | 510 | 511 | 512 | /** 513 | * #service 514 | */ 515 | 516 | .service { margin-bottom: 35px; } 517 | 518 | .service-title { margin-bottom: 20px; } 519 | 520 | .service-list { 521 | display: grid; 522 | grid-template-columns: 1fr; 523 | gap: 20px; 524 | } 525 | 526 | .service-item { 527 | position: relative; 528 | background: var(--border-gradient-onyx); 529 | padding: 20px; 530 | border-radius: 14px; 531 | box-shadow: var(--shadow-2); 532 | z-index: 1; 533 | } 534 | 535 | .service-item::before { 536 | content: ""; 537 | position: absolute; 538 | inset: 1px; 539 | background: var(--bg-gradient-jet); 540 | border-radius: inherit; 541 | z-index: -1; 542 | } 543 | 544 | .service-icon-box { margin-bottom: 10px; } 545 | 546 | .service-icon-box img { margin: auto; } 547 | 548 | .service-content-box { text-align: center; } 549 | 550 | .service-item-title { margin-bottom: 7px; } 551 | 552 | .service-item-text { 553 | color: var(--light-gray); 554 | font-size: var(--fs-6); 555 | font-weight: var(--fw-3); 556 | line-height: 1.6; 557 | } 558 | 559 | 560 | /** 561 | * #testimonials 562 | */ 563 | 564 | .testimonials { margin-bottom: 30px; } 565 | 566 | .testimonials-title { margin-bottom: 20px; } 567 | 568 | .testimonials-list { 569 | display: flex; 570 | justify-content: flex-start; 571 | align-items: flex-start; 572 | gap: 15px; 573 | margin: 0 -15px; 574 | padding: 25px 15px; 575 | padding-bottom: 35px; 576 | overflow-x: auto; 577 | scroll-behavior: smooth; 578 | overscroll-behavior-inline: contain; 579 | scroll-snap-type: inline mandatory; 580 | } 581 | 582 | .testimonials-item { 583 | min-width: 100%; 584 | scroll-snap-align: center; 585 | } 586 | 587 | .testimonials-avatar-box { 588 | position: absolute; 589 | top: 0; 590 | left: 0; 591 | transform: translate(15px, -25px); 592 | background: var(--bg-gradient-onyx); 593 | border-radius: 14px; 594 | box-shadow: var(--shadow-1); 595 | } 596 | 597 | .testimonials-item-title { margin-bottom: 7px; } 598 | 599 | .testimonials-text { 600 | color: var(--light-gray); 601 | font-size: var(--fs-6); 602 | font-weight: var(--fw-300); 603 | line-height: 1.6; 604 | display: -webkit-box; 605 | line-clamp: 4; 606 | -webkit-line-clamp: 4; 607 | -webkit-box-orient: vertical; 608 | overflow: hidden; 609 | } 610 | 611 | 612 | /** 613 | * #testimonials-modal 614 | */ 615 | 616 | .modal-container { 617 | position: fixed; 618 | top: 0; 619 | left: 0; 620 | width: 100%; 621 | height: 100%; 622 | display: flex; 623 | justify-content: center; 624 | align-items: center; 625 | overflow-y: auto; 626 | overscroll-behavior: contain; 627 | z-index: 20; 628 | pointer-events: none; 629 | visibility: hidden; 630 | } 631 | 632 | .modal-container::-webkit-scrollbar { display: none; } 633 | 634 | .modal-container.active { 635 | pointer-events: all; 636 | visibility: visible; 637 | } 638 | 639 | .overlay { 640 | position: fixed; 641 | top: 0; 642 | left: 0; 643 | width: 100%; 644 | height: 100vh; 645 | background: hsl(0, 0%, 5%); 646 | opacity: 0; 647 | visibility: hidden; 648 | pointer-events: none; 649 | z-index: 1; 650 | transition: var(--transition-1); 651 | } 652 | 653 | .overlay.active { 654 | opacity: 0.8; 655 | visibility: visible; 656 | pointer-events: all; 657 | } 658 | 659 | .testimonials-modal { 660 | background: var(--eerie-black-2); 661 | position: relative; 662 | padding: 15px; 663 | margin: 15px 12px; 664 | border: 1px solid var(--jet); 665 | border-radius: 14px; 666 | box-shadow: var(--shadow-5); 667 | transform: scale(1.2); 668 | opacity: 0; 669 | transition: var(--transition-1); 670 | z-index: 2; 671 | } 672 | 673 | .modal-container.active .testimonials-modal { 674 | transform: scale(1); 675 | opacity: 1; 676 | } 677 | 678 | .modal-close-btn { 679 | position: absolute; 680 | top: 15px; 681 | right: 15px; 682 | background: var(--onyx); 683 | border-radius: 8px; 684 | width: 32px; 685 | height: 32px; 686 | display: flex; 687 | justify-content: center; 688 | align-items: center; 689 | color: var(--white-2); 690 | font-size: 18px; 691 | opacity: 0.7; 692 | } 693 | 694 | .modal-close-btn:hover, 695 | .modal-close-btn:focus { opacity: 1; } 696 | 697 | .modal-close-btn ion-icon { --ionicon-stroke-width: 50px; } 698 | 699 | .modal-avatar-box { 700 | background: var(--bg-gradient-onyx); 701 | width: max-content; 702 | border-radius: 14px; 703 | margin-bottom: 15px; 704 | box-shadow: var(--shadow-2); 705 | } 706 | 707 | .modal-img-wrapper > img { display: none; } 708 | 709 | .modal-title { margin-bottom: 4px; } 710 | 711 | .modal-content time { 712 | font-size: var(--fs-6); 713 | color: var(--light-gray-70); 714 | font-weight: var(--fw-300); 715 | margin-bottom: 10px; 716 | } 717 | 718 | .modal-content p { 719 | color: var(--light-gray); 720 | font-size: var(--fs-6); 721 | font-weight: var(--fw-300); 722 | line-height: 1.6; 723 | } 724 | 725 | 726 | /** 727 | * #clients 728 | */ 729 | 730 | .clients { margin-bottom: 15px; } 731 | 732 | .clients-list { 733 | display: flex; 734 | justify-content: flex-start; 735 | align-items: flex-start; 736 | gap: 15px; 737 | margin: 0 -15px; 738 | padding: 25px; 739 | padding-bottom: 25px; 740 | overflow-x: auto; 741 | scroll-behavior: smooth; 742 | overscroll-behavior-inline: contain; 743 | scroll-snap-type: inline mandatory; 744 | scroll-padding-inline: 25px; 745 | } 746 | 747 | .clients-item { 748 | min-width: 50%; 749 | scroll-snap-align: start; 750 | } 751 | 752 | .clients-item img { 753 | width: 100%; 754 | filter: grayscale(1); 755 | transition: var(--transition-1); 756 | } 757 | 758 | .clients-item img:hover { filter: grayscale(0); } 759 | 760 | 761 | 762 | 763 | 764 | /*-----------------------------------*\ 765 | #RESUME 766 | \*-----------------------------------*/ 767 | 768 | .article-title { margin-bottom: 30px; } 769 | 770 | 771 | /** 772 | * education and experience 773 | */ 774 | 775 | .timeline { margin-bottom: 30px; } 776 | 777 | .timeline .title-wrapper { 778 | display: flex; 779 | align-items: center; 780 | gap: 15px; 781 | margin-bottom: 25px; 782 | } 783 | 784 | .timeline-list { 785 | font-size: var(--fs-6); 786 | margin-left: 45px; 787 | } 788 | 789 | .timeline-item { position: relative; } 790 | 791 | .timeline-item:not(:last-child) { margin-bottom: 20px; } 792 | 793 | .timeline-item-title { 794 | font-size: var(--fs-6); 795 | line-height: 1.3; 796 | margin-bottom: 7px; 797 | } 798 | 799 | .timeline-list span { 800 | color: var(--vegas-gold); 801 | font-weight: var(--fw-400); 802 | line-height: 1.6; 803 | } 804 | 805 | .timeline-item:not(:last-child)::before { 806 | content: ""; 807 | position: absolute; 808 | top: -25px; 809 | left: -30px; 810 | width: 1px; 811 | height: calc(100% + 50px); 812 | background: var(--jet); 813 | } 814 | 815 | .timeline-item::after { 816 | content: ""; 817 | position: absolute; 818 | top: 5px; 819 | left: -33px; 820 | height: 6px; 821 | width: 6px; 822 | background: var(--text-gradient-yellow); 823 | border-radius: 50%; 824 | box-shadow: 0 0 0 4px var(--jet); 825 | } 826 | 827 | .timeline-text { 828 | color: var(--light-gray); 829 | font-weight: var(--fw-300); 830 | line-height: 1.6; 831 | } 832 | 833 | 834 | /** 835 | * skills 836 | */ 837 | 838 | .skills-title { margin-bottom: 20px; } 839 | 840 | .skills-list { padding: 20px; } 841 | 842 | 843 | .skills-item:not(:last-child) { margin-bottom: 15px; } 844 | 845 | .skill .title-wrapper { 846 | display: flex; 847 | align-items: center; 848 | gap: 5px; 849 | margin-bottom: 8px; 850 | } 851 | 852 | .skill .title-wrapper data { 853 | color: var(--light-gray); 854 | font-size: var(--fs-7); 855 | font-weight: var(--fw-300); 856 | } 857 | 858 | .skill-progress-bg { 859 | background: var(--jet); 860 | width: 100%; 861 | height: 8px; 862 | border-radius: 10px; 863 | } 864 | 865 | .skill-progress-fill { 866 | background: var(--text-gradient-yellow); 867 | height: 100%; 868 | border-radius: inherit; 869 | } 870 | 871 | 872 | 873 | 874 | 875 | /*-----------------------------------*\ 876 | #PORTFOLIO 877 | \*-----------------------------------*/ 878 | 879 | .filter-list { display: none; } 880 | 881 | .filter-select-box { 882 | position: relative; 883 | margin-bottom: 25px; 884 | } 885 | 886 | .filter-select { 887 | background: var(--eerie-black-2); 888 | color: var(--light-gray); 889 | display: flex; 890 | justify-content: space-between; 891 | align-items: center; 892 | width: 100%; 893 | padding: 12px 16px; 894 | border: 1px solid var(--jet); 895 | border-radius: 14px; 896 | font-size: var(--fs-6); 897 | font-weight: var(--fw-300); 898 | } 899 | 900 | .filter-select.active .select-icon { transform: rotate(0.5turn); } 901 | 902 | .select-list { 903 | background: var(--eerie-black-2); 904 | position: absolute; 905 | top: calc(100% + 6px); 906 | width: 100%; 907 | padding: 6px; 908 | border: 1px solid var(--jet); 909 | border-radius: 14px; 910 | z-index: 2; 911 | opacity: 0; 912 | visibility: hidden; 913 | pointer-events: none; 914 | transition: 0.15s ease-in-out; 915 | } 916 | 917 | .filter-select.active + .select-list { 918 | opacity: 1; 919 | visibility: visible; 920 | pointer-events: all; 921 | } 922 | 923 | .select-item button { 924 | background: var(--eerie-black-2); 925 | color: var(--light-gray); 926 | font-size: var(--fs-6); 927 | font-weight: var(--fw-300); 928 | text-transform: capitalize; 929 | width: 100%; 930 | padding: 8px 10px; 931 | border-radius: 8px; 932 | } 933 | 934 | .select-item button:hover { --eerie-black-2: hsl(240, 2%, 20%); } 935 | 936 | .project-list { 937 | display: grid; 938 | grid-template-columns: 1fr; 939 | gap: 30px; 940 | margin-bottom: 10px; 941 | } 942 | 943 | .project-item { display: none; } 944 | 945 | .project-item.active { 946 | display: block; 947 | animation: scaleUp 0.25s ease forwards; 948 | } 949 | 950 | @keyframes scaleUp { 951 | 0% { transform: scale(0.5); } 952 | 100% { transform: scale(1); } 953 | } 954 | 955 | .project-item > a { width: 100%; } 956 | 957 | .project-img { 958 | position: relative; 959 | width: 100%; 960 | height: 200px; 961 | border-radius: 16px; 962 | overflow: hidden; 963 | margin-bottom: 15px; 964 | } 965 | 966 | .project-img::before { 967 | content: ""; 968 | position: absolute; 969 | top: 0; 970 | left: 0; 971 | width: 100%; 972 | height: 100%; 973 | background: transparent; 974 | z-index: 1; 975 | transition: var(--transition-1); 976 | } 977 | 978 | .project-item > a:hover .project-img::before { background: hsla(0, 0%, 0%, 0.5); } 979 | 980 | .project-item-icon-box { 981 | --scale: 0.8; 982 | 983 | background: var(--jet); 984 | color: var(--vegas-gold); 985 | position: absolute; 986 | top: 50%; 987 | left: 50%; 988 | transform: translate(-50%, -50%) scale(var(--scale)); 989 | font-size: 20px; 990 | padding: 18px; 991 | border-radius: 12px; 992 | opacity: 0; 993 | z-index: 1; 994 | transition: var(--transition-1); 995 | } 996 | 997 | .project-item > a:hover .project-item-icon-box { 998 | --scale: 1; 999 | opacity: 1; 1000 | } 1001 | 1002 | .project-item-icon-box ion-icon { --ionicon-stroke-width: 50px; } 1003 | 1004 | .project-img img { 1005 | width: 100%; 1006 | height: 100%; 1007 | object-fit: cover; 1008 | transition: var(--transition-1); 1009 | } 1010 | 1011 | .project-item > a:hover img { transform: scale(1.1); } 1012 | 1013 | .project-title, 1014 | .project-category { margin-left: 10px; } 1015 | 1016 | .project-title { 1017 | color: var(--white-2); 1018 | font-size: var(--fs-5); 1019 | font-weight: var(--fw-400); 1020 | text-transform: capitalize; 1021 | line-height: 1.3; 1022 | } 1023 | 1024 | .project-category { 1025 | color: var(--light-gray-70); 1026 | font-size: var(--fs-6); 1027 | font-weight: var(--fw-300); 1028 | } 1029 | 1030 | 1031 | 1032 | 1033 | 1034 | /*-----------------------------------*\ 1035 | #BLOG 1036 | \*-----------------------------------*/ 1037 | 1038 | .blog-posts { margin-bottom: 10px; } 1039 | 1040 | .blog-posts-list { 1041 | display: grid; 1042 | grid-template-columns: 1fr; 1043 | gap: 20px; 1044 | } 1045 | 1046 | .blog-post-item > a { 1047 | position: relative; 1048 | background: var(--border-gradient-onyx); 1049 | height: 100%; 1050 | box-shadow: var(--shadow-4); 1051 | border-radius: 16px; 1052 | z-index: 1; 1053 | } 1054 | 1055 | .blog-post-item > a::before { 1056 | content: ""; 1057 | position: absolute; 1058 | inset: 1px; 1059 | border-radius: inherit; 1060 | background: var(--eerie-black-1); 1061 | z-index: -1; 1062 | } 1063 | 1064 | .blog-banner-box { 1065 | width: 100%; 1066 | height: 200px; 1067 | border-radius: 12px; 1068 | overflow: hidden; 1069 | } 1070 | 1071 | .blog-banner-box img { 1072 | width: 100%; 1073 | height: 100%; 1074 | object-fit: cover; 1075 | transition: var(--transition-1); 1076 | } 1077 | 1078 | .blog-post-item > a:hover .blog-banner-box img { transform: scale(1.1); } 1079 | 1080 | .blog-content { padding: 15px; } 1081 | 1082 | .blog-meta { 1083 | display: flex; 1084 | justify-content: flex-start; 1085 | align-items: center; 1086 | gap: 7px; 1087 | margin-bottom: 10px; 1088 | } 1089 | 1090 | .blog-meta :is(.blog-category, time) { 1091 | color: var(--light-gray-70); 1092 | font-size: var(--fs-6); 1093 | font-weight: var(--fw-300); 1094 | } 1095 | 1096 | .blog-meta .dot { 1097 | background: var(--light-gray-70); 1098 | width: 4px; 1099 | height: 4px; 1100 | border-radius: 4px; 1101 | } 1102 | 1103 | .blog-item-title { 1104 | margin-bottom: 10px; 1105 | line-height: 1.3; 1106 | transition: var(--transition-1); 1107 | } 1108 | 1109 | .blog-post-item > a:hover .blog-item-title { color: var(--vegas-gold); } 1110 | 1111 | .blog-text { 1112 | color: var(--light-gray); 1113 | font-size: var(--fs-6); 1114 | font-weight: var(--fw-300); 1115 | line-height: 1.6; 1116 | } 1117 | 1118 | 1119 | 1120 | 1121 | 1122 | /*-----------------------------------*\ 1123 | #CONTACT 1124 | \*-----------------------------------*/ 1125 | 1126 | .mapbox { 1127 | position: relative; 1128 | height: 250px; 1129 | width: 100%; 1130 | border-radius: 16px; 1131 | margin-bottom: 30px; 1132 | border: 1px solid var(--jet); 1133 | overflow: hidden; 1134 | } 1135 | 1136 | .mapbox figure { height: 100%; } 1137 | 1138 | .mapbox iframe { 1139 | width: 100%; 1140 | height: 100%; 1141 | border: none; 1142 | filter: grayscale(1) invert(1); 1143 | } 1144 | 1145 | .contact-form { margin-bottom: 10px; } 1146 | 1147 | .form-title { margin-bottom: 20px; } 1148 | 1149 | .input-wrapper { 1150 | display: grid; 1151 | grid-template-columns: 1fr; 1152 | gap: 25px; 1153 | margin-bottom: 25px; 1154 | } 1155 | 1156 | .form-input { 1157 | color: var(--white-2); 1158 | font-size: var(--fs-6); 1159 | font-weight: var(--fw-400); 1160 | padding: 13px 20px; 1161 | border: 1px solid var(--jet); 1162 | border-radius: 14px; 1163 | outline: none; 1164 | } 1165 | 1166 | .form-input::placeholder { font-weight: var(--fw-500); } 1167 | 1168 | .form-input:focus { border-color: var(--vegas-gold); } 1169 | 1170 | textarea.form-input { 1171 | min-height: 100px; 1172 | height: 120px; 1173 | max-height: 200px; 1174 | resize: vertical; 1175 | margin-bottom: 25px; 1176 | } 1177 | 1178 | textarea.form-input::-webkit-resizer { display: none; } 1179 | 1180 | .form-input:focus:invalid { border-color: var(--bittersweet-shimmer); } 1181 | 1182 | .form-btn { 1183 | position: relative; 1184 | width: 100%; 1185 | background: var(--border-gradient-onyx); 1186 | color: var(--vegas-gold); 1187 | display: flex; 1188 | justify-content: center; 1189 | align-items: center; 1190 | gap: 10px; 1191 | padding: 13px 20px; 1192 | border-radius: 14px; 1193 | font-size: var(--fs-6); 1194 | text-transform: capitalize; 1195 | box-shadow: var(--shadow-3); 1196 | z-index: 1; 1197 | transition: var(--transition-1); 1198 | } 1199 | 1200 | .form-btn::before { 1201 | content: ""; 1202 | position: absolute; 1203 | inset: 1px; 1204 | background: var(--bg-gradient-jet); 1205 | border-radius: inherit; 1206 | z-index: -1; 1207 | transition: var(--transition-1); 1208 | } 1209 | 1210 | .form-btn ion-icon { font-size: 16px; } 1211 | 1212 | .form-btn:hover { background: var(--bg-gradient-yellow-1); } 1213 | 1214 | .form-btn:hover::before { background: var(--bg-gradient-yellow-2); } 1215 | 1216 | .form-btn:disabled { 1217 | opacity: 0.7; 1218 | cursor: not-allowed; 1219 | } 1220 | 1221 | .form-btn:disabled:hover { background: var(--border-gradient-onyx); } 1222 | 1223 | .form-btn:disabled:hover::before { background: var(--bg-gradient-jet); } 1224 | 1225 | 1226 | 1227 | 1228 | 1229 | /*-----------------------------------*\ 1230 | #RESPONSIVE 1231 | \*-----------------------------------*/ 1232 | 1233 | /** 1234 | * responsive larger than 450px screen 1235 | */ 1236 | 1237 | @media (min-width: 450px) { 1238 | 1239 | /** 1240 | * client 1241 | */ 1242 | 1243 | .clients-item { min-width: calc(33.33% - 10px); } 1244 | 1245 | 1246 | 1247 | /** 1248 | * #PORTFOLIO, BLOG 1249 | */ 1250 | 1251 | .project-img, 1252 | .blog-banner-box { height: auto; } 1253 | 1254 | } 1255 | 1256 | 1257 | 1258 | 1259 | 1260 | /** 1261 | * responsive larger than 580px screen 1262 | */ 1263 | 1264 | @media (min-width: 580px) { 1265 | 1266 | /** 1267 | * CUSTOM PROPERTY 1268 | */ 1269 | 1270 | :root { 1271 | 1272 | /** 1273 | * typography 1274 | */ 1275 | 1276 | --fs-1: 32px; 1277 | --fs-2: 24px; 1278 | --fs-3: 26px; 1279 | --fs-4: 18px; 1280 | --fs-6: 15px; 1281 | --fs-7: 15px; 1282 | --fs-8: 12px; 1283 | 1284 | } 1285 | 1286 | 1287 | 1288 | /** 1289 | * #REUSED STYLE 1290 | */ 1291 | 1292 | .sidebar, article { 1293 | width: 520px; 1294 | margin-inline: auto; 1295 | padding: 30px; 1296 | } 1297 | 1298 | .article-title { 1299 | font-weight: var(--fw-600); 1300 | padding-bottom: 15px; 1301 | } 1302 | 1303 | .article-title::after { 1304 | width: 40px; 1305 | height: 5px; 1306 | } 1307 | 1308 | .icon-box { 1309 | width: 48px; 1310 | height: 48px; 1311 | border-radius: 12px; 1312 | font-size: 18px; 1313 | } 1314 | 1315 | 1316 | 1317 | /** 1318 | * #MAIN 1319 | */ 1320 | 1321 | main { 1322 | margin-top: 60px; 1323 | margin-bottom: 100px; 1324 | } 1325 | 1326 | 1327 | 1328 | /** 1329 | * #SIDEBAR 1330 | */ 1331 | 1332 | .sidebar { 1333 | max-height: 180px; 1334 | margin-bottom: 30px; 1335 | } 1336 | 1337 | .sidebar.active { max-height: 584px; } 1338 | 1339 | .sidebar-info { gap: 25px; } 1340 | 1341 | .avatar-box { border-radius: 30px; } 1342 | 1343 | .avatar-box img { width: 120px; } 1344 | 1345 | .info-content .name { margin-bottom: 15px; } 1346 | 1347 | .info-content .title { padding: 5px 18px; } 1348 | 1349 | .info_more-btn { 1350 | top: -30px; 1351 | right: -30px; 1352 | padding: 10px 15px; 1353 | } 1354 | 1355 | .info_more-btn span { 1356 | display: block; 1357 | font-size: var(--fs-8); 1358 | } 1359 | 1360 | .info_more-btn ion-icon { display: none; } 1361 | 1362 | .separator { margin: 32px 0; } 1363 | 1364 | .contacts-list { gap: 20px; } 1365 | 1366 | .contact-info { 1367 | max-width: calc(100% - 64px); 1368 | width: calc(100% - 64px); 1369 | } 1370 | 1371 | 1372 | 1373 | /** 1374 | * #NAVBAR 1375 | */ 1376 | 1377 | .navbar { border-radius: 20px 20px 0 0; } 1378 | 1379 | .navbar-list { gap: 20px; } 1380 | 1381 | .navbar-link { --fs-8: 14px; } 1382 | 1383 | 1384 | 1385 | /** 1386 | * #ABOUT 1387 | */ 1388 | 1389 | .about .article-title { margin-bottom: 20px; } 1390 | 1391 | .about-text { margin-bottom: 40px; } 1392 | 1393 | /* service */ 1394 | 1395 | .service-item { 1396 | display: flex; 1397 | justify-content: flex-start; 1398 | align-items: flex-start; 1399 | gap: 18px; 1400 | padding: 30px; 1401 | } 1402 | 1403 | .service-icon-box { 1404 | margin-bottom: 0; 1405 | margin-top: 5px; 1406 | } 1407 | 1408 | .service-content-box { text-align: left; } 1409 | 1410 | /* testimonials */ 1411 | 1412 | .testimonials-title { margin-bottom: 25px; } 1413 | 1414 | .testimonials-list { 1415 | gap: 30px; 1416 | margin: 0 -30px; 1417 | padding: 30px; 1418 | padding-bottom: 35px; 1419 | } 1420 | 1421 | .content-card { 1422 | padding: 30px; 1423 | padding-top: 25px; 1424 | } 1425 | 1426 | .testimonials-avatar-box { 1427 | transform: translate(30px, -30px); 1428 | border-radius: 20px; 1429 | } 1430 | 1431 | .testimonials-avatar-box img { width: 80px; } 1432 | 1433 | .testimonials-item-title { 1434 | margin-bottom: 10px; 1435 | margin-left: 95px; 1436 | } 1437 | 1438 | .testimonials-text { 1439 | line-clamp: 2; 1440 | -webkit-line-clamp: 2; 1441 | } 1442 | 1443 | /* testimonials modal */ 1444 | 1445 | .modal-container { padding: 20px; } 1446 | 1447 | .testimonials-modal { 1448 | justify-content: flex-start; 1449 | align-items: stretch; 1450 | gap: 25px; 1451 | padding: 30px; 1452 | border-radius: 20px; 1453 | } 1454 | 1455 | .modal-img-wrapper { 1456 | display: flex; 1457 | flex-direction: column; 1458 | align-items: center; 1459 | } 1460 | 1461 | .modal-avatar-box { 1462 | border-radius: 18px; 1463 | margin-bottom: 0; 1464 | } 1465 | 1466 | .modal-avatar-box img { width: 65px; } 1467 | 1468 | .modal-img-wrapper > img { 1469 | display: block; 1470 | flex-grow: 1; 1471 | width: 35px; 1472 | } 1473 | 1474 | /* clients */ 1475 | 1476 | .clients-list { 1477 | gap: 50px; 1478 | margin: 0 -30px; 1479 | padding: 45px; 1480 | scroll-padding-inline: 45px; 1481 | } 1482 | 1483 | .clients-item { min-width: calc(33.33% - 35px); } 1484 | 1485 | 1486 | 1487 | /** 1488 | * #RESUME 1489 | */ 1490 | 1491 | .timeline-list { margin-left: 65px; } 1492 | 1493 | .timeline-item:not(:last-child)::before { left: -40px; } 1494 | 1495 | .timeline-item::after { 1496 | height: 8px; 1497 | width: 8px; 1498 | left: -43px; 1499 | } 1500 | 1501 | .skills-item:not(:last-child) { margin-bottom: 25px; } 1502 | 1503 | 1504 | 1505 | /** 1506 | * #PORTFOLIO, BLOG 1507 | */ 1508 | 1509 | .project-img, .blog-banner-box { border-radius: 16px; } 1510 | 1511 | .blog-posts-list { gap: 30px; } 1512 | 1513 | .blog-content { padding: 25px; } 1514 | 1515 | 1516 | 1517 | /** 1518 | * #CONTACT 1519 | */ 1520 | 1521 | .mapbox { 1522 | height: 380px; 1523 | border-radius: 18px; 1524 | } 1525 | 1526 | .input-wrapper { 1527 | gap: 30px; 1528 | margin-bottom: 30px; 1529 | } 1530 | 1531 | .form-input { padding: 15px 20px; } 1532 | 1533 | textarea.form-input { margin-bottom: 30px; } 1534 | 1535 | .form-btn { 1536 | --fs-6: 16px; 1537 | padding: 16px 20px; 1538 | } 1539 | 1540 | .form-btn ion-icon { font-size: 18px; } 1541 | 1542 | } 1543 | 1544 | 1545 | 1546 | 1547 | 1548 | /** 1549 | * responsive larger than 768px screen 1550 | */ 1551 | 1552 | @media (min-width: 768px) { 1553 | 1554 | /** 1555 | * REUSED STYLE 1556 | */ 1557 | 1558 | .sidebar, article { width: 700px; } 1559 | 1560 | .has-scrollbar::-webkit-scrollbar-button { width: 100px; } 1561 | 1562 | 1563 | 1564 | /** 1565 | * SIDEBAR 1566 | */ 1567 | 1568 | .contacts-list { 1569 | grid-template-columns: 1fr 1fr; 1570 | gap: 30px 15px; 1571 | } 1572 | 1573 | 1574 | 1575 | /** 1576 | * NAVBAR 1577 | */ 1578 | 1579 | .navbar-link { --fs-8: 15px; } 1580 | 1581 | 1582 | 1583 | /** 1584 | * ABOUT 1585 | */ 1586 | 1587 | /* testimonials modal */ 1588 | 1589 | .testimonials-modal { 1590 | gap: 35px; 1591 | max-width: 680px; 1592 | } 1593 | 1594 | .modal-avatar-box img { width: 80px; } 1595 | 1596 | 1597 | 1598 | /** 1599 | * PORTFOLIO 1600 | */ 1601 | 1602 | .article-title { padding-bottom: 20px; } 1603 | 1604 | .filter-select-box { display: none; } 1605 | 1606 | .filter-list { 1607 | display: flex; 1608 | justify-content: flex-start; 1609 | align-items: center; 1610 | gap: 25px; 1611 | padding-left: 5px; 1612 | margin-bottom: 30px; 1613 | } 1614 | 1615 | .filter-item button { 1616 | color: var(--light-gray); 1617 | font-size: var(--fs-5); 1618 | transition: var(--transition-1); 1619 | } 1620 | 1621 | .filter-item button:hover { color: var(--light-gray-70); } 1622 | 1623 | .filter-item button.active { color: var(--vegas-gold); } 1624 | 1625 | /* portfolio and blog grid */ 1626 | 1627 | .project-list, .blog-posts-list { grid-template-columns: 1fr 1fr; } 1628 | 1629 | 1630 | 1631 | /** 1632 | * CONTACT 1633 | */ 1634 | 1635 | .input-wrapper { grid-template-columns: 1fr 1fr; } 1636 | 1637 | .form-btn { 1638 | width: max-content; 1639 | margin-left: auto; 1640 | } 1641 | 1642 | } 1643 | 1644 | 1645 | 1646 | 1647 | 1648 | /** 1649 | * responsive larger than 1024px screen 1650 | */ 1651 | 1652 | @media (min-width: 1024px) { 1653 | 1654 | /** 1655 | * CUSTOM PROPERTY 1656 | */ 1657 | 1658 | :root { 1659 | 1660 | /** 1661 | * shadow 1662 | */ 1663 | 1664 | --shadow-1: -4px 8px 24px hsla(0, 0%, 0%, 0.125); 1665 | --shadow-2: 0 16px 30px hsla(0, 0%, 0%, 0.125); 1666 | --shadow-3: 0 16px 40px hsla(0, 0%, 0%, 0.125); 1667 | 1668 | } 1669 | 1670 | 1671 | 1672 | /** 1673 | * REUSED STYLE 1674 | */ 1675 | 1676 | .sidebar, article { 1677 | width: 950px; 1678 | box-shadow: var(--shadow-5); 1679 | } 1680 | 1681 | 1682 | 1683 | /** 1684 | * MAIN 1685 | */ 1686 | 1687 | main { margin-bottom: 60px; } 1688 | 1689 | .main-content { 1690 | position: relative; 1691 | width: max-content; 1692 | margin: auto; 1693 | } 1694 | 1695 | 1696 | 1697 | /** 1698 | * NAVBAR 1699 | */ 1700 | 1701 | .navbar { 1702 | position: absolute; 1703 | bottom: auto; 1704 | top: 0; 1705 | left: auto; 1706 | right: 0; 1707 | width: max-content; 1708 | border-radius: 0 20px; 1709 | padding: 0 20px; 1710 | box-shadow: none; 1711 | } 1712 | 1713 | .navbar-list { 1714 | gap: 30px; 1715 | padding: 0 20px; 1716 | } 1717 | 1718 | .navbar-link { font-weight: var(--fw-500); } 1719 | 1720 | 1721 | 1722 | /** 1723 | * ABOUT 1724 | */ 1725 | 1726 | /* service */ 1727 | 1728 | .service-list { 1729 | grid-template-columns: 1fr 1fr; 1730 | gap: 20px 25px; 1731 | } 1732 | 1733 | /* testimonials */ 1734 | 1735 | .testimonials-item { min-width: calc(50% - 15px); } 1736 | 1737 | /* clients */ 1738 | 1739 | .clients-item { min-width: calc(25% - 38px); } 1740 | 1741 | 1742 | 1743 | /** 1744 | * PORTFOLIO 1745 | */ 1746 | 1747 | .project-list { grid-template-columns: repeat(3, 1fr); } 1748 | 1749 | 1750 | 1751 | /** 1752 | * BLOG 1753 | */ 1754 | 1755 | .blog-banner-box { height: 230px; } 1756 | 1757 | } 1758 | 1759 | 1760 | 1761 | 1762 | 1763 | /** 1764 | * responsive larger than 1250px screen 1765 | */ 1766 | 1767 | @media (min-width: 1250px) { 1768 | 1769 | /** 1770 | * RESET 1771 | */ 1772 | 1773 | body::-webkit-scrollbar { width: 20px; } 1774 | 1775 | body::-webkit-scrollbar-track { background: var(--smoky-black); } 1776 | 1777 | body::-webkit-scrollbar-thumb { 1778 | border: 5px solid var(--smoky-black); 1779 | background: hsla(0, 0%, 100%, 0.1); 1780 | border-radius: 20px; 1781 | box-shadow: inset 1px 1px 0 hsla(0, 0%, 100%, 0.11), 1782 | inset -1px -1px 0 hsla(0, 0%, 100%, 0.11); 1783 | } 1784 | 1785 | body::-webkit-scrollbar-thumb:hover { background: hsla(0, 0%, 100%, 0.15); } 1786 | 1787 | body::-webkit-scrollbar-button { height: 60px; } 1788 | 1789 | 1790 | 1791 | /** 1792 | * REUSED STYLE 1793 | */ 1794 | 1795 | .sidebar, article { width: auto; } 1796 | 1797 | article { min-height: 100%; } 1798 | 1799 | 1800 | 1801 | /** 1802 | * MAIN 1803 | */ 1804 | 1805 | main { 1806 | max-width: 1200px; 1807 | margin-inline: auto; 1808 | display: flex; 1809 | justify-content: center; 1810 | align-items: stretch; 1811 | gap: 25px; 1812 | } 1813 | 1814 | .main-content { 1815 | min-width: 75%; 1816 | width: 75%; 1817 | margin: 0; 1818 | } 1819 | 1820 | 1821 | 1822 | /** 1823 | * SIDEBAR 1824 | */ 1825 | 1826 | .sidebar { 1827 | position: sticky; 1828 | top: 60px; 1829 | max-height: 50rem; 1830 | height: 100%; 1831 | margin-bottom: 0; 1832 | padding-top: 60px; 1833 | z-index: 1; 1834 | } 1835 | 1836 | .sidebar-info { flex-direction: column; } 1837 | 1838 | .avatar-box img { width: 150px; } 1839 | 1840 | .info-content .name { 1841 | white-space: nowrap; 1842 | text-align: center; 1843 | } 1844 | 1845 | .info-content .title { margin: auto; } 1846 | 1847 | .info_more-btn { display: none; } 1848 | 1849 | .sidebar-info_more { 1850 | opacity: 1; 1851 | visibility: visible; 1852 | } 1853 | 1854 | .contacts-list { grid-template-columns: 1fr; } 1855 | 1856 | .contact-info :is(.contact-link) { 1857 | white-space: nowrap; 1858 | overflow: hidden; 1859 | text-overflow: ellipsis; 1860 | } 1861 | 1862 | .contact-info :is(.contact-link, time, address) { 1863 | --fs-7: 14px; 1864 | font-weight: var(--fw-300); 1865 | } 1866 | 1867 | .separator:last-of-type { 1868 | margin: 15px 0; 1869 | opacity: 0; 1870 | } 1871 | 1872 | .social-list { justify-content: center; } 1873 | 1874 | 1875 | 1876 | /** 1877 | * RESUME 1878 | */ 1879 | 1880 | .timeline-text { max-width: 700px; } 1881 | 1882 | } -------------------------------------------------------------------------------- /assets/css/tailwind.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; -------------------------------------------------------------------------------- /assets/js/script.js: -------------------------------------------------------------------------------- 1 | // element toggle function 2 | const elementToggleFunc = function (elem) { elem.classList.toggle('active') } 3 | 4 | // sidebar variables 5 | const sidebar = document.querySelector('[data-sidebar]') 6 | const sidebarBtn = document.querySelector('[data-sidebar-btn]') 7 | 8 | // sidebar toggle functionality for mobile 9 | sidebarBtn.addEventListener('click', () => { elementToggleFunc(sidebar) })> 10 | 11 | // testimonials variables 12 | const testimonialsItem = document.querySelectorAll('[data-testimonials-item]') 13 | const modalContainer = document.querySelector('[data-modal-container]') 14 | const modalCloseBtn = document.querySelector('[data-modal-close-btn]') 15 | const overlay = document.querySelector('[data-overlay]') 16 | 17 | // modal variable 18 | const modalImg = document.querySelector('[data-modal-img]') 19 | const modalTitle = document.querySelector('[data-modal-title]') 20 | const modalText = document.querySelector('[data-modal-text]') 21 | 22 | // modal toggle function 23 | const testimonialsModalFunc = function () { 24 | modalContainer.classList.toggle('active') 25 | overlay.classList.toggle('active') 26 | } 27 | 28 | // add click event to all modal items 29 | for (let i = 0; i < testimonialsItem.length; i++) { 30 | testimonialsItem[i].addEventListener('click', function () { 31 | modalImg.src = this.querySelector('[data-testimonials-avatar]').src 32 | modalImg.alt = this.querySelector('[data-testimonials-avatar]').alt 33 | modalTitle.innerHTML = this.querySelector('[data-testimonials-title]').innerHTML 34 | modalText.innerHTML = this.querySelector('[data-testimonials-text]').innerHTML 35 | 36 | testimonialsModalFunc() 37 | }) 38 | } 39 | 40 | // add click event to modal close button 41 | modalCloseBtn.addEventListener('click', testimonialsModalFunc) 42 | overlay.addEventListener('click', testimonialsModalFunc) 43 | 44 | // custom select variables 45 | const select = document.querySelector('[data-select]') 46 | const selectItems = document.querySelectorAll('[data-select-item]') 47 | const selectValue = document.querySelector('[data-selecct-value]') 48 | const filterBtn = document.querySelectorAll('[data-filter-btn]') 49 | 50 | select.addEventListener('click', function () { elementToggleFunc(this) }) 51 | 52 | // add event in all select items 53 | for (let i = 0; i < selectItems.length; i++) { 54 | selectItems[i].addEventListener('click', function () { 55 | const selectedValue = this.innerText.toLowerCase() 56 | selectValue.innerText = this.innerText 57 | elementToggleFunc(select) 58 | filterFunc(selectedValue) 59 | }) 60 | } 61 | 62 | // filter variables 63 | const filterItems = document.querySelectorAll('[data-filter-item]') 64 | 65 | const filterFunc = function (selectedValue) { 66 | for (let i = 0; i < filterItems.length; i++) { 67 | if (selectedValue === 'all') 68 | filterItems[i].classList.add('active') 69 | 70 | else if (selectedValue === filterItems[i].dataset.category) 71 | filterItems[i].classList.add('active') 72 | 73 | else 74 | filterItems[i].classList.remove('active') 75 | } 76 | } 77 | 78 | // add event in all filter button items for large screen 79 | let lastClickedBtn = filterBtn[0] 80 | 81 | for (let i = 0; i < filterBtn.length; i++) { 82 | filterBtn[i].addEventListener('click', function () { 83 | const selectedValue = this.innerText.toLowerCase() 84 | selectValue.innerText = this.innerText 85 | filterFunc(selectedValue) 86 | 87 | lastClickedBtn.classList.remove('active') 88 | this.classList.add('active') 89 | lastClickedBtn = this 90 | }) 91 | } 92 | 93 | // contact form variables 94 | const form = document.querySelector('[data-form]') 95 | const formInputs = document.querySelectorAll('[data-form-input]') 96 | const formBtn = document.querySelector('[data-form-btn]') 97 | 98 | // add event to all form input field 99 | for (let i = 0; i < formInputs.length; i++) { 100 | formInputs[i].addEventListener('input', () => { 101 | // check form validation 102 | if (form.checkValidity()) 103 | formBtn.removeAttribute('disabled') 104 | 105 | else 106 | formBtn.setAttribute('disabled', '') 107 | }) 108 | } 109 | 110 | // page navigation variables 111 | const navigationLinks = document.querySelectorAll('[data-nav-link]') 112 | const pages = document.querySelectorAll('[data-page]') 113 | 114 | // add event to all nav link 115 | for (let i = 0; i < navigationLinks.length; i++) { 116 | navigationLinks[i].addEventListener('click', function () { 117 | for (let i = 0; i < pages.length; i++) { 118 | if (this.innerHTML.toLowerCase() === pages[i].dataset.page) { 119 | pages[i].classList.add('active') 120 | navigationLinks[i].classList.add('active') 121 | window.scrollTo(0, 0) 122 | } 123 | else { 124 | pages[i].classList.remove('active') 125 | navigationLinks[i].classList.remove('active') 126 | } 127 | } 128 | }) 129 | } 130 | -------------------------------------------------------------------------------- /components/CookieBar.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 21 | 22 | 45 | -------------------------------------------------------------------------------- /components/DarkToggle.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 15 | -------------------------------------------------------------------------------- /components/LangSwitcher.vue: -------------------------------------------------------------------------------- 1 | 19 | 20 | 34 | 35 | 40 | -------------------------------------------------------------------------------- /components/LangSwitcher2.vue: -------------------------------------------------------------------------------- 1 | 23 | 24 | 29 | 30 | 35 | -------------------------------------------------------------------------------- /components/LoadingPage.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 41 | -------------------------------------------------------------------------------- /components/Navbar.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 40 | 41 | 49 | -------------------------------------------------------------------------------- /components/ServiceItem.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 33 | -------------------------------------------------------------------------------- /components/Sidebar.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 114 | -------------------------------------------------------------------------------- /composables/cookie.js: -------------------------------------------------------------------------------- 1 | import { defineStore } from 'pinia' 2 | import { computed, ref } from 'vue' 3 | import { inject } from '@vue/composition-api' 4 | import { useCookie } from '#app' 5 | 6 | export const useCookieStore = defineStore('cookieStore', () => { 7 | const cookie = ref(useCookie('accept-cookie')) 8 | const $cookies = inject('$cookies') 9 | 10 | function setCookie() { 11 | $cookies.set('accept-cookie', true, '30d') 12 | return this.cookie = true 13 | } 14 | const getCookie = computed(() => { 15 | return cookie.value 16 | }) 17 | 18 | return { cookie, setCookie, getCookie } 19 | }) 20 | -------------------------------------------------------------------------------- /composables/locale.js: -------------------------------------------------------------------------------- 1 | import { defineStore } from 'pinia' 2 | import { computed, ref } from 'vue' 3 | import { useCookie } from '#app' 4 | 5 | export const useLocaleStore = defineStore('localeStore', () => { 6 | const locale = ref(useCookie('locale')) 7 | function setLocale(val) { 8 | return this.locale = val 9 | } 10 | const getLocale = computed(() => { 11 | return locale.value 12 | }) 13 | 14 | return { locale, setLocale, getLocale } 15 | }) 16 | -------------------------------------------------------------------------------- /html.d.ts: -------------------------------------------------------------------------------- 1 | // for UnoCSS attributify mode compact in Volar 2 | // refer: https://github.com/johnsoncodehk/volar/issues/1077#issuecomment-1145361472 3 | declare module '@vue/runtime-dom' { 4 | interface HTMLAttributes { 5 | [key: string]: any 6 | } 7 | } 8 | declare module '@vue/runtime-core' { 9 | interface AllowedComponentProps { 10 | [key: string]: any 11 | } 12 | } 13 | export {} 14 | -------------------------------------------------------------------------------- /layouts/README.md: -------------------------------------------------------------------------------- 1 | ## Layouts 2 | 3 | Vue components in this dir are used as layouts. 4 | 5 | By default, `default.vue` will be used unless an alternative is specified in the route meta. 6 | 7 | ```html 8 | 13 | ``` 14 | 15 | Learn more on https://v3.nuxtjs.org/guide/directory-structure/layouts -------------------------------------------------------------------------------- /layouts/default.vue: -------------------------------------------------------------------------------- 1 | 44 | 45 | 55 | -------------------------------------------------------------------------------- /layouts/home.vue: -------------------------------------------------------------------------------- 1 | 9 | -------------------------------------------------------------------------------- /locales/en.json: -------------------------------------------------------------------------------- 1 | { 2 | "hello": "Hello", 3 | "goodbye": "Good Bye", 4 | "pageTitles": { 5 | "about": "About", 6 | "resume": "Resume", 7 | "portfolio": "Portfolio", 8 | "blog": "Blog", 9 | "contact": "Contact" 10 | } 11 | } -------------------------------------------------------------------------------- /locales/tr.json: -------------------------------------------------------------------------------- 1 | { 2 | "hello": "Merhaba", 3 | "goodbye": "Hoşçakal", 4 | "pageTitles": { 5 | "about": "Hakkımda", 6 | "resume": "Özgeçmiş", 7 | "portfolio": "Portfolyo", 8 | "blog": "Blog", 9 | "contact": "İletişim" 10 | } 11 | } -------------------------------------------------------------------------------- /netlify.toml: -------------------------------------------------------------------------------- 1 | [build.environment] 2 | NPM_FLAGS = "--version" 3 | NODE_VERSION = "16" 4 | 5 | [build] 6 | publish = "dist" 7 | command = "npx pnpm i --store=node_modules/.pnpm-store && npx pnpm run build" 8 | 9 | [[redirects]] 10 | from = "/*" 11 | to = "/index.html" 12 | status = 200 13 | -------------------------------------------------------------------------------- /nuxt.config.ts: -------------------------------------------------------------------------------- 1 | export default defineNuxtConfig({ 2 | modules: [ 3 | '@vueuse/nuxt', 4 | '@pinia/nuxt', 5 | '@nuxtjs/color-mode', 6 | '@nuxtjs/tailwindcss', 7 | '@intlify/nuxt3', 8 | ], 9 | experimental: { 10 | reactivityTransform: true, 11 | viteNode: false, 12 | }, 13 | plugins: [ 14 | ], 15 | colorMode: { 16 | classSuffix: '', 17 | }, 18 | // https://github.com/nuxt/framework/issues/6204#issuecomment-1201398080 19 | hooks: { 20 | 'vite:extendConfig': function (config: any, { isServer }: any) { 21 | if (isServer) { 22 | // Workaround for netlify issue 23 | // https://github.com/nuxt/framework/issues/6204 24 | config.build.rollupOptions.output.inlineDynamicImports = true 25 | } 26 | }, 27 | }, 28 | css: [ 29 | // 'primevue/resources/themes/bootstrap4-dark-blue/theme.css', 30 | // 'primevue/resources/primevue.css', 31 | // 'primeicons/primeicons.css', 32 | '/assets/css/style.css', 33 | ], 34 | build: { 35 | transpile: ['primevue', 'pinia-orm'], 36 | }, 37 | tailwindcss: { 38 | cssPath: '~/assets/css/tailwind.css', 39 | configPath: 'tailwind.config.js', 40 | exposeConfig: true, 41 | injectPosition: 0, 42 | viewer: true, 43 | }, 44 | vue: { 45 | config: { 46 | productionTip: true, 47 | warn: false, 48 | }, 49 | compilerOptions: { 50 | isCustomElement: tag => tag.startsWith('ion-'), 51 | }, 52 | }, 53 | loading: { 54 | color: 'blue', 55 | height: '5px', 56 | }, 57 | }) 58 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "packageManager": "pnpm@7.9.0", 4 | "scripts": { 5 | "build": "nuxi build", 6 | "dev": "nuxi dev", 7 | "start": "node .output/server/index.mjs", 8 | "lint": "eslint .", 9 | "postinstall": "nuxi prepare", 10 | "generate": "nuxi generate" 11 | }, 12 | "devDependencies": { 13 | "@antfu/eslint-config": "^0.26.3", 14 | "@iconify-json/carbon": "^1.1.8", 15 | "@iconify-json/twemoji": "^1.1.5", 16 | "@intlify/nuxt3": "^0.2.4", 17 | "@nuxtjs/color-mode": "^3.1.5", 18 | "@nuxtjs/tailwindcss": "^5.3.3", 19 | "@pinia/nuxt": "^0.4.2", 20 | "@vueuse/nuxt": "^9.2.0", 21 | "eslint": "^8.23.1", 22 | "nuxt": "^3.0.0-rc.11", 23 | "pinia": "^2.0.22", 24 | "tailwindcss-dark-mode": "^1.1.7", 25 | "typescript": "^4.8.3", 26 | "vue-i18n": "^9.2.2" 27 | }, 28 | "dependencies": { 29 | "@egjs/vue3-flicking": "^4.10.0", 30 | "@pinia-orm/nuxt": "^1.1.0", 31 | "primeicons": "^6.0.1", 32 | "primevue": "^3.17.0", 33 | "vue-cookies": "^1.8.1" 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /pages/404.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 30 | -------------------------------------------------------------------------------- /pages/blog/index.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 190 | -------------------------------------------------------------------------------- /pages/contact.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 |