diff --git a/.gitignore b/.gitignore index b5b4194..a6845f5 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,5 @@ dist build .github .vscode -.DS_Store \ No newline at end of file +.DS_Store +.claude \ No newline at end of file diff --git a/client/package-lock.json b/client/package-lock.json index f130dda..9c61028 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -637,7 +637,6 @@ "resolved": "https://registry.npmjs.org/svelte/-/svelte-3.53.1.tgz", "integrity": "sha512-Q4/hHkktZogGhN5iqxqSi9sjEVoe/NbIxX4hXEHoasTxj+TxEQVAq66LnDMdAZxjmsodkoI5F3slqsS68U7FNw==", "dev": true, - "peer": true, "engines": { "node": ">= 8" } @@ -659,7 +658,6 @@ "resolved": "https://registry.npmjs.org/vite/-/vite-3.2.3.tgz", "integrity": "sha512-h8jl1TZ76eGs3o2dIBSsvXDLb1m/Ec1iej8ZMdz+PsaFUsftZeWe2CZOI3qogEsMNaywc17gu0q6cQDzh/weCQ==", "dev": true, - "peer": true, "dependencies": { "esbuild": "^0.15.9", "postcss": "^8.4.18", @@ -1041,8 +1039,7 @@ "version": "3.53.1", "resolved": "https://registry.npmjs.org/svelte/-/svelte-3.53.1.tgz", "integrity": "sha512-Q4/hHkktZogGhN5iqxqSi9sjEVoe/NbIxX4hXEHoasTxj+TxEQVAq66LnDMdAZxjmsodkoI5F3slqsS68U7FNw==", - "dev": true, - "peer": true + "dev": true }, "svelte-hmr": { "version": "0.15.0", @@ -1056,7 +1053,6 @@ "resolved": "https://registry.npmjs.org/vite/-/vite-3.2.3.tgz", "integrity": "sha512-h8jl1TZ76eGs3o2dIBSsvXDLb1m/Ec1iej8ZMdz+PsaFUsftZeWe2CZOI3qogEsMNaywc17gu0q6cQDzh/weCQ==", "dev": true, - "peer": true, "requires": { "esbuild": "^0.15.9", "fsevents": "~2.3.2", diff --git a/client/public/group-photo.jpg b/client/public/group-photo.jpg new file mode 100644 index 0000000..ba25fc8 Binary files /dev/null and b/client/public/group-photo.jpg differ diff --git a/client/src/app.css b/client/src/app.css index bcc7233..dcf9269 100644 --- a/client/src/app.css +++ b/client/src/app.css @@ -1,12 +1,56 @@ +@font-face { + font-family: 'Phantom Sans'; + src: url('https://assets.hackclub.com/fonts/Phantom_Sans_0.7/Regular.woff2') format('woff2'), + url('https://assets.hackclub.com/fonts/Phantom_Sans_0.7/Regular.woff') format('woff'); + font-weight: 400; + font-style: normal; + font-display: swap; +} + +@font-face { + font-family: 'Phantom Sans'; + src: url('https://assets.hackclub.com/fonts/Phantom_Sans_0.7/Italic.woff2') format('woff2'), + url('https://assets.hackclub.com/fonts/Phantom_Sans_0.7/Italic.woff') format('woff'); + font-weight: 400; + font-style: italic; + font-display: swap; +} + +@font-face { + font-family: 'Phantom Sans'; + src: url('https://assets.hackclub.com/fonts/Phantom_Sans_0.7/Bold.woff2') format('woff2'), + url('https://assets.hackclub.com/fonts/Phantom_Sans_0.7/Bold.woff') format('woff'); + font-weight: 700; + font-style: normal; + font-display: swap; +} + :root { - font-family: Inter, Avenir, Helvetica, Arial, sans-serif; + --red: #ec3750; + --orange: #ff8c37; + --yellow: #f1c40f; + --green: #33d6a6; + --cyan: #5bc0de; + --blue: #338eda; + --purple: #a633d6; + --muted: #8492a6; + --darker: #121217; + --dark: #17171d; + --darkless: #252429; + --black: #1f2d3d; + --steel: #273444; + --slate: #3c4858; + --smoke: #e0e6ed; + --snow: #f9fafc; + --white: #ffffff; + + font-family: 'Phantom Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; font-size: 16px; - line-height: 24px; + line-height: 1.5; font-weight: 400; - color-scheme: light dark; - color: rgba(255, 255, 255, 0.87); - background-color: #242424; + color: var(--black); + background-color: var(--snow); font-synthesis: none; text-rendering: optimizeLegibility; @@ -15,67 +59,40 @@ -webkit-text-size-adjust: 100%; } -a { - font-weight: 500; - color: #646cff; - text-decoration: inherit; -} -a:hover { - color: #535bf2; +* { + box-sizing: border-box; } body { margin: 0; - display: flex; - place-items: center; min-width: 320px; min-height: 100vh; } -h1 { - font-size: 3.2em; - line-height: 1.1; -} - -.card { - padding: 2em; -} - #app { - max-width: 1280px; - margin: 0 auto; - padding: 2rem; - text-align: center; + width: 100%; + min-height: 100vh; +} + +a { + color: var(--blue); + text-decoration: none; + transition: color 0.125s ease-in-out; +} + +a:hover { + color: var(--red); +} + +h1, h2, h3, h4, h5, h6 { + font-weight: bold; + line-height: 1.2; } button { - border-radius: 8px; - border: 1px solid transparent; - padding: 0.6em 1.2em; - font-size: 1em; - font-weight: 500; - font-family: inherit; - background-color: #1a1a1a; - cursor: pointer; - transition: border-color 0.25s; -} -button:hover { - border-color: #646cff; -} -button:focus, -button:focus-visible { - outline: 4px auto -webkit-focus-ring-color; + font-family: 'Phantom Sans', sans-serif; } -@media (prefers-color-scheme: light) { - :root { - color: #213547; - background-color: #ffffff; - } - a:hover { - color: #747bff; - } - button { - background-color: #f9f9f9; - } +input, textarea, select { + font-family: 'Phantom Sans', sans-serif; } diff --git a/client/src/lib/Auth.svelte b/client/src/lib/Auth.svelte index 844b8d5..45031b9 100644 --- a/client/src/lib/Auth.svelte +++ b/client/src/lib/Auth.svelte @@ -1,22 +1,23 @@ -
-
-

Hack Club Spaces

- - {#if mode === 'login' || mode === 'signup'} -
- - + + + + + + Hack Club + + +
+
+
+
+ +

{displayMode === 'signup' ? 'Join Hack Club Spaces' : 'Welcome Back'}

+

Lorem ipsum dolor sit amet

- -
-
- - -
- - {#if mode === 'signup'} + + {#if mode === 'login' || mode === 'signup'} +
- + +
+ +
+ +
- {/if} - - {#if error} -
{error}
- {/if} - - {#if message} -
{message}
- {/if} - - -
- {:else if mode === 'verify'} -

Check your email for the verification code

- -
-
- - + + {#if error} +
{error}
+ {/if} + + {#if message} +
{message}
+ {/if} + + + + +
+ {#if mode === 'login'} + Don't have an account? switchMode('signup')} on:keypress={(e) => e.key === 'Enter' && switchMode('signup')} role="button" tabindex="0">Sign up + {:else} + Already have an account? switchMode('login')} on:keypress={(e) => e.key === 'Enter' && switchMode('login')} role="button" tabindex="0">Log in + {/if}
- - {#if error} -
{error}
- {/if} - - - - - - {/if} + {:else if mode === 'verify'} +

Check your email for the verification code

+ +
+
+ + +
+ + {#if error} +
{error}
+ {/if} + + + + +
+ {/if} +
+
+ +
+
+ Hack Club Shipwrecked +
+ Hackers at Shipwrecked, 2025 +
+
- - \ No newline at end of file diff --git a/client/src/lib/Dashboard.svelte b/client/src/lib/Dashboard.svelte index 9c480c1..e62908e 100644 --- a/client/src/lib/Dashboard.svelte +++ b/client/src/lib/Dashboard.svelte @@ -1,13 +1,13 @@ + + + +
-
-
-

Hack Club Spaces

-

Welcome, {username}!

+
+
+ +
+

Hack Club Spaces

+

Welcome, {username}!

+
- +
- -
+ +
- -
- + {#if showCreateForm}
-

Create New Space

- +

Create New Space

+
- - + +
+ +
+
+ {#each spaceTypes as spaceType} +
selectSpaceType(spaceType.value)} + on:keypress={(e) => e.key === 'Enter' && selectSpaceType(spaceType.value)} + role="option" + tabindex="0" + aria-selected={spaceType.value === newSpaceType} + > +
{spaceType.label}
+
{spaceType.description}
+
+ {/each} +
+
- +
- - + +
+ {#if showPassword} + + {:else} + + {/if} + +
- + {#if error} -
{error}
+
{error}
{/if} - -
{/if} - +
-

Your Spaces

- +

Your Spaces

+ {#if spaces.length === 0}

No spaces yet. Create your first space to get started!

@@ -257,19 +330,16 @@ {#each spaces as space}
-

{space.type}

- +

{space.type}

+ {space.status || 'Unknown'}
- +

Space ID: {space.id}

{#if space.url} -

URL: +

URL: {space.url} @@ -277,11 +347,11 @@ {/if}

Created: {new Date(space.created_at).toLocaleString()}

- + {#if actionError[space.id]} -
{actionError[space.id]}
+
{actionError[space.id]}
{/if} - +
{#if actionLoading[space.id]} {:else} {#if space.status?.toLowerCase() === 'running'} - {#if space.url} - @@ -306,15 +376,15 @@ {/if} {:else} - {/if} -
- - \ No newline at end of file diff --git a/client/src/styles/auth.css b/client/src/styles/auth.css new file mode 100644 index 0000000..7b9f874 --- /dev/null +++ b/client/src/styles/auth.css @@ -0,0 +1,322 @@ +.auth-container { + display: flex; + min-height: 100vh; + background: #f9fafc; + position: relative; + overflow: hidden; +} + +.auth-panel { + width: 50%; + display: flex; + align-items: center; + justify-content: center; + position: absolute; + height: 100%; + top: 0; + transition: left 1s cubic-bezier(0.65, 0, 0.35, 1), right 1s cubic-bezier(0.65, 0, 0.35, 1); +} + +.auth-form-panel { + background: #ffffff; + left: 0; + padding: 64px; +} + +.auth-image-panel { + background: #f9fafc; + right: 0; + padding: 0; +} + +.auth-container.signup-mode .auth-form-panel { + left: 50%; +} + +.auth-container.signup-mode .auth-image-panel { + right: 50%; +} + +.auth-form-content { + width: 100%; + max-width: 440px; +} + +.auth-image-content { + width: 100%; + height: 100%; + position: relative; +} + +.auth-image { + width: 100%; + height: 100%; + object-fit: cover; +} + +.auth-image-content::before { + content: ''; + position: absolute; + top: 0; + left: 0; + right: 0; + height: 120px; + background: linear-gradient(to bottom, rgba(249, 250, 252, 0.3) 0%, transparent 100%); + pointer-events: none; + z-index: 1; +} + +.auth-image-content::after { + content: ''; + position: absolute; + top: 0; + bottom: 0; + left: 0; + width: 60px; + background: linear-gradient(to right, rgba(249, 250, 252, 0.2) 0%, transparent 100%); + pointer-events: none; + z-index: 1; +} + +.image-caption { + position: absolute; + bottom: 32px; + left: 32px; + font-size: 16px; + font-weight: bold; + color: #ffffff; + z-index: 2; + text-shadow: 0 2px 8px rgba(0, 0, 0, 0.5); +} + +.image-caption a { + color: #ffffff; + text-decoration: underline; + transition: opacity 0.125s ease-in-out; +} + +.image-caption a:hover { + opacity: 0.8; +} + +.flag-banner { + position: absolute; + top: 0; + left: 10px; + width: 256px; + z-index: 999; + border: 0; +} + +.auth-header { + margin-bottom: 48px; +} + +.auth-logo { + width: 56px; + height: 56px; + margin-bottom: 16px; +} + +.auth-title { + font-size: 36px; + font-weight: bold; + color: #1f2d3d; + margin: 0 0 8px 0; + line-height: 1.2; + transition: opacity 0.3s ease-in-out; +} + +.auth-subtitle { + font-size: 18px; + color: #8492a6; + margin: 0; + line-height: 1.5; + transition: opacity 0.3s ease-in-out; +} + +.auth-mode-switch { + text-align: center; + margin-top: 24px; + font-size: 16px; + color: #8492a6; +} + +.auth-mode-link { + color: #ec3750; + font-weight: bold; + cursor: pointer; + transition: color 0.125s ease-in-out; + text-decoration: underline; +} + +.auth-mode-link:hover { + color: #ff8c37; +} + +.form-group { + margin-bottom: 24px; + transition: opacity 0.6s ease-in-out, max-height 0.8s ease-in-out, margin 0.8s ease-in-out; +} + +.username-field { + max-height: 0; + opacity: 0; + margin-bottom: 0; + overflow: hidden; +} + +.username-field.show { + max-height: 200px; + opacity: 1; + margin-bottom: 24px; +} + +.form-label { + display: block; + margin-bottom: 8px; + font-size: 16px; + font-weight: bold; + color: #1f2d3d; +} + +.form-input { + width: 100%; + padding: 14px 16px; + border: 2px solid #e0e6ed; + border-radius: 8px; + background: #ffffff; + color: #1f2d3d; + font-size: 16px; + font-family: Phantom Sans, sans-serif; + box-sizing: border-box; + transition: border-color 0.125s ease-in-out, box-shadow 0.125s ease-in-out; +} + +.form-input:focus { + outline: none; + border-color: #338eda; + box-shadow: 0 0 0 3px rgba(51, 142, 218, 0.1); +} + +.form-input::placeholder { + color: #8492a6; +} + +.primary-button { + width: 100%; + padding: 16px 32px; + margin-top: 8px; + border: none; + border-radius: 99999px; + background: #ec3750; + color: #ffffff; + font-size: 18px; + font-weight: bold; + font-family: Phantom Sans, sans-serif; + cursor: pointer; + display: inline-flex; + align-items: center; + justify-content: center; + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.125); + transition: transform 0.125s ease-in-out, box-shadow 0.125s ease-in-out; + -webkit-tap-highlight-color: transparent; +} + +.primary-button:hover:not(:disabled) { + transform: scale(1.0625); + box-shadow: 0 8px 16px rgba(0, 0, 0, 0.2); +} + +.primary-button:active:not(:disabled) { + transform: scale(1); +} + +.primary-button:disabled { + opacity: 0.5; + cursor: not-allowed; +} + +.secondary-button { + width: 100%; + padding: 16px 32px; + margin-top: 16px; + background: transparent; + border: 2px solid #ec3750; + border-radius: 99999px; + color: #ec3750; + font-size: 18px; + font-weight: bold; + font-family: Phantom Sans, sans-serif; + cursor: pointer; + display: inline-flex; + align-items: center; + justify-content: center; + transition: transform 0.125s ease-in-out, box-shadow 0.125s ease-in-out; + -webkit-tap-highlight-color: transparent; +} + +.secondary-button:hover { + transform: scale(1.0625); + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.125); +} + +.secondary-button:active { + transform: scale(1); +} + +.error-message { + padding: 12px 16px; + margin-bottom: 16px; + background: rgba(236, 55, 80, 0.1); + border: 2px solid #ec3750; + border-radius: 8px; + color: #ec3750; + font-size: 16px; +} + +.success-message { + padding: 12px 16px; + margin-bottom: 16px; + background: rgba(51, 214, 166, 0.1); + border: 2px solid #33d6a6; + border-radius: 8px; + color: #33d6a6; + font-size: 16px; +} + +.info-message { + text-align: center; + margin-bottom: 24px; + color: #8492a6; + font-size: 16px; +} + + +@media (max-width: 768px) { + .auth-container { + flex-direction: column; + } + + .auth-panel { + padding: 32px; + } + + .auth-form-panel { + order: 1 !important; + min-height: auto; + } + + .auth-image-panel { + order: 2 !important; + min-height: 300px; + } + + .flag-banner { + width: 128px; + } + + .auth-title { + font-size: 28px; + } +} diff --git a/client/src/styles/dashboard.css b/client/src/styles/dashboard.css new file mode 100644 index 0000000..c517530 --- /dev/null +++ b/client/src/styles/dashboard.css @@ -0,0 +1,503 @@ +.dashboard { + min-height: 100vh; + padding: 32px; + background: #f9fafc; +} + +.dashboard-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 64px; + padding-bottom: 32px; + border-bottom: 2px solid #e0e6ed; +} + +.header-content { + display: flex; + align-items: center; + gap: 16px; +} + +.dashboard-logo { + width: 48px; + height: 48px; +} + +.dashboard-title { + font-size: 32px; + font-weight: bold; + color: #1f2d3d; + margin: 0; +} + +.welcome-text { + margin: 8px 0 0 0; + font-size: 16px; + color: #8492a6; +} + +.signout-button { + padding: 12px 24px; + background: transparent; + border: 2px solid #ec3750; + border-radius: 99999px; + color: #ec3750; + font-size: 16px; + font-weight: bold; + font-family: Phantom Sans, sans-serif; + cursor: pointer; + transition: transform 0.125s ease-in-out, box-shadow 0.125s ease-in-out; + -webkit-tap-highlight-color: transparent; +} + +.signout-button:hover { + transform: scale(1.0625); + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.125); +} + +.signout-button:active { + transform: scale(1); +} + +.dashboard-content { + max-width: 1200px; + margin: 0 auto; +} + +.actions-bar { + display: flex; + gap: 16px; + margin-bottom: 32px; +} + +.btn-primary { + padding: 14px 32px; + background: #ec3750; + color: #ffffff; + border: none; + border-radius: 99999px; + font-size: 16px; + font-weight: bold; + font-family: Phantom Sans, sans-serif; + cursor: pointer; + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.125); + transition: transform 0.125s ease-in-out, box-shadow 0.125s ease-in-out; + -webkit-tap-highlight-color: transparent; +} + +.btn-primary:hover:not(:disabled) { + transform: scale(1.0625); + box-shadow: 0 8px 16px rgba(0, 0, 0, 0.2); +} + +.btn-primary:active:not(:disabled) { + transform: scale(1); +} + +.btn-primary:disabled { + opacity: 0.5; + cursor: not-allowed; +} + +.btn-secondary { + padding: 14px 32px; + background: transparent; + border: 2px solid #ec3750; + border-radius: 99999px; + color: #ec3750; + font-size: 16px; + font-weight: bold; + font-family: Phantom Sans, sans-serif; + cursor: pointer; + transition: transform 0.125s ease-in-out, box-shadow 0.125s ease-in-out; + -webkit-tap-highlight-color: transparent; +} + +.btn-secondary:hover { + transform: scale(1.0625); + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.125); +} + +.btn-secondary:active { + transform: scale(1); +} + +.create-form { + background: #ffffff; + padding: 32px; + border-radius: 8px; + margin-bottom: 32px; + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.125); +} + +.create-form-title { + margin: 0 0 24px 0; + font-size: 24px; + font-weight: bold; + color: #1f2d3d; +} + +.form-group { + margin-bottom: 24px; +} + +.form-label { + display: block; + margin-bottom: 8px; + font-size: 16px; + font-weight: bold; + color: #1f2d3d; +} + +.form-input { + width: 100%; + padding: 14px 16px; + border: 2px solid #e0e6ed; + border-radius: 8px; + background: #ffffff; + color: #1f2d3d; + font-size: 16px; + font-family: Phantom Sans, sans-serif; + box-sizing: border-box; + transition: border-color 0.125s ease-in-out, box-shadow 0.125s ease-in-out; +} + +.form-input:focus { + outline: none; + border-color: #338eda; + box-shadow: 0 0 0 3px rgba(51, 142, 218, 0.1); +} + +.password-input-wrapper { + position: relative; + width: 100%; +} + +.password-input { + padding-right: 48px; +} + +.password-toggle { + position: absolute; + right: 12px; + top: 50%; + transform: translateY(-50%); + background: transparent; + border: none; + cursor: pointer; + padding: 4px; + display: flex; + align-items: center; + justify-content: center; + transition: opacity 0.125s ease-in-out; +} + +.password-toggle:hover { + opacity: 0.7; +} + +.password-toggle img { + width: 20px; + height: 20px; + filter: opacity(0.6); + transition: filter 0.125s ease-in-out; +} + +.password-toggle:hover img { + filter: opacity(1); +} + +.custom-select { + position: relative; + width: 100%; +} + +.select-trigger { + width: 100%; + padding: 14px 16px; + padding-right: 48px; + border: 2px solid #e0e6ed; + border-radius: 8px; + background: #ffffff; + color: #1f2d3d; + font-size: 16px; + font-family: Phantom Sans, sans-serif; + font-weight: bold; + cursor: pointer; + box-sizing: border-box; + transition: border-color 0.125s ease-in-out, box-shadow 0.125s ease-in-out; + text-align: left; +} + +.select-trigger:hover { + border-color: #338eda; +} + +.select-trigger.open { + border-color: #338eda; + box-shadow: 0 0 0 3px rgba(51, 142, 218, 0.1); +} + +.select-arrow { + position: absolute; + right: 16px; + top: 50%; + transform: translateY(-50%); + width: 0; + height: 0; + border-left: 6px solid transparent; + border-right: 6px solid transparent; + border-top: 6px solid #3c4858; + transition: transform 0.125s ease-in-out; + pointer-events: none; +} + +.select-arrow.open { + transform: translateY(-50%) rotate(180deg); +} + +.select-dropdown { + position: absolute; + top: calc(100% + 8px); + left: 0; + right: 0; + background: #ffffff; + border: 2px solid #338eda; + border-radius: 8px; + box-shadow: 0 8px 16px rgba(0, 0, 0, 0.1); + z-index: 100; + max-height: 0; + overflow: hidden; + opacity: 0; + transition: max-height 0.25s ease-in-out, opacity 0.25s ease-in-out; +} + +.select-dropdown.open { + max-height: 300px; + opacity: 1; + overflow-y: auto; +} + +.select-option { + padding: 14px 16px; + cursor: pointer; + transition: background-color 0.125s ease-in-out; + border-bottom: 1px solid #e0e6ed; +} + +.select-option:last-child { + border-bottom: none; +} + +.select-option:hover { + background: #f9fafc; +} + +.select-option.selected { + background: rgba(51, 142, 218, 0.1); + color: #338eda; + font-weight: bold; +} + +.option-label { + font-size: 16px; + font-weight: bold; + color: #1f2d3d; + margin-bottom: 4px; +} + +.option-description { + font-size: 14px; + color: #8492a6; +} + +.error-message { + padding: 12px 16px; + margin-bottom: 16px; + background: rgba(236, 55, 80, 0.1); + border: 2px solid #ec3750; + border-radius: 8px; + color: #ec3750; + font-size: 16px; +} + +.error-message.small { + padding: 8px 12px; + font-size: 14px; +} + +.section-title { + font-size: 24px; + font-weight: bold; + color: #1f2d3d; + margin: 0 0 24px 0; +} + +.empty-state { + text-align: center; + padding: 64px 32px; + color: #8492a6; + font-size: 16px; +} + +.spaces-grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); + gap: 24px; +} + +.space-card { + background: #ffffff; + padding: 24px; + border-radius: 8px; + border: 2px solid #e0e6ed; + transition: border-color 0.125s ease-in-out, box-shadow 0.125s ease-in-out; +} + +.space-card:hover { + border-color: #338eda; + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.125); +} + +.space-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 16px; +} + +.space-type { + font-size: 20px; + font-weight: bold; + color: #1f2d3d; + margin: 0; + text-transform: capitalize; +} + +.status-badge { + padding: 4px 12px; + border-radius: 99999px; + font-size: 14px; + font-weight: bold; + color: #ffffff; +} + +.status-running { + background: #33d6a6; +} + +.status-stopped { + background: #ec3750; +} + +.status-created { + background: #f1c40f; +} + +.status-unknown { + background: #8492a6; +} + +.space-info { + margin-bottom: 16px; + font-size: 14px; +} + +.space-info p { + margin: 8px 0; + color: #8492a6; +} + +.space-info strong { + color: #3c4858; +} + +.space-info a { + color: #338eda; + text-decoration: none; + transition: color 0.125s ease-in-out; +} + +.space-info a:hover { + color: #ec3750; + text-decoration: underline; +} + +.space-actions { + display: flex; + gap: 8px; +} + +.action-btn { + flex: 1; + padding: 10px 16px; + border-radius: 99999px; + border: none; + font-size: 14px; + font-weight: bold; + font-family: Phantom Sans, sans-serif; + cursor: pointer; + transition: transform 0.125s ease-in-out; + text-decoration: none; + display: flex; + align-items: center; + justify-content: center; + -webkit-tap-highlight-color: transparent; +} + +.action-btn:hover:not(:disabled) { + transform: scale(1.0625); +} + +.action-btn:active:not(:disabled) { + transform: scale(1); +} + +.action-btn:disabled { + opacity: 0.5; + cursor: not-allowed; +} + +.action-btn.start { + background: #33d6a6; + color: #ffffff; +} + +.action-btn.stop { + background: #ec3750; + color: #ffffff; +} + +.action-btn.open { + background: #338eda; + color: #ffffff; +} + +.action-btn.refresh { + background: transparent; + border: 2px solid #338eda; + color: #338eda; + flex: 0 0 auto; + min-width: 44px; +} + +@media (max-width: 768px) { + .dashboard { + padding: 16px; + } + + .dashboard-header { + flex-direction: column; + align-items: flex-start; + gap: 16px; + } + + .actions-bar { + flex-direction: column; + } + + .spaces-grid { + grid-template-columns: 1fr; + } +}