diff --git a/index.html b/index.html index 8df2b46..99b48ae 100644 --- a/index.html +++ b/index.html @@ -4,6 +4,9 @@ + + + Grateful Journal diff --git a/src/App.css b/src/App.css index dd3341e..1ea088c 100644 --- a/src/App.css +++ b/src/App.css @@ -160,62 +160,260 @@ .home-page { min-height: 100vh; min-height: 100dvh; - background: var(--color-bg-soft, #f1eee1); - padding: clamp(0.75rem, 3vw, 1.5rem); - padding-left: max(clamp(0.75rem, 3vw, 1.5rem), env(safe-area-inset-left)); - padding-right: max(clamp(0.75rem, 3vw, 1.5rem), env(safe-area-inset-right)); + background: + linear-gradient(135deg, rgba(241, 238, 225, 0.9) 0%, rgba(232, 245, 237, 0.85) 100%), + url('data:image/svg+xml,%3Csvg width="1920" height="1080" xmlns="http://www.w3.org/2000/svg"%3E%3Cdefs%3E%3CradialGradient id="g1" cx="30%25" cy="30%25"%3E%3Cstop offset="0%25" style="stop-color:%23c3fd2f;stop-opacity:0.15" /%3E%3Cstop offset="100%25" style="stop-color:%23c3fd2f;stop-opacity:0" /%3E%3C/radialGradient%3E%3CradialGradient id="g2" cx="70%25" cy="70%25"%3E%3Cstop offset="0%25" style="stop-color:%231be62c;stop-opacity:0.12" /%3E%3Cstop offset="100%25" style="stop-color:%231be62c;stop-opacity:0" /%3E%3C/radialGradient%3E%3C/defs%3E%3Crect fill="%23f1eee1" width="1920" height="1080"/%3E%3Cellipse cx="576" cy="324" rx="500" ry="500" fill="url(%23g1)" /%3E%3Cellipse cx="1344" cy="756" rx="400" rx="400" fill="url(%23g2)" /%3E%3C/svg%3E'); + background-size: cover; + background-position: center; + background-attachment: fixed; + padding: clamp(1rem, 3vw, 2rem); + padding-left: max(clamp(1rem, 3vw, 2rem), env(safe-area-inset-left)); + padding-right: max(clamp(1rem, 3vw, 2rem), env(safe-area-inset-right)); + position: relative; + overflow: hidden; +} + +/* Background decorative elements */ +.home-bg-decoration { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + pointer-events: none; + z-index: 0; + overflow: hidden; +} + +.bg-orb { + position: absolute; + border-radius: 50%; + filter: blur(100px); + opacity: 0.25; + mix-blend-mode: multiply; + animation: float 20s ease-in-out infinite; +} + +.bg-orb-1 { + width: 500px; + height: 500px; + background: radial-gradient(circle, rgba(27, 230, 44, 0.3) 0%, rgba(27, 230, 44, 0) 70%); + top: -150px; + left: -150px; + animation-delay: 0s; + animation-duration: 25s; +} + +.bg-orb-2 { + width: 400px; + height: 400px; + background: radial-gradient(circle, rgba(195, 253, 47, 0.25) 0%, rgba(195, 253, 47, 0) 70%); + bottom: -100px; + right: -100px; + animation-delay: -8s; + animation-duration: 30s; +} + +.bg-orb-3 { + width: 350px; + height: 350px; + background: radial-gradient(circle, rgba(207, 242, 220, 0.4) 0%, rgba(207, 242, 220, 0) 70%); + top: 50%; + right: 10%; + animation-delay: -15s; + animation-duration: 35s; +} + +@keyframes float { + 0%, 100% { + transform: translate(0, 0) scale(1); + } + 33% { + transform: translate(30px, -30px) scale(1.1); + } + 66% { + transform: translate(-20px, 20px) scale(0.9); + } +} + +.bg-pattern { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-image: + radial-gradient(circle at 20% 30%, rgba(27, 230, 44, 0.03) 0%, transparent 50%), + radial-gradient(circle at 80% 70%, rgba(195, 253, 47, 0.03) 0%, transparent 50%), + radial-gradient(circle at 40% 80%, rgba(207, 242, 220, 0.04) 0%, transparent 50%); + background-size: 100% 100%; +} + +/* Side decorative panels */ +.bg-pattern::before, +.bg-pattern::after { + content: ''; + position: absolute; + top: 0; + bottom: 0; + width: 250px; + opacity: 0.15; +} + +.bg-pattern::before { + left: 0; + background: linear-gradient( + to right, + rgba(27, 230, 44, 0.1) 0%, + rgba(207, 242, 220, 0.05) 50%, + transparent 100% + ); + -webkit-mask-image: repeating-linear-gradient( + to bottom, + black 0px, + black 3px, + transparent 3px, + transparent 6px + ); + mask-image: repeating-linear-gradient( + to bottom, + black 0px, + black 3px, + transparent 3px, + transparent 6px + ); +} + +.bg-pattern::after { + right: 0; + background: linear-gradient( + to left, + rgba(195, 253, 47, 0.08) 0%, + rgba(207, 242, 220, 0.05) 50%, + transparent 100% + ); + -webkit-mask-image: repeating-linear-gradient( + to bottom, + black 0px, + black 3px, + transparent 3px, + transparent 6px + ); + mask-image: repeating-linear-gradient( + to bottom, + black 0px, + black 3px, + transparent 3px, + transparent 6px + ); +} + +/* Decorative quote marks or subtle elements on sides */ +.home-page::before, +.home-page::after { + content: ''; + position: absolute; + width: 200px; + height: 200px; + background: radial-gradient(circle, rgba(27, 230, 44, 0.05) 0%, transparent 70%); + border-radius: 50%; + filter: blur(40px); + pointer-events: none; +} + +.home-page::before { + top: 20%; + left: 5%; + animation: pulse 8s ease-in-out infinite; +} + +.home-page::after { + bottom: 30%; + right: 5%; + animation: pulse 8s ease-in-out infinite; + animation-delay: -4s; +} + +@keyframes pulse { + 0%, 100% { + opacity: 0.3; + transform: scale(1); + } + 50% { + opacity: 0.5; + transform: scale(1.2); + } } .home-header { - max-width: 720px; - margin: 0 auto 1.5rem; + max-width: 680px; + margin: 0 auto 2rem; display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; - gap: 0.75rem; + gap: 1rem; + padding-bottom: 0.5rem; + position: relative; + z-index: 1; } .home-header h1 { margin: 0; - font-size: clamp(1.2rem, 3.5vw, 1.5rem); - color: var(--color-text, #1a1a1a); + font-size: clamp(1.25rem, 3.5vw, 1.625rem); + font-weight: 600; + color: #2d3748; + letter-spacing: -0.01em; word-break: break-word; + font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif; } .home-user { display: flex; align-items: center; - gap: 0.5rem; + gap: 0.75rem; flex-wrap: wrap; min-width: 0; } .home-username { font-weight: 500; - color: var(--color-text, #1a1a1a); + font-size: clamp(0.875rem, 2vw, 0.9375rem); + color: #4a5568; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; - max-width: min(50vw, 180px); + max-width: min(50vw, 200px); + font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif; } .home-sign-out { min-height: 44px; - padding: 0.5rem 0.75rem; + padding: 0.625rem 1.125rem; font-size: 0.875rem; - color: var(--color-text-muted, #555); - background: transparent; - border: 1px solid var(--color-border, #cff2dc); - border-radius: 6px; + font-weight: 500; + color: #4a5568; + background: rgba(255, 255, 255, 0.6); + border: 1px solid rgba(0, 0, 0, 0.08); + border-radius: 10px; cursor: pointer; - transition: background 0.2s, color 0.2s; + transition: all 0.2s ease; -webkit-tap-highlight-color: transparent; + backdrop-filter: blur(10px); + -webkit-backdrop-filter: blur(10px); + font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif; } .home-sign-out:hover { - background: var(--color-surface, #ffffff); - color: var(--color-text, #1a1a1a); + background: rgba(255, 255, 255, 0.85); + border-color: rgba(0, 0, 0, 0.12); + color: #2d3748; + transform: translateY(-1px); + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08); +} + +.home-sign-out:active { + transform: translateY(0); } .home-main { @@ -275,3 +473,1040 @@ max-width: none; } } + +/* ----- Journal writing interface ----- */ +.journal-container { + max-width: 680px; + margin: 0 auto; + min-width: 0; + position: relative; + z-index: 1; +} + +.journal-card { + background: rgba(255, 255, 255, 0.75); + backdrop-filter: blur(30px) saturate(180%); + -webkit-backdrop-filter: blur(30px) saturate(180%); + padding: clamp(2.5rem, 7vw, 4.5rem) clamp(2.5rem, 7vw, 4rem); + padding-bottom: clamp(3rem, 7vw, 4.5rem); + border-radius: 28px; + border: 1px solid rgba(255, 255, 255, 0.6); + box-shadow: + 0 8px 32px rgba(31, 38, 135, 0.15), + 0 2px 8px rgba(0, 0, 0, 0.04), + inset 0 1px 0 rgba(255, 255, 255, 0.9); + min-height: 70vh; + display: flex; + flex-direction: column; + position: relative; + overflow: hidden; +} + +.journal-card::before { + content: ''; + position: absolute; + top: 0; + left: 0; + right: 0; + height: 3px; + background: linear-gradient(90deg, + rgba(27, 230, 44, 0.6) 0%, + rgba(195, 253, 47, 0.5) 50%, + rgba(27, 230, 44, 0.6) 100%); + opacity: 0.7; + border-radius: 28px 28px 0 0; +} + +.journal-date { + margin: 0 0 2.5rem; + font-size: clamp(0.6875rem, 1.75vw, 0.75rem); + font-weight: 600; + letter-spacing: 0.15em; + color: rgba(27, 230, 44, 0.85); + text-transform: uppercase; + font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif; +} + +.journal-prompt { + margin: 0 0 3rem; + font-size: clamp(2rem, 5.5vw, 3.25rem); + font-weight: 600; + line-height: 1.2; + color: #2d3748; + letter-spacing: -0.015em; + font-family: 'Playfair Display', 'Georgia', 'Times New Roman', serif; +} + +.journal-writing-area { + flex: 1; + display: flex; + flex-direction: column; + gap: 2rem; + margin-bottom: 0; +} + +.journal-title-input { + width: 100%; + padding: 1.25rem 0; + font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif; + font-size: clamp(1.125rem, 2.75vw, 1.375rem); + font-weight: 500; + color: #2d3748; + background: transparent; + border: none; + border-bottom: 1px solid rgba(0, 0, 0, 0.06); + outline: none; + transition: all 0.3s ease; +} + +.journal-title-input::placeholder { + color: #cbd5e0; + font-weight: 400; + opacity: 0.65; + letter-spacing: 0.01em; +} + +.journal-title-input:focus { + border-bottom-color: rgba(27, 230, 44, 0.4); +} + +.journal-entry-textarea { + flex: 1; + width: 100%; + min-height: 300px; + padding: 1.25rem 0; + font-family: 'Lora', 'Georgia', 'Times New Roman', serif; + font-size: clamp(1.0625rem, 2.5vw, 1.1875rem); + line-height: 1.8; + color: #2d3748; + background: transparent; + border: none; + outline: none; + resize: none; + -webkit-font-smoothing: antialiased; + font-weight: 400; +} + +.journal-entry-textarea::placeholder { + color: #cbd5e0; + font-style: italic; + opacity: 0.45; +} + +.journal-actions { + display: flex; + align-items: center; + gap: 0.875rem; + margin-top: 1.75rem; + padding: 0; +} + +.journal-write-btn { + display: inline-flex; + align-items: center; + justify-content: center; + gap: 0.625rem; + min-height: 56px; + padding: 1rem 2.75rem; + font-size: clamp(0.9375rem, 2.25vw, 1rem); + font-weight: 600; + color: #fff; + background: linear-gradient(135deg, #6dd98b 0%, #1be62c 100%); + border: none; + border-radius: 100px; + cursor: pointer; + transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); + -webkit-tap-highlight-color: transparent; + box-shadow: + 0 4px 16px rgba(27, 230, 44, 0.25), + 0 2px 8px rgba(0, 0, 0, 0.08), + inset 0 1px 0 rgba(255, 255, 255, 0.2); + text-transform: none; + letter-spacing: 0.02em; + font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif; +} + +.journal-write-btn:hover:not(:disabled) { + transform: translateY(-2px); + box-shadow: + 0 6px 24px rgba(27, 230, 44, 0.3), + 0 3px 10px rgba(0, 0, 0, 0.1), + inset 0 1px 0 rgba(255, 255, 255, 0.25); + background: linear-gradient(135deg, #7de397 0%, #1ef030 100%); +} + +.journal-write-btn:active:not(:disabled) { + transform: translateY(0); + box-shadow: + 0 2px 8px rgba(27, 230, 44, 0.25), + 0 1px 4px rgba(0, 0, 0, 0.1); +} + +.journal-write-btn:disabled { + opacity: 0.5; + cursor: not-allowed; + transform: none; +} + +.journal-icon-btn { + display: inline-flex; + align-items: center; + justify-content: center; + width: 52px; + height: 52px; + min-height: 52px; + padding: 0; + font-size: 1.25rem; + background: rgba(255, 255, 255, 0.5); + backdrop-filter: blur(10px); + border: 1px solid rgba(0, 0, 0, 0.06); + border-radius: 14px; + cursor: pointer; + transition: all 0.2s ease; + -webkit-tap-highlight-color: transparent; + opacity: 0.7; +} + +.journal-icon-btn:hover { + background: rgba(255, 255, 255, 0.8); + border-color: rgba(0, 0, 0, 0.1); + opacity: 1; + transform: translateY(-2px); + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08); +} + +.journal-icon-btn:active { + transform: translateY(0); +} + +/* Button icon styling */ +.journal-write-btn svg, +.journal-icon-btn svg { + flex-shrink: 0; + display: block; +} + +/* Mobile adjustments */ +@media (max-width: 480px) { + .journal-card { + min-height: calc(100vh - 10rem); + padding: clamp(1.5rem, 5vw, 2rem); + border-radius: 16px; + } + + .journal-prompt { + margin-bottom: 2rem; + } + + .journal-entry-textarea { + min-height: 220px; + } + + /* Simplify background on mobile */ + .bg-orb { + filter: blur(60px); + opacity: 0.25; + } + + .bg-pattern::before, + .bg-pattern::after { + width: 100px; + opacity: 0.08; + } + + .home-page::before, + .home-page::after { + display: none; + } +} + +@media (max-width: 768px) { + .bg-pattern::before, + .bg-pattern::after { + width: 150px; + } +} + +/* ----- History Page ----- */ +.history-page { + min-height: 100vh; + min-height: 100dvh; + background: linear-gradient(135deg, rgba(241, 238, 225, 0.9) 0%, rgba(232, 245, 237, 0.85) 100%), + url('data:image/svg+xml,%3Csvg width="1920" height="1080" xmlns="http://www.w3.org/2000/svg"%3E%3Cdefs%3E%3CradialGradient id="g1" cx="30%25" cy="30%25"%3E%3Cstop offset="0%25" style="stop-color:%23c3fd2f;stop-opacity:0.15" /%3E%3Cstop offset="100%25" style="stop-color:%23c3fd2f;stop-opacity:0" /%3E%3C/radialGradient%3E%3CradialGradient id="g2" cx="70%25" cy="70%25"%3E%3Cstop offset="0%25" style="stop-color:%231be62c;stop-opacity:0.12" /%3E%3Cstop offset="100%25" style="stop-color:%231be62c;stop-opacity:0" /%3E%3C/radialGradient%3E%3C/defs%3E%3Crect fill="%23f1eee1" width="1920" height="1080"/%3E%3Cellipse cx="576" cy="324" rx="500" ry="500" fill="url(%23g1)" /%3E%3Cellipse cx="1344" cy="756" rx="400" rx="400" fill="url(%23g2)" /%3E%3C/svg%3E'); + background-size: cover; + background-position: center; + background-attachment: fixed; + padding: clamp(1rem, 3vw, 2rem); + padding-bottom: 90px; + padding-left: max(clamp(1rem, 3vw, 2rem), env(safe-area-inset-left)); + padding-right: max(clamp(1rem, 3vw, 2rem), env(safe-area-inset-right)); + position: relative; + overflow-x: hidden; +} + +.history-bg-decoration { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + pointer-events: none; + z-index: 0; + overflow: hidden; +} + +.history-header { + max-width: 680px; + margin: 0 auto 2rem; + display: flex; + align-items: flex-start; + justify-content: space-between; + gap: 1rem; + position: relative; + z-index: 1; +} + +.history-header-text h1 { + margin: 0 0 0.25rem; + font-size: clamp(2rem, 6vw, 2.5rem); + font-weight: 700; + color: #2d3748; + letter-spacing: -0.02em; + font-family: 'Playfair Display', 'Georgia', 'Times New Roman', serif; +} + +.history-subtitle { + margin: 0; + font-size: clamp(0.9375rem, 2.25vw, 1.0625rem); + color: #6b7280; + font-weight: 400; + font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif; +} + +.history-search-btn { + width: 48px; + height: 48px; + min-height: 48px; + display: flex; + align-items: center; + justify-content: center; + background: rgba(255, 255, 255, 0.6); + backdrop-filter: blur(10px); + -webkit-backdrop-filter: blur(10px); + border: 1px solid rgba(0, 0, 0, 0.06); + border-radius: 14px; + cursor: pointer; + transition: all 0.2s ease; + color: #4a5568; +} + +.history-search-btn:hover { + background: rgba(255, 255, 255, 0.85); + border-color: rgba(0, 0, 0, 0.1); + transform: translateY(-2px); + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08); +} + +.history-container { + max-width: 680px; + margin: 0 auto; + position: relative; + z-index: 1; +} + +/* Calendar Card */ +.calendar-card { + background: rgba(255, 255, 255, 0.75); + backdrop-filter: blur(30px) saturate(180%); + -webkit-backdrop-filter: blur(30px) saturate(180%); + padding: clamp(1.75rem, 5vw, 2.5rem); + border-radius: 24px; + border: 1px solid rgba(255, 255, 255, 0.6); + box-shadow: + 0 8px 32px rgba(31, 38, 135, 0.12), + 0 2px 8px rgba(0, 0, 0, 0.04), + inset 0 1px 0 rgba(255, 255, 255, 0.9); + margin-bottom: 2rem; +} + +.calendar-header { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 1.75rem; +} + +.calendar-month { + margin: 0; + font-size: clamp(1.25rem, 3.5vw, 1.5rem); + font-weight: 600; + color: #2d3748; + font-family: 'Playfair Display', 'Georgia', 'Times New Roman', serif; +} + +.calendar-nav { + display: flex; + gap: 0.5rem; +} + +.calendar-nav-btn { + width: 40px; + height: 40px; + display: flex; + align-items: center; + justify-content: center; + background: transparent; + border: 1px solid rgba(0, 0, 0, 0.06); + border-radius: 10px; + cursor: pointer; + color: #4a5568; + transition: all 0.2s ease; +} + +.calendar-nav-btn:hover { + background: rgba(0, 0, 0, 0.03); + border-color: rgba(0, 0, 0, 0.1); +} + +.calendar-grid { + display: grid; + grid-template-columns: repeat(7, 1fr); + gap: clamp(0.5rem, 2vw, 0.875rem); +} + +.calendar-weekday { + font-size: clamp(0.75rem, 2vw, 0.875rem); + font-weight: 500; + color: #9ca3af; + text-align: center; + padding: 0.5rem 0; + font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif; + letter-spacing: 0.02em; +} + +.calendar-day { + aspect-ratio: 1; + display: flex; + align-items: center; + justify-content: center; + font-size: clamp(0.9375rem, 2.25vw, 1.0625rem); + font-weight: 500; + color: #4a5568; + background: transparent; + border: none; + border-radius: 50%; + cursor: pointer; + transition: all 0.2s ease; + font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif; + position: relative; +} + +.calendar-day-empty { + cursor: default; +} + +.calendar-day:not(.calendar-day-empty):hover { + background: rgba(27, 230, 44, 0.08); + color: #2d3748; +} + +.calendar-day-has-entry { + background: rgba(27, 230, 44, 0.15); + color: #1be62c; + font-weight: 600; +} + +.calendar-day-has-entry:hover { + background: rgba(27, 230, 44, 0.25); +} + +.calendar-day-today { + background: #1be62c; + color: #fff; + font-weight: 700; +} + +.calendar-day-today:hover { + background: #18c925; +} + +/* Recent Entries */ +.recent-entries { + margin-bottom: 2rem; +} + +.recent-entries-title { + margin: 0 0 1.25rem; + font-size: clamp(0.6875rem, 1.75vw, 0.75rem); + font-weight: 600; + letter-spacing: 0.15em; + color: #9ca3af; + font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif; +} + +.entries-list { + display: flex; + flex-direction: column; + gap: 1rem; +} + +.entry-card { + background: rgba(255, 255, 255, 0.75); + backdrop-filter: blur(20px) saturate(180%); + -webkit-backdrop-filter: blur(20px) saturate(180%); + padding: clamp(1.25rem, 4vw, 1.75rem); + border-radius: 20px; + border: 1px solid rgba(255, 255, 255, 0.6); + border-left: 4px solid #1be62c; + box-shadow: + 0 4px 16px rgba(31, 38, 135, 0.08), + 0 1px 4px rgba(0, 0, 0, 0.02); + cursor: pointer; + transition: all 0.2s ease; + text-align: left; + width: 100%; +} + +.entry-card:hover { + transform: translateY(-2px); + box-shadow: + 0 8px 24px rgba(31, 38, 135, 0.12), + 0 2px 8px rgba(0, 0, 0, 0.04); + border-left-color: #18c925; +} + +.entry-header { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 0.75rem; + gap: 1rem; +} + +.entry-date { + font-size: clamp(0.6875rem, 1.75vw, 0.75rem); + font-weight: 600; + letter-spacing: 0.08em; + color: #1be62c; + font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif; +} + +.entry-time { + font-size: clamp(0.75rem, 1.85vw, 0.8125rem); + color: #9ca3af; + font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif; +} + +.entry-title { + margin: 0 0 0.5rem; + font-size: clamp(1.125rem, 2.75vw, 1.375rem); + font-weight: 600; + color: #2d3748; + line-height: 1.3; + font-family: 'Playfair Display', 'Georgia', 'Times New Roman', serif; +} + +.entry-preview { + margin: 0; + font-size: clamp(0.9375rem, 2.25vw, 1rem); + line-height: 1.6; + color: #6b7280; + font-family: 'Lora', 'Georgia', serif; + display: -webkit-box; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; + overflow: hidden; +} + +/* ----- Bottom Navigation ----- */ +.bottom-nav { + position: fixed; + bottom: 0; + left: 0; + right: 0; + background: rgba(255, 255, 255, 0.85); + backdrop-filter: blur(20px) saturate(180%); + -webkit-backdrop-filter: blur(20px) saturate(180%); + border-top: 1px solid rgba(0, 0, 0, 0.06); + padding: 0.75rem clamp(1rem, 3vw, 2rem); + padding-bottom: calc(0.75rem + env(safe-area-inset-bottom)); + display: flex; + align-items: center; + justify-content: space-around; + gap: 0.5rem; + z-index: 100; + box-shadow: 0 -2px 12px rgba(0, 0, 0, 0.04); +} + +.bottom-nav-btn { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + gap: 0.375rem; + padding: 0.625rem 1rem; + background: transparent; + border: none; + border-radius: 12px; + cursor: pointer; + color: #9ca3af; + transition: all 0.2s ease; + min-width: 70px; + font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif; +} + +.bottom-nav-btn svg { + width: 24px; + height: 24px; + stroke-width: 2; +} + +.bottom-nav-btn span { + font-size: 0.6875rem; + font-weight: 500; + letter-spacing: 0.01em; +} + +.bottom-nav-btn:hover { + color: #4a5568; + background: rgba(0, 0, 0, 0.02); +} + +.bottom-nav-btn-active { + color: #1be62c; + background: rgba(27, 230, 44, 0.08); +} + +.bottom-nav-btn-active:hover { + color: #18c925; + background: rgba(27, 230, 44, 0.12); +} + +/* Adjust home page for bottom nav */ +.home-page { + padding-bottom: 100px; +} + +/* Mobile adjustments for history */ +@media (max-width: 480px) { + .history-header-text h1 { + font-size: clamp(1.75rem, 6vw, 2rem); + } + + .calendar-card { + padding: clamp(1.25rem, 4vw, 1.75rem); + } + + .calendar-grid { + gap: clamp(0.375rem, 1.5vw, 0.5rem); + } + + .entry-card { + padding: 1.125rem; + } +} + +/* ----- Settings Page ----- */ +.settings-page { + min-height: 100vh; + min-height: 100dvh; + background: linear-gradient(135deg, rgba(241, 238, 225, 0.9) 0%, rgba(232, 245, 237, 0.85) 100%), + url('data:image/svg+xml,%3Csvg width="1920" height="1080" xmlns="http://www.w3.org/2000/svg"%3E%3Cdefs%3E%3CradialGradient id="g1" cx="30%25" cy="30%25"%3E%3Cstop offset="0%25" style="stop-color:%23c3fd2f;stop-opacity:0.15" /%3E%3Cstop offset="100%25" style="stop-color:%23c3fd2f;stop-opacity:0" /%3E%3C/radialGradient%3E%3CradialGradient id="g2" cx="70%25" cy="70%25"%3E%3Cstop offset="0%25" style="stop-color:%231be62c;stop-opacity:0.12" /%3E%3Cstop offset="100%25" style="stop-color:%231be62c;stop-opacity:0" /%3E%3C/radialGradient%3E%3C/defs%3E%3Crect fill="%23f1eee1" width="1920" height="1080"/%3E%3Cellipse cx="576" cy="324" rx="500" ry="500" fill="url(%23g1)" /%3E%3Cellipse cx="1344" cy="756" rx="400" rx="400" fill="url(%23g2)" /%3E%3C/svg%3E'); + background-size: cover; + background-position: center; + background-attachment: fixed; + padding: clamp(1rem, 3vw, 2rem); + padding-bottom: 100px; + padding-left: max(clamp(1rem, 3vw, 2rem), env(safe-area-inset-left)); + padding-right: max(clamp(1rem, 3vw, 2rem), env(safe-area-inset-right)); + position: relative; + overflow-x: hidden; +} + +.settings-bg-decoration { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + pointer-events: none; + z-index: 0; + overflow: hidden; +} + +.settings-header { + max-width: 680px; + margin: 0 auto 2rem; + position: relative; + z-index: 1; +} + +.settings-header-text h1 { + margin: 0 0 0.25rem; + font-size: clamp(2rem, 6vw, 2.5rem); + font-weight: 700; + color: #2d3748; + letter-spacing: -0.02em; + font-family: 'Playfair Display', 'Georgia', 'Times New Roman', serif; +} + +.settings-subtitle { + margin: 0; + font-size: clamp(0.9375rem, 2.25vw, 1.0625rem); + color: #6b7280; + font-weight: 400; + font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif; +} + +.settings-container { + max-width: 680px; + margin: 0 auto; + position: relative; + z-index: 1; +} + +/* Profile Section */ +.settings-profile { + display: flex; + align-items: center; + gap: 1.25rem; + margin-bottom: 2.5rem; +} + +.settings-avatar { + width: 80px; + height: 80px; + flex-shrink: 0; +} + +.settings-avatar-img { + width: 100%; + height: 100%; + border-radius: 50%; + object-fit: cover; + border: 3px solid rgba(255, 255, 255, 0.8); + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); +} + +.settings-avatar-placeholder { + width: 100%; + height: 100%; + border-radius: 50%; + background: linear-gradient(135deg, #f8ceec 0%, #f4b6d3 100%); + display: flex; + align-items: center; + justify-content: center; + font-size: 2rem; + font-weight: 600; + color: #fff; + border: 3px solid rgba(255, 255, 255, 0.8); + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); +} + +.settings-profile-info { + flex: 1; + min-width: 0; +} + +.settings-profile-name { + margin: 0 0 0.5rem; + font-size: clamp(1.25rem, 3vw, 1.5rem); + font-weight: 600; + color: #2d3748; + font-family: 'Playfair Display', 'Georgia', 'Times New Roman', serif; +} + +.settings-profile-badge { + display: inline-block; + padding: 0.375rem 0.875rem; + font-size: 0.75rem; + font-weight: 700; + letter-spacing: 0.05em; + color: #166534; + background: rgba(27, 230, 44, 0.2); + border-radius: 100px; + font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif; +} + +/* Settings Sections */ +.settings-section { + margin-bottom: 2rem; +} + +.settings-section-title { + margin: 0 0 1rem; + font-size: clamp(0.6875rem, 1.75vw, 0.75rem); + font-weight: 600; + letter-spacing: 0.15em; + color: #9ca3af; + font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif; +} + +.settings-card { + background: rgba(255, 255, 255, 0.75); + backdrop-filter: blur(30px) saturate(180%); + -webkit-backdrop-filter: blur(30px) saturate(180%); + border-radius: 20px; + border: 1px solid rgba(255, 255, 255, 0.6); + box-shadow: + 0 8px 32px rgba(31, 38, 135, 0.12), + 0 2px 8px rgba(0, 0, 0, 0.04), + inset 0 1px 0 rgba(255, 255, 255, 0.9); + overflow: hidden; +} + +/* Settings Items */ +.settings-item { + display: flex; + align-items: center; + gap: 1rem; + padding: 1.25rem 1.5rem; + background: transparent; + border: none; + width: 100%; + text-align: left; +} + +.settings-item-button { + cursor: pointer; + transition: background 0.2s ease; +} + +.settings-item-button:hover { + background: rgba(0, 0, 0, 0.02); +} + +.settings-item-icon { + width: 48px; + height: 48px; + flex-shrink: 0; + display: flex; + align-items: center; + justify-content: center; + border-radius: 12px; +} + +.settings-item-icon-green { + background: rgba(27, 230, 44, 0.12); + color: #1be62c; +} + +.settings-item-icon-gray { + background: rgba(107, 114, 128, 0.12); + color: #6b7280; +} + +.settings-item-icon-orange { + background: rgba(251, 146, 60, 0.12); + color: #f97316; +} + +.settings-item-icon-blue { + background: rgba(59, 130, 246, 0.12); + color: #3b82f6; +} + +.settings-item-content { + flex: 1; + min-width: 0; +} + +.settings-item-title { + margin: 0 0 0.25rem; + font-size: clamp(1rem, 2.5vw, 1.125rem); + font-weight: 600; + color: #2d3748; + font-family: 'Playfair Display', 'Georgia', 'Times New Roman', serif; +} + +.settings-item-subtitle { + margin: 0; + font-size: clamp(0.8125rem, 2vw, 0.875rem); + color: #9ca3af; + font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif; +} + +.settings-item-arrow { + flex-shrink: 0; + color: #cbd5e0; +} + +.settings-divider { + height: 1px; + background: rgba(0, 0, 0, 0.06); + margin: 0 1.5rem; +} + +/* Toggle Switch */ +.settings-toggle { + position: relative; + display: inline-block; + width: 52px; + height: 32px; + flex-shrink: 0; +} + +.settings-toggle input { + opacity: 0; + width: 0; + height: 0; +} + +.settings-toggle-slider { + position: absolute; + cursor: pointer; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: #cbd5e0; + transition: 0.3s; + border-radius: 100px; +} + +.settings-toggle-slider:before { + position: absolute; + content: ""; + height: 24px; + width: 24px; + left: 4px; + bottom: 4px; + background: white; + transition: 0.3s; + border-radius: 50%; + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); +} + +.settings-toggle input:checked + .settings-toggle-slider { + background: #1be62c; +} + +.settings-toggle input:checked + .settings-toggle-slider:before { + transform: translateX(20px); +} + +/* Theme Colors */ +.settings-theme-colors { + display: flex; + gap: 0.5rem; + margin-right: 0.5rem; +} + +.settings-theme-dot { + width: 24px; + height: 24px; + border-radius: 50%; + border: 2px solid rgba(0, 0, 0, 0.1); + cursor: pointer; + transition: all 0.2s ease; +} + +.settings-theme-dot-beige { + background: #f1eee1; +} + +.settings-theme-dot-dark { + background: #1a1a1a; +} + +.settings-theme-dot:hover { + transform: scale(1.1); + border-color: rgba(0, 0, 0, 0.2); +} + +/* Clear Data Button */ +.settings-clear-btn { + width: 100%; + display: flex; + align-items: center; + justify-content: space-between; + padding: 1.25rem 1.5rem; + margin-bottom: 1rem; + font-size: clamp(0.9375rem, 2.25vw, 1rem); + font-weight: 600; + color: #dc2626; + background: rgba(255, 255, 255, 0.75); + backdrop-filter: blur(20px) saturate(180%); + -webkit-backdrop-filter: blur(20px) saturate(180%); + border: 1px solid rgba(255, 255, 255, 0.6); + border-radius: 16px; + cursor: pointer; + transition: all 0.2s ease; + font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif; + box-shadow: 0 4px 12px rgba(220, 38, 38, 0.08); +} + +.settings-clear-btn:hover { + background: rgba(254, 226, 226, 0.9); + border-color: rgba(220, 38, 38, 0.2); + transform: translateY(-1px); + box-shadow: 0 6px 16px rgba(220, 38, 38, 0.12); +} + +.settings-clear-btn svg { + flex-shrink: 0; +} + +/* Sign Out Button */ +.settings-signout-btn { + width: 100%; + padding: 1rem; + margin-bottom: 1.5rem; + font-size: clamp(0.9375rem, 2.25vw, 1rem); + font-weight: 600; + color: #4a5568; + background: rgba(255, 255, 255, 0.6); + backdrop-filter: blur(20px); + -webkit-backdrop-filter: blur(20px); + border: 1px solid rgba(0, 0, 0, 0.08); + border-radius: 14px; + cursor: pointer; + transition: all 0.2s ease; + font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif; +} + +.settings-signout-btn:hover { + background: rgba(255, 255, 255, 0.85); + border-color: rgba(0, 0, 0, 0.12); + color: #2d3748; + transform: translateY(-1px); + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08); +} + +/* Version */ +.settings-version { + text-align: center; + font-size: 0.6875rem; + font-weight: 500; + letter-spacing: 0.08em; + color: #cbd5e0; + margin: 2rem 0 0; + font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif; +} + +/* Mobile adjustments for settings */ +@media (max-width: 480px) { + .settings-header-text h1 { + font-size: clamp(1.75rem, 6vw, 2rem); + } + + .settings-profile { + margin-bottom: 2rem; + } + + .settings-avatar { + width: 64px; + height: 64px; + } + + .settings-item { + padding: 1rem 1.25rem; + } + + .settings-item-icon { + width: 44px; + height: 44px; + } +} + + diff --git a/src/App.tsx b/src/App.tsx index e014b3b..afe9b3c 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -2,6 +2,8 @@ import { BrowserRouter, Routes, Route, Navigate } from 'react-router-dom' import { AuthProvider } from './contexts/AuthContext' import { ProtectedRoute } from './components/ProtectedRoute' import HomePage from './pages/HomePage' +import HistoryPage from './pages/HistoryPage' +import SettingsPage from './pages/SettingsPage' import LoginPage from './pages/LoginPage' import './App.css' @@ -18,6 +20,22 @@ function App() { } /> + + + + } + /> + + + + } + /> } /> } /> diff --git a/src/components/BottomNav.tsx b/src/components/BottomNav.tsx new file mode 100644 index 0000000..ec56a81 --- /dev/null +++ b/src/components/BottomNav.tsx @@ -0,0 +1,48 @@ +import { useNavigate, useLocation } from 'react-router-dom' + +export default function BottomNav() { + const navigate = useNavigate() + const location = useLocation() + + const isActive = (path: string) => location.pathname === path + + return ( + + ) +} diff --git a/src/index.css b/src/index.css index f67d0ee..94f9e9d 100644 --- a/src/index.css +++ b/src/index.css @@ -1,4 +1,4 @@ -/* Grateful Journal – green palette from Coolors */ +/* Grateful Journal – enhanced green palette */ *, *::before, *::after { @@ -6,7 +6,7 @@ } :root { - font-family: system-ui, -apple-system, sans-serif; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif; line-height: 1.5; font-weight: 400; /* Responsive base: 16px at 320px, scales up to 18px by 768px */ @@ -19,7 +19,7 @@ --color-accent-light: #cff2dc; --color-accent-bright: #c3fd2f; --color-text: #1a1a1a; - --color-text-muted: #555; + --color-text-muted: #6b7280; --color-border: #cff2dc; color: var(--color-text); diff --git a/src/pages/HistoryPage.tsx b/src/pages/HistoryPage.tsx new file mode 100644 index 0000000..eb92a45 --- /dev/null +++ b/src/pages/HistoryPage.tsx @@ -0,0 +1,180 @@ +import { useState } from 'react' +import BottomNav from '../components/BottomNav' + +interface JournalEntry { + id: string + date: Date + title: string + content: string +} + +export default function HistoryPage() { + const [currentMonth, setCurrentMonth] = useState(new Date()) + + // Mock data - replace with actual Firebase data later + const mockEntries: JournalEntry[] = [ + { + id: '1', + date: new Date(2026, 1, 12), + title: 'Feeling much lighter today', + content: 'After the long conversation yesterday, I woke up with a sense of clarity I haven\'t felt in weeks...' + }, + { + id: '2', + date: new Date(2026, 1, 5), + title: 'Morning thoughts', + content: 'The coffee smells amazing this morning. Simple pleasures like this remind me...' + } + ] + + const getDaysInMonth = (date: Date) => { + const year = date.getFullYear() + const month = date.getMonth() + const firstDay = new Date(year, month, 1) + const lastDay = new Date(year, month + 1, 0) + const daysInMonth = lastDay.getDate() + const startingDayOfWeek = firstDay.getDay() + + return { daysInMonth, startingDayOfWeek } + } + + const hasEntryOnDate = (day: number) => { + return mockEntries.some(entry => { + const entryDate = new Date(entry.date) + return entryDate.getDate() === day && + entryDate.getMonth() === currentMonth.getMonth() && + entryDate.getFullYear() === currentMonth.getFullYear() + }) + } + + const isToday = (day: number) => { + const today = new Date() + return day === today.getDate() && + currentMonth.getMonth() === today.getMonth() && + currentMonth.getFullYear() === today.getFullYear() + } + + const formatDate = (date: Date) => { + return date.toLocaleDateString('en-US', { + weekday: 'short', + month: 'short', + day: '2-digit' + }).toUpperCase() + } + + const formatTime = (date: Date) => { + return date.toLocaleTimeString('en-US', { + hour: '2-digit', + minute: '2-digit' + }).toUpperCase() + } + + const { daysInMonth, startingDayOfWeek } = getDaysInMonth(currentMonth) + const monthName = currentMonth.toLocaleDateString('en-US', { month: 'long', year: 'numeric' }) + + const previousMonth = () => { + setCurrentMonth(new Date(currentMonth.getFullYear(), currentMonth.getMonth() - 1)) + } + + const nextMonth = () => { + setCurrentMonth(new Date(currentMonth.getFullYear(), currentMonth.getMonth() + 1)) + } + + return ( +
+
+
+
+
+
+ +
+
+

History

+

Your past reflections

+
+ +
+ +
+
+
+

{monthName}

+
+ + +
+
+ +
+
S
+
M
+
T
+
W
+
T
+
F
+
S
+ + {Array.from({ length: startingDayOfWeek }).map((_, i) => ( +
+ ))} + + {Array.from({ length: daysInMonth }).map((_, i) => { + const day = i + 1 + const hasEntry = hasEntryOnDate(day) + const isTodayDate = isToday(day) + + return ( + + ) + })} +
+
+ +
+

RECENT ENTRIES

+ +
+ {mockEntries.map(entry => ( + + ))} +
+
+
+ + +
+ ) +} diff --git a/src/pages/HomePage.tsx b/src/pages/HomePage.tsx index 021bd9d..1639f21 100644 --- a/src/pages/HomePage.tsx +++ b/src/pages/HomePage.tsx @@ -1,8 +1,12 @@ import { useAuth } from '../contexts/AuthContext' import { Link } from 'react-router-dom' +import { useState } from 'react' +import BottomNav from '../components/BottomNav' export default function HomePage() { const { user, loading, signOut } = useAuth() + const [entry, setEntry] = useState('') + const [title, setTitle] = useState('') if (loading) { return ( @@ -24,11 +28,32 @@ export default function HomePage() { ) } - const displayName = - user.displayName ?? user.email ?? 'there' + const displayName = user.displayName ?? user.email ?? 'there' + + // Get current date formatted like "THURSDAY, OCT 24" + const today = new Date() + const dateString = today.toLocaleDateString('en-US', { + weekday: 'long', + month: 'short', + day: 'numeric' + }).toUpperCase() + + const handleWrite = () => { + console.log('Saving entry:', { title, entry }) + // TODO: Save to Firebase + setTitle('') + setEntry('') + } return (
+
+
+
+
+
+
+

Grateful Journal

@@ -38,10 +63,32 @@ export default function HomePage() {
-
-

Hello, {displayName}.

-

Your writing space will go here.

+ +
+
+
{dateString}
+ +

What are you grateful for today?

+ +
+ setTitle(e.target.value)} + /> +