Skip to content

Commit aeab7e6

Browse files
authored
Add heart portal HTML structure and styles
1 parent d5901d5 commit aeab7e6

1 file changed

Lines changed: 257 additions & 0 deletions

File tree

ForNicole/heart.html

Lines changed: 257 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,257 @@
1+
<!doctype html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="utf-8" />
5+
<meta name="viewport" content="width=device-width,initial-scale=1" />
6+
<title>For Nicole — Heart Portal</title>
7+
<meta name="color-scheme" content="light dark" />
8+
<style>
9+
:root{
10+
--bg: #1b1b23; /* default: comfy dark */
11+
--card: #232334;
12+
--text: #f5f7ff;
13+
--muted: #cfd6ffcc;
14+
--accent: #ff87b5; /* pink */
15+
--accent-2: #ffd1e6;
16+
--ring: #ffb3cf;
17+
--shadow: 0 10px 30px rgba(0,0,0,.35);
18+
}
19+
/* Seafoam theme */
20+
.theme-seafoam{
21+
--bg:#10221f; --card:#1a2f2b; --text:#eefbf5; --muted:#d1f5e8cc;
22+
--accent:#58e1b9; --accent-2:#bdf5e4; --ring:#8ff0d2;
23+
}
24+
/* Lavender theme */
25+
.theme-lavender{
26+
--bg:#1a1821; --card:#231f33; --text:#f7f2ff; --muted:#e1d9ffcc;
27+
--accent:#b08cff; --accent-2:#d8c7ff; --ring:#c8adff;
28+
}
29+
30+
/* Pink (default) uses :root variables above */
31+
32+
*{box-sizing:border-box}
33+
html,body{height:100%}
34+
body{
35+
margin:0; font-family: ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, "Helvetica Neue", Arial, "Apple Color Emoji", "Segoe UI Emoji";
36+
background:
37+
radial-gradient(60vmax 60vmax at 20% -20%, color-mix(in srgb, var(--accent) 24%, transparent) 0 50%, transparent 60%),
38+
radial-gradient(70vmax 70vmax at 120% 20%, color-mix(in srgb, var(--accent-2) 20%, transparent) 0 40%, transparent 60%),
39+
var(--bg);
40+
color:var(--text);
41+
display:grid; place-items:center;
42+
}
43+
.wrap{
44+
width:min(880px, 92vw);
45+
display:grid; gap:18px;
46+
padding:24px;
47+
}
48+
49+
.card{
50+
background:linear-gradient(180deg, color-mix(in srgb, var(--card) 90%, black 0%), var(--card));
51+
border:1px solid color-mix(in srgb, var(--ring) 22%, transparent);
52+
border-radius:24px;
53+
box-shadow:var(--shadow);
54+
padding: clamp(20px, 5vw, 34px);
55+
position:relative;
56+
overflow:hidden;
57+
isolation:isolate;
58+
}
59+
.title{
60+
margin:0 0 8px 0;
61+
font-size: clamp(20px, 3.6vw, 30px);
62+
letter-spacing:.2px;
63+
}
64+
.subtitle{
65+
margin:0 0 18px 0;
66+
color:var(--muted);
67+
font-size: clamp(14px, 2.2vw, 16px);
68+
}
69+
70+
/* Heart container */
71+
.heartbox{
72+
display:grid; place-items:center;
73+
margin:12px 0 20px 0;
74+
}
75+
svg{ width:min(320px, 68vw); height:auto; display:block; }
76+
77+
/* Pulse animation (respects reduced motion) */
78+
@media (prefers-reduced-motion:no-preference){
79+
.pulse{ animation: pulse 1800ms ease-in-out infinite; transform-origin: center; }
80+
@keyframes pulse{
81+
0%{ transform:scale(0.98); filter: drop-shadow(0 0 0 rgba(0,0,0,0)); }
82+
50%{ transform:scale(1.03); filter: drop-shadow(0 12px 24px rgba(0,0,0,.25)); }
83+
100%{ transform:scale(0.98); }
84+
}
85+
.sparkle{ animation: sparkle 6s linear infinite; }
86+
@keyframes sparkle{
87+
0%{ opacity:.0; transform:translateY(10px) scale(.9) rotate(0deg); }
88+
20%{ opacity:.7; }
89+
50%{ opacity:.0; transform:translateY(-40px) scale(1.1) rotate(180deg); }
90+
100%{ opacity:.0; transform:translateY(10px) scale(.9) rotate(360deg); }
91+
}
92+
}
93+
94+
/* Buttons */
95+
.buttons{
96+
display:grid; grid-template-columns: repeat(2, minmax(0,1fr));
97+
gap:12px;
98+
margin-top:8px;
99+
}
100+
@media (max-width:560px){ .buttons{ grid-template-columns:1fr; } }
101+
102+
.btn{
103+
--bg-btn: color-mix(in srgb, var(--accent) 18%, var(--card));
104+
--bg-btn-hover: color-mix(in srgb, var(--accent) 28%, var(--card));
105+
display:inline-flex; align-items:center; justify-content:center;
106+
gap:10px;
107+
border:1px solid color-mix(in srgb, var(--ring) 30%, transparent);
108+
border-radius:14px;
109+
padding:12px 14px;
110+
color:var(--text); text-decoration:none; font-weight:600;
111+
background: var(--bg-btn);
112+
box-shadow: 0 6px 16px rgba(0,0,0,.20);
113+
transition: transform .12s ease, background .15s ease, box-shadow .15s ease;
114+
outline: none;
115+
}
116+
.btn:hover, .btn:focus-visible{
117+
background: var(--bg-btn-hover);
118+
box-shadow: 0 10px 22px rgba(0,0,0,.28);
119+
transform: translateY(-1px);
120+
}
121+
.btn:active{ transform: translateY(0); }
122+
123+
/* Theme switcher row */
124+
.row{
125+
display:flex; flex-wrap:wrap; gap:10px; align-items:center; justify-content:space-between;
126+
margin-top:8px;
127+
}
128+
.swatch{
129+
width:36px; height:28px; border-radius:9px; border:1px solid color-mix(in srgb, var(--ring) 35%, transparent);
130+
cursor:pointer; display:inline-block;
131+
box-shadow: 0 4px 10px rgba(0,0,0,.2);
132+
}
133+
.swatch[data-theme="pink"]{ background: linear-gradient(180deg,#ff9ac2,#ff6ea7); }
134+
.swatch[data-theme="seafoam"]{ background: linear-gradient(180deg,#74f0c4,#34d1a6); }
135+
.swatch[data-theme="lavender"]{ background: linear-gradient(180deg,#c3b1ff,#9c7cff); }
136+
.swatch:focus-visible{ outline:2px solid var(--ring); outline-offset:2px; }
137+
138+
.note{ color:var(--muted); font-size:12px; margin-top:6px; }
139+
140+
/* Decorative sparkles (non-blocking) */
141+
.sparkle{
142+
position:absolute; inset:auto auto 18px 18px;
143+
width:80px; height:80px; pointer-events:none; opacity:.35;
144+
filter: drop-shadow(0 4px 10px rgba(0,0,0,.4));
145+
z-index:0;
146+
}
147+
.card > *{ position:relative; z-index:1; } /* keep content above sparkles */
148+
</style>
149+
</head>
150+
<body>
151+
<main class="wrap" id="app">
152+
<section class="card" aria-label="For Nicole — Heart Portal">
153+
<!-- Decorative sparkle -->
154+
<svg class="sparkle" viewBox="0 0 64 64" aria-hidden="true" focusable="false">
155+
<path fill="url(#g1)" d="M32 10l4 10 10 4-10 4-4 10-4-10-10-4 10-4 4-10z"/>
156+
<defs>
157+
<linearGradient id="g1" x1="0" y1="0" x2="1" y2="1">
158+
<stop offset="0" stop-color="var(--accent)"/>
159+
<stop offset="1" stop-color="var(--accent-2)"/>
160+
</linearGradient>
161+
</defs>
162+
</svg>
163+
164+
<h1 class="title">Hi Nicole — this is your heart portal</h1>
165+
<p class="subtitle">Tiny reps. Bright wins. A soft place to land and learn.</p>
166+
167+
<div class="heartbox" role="img" aria-label="A glowing animated heart">
168+
<!-- SVG Heart with gradient fill and soft pulse -->
169+
<svg viewBox="0 0 400 360" aria-hidden="true" class="pulse">
170+
<defs>
171+
<radialGradient id="heartGrad" cx="50%" cy="40%" r="70%">
172+
<stop offset="0%" stop-color="var(--accent-2)"/>
173+
<stop offset="70%" stop-color="var(--accent)"/>
174+
<stop offset="100%" stop-color="var(--accent)"/>
175+
</radialGradient>
176+
<filter id="glow" x="-40%" y="-40%" width="180%" height="180%">
177+
<feGaussianBlur stdDeviation="8" result="b"/>
178+
<feMerge>
179+
<feMergeNode in="b"/>
180+
<feMergeNode in="SourceGraphic"/>
181+
</feMerge>
182+
</filter>
183+
</defs>
184+
<!-- Heart path -->
185+
<path filter="url(#glow)" fill="url(#heartGrad)" d="
186+
M200,330
187+
C120,270 60,220 40,170
188+
C10,90 70,40 120,60
189+
C155,75 175,105 200,135
190+
C225,105 245,75 280,60
191+
C330,40 390,90 360,170
192+
C340,220 280,270 200,330 Z"/>
193+
</svg>
194+
</div>
195+
196+
<div class="buttons" role="group" aria-label="Quick actions">
197+
<a class="btn" href="javascript:void(0)" id="studydateBtn" aria-label="Open Study Date notebook">📓 Study Date</a>
198+
<a class="btn" href="https://github.com/DaScient/MakeItCute" target="_blank" rel="noopener" aria-label="Open MakeItCute Source">🌐 MakeItCute Source</a>
199+
<a class="btn" href="https://kdpreports.amazon.com/orders" target="_blank" rel="noopener" aria-label="Open Amazon KDP Orders">📈 KDP Orders</a>
200+
<a class="btn" href="https://www.tiktok.com/@nicollettesheart" target="_blank" rel="noopener" aria-label="Open Nicole’s TikTok">🎵 TikTok</a>
201+
</div>
202+
203+
<div class="row" aria-label="Theme picker">
204+
<div style="display:flex; gap:10px; align-items:center;">
205+
<span class="note" id="themeLabel">Theme:</span>
206+
<button class="swatch" data-theme="pink" aria-labelledby="themeLabel" title="Pink theme"></button>
207+
<button class="swatch" data-theme="seafoam" aria-labelledby="themeLabel" title="Seafoam theme"></button>
208+
<button class="swatch" data-theme="lavender" aria-labelledby="themeLabel" title="Lavender theme"></button>
209+
</div>
210+
<span class="note">Remembers your pick • Respects Reduced Motion</span>
211+
</div>
212+
</section>
213+
</main>
214+
215+
<script>
216+
(function(){
217+
const app = document.getElementById('app');
218+
219+
// Theme management
220+
const THEME_KEY = 'nicole-heart-theme';
221+
const applyTheme = (name) => {
222+
app.classList.remove('theme-seafoam','theme-lavender');
223+
if(name === 'seafoam') app.classList.add('theme-seafoam');
224+
if(name === 'lavender') app.classList.add('theme-lavender');
225+
localStorage.setItem(THEME_KEY, name);
226+
};
227+
const initial = localStorage.getItem(THEME_KEY) || 'pink';
228+
applyTheme(initial);
229+
230+
document.querySelectorAll('.swatch').forEach(btn=>{
231+
btn.addEventListener('click', ()=> applyTheme(btn.dataset.theme));
232+
btn.addEventListener('keydown', (e)=>{ if(e.key==='Enter' || e.key===' ') { e.preventDefault(); btn.click(); }});
233+
});
234+
235+
// Study Date: in a browser we can’t launch Jupyter, so we nudge kindly.
236+
const studyBtn = document.getElementById('studydateBtn');
237+
studyBtn.addEventListener('click', ()=>{
238+
alert([
239+
"Study Date opens in your terminal.",
240+
"Tip: in your pastel shell, type: studydate",
241+
"Or use the Learn Menu: Alt-m → 2"
242+
].join("\n"));
243+
});
244+
245+
// Respect reduced motion: pause pulse if user prefers less motion.
246+
const mq = window.matchMedia('(prefers-reduced-motion: reduce)');
247+
const toggleMotion = () => {
248+
document.querySelectorAll('.pulse').forEach(el=>{
249+
el.style.animationPlayState = mq.matches ? 'paused' : 'running';
250+
});
251+
};
252+
mq.addEventListener ? mq.addEventListener('change', toggleMotion) : mq.addListener(toggleMotion);
253+
toggleMotion();
254+
})();
255+
</script>
256+
</body>
257+
</html>

0 commit comments

Comments
 (0)