diff --git a/src/app/page.tsx b/src/app/PortfolioApp.tsx similarity index 100% rename from src/app/page.tsx rename to src/app/PortfolioApp.tsx diff --git a/src/main.tsx b/src/main.tsx index 171d58a..93a9ac7 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -1,6 +1,6 @@ import { StrictMode } from 'react'; import { createRoot } from 'react-dom/client'; -import PortfolioApp from './app/page.tsx'; +import PortfolioApp from './app/PortfolioApp.tsx'; createRoot(document.getElementById('root')!).render( diff --git a/src/scss/contact-section.scss b/src/scss/contact-section.scss new file mode 100644 index 0000000..cccc3f8 --- /dev/null +++ b/src/scss/contact-section.scss @@ -0,0 +1,279 @@ +@use 'globals'; + +.contact-section { + background: var(--contact-background); + + &__container { + max-width: 80rem; + margin: 0 auto; + padding: 0 1rem; + + @include globals.desktop-only { + padding: 0 1.5rem; + } + } + + &__header { + text-align: center; + margin-bottom: 4rem; + } + + &__title { + font-size: 1.875rem; + font-weight: bold; + margin-bottom: 1rem; + background: var(--gradient-contact-title); + background-clip: text; + -webkit-background-clip: text; + color: transparent; + -webkit-text-fill-color: transparent; + + @include globals.desktop-only { + font-size: 2.25rem; + } + } + + &__subtitle { + font-size: 1.25rem; + color: var(--color-text-muted); + max-width: 48rem; + margin: 0 auto; + } + + &__grid { + display: grid; + grid-template-columns: 1fr; + gap: 3rem; + + @include globals.desktop-only { + grid-template-columns: 1fr 1fr; + } + } + + // Contact Info Section + &__info { + display: flex; + flex-direction: column; + gap: 2rem; + } + + &__connect-title { + font-size: 1.5rem; + font-weight: 600; + color: var(--color-text); + margin-bottom: 1.5rem; + } + + &__connect-description { + color: var(--color-text-muted); + line-height: 1.6; + margin-bottom: 2rem; + } + + &__details { + display: flex; + flex-direction: column; + gap: 1rem; + } + + &__detail-item { + display: flex; + align-items: center; + gap: 1rem; + } + + &__detail-icon { + width: 1.25rem; + height: 1.25rem; + color: var(--color-contact-primary); + flex-shrink: 0; + } + + &__detail-text { + color: var(--color-text); + font-size: 0.875rem; + } + + &__social { + display: flex; + gap: 1rem; + margin-top: 1rem; + } + + &__social-button { + display: flex; + align-items: center; + justify-content: center; + width: 2.5rem; + height: 2.5rem; + border: 1px solid var(--contact-social-border); + border-radius: 0.375rem; + background: var(--contact-social-bg); + color: var(--contact-social-text); + text-decoration: none; + transition: all 0.2s ease; + + &:hover { + background: var(--contact-social-hover-bg); + border-color: var(--contact-social-hover-border); + transform: translateY(-1px); + } + } + + &__social-icon { + width: 1rem; + height: 1rem; + } + + // Contact Form Section + &__form-card { + background: var(--contact-form-bg); + border: 1px solid var(--contact-form-border); + border-radius: 1rem; + box-shadow: var(--contact-form-shadow); + overflow: hidden; + } + + &__form-header { + padding: 1.5rem 1.5rem 0; + margin-bottom: 1.5rem; + } + + &__form-title { + font-size: 1.25rem; + font-weight: 600; + color: var(--color-text); + margin-bottom: 0.5rem; + } + + &__form-description { + color: var(--color-text-muted); + font-size: 0.875rem; + } + + &__form { + padding: 0 1.5rem 1.5rem; + display: flex; + flex-direction: column; + gap: 1rem; + } + + // Honeypot field - hidden from users but visible to bots + &__honeypot { + position: absolute; + left: -9999px; + width: 1px; + height: 1px; + overflow: hidden; + opacity: 0; + } + + &__honeypot-label, + &__honeypot-input { + position: absolute; + left: -9999px; + width: 1px; + height: 1px; + overflow: hidden; + opacity: 0; + } + + &__form-row { + display: grid; + grid-template-columns: 1fr; + gap: 1rem; + + @include globals.mobile-only { + grid-template-columns: 1fr 1fr; + } + } + + &__form-group { + display: flex; + flex-direction: column; + gap: 0.5rem; + } + + &__form-label { + font-size: 0.875rem; + font-weight: 500; + color: var(--color-text); + } + + &__form-input, + &__form-textarea { + padding: 0.75rem; + border: 1px solid var(--contact-input-border); + border-radius: 0.375rem; + background: var(--contact-input-bg); + color: var(--color-text); + font-size: 0.875rem; + transition: all 0.2s ease; + + &::placeholder { + color: var(--color-text-muted); + } + + &:focus { + outline: none; + border-color: var(--color-contact-primary); + box-shadow: 0 0 0 3px var(--contact-input-focus-ring); + } + } + + &__form-textarea { + resize: vertical; + min-height: 5rem; + font-family: inherit; + } + + &__form-button { + background: var(--contact-button-bg); + color: var(--contact-button-text); + border: none; + border-radius: 0.375rem; + padding: 0.75rem 1.5rem; + font-size: 0.875rem; + font-weight: 500; + cursor: pointer; + transition: all 0.2s ease; + margin-top: 0.5rem; + + &:hover:not(:disabled) { + background: var(--contact-button-hover-bg); + transform: translateY(-1px); + } + + &:active:not(:disabled) { + transform: translateY(0); + } + + &:disabled { + opacity: 0.6; + cursor: not-allowed; + transform: none; + } + } + + // Responsive adjustments + @include globals.mobile-only { + &__grid { + gap: 2rem; + } + + &__form-card { + border-radius: 0.75rem; + } + + &__form-header, + &__form { + padding-left: 1rem; + padding-right: 1rem; + } + + &__social { + justify-content: center; + margin-top: 1.5rem; + } + } +} diff --git a/src/scss/projects-section.scss b/src/scss/projects-section.scss new file mode 100644 index 0000000..1bdae2b --- /dev/null +++ b/src/scss/projects-section.scss @@ -0,0 +1,211 @@ +@use 'globals'; + +.projects-section { + background: var(--projects-background); + + &__container { + max-width: 80rem; + margin: 0 auto; + padding: 0 1rem; + + @include globals.desktop-only { + padding: 0 1.5rem; + } + } + + &__header { + text-align: center; + margin-bottom: 4rem; + } + + &__title { + font-size: 1.875rem; + font-weight: bold; + margin-bottom: 1rem; + background: var(--gradient-projects-title); + background-clip: text; + -webkit-background-clip: text; + color: transparent; + -webkit-text-fill-color: transparent; + + @include globals.desktop-only { + font-size: 2.25rem; + } + } + + &__subtitle { + font-size: 1.25rem; + color: var(--color-text-muted); + max-width: 48rem; + margin: 0 auto; + } + + &__grid { + display: grid; + grid-template-columns: repeat(1, 1fr); + gap: 2rem; + + @include globals.mobile-only { + grid-template-columns: repeat(2, 1fr); + } + + @include globals.desktop-only { + grid-template-columns: repeat(3, 1fr); + } + } + + &__card { + background: var(--projects-card-background); + border-radius: 1rem; + box-shadow: var(--projects-card-shadow); + overflow: hidden; + transition: all 0.3s ease; + border: 1px solid var(--projects-card-border); + + &:hover { + transform: translateY(-0.25rem); + box-shadow: var(--projects-card-shadow-hover); + + .projects-section__image { + transform: scale(1.05); + } + + .projects-section__overlay { + opacity: 1; + } + } + } + + &__image-container { + position: relative; + overflow: hidden; + height: 12rem; + } + + &__image { + width: 100%; + height: 100%; + object-fit: cover; + transition: transform 0.3s ease; + } + + &__overlay { + position: absolute; + inset: 0; + background: var(--projects-overlay-background); + opacity: 0; + transition: opacity 0.3s ease; + display: flex; + align-items: center; + justify-content: center; + } + + &__actions { + display: flex; + gap: 1rem; + } + + &__action-button { + display: inline-flex; + align-items: center; + gap: 0.5rem; + padding: 0.5rem 1rem; + border-radius: 0.375rem; + font-size: 0.875rem; + font-weight: 500; + text-decoration: none; + transition: all 0.2s ease; + border: 1px solid transparent; + + &--primary { + background: var(--projects-button-primary-bg); + color: var(--projects-button-primary-text); + border-color: var(--projects-button-primary-border); + + &:hover { + background: var(--projects-button-primary-hover-bg); + transform: translateY(-1px); + } + } + + &--secondary { + background: var(--projects-button-secondary-bg); + color: var(--projects-button-secondary-text); + border-color: var(--projects-button-secondary-border); + + &:hover { + background: var(--projects-button-secondary-hover-bg); + transform: translateY(-1px); + } + } + } + + &__action-icon { + width: 1rem; + height: 1rem; + } + + &__content { + padding: 1.5rem; + } + + &__header-content { + margin-bottom: 1.5rem; + } + + &__card-title { + font-size: 1.125rem; + font-weight: 600; + color: var(--color-text); + margin-bottom: 0.5rem; + line-height: 1.4; + } + + &__card-description { + color: var(--color-text-muted); + font-size: 0.875rem; + line-height: 1.5; + } + + &__technologies { + display: flex; + flex-wrap: wrap; + gap: 0.5rem; + } + + &__tech-badge { + display: inline-block; + background: var(--projects-tech-badge-bg); + color: var(--projects-tech-badge-text); + padding: 0.25rem 0.75rem; + border-radius: 9999px; + font-size: 0.75rem; + font-weight: 500; + border: 1px solid var(--projects-tech-badge-border); + } + + // Responsive adjustments + @include globals.mobile-only { + &__card { + border-radius: 0.75rem; + } + + &__content { + padding: 1rem; + } + + &__image-container { + height: 10rem; + } + + &__actions { + flex-direction: column; + gap: 0.75rem; + } + + &__action-button { + justify-content: center; + padding: 0.75rem 1rem; + } + } +}