irkan commited on
Commit
af77065
Β·
verified Β·
1 Parent(s): 8c6ce69

Deploy screen-companion from 5ffc29e

Browse files
static/companion.js CHANGED
@@ -202,40 +202,8 @@ function formatMemoriesForPrompt() {
202
  // ─── Companion SVG (injected into PiP window) ─────────────────────────────
203
 
204
  const COMPANION_HTML = `
205
- <div class="pip-scene" id="pip-scene" data-time="day">
206
- <div class="scene-sky"></div>
207
- <div class="scene-canopy"></div>
208
- <div class="scene-chimney"><div class="chimney-smoke"><span></span></div></div>
209
- <div class="scene-roof"></div>
210
- <div class="scene-dormer"></div>
211
- <div class="scene-house-body"></div>
212
- <div class="scene-window scene-window--left"></div>
213
- <div class="scene-window scene-window--right"></div>
214
- <div class="scene-door"></div>
215
- <div class="scene-lantern scene-lantern--left"></div>
216
- <div class="scene-lantern scene-lantern--right"></div>
217
- <div class="scene-vine"></div>
218
- <div class="scene-porch"></div>
219
- <div class="scene-flowerbox scene-flowerbox--left"></div>
220
- <div class="scene-flowerbox scene-flowerbox--right"></div>
221
- <div class="scene-steps"></div>
222
- <div class="scene-garden">
223
- <div class="scene-path"></div>
224
- <div class="scene-flowers-l"></div>
225
- <div class="scene-flowers-r"></div>
226
- <div class="scene-lamp"></div>
227
- <div class="scene-pot scene-pot--1"></div>
228
- <div class="scene-pot scene-pot--2"></div>
229
- <div class="scene-fence"></div>
230
- <div class="scene-gate"></div>
231
- </div>
232
- <div class="scene-fireflies">
233
- <div class="firefly"></div><div class="firefly"></div><div class="firefly"></div>
234
- <div class="firefly"></div><div class="firefly"></div><div class="firefly"></div>
235
- </div>
236
- </div>
237
  <div class="pip-container">
238
- <div class="house-spacer"></div>
239
  <div class="companion-wrap">
240
  <svg viewBox="0 0 64 64" class="companion-svg state-idle" id="pip-companion" xmlns="http://www.w3.org/2000/svg">
241
  <g class="body-group">
@@ -392,6 +360,9 @@ async function launchCompanion() {
392
  loadStreak();
393
  startStreak();
394
 
 
 
 
395
  // Immediate greeting (before first VLM call)
396
  showGreeting();
397
 
@@ -994,9 +965,61 @@ function reactToTimeChange(from, to) {
994
  }
995
  }
996
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
997
  // ─── Cleanup ───────────────────────────────────────────────────────────────
998
 
999
  function cleanup() {
 
1000
  if (gazeChangeTimer && pipWindow) {
1001
  pipWindow.clearTimeout(gazeChangeTimer);
1002
  gazeChangeTimer = null;
 
202
  // ─── Companion SVG (injected into PiP window) ─────────────────────────────
203
 
204
  const COMPANION_HTML = `
205
+ <div class="pip-scene" id="pip-scene" data-time="day"></div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
206
  <div class="pip-container">
 
207
  <div class="companion-wrap">
208
  <svg viewBox="0 0 64 64" class="companion-svg state-idle" id="pip-companion" xmlns="http://www.w3.org/2000/svg">
209
  <g class="body-group">
 
360
  loadStreak();
361
  startStreak();
362
 
363
+ // Start garden wander (Pip roams the garden, background follows)
364
+ startWander();
365
+
366
  // Immediate greeting (before first VLM call)
367
  showGreeting();
368
 
 
965
  }
966
  }
967
 
968
+ // ─── Wander System ────────────────────────────────────────────────────────
969
+ // Pip wanders within the garden zone of the image. The background pans to
970
+ // follow, so Pip is always shown against the correct part of the scene.
971
+ // Garden bounds in the source image (as % of image dimensions):
972
+ // X: 5% to 95% (full width minus fence edges)
973
+ // Y: 55% to 88% (below porch steps, above fence)
974
+
975
+ const GARDEN_BOUNDS = { xMin: 15, xMax: 85, yMin: 58, yMax: 85 };
976
+ let wanderTimer = null;
977
+ let currentBgX = 50;
978
+ let currentBgY = 80;
979
+
980
+ function startWander() {
981
+ if (!pipWindow) return;
982
+ scheduleWander();
983
+ }
984
+
985
+ function scheduleWander() {
986
+ if (!pipWindow) return;
987
+ const delay = 6000 + Math.floor(Math.random() * 8000);
988
+ wanderTimer = pipWindow.setTimeout(() => {
989
+ wanderToRandomSpot();
990
+ scheduleWander();
991
+ }, delay);
992
+ }
993
+
994
+ function wanderToRandomSpot() {
995
+ if (!pipWindow) return;
996
+ const scene = pipWindow.document.getElementById('pip-scene');
997
+ const wrap = pipWindow.document.querySelector('.companion-wrap');
998
+ if (!scene || !wrap) return;
999
+
1000
+ const targetX = GARDEN_BOUNDS.xMin + Math.random() * (GARDEN_BOUNDS.xMax - GARDEN_BOUNDS.xMin);
1001
+ const targetY = GARDEN_BOUNDS.yMin + Math.random() * (GARDEN_BOUNDS.yMax - GARDEN_BOUNDS.yMin);
1002
+
1003
+ currentBgX = targetX;
1004
+ currentBgY = targetY;
1005
+ scene.style.backgroundPosition = `${targetX}% ${targetY}%`;
1006
+
1007
+ const pipOffsetX = (targetX - 50) * 0.4;
1008
+ const pipOffsetY = (targetY - 70) * 0.3;
1009
+ wrap.style.transform = `translate(${pipOffsetX}px, ${pipOffsetY}px)`;
1010
+ }
1011
+
1012
+ function stopWander() {
1013
+ if (wanderTimer && pipWindow) {
1014
+ pipWindow.clearTimeout(wanderTimer);
1015
+ wanderTimer = null;
1016
+ }
1017
+ }
1018
+
1019
  // ─── Cleanup ───────────────────────────────────────────────────────────────
1020
 
1021
  function cleanup() {
1022
+ stopWander();
1023
  if (gazeChangeTimer && pipWindow) {
1024
  pipWindow.clearTimeout(gazeChangeTimer);
1025
  gazeChangeTimer = null;
static/day_house.jpg ADDED
static/night_house.jpg ADDED
static/style.css CHANGED
@@ -325,626 +325,23 @@ body {
325
  image-rendering: pixelated;
326
  }
327
 
328
- /* ─── Cozy House Exterior (pure CSS pixel art, day/night) ─────────── */
329
 
330
  .pip-scene {
331
  position: absolute;
332
  inset: 0;
333
  z-index: 0;
334
  overflow: hidden;
335
- --sky: #87ceeb;
336
- --canopy: #2d6b2d;
337
- --canopy-cherry: #e88cc8;
338
- --roof: #b05a28;
339
- --roof-dark: #8a4420;
340
- --walls: #2a1a0d;
341
- --walls-plank: #1f1408;
342
- --window-glow: rgba(255, 180, 50, 0.7);
343
- --window-glow-shadow: rgba(255, 180, 50, 0.5);
344
- --lantern-glow: rgba(255, 200, 80, 0.4);
345
- --porch: #7a5830;
346
- --porch-dark: #5a3f20;
347
- --grass: #4a8c3f;
348
- --grass-dark: #3a7030;
349
- --path: #c4a67a;
350
- --path-dark: #a88c5e;
351
- --flowers-l: #ff69b4;
352
- --flowers-r: #ffaa33;
353
- --fence: #6b4c2a;
354
- --fence-dark: #5a3f20;
355
- --lamp-glow: rgba(255, 220, 100, 0);
356
- --smoke-color: rgba(180, 180, 180, 0.4);
357
- --vine: #3a7a3a;
358
- transition:
359
- --sky 1.5s, --canopy 1.5s, --canopy-cherry 1.5s,
360
- --roof 1.5s, --walls 1.5s, --grass 1.5s,
361
- --path 1.5s, --fence 1.5s, --lamp-glow 1.5s,
362
- --smoke-color 1.5s, --vine 1.5s;
363
  }
364
 
365
  .pip-scene[data-time="night"] {
366
- --sky: #1a0f33;
367
- --canopy: #1a2a4a;
368
- --canopy-cherry: #6644aa;
369
- --roof: #8a4420;
370
- --roof-dark: #6a3318;
371
- --walls: #1a0f08;
372
- --walls-plank: #120a04;
373
- --window-glow: rgba(255, 160, 40, 0.95);
374
- --window-glow-shadow: rgba(255, 140, 30, 0.7);
375
- --lantern-glow: rgba(255, 200, 80, 0.8);
376
- --porch: #4a3318;
377
- --porch-dark: #3a2510;
378
- --grass: #1a3a1a;
379
- --grass-dark: #122a12;
380
- --path: #5a4a3a;
381
- --path-dark: #4a3a2a;
382
- --flowers-l: #4a2060;
383
- --flowers-r: #3a3020;
384
- --fence: #3a2818;
385
- --fence-dark: #2a1a0d;
386
- --lamp-glow: rgba(255, 220, 100, 0.35);
387
- --smoke-color: rgba(80, 80, 120, 0.2);
388
- --vine: #1a4a2a;
389
- }
390
-
391
- /* Sky / background fill */
392
- .scene-sky {
393
- position: absolute;
394
- inset: 0;
395
- background: var(--grass);
396
- transition: background 1.5s;
397
- }
398
-
399
- /* Dense tree canopy (top band, no sky visible) */
400
- .scene-canopy {
401
- position: absolute;
402
- top: 0;
403
- left: 0;
404
- right: 0;
405
- height: 9%;
406
- background: var(--canopy);
407
- transition: background 1.5s;
408
- }
409
- .scene-canopy::before {
410
- content: '';
411
- position: absolute;
412
- top: 0;
413
- left: 0;
414
- width: 50px;
415
- height: 100%;
416
- background: var(--canopy-cherry);
417
- border-radius: 0 0 60% 0;
418
- transition: background 1.5s;
419
- }
420
- .scene-canopy::after {
421
- content: '';
422
- position: absolute;
423
- top: 0;
424
- right: 0;
425
- width: 45px;
426
- height: 100%;
427
- background: var(--canopy);
428
- border-radius: 0 0 0 50%;
429
- filter: brightness(0.85);
430
- transition: background 1.5s;
431
- }
432
-
433
- /* Chimney */
434
- .scene-chimney {
435
- position: absolute;
436
- top: 4%;
437
- left: 53%;
438
- width: 7px;
439
- height: 16px;
440
- background: #7a7a7a;
441
- border: 1px solid #5a5a5a;
442
- z-index: 1;
443
- }
444
- .chimney-smoke {
445
- position: absolute;
446
- top: -4px;
447
- left: 1px;
448
- }
449
- .chimney-smoke::before,
450
- .chimney-smoke::after,
451
- .chimney-smoke span {
452
- content: '';
453
- position: absolute;
454
- width: 4px;
455
- height: 4px;
456
- border-radius: 50%;
457
- background: var(--smoke-color);
458
- animation: smoke 3s ease-out infinite;
459
- transition: background 1.5s;
460
- }
461
- .chimney-smoke::after {
462
- left: 2px;
463
- animation-delay: 1s;
464
- }
465
- .chimney-smoke span {
466
- display: block;
467
- left: -1px;
468
- animation-delay: 2s;
469
- }
470
-
471
- @keyframes smoke {
472
- 0% { transform: translateY(0) scale(1); opacity: 0.4; }
473
- 100% { transform: translateY(-15px) translateX(3px) scale(1.8); opacity: 0; }
474
- }
475
-
476
- /* Roof */
477
- .scene-roof {
478
- position: absolute;
479
- top: 9%;
480
- left: 14%;
481
- width: 72%;
482
- height: 14%;
483
- overflow: visible;
484
- }
485
- .scene-roof::before {
486
- content: '';
487
- position: absolute;
488
- bottom: 0;
489
- left: 0;
490
- right: 0;
491
- height: 0;
492
- border-bottom: 40px solid var(--roof);
493
- border-left: 79px solid transparent;
494
- border-right: 79px solid transparent;
495
- transition: border-bottom-color 1.5s;
496
- }
497
- .scene-roof::after {
498
- content: '';
499
- position: absolute;
500
- bottom: 0;
501
- left: 0;
502
- right: 0;
503
- height: 40px;
504
- background: repeating-linear-gradient(0deg, transparent 0 3px, rgba(0,0,0,0.08) 3px 4px);
505
- pointer-events: none;
506
- }
507
-
508
- /* Dormer / attic window */
509
- .scene-dormer {
510
- position: absolute;
511
- top: 12%;
512
- left: 43%;
513
- width: 14px;
514
- height: 12px;
515
- background: var(--roof-dark);
516
- border-radius: 3px 3px 0 0;
517
- transition: background 1.5s;
518
- }
519
- .scene-dormer::after {
520
- content: '';
521
- position: absolute;
522
- top: 3px;
523
- left: 3px;
524
- width: 8px;
525
- height: 6px;
526
- background: var(--window-glow);
527
- box-shadow: 0 0 4px var(--window-glow-shadow);
528
- border-radius: 1px;
529
- transition: background 1.5s, box-shadow 1.5s;
530
- }
531
-
532
- /* House face */
533
- .scene-house-body {
534
- position: absolute;
535
- top: 23%;
536
- left: 16%;
537
- width: 68%;
538
- height: 12%;
539
- background:
540
- repeating-linear-gradient(0deg, var(--walls) 0 5px, var(--walls-plank) 5px 6px);
541
- transition: background 1.5s;
542
- }
543
-
544
- /* Windows */
545
- .scene-window {
546
- position: absolute;
547
- width: 14px;
548
- height: 11px;
549
- background: var(--window-glow);
550
- border: 2px solid #1a0f08;
551
- box-shadow: inset 0 0 6px var(--window-glow-shadow), 0 0 6px var(--window-glow-shadow);
552
- transition: background 1.5s, box-shadow 1.5s;
553
- }
554
- .scene-window--left {
555
- top: 25%;
556
- left: 22%;
557
- }
558
- .scene-window--right {
559
- top: 25%;
560
- left: 60%;
561
- }
562
- .scene-window::before {
563
- content: '';
564
- position: absolute;
565
- top: 0;
566
- left: 50%;
567
- width: 1px;
568
- height: 100%;
569
- background: #1a0f08;
570
- }
571
- .scene-window::after {
572
- content: '';
573
- position: absolute;
574
- top: 50%;
575
- left: 0;
576
- width: 100%;
577
- height: 1px;
578
- background: #1a0f08;
579
- }
580
-
581
- /* Front door */
582
- .scene-door {
583
- position: absolute;
584
- top: 26%;
585
- left: 44%;
586
- width: 11px;
587
- height: 16px;
588
- background: #1a0f08;
589
- border-radius: 2px 2px 0 0;
590
- }
591
- .scene-door::after {
592
- content: '';
593
- position: absolute;
594
- top: 7px;
595
- right: 2px;
596
- width: 2px;
597
- height: 2px;
598
- background: #c0a060;
599
- border-radius: 50%;
600
- }
601
-
602
- /* Wall lanterns */
603
- .scene-lantern {
604
- position: absolute;
605
- width: 3px;
606
- height: 5px;
607
- background: #8a6a3a;
608
- }
609
- .scene-lantern::after {
610
- content: '';
611
- position: absolute;
612
- top: -4px;
613
- left: -5px;
614
- width: 13px;
615
- height: 13px;
616
- border-radius: 50%;
617
- background: radial-gradient(circle, var(--lantern-glow) 0%, transparent 70%);
618
- transition: background 1.5s;
619
- }
620
- .scene-lantern--left {
621
- top: 24%;
622
- left: 19%;
623
- }
624
- .scene-lantern--right {
625
- top: 24%;
626
- left: 66%;
627
- }
628
-
629
- /* Vine */
630
- .scene-vine {
631
- position: absolute;
632
- top: 15%;
633
- left: 16%;
634
- width: 3px;
635
- height: 20%;
636
- background: var(--vine);
637
- border-radius: 1px;
638
- transition: background 1.5s;
639
- }
640
- .scene-vine::before {
641
- content: '';
642
- position: absolute;
643
- top: 4px;
644
- left: -2px;
645
- width: 7px;
646
- height: 100%;
647
- background:
648
- radial-gradient(circle 2px at 1px 5px, var(--vine) 50%, transparent 50%),
649
- radial-gradient(circle 2px at 5px 14px, var(--vine) 50%, transparent 50%),
650
- radial-gradient(circle 2px at 2px 24px, var(--vine) 50%, transparent 50%),
651
- radial-gradient(circle 2px at 6px 34px, var(--vine) 50%, transparent 50%);
652
- }
653
-
654
- /* Porch */
655
- .scene-porch {
656
- position: absolute;
657
- top: 35%;
658
- left: 16%;
659
- width: 68%;
660
- height: 6%;
661
- background: var(--porch);
662
- border-top: 2px solid var(--porch-dark);
663
- transition: background 1.5s, border-color 1.5s;
664
- }
665
- .scene-porch::before {
666
- content: '';
667
- position: absolute;
668
- top: 0;
669
- left: 0;
670
- right: 0;
671
- height: 3px;
672
- background: repeating-linear-gradient(90deg, var(--porch-dark) 0 1px, transparent 1px 5px);
673
- transition: background 1.5s;
674
- }
675
-
676
- /* Flower boxes on porch */
677
- .scene-flowerbox {
678
- position: absolute;
679
- top: 36%;
680
- width: 12px;
681
- height: 5px;
682
- background: #5a4020;
683
- border-radius: 1px;
684
- }
685
- .scene-flowerbox::after {
686
- content: '';
687
- position: absolute;
688
- top: -3px;
689
- left: 1px;
690
- width: 10px;
691
- height: 3px;
692
- background:
693
- radial-gradient(circle 2px at 2px 1px, #ff88aa 80%, transparent 80%),
694
- radial-gradient(circle 2px at 6px 1px, #ffaacc 80%, transparent 80%),
695
- radial-gradient(circle 2px at 9px 2px, #ff88aa 80%, transparent 80%);
696
- }
697
- .scene-flowerbox--left { left: 20%; }
698
- .scene-flowerbox--right { left: 62%; }
699
-
700
- /* Steps */
701
- .scene-steps {
702
- position: absolute;
703
- top: 41%;
704
- left: 34%;
705
- width: 32%;
706
- height: 4%;
707
- }
708
- .scene-steps::before {
709
- content: '';
710
- position: absolute;
711
- top: 0;
712
- left: 2px;
713
- right: 2px;
714
- height: 33%;
715
- background: #8a7a6a;
716
- }
717
- .scene-steps::after {
718
- content: '';
719
- position: absolute;
720
- top: 33%;
721
- left: 0;
722
- right: 0;
723
- bottom: 0;
724
- background:
725
- linear-gradient(to bottom,
726
- #8a7a6a 0%, #8a7a6a 45%,
727
- #9a8a7a 50%, #9a8a7a 100%);
728
- }
729
-
730
- /* Garden ground (from 45% to 82%) */
731
- .scene-garden {
732
- position: absolute;
733
- top: 45%;
734
- left: 0;
735
- right: 0;
736
- bottom: 11%;
737
- background: var(--grass);
738
- transition: background 1.5s;
739
- }
740
-
741
- /* Cobblestone path */
742
- .scene-path {
743
- position: absolute;
744
- top: 0;
745
- left: 36%;
746
- width: 22%;
747
- height: 90%;
748
- background:
749
- radial-gradient(ellipse 5px 4px at 30% 8%, var(--path) 80%, transparent 80%),
750
- radial-gradient(ellipse 6px 4px at 60% 12%, var(--path-dark) 80%, transparent 80%),
751
- radial-gradient(ellipse 5px 5px at 45% 20%, var(--path) 80%, transparent 80%),
752
- radial-gradient(ellipse 6px 4px at 35% 28%, var(--path-dark) 80%, transparent 80%),
753
- radial-gradient(ellipse 5px 5px at 55% 35%, var(--path) 80%, transparent 80%),
754
- radial-gradient(ellipse 6px 4px at 40% 42%, var(--path) 80%, transparent 80%),
755
- radial-gradient(ellipse 5px 4px at 60% 50%, var(--path-dark) 80%, transparent 80%),
756
- radial-gradient(ellipse 6px 5px at 38% 58%, var(--path) 80%, transparent 80%),
757
- radial-gradient(ellipse 5px 4px at 55% 65%, var(--path-dark) 80%, transparent 80%),
758
- radial-gradient(ellipse 6px 5px at 42% 72%, var(--path) 80%, transparent 80%),
759
- radial-gradient(ellipse 5px 4px at 58% 80%, var(--path-dark) 80%, transparent 80%),
760
- radial-gradient(ellipse 6px 5px at 45% 88%, var(--path) 80%, transparent 80%);
761
- transition: background 1.5s;
762
- }
763
-
764
- /* Left flower cluster (box-shadow trick) */
765
- .scene-flowers-l {
766
- position: absolute;
767
- top: 10%;
768
- left: 10%;
769
- width: 4px;
770
- height: 4px;
771
- border-radius: 50%;
772
- background: var(--flowers-l);
773
- box-shadow:
774
- 8px 4px 0 0 #ff88cc,
775
- 16px -2px 0 0 #aa44ff,
776
- 4px 14px 0 0 #ffaacc,
777
- 20px 12px 0 0 #ff69b4,
778
- 12px 22px 0 0 #cc55ee,
779
- 2px 30px 0 0 #ff88cc,
780
- 18px 32px 0 0 #aa44ff,
781
- 8px 40px 0 0 #ffaacc,
782
- 22px 44px 0 0 #ff69b4,
783
- 14px 52px 0 0 #cc55ee,
784
- 4px 58px 0 0 #ff88cc,
785
- 20px 60px 0 0 #aa44ff;
786
- transition: background 1.5s, box-shadow 1.5s;
787
- }
788
-
789
- /* Right flower cluster */
790
- .scene-flowers-r {
791
- position: absolute;
792
- top: 10%;
793
- right: 10%;
794
- width: 4px;
795
- height: 4px;
796
- border-radius: 50%;
797
- background: var(--flowers-r);
798
- box-shadow:
799
- -8px 6px 0 0 #ffcc44,
800
- -16px 2px 0 0 #4488ff,
801
- -4px 16px 0 0 #ffaa33,
802
- -20px 14px 0 0 #44aaff,
803
- -12px 24px 0 0 #ffcc44,
804
- -2px 32px 0 0 #ff8844,
805
- -18px 34px 0 0 #4488ff,
806
- -8px 42px 0 0 #ffaa33,
807
- -22px 48px 0 0 #ffcc44,
808
- -14px 54px 0 0 #44aaff,
809
- -4px 60px 0 0 #ff8844;
810
- transition: background 1.5s, box-shadow 1.5s;
811
- }
812
-
813
- /* Garden lamp */
814
- .scene-lamp {
815
- position: absolute;
816
- top: 65%;
817
- left: 48%;
818
- width: 3px;
819
- height: 20px;
820
- background: #5a4020;
821
- }
822
- .scene-lamp::before {
823
- content: '';
824
- position: absolute;
825
- top: -3px;
826
- left: -3px;
827
- width: 9px;
828
- height: 5px;
829
- background: #8a7a5a;
830
- border-radius: 2px 2px 0 0;
831
- }
832
- .scene-lamp::after {
833
- content: '';
834
- position: absolute;
835
- bottom: -8px;
836
- left: -10px;
837
- width: 24px;
838
- height: 14px;
839
- border-radius: 50%;
840
- background: radial-gradient(circle, var(--lamp-glow) 0%, transparent 70%);
841
- transition: background 1.5s;
842
- }
843
-
844
- /* Potted plants */
845
- .scene-pot {
846
- position: absolute;
847
- width: 7px;
848
- height: 6px;
849
- background: #6a4a2a;
850
- border-radius: 0 0 1px 1px;
851
- }
852
- .scene-pot::before {
853
- content: '';
854
- position: absolute;
855
- top: -5px;
856
- left: -1px;
857
- width: 9px;
858
- height: 7px;
859
- background: #3a7a3a;
860
- border-radius: 50%;
861
- }
862
- .scene-pot--1 { top: 8%; left: 28%; }
863
- .scene-pot--2 { top: 22%; left: 64%; }
864
-
865
- /* Fence */
866
- .scene-fence {
867
- position: absolute;
868
- bottom: 0;
869
- left: 5%;
870
- width: 90%;
871
- height: 18%;
872
- background:
873
- repeating-linear-gradient(
874
- 90deg,
875
- var(--fence) 0 3px,
876
- var(--fence-dark) 3px 4px,
877
- transparent 4px 8px
878
- );
879
- border-top: 2px solid var(--fence-dark);
880
- transition: background 1.5s, border-color 1.5s;
881
- }
882
- .scene-fence::before {
883
- content: '';
884
- position: absolute;
885
- top: 35%;
886
- left: 0;
887
- right: 0;
888
- height: 2px;
889
- background: var(--fence-dark);
890
- transition: background 1.5s;
891
- }
892
-
893
- /* Gate opening */
894
- .scene-gate {
895
- position: absolute;
896
- bottom: 0;
897
- left: 40%;
898
- width: 20%;
899
- height: 18%;
900
- background: var(--grass);
901
- border-top: 2px solid var(--fence-dark);
902
- border-radius: 6px 6px 0 0;
903
- transition: background 1.5s, border-color 1.5s;
904
- }
905
-
906
- /* Fireflies (night only) */
907
- .scene-fireflies {
908
- position: absolute;
909
- top: 48%;
910
- left: 0;
911
- right: 0;
912
- bottom: 20%;
913
- pointer-events: none;
914
- opacity: 0;
915
- transition: opacity 1.5s;
916
- }
917
- .pip-scene[data-time="night"] .scene-fireflies { opacity: 1; }
918
-
919
- .firefly {
920
- position: absolute;
921
- width: 3px;
922
- height: 3px;
923
- border-radius: 50%;
924
- background: #ffe066;
925
- animation: firefly 3s ease-in-out infinite;
926
- }
927
- .firefly:nth-child(1) { top: 20%; left: 15%; animation-delay: 0s; }
928
- .firefly:nth-child(2) { top: 40%; left: 75%; animation-delay: 0.7s; }
929
- .firefly:nth-child(3) { top: 60%; left: 30%; animation-delay: 1.4s; }
930
- .firefly:nth-child(4) { top: 30%; left: 60%; animation-delay: 2.1s; }
931
- .firefly:nth-child(5) { top: 70%; left: 50%; animation-delay: 0.4s; }
932
- .firefly:nth-child(6) { top: 50%; left: 85%; animation-delay: 1.8s; }
933
-
934
- @keyframes firefly {
935
- 0%, 100% { opacity: 0; transform: translate(0, 0); }
936
- 20% { opacity: 1; }
937
- 50% { opacity: 0.8; transform: translate(5px, -4px); }
938
- 80% { opacity: 0.2; transform: translate(-2px, -6px); }
939
- }
940
-
941
- /* Night glow pulse on windows */
942
- .pip-scene[data-time="night"] .scene-window {
943
- animation: window-pulse 4s ease-in-out infinite;
944
- }
945
- @keyframes window-pulse {
946
- 0%, 100% { opacity: 1; }
947
- 50% { opacity: 0.8; }
948
  }
949
 
950
  .pip-container {
@@ -953,30 +350,27 @@ body {
953
  display: flex;
954
  flex-direction: column;
955
  align-items: center;
 
956
  height: 100%;
957
  padding: 0 0.5rem 0.4rem;
958
  }
959
 
960
- .house-spacer {
961
- flex: 0 0 45%;
962
- width: 100%;
963
- pointer-events: none;
964
- }
965
-
966
  .companion-wrap {
967
  display: flex;
968
  align-items: center;
969
  justify-content: center;
970
  flex-shrink: 0;
 
971
  }
972
 
973
  .speech-area {
974
- flex: 1;
975
  display: flex;
976
  align-items: flex-start;
977
  justify-content: center;
978
  padding-top: 0.25rem;
979
  min-height: 48px;
 
980
  }
981
 
982
  /* ─── SVG base styles ─────────────────────────────────────────────── */
 
325
  image-rendering: pixelated;
326
  }
327
 
328
+ /* ─── Cozy House Exterior (image-based, day/night) ────────────────── */
329
 
330
  .pip-scene {
331
  position: absolute;
332
  inset: 0;
333
  z-index: 0;
334
  overflow: hidden;
335
+ background-image: url('/static/day_house.jpg');
336
+ background-size: 200% 200%;
337
+ background-position: 50% 80%;
338
+ background-repeat: no-repeat;
339
+ transition: background-position 1.5s ease-in-out;
340
+ image-rendering: pixelated;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
341
  }
342
 
343
  .pip-scene[data-time="night"] {
344
+ background-image: url('/static/night_house.jpg');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
345
  }
346
 
347
  .pip-container {
 
350
  display: flex;
351
  flex-direction: column;
352
  align-items: center;
353
+ justify-content: flex-end;
354
  height: 100%;
355
  padding: 0 0.5rem 0.4rem;
356
  }
357
 
 
 
 
 
 
 
358
  .companion-wrap {
359
  display: flex;
360
  align-items: center;
361
  justify-content: center;
362
  flex-shrink: 0;
363
+ transition: transform 1.5s ease-in-out;
364
  }
365
 
366
  .speech-area {
367
+ flex: 0 0 auto;
368
  display: flex;
369
  align-items: flex-start;
370
  justify-content: center;
371
  padding-top: 0.25rem;
372
  min-height: 48px;
373
+ max-height: 60px;
374
  }
375
 
376
  /* ─── SVG base styles ─────────────────────────────────────────────── */