3 Commits

Author SHA1 Message Date
e395da105e Hide regtest tab when not on localhost 2026-07-22 12:43:47 -04:00
8c75e40edc Upload files to "/"
mobile changes
2026-07-21 22:48:50 +00:00
97617cecad Update index.html
added mobile view
2026-07-21 22:47:53 +00:00
2 changed files with 190 additions and 3 deletions

99
MOBILE-CHANGES.md Normal file
View File

@@ -0,0 +1,99 @@
# Mobile readability fixes — `index.html`
Base: commit `3dcd822` (`bitcoinafterlife/bal-welist-website`, `main`).
**Scope:** header, filter bar and server list only. CSS-only — the JavaScript is
byte-for-byte unchanged. Desktop rendering is unaffected: every change sits
inside a `@media (max-width: ...)` block, except one line on `body` (item 7).
The "Add your Will Executor" panel, the invoice and the QR code were left
untouched on purpose, since payments are expected to be made from a desktop
browser.
---
## 1. Chain selector overflowed the viewport
**Before:** `.seg` was an `inline-flex` row of four buttons (Bitcoin, Testnet,
Testnet4, Regtest) with no wrapping — roughly 340px wide. On a 360390px phone,
minus page padding, it pushed past the right edge and made the whole page scroll
horizontally.
**After:** below 600px the selector becomes a full-width 2×2 grid. Inner
dividers are recalculated with `:nth-child` so the borders stay correct in the
new arrangement.
## 2. Touch targets too small
Chain buttons were ~33px tall. Raised to `min-height: 44px` (the standard
minimum for a finger), applied to the chain buttons, the Tor toggle row and the
JSON link.
## 3. Nested scrolling in the server list
**Before:** `.mobile-list` carried `max-height: 350px; overflow: auto`, so on a
phone the list was a small window scrolling inside a page that also scrolls —
the two gestures fight each other.
**After:** the height cap is removed below 860px; the list flows with the page.
The desktop table (`.table-card`) keeps its 350px cap unchanged.
## 4. Long URLs broke out of the cards
Server URLs contain no spaces, so the browser cannot break them and they
overflowed the card. Added `overflow-wrap: anywhere`, plus `min-width: 0` on the
flex parent — without it a flex child defaults to `min-width: auto` and refuses
to shrink below its content width.
The JS truncation at 40 characters is unchanged.
## 5. Uneven card grid
The five fields (Score, Wins, Fee, Version, Height) sat in two fixed columns,
leaving Height alone on a half-empty row. Switched to
`repeat(auto-fit, minmax(84px, 1fr))`, which fits as many columns as the width
allows.
## 6. iOS auto-zoom on the search field
iOS Safari zooms the entire page when a focused input has a font size below
16px, and the user then has to pinch back out. The filter field is raised to
16px below 600px and made full width.
## 7. Text inflation in landscape
Added `-webkit-text-size-adjust: 100%` to `body`. iOS enlarges font sizes when a
phone is rotated to landscape, which distorted the header and the cards. This is
the only change outside a media query; it has no effect on desktop browsers.
## 8. Tighter spacing below 480px
New breakpoint reducing padding and type size where space is scarce:
| Element | Before | After |
| --- | --- | --- |
| `.wrap` side padding | 20px | 14px (+12px usable width per row) |
| `header.hero` padding | 48px 0 28px | 28px 0 20px |
| `.brand h1` | 24px | 20px |
| Logo mark | 46px | 40px |
| `.stat .n` | 26px | 22px |
| `.intro-card` padding | 28px 32px | 20px 18px |
| `.info-block` padding | 22px 24px | 18px 16px |
| `.srv` padding | 16px | 14px |
| Footer | space-between, wrapping | single column |
---
## Verification performed
- CSS braces balanced (148 open / 148 close).
- All 32 element IDs referenced by the JavaScript still present in the markup.
- Tag balance checked for `div`, `section`, `header`, `footer`, `main`, `table`,
`style`, `script`.
- Media queries present in order: 860px, 600px, 480px, `prefers-reduced-motion`.
## Not yet verified
Rendering was not tested on a physical device. Worth a quick check on one iPhone
and one Android phone before merging, in particular the 2×2 chain selector at
320px width (iPhone SE, the narrowest screen still in common use).

View File

@@ -40,6 +40,10 @@ body{
font-family:var(--body); font-family:var(--body);
line-height:1.5; line-height:1.5;
-webkit-font-smoothing:antialiased; -webkit-font-smoothing:antialiased;
/* WHY: iOS Safari inflates font sizes when a phone is rotated to landscape,
which breaks the header and the server cards. Locking the adjustment to
100% keeps the layout identical in both orientations. No effect on desktop. */
-webkit-text-size-adjust:100%;
} }
.wrap{max-width:var(--maxw);margin:0 auto;padding:0 20px} .wrap{max-width:var(--maxw);margin:0 auto;padding:0 20px}
@@ -207,7 +211,11 @@ footer a{color:var(--accent);text-decoration:none}
.mobile-list{display:none} .mobile-list{display:none}
@media (max-width:860px){ @media (max-width:860px){
.table-card{display:none} .table-card{display:none}
.mobile-list{display:grid;gap:12px;max-height:350px;overflow:auto;padding-right:2px} /* WHY: the previous "max-height:350px;overflow:auto" turned the server list
into a small scrollable window nested inside the page. On a touch screen
that inner scroll competes with the normal page scroll and makes the list
hard to read. On mobile the list now flows naturally with the page. */
.mobile-list{display:grid;gap:12px}
.add-grid{grid-template-columns:1fr} .add-grid{grid-template-columns:1fr}
.info-grid{grid-template-columns:1fr} .info-grid{grid-template-columns:1fr}
.hero-stats{gap:20px} .hero-stats{gap:20px}
@@ -215,9 +223,82 @@ footer a{color:var(--accent);text-decoration:none}
.srv{background:var(--panel);border:1px solid var(--line);border-radius:var(--radius);padding:16px;box-shadow:var(--shadow)} .srv{background:var(--panel);border:1px solid var(--line);border-radius:var(--radius);padding:16px;box-shadow:var(--shadow)}
.srv .top{display:flex;justify-content:space-between;align-items:flex-start;gap:10px;margin-bottom:12px} .srv .top{display:flex;justify-content:space-between;align-items:flex-start;gap:10px;margin-bottom:12px}
.srv .rk{font-family:var(--display);font-weight:600;color:var(--rank);font-size:18px} .srv .rk{font-family:var(--display);font-weight:600;color:var(--rank);font-size:18px}
.srv .grid{display:grid;grid-template-columns:1fr 1fr;gap:10px;font-size:13px} /* WHY: server URLs have no spaces, so a long URL cannot break by itself and
would overflow the card. "anywhere" lets it wrap at any character.
"min-width:0" is required because a flex child defaults to min-width:auto,
which prevents it from shrinking below its content width. */
.srv .top>div{min-width:0}
.srv .top a{display:inline-block;max-width:100%;overflow-wrap:anywhere}
/* WHY: with two fixed columns the fifth field (Height) was left alone on a
half-empty row. auto-fit fills the available width with as many columns as
fit, so the five fields always line up tidily. */
.srv .grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(84px,1fr));gap:10px;font-size:13px}
.srv .grid div span{display:block;color:var(--muted);font-size:11px;text-transform:uppercase;letter-spacing:.06em;margin-bottom:2px} .srv .grid div span{display:block;color:var(--muted);font-size:11px;text-transform:uppercase;letter-spacing:.06em;margin-bottom:2px}
.srv .grid div b{font-family:var(--mono);font-weight:600} .srv .grid div b{font-family:var(--mono);font-weight:600;overflow-wrap:anywhere}
}
/* ---------------------------------------------------------------------------
Phone layout (<=600px).
Scope: header, filter bar and server list only. The "Add your Will Executor"
panel, the invoice and the QR code are intentionally left untouched, because
payments are expected to be made from a desktop browser.
--------------------------------------------------------------------------- */
@media (max-width:600px){
.controls{gap:10px}
/* WHY: the four chain buttons form a single non-wrapping row about 340px wide.
Inside a 360-390px phone screen (minus page padding) it overflowed the
viewport and produced horizontal scrolling. A 2x2 grid across the full
width removes the overflow. min-height:44px matches the recommended
minimum touch target size. */
.seg{display:grid;grid-template-columns:1fr 1fr;width:100%;border-radius:8px}
.seg button{font-size:14px;min-height:44px;padding:8px 10px;border-bottom:1px solid var(--line)}
.seg button:nth-child(2n){border-right:0} /* right column: no inner divider */
.seg button:nth-child(n+3){border-bottom:0} /* last row: no bottom divider */
/* Give the toggle and the JSON link a full-size touch area. */
.field{min-height:44px}
.btn-ghost{min-height:44px}
/* WHY: the search field takes the full width so it is comfortable to type in,
and the font is raised to 16px. Below 16px, iOS Safari automatically zooms
the whole page when the field receives focus, and the user then has to
pinch back out. 16px disables that behaviour. */
.search{flex:1 1 100%}
.search input{font-size:16px}
}
/* ---------------------------------------------------------------------------
Narrow phone layout (<=480px): tighter spacing to recover horizontal space.
--------------------------------------------------------------------------- */
@media (max-width:480px){
/* Recovers 12px of usable width on every row of the page. */
.wrap{padding:0 14px}
header.hero{padding:28px 0 20px}
.hero .wrap{gap:16px}
.brand{gap:12px}
.brand .mark{width:40px;height:40px;border-radius:10px}
.brand .mark .brand-logo{width:28px;height:28px}
.brand h1{font-size:20px}
.brand .sub{font-size:13px}
.stat .n{font-size:22px}
.controls{padding:16px 0 12px}
.srv{padding:14px}
.intro-card{padding:20px 18px;margin:22px 0 8px}
.intro-card h2{font-size:20px}
.intro-card p{font-size:14px}
.info-section{margin:32px 0}
.info-block{padding:18px 16px}
/* WHY: the four footer items were spread with space-between and wrapped into
an uneven, hard-to-read block. A single column reads cleanly on a phone. */
footer{margin-top:32px;padding:22px 0}
footer .wrap{flex-direction:column;gap:8px}
} }
@media (prefers-reduced-motion:reduce){*{transition:none!important}} @media (prefers-reduced-motion:reduce){*{transition:none!important}}
@@ -394,6 +475,13 @@ footer a{color:var(--accent);text-decoration:none}
</footer> </footer>
<script> <script>
if (window.location.hostname !== 'localhost') {
const regtestBtn = document.querySelector('#chainSeg [data-c="regtest"]');
if (regtestBtn) {
regtestBtn.style.display = 'none';
regtestBtn.setAttribute('aria-pressed', 'false');
}
}
let allServers = []; let allServers = [];
let withTor = true, q = ""; let withTor = true, q = "";
let minAmount = 50000; let minAmount = 50000;