Accessibility fixes
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"semi": false,
|
||||
"semi": true,
|
||||
"singleQuote": true,
|
||||
"tabWidth": 4,
|
||||
"trailingComma": "none",
|
||||
"trailingComma": "all",
|
||||
"overrides": [
|
||||
{
|
||||
"files": "*.yml",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import prettierConfig from 'eslint-config-prettier/flat'
|
||||
import prettierConfig from 'eslint-config-prettier/flat';
|
||||
|
||||
export default [
|
||||
{
|
||||
@@ -9,12 +9,12 @@ export default [
|
||||
globals: {
|
||||
window: 'readonly',
|
||||
document: 'readonly',
|
||||
dataLayer: 'writable'
|
||||
}
|
||||
dataLayer: 'writable',
|
||||
},
|
||||
},
|
||||
rules: {
|
||||
'no-unused-vars': ['warn', { argsIgnorePattern: '^_' }]
|
||||
}
|
||||
'no-unused-vars': ['warn', { argsIgnorePattern: '^_' }],
|
||||
},
|
||||
},
|
||||
prettierConfig
|
||||
]
|
||||
prettierConfig,
|
||||
];
|
||||
|
||||
@@ -8,71 +8,71 @@ import {
|
||||
readFileSync,
|
||||
writeFileSync,
|
||||
cpSync,
|
||||
readdirSync
|
||||
} from 'fs'
|
||||
import { join, dirname, extname } from 'path'
|
||||
import { fileURLToPath } from 'url'
|
||||
import Beasties from 'beasties'
|
||||
import { minify as minifyJs } from 'terser'
|
||||
import CleanCSS from 'clean-css'
|
||||
readdirSync,
|
||||
} from 'fs';
|
||||
import { join, dirname, extname } from 'path';
|
||||
import { fileURLToPath } from 'url';
|
||||
import Beasties from 'beasties';
|
||||
import { minify as minifyJs } from 'terser';
|
||||
import CleanCSS from 'clean-css';
|
||||
|
||||
const __dirname = dirname(fileURLToPath(import.meta.url))
|
||||
const root = join(__dirname, '..')
|
||||
const srcDir = join(root, 'src')
|
||||
const distDir = join(root, 'dist')
|
||||
const __dirname = dirname(fileURLToPath(import.meta.url));
|
||||
const root = join(__dirname, '..');
|
||||
const srcDir = join(root, 'src');
|
||||
const distDir = join(root, 'dist');
|
||||
|
||||
function getFiles(dir, files = []) {
|
||||
const entries = readdirSync(dir, { withFileTypes: true })
|
||||
const entries = readdirSync(dir, { withFileTypes: true });
|
||||
for (const e of entries) {
|
||||
const full = join(dir, e.name)
|
||||
if (e.isDirectory()) getFiles(full, files)
|
||||
else files.push(full)
|
||||
const full = join(dir, e.name);
|
||||
if (e.isDirectory()) getFiles(full, files);
|
||||
else files.push(full);
|
||||
}
|
||||
return files
|
||||
return files;
|
||||
}
|
||||
|
||||
async function main() {
|
||||
// 1. Clean and copy src → dist
|
||||
rmSync(distDir, { recursive: true, force: true })
|
||||
mkdirSync(distDir, { recursive: true })
|
||||
cpSync(srcDir, distDir, { recursive: true })
|
||||
rmSync(distDir, { recursive: true, force: true });
|
||||
mkdirSync(distDir, { recursive: true });
|
||||
cpSync(srcDir, distDir, { recursive: true });
|
||||
|
||||
const distFiles = getFiles(distDir)
|
||||
const distFiles = getFiles(distDir);
|
||||
|
||||
// 2. Minify JS
|
||||
const jsFiles = distFiles.filter((f) => extname(f) === '.js')
|
||||
const jsFiles = distFiles.filter((f) => extname(f) === '.js');
|
||||
for (const f of jsFiles) {
|
||||
const code = readFileSync(f, 'utf8')
|
||||
const result = await minifyJs(code, { format: { comments: false } })
|
||||
if (result.code) writeFileSync(f, result.code)
|
||||
const code = readFileSync(f, 'utf8');
|
||||
const result = await minifyJs(code, { format: { comments: false } });
|
||||
if (result.code) writeFileSync(f, result.code);
|
||||
}
|
||||
|
||||
// 3. Minify CSS
|
||||
const cleanCss = new CleanCSS({ level: 2 })
|
||||
const cssFiles = distFiles.filter((f) => extname(f) === '.css')
|
||||
const cleanCss = new CleanCSS({ level: 2 });
|
||||
const cssFiles = distFiles.filter((f) => extname(f) === '.css');
|
||||
for (const f of cssFiles) {
|
||||
const code = readFileSync(f, 'utf8')
|
||||
const result = cleanCss.minify(code)
|
||||
if (!result.errors.length) writeFileSync(f, result.styles)
|
||||
const code = readFileSync(f, 'utf8');
|
||||
const result = cleanCss.minify(code);
|
||||
if (!result.errors.length) writeFileSync(f, result.styles);
|
||||
}
|
||||
|
||||
// 4. Inline critical CSS with Beasties for all HTML files (no browser; works in CI)
|
||||
const htmlFiles = distFiles.filter((f) => extname(f) === '.html')
|
||||
const htmlFiles = distFiles.filter((f) => extname(f) === '.html');
|
||||
const beasties = new Beasties({
|
||||
path: distDir,
|
||||
preload: 'default',
|
||||
logLevel: 'warn'
|
||||
})
|
||||
logLevel: 'warn',
|
||||
});
|
||||
for (const htmlFile of htmlFiles) {
|
||||
const html = readFileSync(htmlFile, 'utf8')
|
||||
const inlined = await beasties.process(html)
|
||||
writeFileSync(htmlFile, inlined)
|
||||
const html = readFileSync(htmlFile, 'utf8');
|
||||
const inlined = await beasties.process(html);
|
||||
writeFileSync(htmlFile, inlined);
|
||||
}
|
||||
|
||||
console.log('Build complete: dist/')
|
||||
console.log('Build complete: dist/');
|
||||
}
|
||||
|
||||
main().catch((err) => {
|
||||
console.error(err)
|
||||
process.exit(1)
|
||||
})
|
||||
console.error(err);
|
||||
process.exit(1);
|
||||
});
|
||||
|
||||
@@ -44,9 +44,53 @@ body {
|
||||
}
|
||||
|
||||
body {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1rem;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.content {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.footer {
|
||||
color: #374151;
|
||||
font-size: 0.94em;
|
||||
letter-spacing: 0.01em;
|
||||
padding: 1rem;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
.footer {
|
||||
color: #aab2bd;
|
||||
}
|
||||
}
|
||||
|
||||
.skip-link {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
padding: 0.75rem 1.25rem;
|
||||
background: var(--accent);
|
||||
color: var(--button-text);
|
||||
font-weight: 600;
|
||||
text-decoration: none;
|
||||
z-index: 100;
|
||||
transform: translateY(-100%);
|
||||
transition: transform 0.2s;
|
||||
}
|
||||
|
||||
.skip-link:focus {
|
||||
transform: translateY(0);
|
||||
outline: 2px solid var(--accent-light);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
@@ -194,9 +238,10 @@ td:first-child {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/* Tip colors chosen for WCAG 2.2 AAA (≥7:1 contrast) */
|
||||
.tip {
|
||||
background: #eef2ff;
|
||||
color: var(--accent-light);
|
||||
color: #3730a3;
|
||||
border-radius: 0.7em;
|
||||
font-size: 0.98em;
|
||||
padding: 0.48em 0.8em;
|
||||
@@ -207,7 +252,7 @@ td:first-child {
|
||||
@media (prefers-color-scheme: dark) {
|
||||
.tip {
|
||||
background: #232555;
|
||||
color: #a5b4fc;
|
||||
color: #c7d2fe;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -295,14 +340,6 @@ td:first-child {
|
||||
color: var(--faq-a);
|
||||
}
|
||||
|
||||
.footer {
|
||||
margin-top: 2.5em;
|
||||
text-align: center;
|
||||
color: #bbb;
|
||||
font-size: 0.94em;
|
||||
letter-spacing: 0.01em;
|
||||
}
|
||||
|
||||
@media (width <= 600px) {
|
||||
.container {
|
||||
padding: 1.1rem 0.5rem 1rem;
|
||||
|
||||
37
src/assets/js/accordion.js
Normal file
37
src/assets/js/accordion.js
Normal file
@@ -0,0 +1,37 @@
|
||||
// Native accessible accordion
|
||||
document.querySelectorAll('.accordion-trigger').forEach((btn) => {
|
||||
btn.addEventListener('click', function () {
|
||||
const section = btn.closest('.accordion-section');
|
||||
const expanded = btn.getAttribute('aria-expanded') === 'true';
|
||||
document.querySelectorAll('.accordion-section').forEach((s) => {
|
||||
if (s === section) {
|
||||
s.classList.toggle('open', !expanded);
|
||||
btn.setAttribute('aria-expanded', String(!expanded));
|
||||
const content = btn.nextElementSibling;
|
||||
content.style.maxHeight = !expanded
|
||||
? content.scrollHeight + 40 + 'px'
|
||||
: '0px';
|
||||
} else {
|
||||
s.classList.remove('open');
|
||||
s.querySelector('.accordion-trigger').setAttribute(
|
||||
'aria-expanded',
|
||||
'false',
|
||||
);
|
||||
s.querySelector('.accordion-content').style.maxHeight = '0px';
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Allow arrow navigation
|
||||
btn.addEventListener('keydown', function (e) {
|
||||
if (e.key === 'ArrowDown' || e.key === 'ArrowUp') {
|
||||
const triggers = Array.from(
|
||||
document.querySelectorAll('.accordion-trigger'),
|
||||
);
|
||||
let idx = triggers.indexOf(e.target);
|
||||
if (e.key === 'ArrowDown') idx = (idx + 1) % triggers.length;
|
||||
else idx = (idx - 1 + triggers.length) % triggers.length;
|
||||
triggers[idx].focus();
|
||||
}
|
||||
});
|
||||
});
|
||||
4
src/assets/js/current-year.js
Normal file
4
src/assets/js/current-year.js
Normal file
@@ -0,0 +1,4 @@
|
||||
(function () {
|
||||
const year = new Date().getFullYear();
|
||||
document.getElementById('current-year').textContent = `–${year}`;
|
||||
})();
|
||||
@@ -1,11 +1,11 @@
|
||||
;(function () {
|
||||
var script = document.currentScript
|
||||
var id = script && script.getAttribute('data-ga-id')
|
||||
if (!id) return
|
||||
window.dataLayer = window.dataLayer || []
|
||||
(function () {
|
||||
var script = document.currentScript;
|
||||
var id = script && script.getAttribute('data-ga-id');
|
||||
if (!id) return;
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag() {
|
||||
window.dataLayer.push(arguments)
|
||||
window.dataLayer.push(arguments);
|
||||
}
|
||||
gtag('js', new Date())
|
||||
gtag('config', id, { anonymize_ip: true })
|
||||
})()
|
||||
gtag('js', new Date());
|
||||
gtag('config', id, { anonymize_ip: true });
|
||||
})();
|
||||
|
||||
@@ -95,283 +95,248 @@
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container faq">
|
||||
<nav aria-label="Breadcrumb">
|
||||
<ol class="breadcrumb">
|
||||
<li><a href="/">Home</a></li>
|
||||
<li aria-current="page">Email Setup & Help</li>
|
||||
</ol>
|
||||
</nav>
|
||||
<h1 class="text-center">Welcome to Email from mifi Ventures</h1>
|
||||
<div class="intro">
|
||||
<strong>Let's get your inbox ready! 📬</strong><br />
|
||||
<p>
|
||||
Friendly help for setting up your email—works with Outlook,
|
||||
Apple Mail, Thunderbird, phones, and more.
|
||||
</p>
|
||||
</div>
|
||||
<a href="#main-content" class="skip-link">Skip to main content</a>
|
||||
<div class="content">
|
||||
<main id="main-content" class="container faq">
|
||||
<nav aria-label="Breadcrumb">
|
||||
<ol class="breadcrumb">
|
||||
<li><a href="/">Home</a></li>
|
||||
<li aria-current="page">Email Setup & Help</li>
|
||||
</ol>
|
||||
</nav>
|
||||
<h1 class="text-center">Welcome to Email from mifi Ventures</h1>
|
||||
<div class="intro">
|
||||
<strong>Let's get your inbox ready! 📬</strong><br />
|
||||
<p>
|
||||
Friendly help for setting up your email—works with
|
||||
Outlook, Apple Mail, Thunderbird, phones, and more.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<section
|
||||
class="general-settings"
|
||||
aria-label="General Email Settings"
|
||||
>
|
||||
<h2>General Settings (All Clients)</h2>
|
||||
<table>
|
||||
<tr>
|
||||
<td>Email Address</td>
|
||||
<td>your.name@yourdomain.com</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Username</td>
|
||||
<td>your.name@yourdomain.com</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Password</td>
|
||||
<td>(your email password)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Incoming Server</td>
|
||||
<td><b>mail.mifi.holdings</b></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Outgoing Server</td>
|
||||
<td><b>mail.mifi.holdings</b></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>IMAP Port</td>
|
||||
<td>993 (SSL/TLS)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>POP3 Port</td>
|
||||
<td>995 (SSL/TLS)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>SMTP Port</td>
|
||||
<td>587 (STARTTLS) or 465 (SSL/TLS)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Authentication</td>
|
||||
<td>Required (use same as incoming)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Encryption</td>
|
||||
<td>SSL/TLS or STARTTLS</td>
|
||||
</tr>
|
||||
</table>
|
||||
<span class="tip"
|
||||
>Tip: Always use your <b>full email address</b> as your
|
||||
username!</span
|
||||
<section
|
||||
class="general-settings"
|
||||
aria-label="General Email Settings"
|
||||
>
|
||||
</section>
|
||||
|
||||
<div class="accordion" id="helpAccordion">
|
||||
<!-- Outlook -->
|
||||
<section class="accordion-section">
|
||||
<button class="accordion-trigger" aria-expanded="false">
|
||||
<span class="icon">▶</span> Microsoft Outlook
|
||||
</button>
|
||||
<div class="accordion-content">
|
||||
<ol>
|
||||
<li>Go to <b>File → Add Account</b></li>
|
||||
<li>Enter your full email address</li>
|
||||
<li>
|
||||
Choose <b>Advanced options</b> → check “Set up
|
||||
manually”
|
||||
</li>
|
||||
<li>Select <b>IMAP</b> (recommended) or POP</li>
|
||||
<li>
|
||||
Incoming server:
|
||||
<code>mail.mifi.holdings</code>, port
|
||||
<b>993</b> (SSL/TLS)
|
||||
</li>
|
||||
<li>
|
||||
Outgoing server:
|
||||
<code>mail.mifi.holdings</code>, port
|
||||
<b>587</b> (STARTTLS) or <b>465</b> (SSL/TLS)
|
||||
</li>
|
||||
<li>
|
||||
Username: full email address; Password: your
|
||||
password
|
||||
</li>
|
||||
<li>Click <b>Connect</b></li>
|
||||
</ol>
|
||||
<span class="tip"
|
||||
>If sending fails, make sure “Require logon using
|
||||
SPA” is <b>unchecked</b>.</span
|
||||
>
|
||||
</div>
|
||||
<h2>General Settings (All Clients)</h2>
|
||||
<table>
|
||||
<tr>
|
||||
<td>Email Address</td>
|
||||
<td>your.name@yourdomain.com</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Username</td>
|
||||
<td>your.name@yourdomain.com</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Password</td>
|
||||
<td>(your email password)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Incoming Server</td>
|
||||
<td><b>mail.mifi.holdings</b></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Outgoing Server</td>
|
||||
<td><b>mail.mifi.holdings</b></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>IMAP Port</td>
|
||||
<td>993 (SSL/TLS)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>POP3 Port</td>
|
||||
<td>995 (SSL/TLS)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>SMTP Port</td>
|
||||
<td>587 (STARTTLS) or 465 (SSL/TLS)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Authentication</td>
|
||||
<td>Required (use same as incoming)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Encryption</td>
|
||||
<td>SSL/TLS or STARTTLS</td>
|
||||
</tr>
|
||||
</table>
|
||||
<span class="tip"
|
||||
>Tip: Always use your <b>full email address</b> as your
|
||||
username!</span
|
||||
>
|
||||
</section>
|
||||
|
||||
<!-- Apple Mail -->
|
||||
<section class="accordion-section">
|
||||
<button class="accordion-trigger" aria-expanded="false">
|
||||
<span class="icon">▶</span> Apple Mail (macOS, iOS)
|
||||
</button>
|
||||
<div class="accordion-content">
|
||||
<ol>
|
||||
<li>
|
||||
Add Account → <b>Other Mail Account</b>
|
||||
</li>
|
||||
<li>Enter your name, email, and password</li>
|
||||
<li>
|
||||
Incoming/Outgoing server:
|
||||
<code>mail.mifi.holdings</code>
|
||||
</li>
|
||||
<li>
|
||||
IMAP port: <b>993</b> (SSL); SMTP port:
|
||||
<b>587</b> (STARTTLS) or <b>465</b> (SSL)
|
||||
</li>
|
||||
<li>Use full email address for username</li>
|
||||
</ol>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Thunderbird -->
|
||||
<section class="accordion-section">
|
||||
<button class="accordion-trigger" aria-expanded="false">
|
||||
<span class="icon">▶</span> Thunderbird
|
||||
</button>
|
||||
<div class="accordion-content">
|
||||
<ol>
|
||||
<li>Menu → Account Settings → Add Mail Account</li>
|
||||
<li>Fill in your name, email, and password</li>
|
||||
<li>
|
||||
Click “Configure manually” and use settings
|
||||
above
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Mobile -->
|
||||
<section class="accordion-section">
|
||||
<button class="accordion-trigger" aria-expanded="false">
|
||||
<span class="icon">▶</span> iOS / Android Mail / Gmail
|
||||
App
|
||||
</button>
|
||||
<div class="accordion-content">
|
||||
<ul>
|
||||
<li>Add Account → Other</li>
|
||||
<li>Enter your email and password</li>
|
||||
<li>
|
||||
Manual setup: <code>mail.mifi.holdings</code>,
|
||||
correct ports, SSL/TLS required
|
||||
</li>
|
||||
<li>
|
||||
Gmail app: tap profile → Add account → Other,
|
||||
fill in details, use IMAP
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- FAQ -->
|
||||
<section class="accordion-section">
|
||||
<button class="accordion-trigger" aria-expanded="false">
|
||||
<span class="icon">▶</span> FAQ / Troubleshooting
|
||||
</button>
|
||||
<div class="accordion-content">
|
||||
<div class="faq-q">Q: My email won’t send?</div>
|
||||
<div class="faq-a">
|
||||
Check that you’re using your full email address for
|
||||
both incoming and outgoing username, and that the
|
||||
port is 587 or 465.
|
||||
<div class="accordion" id="helpAccordion">
|
||||
<!-- Outlook -->
|
||||
<section class="accordion-section">
|
||||
<button class="accordion-trigger" aria-expanded="false">
|
||||
<span class="icon">▶</span> Microsoft Outlook
|
||||
</button>
|
||||
<div class="accordion-content">
|
||||
<ol>
|
||||
<li>Go to <b>File → Add Account</b></li>
|
||||
<li>Enter your full email address</li>
|
||||
<li>
|
||||
Choose <b>Advanced options</b> → check “Set
|
||||
up manually”
|
||||
</li>
|
||||
<li>Select <b>IMAP</b> (recommended) or POP</li>
|
||||
<li>
|
||||
Incoming server:
|
||||
<code>mail.mifi.holdings</code>, port
|
||||
<b>993</b> (SSL/TLS)
|
||||
</li>
|
||||
<li>
|
||||
Outgoing server:
|
||||
<code>mail.mifi.holdings</code>, port
|
||||
<b>587</b> (STARTTLS) or
|
||||
<b>465</b> (SSL/TLS)
|
||||
</li>
|
||||
<li>
|
||||
Username: full email address; Password: your
|
||||
password
|
||||
</li>
|
||||
<li>Click <b>Connect</b></li>
|
||||
</ol>
|
||||
<span class="tip"
|
||||
>If sending fails, make sure “Require logon
|
||||
using SPA” is <b>unchecked</b>.</span
|
||||
>
|
||||
</div>
|
||||
<div class="faq-q">Q: SSL/TLS errors?</div>
|
||||
<div class="faq-a">
|
||||
Ensure SSL or STARTTLS is enabled for both incoming
|
||||
and outgoing mail.
|
||||
</div>
|
||||
<div class="faq-q">Q: Still stuck?</div>
|
||||
<div class="faq-a">
|
||||
Contact
|
||||
<a href="mailto:postmaster@mifi.holdings"
|
||||
>postmaster@mifi.holdings</a
|
||||
>.<br />
|
||||
Please include any error messages, your mail app,
|
||||
and a screenshot if you can!
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
<!-- Pro Tips -->
|
||||
<section class="accordion-section">
|
||||
<button class="accordion-trigger" aria-expanded="false">
|
||||
<span class="icon">▶</span> Pro Tips & Advanced
|
||||
</button>
|
||||
<div class="accordion-content">
|
||||
<ul>
|
||||
<li>
|
||||
<b>IMAP syncs</b> your mail everywhere—choose
|
||||
IMAP unless you know you want POP3.
|
||||
</li>
|
||||
<li>
|
||||
Your login is always your
|
||||
<b>full email address</b>.
|
||||
</li>
|
||||
<li>
|
||||
Check your Spam/Junk folder for misfiled good
|
||||
emails.
|
||||
</li>
|
||||
<li>
|
||||
Advanced: IMAP path prefix =
|
||||
<b>(leave blank)</b>; SMTP authentication is
|
||||
always required.
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
<div class="footer">
|
||||
Email from mifi Ventures · Help Page – © 2025
|
||||
mifi Ventures, LLC
|
||||
</div>
|
||||
<!-- Apple Mail -->
|
||||
<section class="accordion-section">
|
||||
<button class="accordion-trigger" aria-expanded="false">
|
||||
<span class="icon">▶</span> Apple Mail (macOS, iOS)
|
||||
</button>
|
||||
<div class="accordion-content">
|
||||
<ol>
|
||||
<li>
|
||||
Add Account → <b>Other Mail Account</b>
|
||||
</li>
|
||||
<li>Enter your name, email, and password</li>
|
||||
<li>
|
||||
Incoming/Outgoing server:
|
||||
<code>mail.mifi.holdings</code>
|
||||
</li>
|
||||
<li>
|
||||
IMAP port: <b>993</b> (SSL); SMTP port:
|
||||
<b>587</b> (STARTTLS) or <b>465</b> (SSL)
|
||||
</li>
|
||||
<li>Use full email address for username</li>
|
||||
</ol>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Thunderbird -->
|
||||
<section class="accordion-section">
|
||||
<button class="accordion-trigger" aria-expanded="false">
|
||||
<span class="icon">▶</span> Thunderbird
|
||||
</button>
|
||||
<div class="accordion-content">
|
||||
<ol>
|
||||
<li>
|
||||
Menu → Account Settings → Add Mail Account
|
||||
</li>
|
||||
<li>Fill in your name, email, and password</li>
|
||||
<li>
|
||||
Click “Configure manually” and use settings
|
||||
above
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Mobile -->
|
||||
<section class="accordion-section">
|
||||
<button class="accordion-trigger" aria-expanded="false">
|
||||
<span class="icon">▶</span> iOS / Android Mail /
|
||||
Gmail App
|
||||
</button>
|
||||
<div class="accordion-content">
|
||||
<ul>
|
||||
<li>Add Account → Other</li>
|
||||
<li>Enter your email and password</li>
|
||||
<li>
|
||||
Manual setup:
|
||||
<code>mail.mifi.holdings</code>, correct
|
||||
ports, SSL/TLS required
|
||||
</li>
|
||||
<li>
|
||||
Gmail app: tap profile → Add account →
|
||||
Other, fill in details, use IMAP
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- FAQ -->
|
||||
<section class="accordion-section">
|
||||
<button class="accordion-trigger" aria-expanded="false">
|
||||
<span class="icon">▶</span> FAQ / Troubleshooting
|
||||
</button>
|
||||
<div class="accordion-content">
|
||||
<div class="faq-q">Q: My email won’t send?</div>
|
||||
<div class="faq-a">
|
||||
Check that you’re using your full email address
|
||||
for both incoming and outgoing username, and
|
||||
that the port is 587 or 465.
|
||||
</div>
|
||||
<div class="faq-q">Q: SSL/TLS errors?</div>
|
||||
<div class="faq-a">
|
||||
Ensure SSL or STARTTLS is enabled for both
|
||||
incoming and outgoing mail.
|
||||
</div>
|
||||
<div class="faq-q">Q: Still stuck?</div>
|
||||
<div class="faq-a">
|
||||
Contact
|
||||
<a href="mailto:postmaster@mifi.holdings"
|
||||
>postmaster@mifi.holdings</a
|
||||
>.<br />
|
||||
Please include any error messages, your mail
|
||||
app, and a screenshot if you can!
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Pro Tips -->
|
||||
<section class="accordion-section">
|
||||
<button class="accordion-trigger" aria-expanded="false">
|
||||
<span class="icon">▶</span> Pro Tips & Advanced
|
||||
</button>
|
||||
<div class="accordion-content">
|
||||
<ul>
|
||||
<li>
|
||||
<b>IMAP syncs</b> your mail
|
||||
everywhere—choose IMAP unless you know you
|
||||
want POP3.
|
||||
</li>
|
||||
<li>
|
||||
Your login is always your
|
||||
<b>full email address</b>.
|
||||
</li>
|
||||
<li>
|
||||
Check your Spam/Junk folder for misfiled
|
||||
good emails.
|
||||
</li>
|
||||
<li>
|
||||
Advanced: IMAP path prefix =
|
||||
<b>(leave blank)</b>; SMTP authentication is
|
||||
always required.
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
<script>
|
||||
// Native accessible accordion
|
||||
document.querySelectorAll('.accordion-trigger').forEach((btn) => {
|
||||
btn.addEventListener('click', function () {
|
||||
const section = btn.closest('.accordion-section')
|
||||
const expanded =
|
||||
btn.getAttribute('aria-expanded') === 'true'
|
||||
document
|
||||
.querySelectorAll('.accordion-section')
|
||||
.forEach((s) => {
|
||||
if (s === section) {
|
||||
s.classList.toggle('open', !expanded)
|
||||
btn.setAttribute(
|
||||
'aria-expanded',
|
||||
String(!expanded)
|
||||
)
|
||||
const content = btn.nextElementSibling
|
||||
content.style.maxHeight = !expanded
|
||||
? content.scrollHeight + 40 + 'px'
|
||||
: '0px'
|
||||
} else {
|
||||
s.classList.remove('open')
|
||||
s.querySelector(
|
||||
'.accordion-trigger'
|
||||
).setAttribute('aria-expanded', 'false')
|
||||
s.querySelector(
|
||||
'.accordion-content'
|
||||
).style.maxHeight = '0px'
|
||||
}
|
||||
})
|
||||
})
|
||||
// Allow arrow navigation
|
||||
btn.addEventListener('keydown', function (e) {
|
||||
if (e.key === 'ArrowDown' || e.key === 'ArrowUp') {
|
||||
const triggers = Array.from(
|
||||
document.querySelectorAll('.accordion-trigger')
|
||||
)
|
||||
let idx = triggers.indexOf(e.target)
|
||||
if (e.key === 'ArrowDown')
|
||||
idx = (idx + 1) % triggers.length
|
||||
else idx = (idx - 1 + triggers.length) % triggers.length
|
||||
triggers[idx].focus()
|
||||
}
|
||||
})
|
||||
})
|
||||
</script>
|
||||
<footer class="footer">
|
||||
Email from mifi Holdings · Help Page · ©
|
||||
2025<span id="current-year"></span>
|
||||
mifi Ventures, LLC
|
||||
</footer>
|
||||
<script defer src="/assets/js/current-year.js"></script>
|
||||
<script defer src="/assets/js/accordion.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -57,24 +57,38 @@
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container text-center">
|
||||
<div class="emoji">📮</div>
|
||||
<h1>This is just a mailbox.</h1>
|
||||
<p>
|
||||
You've reached <b>mail.mifi.holdings</b>.<br />
|
||||
There's nothing exciting here's nothing exciting
|
||||
here—just some gears whirring and mail being sorted.<br />
|
||||
Looking for your messages?
|
||||
</p>
|
||||
<a class="button" href="/help">Email Setup Help</a>
|
||||
<a class="button" href="https://webmail.mifi.holdings"
|
||||
>Go to Webmail</a
|
||||
>
|
||||
<a
|
||||
class="button"
|
||||
href="https://postmaster.mifi.holdings/users/login.php"
|
||||
>Change/Forgot Password</a
|
||||
>
|
||||
<a href="#main-content" class="skip-link">Skip to main content</a>
|
||||
<div class="content">
|
||||
<main id="main-content" class="container text-center">
|
||||
<div class="emoji">📮</div>
|
||||
<h1>This is just a mailbox.</h1>
|
||||
<p>
|
||||
You've reached <b>mail.mifi.holdings</b>.<br />
|
||||
There's nothing exciting here's nothing exciting
|
||||
here—just some gears whirring and mail being sorted.<br />
|
||||
Looking for your messages?
|
||||
</p>
|
||||
<a class="button" href="/help">Email Setup Help</a>
|
||||
<a
|
||||
class="button"
|
||||
href="https://webmail.mifi.holdings"
|
||||
target="_blank"
|
||||
>Go to Webmail</a
|
||||
>
|
||||
<a
|
||||
class="button"
|
||||
href="https://postmaster.mifi.holdings/users/login.php"
|
||||
target="_blank"
|
||||
>Change/Forgot Password</a
|
||||
>
|
||||
</main>
|
||||
</div>
|
||||
<footer class="footer">
|
||||
Email from mifi Holdings · © 2025<span
|
||||
id="current-year"
|
||||
></span>
|
||||
mifi Ventures, LLC
|
||||
</footer>
|
||||
<script defer src="/assets/js/current-year.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -2,7 +2,7 @@ export default {
|
||||
extends: ['stylelint-config-standard'],
|
||||
overrides: [
|
||||
{
|
||||
files: ['src/**/*.css']
|
||||
}
|
||||
]
|
||||
}
|
||||
files: ['src/**/*.css'],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user