extremely claude-assisted go game based on atproto! working on cleaning up and giving a more unique design, still has a bit of a slop vibe to it.
1<script lang="ts">
2 interface Props {
3 isOpen: boolean;
4 onClose: () => void;
5 class?: string;
6 children?: any;
7 }
8
9 let { isOpen, onClose, class: className = '', children }: Props = $props();
10
11 function handleKeydown(e: KeyboardEvent) {
12 if (e.key === 'Escape') {
13 onClose();
14 }
15 }
16</script>
17
18{#if isOpen}
19 <div
20 class="modal-overlay"
21 onclick={onClose}
22 onkeydown={handleKeydown}
23 role="button"
24 tabindex="0"
25 >
26 <div
27 class="modal-content cloud-card {className}"
28 onclick={(e) => e.stopPropagation()}
29 role="dialog"
30 aria-modal="true"
31 >
32 <button class="modal-close" onclick={onClose} aria-label="Close modal">
33 ✕
34 </button>
35 {@render children?.()}
36 </div>
37 </div>
38{/if}
39
40<style>
41 .modal-overlay {
42 position: fixed;
43 top: 0;
44 left: 0;
45 width: 100%;
46 height: 100%;
47 background: rgba(90, 122, 144, 0.3);
48 backdrop-filter: blur(4px);
49 z-index: 1000;
50 display: flex;
51 align-items: center;
52 justify-content: center;
53 padding: 1rem;
54 animation: fadeIn 0.2s ease-out;
55 }
56
57 .modal-content {
58 max-width: 650px;
59 width: 100%;
60 max-height: 90vh;
61 overflow: visible;
62 animation: slideIn 0.3s ease-out;
63 display: flex;
64 flex-direction: column;
65 background: linear-gradient(
66 135deg,
67 rgba(255, 255, 255, 0.95) 0%,
68 rgba(245, 248, 250, 0.9) 50%,
69 rgba(232, 239, 244, 0.85) 100%
70 );
71 border: none;
72 border-radius: 2rem 2.5rem 2rem 2.2rem;
73 box-shadow:
74 0 0 20px rgba(255, 255, 255, 0.8),
75 0 0 40px rgba(255, 255, 255, 0.4),
76 0 8px 32px rgba(90, 122, 144, 0.12),
77 inset 0 1px 1px rgba(255, 255, 255, 0.9);
78 backdrop-filter: blur(8px);
79 position: relative;
80 }
81
82 .modal-content::before {
83 content: '';
84 position: absolute;
85 inset: -2px;
86 border-radius: inherit;
87 background: linear-gradient(
88 135deg,
89 rgba(255, 255, 255, 0.6) 0%,
90 rgba(212, 229, 239, 0.3) 50%,
91 rgba(255, 255, 255, 0.4) 100%
92 );
93 filter: blur(4px);
94 z-index: -1;
95 }
96
97 .modal-close {
98 position: absolute;
99 top: 1rem;
100 right: 1rem;
101 background: transparent;
102 border: none;
103 font-size: 1.5rem;
104 color: var(--sky-slate);
105 cursor: pointer;
106 width: 2rem;
107 height: 2rem;
108 display: flex;
109 align-items: center;
110 justify-content: center;
111 border-radius: 0.5rem;
112 transition: all 0.6s ease;
113 z-index: 10;
114 }
115
116 .modal-close:hover {
117 background: var(--sky-apricot-light);
118 color: var(--sky-apricot-dark);
119 transform: rotate(90deg);
120 }
121
122 @keyframes fadeIn {
123 from {
124 opacity: 0;
125 }
126 to {
127 opacity: 1;
128 }
129 }
130
131 @keyframes slideIn {
132 from {
133 opacity: 0;
134 transform: translateY(-20px);
135 }
136 to {
137 opacity: 1;
138 transform: translateY(0);
139 }
140 }
141</style>