percolation
This commit is contained in:
13
projects/cellular_automata/asset-manifest.json
Normal file
13
projects/cellular_automata/asset-manifest.json
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"files": {
|
||||
"main.css": "/projects/cellular_automata/static/css/main.5cae1eb5.css",
|
||||
"main.js": "/projects/cellular_automata/static/js/main.608a23ae.js",
|
||||
"index.html": "/projects/cellular_automata/index.html",
|
||||
"main.5cae1eb5.css.map": "/projects/cellular_automata/static/css/main.5cae1eb5.css.map",
|
||||
"main.608a23ae.js.map": "/projects/cellular_automata/static/js/main.608a23ae.js.map"
|
||||
},
|
||||
"entrypoints": [
|
||||
"static/css/main.5cae1eb5.css",
|
||||
"static/js/main.608a23ae.js"
|
||||
]
|
||||
}
|
||||
BIN
projects/cellular_automata/favicon.ico
Normal file
BIN
projects/cellular_automata/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.8 KiB |
1
projects/cellular_automata/index.html
Normal file
1
projects/cellular_automata/index.html
Normal file
@@ -0,0 +1 @@
|
||||
<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="icon" href="/projects/cellular_automata/favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><meta name="description" content="Web site created using create-react-app"/><link rel="apple-touch-icon" href="/projects/cellular_automata/logo192.png"/><link rel="manifest" href="/projects/cellular_automata/manifest.json"/><title>React App</title><script defer="defer" src="/projects/cellular_automata/static/js/main.608a23ae.js"></script><link href="/projects/cellular_automata/static/css/main.5cae1eb5.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>
|
||||
BIN
projects/cellular_automata/logo192.png
Normal file
BIN
projects/cellular_automata/logo192.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.2 KiB |
BIN
projects/cellular_automata/logo512.png
Normal file
BIN
projects/cellular_automata/logo512.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 9.4 KiB |
25
projects/cellular_automata/manifest.json
Normal file
25
projects/cellular_automata/manifest.json
Normal file
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"short_name": "React App",
|
||||
"name": "Create React App Sample",
|
||||
"icons": [
|
||||
{
|
||||
"src": "favicon.ico",
|
||||
"sizes": "64x64 32x32 24x24 16x16",
|
||||
"type": "image/x-icon"
|
||||
},
|
||||
{
|
||||
"src": "logo192.png",
|
||||
"type": "image/png",
|
||||
"sizes": "192x192"
|
||||
},
|
||||
{
|
||||
"src": "logo512.png",
|
||||
"type": "image/png",
|
||||
"sizes": "512x512"
|
||||
}
|
||||
],
|
||||
"start_url": ".",
|
||||
"display": "standalone",
|
||||
"theme_color": "#000000",
|
||||
"background_color": "#ffffff"
|
||||
}
|
||||
3
projects/cellular_automata/robots.txt
Normal file
3
projects/cellular_automata/robots.txt
Normal file
@@ -0,0 +1,3 @@
|
||||
# https://www.robotstxt.org/robotstxt.html
|
||||
User-agent: *
|
||||
Disallow:
|
||||
2
projects/cellular_automata/static/css/main.5cae1eb5.css
Normal file
2
projects/cellular_automata/static/css/main.5cae1eb5.css
Normal file
@@ -0,0 +1,2 @@
|
||||
#root,body,html{margin:0;min-height:100%}body{background:radial-gradient(circle at top,#eef4ff 0,#f8fbff 55%,#eef2f7 100%);color:#0f172a;font-family:Segoe UI,sans-serif}.cell{border:1px solid #1f2937;box-sizing:border-box;margin:0;padding:0}.dead{background:#000}.alive{background:#fff}.board{border:1px solid #94a3b8;cursor:crosshair;display:inline-block;-webkit-user-select:none;user-select:none}.row{display:flex}.horizontal-slider{margin:auto;width:100%}.example-thumb{background:#fff;border:5px solid #3774ff;border-radius:100%;box-shadow:0 0 2px 0 #00000070;cursor:pointer;display:block;position:absolute;z-index:100}.example-thumb.active{background-color:grey}.example-track{background:#ddd;position:relative}.example-track.example-track-0{background:#83a9ff}.horizontal-slider .example-track{height:4px;top:20px}.horizontal-slider .example-thumb{height:10px;line-height:38px;outline:none;top:12px;width:10px}.radioGroup{grid-gap:.45rem;display:grid;gap:.45rem}.radioOption{align-items:center;color:#1e293b;cursor:pointer;display:flex;font-size:.92rem;gap:.5rem}.radioOption input{accent-color:#2f7df6;margin:0}.title{margin:2rem 0 1.25rem;text-align:center}.title h1{color:#0f172a;font-size:2.2rem;letter-spacing:.03em;margin:0}.title p{color:#475569;font-size:.95rem;margin:.35rem 0 0}.body{align-items:flex-start;display:flex;gap:1.25rem;justify-content:center;margin:0 auto 1.75rem;max-width:980px;padding:0 1rem}.gameBoard{padding:.6rem}.controlPanel,.gameBoard{background:#fff;border:1px solid #d5deea;border-radius:12px;box-shadow:0 12px 28px #0f172a1a}.controlPanel{color:#1e293b;padding:1rem;width:270px}.panelSection{margin-bottom:1rem}.panelSection h3{color:#334155;font-size:.95rem;margin:0 0 .5rem}.buttonRow{grid-gap:.5rem;display:grid;gap:.5rem;grid-template-columns:repeat(3,1fr);margin-bottom:1.1rem}.controlButton{background:#f8fafc;border:1px solid #cbd5e1;border-radius:8px;color:#1e293b;cursor:pointer;font-weight:500;padding:.45rem .35rem}.controlButton:hover{background:#eef2f8}.sliderContainer{grid-gap:.25rem;display:grid;gap:.25rem}.sliderContainer span{color:#334155;font-size:.95rem}.fpsValue{color:#64748b;font-size:.85rem;margin:.3rem 0 0}
|
||||
/*# sourceMappingURL=main.5cae1eb5.css.map*/
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"static/css/main.5cae1eb5.css","mappings":"AAAA,gBAGE,QAAS,CACT,eACF,CAEA,KAEE,4EAAiF,CACjF,aAAc,CAFd,+BAGF,CCXA,MAGE,wBAAyB,CACzB,qBAAsB,CAHtB,QAAS,CACT,SAGF,CAEA,MACE,eACF,CAEA,OACE,eACF,CCbA,OAEE,wBAAyB,CAEzB,gBAAiB,CAHjB,oBAAqB,CAErB,wBAAiB,CAAjB,gBAEF,CAEA,KACE,YACF,CCTA,mBAEE,WAAY,CADZ,UAEF,CAEA,eAIE,eAAmB,CACnB,wBAAyB,CACzB,kBAAmB,CAEnB,8BAAsC,CAPtC,cAAe,CAMf,aAAc,CALd,iBAAkB,CAClB,WAMF,CAEA,sBACE,qBACF,CAEA,eAEE,eAAgB,CADhB,iBAEF,CAEA,+BACE,kBACF,CAEA,kCAEE,UAAW,CADX,QAEF,CAEA,kCAIE,WAAY,CACZ,gBAAiB,CAFjB,YAAa,CAFb,QAAS,CACT,UAIF,CCxCA,YAEE,eAAY,CADZ,YAAa,CACb,UACF,CAEA,aAEE,kBAAmB,CAInB,aAAc,CADd,cAAe,CAJf,YAAa,CAGb,gBAAkB,CADlB,SAIF,CAEA,mBAEE,oBAAqB,CADrB,QAEF,CCjBA,OACE,qBAAsB,CACtB,iBACF,CAEA,UAIE,aAAc,CAFd,gBAAiB,CACjB,oBAAsB,CAFtB,QAIF,CAEA,SAGE,aAAc,CADd,gBAAkB,CADlB,iBAGF,CAEA,MAGE,sBAAuB,CAFvB,YAAa,CAGb,WAAY,CAFZ,sBAAuB,CAIvB,qBAAsB,CADtB,eAAgB,CAEhB,cACF,CAEA,WAIE,aAEF,CAEA,yBAPE,eAAmB,CACnB,wBAAyB,CACzB,kBAAmB,CAEnB,gCAWF,CARA,cAME,aAAc,CADd,YAAa,CAJb,WAOF,CAEA,cACE,kBACF,CAEA,iBAGE,aAAc,CADd,gBAAkB,CADlB,gBAGF,CAEA,WAGE,cAAW,CAFX,YAAa,CAEb,SAAW,CADX,mCAAqC,CAErC,oBACF,CAEA,eAEE,kBAAmB,CADnB,wBAAyB,CAGzB,iBAAkB,CADlB,aAAc,CAGd,cAAe,CACf,eAAgB,CAFhB,qBAGF,CAEA,qBACE,kBACF,CAEA,iBAEE,eAAY,CADZ,YAAa,CACb,UACF,CAEA,sBAEE,aAAc,CADd,gBAEF,CAEA,UAGE,aAAc,CADd,gBAAkB,CADlB,gBAGF","sources":["index.css","styles/cell.css","styles/board.css","styles/slider.css","styles/brushes.css","styles/game.css"],"sourcesContent":["html,\nbody,\n#root {\n margin: 0;\n min-height: 100%;\n}\n\nbody {\n font-family: \"Segoe UI\", sans-serif;\n background: radial-gradient(circle at top, #eef4ff 0%, #f8fbff 55%, #eef2f7 100%);\n color: #0f172a;\n}\n",".cell {\n margin: 0;\n padding: 0;\n border: 1px solid #1f2937;\n box-sizing: border-box;\n}\n\n.dead {\n background: #000000;\n}\n\n.alive {\n background: #ffffff;\n}\n",".board {\n display: inline-block;\n border: 1px solid #94a3b8;\n user-select: none;\n cursor: crosshair;\n}\n\n.row {\n display: flex;\n}\n",".horizontal-slider {\n width: 100%;\n margin: auto;\n}\n\n.example-thumb {\n cursor: pointer;\n position: absolute;\n z-index: 100;\n background: #ffffff;\n border: 5px solid #3774ff;\n border-radius: 100%;\n display: block;\n box-shadow: 0 0 2px 0 rgb(0 0 0 / 44%);\n}\n\n.example-thumb.active {\n background-color: grey;\n}\n\n.example-track {\n position: relative;\n background: #ddd;\n}\n\n.example-track.example-track-0 {\n background: #83a9ff;\n}\n\n.horizontal-slider .example-track {\n top: 20px;\n height: 4px;\n}\n\n.horizontal-slider .example-thumb {\n top: 12px;\n width: 10px;\n outline: none;\n height: 10px;\n line-height: 38px;\n}\n",".radioGroup {\n display: grid;\n gap: 0.45rem;\n}\n\n.radioOption {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n font-size: 0.92rem;\n cursor: pointer;\n color: #1e293b;\n}\n\n.radioOption input {\n margin: 0;\n accent-color: #2f7df6;\n}\n",".title {\n margin: 2rem 0 1.25rem;\n text-align: center;\n}\n\n.title h1 {\n margin: 0;\n font-size: 2.2rem;\n letter-spacing: 0.03em;\n color: #0f172a;\n}\n\n.title p {\n margin: 0.35rem 0 0;\n font-size: 0.95rem;\n color: #475569;\n}\n\n.body {\n display: flex;\n justify-content: center;\n align-items: flex-start;\n gap: 1.25rem;\n max-width: 980px;\n margin: 0 auto 1.75rem;\n padding: 0 1rem;\n}\n\n.gameBoard {\n background: #ffffff;\n border: 1px solid #d5deea;\n border-radius: 12px;\n padding: 0.6rem;\n box-shadow: 0 12px 28px rgb(15 23 42 / 10%);\n}\n\n.controlPanel {\n width: 270px;\n background: #ffffff;\n border: 1px solid #d5deea;\n border-radius: 12px;\n padding: 1rem;\n color: #1e293b;\n box-shadow: 0 12px 28px rgb(15 23 42 / 10%);\n}\n\n.panelSection {\n margin-bottom: 1rem;\n}\n\n.panelSection h3 {\n margin: 0 0 0.5rem;\n font-size: 0.95rem;\n color: #334155;\n}\n\n.buttonRow {\n display: grid;\n grid-template-columns: repeat(3, 1fr);\n gap: 0.5rem;\n margin-bottom: 1.1rem;\n}\n\n.controlButton {\n border: 1px solid #cbd5e1;\n background: #f8fafc;\n color: #1e293b;\n border-radius: 8px;\n padding: 0.45rem 0.35rem;\n cursor: pointer;\n font-weight: 500;\n}\n\n.controlButton:hover {\n background: #eef2f8;\n}\n\n.sliderContainer {\n display: grid;\n gap: 0.25rem;\n}\n\n.sliderContainer span {\n font-size: 0.95rem;\n color: #334155;\n}\n\n.fpsValue {\n margin: 0.3rem 0 0;\n font-size: 0.85rem;\n color: #64748b;\n}\n"],"names":[],"sourceRoot":""}
|
||||
3
projects/cellular_automata/static/js/main.608a23ae.js
Normal file
3
projects/cellular_automata/static/js/main.608a23ae.js
Normal file
File diff suppressed because one or more lines are too long
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* @license React
|
||||
* react-dom.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @license React
|
||||
* react-jsx-runtime.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @license React
|
||||
* react.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @license React
|
||||
* scheduler.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
File diff suppressed because one or more lines are too long
73
projects/percolation/index.html
Normal file
73
projects/percolation/index.html
Normal file
@@ -0,0 +1,73 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Percolation</title>
|
||||
<link rel="stylesheet" href="style.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<a href="/#projects" class="back-button">← Back</a>
|
||||
|
||||
<header>
|
||||
<h1>Percolation</h1>
|
||||
<p class="subtitle">A simulation written in C & Raylib.</p>
|
||||
</header>
|
||||
|
||||
<section>
|
||||
<p>
|
||||
<strong>Percolation</strong> is a simple model for connectivity on a grid. Each cell is either open or closed.
|
||||
This simulation stops as soon as there is a path from the top of the grid to the bottom through the open cells.
|
||||
</p>
|
||||
<div class="info-box">
|
||||
<p>
|
||||
In this simulation, cells are randomly opened on a grid. Percolation occurs when there exists
|
||||
a connected path of open cells from the top to the bottom of the grid. It is a neat way to visualise
|
||||
threshold behaviour: below a certain probability nothing connects, and above it large connected regions
|
||||
suddenly begin to appear.
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div class="canvas-container">
|
||||
<div class="canvas-toolbar">
|
||||
<p>Canvas</p>
|
||||
<button id="fullscreenButton" class="action-button" type="button">Fullscreen</button>
|
||||
</div>
|
||||
|
||||
<div class="canvas-shell">
|
||||
<canvas id="canvas" aria-label="Percolation simulation canvas" oncontextmenu="event.preventDefault()"></canvas>
|
||||
</div>
|
||||
|
||||
<div id="status" class="status">Downloading...</div>
|
||||
<progress id="progress" value="0" max="100" hidden></progress>
|
||||
|
||||
<details>
|
||||
<summary>Show console output</summary>
|
||||
<label class="visually-hidden" for="output">Console output</label>
|
||||
<textarea id="output" rows="8" readonly></textarea>
|
||||
</details>
|
||||
</div>
|
||||
|
||||
<section>
|
||||
<h3>Technical Details</h3>
|
||||
<p>
|
||||
The simulation uses a <strong>disjoint-set (Union-Find)</strong> style connectivity algorithm. As random cells open,
|
||||
each open cell is union-ed with its open neighbours, and two virtual nodes represent the top and bottom edges
|
||||
of the grid. Percolation is detected the moment those two virtual nodes become connected.
|
||||
</p>
|
||||
<p>
|
||||
This makes each update fast and scalable even for larger grids.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<footer>
|
||||
<p>Built with C, Raylib, and WebAssembly</p>
|
||||
</footer>
|
||||
</div>
|
||||
|
||||
<script src="script.js"></script>
|
||||
<script async src="index.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
10120
projects/percolation/index.js
Normal file
10120
projects/percolation/index.js
Normal file
File diff suppressed because it is too large
Load Diff
BIN
projects/percolation/index.wasm
Executable file
BIN
projects/percolation/index.wasm
Executable file
Binary file not shown.
78
projects/percolation/script.js
Normal file
78
projects/percolation/script.js
Normal file
@@ -0,0 +1,78 @@
|
||||
const statusElement = document.getElementById('status');
|
||||
const progressElement = document.getElementById('progress');
|
||||
const canvasElement = document.getElementById('canvas');
|
||||
const outputElement = document.getElementById('output');
|
||||
const fullscreenButton = document.getElementById('fullscreenButton');
|
||||
|
||||
outputElement.value = '';
|
||||
|
||||
canvasElement.addEventListener('webglcontextlost', (event) => {
|
||||
event.preventDefault();
|
||||
setStatus('WebGL context lost. Reload the page to restart the simulation.');
|
||||
}, false);
|
||||
|
||||
function setStatus(text) {
|
||||
if (!setStatus.last) {
|
||||
setStatus.last = { time: Date.now(), text: '' };
|
||||
}
|
||||
|
||||
if (text === setStatus.last.text) {
|
||||
return;
|
||||
}
|
||||
|
||||
const match = text && text.match(/([^(]+)\((\d+(?:\.\d+)?)\/(\d+)\)/);
|
||||
const now = Date.now();
|
||||
|
||||
if (match && now - setStatus.last.time < 30) {
|
||||
return;
|
||||
}
|
||||
|
||||
setStatus.last.time = now;
|
||||
setStatus.last.text = text;
|
||||
|
||||
if (match) {
|
||||
statusElement.textContent = match[1].trim();
|
||||
progressElement.value = Number.parseInt(match[2], 10) * 100;
|
||||
progressElement.max = Number.parseInt(match[3], 10) * 100;
|
||||
progressElement.hidden = false;
|
||||
} else {
|
||||
statusElement.textContent = text || '';
|
||||
progressElement.hidden = !text;
|
||||
if (!text) {
|
||||
progressElement.removeAttribute('value');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var Module = {
|
||||
canvas: canvasElement,
|
||||
print: (...args) => {
|
||||
console.log(...args);
|
||||
outputElement.value += `${args.join(' ')}\n`;
|
||||
outputElement.scrollTop = outputElement.scrollHeight;
|
||||
},
|
||||
printErr: (...args) => {
|
||||
console.error(...args);
|
||||
outputElement.value += `[err] ${args.join(' ')}\n`;
|
||||
outputElement.scrollTop = outputElement.scrollHeight;
|
||||
},
|
||||
setStatus,
|
||||
totalDependencies: 0,
|
||||
monitorRunDependencies(left) {
|
||||
this.totalDependencies = Math.max(this.totalDependencies, left);
|
||||
setStatus(left ? `Preparing... (${this.totalDependencies - left}/${this.totalDependencies})` : 'Running...');
|
||||
if (!left) {
|
||||
setTimeout(() => setStatus(''), 250);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
fullscreenButton.addEventListener('click', () => {
|
||||
if (typeof Module.requestFullscreen === 'function') {
|
||||
Module.requestFullscreen(false, false);
|
||||
}
|
||||
});
|
||||
|
||||
globalThis.onerror = () => {
|
||||
setStatus('Exception thrown, see JavaScript console');
|
||||
};
|
||||
197
projects/percolation/style.css
Normal file
197
projects/percolation/style.css
Normal file
@@ -0,0 +1,197 @@
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body {
|
||||
background: white;
|
||||
color: black;
|
||||
font-family: Arial, sans-serif;
|
||||
font-size: 16px;
|
||||
line-height: 1.6;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 900px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
header {
|
||||
text-align: center;
|
||||
margin-bottom: 30px;
|
||||
border-bottom: 1px solid #ccc;
|
||||
padding-bottom: 20px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 2.5rem;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 1.8rem;
|
||||
margin: 20px 0 15px;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 1.3rem;
|
||||
margin: 15px 0;
|
||||
}
|
||||
|
||||
p {
|
||||
margin-bottom: 15px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.subtitle {
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.back-button {
|
||||
display: inline-block;
|
||||
margin-bottom: 20px;
|
||||
padding: 10px 15px;
|
||||
background: #f0f0f0;
|
||||
color: black;
|
||||
text-decoration: none;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.back-button:hover,
|
||||
.action-button:hover {
|
||||
background: #e0e0e0;
|
||||
}
|
||||
|
||||
.info-box {
|
||||
background: #f9f9f9;
|
||||
border-left: 4px solid #333;
|
||||
padding: 15px;
|
||||
margin: 20px 0;
|
||||
}
|
||||
|
||||
.canvas-container {
|
||||
background: #f9f9f9;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 4px;
|
||||
padding: 20px;
|
||||
margin: 30px 0;
|
||||
}
|
||||
|
||||
.canvas-toolbar {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
margin-bottom: 15px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.canvas-toolbar p {
|
||||
margin: 0;
|
||||
color: #666;
|
||||
font-size: 0.95rem;
|
||||
}
|
||||
|
||||
.action-button {
|
||||
padding: 8px 12px;
|
||||
background: #f0f0f0;
|
||||
color: black;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
font: inherit;
|
||||
}
|
||||
|
||||
.canvas-shell {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
min-height: 500px;
|
||||
overflow: auto;
|
||||
background: white;
|
||||
border: 1px solid #ddd;
|
||||
}
|
||||
|
||||
#canvas {
|
||||
display: block;
|
||||
margin: 0 auto;
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
background: black;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.status {
|
||||
margin-top: 15px;
|
||||
min-height: 24px;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
progress {
|
||||
width: 100%;
|
||||
height: 16px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
progress[hidden] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
details {
|
||||
margin-top: 15px;
|
||||
}
|
||||
|
||||
.visually-hidden {
|
||||
position: absolute;
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
padding: 0;
|
||||
margin: -1px;
|
||||
overflow: hidden;
|
||||
clip: rect(0, 0, 0, 0);
|
||||
white-space: nowrap;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
textarea {
|
||||
width: 100%;
|
||||
min-height: 120px;
|
||||
margin-top: 10px;
|
||||
padding: 10px;
|
||||
border: 1px solid #ddd;
|
||||
font-family: "Courier New", monospace;
|
||||
font-size: 0.9rem;
|
||||
resize: vertical;
|
||||
background: white;
|
||||
color: black;
|
||||
}
|
||||
|
||||
footer {
|
||||
text-align: center;
|
||||
margin-top: 40px;
|
||||
padding-top: 20px;
|
||||
border-top: 1px solid #ccc;
|
||||
font-size: 0.85rem;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
body {
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
.canvas-container {
|
||||
padding: 15px;
|
||||
}
|
||||
|
||||
.canvas-shell {
|
||||
min-height: 360px;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user