tbaro commited on
Commit
af32bc7
·
verified ·
1 Parent(s): 2eb27f6

Upload 14 files

Browse files
.gitattributes CHANGED
@@ -33,3 +33,11 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
 
 
 
 
 
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ IMG_9450.jpg filter=lfs diff=lfs merge=lfs -text
37
+ IMG_9451.jpg filter=lfs diff=lfs merge=lfs -text
38
+ IMG_9453.jpg filter=lfs diff=lfs merge=lfs -text
39
+ IMG_9461.jpg filter=lfs diff=lfs merge=lfs -text
40
+ IMG_9547.jpg filter=lfs diff=lfs merge=lfs -text
41
+ pngegg.png filter=lfs diff=lfs merge=lfs -text
42
+ z7273034591306_f2041027e92ac75073dc44d48a044a19.jpg filter=lfs diff=lfs merge=lfs -text
43
+ z7273040168526_69abfd03e0779e60ce9b0b181353a68b.jpg filter=lfs diff=lfs merge=lfs -text
5f5e9622-f3f6-49e9-bfd3-886ffc2d9496.jpg ADDED
IMG_9450.jpg ADDED

Git LFS Details

  • SHA256: d7893c8584d172c8338590fadb160dd9fd56545f52deb6fc8c02be040a80d03c
  • Pointer size: 132 Bytes
  • Size of remote file: 8.15 MB
IMG_9451.jpg ADDED

Git LFS Details

  • SHA256: 04b3f705b280e455fe16ef4507fcf95cd48e6ca16345205d01decbeeaa7eb187
  • Pointer size: 132 Bytes
  • Size of remote file: 8.24 MB
IMG_9453.jpg ADDED

Git LFS Details

  • SHA256: 9e116fffd56e8b12b98f6832729f0217fbe3ca4771440e2cd978350806575727
  • Pointer size: 132 Bytes
  • Size of remote file: 7.89 MB
IMG_9461.jpg ADDED

Git LFS Details

  • SHA256: f464f4b2ccbfbb96a8e6adeb2609dcc1cd074b76d89324557675d82a1fd5cf19
  • Pointer size: 132 Bytes
  • Size of remote file: 6.45 MB
IMG_9547.jpg ADDED

Git LFS Details

  • SHA256: 82d481d8fc32642defa99ddedfa654533978f08834ad83e8f442728d4ccc1c09
  • Pointer size: 133 Bytes
  • Size of remote file: 11.3 MB
README.md CHANGED
@@ -1,10 +1,22 @@
1
- ---
2
- title: Noel
3
- emoji: 💻
4
- colorFrom: red
5
- colorTo: blue
6
- sdk: static
7
- pinned: false
8
- ---
9
-
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ title: Merry Christmas em iu của anh
3
+ emoji: 🎄
4
+ colorFrom: green
5
+ colorTo: blue
6
+ sdk: static
7
+ pinned: false
8
+ ---
9
+
10
+ This project is a client-side Christmas page and can be deployed as a **Static HTML** Hugging Face Space.
11
+
12
+ Quick steps to deploy on Hugging Face Spaces (Static HTML):
13
+
14
+ 1. Create a new Space at https://huggingface.co/spaces and choose "Static HTML" as the SDK.
15
+ 2. Push this repository to the new Space (the repo should contain `index.html` at the project root and assets at the repo root: `main.js`, `style.css`, `pngegg.png` and the image files).
16
+ 3. No `requirements.txt` is required for a static Space.
17
+
18
+ Notes:
19
+ - I updated asset paths in `static/main.js` to be relative so the app works when served statically.
20
+ - You can remove `app.py` (Flask) if you plan to host as a static Space; keep it if you want to run locally with Flask.
21
+
22
+ If you'd rather convert this to a Gradio or Streamlit-based Space (so you can add Python-powered interactivity), tell me and I can scaffold that for you.
app.py ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from flask import Flask, render_template, send_from_directory
2
+ import os
3
+
4
+ app = Flask(__name__)
5
+
6
+ @app.route('/')
7
+ def index():
8
+ return render_template('index.html')
9
+
10
+ @app.route('/images/<path:filename>')
11
+ def images(filename):
12
+ # After flattening repository, images are at the project root. Serve from root.
13
+ return send_from_directory(app.root_path, filename)
14
+
15
+ @app.route('/pngegg.png')
16
+ def tree_png():
17
+ return send_from_directory(app.root_path, 'pngegg.png')
18
+
19
+ if __name__ == '__main__':
20
+ app.run(host='0.0.0.0', port=5000, debug=True)
index.html CHANGED
@@ -1,19 +1,32 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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.0">
6
+ <title>Merry Christmas em iu của anh</title>
7
+ <link href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css" rel="stylesheet">
8
+ <link rel="stylesheet" href="/style.css">
9
+ </head>
10
+ <body class="bg-gradient-to-b from-gray-900 to-gray-800 min-h-screen flex flex-col justify-between relative overflow-hidden">
11
+ <!-- Snow effect -->
12
+ <canvas id="snow-canvas" class="absolute inset-0 w-full h-full pointer-events-none z-0"></canvas>
13
+ <!-- Header -->
14
+ <header class="text-center py-8">
15
+ <h1 class="text-4xl md:text-6xl font-bold text-yellow-300 drop-shadow-lg tracking-wide">Merry Christmas em iu của anh</h1>
16
+ </header>
17
+ <!-- Main Content -->
18
+ <main class="flex-1 flex flex-col items-center justify-center relative z-10 w-full">
19
+ <div id="tree-container" class="relative flex flex-col items-center justify-center w-full max-w-full">
20
+ <!-- Christmas tree will be rendered here by JS -->
21
+ </div>
22
+ <div id="gifts-container" class="flex flex-row flex-wrap justify-center items-end mt-8 space-x-4 w-full max-w-full px-2">
23
+ <!-- Gift boxes will be rendered here by JS -->
24
+ </div>
25
+ </main>
26
+ <!-- Footer -->
27
+ <footer class="text-center py-6">
28
+ <span class="text-lg text-gray-300 font-medium">Made by: @tbaro - your love</span>
29
+ </footer>
30
+ <script src="/main.js"></script>
31
+ </body>
32
+ </html>
main.js ADDED
@@ -0,0 +1,359 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // --- Christmas Tree, Ornaments, Gifts, Snow, Interactivity ---
2
+
3
+
4
+
5
+ // Romantic quotes (expanded)
6
+ const quotes = [
7
+ "Love is composed of a single soul inhabiting two bodies. – Aristotle",
8
+ "You are my heart, my life, my one and only thought. – Arthur Conan Doyle",
9
+ "I love you not only for what you are, but for what I am when I am with you. – Roy Croft",
10
+ "Whatever our souls are made of, his and mine are the same. – Emily Brontë",
11
+ "You are the finest, loveliest, tenderest, and most beautiful person I have ever known. – F. Scott Fitzgerald",
12
+ "I wish you to know that you have been the last dream of my soul. – Charles Dickens",
13
+ "If I know what love is, it is because of you. – Hermann Hesse",
14
+ "You are my sun, my moon, and all my stars. – E.E. Cummings",
15
+ "I love you more than words can wield the matter. – Shakespeare",
16
+ "To love and be loved is to feel the sun from both sides. – David Viscott",
17
+ "Anh yêu em hơn tất cả những gì anh có thể nói bằng lời.",
18
+ "Em là món quà tuyệt vời nhất mà cuộc đời đã ban tặng cho anh.",
19
+ "Chỉ cần có em bên cạnh, mọi mùa đông đều trở nên ấm áp."
20
+ ];
21
+
22
+ // Bauble images - read from project images folder
23
+ const baubleImages = [
24
+ "5f5e9622-f3f6-49e9-bfd3-886ffc2d9496.jpg",
25
+ "IMG_9450.jpg",
26
+ "IMG_9451.jpg",
27
+ "IMG_9453.jpg",
28
+ "IMG_9461.jpg",
29
+ "IMG_9547.jpg",
30
+ "z7273034591306_f2041027e92ac75073dc44d48a044a19.jpg",
31
+ "z7273040168526_69abfd03e0779e60ce9b0b181353a68b.jpg"
32
+ ];
33
+
34
+ // Ornaments storage
35
+ const ornaments = [];
36
+
37
+ // Create bauble ornaments - here we just rely on baubleImages used when rendering
38
+ function createBaubleOrnaments() {
39
+ // This is a placeholder; baubles are rendered directly in renderTree using baubleImages
40
+ }
41
+
42
+ // Create smaller decorative ornaments (circles) with relative positions (rx, ry)
43
+ function createTreeOrnaments() {
44
+ ornaments.length = 0;
45
+ const count = 12;
46
+ for (let i = 0; i < count; i++) {
47
+ ornaments.push({
48
+ type: 'circle',
49
+ color: i % 2 === 0 ? '#FFD700' : '#E63946',
50
+ size: window.innerWidth < 600 ? 12 : 18,
51
+ rx: 0.25 + Math.random() * 0.5, // relative x position inside tree image
52
+ ry: 0.2 + Math.random() * 0.6 // relative y position inside tree image
53
+ });
54
+ }
55
+ }
56
+
57
+ function renderTree() {
58
+ // Use a single cartoon tree image as centerpiece
59
+ const treeContainer = document.getElementById('tree-container');
60
+ treeContainer.innerHTML = '';
61
+
62
+ // wrapper to align baubles relative to the image
63
+ const wrapper = document.createElement('div');
64
+ wrapper.className = 'tree-wrapper';
65
+ wrapper.style.position = 'relative';
66
+ wrapper.style.display = 'inline-block';
67
+
68
+ const treeImg = document.createElement('img');
69
+ // use relative route for static deployment
70
+ treeImg.src = 'pngegg.png';
71
+ treeImg.alt = 'Christmas Tree';
72
+ treeImg.className = 'cartoon-tree-img';
73
+ treeImg.style.display = 'block';
74
+ treeImg.style.margin = '0 auto';
75
+ // Larger tree sizes for a premium look
76
+ // let CSS control responsive width; remove hard-coded inline width
77
+ // treeImg.style.width = window.innerWidth < 600 ? '220px' : (window.innerWidth < 900 ? '340px' : '480px');
78
+ treeImg.style.height = 'auto';
79
+ treeImg.style.position = 'relative';
80
+ treeImg.style.zIndex = 2;
81
+ wrapper.appendChild(treeImg);
82
+ treeContainer.appendChild(wrapper);
83
+
84
+ // Overlay baubles (images) on the tree image in a circular/spiral pattern
85
+ const baubleCount = baubleImages.length;
86
+ function placeBaublesAndOrnaments() {
87
+ const rect = treeImg.getBoundingClientRect();
88
+ const w = Math.round(rect.width);
89
+ const h = Math.round(rect.height);
90
+ // clear previous ornaments inside wrapper
91
+ wrapper.querySelectorAll('.ornament').forEach(e => e.remove());
92
+ for (let i = 0; i < baubleCount; i++) {
93
+ const angle = (i / baubleCount) * Math.PI * 2 - Math.PI / 2;
94
+ const radius = w * 0.32 + (i % 2) * 18;
95
+ const x = w / 2 + Math.cos(angle) * radius;
96
+ const y = h * 0.45 + Math.sin(angle) * (radius * 0.7);
97
+ const bauble = document.createElement('div');
98
+ bauble.className = 'ornament';
99
+ bauble.style.position = 'absolute';
100
+ bauble.style.left = (x - 22) + 'px';
101
+ bauble.style.top = (y - 22) + 'px';
102
+ // larger baubles for better visibility
103
+ bauble.style.width = window.innerWidth < 600 ? '44px' : (window.innerWidth < 900 ? '64px' : '80px');
104
+ bauble.style.height = window.innerWidth < 600 ? '44px' : (window.innerWidth < 900 ? '64px' : '80px');
105
+ bauble.style.background = `url('${baubleImages[i]}') center/cover no-repeat`;
106
+ bauble.style.border = '3px solid #fff8';
107
+ bauble.style.boxShadow = '0 6px 18px 4px rgba(0,0,0,0.35), 0 0 24px 6px #FFD70044';
108
+ bauble.style.borderRadius = '50%';
109
+ bauble.style.zIndex = 60;
110
+ // gentle float animation
111
+ bauble.style.animation = `float ${3 + Math.random()*2}s ${i * 100}ms ease-in-out infinite`;
112
+ wrapper.appendChild(bauble);
113
+ }
114
+
115
+ // Render extra small ornaments (circles) from ornaments array (rx/ry - relative coords)
116
+ ornaments.forEach(o => {
117
+ if (o.type === 'circle') {
118
+ const el = document.createElement('div');
119
+ el.className = 'ornament';
120
+ const x = Math.round(o.rx * w);
121
+ const y = Math.round(o.ry * h);
122
+ const size = o.size || (window.innerWidth < 600 ? 14 : 26);
123
+ el.style.position = 'absolute';
124
+ el.style.left = (x - size / 2) + 'px';
125
+ el.style.top = (y - size / 2) + 'px';
126
+ el.style.width = size + 'px';
127
+ el.style.height = size + 'px';
128
+ el.style.borderRadius = '50%';
129
+ el.style.background = o.color || '#FFD700';
130
+ el.style.border = '2px solid #fff4';
131
+ el.style.boxShadow = '0 6px 14px 3px rgba(0,0,0,0.28)';
132
+ el.style.zIndex = 55;
133
+ el.style.opacity = 0.95;
134
+ wrapper.appendChild(el);
135
+ }
136
+ });
137
+
138
+ wrapper.style.width = w + 'px';
139
+ wrapper.style.height = h + 'px';
140
+ // Ensure wrapper is centered in container
141
+ wrapper.style.display = 'block';
142
+ wrapper.style.margin = '0 auto';
143
+ }
144
+ // use load event for reliability
145
+ treeImg.onload = () => {
146
+ placeBaublesAndOrnaments();
147
+ // now we can safely render gift boxes positioned relative to the tree
148
+ renderGiftBoxes();
149
+ };
150
+ if (treeImg.complete) {
151
+ placeBaublesAndOrnaments();
152
+ renderGiftBoxes();
153
+ }
154
+ }
155
+
156
+ // Render gift boxes
157
+ function renderGiftBoxes() {
158
+ const giftsContainer = document.getElementById('gifts-container');
159
+ giftsContainer.innerHTML = '';
160
+ const wrapper = document.querySelector('.tree-wrapper');
161
+ const boxCount = window.innerWidth > 1200 ? 8 : window.innerWidth > 900 ? 6 : (window.innerWidth < 600 ? 3 : 5);
162
+
163
+ // If wrapper exists, place boxes around base of the tree
164
+ if (wrapper) {
165
+ // remove any old boxes and any previous row
166
+ wrapper.querySelectorAll('.gift-box.inside').forEach(e => e.remove());
167
+ wrapper.querySelectorAll('.boxes-row').forEach(e => e.remove());
168
+ const w = wrapper.clientWidth;
169
+ const h = wrapper.clientHeight;
170
+ // preferred sizes (relative to container)
171
+ let desiredBox = Math.round(Math.min(110, w * 0.18));
172
+ let gap = Math.round(Math.max(8, w * 0.02));
173
+ const padding = 12;
174
+ // compute max possible box size to fit
175
+ const maxBox = Math.floor((w - padding * 2 - (boxCount - 1) * gap) / boxCount);
176
+ let boxSize = Math.max(36, Math.min(desiredBox, maxBox));
177
+ // if still too big, reduce gap and try again
178
+ if (boxSize * boxCount + (boxCount - 1) * gap + padding * 2 > w) {
179
+ gap = Math.max(6, Math.floor((w - padding * 2 - boxCount * boxSize) / Math.max(1, boxCount - 1)));
180
+ boxSize = Math.max(32, Math.floor((w - padding * 2 - (boxCount - 1) * gap) / boxCount));
181
+ }
182
+ const totalWidth = boxCount * boxSize + (boxCount - 1) * gap;
183
+ // create a centered, responsive row container that sits visually in front of the tree
184
+ const row = document.createElement('div');
185
+ row.className = 'boxes-row';
186
+ row.style.position = 'absolute';
187
+ row.style.left = '50%';
188
+ row.style.transform = 'translateX(-50%)';
189
+ row.style.width = totalWidth + 'px';
190
+ row.style.display = 'flex';
191
+ row.style.gap = gap + 'px';
192
+ row.style.justifyContent = 'center';
193
+ row.style.flexWrap = 'nowrap';
194
+ row.style.bottom = '-' + Math.round(boxSize / 2) + 'px';
195
+ row.style.zIndex = 140;
196
+ row.style.pointerEvents = 'auto';
197
+ // fill row
198
+ for (let i = 0; i < boxCount; i++) {
199
+ const box = document.createElement('div');
200
+ box.className = 'gift-box inside';
201
+ box.style.width = boxSize + 'px';
202
+ box.style.height = boxSize + 'px';
203
+ box.style.boxShadow = '0 16px 40px rgba(0,0,0,0.5), 0 0 18px 6px #FFD70033';
204
+ box.innerHTML = `<div class="gift-ribbon"></div><div class="gift-bow"></div>`;
205
+ box.onclick = () => showQuotePopup();
206
+ box.style.animation = `bob 3s ${i * 120}ms ease-in-out infinite`;
207
+ // subtle rotation
208
+ box.style.transform = (i % 2 === 0) ? 'rotate(-2deg)' : 'rotate(2deg)';
209
+ row.appendChild(box);
210
+ }
211
+ // append to wrapper so it always aligns with the tree image
212
+ wrapper.appendChild(row);
213
+ } else {
214
+ // fallback: render in gifts container
215
+ for (let i = 0; i < boxCount; i++) {
216
+ const box = document.createElement('div');
217
+ box.className = 'gift-box';
218
+ box.innerHTML = `<div class="gift-ribbon"></div><div class="gift-bow"></div>`;
219
+ box.onclick = () => showQuotePopup();
220
+ giftsContainer.appendChild(box);
221
+ }
222
+ giftsContainer.style.justifyContent = 'center';
223
+ giftsContainer.style.gap = '12px';
224
+ }
225
+ }
226
+
227
+ // Show quote popup
228
+ let lastQuoteIndex = -1;
229
+ function showQuotePopup() {
230
+ // Remove any existing popup
231
+ const old = document.querySelector('.quote-popup');
232
+ if (old) old.remove();
233
+ // Pick a new quote, not the same as last
234
+ let idx;
235
+ do {
236
+ idx = Math.floor(Math.random() * quotes.length);
237
+ } while (quotes.length > 1 && idx === lastQuoteIndex);
238
+ lastQuoteIndex = idx;
239
+ const popup = document.createElement('div');
240
+ popup.className = 'quote-popup';
241
+ const quote = quotes[idx];
242
+ popup.innerHTML = `<button class="close-btn">×</button><div>${quote}</div>`;
243
+ popup.querySelector('.close-btn').onclick = () => popup.remove();
244
+ document.body.appendChild(popup);
245
+ }
246
+
247
+ // Snow effect
248
+ function snowEffect() {
249
+ const canvas = document.getElementById('snow-canvas');
250
+ const ctx = canvas.getContext('2d');
251
+ let W = window.innerWidth, H = window.innerHeight;
252
+ canvas.width = W;
253
+ canvas.height = H;
254
+ let mp = 80;
255
+ let particles = [];
256
+ for (let i = 0; i < mp; i++) {
257
+ particles.push({
258
+ x: Math.random() * W,
259
+ y: Math.random() * H,
260
+ r: 2 + Math.random() * 4,
261
+ d: Math.random() * mp
262
+ });
263
+ }
264
+ function draw() {
265
+ ctx.clearRect(0, 0, W, H);
266
+ ctx.fillStyle = "rgba(255,255,255,0.85)";
267
+ ctx.beginPath();
268
+ for (let i = 0; i < mp; i++) {
269
+ let p = particles[i];
270
+ ctx.moveTo(p.x, p.y);
271
+ ctx.arc(p.x, p.y, p.r, 0, Math.PI * 2, true);
272
+ }
273
+ ctx.fill();
274
+ update();
275
+ }
276
+ let angle = 0;
277
+ function update() {
278
+ angle += 0.01;
279
+ for (let i = 0; i < mp; i++) {
280
+ let p = particles[i];
281
+ p.y += Math.cos(angle + p.d) + 1 + p.r / 2;
282
+ p.x += Math.sin(angle) * 2;
283
+ if (p.x > W + 5 || p.x < -5 || p.y > H) {
284
+ if (i % 3 > 0) {
285
+ particles[i] = {x: Math.random() * W, y: -10, r: p.r, d: p.d};
286
+ } else {
287
+ if (Math.sin(angle) > 0) {
288
+ particles[i] = {x: -5, y: Math.random() * H, r: p.r, d: p.d};
289
+ } else {
290
+ particles[i] = {x: W + 5, y: Math.random() * H, r: p.r, d: p.d};
291
+ }
292
+ }
293
+ }
294
+ }
295
+ }
296
+ setInterval(draw, 33);
297
+ window.addEventListener('resize', () => {
298
+ W = window.innerWidth;
299
+ H = window.innerHeight;
300
+ canvas.width = W;
301
+ canvas.height = H;
302
+ });
303
+ }
304
+
305
+ // --- INIT & Responsive ---
306
+ function renderAll() {
307
+ ornaments.length = 0;
308
+ createBaubleOrnaments();
309
+ createTreeOrnaments();
310
+ renderTree();
311
+ renderGiftBoxes();
312
+ }
313
+ function renderMoonAndStars() {
314
+ // Add a moon and stars to the background
315
+ let moon = document.getElementById('moon');
316
+ if (!moon) {
317
+ moon = document.createElement('div');
318
+ moon.id = 'moon';
319
+ moon.style.position = 'fixed';
320
+ moon.style.top = '60px';
321
+ moon.style.right = '80px';
322
+ moon.style.width = '80px';
323
+ moon.style.height = '80px';
324
+ moon.style.borderRadius = '50%';
325
+ moon.style.background = 'radial-gradient(circle at 60% 40%, #fffbe6 70%, #ffe066 100%, #fff0 100%)';
326
+ moon.style.boxShadow = '0 0 60px 10px #fffbe6cc, 0 0 120px 40px #ffe06644';
327
+ moon.style.zIndex = 1;
328
+ document.body.appendChild(moon);
329
+ }
330
+ // Remove old stars
331
+ document.querySelectorAll('.starry-star').forEach(e => e.remove());
332
+ // Add random stars
333
+ for (let i = 0; i < 40; i++) {
334
+ const star = document.createElement('div');
335
+ star.className = 'starry-star';
336
+ star.style.position = 'fixed';
337
+ star.style.top = (Math.random() * 40 + 10) + '%';
338
+ star.style.left = (Math.random() * 100) + '%';
339
+ const size = Math.random() * 2.5 + 1.5;
340
+ star.style.width = size + 'px';
341
+ star.style.height = size + 'px';
342
+ star.style.background = 'white';
343
+ star.style.borderRadius = '50%';
344
+ star.style.opacity = 0.7 + Math.random() * 0.3;
345
+ star.style.zIndex = 1;
346
+ star.style.boxShadow = `0 0 ${size*4}px ${size/2}px #fff8`;
347
+ document.body.appendChild(star);
348
+ }
349
+ }
350
+
351
+ document.addEventListener('DOMContentLoaded', () => {
352
+ renderAll();
353
+ snowEffect();
354
+ renderMoonAndStars();
355
+ window.addEventListener('resize', () => {
356
+ renderAll();
357
+ renderMoonAndStars();
358
+ });
359
+ });
pngegg.png ADDED

Git LFS Details

  • SHA256: da3e15cceadd6ee4a9ce3694b9efcbb11169211739ee2745a90ebab7644ae4f6
  • Pointer size: 132 Bytes
  • Size of remote file: 3.2 MB
style.css CHANGED
@@ -1,28 +1,276 @@
1
- body {
2
- padding: 2rem;
3
- font-family: -apple-system, BlinkMacSystemFont, "Arial", sans-serif;
4
- }
5
-
6
- h1 {
7
- font-size: 16px;
8
- margin-top: 0;
9
- }
10
-
11
- p {
12
- color: rgb(107, 114, 128);
13
- font-size: 15px;
14
- margin-bottom: 10px;
15
- margin-top: 5px;
16
- }
17
-
18
- .card {
19
- max-width: 620px;
20
- margin: 0 auto;
21
- padding: 16px;
22
- border: 1px solid lightgray;
23
- border-radius: 16px;
24
- }
25
-
26
- .card p:last-child {
27
- margin-bottom: 0;
28
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Premium, warm, romantic Christmas styles */
2
+ body {
3
+ font-family: 'Segoe UI', 'Roboto', 'Arial', sans-serif;
4
+ background: linear-gradient(180deg, #232946 0%, #1a202c 100%);
5
+ }
6
+
7
+ #tree-container {
8
+ min-height: 320px;
9
+ min-width: 220px;
10
+ width: 100vw;
11
+ max-width: 100vw;
12
+ display: flex;
13
+ justify-content: center;
14
+ align-items: center;
15
+ }
16
+
17
+ /* Christmas tree styles */
18
+ /* Beautiful, lush, premium Christmas tree */
19
+ /* Cartoon tree image style */
20
+ .cartoon-tree-img {
21
+ display: block;
22
+ margin: 0 auto;
23
+ width: min(72vw, 520px);
24
+ max-width: 92vw;
25
+ height: auto;
26
+ filter: drop-shadow(0 0 26px #fff8) drop-shadow(0 0 48px #FFD70044);
27
+ border-radius: 18px;
28
+ background: none;
29
+ z-index: 2;
30
+ box-shadow: 0 0 0 6px #fff2;
31
+ transition: width 0.25s ease, height 0.25s ease, transform 0.25s ease;
32
+ }
33
+ @media (max-width: 1200px) {
34
+ .cartoon-tree-img {
35
+ width: min(72vw, 420px);
36
+ }
37
+ }
38
+ @media (max-width: 900px) {
39
+ .cartoon-tree-img {
40
+ width: min(80vw, 360px);
41
+ }
42
+ }
43
+ @media (max-width: 600px) {
44
+ .cartoon-tree-img {
45
+ width: min(92vw, 220px);
46
+ }
47
+ }
48
+ .christmas-tree {
49
+ width: 260px;
50
+ height: 400px;
51
+ }
52
+ }
53
+ @media (max-width: 600px) {
54
+ .christmas-tree {
55
+ width: 220px;
56
+ height: 320px;
57
+ }
58
+ }
59
+
60
+ .tree-part {
61
+ position: absolute;
62
+ left: 50%;
63
+ transform: translateX(-50%);
64
+ border-radius: 50%;
65
+ background: linear-gradient(135deg, #2d6a4f 60%, #1b4332 100%);
66
+ box-shadow: 0 0 40px 10px #14532d44;
67
+ border: 2px solid #fff2;
68
+ }
69
+
70
+ /* Glowing star */
71
+ .tree-star {
72
+ position: absolute;
73
+ left: 50%;
74
+ transform: translateX(-50%);
75
+ width: 60px;
76
+ height: 60px;
77
+ z-index: 40;
78
+ animation: twinkle 2s infinite alternate;
79
+ filter: drop-shadow(0 0 18px #fff8) drop-shadow(0 0 32px #FFD700);
80
+ }
81
+
82
+ @keyframes twinkle {
83
+ 0% { filter: brightness(1.2); }
84
+ 100% { filter: brightness(2.2); }
85
+ }
86
+
87
+ /* tree wrapper for relative placements */
88
+ .tree-wrapper {
89
+ position: relative;
90
+ display: inline-block;
91
+ overflow: visible;
92
+ padding-bottom: 48px; /* space for gifts */
93
+ }
94
+
95
+ /* centered row of gift boxes */
96
+ .boxes-row {
97
+ display: flex;
98
+ justify-content: center;
99
+ align-items: flex-end;
100
+ gap: 18px;
101
+ pointer-events: auto;
102
+ }
103
+ @media (max-width: 600px) {
104
+ .boxes-row {
105
+ gap: 10px;
106
+ }
107
+ }
108
+
109
+ /* star twinkle */
110
+ .starry-star {
111
+ animation: starTwinkle 3s infinite ease-in-out;
112
+ }
113
+ @keyframes starTwinkle {
114
+ 0% { opacity: 0.6; transform: scale(1); }
115
+ 50% { opacity: 1; transform: scale(1.4); }
116
+ 100% { opacity: 0.6; transform: scale(1); }
117
+ }
118
+
119
+ /* Ornaments */
120
+ .ornament {
121
+ position: absolute;
122
+ border-radius: 50%;
123
+ transition: transform 0.3s, box-shadow 0.3s;
124
+ cursor: pointer;
125
+ border: 2.5px solid #fff8;
126
+ box-shadow: 0 0 12px 2px #fff8, 0 0 18px 4px #FFD70044;
127
+ background: #fff;
128
+ z-index: 10;
129
+ }
130
+ .ornament:hover {
131
+ transform: scale(1.18) rotate(-2deg);
132
+ box-shadow: 0 0 32px 8px #fff9, 0 0 18px 4px #FFD70099;
133
+ z-index: 99;
134
+ }
135
+
136
+ /* Gift boxes */
137
+
138
+ .gift-box {
139
+ width: 100px;
140
+ height: 100px;
141
+ background: linear-gradient(135deg, #e63946 60%, #fbefef 100%);
142
+ border-radius: 14px;
143
+ box-shadow: 0 12px 36px 0 rgba(0,0,0,0.35);
144
+ position: relative;
145
+ cursor: pointer;
146
+ transition: transform 0.25s, box-shadow 0.25s;
147
+ margin-bottom: 16px;
148
+ border: 2.5px solid #fff6;
149
+ overflow: hidden;
150
+ }
151
+ .gift-box:hover {
152
+ transform: scale(1.14) translateY(-6px) rotate(-2deg);
153
+ box-shadow: 0 18px 44px 0 rgba(0,0,0,0.45), 0 0 18px 6px #FFD70088;
154
+ }
155
+
156
+ .gift-box.inside {
157
+ cursor: pointer;
158
+ }
159
+
160
+ @keyframes bob {
161
+ 0% { transform: translateY(0); }
162
+ 50% { transform: translateY(-8px); }
163
+ 100% { transform: translateY(0); }
164
+ }
165
+
166
+ @keyframes float {
167
+ 0% { transform: translateY(0); }
168
+ 50% { transform: translateY(-6px); }
169
+ 100% { transform: translateY(0); }
170
+ }
171
+
172
+ @media (max-width: 900px) {
173
+ .gift-box {
174
+ width: 80px;
175
+ height: 80px;
176
+ }
177
+ .gift-ribbon {
178
+ width: 80px;
179
+ top: 28px;
180
+ }
181
+ .gift-bow {
182
+ left: 24px;
183
+ top: 16px;
184
+ }
185
+ }
186
+ @media (max-width: 600px) {
187
+ .gift-box {
188
+ width: 56px;
189
+ height: 56px;
190
+ }
191
+ .gift-ribbon {
192
+ width: 56px;
193
+ top: 18px;
194
+ }
195
+ .gift-bow {
196
+ left: 12px;
197
+ top: 6px;
198
+ width: 10px;
199
+ height: 10px;
200
+ }
201
+ }
202
+
203
+ .gift-ribbon {
204
+ position: absolute;
205
+ top: 46%;
206
+ left: 0;
207
+ width: 100%;
208
+ height: 12px;
209
+ background: linear-gradient(90deg, #c1121f 30%, #e63946 70%);
210
+ border-radius: 6px;
211
+ box-shadow: inset 0 -2px 6px rgba(0,0,0,0.25);
212
+ }
213
+ .gift-ribbon::before {
214
+ content: '';
215
+ position: absolute;
216
+ left: 50%;
217
+ transform: translateX(-50%);
218
+ top: -8px;
219
+ width: 12px;
220
+ height: 32px;
221
+ background: linear-gradient(180deg, #ffdede, #ff7b7b);
222
+ border-radius: 4px;
223
+ opacity: 0.9;
224
+ }
225
+ .gift-bow {
226
+ position: absolute;
227
+ top: 30%;
228
+ left: 50%;
229
+ transform: translate(-50%, -50%);
230
+ width: 18px;
231
+ height: 18px;
232
+ background: radial-gradient(circle, #fff 40%, #ffccd5 100%);
233
+ border-radius: 6px;
234
+ box-shadow: 0 2px 8px rgba(0,0,0,0.2);
235
+ }
236
+
237
+
238
+ /* Popup styles */
239
+ .quote-popup {
240
+ position: fixed;
241
+ left: 50%;
242
+ top: 60%;
243
+ transform: translate(-50%, -50%);
244
+ background: rgba(34, 40, 49, 0.98);
245
+ color: #ffd6e0;
246
+ border-radius: 16px;
247
+ box-shadow: 0 8px 32px 0 #0008;
248
+ padding: 32px 40px;
249
+ font-size: 1.25rem;
250
+ font-family: 'Georgia', serif;
251
+ z-index: 50;
252
+ animation: fadeIn 0.5s;
253
+ max-width: 90vw;
254
+ word-break: break-word;
255
+ }
256
+ @media (max-width: 600px) {
257
+ .quote-popup {
258
+ padding: 16px 10px;
259
+ font-size: 1rem;
260
+ }
261
+ }
262
+ @keyframes fadeIn {
263
+ from { opacity: 0; transform: translate(-50%, -60%); }
264
+ to { opacity: 1; transform: translate(-50%, -50%); }
265
+ }
266
+
267
+ .quote-popup .close-btn {
268
+ position: absolute;
269
+ top: 12px;
270
+ right: 18px;
271
+ background: none;
272
+ border: none;
273
+ color: #fff;
274
+ font-size: 1.5rem;
275
+ cursor: pointer;
276
+ }
z7273034591306_f2041027e92ac75073dc44d48a044a19.jpg ADDED

Git LFS Details

  • SHA256: 5d4ec32f948c19e7ab8f3178ef8959fa85bbac2633d54c9563f3938da155f2bc
  • Pointer size: 131 Bytes
  • Size of remote file: 363 kB
z7273040168526_69abfd03e0779e60ce9b0b181353a68b.jpg ADDED

Git LFS Details

  • SHA256: e3371b5489b55c91ef8794450b21bacb723c0885fecd73632b3199c570e94b41
  • Pointer size: 131 Bytes
  • Size of remote file: 690 kB