diff --git a/web-app/css/styles.css b/web-app/css/styles.css index 97de1fb..cfe0736 100644 --- a/web-app/css/styles.css +++ b/web-app/css/styles.css @@ -96,7 +96,7 @@ body { color: var(--text-color); line-height: 1.6; transition: background-color var(--motion-duration) ease, color var(--motion-duration) ease; - /* padding-bottom: 6rem; */ + padding-bottom: 6rem; /* reserve space for fixed footer */ } #main-content { @@ -2701,4 +2701,112 @@ body { padding: 0.3rem 0.7rem; font-size: 0.78rem; } +} + +/* ========================== + Modern Playground Card + ========================== */ +.playground-section { + padding: 1.75rem 0 2.5rem; /* reduced top space so playground sits below tabs */ +} + +.playground-card { + background: color-mix(in srgb, var(--panel-color) 85%, transparent); + border: 1px solid var(--border-color); + border-radius: 14px; + padding: 1rem; + box-shadow: 0 12px 30px rgba(2,8,23,0.48), 0 2px 6px rgba(0,0,0,0.35); + overflow: hidden; + position: relative; + z-index: 50; /* ensure card sits above hero canvas/snippets */ +} + +/* visually lift the playground card towards the tabs to reduce empty space */ +@media (min-width: 680px) { + .playground-card { margin-top: -0.8rem; } +} + +.playground-card-header { + display: flex; + align-items: center; + gap: 1rem; + justify-content: space-between; + padding: 0.6rem 0.6rem 0.8rem 0.6rem; + border-bottom: 1px solid rgba(255,255,255,0.02); +} + +.playground-card-header .title-wrap { + display:flex; align-items:baseline; gap:0.8rem; +} +.playground-card-header h2 { margin:0; font-size:1.3rem; } +.playground-card-header p { margin:0; color:var(--text-secondary); font-size:0.95rem; } + +.playground-badge { + display:inline-flex; align-items:center; gap:0.5rem; + background: linear-gradient(180deg, rgba(255,255,255,0.02), transparent); + padding: 0.35rem 0.6rem; border-radius: 999px; font-weight:700; font-size:0.85rem; + border:1px solid rgba(255,255,255,0.03); +} + +.playground-card-body { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 1rem; + align-items: stretch; + padding: 1rem 0 0 0; +} + +.editor-card, .console-card { + display:flex; flex-direction:column; background: var(--surface-color); + border-radius: 12px; border:1px solid var(--border-color); overflow: hidden; + box-shadow: var(--shadow); + height: 100%; + position: relative; z-index: 51; /* ensure inner cards are above decorative elements */ +} + +.card-header { + display:flex; align-items:center; justify-content:space-between; gap:0.6rem; + padding:0.6rem 0.85rem; background: linear-gradient(180deg, rgba(255,255,255,0.01), transparent); + border-bottom: 1px solid var(--border-color); + font-weight:600; color:var(--text-secondary); font-size:0.9rem; +} + +.card-title { display:flex; align-items:center; gap:0.6rem; } +.card-title .dot { width:10px; height:10px; border-radius:50%; background:var(--accent-color); box-shadow:0 0 8px var(--hero-green-glow); } + +.editor-body, .console-body { + flex:1 1 auto; display:flex; flex-direction:column; min-height:160px; max-height: calc(60vh); +} + +.editor-body textarea#pythonEditor { + width:100%; height:100%; padding:1rem; border:none; background: var(--panel-color); color:var(--text-color) !important; + caret-color: var(--accent-color); resize:vertical; outline:none; font-family: 'Cascadia Code', 'Fira Code', monospace; font-size:0.95rem; line-height:1.6; +} + +/* ensure placeholder remains readable */ +.editor-body textarea#pythonEditor::placeholder { color: var(--text-secondary); opacity:0.6; } + +.console-body pre.console-output { + width:100%; padding:1rem; margin:0; overflow:auto; background:transparent; color:var(--text-color); +} + +.playground-card-footer { + display:flex; align-items:center; justify-content:flex-start; gap:0.75rem; padding-top:1rem; +} + +.btn-run, .btn-stop { + border-radius: 999px; padding:0.7rem 1.6rem; font-weight:800; border:none; cursor:pointer; display:inline-flex; gap:0.6rem; align-items:center; +} +.btn-run { background: linear-gradient(135deg, #10b981, #059669); color:#fff; box-shadow: 0 8px 30px rgba(16,185,129,0.18); } +.btn-stop { background: linear-gradient(135deg, #c53030, #8b1a2b); color:#fff; box-shadow: 0 8px 22px rgba(197,63,80,0.12); } +.btn-run:disabled, .btn-stop:disabled { opacity:0.55; cursor:not-allowed; box-shadow:none; } + +/* responsive overrides */ +@media (max-width: 920px) { + .playground-card-body { grid-template-columns: 1fr; } + .editor-body, .console-body { max-height: none; } +} + +@media (prefers-reduced-motion: reduce) { + .playground-card, .editor-card, .console-card { transition:none !important; } } \ No newline at end of file diff --git a/web-app/index.html b/web-app/index.html index def5f9a..b118ab1 100644 --- a/web-app/index.html +++ b/web-app/index.html @@ -176,11 +176,23 @@ } /* ── Two-column editor / console layout ─────────────────────── */ + :root { + --pg-footer-space: 6rem; /* reserve space for fixed footer */ + --pg-controls-height: 88px; /* controls + header space buffer */ + } + .playground-body { display: grid; - grid-template-columns: 1fr 1fr; - gap: 1.5rem; - margin-bottom: 1.5rem; + grid-template-columns: minmax(360px, 1fr) minmax(360px, 1fr); + gap: 1rem 1.5rem; + margin-bottom: 1rem; + align-items: start; /* align panels to the top to avoid uneven stretching */ + } + + @media (max-width: 1100px) { + .playground-body { + grid-template-columns: 1fr 1fr; + } } @media (max-width: 768px) { @@ -199,6 +211,8 @@ border-radius: 16px; overflow: hidden; transition: border-color 0.25s ease; + /* cap panel height so content stays inside the viewport */ + max-height: calc(100vh - var(--pg-controls-height) - var(--pg-footer-space)); } .editor-panel:focus-within { @@ -255,17 +269,20 @@ /* ── Code textarea ──────────────────────────────────────────── */ #pythonEditor { - flex: 1; - min-height: 320px; - background: transparent; + flex: 1 1 auto; + min-height: 180px; + max-height: calc(100vh - var(--pg-controls-height) - var(--pg-footer-space) - 72px); + overflow: auto; + background: var(--panel-color); border: none; outline: none; resize: vertical; color: var(--text-color); + caret-color: var(--accent-color); font-family: 'Cascadia Code', 'Fira Code', 'Consolas', 'Courier New', monospace; font-size: 0.95rem; line-height: 1.65; - padding: 1.25rem; + padding: 1rem 1.25rem; tab-size: 4; } @@ -276,9 +293,10 @@ /* ── Console output ─────────────────────────────────────────── */ .console-output { - flex: 1; - min-height: 320px; - padding: 1.25rem; + flex: 1 1 auto; + min-height: 180px; + max-height: calc(100vh - var(--pg-controls-height) - var(--pg-footer-space) - 72px); + padding: 1rem 1.25rem; margin: 0; font-family: 'Cascadia Code', 'Fira Code', 'Consolas', 'Courier New', monospace; font-size: 0.9rem; @@ -1030,40 +1048,53 @@

Word Scramble

Unscramble words before attempts run out!

- +
+
+
+
+

🐍 Interactive Python Playground

+

Write and execute Python code instantly — powered by Pyodide.

+ Python
- -
- -
-
- Output Console - +
+ +
Open the tab to load Python
-

+                    
+
+                    
+
+
+
Code Editor
+
+ + +
+
+
+ +
+
+ +
+
+
Output Console
+
+ +
+
+
+

+                            
+
-
-
- - +