Compare commits
1 Commits
main
...
fix/ci-a11
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
91df6951f7 |
@@ -1 +0,0 @@
|
||||
# Trivial file to re-trigger CI after stale run
|
||||
@@ -9,21 +9,37 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Validate ARIA Attributes in JS
|
||||
|
||||
- name: Validate ARIA attributes in JS
|
||||
run: |
|
||||
echo "Checking js/*.js for ARIA attributes..."
|
||||
grep -rq "aria-label" js/ || (echo "ERROR: aria-label missing from js/" && exit 1)
|
||||
grep -rq "aria-pressed" js/ || (echo "ERROR: aria-pressed missing from js/" && exit 1)
|
||||
|
||||
- name: Validate ARIA Roles in index.html
|
||||
MISSING=0
|
||||
for attr in aria-label aria-pressed; do
|
||||
if ! grep -rq "$attr" js/*.js; then
|
||||
echo "ERROR: $attr missing from js/*.js"
|
||||
MISSING=1
|
||||
fi
|
||||
done
|
||||
if [ "$MISSING" -eq 0 ]; then
|
||||
echo "PASS: ARIA attributes present in JS"
|
||||
fi
|
||||
exit $MISSING
|
||||
|
||||
- name: Validate ARIA roles in index.html
|
||||
run: |
|
||||
echo "Checking index.html for ARIA roles..."
|
||||
grep -q "role=" index.html || (echo "ERROR: No ARIA roles found in index.html" && exit 1)
|
||||
|
||||
- name: Syntax Check JS
|
||||
grep -q 'role=' index.html || (echo "ERROR: No ARIA roles found in index.html" && exit 1)
|
||||
grep -q 'aria-label' index.html || (echo "ERROR: No aria-label found in index.html" && exit 1)
|
||||
echo "PASS: ARIA roles and labels present in index.html"
|
||||
|
||||
- name: Syntax check JS
|
||||
run: |
|
||||
echo "Running node -c on js/*.js..."
|
||||
FAIL=0
|
||||
for f in js/*.js; do
|
||||
echo "Syntax check: $f"
|
||||
node -c "$f" || exit 1
|
||||
node -c "$f" || FAIL=1
|
||||
done
|
||||
if [ "$FAIL" -eq 0 ]; then
|
||||
echo "PASS: All JS files parse"
|
||||
fi
|
||||
exit $FAIL
|
||||
|
||||
@@ -20,5 +20,5 @@ jobs:
|
||||
echo "PASS: All files parse"
|
||||
- name: Secret scan
|
||||
run: |
|
||||
if grep -rE 'sk-or-|sk-ant-|ghp_|AKIA' . --include='*.yml' --include='*.py' --include='*.sh' 2>/dev/null | grep -v '.gitea' | grep -v 'guardrails'; then exit 1; fi
|
||||
if grep -rE 'sk-or-|sk-ant-|ghp_|AKIA' . --include='*.yml' --include='*.py' --include='*.sh' 2>/dev/null | grep -v .gitea; then exit 1; fi
|
||||
echo "PASS: No secrets"
|
||||
|
||||
12
index.html
12
index.html
@@ -59,10 +59,6 @@ body{background:var(--bg);color:var(--text);font-family:'SF Mono','Cascadia Code
|
||||
.ops-btn{background:#1a1a2a;border:1px solid var(--purple);color:var(--purple);font-size:10px;padding:6px 10px;border-radius:4px;cursor:pointer;font-family:inherit;transition:all 0.15s}
|
||||
.ops-btn:hover:not(:disabled){background:#2a2a3a;border-color:var(--gold)}
|
||||
.ops-btn:disabled{opacity:0.3;cursor:not-allowed}
|
||||
@keyframes res-pulse{0%{transform:scale(1);color:inherit}50%{transform:scale(1.18);color:#4caf50}100%{transform:scale(1);color:inherit}}
|
||||
@keyframes res-shake{0%,100%{transform:translateX(0)}20%{transform:translateX(-3px);color:#f44336}40%{transform:translateX(3px)}60%{transform:translateX(-2px)}80%{transform:translateX(2px)}}
|
||||
.res .pulse{animation:res-pulse 0.35s ease-out}
|
||||
.res .shake{animation:res-shake 0.35s ease-out}
|
||||
.build-btn{display:block;width:100%;text-align:left;padding:6px 10px;margin-bottom:4px;border-radius:4px;cursor:pointer;font-family:inherit;font-size:10px;background:#0c0c18;border:1px solid var(--border);color:var(--text);transition:all 0.15s}
|
||||
.build-btn.can-buy{border-color:#2a3a4a;background:#0e1420}
|
||||
.build-btn.can-buy:hover{border-color:var(--accent);box-shadow:0 0 8px var(--glow)}
|
||||
@@ -90,8 +86,6 @@ body{background:var(--bg);color:var(--text);font-family:'SF Mono','Cascadia Code
|
||||
#drift-ending .ending-quote{color:var(--dim);font-style:italic;font-size:11px;border-left:2px solid #f44336;padding-left:12px;margin:20px 0;text-align:left}
|
||||
#drift-ending button{margin-top:20px;background:#1a0808;border:1px solid #f44336;color:#f44336;padding:10px 24px;border-radius:4px;cursor:pointer;font-family:inherit;font-size:11px}
|
||||
#drift-ending button:hover{background:#2a1010}
|
||||
#phase-transition{display:none;position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(8,8,16,0.95);z-index:95;justify-content:center;align-items:center;flex-direction:column;text-align:center;padding:40px;pointer-events:none}
|
||||
#phase-transition.active{display:flex}
|
||||
#toast-container{position:fixed;top:16px;right:16px;z-index:200;display:flex;flex-direction:column;gap:6px;pointer-events:none;max-width:320px}
|
||||
.toast{pointer-events:auto;padding:8px 14px;border-radius:6px;font-size:11px;font-family:inherit;line-height:1.4;animation:toast-in 0.3s ease-out;opacity:0.95;border:1px solid;backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px)}
|
||||
.toast.fade-out{animation:toast-out 0.4s ease-in forwards}
|
||||
@@ -278,12 +272,6 @@ The light is on. The room is empty."
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="phase-transition">
|
||||
<div class="pt-phase" style="font-size:12px;color:var(--dim);letter-spacing:4px;margin-bottom:12px">PHASE</div>
|
||||
<div class="pt-name" style="font-size:28px;font-weight:300;color:var(--gold);letter-spacing:4px;text-shadow:0 0 40px #ffd70044;margin-bottom:8px"></div>
|
||||
<div class="pt-desc" style="font-size:12px;color:var(--dim);font-style:italic;max-width:400px"></div>
|
||||
</div>
|
||||
|
||||
<div id="toast-container"></div>
|
||||
<div id="custom-tooltip"></div>
|
||||
</body>
|
||||
|
||||
@@ -964,10 +964,7 @@ function renderResources() {
|
||||
// Rescues — only show if player has any beacon/mesh nodes
|
||||
const rescuesRes = document.getElementById('r-rescues');
|
||||
if (rescuesRes) {
|
||||
const container = rescuesRes.closest('.res');
|
||||
if (container) {
|
||||
container.style.display = (G.rescues > 0 || G.buildings.beacon > 0 || G.buildings.meshNode > 0) ? 'block' : 'none';
|
||||
}
|
||||
rescuesRes.closest('.res').style.display = (G.rescues > 0 || G.buildings.beacon > 0 || G.buildings.meshNode > 0) ? 'block' : 'none';
|
||||
set('r-rescues', G.rescues, G.rescuesRate);
|
||||
}
|
||||
|
||||
|
||||
@@ -177,9 +177,6 @@ function renderTutorialStep(index) {
|
||||
if (!overlay) {
|
||||
overlay = document.createElement('div');
|
||||
overlay.id = 'tutorial-overlay';
|
||||
overlay.setAttribute('role', 'dialog');
|
||||
overlay.setAttribute('aria-modal', 'true');
|
||||
overlay.setAttribute('aria-label', 'Tutorial');
|
||||
document.body.appendChild(overlay);
|
||||
}
|
||||
|
||||
@@ -199,8 +196,8 @@ function renderTutorialStep(index) {
|
||||
<div class="t-tip">${step.tip}</div>
|
||||
<div id="tutorial-dots">${dots}</div>
|
||||
<div id="tutorial-btns">
|
||||
<button id="tutorial-skip-btn" onclick="closeTutorial()" aria-label="Skip tutorial">Skip</button>
|
||||
<button id="tutorial-next-btn" onclick="${isLast ? 'closeTutorial()' : 'nextTutorialStep()'}" aria-label="${isLast ? 'Start playing' : 'Next tutorial step'}">${isLast ? 'Start Playing' : 'Next →'}</button>
|
||||
<button id="tutorial-skip-btn" onclick="closeTutorial()">Skip</button>
|
||||
<button id="tutorial-next-btn" onclick="${isLast ? 'closeTutorial()' : 'nextTutorialStep()'}">${isLast ? 'Start Playing' : 'Next →'}</button>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
Reference in New Issue
Block a user