Skip to content

Latest commit

 

History

History
244 lines (205 loc) · 8.14 KB

File metadata and controls

244 lines (205 loc) · 8.14 KB

Kindle Browser Compatibility Guide

CRITICAL: When developing for this project, you must adhere to the following constraints to ensure compatibility with Kindle and E-ink browsers.

🚫 Restrictions (Target: Chromium 75)

1. No Flexbox Gap (gap)

Constraint: Chromium 75 supports gap for CSS Grid but NOT for Flexbox (added in Chrome 84). Solution:

  • Flex Containers: Use Margins (margin-left / margin-top on siblings).
  • Grid Containers: You CAN use gap. Prefer CSS Grid for layouts requiring gutters.

Example (Correct):

/* OK in Grid */
.grid-box { display: grid; gap: 10px; }

/* BROKEN in Flex (Do NOT use) */
.flex-box { display: flex; gap: 10px; }

2. JavaScript Limits (ES2019 Ceiling)

Constraint: The browser supports up to ES2019. BANNED Syntax (ES2020+):

  • ❌ Optional Chaining (?.) -> user?.name will CRASH the app.
  • ❌ Nullish Coalescing (??) -> val ?? default will CRASH the app.
  • async/await, Promises, Arrow Functions are SAFE.

3. No Animations / Transitions

Constraint: E-ink displays run at ~7-15fps. CSS animations cause severe ghosting and flashing. Solution: Disable all animations.

* {
    transition: none !important;
    animation: none !important;
}

4. No Alerts (alert())

Constraint: window.alert(), confirm(), and prompt() are unsupported. Solution: Use Custom Modals (HTML/CSS overlays).

Example (Correct):

<!-- Use a custom div overlay -->
<div id="custom-alert" class="modal-overlay">
  <div class="modal-box">
    <p>Operation failed.</p>
    <button onclick="closeModal()">OK</button>
  </div>
</div>

🎨 Standard UI Patterns (System 7)

All applications must adhere to the following strict HTML/CSS patterns to maintain the "Retro OS" look.

1. The Environment (body)

The body acts as the "desktop" background. It handles the centering of the application window.

body {
    background-color: #e5e5e5; /* Desktop Gray */
    font-family: "Geneva", "Verdana", sans-serif;
    image-rendering: pixelated; /* CRITICAL for crisp edges */
    margin: 0;
    height: 100vh;
    overflow: hidden; /* Prevent body scroll */
    
    /* Center the App Window */
    display: flex; 
    align-items: center; 
    justify-content: center;
}

2. The Window (.window)

The main container for every app.

:root {
    --shadow: 4px 4px 0px #000000;
}

.window {
    background: white;
    border: 2px solid black;
    box-shadow: var(--shadow); /* Hard, non-blurred shadow */
    width: 95%;
    max-width: 600px; /* Standard Tablet Width */
    height: 90vh; /* Or fit-content */
    display: flex;
    flex-direction: column;
    position: relative;
}

3. The Title Bar (.title-bar)

Mandatory Structure: The title bar uses a specific layered technique to achieve the "text on stripes" look.

HTML:

<div class="title-bar">
    <div class="title-stripes"></div>
    <div class="close-box" onclick="window.location.href='index'">X</div>
    <span class="title-text" data-i18n="app.title">My App</span>
</div>

CSS:

:root {
    --stripe-pattern: repeating-linear-gradient(0deg, transparent, transparent 2px, #000 3px, #000 4px);
}

.title-bar {
    height: 35px;
    border-bottom: 2px solid black;
    display: flex;
    align-items: center;
    justify-content: center;
    background: white;
    position: relative; /* Context for absolute children */
}

/* The Striped Background Layer */
.title-stripes {
    position: absolute;
    top: 4px; bottom: 4px; left: 4px; right: 4px;
    background-image: var(--stripe-pattern);
    z-index: 0;
}

/* The centered text with white background blocking stripes */
.title-text {
    background: white;
    padding: 0 15px;
    font-weight: bold;
    font-size: 1.1rem;
    z-index: 1; /* Sits above stripes */
}

/* Standard Close Button */
.close-box {
    position: absolute;
    left: 10px;
    width: 18px; height: 18px;
    border: 2px solid black;
    background: white;
    z-index: 2; /* Sits above everything */
    box-shadow: 2px 2px 0 black;
    cursor: pointer;
    /* Flex center content "X" */
    display: flex; align-items: center; justify-content: center;
}

4. Interactive Elements

Buttons and inputs share a "tactile" 2px border style.

  • Buttons: border: 2px solid black, box-shadow: 2px 2px 0 black.
    • Active State: transform: translate(2px, 2px), box-shadow: none, background: black, color: white.
  • Inputs: border: 2px solid black, border-radius: 0, font-family: inherit.

5. Z-Index Layering

Strict layering constants to prevent overlap issues.

Component Z-Index Notes
title-stripes 0 Background pattern
title-text 1 Sits above stripes
close-box 2 Interactive top layer
modal-overlay 10000 Always top-most

6. Branding & Badges

Standardized "Beta" or status badges.

Beta Badge:

.beta-badge {
    font-size: 0.6rem;
    margin-left: 5px;
    border: 1px solid black;
    padding: 1px 3px;
    font-weight: bold;
    font-family: sans-serif;
    vertical-align: text-top;
    display: inline-block;
    background: white;
    color: black;
}

🌍 Localization (i18n.js)

The project uses a custom i18n.js loader.

Attributes

Attribute Usage
data-i18n="key" Sets innerText
data-i18n-html="key" Sets innerHTML (Careful with XSS)
data-i18n-placeholder="key" Sets input placeholder
data-i18n-title="key" Sets element title tooltip
data-i18n-only="lang" Shows element only for specific lang code (e.g., "en")

Icons (SVG)

Icons are stored as raw SVG strings in icons.js.

  • Size: Designed for 32x32 pixel grid.
  • Stroke: stroke-width="2" (Standard) or "1.5" for detail.
  • Style: fill="none" stroke="black" OR fill="black" stroke="none".

🏗 System Architecture

1. JavaScript Execution (JIT-less)

  • Engine: V8 (Ignition Interpreter ONLY).
  • Flag: --js-flags="jitless".
  • Impact: 5x-10x slower CPU performance than standard mobile browsers.
  • Rule: Avoid heavy computation, crypto, or massive data parsing on the main thread.

2. Localization

  • Method: Use data-i18n attributes for all text content.
  • Library: js/i18n.js handles replacement automatically.

3. Viewport & Rendering

  • Meta Tag: user-scalable=no.
  • Sticky Positioning: AVOID position: sticky or fixed header/footers. They cause "checkerboarding" artifacts during E-ink page refreshes.
  • Touch Targets: Minimum 48x48px.

4. Storage & State

  • Persistence: localStorage is available but volatile.
  • Limit: 64MB Global Cache Limit. If exceeded, the OS performs rm -rf on the entire cache directory at launch.
  • Sync: Rely on Firebase Firestore for critical data; do not trust localStorage for long-term storage.

5. Timezone & Date Quirks

  • Constraint: The Kindle browser (Intl API) often defaults to UTC or ignores the system timezone configuration.
  • Impact: new Date().getHours() return UTC hours, not local wall time. toLocaleString() often fails to apply named timezones (e.g. "Australia/Sydney").
  • Date Formatting: The Kindle browser does not reliably support dateStyle / timeStyle options in toLocaleString() / Intl.DateTimeFormat. Output may differ from desktop browsers or be ignored entirely. Always use manual string formatting (e.g., building "Feb 10, 2026 at 2:42 PM" from individual date components) instead of relying on these options.
  • Solution:
    • Avoid relying on Intl.DateTimeFormat for timezone shifting.
    • Use a Manual Offset strategy: Store a numeric offset (e.g., +11) and mathematically shift the timestamp before displaying.
    • Use the time.js helper rekindleGetZonedDate() which handles this shim.

✅ Best Practices

  • Images: Use WebP or SVG. They are fully supported and perform best.
  • Modals: Always stick to the .modal-overlay / .modal-box DOM structure found in weather.html.