Compare commits

..

2 commits

Author SHA1 Message Date
a06795c694 font 2026-06-05 15:28:02 +09:00
2eab826979 ---- 2026-06-04 18:20:50 +09:00
8 changed files with 100 additions and 46 deletions

1
.htaccess Normal file
View file

@ -0,0 +1 @@
AddType font/ttf .ttf

View file

@ -63,7 +63,6 @@ Open `index.html` in a modern browser. No build step or third-party dependency i
- Dynamic sprites now pause intermittently instead of walking continuously.
- Night rendering is darker.
- Object picking now uses sprite-sized, per-opaque-pixel hit testing, so transparent pixels are not clickable.
- The CSS font stack now tries `3x5 MT Pixel Font` first. The font file itself is not bundled.
## Phase 5 changes

View file

@ -446,7 +446,7 @@ window.addEventListener('load', () => {
});
</script>
<style>
body{font-family:system-ui,sans-serif;margin:24px;background:#f7f4ea;color:#2b2b2b}h1{margin-bottom:4px}.grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(380px,1fr));gap:12px}.card{background:#fff;border:1px solid #ddd;border-radius:10px;padding:14px;margin:10px 0}.media{display:flex;gap:14px;align-items:flex-start}.muted{color:#666;font-size:13px}.error{background:#fff1f1;border:1px solid #e3aaaa;padding:12px;border-radius:8px}code{background:#eee;padding:1px 4px;border-radius:4px}input{max-width:210px;padding:6px;margin:2px 4px 2px 0}button{margin:2px 4px 2px 0;padding:6px 9px;border:1px solid #bbb;border-radius:6px;background:#f5f5f5}.danger{background:#b92323;color:white;border:0}.ok{background:#267a3e;color:white;border:0}.warn{background:#8b5b00;color:white;border:0}.pill{display:inline-block;padding:2px 7px;border-radius:999px;background:#eee;font-size:12px}.nav a{margin-right:10px}.thumb{position:relative;flex:0 0 auto;width:128px;height:128px;background:#f2eadb;border:1px solid #ddd;image-rendering:pixelated;overflow:hidden}.thumb i{position:absolute;transform:scale(1.02);transform-origin:0 0}.thumb.empty:after{content:'no image';position:absolute;inset:0;display:grid;place-items:center;color:#777;font-size:11px}@media(max-width:520px){.grid{grid-template-columns:1fr}.media{flex-direction:column}.thumb{width:112px;height:112px}}
@font-face{font-family:PixelIslandServiceFont;src:url("../assets/fonts/PixelMplus10-Regular.ttf?v=20260605-2") format("truetype");font-weight:100 900;font-style:normal;font-display:swap}body{font-family:PixelIslandServiceFont,sans-serif;margin:24px;background:#f7f4ea;color:#2b2b2b}h1{margin-bottom:4px}.grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(380px,1fr));gap:12px}.card{background:#fff;border:1px solid #ddd;border-radius:10px;padding:14px;margin:10px 0}.media{display:flex;gap:14px;align-items:flex-start}.muted{color:#666;font-size:13px}.error{background:#fff1f1;border:1px solid #e3aaaa;padding:12px;border-radius:8px}code{background:#eee;padding:1px 4px;border-radius:4px}input{max-width:210px;padding:6px;margin:2px 4px 2px 0}button{margin:2px 4px 2px 0;padding:6px 9px;border:1px solid #bbb;border-radius:6px;background:#f5f5f5}.danger{background:#b92323;color:white;border:0}.ok{background:#267a3e;color:white;border:0}.warn{background:#8b5b00;color:white;border:0}.pill{display:inline-block;padding:2px 7px;border-radius:999px;background:#eee;font-size:12px}.nav a{margin-right:10px}.thumb{position:relative;flex:0 0 auto;width:128px;height:128px;background:#f2eadb;border:1px solid #ddd;image-rendering:pixelated;overflow:hidden}.thumb i{position:absolute;transform:scale(1.02);transform-origin:0 0}.thumb.empty:after{content:'no image';position:absolute;inset:0;display:grid;place-items:center;color:#777;font-size:11px}@media(max-width:520px){.grid{grid-template-columns:1fr}.media{flex-direction:column}.thumb{width:112px;height:112px}}
</style>
<h1>Pixel Island Admin</h1>
<p class="muted">Store: <?=h($storeLabel)?> / Users: <?=count($accounts)?> / Pictures: <?=count($assets)?> / Reports: <?=count($reports)?></p>

80
app.js
View file

@ -58,37 +58,28 @@
const uid = () => Math.random().toString(36).slice(2, 9) + Date.now().toString(36).slice(-5);
const mod = (n, m) => ((n % m) + m) % m;
const lerp = (a, b, t) => a + (b - a) * t;
function clampDimension(value, fallback = 8) {
return PixelCodec.clampDimension ? PixelCodec.clampDimension(value, fallback) : Math.max(1, Math.min(MAX_EDITOR_DIMENSION, Math.round(Number(value) || fallback)));
}
function rectArea(width, height = width) {
return Math.max(1, Math.floor(Number(width) || 1)) * Math.max(1, Math.floor(Number(height) || width || 1));
}
function lightBudgetForArea(width, height = width) {
return Math.max(1, Math.ceil(rectArea(width, height) / 100));
}
function assetWidth(asset) {
return PixelCodec.assetWidth ? PixelCodec.assetWidth(asset) : clampDimension(asset?.width ?? asset?.w ?? asset?.size, 16);
}
function assetHeight(asset) {
return PixelCodec.assetHeight ? PixelCodec.assetHeight(asset) : clampDimension(asset?.height ?? asset?.ht ?? asset?.size, assetWidth(asset));
}
function assetMaxSize(asset) {
return PixelCodec.assetMaxSize ? PixelCodec.assetMaxSize(asset) : Math.max(assetWidth(asset), assetHeight(asset));
}
function clampInt(value, min, max, fallback = min) {
const n = Math.round(Number(value));
return PixelCodec.clampInt ? PixelCodec.clampInt(value, min, max, fallback) : (Number.isFinite(n) ? clamp(n, min, max) : fallback);
}
function buildPixelBlob(encodedPixels, width, height = width) {
return PixelCodec.buildPixelBlob(encodedPixels, width, height, PALETTE, DEFAULT_SELECTED_COLOR_CODE);
}
@ -283,8 +274,8 @@
staticKindWrap: $('staticKindWrap'),
dynamicKindWrap: $('dynamicKindWrap'),
roleHint: $('roleHint'),
sideSwitcher: $('sideSwitcher'),
editRight: $('editRight'), editLeft: $('editLeft'),
sideSwitcher: $('sideSwitcher'), frontSideSwitcher: $('frontSideSwitcher'),
editRight: $('editRight'), editLeft: $('editLeft'), frontRight: $('frontRight'), frontLeft: $('frontLeft'),
paintColor: $('paintColor'), toolBrush: $('toolBrush'), toolErase: $('toolErase'), toolFill: $('toolFill'), toolPick: $('toolPick'), toolLine: $('toolLine'), toolRect: $('toolRect'), toolSelect: $('toolSelect'), undoPaint: $('undoPaint'), redoPaint: $('redoPaint'),
toolLight: $('toolLight'), toolParticle: $('toolParticle'), toolDoor: $('toolDoor'), toolDepth: $('toolDepth'), depthHigh: $('depthHigh'), depthLow: $('depthLow'), toggleAdvanced: $('toggleAdvanced'), advancedHint: $('advancedHint'), advancedToolGroup: $('advancedToolGroup'), particleDirectionWrap: $('particleDirectionWrap'), particleDirection: $('particleDirection'), particleUseSelection: $('particleUseSelection'), particleClearRange: $('particleClearRange'), particleRangeStatus: $('particleRangeStatus'), clearPaint: $('clearPaint'), flipHorizontal: $('flipHorizontal'), flipVertical: $('flipVertical'), outlinePaint: $('outlinePaint'), clearSelection: $('clearSelection'), nudgeLeft: $('nudgeLeft'), nudgeRight: $('nudgeRight'), nudgeUp: $('nudgeUp'), nudgeDown: $('nudgeDown'),
paintCanvas: $('paintCanvas'), editHint: $('editHint'), paletteGrid: $('paletteGrid'),
@ -332,6 +323,7 @@
let editorPixels = blankPixels(8);
let editorLeftPixels = blankPixels(8);
let editingSide = 'right';
let frontSide = 'right';
let paintTool = 'brush';
let selectedColorCode = DEFAULT_SELECTED_COLOR_CODE;
let advancedDraw = false;
@ -464,7 +456,8 @@
});
els.createAccount?.addEventListener('click', () => createLocalAccount(false));
els.placeHereButton?.addEventListener('click', confirmPreviewPlacement);
els.placeHereButton?.addEventListener('pointerdown', (event) => { event.preventDefault(); event.stopPropagation(); confirmPreviewPlacement(); });
els.placeHereButton?.addEventListener('click', (event) => { event.preventDefault(); event.stopPropagation(); if (placementPreview?.asset) confirmPreviewPlacement(); });
els.settingLights?.addEventListener('change', () => {
visualSettings().enableLights = !!els.settingLights.checked;
@ -552,6 +545,8 @@
els.editRight.addEventListener('click', () => setEditingSide('right'));
els.editLeft.addEventListener('click', () => setEditingSide('left'));
els.frontRight?.addEventListener('click', () => setFrontSide('right'));
els.frontLeft?.addEventListener('click', () => setFrontSide('left'));
els.toolBrush.addEventListener('click', () => setPaintTool('brush'));
els.toolErase.addEventListener('click', () => setPaintTool('erase'));
@ -734,6 +729,7 @@
els.panels.forEach((panel) => panel.classList.toggle('active', panel.id === `tab-${name}`));
if (name !== 'draw' && advancedDraw) setAdvancedDraw(false, { redraw: false });
else els.drawer?.classList.toggle('advancedTools', name === 'draw' && advancedDraw);
refreshCategoryUI();
if (keepScroll) restoreLibraryScrollState(scrollState);
}
@ -805,7 +801,8 @@
toggleHidden(els.staticKindWrap, true);
toggleHidden(els.dynamicKindWrap, true);
toggleHidden(els.sideSwitcher, isStatic);
const showDynamicDrawControls = activeTabName === 'draw' && !isStatic;
toggleHidden(els.sideSwitcher, true); toggleHidden(els.frontSideSwitcher, !showDynamicDrawControls);
toggleHidden(els.staticSettingsPanel, !isStatic);
toggleHidden(els.dynamicSettingsPanel, true);
toggleHidden(els.advancedToolGroup, !advancedDraw);
@ -822,6 +819,7 @@
if (!isStatic && paintTool === 'door') setPaintTool('brush');
if (isStatic && role !== 'building' && paintTool === 'door') setPaintTool('brush');
if (isStatic) editingSide = 'right';
if (isStatic) frontSide = 'right';
updateRoleHint();
updateSideButtons();
@ -860,7 +858,7 @@
} else {
const particleText = particlePixels.length ? ` / particles ${particlePixels.length} cell${particlePixels.length === 1 ? '' : 's'}` : '';
const sideText = editingSide === 'left' ? 'canvas marked Left; Save mirrors it into canonical Right' : 'canvas marked canonical Right';
els.settingsSummary.textContent = `${cap(role)} / ${editorWidth}x${editorHeight} canvas / ${sideText}${particleText}.`;
els.settingsSummary.textContent = `${cap(role)} / ${editorWidth}x${editorHeight} canvas / ${sideText} / ${frontSide === 'left' ? 'front starts Left' : 'front starts Right'}${particleText}.`;
}
}
@ -909,14 +907,23 @@
drawEditor();
}
function setFrontSide(side) {
if (roleToCategory(currentRole()) !== 'dynamic') return;
frontSide = side === 'left' ? 'left' : 'right'; updateSideButtons();
if (els.editHint) els.editHint.textContent = `Movable sprite will appear facing ${frontSide} when first placed.`;
spriteCache.clear(); drawEditor(); render();
}
function updateSideButtons() {
if (els.editRight) els.editRight.classList.toggle('active', editingSide === 'right');
if (els.editLeft) els.editLeft.classList.toggle('active', editingSide === 'left');
if (els.frontRight) els.frontRight.classList.toggle('active', frontSide === 'right'); if (els.frontLeft) els.frontLeft.classList.toggle('active', frontSide === 'left');
updateSettingsSummary();
}
function onWorldPointerDown(event) {
event.preventDefault();
if (isPlaceHereEvent(event)) { confirmPreviewPlacement(); return; }
const downPos = getCanvasPoint(event);
cursorScreen = { x: downPos.x, y: downPos.y, active: true };
if (event.button === 2) {
@ -970,6 +977,7 @@
}
function onWorldPointerUp(event) {
if (isPlaceHereEvent(event)) { confirmPreviewPlacement(); return; }
if (!pointer.down || pointer.id !== event.pointerId) return;
els.canvas.classList.remove('dragging');
const total = Math.hypot(event.clientX - pointer.startX, event.clientY - pointer.startY);
@ -995,6 +1003,11 @@
pointer.dragging = false;
}
function isPlaceHereEvent(event) {
if (mode !== 'place' || !placementPreview?.asset || !els.placeHereButton || els.placeHereButton.hidden) return false;
const rect = els.placeHereButton.getBoundingClientRect(); return event.clientX >= rect.left - 8 && event.clientX <= rect.right + 8 && event.clientY >= rect.top - 8 && event.clientY <= rect.bottom + 8;
}
function onWorldWheel(event) {
event.preventDefault();
cameraFollowSelected = false;
@ -1684,7 +1697,7 @@
}
if (placementPreview?.asset && placementPreview.x != null && placementPreview.y != null) {
const asset = placementPreview.asset;
items.push({ kind: asset.category === 'dynamic' ? 'dynamic' : 'static', asset, x: placementPreview.x + .5, y: placementPreview.y + .5, source: { id: 'placement-preview', preview: true }, preview: true });
items.push({ kind: asset.category === 'dynamic' ? 'dynamic' : 'static', asset, x: placementPreview.x + .5, y: placementPreview.y + .5, source: { id: 'placement-preview', preview: true, selectedAt: placementPreview.selectedAt || performance.now() }, preview: true });
}
items.sort(drawOrderCompare);
return items;
@ -1862,7 +1875,7 @@
const tile = world.get(x, y);
if (!canPlace(asset, tile)) return;
const savedAssetId = placementPreview?.savedAssetId || selectedAssetId || asset.id;
placementPreview = { asset, savedAssetId, x, y };
placementPreview = { asset, savedAssetId, x, y, selectedAt: performance.now() };
clearWorldSelection(false);
syncPlacementUi();
if (visualSettings().enableParticles) spawnEffects.push({ x: x + .5, y: y + .5, started: performance.now(), preview: true });
@ -1885,6 +1898,7 @@
}
placementPreview.x = x;
placementPreview.y = y;
placementPreview.selectedAt = performance.now();
if (visualSettings().enableParticles) spawnEffects.push({ x: x + .5, y: y + .5, started: performance.now(), preview: true });
render();
toast(adjusted.moved ? 'Preview nudged away from the remix source. Right-click or DRAW to exit.' : 'Preview set. Right-click or DRAW to exit.');
@ -3501,7 +3515,7 @@
} : null,
meta: buildAssetMeta(category, subtype, aligned.depthPixels, aligned.lightPixels, selectedColorCode, aligned.door, savedWidth, aligned.particlePixels, aligned.rightPixels, savedHeight)
};
asset.contentHash = computeAssetContentHash(asset);
if (asset.meta && category === 'dynamic') asset.meta.frontSide = frontSide; asset.contentHash = computeAssetContentHash(asset);
return { asset, pixelBlob, existing, aligned };
}
@ -3607,7 +3621,7 @@
faces: category === 'dynamic' ? { right: encodedRight, left: 'mirror' } : null,
meta: buildAssetMeta(category, subtype, aligned.depthPixels, aligned.lightPixels, selectedColorCode, aligned.door, savedWidth, aligned.particlePixels, aligned.rightPixels, savedHeight)
};
return asset;
if (asset.meta && category === 'dynamic') asset.meta.frontSide = frontSide; return asset;
}
function checkCurrentEditorOnIsland() {
@ -3634,9 +3648,11 @@
toast('Click a tile first.');
return;
}
const assetId = placementPreview.savedAssetId || placementPreview.asset.id;
if (!findAsset(assetId)) {
toast('Saved asset is missing. Back to canvas and save again.');
let assetId = placementPreview.savedAssetId || placementPreview.asset.id;
if (!findAsset(assetId) && String(assetId).startsWith('preview:')) {
const saved = saveAssetFromEditor(); if (saved) assetId = saved.id;
}
if (!findAsset(assetId)) { toast('Saved asset is missing. Back to canvas and save again.');
return;
}
selectedAssetId = assetId;
@ -3656,7 +3672,7 @@
staticKind = 'nature';
dynamicKind = 'human';
editingSide = 'right';
lightPixels = [];
frontSide = 'right'; lightPixels = [];
particlePixels = [];
particleConfig = { enabled: false, c: selectedColorCode, dir: 'up' };
depthPixels = blankPixels(8).map(() => 0);
@ -4292,7 +4308,7 @@
els.assetCategory.value = subtypeToRole(asset);
staticKind = asset.category === 'static' ? asset.subtype : staticKind;
dynamicKind = asset.category === 'dynamic' ? asset.subtype : dynamicKind;
editingSide = 'right';
editingSide = 'right'; frontSide = asset.meta?.frontSide === 'left' ? 'left' : 'right';
const right = getAssetPixels(asset, 'right');
lightPixels = (asset.meta?.lightPixels || []).map((p) => ({ x: p.x, y: p.y, c: p.c || asset.meta?.lightColor || selectedColorCode }));
particlePixels = (asset.meta?.particlePixels || []).map((p) => ({ x: p.x, y: p.y, c: p.c || selectedColorCode, dir: p.dir || 'up' }));
@ -4449,7 +4465,7 @@
const startY = Number.isFinite(Number(synced.y)) ? Number(synced.y) : (previous ? previous.y : spawn.y + .5);
const targetX = Number.isFinite(Number(synced.targetX)) ? Number(synced.targetX) : (previous ? previous.targetX : startX);
const targetY = Number.isFinite(Number(synced.targetY)) ? Number(synced.targetY) : (previous ? previous.targetY : startY);
const facing = Number.isFinite(Number(synced.facing)) && Number(synced.facing) !== 0 ? Math.sign(Number(synced.facing)) : (previous?.facing || 1);
const facing = Number.isFinite(Number(synced.facing)) && Number(synced.facing) !== 0 ? Math.sign(Number(synced.facing)) : (previous?.facing || (asset.meta?.frontSide === 'left' ? -1 : 1));
return {
id: summon.id,
assetId: summon.assetId,
@ -5125,8 +5141,8 @@
const runtime = item.source || {};
const seed = Number.isFinite(runtime.seed) ? runtime.seed : 0;
const isPreview = Boolean(item.preview || runtime.preview);
const moveFacing = Math.abs(runtime.lastMoveX || 0) > 0.003 ? Math.sign(runtime.lastMoveX) : (runtime.facing || runtime.vx || 1);
side = isPreview ? 'right' : (moveFacing < 0 ? 'left' : 'right');
const moveFacing = Math.abs(runtime.lastMoveX || 0) > 0.003 ? Math.sign(runtime.lastMoveX) : (runtime.facing || runtime.vx || (asset.meta?.frontSide === 'left' ? -1 : 1));
side = isPreview ? (asset.meta?.frontSide === 'left' ? 'left' : 'right') : (moveFacing < 0 ? 'left' : 'right');
if (asset.subtype === 'human' || asset.subtype === 'animal') {
const idle = isPreview || time < (runtime.idleUntil || 0);
if (!idle) {
@ -5166,6 +5182,14 @@
}
}
if (item.preview) {
const previewElapsed = time - (item.source?.selectedAt || item.source?.createdAt || time);
if (previewElapsed < 720) {
const hop = Math.sin(clamp(previewElapsed / 720, 0, 1) * Math.PI);
const settle = Math.exp(-Math.pow((previewElapsed - 470) / 120, 2)); bob += -hop * 12; stretchX += settle * 0.28; stretchY -= settle * 0.2;
}
}
const sprite = getSpriteCanvas(asset, side);
const drawX = pos.x - sprite.width / 2;
const anchorY = asset.category === 'static' ? 0 : TILE_H / 2;
@ -6712,6 +6736,7 @@ function drawShipRipples(pos, time, seedValue = '', asset = null) {
.filter((p) => Number.isFinite(p.x) && Number.isFinite(p.y))
: [];
const normalized = buildAssetMeta(category, subtype, normalizedDepth, lightPixels, meta.lightColor || '#ffd86a', meta.door || null, width, legacyParticlePixels, sourcePixels, height);
if (category === 'dynamic') normalized.frontSide = meta.frontSide === 'left' ? 'left' : 'right';
return normalized;
}
@ -7100,6 +7125,7 @@ function drawShipRipples(pos, time, seedValue = '', asset = null) {
JSON.stringify(asset.meta?.lightPixels || []),
JSON.stringify(asset.meta?.particlePixels || []),
JSON.stringify(asset.meta?.particleConfig || null),
asset.meta?.frontSide || '',
asset.meta?.door ? `${asset.meta.door.x},${asset.meta.door.y}` : ''
].join('|');
return `fnv1a:${fnv1a(payload)}`;
@ -7671,4 +7697,4 @@ function drawShipRipples(pos, time, seedValue = '', asset = null) {
// Pixel Island default-art drawing code was moved out of app.js.
window.PixelIslandDebug = { ...(window.PixelIslandDebug || {}), applySyncEvent };
bootstrap();
})();
})();

Binary file not shown.

View file

@ -4,7 +4,7 @@
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Pixel Island</title>
<link rel="stylesheet" href="./styles.css" />
<link rel="stylesheet" href="./styles.css?v=20260605-2" />
</head>
<body>
<div class="app">
@ -71,6 +71,11 @@
<button id="editLeft" title="Left-facing sprite">◀ Left</button>
<button id="editRight" class="active" title="Right-facing sprite is the main/front direction">▶ Right</button>
</div>
<div id="frontSideSwitcher" class="sideSwitcher frontSideSwitcher" hidden aria-label="Front-facing side">
<span class="sideSwitcherLabel">Front</span>
<button id="frontLeft" title="Show left side first">◀ Left</button>
<button id="frontRight" class="active" title="Show right side first">▶ Right</button>
</div>
</div>
<div class="paintLayout">

View file

@ -1,3 +1,11 @@
@font-face {
font-family: "PixelIslandServiceFont";
src: url("./assets/fonts/PixelMplus10-Regular.ttf?v=20260605-2") format("truetype");
font-weight: 100 900;
font-style: normal;
font-display: swap;
}
:root {
--ink: #243044;
--muted: #6f7b91;
@ -25,7 +33,7 @@ body {
margin: 0;
color: var(--ink);
background: #92d8ff;
font-family: "3x5 MT Pixel Font", "Press Start 2P", "PixelMplus10", "DotGothic16", "Courier New", "Monaco", "Lucida Console", ui-monospace, monospace;
font-family: "PixelIslandServiceFont", sans-serif;
overflow: hidden;
}
@ -415,6 +423,18 @@ input[type="checkbox"] { width: auto; margin: 0 8px 0 0; }
align-items: center;
}
.sideSwitcher button { padding: 6px 7px; font-size: 11px; }
.compactEditorTop {
display: flex;
flex-wrap: wrap;
gap: 8px;
align-items: center;
}
.sideSwitcherLabel {
font-size: 10px;
font-weight: 900;
color: #334155;
text-transform: uppercase;
}
.toolRow {
display: grid;
@ -730,7 +750,6 @@ button:disabled, .tool:disabled { opacity: .45; cursor: not-allowed; transform:
.heroEditor .hint { line-height: 1.35; }
.compactEditorTop { margin-bottom: 4px; min-height: 0; }
body, button, input, select, textarea { font-smooth: never; -webkit-font-smoothing: none; }
.studioDrawer { width: min(600px, calc(100vw - 24px)); }
.paintLayout {
@ -846,10 +865,6 @@ body, button, input, select, textarea { font-smooth: never; -webkit-font-smoothi
background: var(--sun);
}
body, button, input, select, textarea {
font-family: "Courier New", "Lucida Console", Monaco, monospace;
letter-spacing: .02em;
}
button, .tab, .tool, .iconButton, .cardTitle, .logo {
text-transform: uppercase;
font-weight: 900;
@ -888,12 +903,6 @@ button, .tab, .tool, .iconButton, .cardTitle, .logo {
color: var(--muted);
}
body, button, input, select, textarea {
font-family: "MS Gothic", "Osaka-Mono", "DotumChe", "Courier New", ui-monospace, monospace;
letter-spacing: .02em;
-webkit-font-smoothing: none;
text-rendering: geometricPrecision;
}
.toolRow { grid-template-columns: repeat(6, minmax(0, 1fr)); }
.editorHistoryRow { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.advancedRow {
@ -982,9 +991,6 @@ body, button, input, select, textarea {
grid-column: span 2;
}
body, button, input, select, textarea {
font-family: "3x5 MT Pixel Font", "Press Start 2P", "PixelMplus10", "DotGothic16", "MS Gothic", "Osaka-Mono", "Courier New", ui-monospace, monospace;
}
.hiddenSectionTitle {
margin: 8px 0 6px;
padding: 5px 7px;
@ -2931,6 +2937,8 @@ body, button, input, select, textarea { font-size: 15px; }
font-weight: 900 !important;
letter-spacing: .04em;
cursor: pointer;
pointer-events: auto !important;
touch-action: manipulation;
}
.placeHereButton[hidden] { display: none !important; }
#confirmDialog.reportDialog { position: fixed !important; z-index: 10000 !important; }
@ -2943,7 +2951,7 @@ body, button, input, select, textarea { font-size: 15px; }
.basicEditorTools,
.studioDrawer.advancedTools .editorToolRow,
.studioDrawer.advancedTools .basicEditorTools {
grid-template-columns: repeat(5, minmax(0, 1fr)) !important;
grid-template-columns: repeat(6, minmax(0, 1fr)) !important;
}
.basicEditorTools #toolBrush {
background: linear-gradient(180deg, #dcfce7, #86efac) !important;
@ -2970,3 +2978,9 @@ body, button, input, select, textarea { font-size: 15px; }
outline-offset: -6px !important;
color: #111827 !important;
}
.basicEditorTools #clearPaint {
border-right: 2px solid var(--line, #243044) !important;
}
.studioDrawer .compactEditorTop {
display: flex !important;
}

9
web.config Normal file
View file

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<staticContent>
<remove fileExtension=".ttf" />
<mimeMap fileExtension=".ttf" mimeType="font/ttf" />
</staticContent>
</system.webServer>
</configuration>