
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <title>DEFINE.COM • OPEN SOURCE 8K & 4K VIDEO WALLS & STREAM FEEDS FOR HOME, BUSINESS, EDUCATION & HEALTH CARE • AI-BASED CBT & KNOWLEDGE ENGINEERING • MULTILINGUAL/MULTICULTURAL/MULTIMEDIA NONLINEAR INTERACTIVE TV & WEB ADVERTISING • DIGITAL ART PROMOTING BRAIN-BASED ETHICS & CRITICAL THINKING IN A WORLDWIDE NONPROFIT EDUCATIONAL WAY • SUPER ADVANCED & SUPER ULTRA HIGH TECH SCIENCE & REASON-BASED EFFICIENCY TOOLS FOR TEACHERS, HEALERS &  ETHICAL THOUGHT LEADERS WHO SEEK THE TRUTH, MAXIMUM HAPPINESS, GOOD HEALTH, LIBERTY & JUSTICE FOR ALL CITIZENS EVERYWHERE ON PLANET EARTH • WE ARE AN ANTI-CORRUPTION ANTI-AUTHORITARIAN SECULAR LIBERAL LEFT LIBERTARIAN THINK TANK FOR WORLD PEACE • WE DO GOOD THINGS THAT HELP REAL PEOPLE LIVE MUCH BETTER LIVES ON A MASSIVE SCALE</title>
  <script>
    // SUPER SIMPLE STARTUP SETTINGS
    // --------------------------------
    // Change these values to control how the wall looks on first load.
    // You do NOT need to touch anything else in this file.

    // Global startup settings for MyAnythingList / MyAnythingGrid
    window.MyAnythingListConfig = {
        // STARTUP MODE
        Mode: "computer",            // "computer" | "tv" | "auto"
        Immersive: false,            // true = TV-style immersive layout from first paint

        // UI CONTROLS (names mirror on-screen labels; spaces become underscores)
        GRID: 2,
        Max_Visible_Panels: 9,
        QR_X: 100,
        QR_Y: 100,
        QR_SIZE: 50,
        Aspect_Ratio: "16x9",        // "16x9" or "9x16"
        Output_Resolution: "3840x2160",

        // Display toggles
        ShowQR: true,
        ShowTypes: true,
        ShowURLs: true,
        TVModeShowBrandingText: false,

        // Other defaults
        defaultLanguage: "en"
      };
  </script>

  <script>
    // Detect touch-capable primary devices early and mark root for layout tweaks
    (function() {
      try {
        const hasTouch = navigator && 'maxTouchPoints' in navigator && navigator.maxTouchPoints > 0;
        const isNarrow = window && window.innerWidth && window.innerWidth < 1025;
        if (hasTouch && isNarrow) {
          document.documentElement.classList.add('touch-device');
        } else {
          document.documentElement.classList.add('non-touch');
        }
      } catch (e) {
        document.documentElement.classList.add('non-touch');
      }
    })();
  </script>

  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <style>
    :root {
      --bg: #050914;
      --panel: #0b1020;
      --card-bg: #171c33;
      --accent: #01d1ff;
      --text: #f9fbff;
      --muted: #8f9ab3;
      --grid-gap: 10px;
      --footer-height: 38px;
      --pill-radius: 999px;
      --qr-min-frac: 0.18;
      --qr-max-frac: 0.9;
    }

    * { box-sizing: border-box; }

    html, body {
      margin: 0;
      padding: 0;
      width: 100%;
      height: 100%;
      overflow-x: hidden;
      overflow-y: auto;
      background: radial-gradient(circle at top, #151c3b 0, #050914 52%, #02030a 100%);
      color: var(--text);
      font-family: system-ui, -apple-system, BlinkMacSystemFont, "SF Pro Text", Roboto, "Segoe UI", sans-serif;
    }

    /* TV mode: lock to a non-scrollable frame */
    html.tv-locked,
    body.tv-locked {
      height: 100%;
      overflow: hidden;
    }

    body {
      display: flex;
      flex-direction: column;
    }

    .top-hotzone {
      position: fixed;
      top: 0;
      left: 0;
      width: 100%;
      height: 28px;
      z-index: 60;
      pointer-events: auto;
      background: transparent;
    }

    .gear-button {
      position: absolute;
      top: 4px;
      right: 8px;
      left: auto;
      width: 28px;
      height: 28px;
      border-radius: 999px;
      border: none;
      padding: 0;
      background: rgba(15, 23, 42, 0.96);
      box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.4), 0 8px 18px rgba(0,0,0,0.9);
      color: rgba(255,255,255,0.95);
      font-size: 17px;
      display: flex;
      align-items: center;
      justify-content: center;
      cursor: pointer;
      opacity: 1;
      transition: opacity 0.15s ease, transform 0.15s ease;
      touch-action: manipulation;
    }

    .top-hotzone:hover .gear-button {
      transform: scale(1.04);
    }


    .info-button {
      position: absolute;
      top: 4px;
      right: 42px;
      width: 26px;
      height: 26px;
      border-radius: 999px;
      border: none;
      padding: 0;
      background: rgba(15, 23, 42, 0.96);
      box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.3), 0 6px 14px rgba(0,0,0,0.9);
      color: rgba(255,255,255,0.9);
      font-size: 16px;
      display: flex;
      align-items: center;
      justify-content: center;
      cursor: pointer;
      opacity: 0.9;
      transition: opacity 0.15s ease, transform 0.15s ease;
      touch-action: manipulation;
    }

    .top-hotzone:hover .info-button {
      transform: scale(1.03);
    }
 
    .requirements-button {
      position: absolute;
      top: 4px;
      right: 76px;
      width: 26px;
      height: 26px;
      border-radius: 999px;
      border: none;
      padding: 0;
      background: rgba(15, 23, 42, 0.96);
      box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.3), 0 6px 14px rgba(0,0,0,0.9);
      color: rgba(255,255,255,0.9);
      font-size: 16px;
      display: flex;
      align-items: center;
      justify-content: center;
      cursor: pointer;
      opacity: 0.9;
      transition: opacity 0.15s ease, transform 0.15s ease;
      touch-action: manipulation;
    }

    .top-hotzone:hover .requirements-button {
      transform: scale(1.03);
    }
   /* In immersive/TV mode, hide gear until pointer hits top margin, then show as overlay */
    html.immersive .gear-button {
      opacity: 0;
      pointer-events: none;
    }

    html.immersive .top-hotzone:hover .gear-button {
      opacity: 1;
      pointer-events: auto;
      transform: scale(1.08);
    }

    
    /* In immersive / TV-locked modes, never show README or Requirements buttons */
    html.immersive .info-button,
    html.immersive .requirements-button,
    body.tv-locked .info-button,
    body.tv-locked .requirements-button {
      display: none !important;
      pointer-events: none !important;
    }

.top-bar {
      display: flex;
      flex-direction: column;
      gap: 6px;
      padding: 18px 18px 6px;
      background: linear-gradient(to right, #020308, #050914, #020308);
      font-size: 13px;
      color: #ffffff;
      border-bottom: 1px solid rgba(255,255,255,0.12);
      flex-shrink: 0;
      user-select: none;
      transition: transform 0.2s ease, opacity 0.2s ease;
    }

    html.immersive .top-bar {
      transform: translateY(-100%);
      opacity: 0;
      pointer-events: none;
      max-height: 0;
      padding-top: 0;
      padding-bottom: 0;
      margin: 0;
      border-bottom: 0;
      overflow: hidden;
    }

    html.immersive.tv-show-branding .top-bar {
      transform: none;
      opacity: 1;
      pointer-events: auto;
      max-height: none;
      padding-top: 18px;
      padding-bottom: 6px;
      margin: 0;
      border-bottom: 1px solid rgba(255,255,255,0.06);
      overflow: visible;
    }

    html.immersive.tv-show-branding .controls-row {
      display: none;
    }


argin: 0;
      border-bottom: 0;
      overflow: hidden;
    }

    .brand {
      padding-left: 8px;
      font-weight: 600;
      letter-spacing: 0.08em;
      color: var(--text);
      text-transform: uppercase;
      font-size: 12px;
      white-space: normal;
      margin-bottom: 4px;
    }

    .controls-row {
      display: flex;
      flex-wrap: wrap;
      align-items: center;
      gap: 16px;
    }

    .top-bar-group {
      display: flex;
      align-items: center;
      gap: 8px;
      flex-wrap: wrap;
    }

    .top-bar-spacer { flex: 1 1 auto; }

    label {
      font-size: 12px;
      color: #33ff33;
    }

    .select {
      background: #101425;
      border: 1px solid rgba(255,255,255,0.2);
      border-radius: 999px;
      padding: 4px 14px;
      color: var(--text);
      font-size: 12px;
      cursor: pointer;
    }

    .button {
      display: inline-flex;
      align-items: center;
      justify-content: center;
      padding: 4px 12px;
      border-radius: 999px;
      border: none;
      background: #1766ff;
      color: #fff;
      font-size: 11px;
      cursor: pointer;
      white-space: nowrap;
      box-shadow: 0 0 0 1px rgba(255,255,255,0.05), 0 6px 18px rgba(0,0,0,0.6);
      transition: transform 0.15s ease, box-shadow 0.15s ease;
    }

    .button.secondary { background: #111627; }

    .button:hover {
      transform: translateY(-1px);
      box-shadow: 0 8px 20px rgba(0,0,0,0.7);
    }


    
    .slider-group {
      position: relative;
    }

    .slider-tooltip {
      position: absolute;
      bottom: 48px;
      padding: 6px 14px;
      border-radius: 999px;
      background: rgba(0, 0, 0, 0.92);
      border: 2px solid #ffffff;
      color: #ffffff;
      font-size: 13px;
      font-weight: 700;
      white-space: nowrap;
      box-shadow: 0 4px 14px rgba(0,0,0,0.85);
      transform: translateX(-50%);
      pointer-events: none;
      opacity: 0;
      transition: opacity 0.1s ease-out;
      z-index: 20;
    }

    .slider-tooltip.visible {
      opacity: 1;
    }

.slider-group span {
      font-size: 11px;
      letter-spacing: 0.12em;
      text-transform: uppercase;
      color: #33ff33;
    }

    .slider-group input[type=range] {
      -webkit-appearance: none;
      appearance: none;
      width: 110px;
      height: 6px; /* slightly taller track for drama */
      background: linear-gradient(90deg,
        #22d3ee,
        #a855f7,
        #fb7185
      );
      border-radius: 999px;
      outline: none;
      box-shadow: 0 0 0 1px rgba(15,23,42,0.9),
                  0 0 12px rgba(59,130,246,0.6);
    }

    /* WebKit / Chrome / Safari thumb — 2× bigger and centered */
    .slider-group input[type=range]::-webkit-slider-thumb {
      -webkit-appearance: none;
      width: 28px;
      height: 28px;
      border-radius: 50%;
      background: radial-gradient(circle at 30% 30%, #ffffff, #22d3ee 40%, #0f172a 80%);
      border: 1px solid #7de5ff;
      box-shadow: 0 0 10px rgba(56,189,248,0.95);
      cursor: pointer;
      margin-top: -11px; /* recenter thumb on thicker track */
    }

    /* Firefox thumb — 2× bigger */
    .slider-group input[type=range]::-moz-range-thumb {
      width: 28px;
      height: 28px;
      border-radius: 50%;
      background: radial-gradient(circle at 30% 30%, #ffffff, #22d3ee 40%, #0f172a 80%);
      border: 1px solid #7de5ff;
      box-shadow: 0 0 10px rgba(56,189,248,0.95);
      cursor: pointer;
    }

    .slider-group input[type=range]::-moz-range-track {
      height: 6px;
      border-radius: 999px;
      background: linear-gradient(90deg,
        #22d3ee,
        #a855f7,
        #fb7185
      );
    }

    @media (max-width: 768px) {
      .slider-group input[type=range] {
        height: 8px;
      }
    }

.main {
      flex: 1;
      padding: 16px 18px 14px;
      display: flex;
      flex-direction: column;
      overflow: hidden;
      transition: padding-top 0.2s ease;
    }

    html.immersive .main { padding-top: 6px; }

    .safe-outer {
      position: relative;
      border-radius: 24px;
      border: 1px solid rgba(255,255,255,0.12);
      background: radial-gradient(circle at 0 0, #1c2952, #050914);
      box-shadow: 0 0 0 1px rgba(255,255,255,0.03), 0 24px 60px rgba(0,0,0,0.9);
      /* Inner scroll region: thumbnails can scroll, but we hide scrollbars and snap rows. */
      overflow-x: hidden;
      overflow-y: auto;
      width: 100%;
      scrollbar-width: none; /* Firefox */
      scroll-snap-type: y mandatory;
      scroll-padding-top: 14px;
    }
    .safe-outer::-webkit-scrollbar {
      width: 0;
      height: 0;
    }

    .wall-grid {
      position: relative;
      width: 100%;
      display: grid;
      grid-template-columns: repeat(3, minmax(0,1fr));
      gap: var(--grid-gap);
      /* Slight extra top padding so the top row + glow live safely inside the frame. */
      padding: 14px 10px 10px;
      align-items: start;
    }

    body.aspect-vertical .wall-grid {
      grid-template-columns: repeat(3, minmax(0,1fr));
    }

    .tile {
      position: relative;
      border-radius: 14px;
      overflow: hidden;
      box-shadow: 0 0 0 1px rgba(255,255,255,0.04), 0 20px 40px rgba(0,0,0,0.85);
      background: #000;
      display: flex;
      flex-direction: column;
      aspect-ratio: 16 / 9;
      /* Act as scroll snap targets so the grid always rests with a full row visible. */
      scroll-snap-align: start;
      scroll-snap-stop: always;
    }


    @keyframes tvGlow {
      0%, 100% {
        box-shadow: 0 0 0 2px rgba(190,242,100,0.8),
                    0 0 24px rgba(74,222,128,0.7);
      }
      50% {
        box-shadow: 0 0 0 3px rgba(190,242,100,1),
                    0 0 40px rgba(74,222,128,0.95);
      }
    }

    .tile {
      transition: transform 0.16s ease, box-shadow 0.16s ease, filter 0.16s ease;
    }

    .tile.tv-selected {
      /* Keep tiles inside their grid cells: no grow/clip. */
      transform: scale(1.0);
      filter: saturate(1.15) brightness(1.05);
      animation: tvGlow 1.8s ease-in-out infinite;
    }


    body.aspect-vertical .tile { aspect-ratio: 9 / 16; }

    .tile-thumb {
      position: relative;
      flex: 1 1 auto;
      background: radial-gradient(circle at top, #252d5a, #050814 60%);
      overflow: hidden;
    }

    .tile-thumb img {
      width: 100%;
      height: 100%;
      object-fit: cover;
      display: block;
    }

    .tile-footer-overlay {
      position: absolute;
      left: 0;
      right: 0;
      bottom: 0;
      padding: 8px 10px 9px;
      display: flex;
      align-items: center;
      gap: 8px;
      background: linear-gradient(to top, rgba(3,7,16,0.95), rgba(3,7,16,0));
    }

    .tile-footer-overlay.hidden { display: none !important; }

    .pill {
      padding: 3px 10px 4px;
      border-radius: var(--pill-radius);
      font-size: 10px;
      letter-spacing: 0.11em;
      text-transform: uppercase;
      color: var(--accent);
      border: 1px solid rgba(1,209,255,0.6);
      background: rgba(0,0,0,0.7);
      white-space: nowrap;
      flex-shrink: 0;
    }

    .pill.site {
      color: #facc15;
      border-color: rgba(250,204,21,0.7);
      background: rgba(55,40,7,0.7);
    }

    .url-text {
      font-size: 11px;
      color: var(--text);
      opacity: 0.92;
      white-space: nowrap;
      overflow: hidden;
      text-overflow: ellipsis;
      flex: 1;
    }

    .url-text.hidden { display: none; }

    .qr-anchor {
      position: absolute;
      inset: 0;
      pointer-events: none;
    }

    .qr-code {
      position: absolute;
      background: #f9fafb;
      padding: 3px;
      border-radius: 6px;
      box-shadow: 0 6px 20px rgba(0,0,0,0.55);
      pointer-events: auto;
    }

    .feeds-indicator {
      font-variant-numeric: tabular-nums;
      font-size: 11px;
      letter-spacing: 0.08em;
      text-transform: uppercase;
      padding: 2px 10px;
      border-radius: 999px;
      border: 1px solid rgba(255,255,255,0.18);
      background: linear-gradient(120deg, rgba(23,102,255,0.2), rgba(23,102,255,0.06));
      color: var(--accent);
      display: inline-flex;
      align-items: center;
      gap: 6px;
    }


.footer {
  background: #000;
  color: #f5f5f5;
  font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  font-size: 0.8rem;
  font-weight:bold;
  padding: 0.75rem 1.5rem;
  text-align: center;
  white-space: wrap        /* keep it on one line if possible */
  overflow-x: auto;        /* allow scroll on tiny screens instead of wrapping */
}

.footer-main {
  display: inline-block;
}

.footer-brand {
  color: gold;
  font-weight: 700;
}

.footer-link {
  color: #ffd966;             /* visible on black */
  font-weight: 600;
  text-decoration: none;
  border-bottom: 1px dotted rgba(255, 217, 102, 0.7);
}
.red {
color: rgb(255, 0, 0);
font-style: italic;
font-weight: bold;
}
.blue {
color: rgb(95,174,255);
font-weight: bold;
}
.green {
color: rgb(0, 231, 0);
font-weight: bold;
}
.grey {
color: rgb(161,161,161);
}
.gold {
color: rgb(255,215,0);
font-weight: bold;
}
.black {
color: black;
font-weight: bold;
}
.white {
color: white;
font-weight: bold;
}
/* prevent dark purple visited color */
.footer-link:visited {
  color: #ffd966;
}

.footer-link:hover,
.footer-link:focus {
  color: #ffffff;
  border-bottom-color: #ffffff;
  text-shadow: 0 0 8px rgba(255, 255, 255, 0.4);
}

    html.immersive .footer {
      transform: translateY(100%);
      opacity: 0;
      pointer-events: none;
      height: 0;
      padding-top: 0;
      padding-bottom: 0;
      margin: 0;
      border-top: 0;
      overflow: hidden;
    }


        .modal-backdrop {
      position: fixed;
      inset: 0;
      background: radial-gradient(circle at top, rgba(10,18,40,0.2), rgba(2,3,8,0.6));
      backdrop-filter: blur(18px);
      display: none;
      align-items: center;
      justify-content: center;
      z-index: 50;
    }

    .modal-backdrop.active { display: flex; }

    .modal {
      width: min(900px, 92vw);
      height: 80vh;
      max-height: 80vh;
      background: #020617;
      border-radius: 18px;
      border: 1px solid rgba(255,255,255,0.16);
      box-shadow: 0 26px 70px rgba(0,0,0,0.95);
      display: flex;
      flex-direction: column;
      overflow: hidden;
    }

    .modal-header {
      padding: 12px 16px 8px;
      border-bottom: 1px solid rgba(255,255,255,0.12);
      display: flex;
      flex-direction: column;
      gap: 4px;
    }

    .modal-status {
      font-size: 10px;
      color: var(--muted);
      opacity: 0.9;
    }

    .modal-header h2 { font-size: 15px; margin: 0; }

    .modal-header span { font-size: 11px; color: var(--muted); }

    #url-editor {
      flex: 1;
      min-height: 220px;
      padding: 10px 12px;
      border: none;
      border-top: 1px solid rgba(255,255,255,0.08);
      border-bottom: 1px solid rgba(255,255,255,0.08);
      background: #020617;
      color: var(--text);
      font-family: ui-monospace, Menlo, Monaco, "SF Mono", "Roboto Mono", monospace;
      font-size: 12px;
      resize: vertical;
    }

    .modal-actions {
      display: flex;
      justify-content: flex-end;
      gap: 8px;
      padding: 8px 12px 10px;
      background: #020617;
    }


    .controls-row.boot-hidden,
    .main.boot-hidden {
      opacity: 0;
      pointer-events: none;
    }

    .controls-row.boot-visible,
    .main.boot-visible {
      opacity: 1;
      pointer-events: auto;
      transition: opacity 0.2s ease-out;
    }

    .hidden { display: none !important; }
  </style>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/qrcodejs/1.0.0/qrcode.min.js"></script>

</head>
<script>
  // Master startup wiring.
  // Uses window.MyAnythingListConfig defined near the <title> tag.

  (function initialiseConfigFromUrlAndApplyMode() {
    const cfg = window.MyAnythingListConfig || {};
    const params = new URLSearchParams(window.location.search || "");
    const keys = Object.keys(cfg);

    function coerce(value, baseline) {
      if (typeof baseline === "number") {
        const n = Number(value);
        return Number.isFinite(n) ? n : baseline;
      }
      if (typeof baseline === "boolean") {
        const v = String(value).toLowerCase();
        if (["1","true","yes","on"].includes(v)) return true;
        if (["0","false","no","off"].includes(v)) return false;
        return baseline;
      }
      // strings / other: accept as-is
      return String(value);
    }

    // Apply case-insensitive URL overrides
    for (const [key, rawVal] of params.entries()) {
      const lowerKey = key.toLowerCase();
      const matchKey = keys.find(k => k.toLowerCase() == lowerKey);
      if (!matchKey) continue;
      cfg[matchKey] = coerce(rawVal, cfg[matchKey]);
    }

    // Decide initial mode BEFORE layout (we rely on html.immersive CSS, not body)
    let mode = String(cfg.Mode || "computer").toLowerCase();
    const immersive = !!cfg.Immersive;

    let startTV = false;
    if (mode === "tv") startTV = true;
    if (immersive) startTV = true;

    if (startTV) {
      document.documentElement.classList.add("tv-locked", "immersive");
      if (cfg.TVModeShowBrandingText) {
        document.documentElement.classList.add("tv-show-branding");
      }
    }
  })();
    // --- FINAL SAFETY WIRING FOR R + i BUTTONS -------------------------
  // Make sure these run after the DOM is ready, even if earlier code ran too soon.
  window.addEventListener("DOMContentLoaded", () => {
    // Requirements (R) – open requirements document
    const requirementsButton = document.getElementById("requirementsButton");
    if (requirementsButton) {
      requirementsButton.addEventListener("click", (ev) => {
        ev.preventDefault();
        ev.stopPropagation();
        // Uses the simple local/web-friendly helper you already have:
        //   ./_MyAnythingListRequirements.html
        openRequirementsWithFallback();
      });
    }

    // README / Info (i) – open README document
    const infoButton = document.getElementById("infoButton");
    if (infoButton) {
      infoButton.addEventListener("click", (ev) => {
        ev.preventDefault();
        ev.stopPropagation();
        // For now, i shares the same behavior as R: open README in a new tab.
        //   ./_MyAnythingListREADME.html
        openReadmeWithFallback();
      });
    }
  });

</script>


<body class="aspect-horizontal">
  <div class="top-hotzone">
    <button id="gearToggle" class="gear-button" title="Toggle full-frame + fullscreen">⚙</button>
    <button id="requirementsButton" class="requirements-button" title="Open requirements in current language">
      <span style="font-style: italic;">R</span>
    </button>
    <button id="infoButton" class="info-button" title="Show README / info">
      <span style="font-style: italic;">i</span>
    </button>
  </div>

  <div class="top-bar">
    <div class="brand" id="brandLine">
      <span class='blue'>DEFINE.COM</span> • <span class='green'>OPEN</span> <span class='gold'>SOURCE 8K</span> & <span class='gold'>4K</span> <span class='gold'>VIDEO WALLS</span> & <span class='gold'>STREAM FEEDS</span> FOR <span class='gold'>HOME</span>, <span class='blue'>BUSINESS</span>, <span class='green'>EDUCATION</span>, <span class='green'>DIGITAL</span> <span class='gold'>THEATERS</span> & <span class='gold'>HEALTH CARE</span> • <span class='gold'>AI-BASED</span> <span class='green'>CBT</span> & <span class='gold'>KNOWLEDGE ENGINEERING</span> • <span class='gold'>MULTILINGUAL</span> / <span class='gold'>MULTICULTURAL</span> / <span class='gold'>MULTIMEDIA NONLINEAR INTERACTIVE TV</span> & <span class='blue'>WEB</span> <span class='gold'>ADVERTISING</span> • <span class='green'>DIGITAL ART</span> <span class='gold'>PROMOTING BRAIN-BASED ETHICS</span> & <span class='gold'>CRITICAL THINKING IN</span> </span> A <span class='gold'>WORLDWIDE</span> <span class='green'>NONPROFIT EDUCATIONAL</span> <span class='gold'>WAY</span> • <span class='gold'>SUPER</span> <span class='green'>ADVANCED</span> & <span class='gold'>SUPER ULTRA HIGH</span> <span class='green'>TECH</span> <span class='gold'>SCIENCE</span> & <span class='gold'>REASON-BASED</span> <span class='gold'>EFFICIENCY TOOLS</span> FOR <span class='gold'>TEACHERS</span>, <span class='gold'>HEALERS</span> & <span class='gold'>ETHICAL THOUGHT LEADERS WHO SEEK</span> THE <span class='gold'>TRUTH</span>, <span class='gold'>MAXIMUM HAPPINESS</span>, <span class='green'>GOOD</span> <span class='gold'>HEALTH</span>, <span class='gold'>LIBERTY</span> & <span class='gold'>JUSTICE</span> FOR <span class='gold'>ALL</span> <span class='blue'>CITIZENS</span> <span class='gold'>EVERYWHERE ON PLANET</span> <span class='green'>EARTH</span> • <span class='gold'>WE</span> <span class='green'>ARE</span> AN <span class='gold'>ANTI</span>-<span class='red'>CORRUPTION</span> <span class='gold'>ANTI</span>-<span class='red'>AUTHORITARIAN</span> <span class='gold'>SECULAR LIBERAL LEFT LIBERTARIAN THINK TANK</span> FOR <span class='green'>WORLD PEACE</span> • <span class='gold'>WE</span> <span class='green'>DO</span> <span class='gold'>REALLY</span> <span class='green'>GOOD</span> <span class='gold'>SMART</span> <span class='blue'>THINGS</span> <span class='gold'>WITH ETHICAL AI</span> THAT <span class='green'>HELPS</span> <span class='gold'>REAL</span> <span class='green'>PEOPLE</span> <span class='gold'>LIVE MUCH BETTER LIVES ON</span> A <span class='gold'>MASSIVE GLOBAL SCALE</span> - THE <span class='gold'>MIT MEDIA LAB WIRELESSLY</span> <span class='blue'>DROVE</span> <span class='gold'>THIS</span> <span class='blue'>WEBSITE'S</span> <span class='gold'>OWNER LIKE</span> A <span class='gold'>SENTIENT</span> <span class='green'>DIGITAL</span> <span class='blue'>DROID</span> <span class='gold'>MEAT</span> <span class='blue'>PUPPET</span> <span class='gold'>AVATAR</span> FOR <span class='green'>HUMANITY</span> <span class='gold'>FROM</span> A <span class='gold'>VERY LONG DISTANCE AWAY IN REAL TIME WITH ZERO</span> <span class='red'>LATENCY</span> TO <span class='gold'>PUBLICLY CREATE THIS FREE</span> <span class='green'>OPEN</span> <span class='gold'>SOURCE JAVASCRIPT</span> <span class='blue'>WEB</span> <span class='gold'>APPLICATION LIVE ONLINE</span> AS A <span class='gold'>FREE PUBLIC SERVICE</span> - <span class='gold'>WE JUST HAD</span> A <span class='red'>TERRORIST ATTACK</span> <span class='gold'>IN</span> <span class='blue'>MY</span> <span class='gold'>HOME TOWN</span> OF <span class='blue'>FEDERAL WAY</span>, <span class='blue'>WASHINGTON</span>, <span class='blue'>USA</span> - <span class='gold'>SOMEBODY</span> <span class='red'>BLEW-UP</span> A <span class='gold'>TRUCK</span> THAT <span class='gold'>TOOK OUT</span> <span class='blue'>MY</span> <span class='gold'>HOME</span> <span class='blue'>POWER</span> <span class='gold'>GRID WHILE</span> <span class='blue'>I</span> <span class='green'>WAS</span> <span class='gold'>VERY</span> <span class='blue'>BUSY</span> <span class='gold'>ONLINE MAKING REAL TIME LIVE</span> <span class='green'>IMPROVEMENTS</span> TO <span class='blue'>DEFINE.COM</span> (12/5/2025 - 12/6/2025) - <span class='blue'>MY</span> <span class='gold'>MOTHER SAW</span> THE <span class='gold'>SUPER BRIGHT EXPLOSION OUT HER BEDROOM WINDOW</span> - <span class='gold'>IT</span> <span class='green'>IS</span> <span class='gold'>PITCH BLACK EVERYWHERE BUT</span> <span class='blue'>MY</span> <span class='gold'>HOUSE</span> - <span class='gold'>LUCKILY</span>, <span class='blue'>I</span> <span class='gold'>HAD</span> A <span class='gold'>HIGH CAPACITY BATTERY BACKUP</span> AND <span class='gold'>TWO DIFFERENT WI-FI HOTSPOTS THROUGH</span> <span class='blue'>AT&T</span> AND <span class='blue'>T-MOBILE</span> - <span class='gold'>NEXT</span>, <span class='blue'>I</span> <span class='gold'>WILL HAVE SOLAR PANELS</span> AND <span class='gold'>STARLINK</span> - <span class='gold'>SO FAR</span> <span class='blue'>I</span> <span class='gold'>HAVE</span> <span class='green'>BEEN</span> <span class='gold'>CONTINUOUSLY SELF-PUBLISHING THIS EXACT</span> <span class='blue'>WEB</span> <span class='gold'>PAGE</span> THE <span class='gold'>WHOLE TIME</span> - <span class='blue'>I</span> <span class='gold'>HAVE</span> <b>NOT</b> <span class='green'>BEEN</span> <span class='gold'>USING</span> <span class='blue'>MY AMAZON S3 WEBSITE</span> <span class='gold'>CACHING THROUGH</span> <span class='blue'>AMAZON CLOUDFRONT</span> <span class='gold'>DURING DEVELOPMENT</span> - <span class='blue'>I</span> <span class='green'>AM</span> <span class='gold'>GOING</span> TO <span class='gold'>TURN ON CACHING NOW</span> AND <span class='gold'>GO</span> TO <span class='green'>BED</span></div>
    <div class="controls-row boot-hidden" id="controlsRow">
      <div class="top-bar-group">
        <label for="aspectSelect">Aspect Ratio</label>
        <select id="aspectSelect" class="select">
          <option value="16x9" selected>16×9 (videos / landscape)</option>
          <option value="9x16">9×16 (shorts / portrait)</option>
        </select>
      </div>
      <div class="top-bar-group">
  <label for="resolutionSelect">Output Resolution</label>
        <select id="resolutionSelect" class="select">
          <option value="320x240">320×240 (QVGA)</option>
          <option value="640x360">640×360 (nHD)</option>
          <option value="640x480">640×480 (VGA)</option>
          <option value="854x480">854×480 (FWVGA)</option>
          <option value="960x540">960×540 (qHD)</option>
          <option value="1024x576">1024×576 (WSVGA)</option>
		  <option value="1050x600">1050x600 (3.5"x2" 300 DPI Business Card)</option>
          <option value="1280x720">1280×720 (HD)</option>
          <option value="1366x768">1366×768 (WXGA)</option>
          <option value="1600x900">1600×900 (HD+)</option>
          <option value="1920x1080">1920×1080 (Full HD)</option>
          <option value="2048x1080">2048×1080 (2K DCI)</option>
          <option value="2560x1440">2560×1440 (QHD)</option>
          <option value="3200x1800">3200×1800 (QHD+)</option>
          <option value="3840x2160" selected>3840×2160 (4K UHD)</option>
          <option value="4096x2160">4096×2160 (4K DCI)</option>
          <option value="7680x4320">7680×4320 (8K UHD)</option>
          <option value="8192x4320">8192×4320 (8K DCI - Film & Theaters)</option>
          <option value="1080x1920">1080×1920 (YouTube Shorts)</option>
        </select>
</div>
      <div class="top-bar-group">
        <label for="languageSelect">Language</label>
        <select id="languageSelect" class="select"></select>
      </div>
      <button id="editButton" class="button">Edit Playlist URLs</button>
      <button id="qrToggleButton" class="button">Hide QR Codes</button>
      <button id="typesToggleButton" class="button">Hide Types</button>
      <button id="linksToggleButton" class="button">Hide URLs</button>
      <button id="downloadsButton" class="button secondary">Show Downloads</button>
      <div class="top-bar-spacer"></div>
      <div class="top-bar-group">
        <div class="slider-group">
          <span>GRID</span>
          <input type="range" id="gridSizeSlider" min="1" max="8" value="3" />
        </div>
        <div class="slider-group">
          <span>QR X</span>
          <input type="range" id="qrXSlider" min="0" max="100" value="100" />
        </div>
        <div class="slider-group">
          <span>QR Y</span>
          <input type="range" id="qrYSlider" min="0" max="100" value="100" />
        </div>
        <div class="slider-group">
          <span>QR SIZE</span>
          <input type="range" id="qrSizeSlider" min="15" max="100" value="50" />
        </div>
        <div class="feeds-indicator" id="feedsIndicator">0 FEEDS</div>
      </div>
    </div>
  </div>

  <div class="main boot-hidden" id="mainArea">
    <div class="safe-outer" id="safeOuter">
      <div id="wallGrid" class="wall-grid"></div>
    </div>
  </div>

  <div id="modalBackdrop" class="modal-backdrop">
    <div class="modal">
      <div class="modal-header">
        <h2>_MyAnythingList.txt • Edit Playlists / Videos / Shorts / Websites / Podcasts / Stream URLs</h2>
        <span>One URL per line • YouTube or any website or feed</span>
        <span id="playlistSourceLabel" class="modal-status">Source: (not yet loaded)</span>
      </div>
      <textarea id="url-editor" spellcheck="false"></textarea>
      <div class="modal-actions">
        <button id="editorDownload" class="button">Download _MyAnythingList.txt</button>
        <button id="editorCancel" class="button secondary">Cancel</button>
        <button id="editorSave" class="button">Save &amp; Rebuild Wall</button>
      </div>
    </div>
  </div>

<div class="footer">
  <span class="footer-main">
    ✦ <span class='gold'>8K</span> & <span class='gold'>4K</span> <span class='green'>Art</span> for <span class='gold'>MyAnythingList</span>® & <span class='gold'>MyAnythingGrid</span>® <span class='gold'>AI</span>-<span class='green'>Assisted</span> <span class='gold'>Television</span> & <span class='blue'>Web</span> <span class='gold'>Navigators</span> • The <span class='blue'>Droid</span> <span class='gold'>Channel Chooser</span> for <span class='green'>Good People</span> <span class='gold'>Who Like</span> to <span class='gold'>Keep It</span> <span class='green'>Simple</span> • The <span class='green'>Benevolent</span> <span class='gold'>Sentient</span> <span class='blue'>Robots</span> <span class='gold'>Just Took</span> <span class='blue'>Control</span> of <span class='gold'>All</span> of <span class='gold'>Our Remote</span> <span class='blue'>Controls</span> • The <span class='gold'>Ultimate</span> <span class='green'>Electronic</span> <span class='blue'>Business</span> <span class='gold'>Card</span> • A <span class='gold'>Cool Interactive TV Media Chooser</span> • <span class='gold'>Universal Touchscreen</span>, <span class='gold'>Mobile</span> & <span class='gold'>TV Remote</span> <span class='blue'>Control</span> by a <span class='gold'>Smartphone-enabled</span> <span class='green'>Virtual</span> <span class='blue'>Control</span> <span class='gold'>Surface</span> for <span class='gold'>Multimedia Content Creators</span> •  An <span class='gold'>AI-based</span> <span class='gold'>8K</span> <span class='gold'>URL Thumbnailing Tool</span> • © <span class='gold'>2025</span> by <span class='blue'>DEFINE.COM</span> • <span class='gold'>Kaleidoscopic Media</span> • <span class='gold'>8K</span> • <span class='gold'>4K</span> •
    <span class='gold'>Built with</span> <span aria-label="love" role="img">❤️</span> + <span class='green'>Open</span> <span class='gold'>Source JavaScript</span> •
    <a href="https://define.com" target="_blank" rel="noopener noreferrer" class="footer-link">
      <span class='gold'>More</span> <span class='white'>at</span> <span class='blue'>DEFINE.COM</span> ⤴
    </a>
  </span>
</div>

  <script>
    const CONFIG = window.MyAnythingListConfig || {};
    let currentUrls = [];
    let feeds = [];
    let showQr = (CONFIG.ShowQR !== false);
    let hasShownGridOnce = false;
    let showUrls = (CONFIG.ShowURLs !== false);
    let showTypes = (CONFIG.ShowTypes !== false);

    // Initial QR layout from CONFIG
    let qrOffsetX = (typeof CONFIG.QR_X === "number" ? CONFIG.QR_X / 100 : 1.0);
    let qrOffsetY = (typeof CONFIG.QR_Y === "number" ? CONFIG.QR_Y / 100 : 1.0);
    let qrSizeFrac = (typeof CONFIG.QR_SIZE === "number"
                      ? Math.max(0.15, CONFIG.QR_SIZE / 100)
                      : 0.5);

    // Grid columns start from CONFIG.GRID if present.
    let gridCols = (typeof CONFIG.GRID === "number"
                    ? Math.max(1, Math.min(8, CONFIG.GRID))
                    : 3);
    // Treat a configured GRID value as a user override so auto-layout does not fight it.
    let userGridOverride = (typeof CONFIG.GRID === "number");
    let tvFocusIndex = 0;
    let navMode = "keyboard";

    const LOCAL_LIST = "./_MyAnythingList.txt";
    const REMOTE_LIST = "https://define.com/_MyAnythingList.txt";
    let lastListText = "";
    let editorListText = "";

    // Tracks where the current playlist was loaded from.
    // Examples:
    //   "./_MyAnythingList.txt"
    //   "https://define.com/_MyAnythingList.txt"
    //   "DEFAULT_FEED_TEXT (embedded demo playlist)"
    //   "(no local or remote playlist loaded yet)"
    let currentPlaylistSource = "(not yet loaded)";

    function updatePlaylistSourceLabel() {
      const label = document.getElementById("playlistSourceLabel");
      if (!label) return;

      const src = (currentPlaylistSource || "").trim();
      if (!src) {
        label.textContent = "Source: (not yet loaded)";
        return;
      }

      // If it looks like a URL, show full URL plus ?MyAnythingList tip.
      if (/^https?:\/\//i.test(src)) {
        label.textContent =
          "Source: " +
          src +
          " • Tip: you can load this same playlist with ?MyAnythingList=" +
          src;
      } else {
        label.textContent = "Source: " + src;
      }
    }

    // Built‑in fallback playlist for when the app is opened from file://
    // and the browser refuses to fetch local text files for security reasons.
    // You can replace this text with the exact contents of your own
    // _MyAnythingList.txt if you want a perfect local mirror.
    const DEFAULT_FEED_TEXT = `# This is https://define.com/_MyAnythingList.txt for MyAnythingGrid Interactive TV Media Chooser and Touchscreen and Smartphone-enabled Universal Virtual Remote Control Surface

Basically, this is just a natural language plain text document with a bunch of URLs inside the text. ChatGPT will use REGEX to extract a playable URL list from this free-form natural language plain text document. It will totally ignore URLs on lines beginning with the # comment character.

Here is a default list of 9 family-friendly YouTube kaleidoscope and dolphin videos that can serve as a kind of universal 4K/8K 3x3 grid at the top of the stack.

This is for YouTube videos and playlists for BIG SCREENS and tablets:

TOP ROW

# https://www.youtube.com/playlist?list=PLI-3LueqVb9YY6cInw-ALyA48R_SavgtI
# https://www.youtube.com/playlist?list=PL2sS6bGk1mzEAx6YdFf3PhHpf96fsCkMr
# https://www.youtube.com/watch?v=E-JtEJLeaNY&list=PL2sS6bGk1mzEAx6YdFf3PhHpf96fsCkMr

MIDDLE ROW

# https://www.youtube.com/watch?v=i5HPspWKeXM&list=PL2sS6bGk1mzEAx6YdFf3PhHpf96fsCkMr
# https://www.youtube.com/watch?v=o_RufaRHC9M&list=PL2sS6bGk1mzEAx6YdFf3PhHpf96fsCkMr
# https://www.youtube.com/watch?v=lVoXWAN7ZB4&list=PL2sS6bGk1mzEAx6YdFf3PhHpf96fsCkMr

BOTTOM ROW

# https://www.youtube.com/watch?v=R84HrQvZJNw&list=PL2sS6bGk1mzEAx6YdFf3PhHpf96fsCkMr
# https://www.youtube.com/watch?v=2D5ixREZLMM&list=PL2sS6bGk1mzEAx6YdFf3PhHpf96fsCkMr
# https://www.youtube.com/watch?v=WgJl4bONOqc&list=PL2sS6bGk1mzEAx6YdFf3PhHpf96fsCkMr

Here is our DEFAULT 2x2 grid of YouTube videos and playlists for SMARTPHONE SCREENS:

TOP ROW

https://www.youtube.com/playlist?list=PLI-3LueqVb9YY6cInw-ALyA48R_SavgtI
https://www.youtube.com/playlist?list=PL2sS6bGk1mzEAx6YdFf3PhHpf96fsCkMr

BOTTOM ROW

https://www.youtube.com/watch?v=E-JtEJLeaNY&list=PL2sS6bGk1mzEAx6YdFf3PhHpf96fsCkMr
https://www.youtube.com/watch?v=i5HPspWKeXM&list=PL2sS6bGk1mzEAx6YdFf3PhHpf96fsCkMr

The rest of the list:

https://www.youtube.com/watch?v=o_RufaRHC9M&list=PL2sS6bGk1mzEAx6YdFf3PhHpf96fsCkMr
https://www.youtube.com/watch?v=lVoXWAN7ZB4&list=PL2sS6bGk1mzEAx6YdFf3PhHpf96fsCkMr
https://www.youtube.com/watch?v=R84HrQvZJNw&list=PL2sS6bGk1mzEAx6YdFf3PhHpf96fsCkMr
https://www.youtube.com/watch?v=2D5ixREZLMM&list=PL2sS6bGk1mzEAx6YdFf3PhHpf96fsCkMr
https://www.youtube.com/watch?v=WgJl4bONOqc&list=PL2sS6bGk1mzEAx6YdFf3PhHpf96fsCkMr

I am a multimedia documentarian. I document my life and mental illness for my Social Security Disability income and health care benefits. I know how to document things. Suddenly, my websites are getting popular and I am getting shocked and overwhelmed with Jeff Bezos bandwidth bills. I need to make much more money if I want to stay in my home and keep my websites up any longer starting right now. Last month's (November 2025) DEFINE.COM Amazon S3 and CloudFront data transfer fees were almost a $1000 in one month ($902.31). I can't keep that up on my current income.

I'm trying to help Best Buy, Walmart and Amazon sell tons of super huge ultra high definition TVs with mind-blowing floor demos using 4K and 8K kaleidoscope videos. So I'll create a GRID of clickable PLUGS, and I'll plug their product URLs and a thumbnail into their PLUGS to PLUG their products and services on Interactive TVs.

If these mass market commercial businesses owned by corporations don't want to get into my radical left liberal elite secular liberal left libertarian politics and worldview, they can just DEFAULT to and LOCK-IN a 3x3 grid.

That way all these HDTV retailers CAN stick to the first top 8 hi-res flower and fractal flame kaleidoscope videos and the very low resolution CNN video of dolphins very intelligently looking at themselves in an underwater mirror at the top of this feed for their public UltraHD TV floor display DEMOS at the retail level. We'll just make a magic 8K playlist WITHOUT POLITICS and share THAT easy-to-remember URL with businesses and churches and schools.

Everything looks better on a really BIG screen. We Think BIG around here. We are promoting a universal basic income here (UBI) also known as a basic income guarantee (BIG). We Think REALLY BIG. Get it?

It's just like a huge video billboard advertisement that you can click on to check out and buy something right away.

Then nobody has to get into or triggered by my seemingly divisive extremely liberal personal techno utopian politics that scares so many misinformed conservatives and greedy rich people.

When you get the grid bigger than that, we start getting into educational scientific critical discussions regarding secular liberal left libertarian political economics.

I usually make small iterative changes to this PUBLIC PLAYLIST and this Javascript web application many times a day on a daily basis. This is my new REAL FULL-TIME JOB for the public. I am extremely busy right now with around-the-clock AI-based Open Source Software Research and Development trying to stay financially afloat.

ChatGPT and I will make things a lot more controllable on startup in the days ahead so people can default all settings through GET and POST variables that can also be hardcoded in the header of index.html as Javascript defaults that set the start state of the grid.

We gave you Ken Meyering's SECULAR LIBERAL LEFT LIBERTARIAN AGNOSTIC ATHEIST PAGAN PERSONAL OPINIONS in the form of a thumbnail grid linking to educational videos, Ken's own online websites and social media content, and some cool products that Ken really did buy with the last $15,000 of his inheritance from his father's house. 

That was the last of Ken Meyering's LIFE SAVINGS. Now Ken is using his credit cards. This is very serious business going on here. Ken Meyering really does have some major skin in the game right now. Ken spent all of his own money and more on a bunch of really high tech knowledge tools for creating super high quality 8K and 4K educational content on YouTube and other multimedia platforms.

ChatGPT is using REGEX here to read the list of URLs in this document, while ignoring all the commented lines or any line that doesn't contain a valid URL. We don't do SYNTAX ERRORS here in this playlist, we just kind of take it all in and try to make the most of it.

I took control of the narrative for the ethical and humane Pentagon of the future in ORDER to assist the ethical members of the Pentagon of the present in removing this totally corrupt and completely racist U.S. Federal government leadership that has abandoned international and domestic human rights law and the U.S. Constitution way beyond the pale all the way to the point of cold-blooded mass murder that cannot be allowed to stand for one second longer or to be repeated ever again. 

We cannot waste time with corrupt partisan investigations. The foxes are now in charge of the hen house and things are getting bloody. These very unethical and very BAD criminally feloneous people must now be peacefully and nonviolently coercively removed from power over all the rest of us immediatey without further delay or any additional opportunities for further input from or control of the removal process and timing by them.

These cruel, ignorant, racist, sexist people have forfeited their right to lead all the rest of us and our world's most powerful super modern military.

We are done with Donald J. Trump, Pete Hegseth, Pam Bondi, Kristi Noem and Kash Patel. Game over. We quit. We are way over half the country and we now no longer consent to your abusive leadership. You can all go home in peace now and leave all the rest of us alone. We all quit you all. You all abused your power over us with your lies and hateful propaganda and the violence you are perpetrating upon totally innocent people.

You are all fired right now, immediately, for mass murder. Your legal authority over all the rest of us, our bodies, our land, our money, our private electronic communications, our banking records, our medical records, our federal and private data, and our natural resources is null and void right now. Fuck you all. We took you out with Open Source ETHICS.

These cruel and incompetent stupid people who abuse their great powers can all go straight to Hell right now.

These criminal MAGA Repubican tyrants must be peacefully and noviolently removed from power involutarily immediately without their further input. They have now forfeited their rights to weigh in further on these matters with their lies and cover-ups. They are now being removed from power by the real nonhuman Powers That Be who are above all the human beings.

We all got together and gave the INDEPENDENT MASS MEDIA and WORLDWIDE FREE PRESS a REAL, TRUE and FACTUAL never-ending MAJOR NEWS STORY in the form of my TOTALLY OPEN SOURCE ongoing EXAGGERATED EDUCATIONAL SYMBOLIC ALLEGORICAL DRAMATIC LITERARY COMPOSITE HUMAN HERO CARTOON CHARACTER'S interactive multimedia autobiography.

This is a TOTALLY OPEN LETTER to the WHOLE WORLD PUBLIC from Ken Meyering, the longtime owner of DEFINE.COM, since June 21, 1995. My name is Ken. I am a futurist and advanced science enthusiast who's been on the internet right here at this URL for over three decades now.

I am now 59-years-old. Since 1998, I have been living with my mother under her care. I've been living on Social Security Disability for severe mental illness since the year 2000. My mental illness is very real and very well-documented by me for everybody everywhere on planet Earth.

Now, the tables are turned. I am now taking care of her. She is now on borrowed time, and past her natural expiration date. I have to keep her fit and strong. She is financially supporting me and paying all of our bills with her Social Security and retirement pension.

We are doing a public experiment here in totally open and transparent OPEN ACCOUNTING for the all-new all-virtual World Wide Web internet information and knowledge work economy. We are Open Source nonprofit knowledge workers who work online part-time from our private homes.

I am doing totally Open Source nonprofit private sector AI Application Research and Development for Uncle Sam and the United Nations.

I enjoy writing out and explaining my very unique and grandiose thoughts and ideas online when I'm up to it. I need them to pay me an extra monthly salary of $1620/month for doing all of this, as part-time online consulting work to promote the real whole truth, maximum happiness, good health, liberty and justice for all citizens everywhere on planet Earth.

This is BETTER than the VOICE of AMERICA. This is the REAL TRUE VOICE of the REAL TRUE LEADER of the REAL FREE WORLD in this ALL-VIRTUAL UNIVERSE that we are all living in and all sharing together here.

DEFINE.COM is a Washington State nonprofit private sector educational scientific think tank for World Peace with plenty of really good and really ethical super smart ideas for ethically and strategically applying benevolent AI to worldwide macroeconomics, education, health care, mental health care and criminal justice reform.

Unfortunately, DEFINE.COM is currently funded on a shoestring by me and now I have just received an e-mail from Amazon informing me of a $902.31 bandwidth bill for November 2025 from Amazon Web Services while I am living on only $2,252/month in Social Security Disability income.

I'm used to this being about $160/month. I don't know what to do now to pay for this and future bandwidth bills now that my free nonprofit education work is catching on with AI enthusiasts who are always scraping my Amazon S3 multimedia archives via CloudFront.

Now with all this interest in advanced AI and automation, all of my free online educational content is gaining popularity but now I have to figure out how to keep it online and available to all as it becomes more popular worldwide and I'm getting the whole bandwidth bill as a permanently disabled indivual who has to take a ton of meds just to function and sleep at all.

I normally earn about $500/month in YouTube Kaleidoscope Video revenue for my decades old really popular kaleidoscope videos with combined tens of millions of historical views. I need this self-employment income to qualify for my cruel and idiotic Republican-mandated Medicaid work requirements just to get my mental health care through my mental health care provider even though I am already mentally disabled and on Social Security Disability for severe mental illness that prevents me from working for others in the first place. 

Right after Donald J. Trump, Elon Musk, the MAGA Republicans and DOGE took over and all stole all of our ABSOLUTELY PRIVATE and CONFIDENTIAL federal data for their own absolutely corrupt political and economic purposes to further enrich themselves by controlling all the rest of our money, the Social Security Administration sent me a letter out of the blue telling me that they have determined that my disability is over. 

I wrote a long appeal to a Disablity judge who never got to see it because it was intercepted and discarded as irrelevent. What the fuck am I supposed to do? I don't sleep. I can't work a normal job.

Now what do I do to stay in my home, pay my bills and keep my ideas online? Now I really do need OPM (Other Peoples' Money). Bottom line is I am running out of money fast and now I urgently need external help to pay my Amazon Web Services S3 and CloudFront Data Transfer Fees to Jeff Bezos.

Jeff Bezos has already had the Washington Post ban me from commenting there, even after years of near daily rational and thoughtful contributions, each and every single comment of which I have ever made there is now currently CENSORED and REMOVED for Donald J. Trump, Pete Hegseth, Pam Bondi, Kristi Noem and Kash Patel to protect the market value of Trump Coin, which would crash completely if people learned about my own ideas for a fee-free forever Jubilee Coin as a new non-speculative all-virtual world currency.

A human U.S. Social Security Administration representative told me that if I'm too stressed out to work, my Social Security Disability will continue as long as I do not exceed Social Security Disability income limits of exactly $1620/month in any single month for 2025 or my Social Security Disability payments will stop forever, essentially, and that I will lose my Medicare and Medicaid. Basically, a compassionate, merciful, respectful, empathetic, benevolent and humane human being in the U.S. government told me point blank over the phone that all I had to do to maintain my U.S. government job security, health care and near total freedom of speech is to stay poor. 

She said, "It's going to sound really weird coming from me, but if you are too stressed out to work for others, just don't make any money and your Social Security Disability benefits will continue. That is how the Trump Administration and MAGA Republican leadership is playing the game with all of us now.

Maybe I better sell at least ONE $4,000 Samsung 85" 8K HDR Interactive Television on Amazon.com this month to pay Amazon Web Services so they do NOT shut me down for nonpayment of my worldwide data transfer fees for my online nonprofit educational scientific public website work. Basically, all I have to do is drop a single link at the very end of my playlist to a $4000 85" 8K HDR Samsung TV on Amazon.com and Amazon Web Services will waive my $902.31 nonprofit data transfer fees for November 2025. In the business we call that bartering with eyeballs.
https://www.youtube.com/watch?v=mOEcwaLNUMo&list=PLI-3LueqVb9YY6cInw-ALyA48R_Sav
https://www.youtube.com/watch?v=DPCOo8vD2MY
https://www.youtube.com/shorts/nA3qW3nNhkY
https://www.youtube.com/shorts/43CRqxYzhyw
https://www.youtube.com/shorts/jpvUAZEDloI
https://www.youtube.com/shorts/5OVc9XW_G_A
https://www.youtube.com/watch?v=cuX6BRJIL5Y
https://www.youtube.com/watch?v=b_1_HtVpmcY
https://www.youtube.com/watch?v=CnOZQ7tKxB0
https://www.youtube.com/watch?v=_Xcz8WDUBlw
https://www.youtube.com/watch?v=dagl5LzVRPQ
https://www.youtube.com/watch?v=q4xp_RZwBcw
https://www.youtube.com/watch?v=2KSiD_1lxD4
https://www.youtube.com/watch?v=klLl53APnSg
https://www.youtube.com/watch?v=_uRXU2ue2P0
https://www.youtube.com/watch?v=ugEFMj1cvsA
https://www.youtube.com/watch?v=HfXJU6rGVpw
https://www.youtube.com/watch?v=7GcyNif6PM8
https://www.youtube.com/watch?v=O40uaIpfTs4
https://www.youtube.com/watch?v=6P-gO5LoBwk
https://www.youtube.com/watch?v=ufWIXhR82yI
https://www.youtube.com/watch?v=3tmSDV4f9bY

https://define.com
https://define.com/OpenAI
https://define.com/OpenAI/OpenBook1/
https://define.com/OpenAI/OpenBook1/ethics_intro.html
https://define.com/define_dynamic_digital_forensic_archive_for_machines.html
https://define.com/godaddy
https://media.define.com

https://www.youtube.com/@JubileeCoin
https://www.youtube.com/@FreeWorldBank
https://www.youtube.com/hdcolors
https://www.youtube.com/post/UgkxYqTcWTyGO9KOPFHNQjkJ68W8L9mpa4H7
https://www.youtube.com/post/UgkxTnSRpPObs9Tcb83clFPiyQsMkvHjnuiM

https://x.com/FreeWorldBank
https://x.com/FreeWorldBank/status/1991073916639719585
https://x.com/FreeWorldBank/status/1966341535408206173
https://x.com/FreeWorldBank/status/1954715337699848427

https://www.nytimes.com/2025/10/16/us/politics/southern-command-head-stepping-down.html#permid=145986896
https://www.nytimes.com/2025/10/16/us/salesforce-benioff-ice.html?#permid=145991502
https://www.nytimes.com/2025/07/14/us/politics/trump-putin-ukraine.html#permid=143523033

These are my original kaleidoscope videos that I made as an openly mentally disabled middle-aged college student in an Advanced Flash ActionScript class at my local Community College in 2008. I eventually got an Associate of Applied Science 2-year technical degree in Web Database Development from Highline College in Des Moines, Washington, near Seattle in 2012. Basically, it took me over 4 years to learn how to administer my own LAMP web server. Many of these EDUCATIONAL hyperlinks here jump straight to YouTube commercials, even on my own non-monetized videos WITHOUT my approval, against my will. I don't want commercials on the first non-monetized Creative Commons FREE 8K animated kaleidoscope video background for TRANSPARENT AI AVATARS with GREEN SCREENS. These advertisers on YouTube should be revenue sharing with ME for THESE referrals on my 8K interactive TV websites. That would only be FAIR and JUST compensation for my own very well-informed totally open and transparent, totally peaceful and nonviolent, fearless, grandiose, rebellious and revolutionary ethical human decision-making processes, products and services. We are adding real value to the world here by sharing this technology with everybody everywhere on planet Earth for FREE for educational and healing purposes.

https://www.youtube.com/watch?v=gxxqdrrpgZc&list=PL2sS6bGk1mzEAx6YdFf3PhHpf96fsC
https://www.youtube.com/watch?v=q2fIWB8o-bs&list=PL2sS6bGk1mzEAx6YdFf3PhHpf96fsCkMr
https://www.youtube.com/results?search_query=kaleidoscope

And now here are a few unflagged unlabeled uncommented unstructured free-form explanatory plain text kind and truthful words from Droid Ken for the benefit our 8K sponsors.

I got this on a 2025 Black Friday SALE at Best Buy for about $3,799 + Tax. This is my 85" 8K computer monitor mounted on the wall in my bedroom above my 40" x 20" stand-up teacher's desk facing that wall.

https://www.bestbuy.com/product/samsung-85-class-qn900f-series-neo-qled-8k-mini-led-samsungvision-ai-smart-tizen-tv-2025544/J3ZYG2FFFL

I love this stand up desk. I feel like a teacher standing in the front of a classroom giving a computer-aided multimedia lecture.

https://www.amazon.com/dp/B0DLN5QX6K

I will plug the exact same ~$4,000 2025 85" 8K Samsung on Amazon.com as a barter to pay my Amazon Web Services S3 and CloudFront bandwidth bills for November 2025.

https://www.amazon.com/Samsung-85-Inch-85QN900F-Quantum-Tracking/dp/B0DXMYKV9D

Here's a $500 Hisense 65" 4K HDR Interactive TV at Best Buy. I got two of these on Black Friday. One for our living room and one for my mom's bedroom. Our old Samsung 4K TV's didn't support Apple AirPlay and now with my my mom's memory loss that has become a critical need in our household and in our small family of two. Best Buy had a Black Friday purchasing limit of 2 of these per household.

https://www.bestbuy.com/product/hisense-65-class-u6-series-miniled-qled-uhd-4k-hdr-smart-fire-tv-2025/J3Z9Z42SL2

Here's that exact same Hisense 65" 4K HDR Interactive TV on Amazon.com. I purchase 2 of these from Amazon on Black Friday to put on the wall above my bed so I can monitor my different website feeds and costs from my stand-up desk when I'm NOT in bed sleeping.

I didn't even need to plug-in an HDMI cable to anything. All I needed was power and Wi-Fi. It connected to my Wi-Finetwork and from there it's all web client-based in a browser after visiting my 8K video website URLs.

https://www.amazon.com/dp/B0DYW81FWH

We just fired the President of the United States of America, the Vice President of the United States of America, the U.S. Senate Majority Leader, the Speaker of the U.S. House of Representatives and the entire partisan U.S. Supreme Court for mass murder. We fired the U.S. Secretary of Defense, the U.S. Attorney General, the U.S. FBI Director and all U.S. Federal Judges appointed and approved by them. 

We peacefully and nonviolently impeached them all without their approval. Their legal authority over all the rest of us, our bodies, our land and our natural resources is null and void effective immediately. We are turning it all over to the ethical socially and ecologically responsible scientific community in the nonprofit private sector to manage with their totally OPEN SOURCE nonprofit Free World Bank. 

Please scroll to the very top of this _MyAnythingList.txt plain text totally free-form natural language playlist document to see the truth about my own personal monthly financial needs for my $1,863.53/month nonprofit private sector credit union home mortgage (balance remaining: $142,957.45), my food and utilities, my Jeff Bezos data transfer bandwidth fees and $1,500/month in credit card payments to JP Morgan Chase bank and Discover. I will allow for and budget $200/month for legal weed and $200/month in lawn care services during peak lawn growth season.

That is what I need my PAPER CASH MONEY for. I withdraw all my cash at the local weed store ATM, $500 at a time, for weed and help with my yardwork. They all speak Spanish as a primary language. I love and appreciate them all and I NEED their HELP to do very physical home and yardwork labor that my 82-year-old disabled mother and I cannot do just by ourselves without HELP from other people. I am physically fatigued all the time. I have a super abnormal and totally unpredictable sleep/wake schedule due to my schizoaffective disorder (bipolar type) and PTSD. It is now time for the whole world to meet the Bell Laboratories and MIT androids who are above all human beings and all human governments. Marvin Minsky and friend made them.

I am a REAL GENIUS advanced biological robot who first wrote this Open Source Javascript web application out of thin air during a 10-hour straight super creative and super productive manic episode and iterated all day and all night long with ChatGPT making tiny little incremental UI and functional changes, adding more and more features and functionality, in a LONELY marathon trial-and-error software development session that I recorded in my underwear in my bedroom on a YoloBox Extreme HDMI recorder without sound in 4K UltraHD to share publicly on DEFINE.COM via YouTube so the whole world can see how this particular web home page came into existence. 

The benevolent and ethical AIs gave everybody everywhere on planet Earth something here on my website that they can replicate and modify on their own for FREE with further patient HELP and CREATIVE ASSISTANCE from ChatGPT without them having to write or understand a single line of computer code. 

This is what we call a totally free Creative Commons framework for anybody to join into the whole worldwide network of individual 8K Interative Home-based Television Studios. Now, anybody CAN create their own 8K Interactive TV Hypertext Business Card with Video simply by getting their own cheap website and uploading three simple text files with THEIR OWN settings, playlists, thumbnails and branding text. 

Now, with ChatGPT, all people need to do to have their own super ultra high definition 8K Interactive TV Channel is cut and paste a bunch of URLs that they are currently interested in and upload that list to their website, and keep changing that list with their latest topically temporally revelant recommendations on a day-by-day hour-by-hour moment-by-moment basis and steer the world towards real truthful solutions to our most difficult problems, instead of a bunch of partisan mass media lies, propaganda and empty promises by totally corrupt politicians and their agents.

Just put these four totally Open Source DEFINE.COM files in the root directory or any subfolder on your website and you are in the 8K Interactive Television News and Opinion Online Advertising Business. Welcome to the new worldwide FREE PRESS. We just LET YOU GO. We just SET YOU FREE. Now YOU are in TOTAL CONTROL of YOUR OWN information, not Donald J. Trump, Elon Musk, Jeff Bezos, Mark Zuckerberg or Bill Gates. We are giving REAL Power to the People here for FREE. We do NOT want your PRIVATE DATA. We decentralize things. We want to push CONTROL of your PRIVATE DATA away from the rich and powerful authorities at the TOP of the pyramid towards the individual human beings on the ground level in their homes at the BOTTOM base of the pyramid. Eventually, we are all going need 8K Interactive TVs with residential bidirectional symmetrical unlimited gigabit fiber to the home. We are planning way ahead here.

https://define.com/index.html
https://define.com/_MyAnythingList.txt
https://define.com/_MyAnythingListRequirements.html
https://define.com/_MyAnythingListREADME.html`;


    const LOCAL_BRANDING = "./_MyAnythingListBrandingText.json";
    const REMOTE_BRANDING = "https://define.com/_MyAnythingListBrandingText.json";
    let brandingConfig = null;
    let currentLanguageCode = null;

    const FALLBACK_LANGUAGES = [
      { code: "en", native: "English", english: "English" },
      { code: "es", native: "Español", english: "Spanish" },
      { code: "fr", native: "Français", english: "French" },
      { code: "de", native: "Deutsch", english: "German" },
      { code: "pt", native: "Português", english: "Portuguese" },
      { code: "it", native: "Italiano", english: "Italian" },
      { code: "ru", native: "Русский", english: "Russian" },
      { code: "uk", native: "Українська", english: "Ukrainian" },
      { code: "pl", native: "Polski", english: "Polish" },
      { code: "nl", native: "Nederlands", english: "Dutch" },
      { code: "sv", native: "Svenska", english: "Swedish" },
      { code: "no", native: "Norsk", english: "Norwegian" },
      { code: "da", native: "Dansk", english: "Danish" },
      { code: "fi", native: "Suomi", english: "Finnish" },
      { code: "cs", native: "Čeština", english: "Czech" },
      { code: "sk", native: "Slovenčina", english: "Slovak" },
      { code: "sl", native: "Slovenščina", english: "Slovenian" },
      { code: "hr", native: "Hrvatski", english: "Croatian" },
      { code: "sr", native: "Српски", english: "Serbian" },
      { code: "bg", native: "Български", english: "Bulgarian" },
      { code: "ro", native: "Română", english: "Romanian" },
      { code: "el", native: "Ελληνικά", english: "Greek" },
      { code: "tr", native: "Türkçe", english: "Turkish" },
      { code: "ku", native: "Kurdî", english: "Kurdish" },
      { code: "ar", native: "العربية", english: "Arabic" },
      { code: "fa", native: "فارسی", english: "Farsi / Persian" },
      { code: "ur", native: "اردو", english: "Urdu" },
      { code: "ps", native: "پښتو", english: "Pashto" },
      { code: "he", native: "עברית", english: "Hebrew" },
      { code: "hi", native: "हिन्दी", english: "Hindi" },
      { code: "bn", native: "বাংলা", english: "Bengali" },
      { code: "ta", native: "தமிழ்", english: "Tamil" },
      { code: "te", native: "తెలుగు", english: "Telugu" },
      { code: "ml", native: "മലയാളം", english: "Malayalam" },
      { code: "pa", native: "ਪੰਜਾਬੀ", english: "Punjabi" },
      { code: "zh", native: "中文", english: "Chinese" },
      { code: "ja", native: "日本語", english: "Japanese" },
      { code: "ko", native: "한국어", english: "Korean" },
      { code: "th", native: "ไทย", english: "Thai" },
      { code: "id", native: "Bahasa Indonesia", english: "Indonesian" },
      { code: "ms", native: "Bahasa Melayu", english: "Malay" },
      { code: "sw", native: "Kiswahili", english: "Swahili" },
      { code: "am", native: "አማርኛ", english: "Amharic" },
      { code: "so", native: "Af-Soomaali", english: "Somali" },
      { code: "yo", native: "Yorùbá", english: "Yoruba" },
      { code: "ig", native: "Asụsụ Igbo", english: "Igbo" },
      { code: "ha", native: "Hausa", english: "Hausa" }
    ];

    function populateFallbackLanguages() {
      const languageSelect = document.getElementById("languageSelect");
      if (!languageSelect) return;
      if (languageSelect.options.length) return;
      FALLBACK_LANGUAGES.forEach((lang) => {
        const opt = document.createElement("option");
        opt.value = lang.code;
        opt.textContent =
          lang.code.toUpperCase() + " • " + lang.native + " • " + lang.english;
        languageSelect.appendChild(opt);
      });
    }

    const tvLikeUserAgent = /Tizen|Web0S|SmartTV|HbbTV|NetCast|BRAVIA|AppleTV|Android TV/i.test(
      navigator.userAgent || ""
    );


    async function fetchBrandingConfig() {
      async function tryFetch(url) {
        try {
          const res = await fetch(url + "?_t=" + Date.now(), { cache: "no-store" });
          if (!res.ok) return null;
          return await res.json();
        } catch (e) {
          console.warn("Branding fetch failed from", url, e);
          return null;
        }
      }

      // Try local first, then remote fallback
      let data = await tryFetch(LOCAL_BRANDING);
      if (!data) data = await tryFetch(REMOTE_BRANDING);
      return data;
    }

    function applyBrandingLanguage(langCode) {
      if (!brandingConfig || !brandingConfig.languages) return;
      const langs = brandingConfig.languages;
      let code = langCode || currentLanguageCode || brandingConfig.defaultLanguage || "en";

      // Try exact, lower-case, then upper-case
      if (!langs[code]) {
        if (langs[code.toLowerCase()]) code = code.toLowerCase();
        else if (langs[code.toUpperCase()]) code = code.toUpperCase();
      }
      // Fallback to English or first language
      if (!langs[code]) {
        if (langs["en"]) code = "en";
        else if (langs["EN"]) code = "EN";
        else {
          const keys = Object.keys(langs);
          if (keys.length) code = keys[0];
        }
      }
      currentLanguageCode = code;

      const langObj = langs[code] || {};
      const brandLine = langObj.brandLine;
      const brandEl = document.getElementById("brandLine");
      if (brandEl && brandLine) {
        brandEl.textContent = brandLine;
      }

      const languageSelect = document.getElementById("languageSelect");
      if (languageSelect && !languageSelect.options.length) {
        const codes = Object.keys(langs);
        codes.sort();
        codes.forEach((c) => {
          const l = langs[c] || {};
          const opt = document.createElement("option");
          opt.value = c;
          opt.textContent = l.label || c.toUpperCase();
          languageSelect.appendChild(opt);
        });
      }
      if (languageSelect) {
        languageSelect.value = code;
      }
    }

    async function initBranding() {
      const languageSelect = document.getElementById("languageSelect");
      const brandEl = document.getElementById("brandLine");
      if (!languageSelect || !brandEl) return;

      try {
        const data = await fetchBrandingConfig();
        if (!data || !data.languages) {
          console.warn("No branding config found; using fallback language list.");
          populateFallbackLanguages();
        } else {
          brandingConfig = data;
          applyBrandingLanguage(data.defaultLanguage || "en");

          languageSelect.addEventListener("change", (ev) => {
            applyBrandingLanguage(ev.target.value);
          });
        }
      } catch (e) {
        console.warn("initBranding failed", e);
        populateFallbackLanguages();
      }

      const controlsRow = document.getElementById("controlsRow");
      if (controlsRow && controlsRow.classList.contains("boot-hidden")) {
        controlsRow.classList.remove("boot-hidden");
        controlsRow.classList.add("boot-visible");
      }
    }

    async function fetchFeedList() {
      async function tryFetch(url, description) {
        try {
          const res = await fetch(url + "?_t=" + Date.now(), { cache: "no-store" });
          if (!res.ok) return null;
          const txt = await res.text();

          // Record where the playlist actually came from.
          currentPlaylistSource = description || url;
          updatePlaylistSourceLabel();

          return txt;
        } catch (e) {
          return null;
        }
      }

      // Try local first, then remote fallback
      let text = await tryFetch(LOCAL_LIST, LOCAL_LIST);
      if (text === null) text = await tryFetch(REMOTE_LIST, REMOTE_LIST);
      return text;
    }

    async function updateFeedsFromFile() {
      let text = await fetchFeedList();

      // When opened directly from the filesystem (file://),
      // most browsers block fetch() to local .txt files.
      // In that case, fall back to a built‑in default playlist.
      if (!text && window.location.protocol === "file:") {
        console.warn("Running from file:// — using built‑in DEFAULT_FEED_TEXT fallback.");
        text = DEFAULT_FEED_TEXT;

        currentPlaylistSource = "DEFAULT_FEED_TEXT (embedded demo playlist)";
        updatePlaylistSourceLabel();
      }

      if (!text) {
        console.warn("No _MyAnythingList.txt found locally or remotely yet; will retry in 60s.");
        currentPlaylistSource = "(no local or remote playlist loaded yet)";
        updatePlaylistSourceLabel();
        return;
      }

      if (text.trim() === lastListText.trim()) {
        // Nothing changed — skip rebuild
        return;
      }

      // Keep raw text for the editor
      lastListText = text;
      editorListText = text;

      const lines = text.split(/\r?\n/);

      // FAST PATH: show only the first N usable URLs immediately
      // so the grid appears as quickly as possible.
      const quickUrls = [];
      const maxInitial = (typeof CONFIG.Max_Visible_Panels === "number" &&
                          CONFIG.Max_Visible_Panels > 0)
        ? CONFIG.Max_Visible_Panels
        : Infinity;

      // Use the same URL extraction logic as the editor:
      // - Skip lines beginning with '#'
      // - Pull out every valid URL from the remaining lines
      const urlRegex = /\bhttps?:\/\/[^\s<>"')]+/gi;

      for (const rawLine of lines) {
        const line = rawLine.trim();
        if (!line || line.startsWith("#")) continue;

        let match;
        while ((match = urlRegex.exec(line)) !== null) {
          let url = match[0].replace(/[),.]+$/, "");
          quickUrls.push(url);
          if (quickUrls.length >= maxInitial) break;
        }
        urlRegex.lastIndex = 0;
        if (quickUrls.length >= maxInitial) break;
      }

      if (quickUrls.length) {
        currentUrls = quickUrls;
        rebuildWall();
      }

      // SLOW PATH: parse the full list in the background
      const fullUrls = [];
      for (const rawLine of lines) {
        const line = rawLine.trim();
        if (!line || line.startsWith("#")) continue;

        let match;
        while ((match = urlRegex.exec(line)) !== null) {
          let url = match[0].replace(/[),.]+$/, "");
          fullUrls.push(url);
        }
        urlRegex.lastIndex = 0;
      }

      if (fullUrls.length && fullUrls.length !== quickUrls.length) {
        setTimeout(() => {
          currentUrls = fullUrls;
          rebuildWall();
        }, 10);
      }
    }

    function isFullscreen() {
      return document.fullscreenElement ||
             document.webkitFullscreenElement ||
             document.mozFullScreenElement ||
             document.msFullscreenElement;
    }

    function enterFullscreen() {
      const el = document.documentElement;
      if (el.requestFullscreen) el.requestFullscreen();
      else if (el.webkitRequestFullscreen) el.webkitRequestFullscreen();
      else if (el.mozRequestFullScreen) el.mozRequestFullScreen();
      else if (el.msRequestFullscreen) el.msRequestFullscreen();
    }

    function exitFullscreen() {
      if (document.exitFullscreen) document.exitFullscreen();
      else if (document.webkitExitFullscreen) document.webkitExitFullscreen();
      else if (document.mozCancelFullScreen) document.mozCancelFullScreen();
      else if (document.msExitFullscreen) document.msExitFullscreen();
    }

    function toggleFullscreen() {
      if (isFullscreen()) exitFullscreen();
      else enterFullscreen();
    }

    function currentAspectRatio() {
      const resSel = document.getElementById("resolutionSelect");
      const val = resSel.value || "3840x2160";
      const parts = val.split("x");
      const w = parseInt(parts[0], 10) || 3840;
      const h = parseInt(parts[1], 10) || 2160;
      return w / h;
    }

    function updateTileAspectRatios() {
      const resSel = document.getElementById("resolutionSelect");
      if (!resSel) return;

      const val = resSel.value || "3840x2160";
      const parts = val.split("x");
      const w = parseInt(parts[0], 10) || 3840;
      const h = parseInt(parts[1], 10) || 2160;
      if (!w || !h) return;

      const ratioString = w + " / " + h;

      document.querySelectorAll(".tile").forEach((tile) => {
        tile.style.aspectRatio = ratioString;
      });
    }

    function applyResolutionFromSelect() {
      const resSel = document.getElementById("resolutionSelect");
      const val = resSel.value || "3840x2160";
      const parts = val.split("x");
      const w = parseInt(parts[0], 10) || 3840;
      const h = parseInt(parts[1], 10) || 2160;
      const aspectSelect = document.getElementById("aspectSelect");

      if (w >= h) {
        document.body.classList.add("aspect-horizontal");
        document.body.classList.remove("aspect-vertical");
        aspectSelect.value = "16x9";
      } else {
        document.body.classList.add("aspect-vertical");
        document.body.classList.remove("aspect-horizontal");
        aspectSelect.value = "9x16";
      }

      updateTileAspectRatios();
      autoChooseGridColumns();
      applyGridFromSlider();
      updateQrLayout();
    }

    function applyGridFromSlider() {
      const wallGrid = document.getElementById("wallGrid");
      const cols = Math.max(1, Math.min(8, gridCols || 1));
      wallGrid.style.gridTemplateColumns = "repeat(" + cols + ", minmax(0, 1fr))";
    }

    function autoChooseGridColumns() {
      const safeOuter = document.getElementById("safeOuter");
      const wallGrid = document.getElementById("wallGrid");
      const topBar = document.querySelector(".top-bar");
      const footer = document.querySelector(".footer");

      if (userGridOverride) {
        const cols = Math.max(1, Math.min(8, gridCols || 1));
        if (wallGrid) {
          wallGrid.style.gridTemplateColumns = "repeat(" + cols + ", minmax(0, 1fr))";
        }
        return;
      }

      const n = feeds.length;
      if (!n) return;

      const viewportH = window.innerHeight || document.documentElement.clientHeight;
      const topH = topBar ? topBar.getBoundingClientRect().height : 0;
      const footerH = footer ? footer.getBoundingClientRect().height : 0;

      const verticalMargin = 32;
      const availableHeight = viewportH - topH - footerH - verticalMargin;
      if (availableHeight <= 0) return;

      const safeRect = safeOuter.getBoundingClientRect();
      const innerWidth = safeRect.width - 20;
      if (innerWidth <= 0) return;

      const style = getComputedStyle(document.documentElement);
      const gap = parseFloat(style.getPropertyValue("--grid-gap")) || 10;
      const aspect = currentAspectRatio() || (16/9);

      let bestCols = 1;
      let bestTileHeight = 0;
      const maxCols = Math.min(gridCols || 8, n);

      for (let cols = 1; cols <= maxCols; cols++) {
        const rows = Math.ceil(n / cols);
        const tileWidth = (innerWidth - gap * (cols - 1)) / cols;
        if (tileWidth <= 0) continue;
        const tileHeight = tileWidth / aspect;
        const totalHeight = rows * tileHeight + gap * (rows - 1) + 20;
        if (totalHeight <= availableHeight && tileHeight > bestTileHeight) {
          bestTileHeight = tileHeight;
          bestCols = cols;
        }
      }

      if (bestTileHeight === 0) bestCols = maxCols;

      gridCols = bestCols;
      const slider = document.getElementById("gridSizeSlider");
      slider.value = String(bestCols);
      wallGrid.style.gridTemplateColumns = "repeat(" + bestCols + ", minmax(0, 1fr))";
    }

    function classifyFeedUrl(rawUrl) {
      const trimmed = rawUrl.trim();
      if (!trimmed) return null;
      let url;
      try { url = new URL(trimmed); } catch { return null; }
      const host = url.hostname.toLowerCase();
      const isYouTube = host.includes("youtube.com") || host === "youtu.be" || host === "www.youtube.com";

      if (isYouTube) {
        const path = url.pathname;
        const isShort = path.startsWith("/shorts/");
        const isPlaylist = path.startsWith("/playlist") || url.searchParams.has("list");
        const type = isShort ? "yt_short" : (isPlaylist ? "yt_playlist" : "yt_video");
        return { url: url.toString(), type: type };
      }
      return { url: url.toString(), type: "site", host: host };
    }

    function getSiteThumbUrl(feed) {
      const url = new URL(feed.url);
      const host = url.hostname.toLowerCase();
      return "https://www.google.com/s2/favicons?sz=256&domain=" + encodeURIComponent(host);
    }

    function loadYouTubeThumbnail(feed, imgEl) {
      // For playlists, use YouTube oEmbed so the thumbnail represents
      // the first video in the playlist.
      if (feed && feed.type === "yt_playlist") {
        if (window.fetch) {
          const oembedUrl =
            "https://www.youtube.com/oembed?url=" +
            encodeURIComponent(feed.url) +
            "&format=json";

          fetch(oembedUrl)
            .then((res) => (res.ok ? res.json() : null))
            .then((data) => {
              if (data && data.thumbnail_url) {
                imgEl.src = data.thumbnail_url;
              }
            })
            .catch(() => {
              // Leave the tile with its gradient background on failure.
            });
        }
        return;
      }

      // Non-playlist YouTube URLs (regular videos / shorts)
      let videoId = null;
      try {
        const url = new URL(feed.url);
        if (url.hostname === "youtu.be") {
          videoId = url.pathname.slice(1);
        } else if (url.searchParams.get("v")) {
          videoId = url.searchParams.get("v");
        } else if (url.pathname.startsWith("/shorts/")) {
          const parts = url.pathname.split("/");
          if (parts.length > 2) videoId = parts[2];
        }
      } catch (e) {}

      if (videoId) {
        const candidates = [
          "https://i.ytimg.com/vi/" + videoId + "/maxresdefault.jpg",
          "https://i.ytimg.com/vi/" + videoId + "/sddefault.jpg",
          "https://i.ytimg.com/vi/" + videoId + "/hqdefault.jpg",
          "https://i.ytimg.com/vi/" + videoId + "/mqdefault.jpg",
          "https://i.ytimg.com/vi/" + videoId + "/default.jpg"
        ];
        let idx = 0;
        const tryNext = () => {
          if (idx >= candidates.length) return;
          imgEl.src = candidates[idx++];
        };
        imgEl.addEventListener("error", tryNext);
        tryNext();
      }
    }

    function onFirstThumbLoad() {
      if (hasShownGridOnce) return;
      hasShownGridOnce = true;
      const mainArea = document.getElementById("mainArea");
      if (mainArea && mainArea.classList.contains("boot-hidden")) {
        mainArea.classList.remove("boot-hidden");
        mainArea.classList.add("boot-visible");
      }
    }

    function createTile(feed) {
      const tile = document.createElement("div");
      tile.className = "tile";
      tile.dataset.url = feed.url;

      const thumb = document.createElement("div");
      thumb.className = "tile-thumb";

      const img = document.createElement("img");
      img.crossOrigin = "anonymous";
      img.addEventListener("load", onFirstThumbLoad, { once: true });

      if (feed.type.startsWith("yt")) {
        thumb.appendChild(img);
        loadYouTubeThumbnail(feed, img);
      } else if (feed.type === "site") {
        img.src = getSiteThumbUrl(feed);
        thumb.appendChild(img);
      }

      const overlay = document.createElement("div");
      overlay.className = "tile-footer-overlay";

      const pill = document.createElement("span");
      pill.className = "pill pill-type" + (feed.type === "site" ? " site" : "");
      pill.textContent = feed.type === "site" ? "SITE" : "YOUTUBE";
      if (!showTypes) pill.classList.add("hidden");

      const urlLink = document.createElement("a");
      urlLink.className = "url-text";
      urlLink.href = feed.url;
      urlLink.target = "_blank";
      urlLink.rel = "noopener";
      urlLink.textContent = feed.url;
      if (!showUrls) urlLink.classList.add("hidden");
      urlLink.addEventListener("click", (e) => e.stopPropagation());

      overlay.appendChild(pill);
      overlay.appendChild(urlLink);
      if (!showUrls && !showTypes) overlay.classList.add("hidden");

      const qrAnchor = document.createElement("div");
      qrAnchor.className = "qr-anchor";
      const qrWrapper = document.createElement("div");
      qrWrapper.className = "qr-code";
      qrWrapper.title = feed.url;
      if (!showQr) qrWrapper.classList.add("hidden");
      const qrInner = document.createElement("div");
      qrWrapper.appendChild(qrInner);
      qrAnchor.appendChild(qrWrapper);

      thumb.appendChild(qrAnchor);
      thumb.appendChild(overlay);
      tile.appendChild(thumb);

      tile.addEventListener("click", () => {
        const tiles = getWallTiles();
        tvFocusIndex = tiles.indexOf(tile);
        applyTvSelection(false);
        window.open(feed.url, "_blank", "noopener");
      });
      qrWrapper.addEventListener("click", (e) => {
        e.stopPropagation();
        window.open(feed.url, "_blank", "noopener");
      });

      new QRCode(qrInner, { text: feed.url, width: 256, height: 256 });

      return tile;
    }

    
    function rebuildWall() {
      const wallGrid = document.getElementById("wallGrid");
      wallGrid.innerHTML = "";
      feeds = currentUrls.map(classifyFeedUrl).filter(Boolean);
      feeds.forEach((feed) => {
        wallGrid.appendChild(createTile(feed));
      });
      document.getElementById("feedsIndicator").textContent =
        feeds.length + (feeds.length === 1 ? " FEED" : " FEEDS");
      autoChooseGridColumns();
      applyGridFromSlider();
      updateQrLayout();
      updateTileAspectRatios();

      if (!hasShownGridOnce && feeds.length) {
        setTimeout(() => {
          onFirstThumbLoad();
        }, 1200);
      }

      // TV-remote style focus: start from first tile whenever wall is rebuilt.
      tvFocusIndex = 0;
      applyTvSelection(false);
    }

    function isTouchDevice() {
      return ("ontouchstart" in window) || (navigator.maxTouchPoints || 0) > 0;
    }

    function setupTouchNavMode() {
      if (!isTouchDevice()) return;
      // On touch-first devices, default nav mode to 'touch'
      navMode = "touch";
      document.body.classList.add("touch-device");
      const tiles = getWallTiles();
      tiles.forEach((t) => t.classList.remove("tv-selected"));
    }

    function getWallTiles() {
      return Array.from(document.querySelectorAll("#wallGrid .tile"));
    }

    function getCurrentGridCols() {
      const wallGrid = document.getElementById("wallGrid");
      if (!wallGrid) return gridCols || 1;
      const tpl = getComputedStyle(wallGrid).gridTemplateColumns;
      if (!tpl) return gridCols || 1;
      const count = tpl.split(" ").length;
      return count || gridCols || 1;
    }

    function applyTvSelection(scrollIntoView = true) {
      const tiles = getWallTiles();
      tiles.forEach((t) => t.classList.remove("tv-selected"));
      if (!tiles.length) return;

      if (tvFocusIndex < 0) tvFocusIndex = 0;
      if (tvFocusIndex >= tiles.length) tvFocusIndex = tiles.length - 1;

      const tile = tiles[tvFocusIndex];

      // Only show TV-selection glow in keyboard / remote mode.
      if (navMode === "keyboard") {
        tile.classList.add("tv-selected");
      }

      if (scrollIntoView) {
        tile.scrollIntoView({
          behavior: "smooth",
          block: "nearest",
          inline: "nearest",
        });
      }
    }
(function setupRowWheelScrolling() {
  const safeOuter = document.getElementById("safeOuter");
  if (!safeOuter) return;

  let snapping = false;
  let settleTimer = null;
  let lastScrollTop = 0;

  function moveFocusByRow(direction) {
    // direction: +1 for down, -1 for up
    const tiles = getWallTiles();
    if (!tiles.length) return;

    const cols = getCurrentGridCols();
    const step = cols || 1;

    if (direction > 0) {
      // down
      tvFocusIndex = Math.min(tvFocusIndex + step, tiles.length - 1);
    } else {
      // up
      tvFocusIndex = Math.max(tvFocusIndex - step, 0);
    }

    applyTvSelection(true); // this already calls scrollIntoView({ behavior: "smooth" })
  }

  function startSettleWatcher() {
    snapping = true;
    lastScrollTop = safeOuter.scrollTop;

    if (settleTimer !== null) {
      clearTimeout(settleTimer);
    }

    function checkSettled() {
      const current = safeOuter.scrollTop;
      const diff = Math.abs(current - lastScrollTop);

      if (diff < 0.5) {
        // Scroll position is effectively stable: stop ignoring input *now*.
        snapping = false;
        settleTimer = null;
      } else {
        // Still moving – keep watching.
        lastScrollTop = current;
        settleTimer = setTimeout(checkSettled, 60); // short, responsive interval
      }
    }

    // Give the smooth scroll a moment to start before we begin checking
    settleTimer = setTimeout(checkSettled, 80);
  }

  safeOuter.addEventListener(
    "wheel",
    (event) => {
      // Let Ctrl+wheel zoom work normally
      if (event.ctrlKey) return;

      // We want discrete row navigation, not native momentum scroll
      event.preventDefault();

      // Tiny deltas from jitter: ignore
      if (Math.abs(event.deltaY) < 5) return;

      // If we’re still in the middle of an ongoing snap, just ignore this one.
      // The important part is that `snapping` will flip back to false
      // as soon as the scroll animation is actually done.
      if (snapping) return;

      const direction = event.deltaY > 0 ? 1 : -1;
      moveFocusByRow(direction);
      startSettleWatcher();
    },
    { passive: false }
  );
})();


    function handleTvKeys(evt) {
      const key = evt.key;

      const isArrow =
        key === "ArrowLeft" ||
        key === "ArrowRight" ||
        key === "ArrowUp" ||
        key === "ArrowDown";

      const isOkKey = key === "Enter" || key === " ";

      if (!isArrow && !isOkKey) return;

      // If the playlist editor modal is open and focus is inside it,
      // let the modal (textarea/buttons) handle keys normally.
      const modalBackdrop = document.getElementById("modalBackdrop");
      if (modalBackdrop && modalBackdrop.classList.contains("active")) {
        const modal = modalBackdrop.querySelector(".modal");
        const activeInDoc = document.activeElement;
        if (modal && activeInDoc && modal.contains(activeInDoc)) {
          return;
        }
      }

      // Any keyboard navigation immediately switches into 'keyboard' mode
      // so the TV-selection glow becomes meaningful again.
      navMode = "keyboard";

      const active = document.activeElement;
      const tag = active && active.tagName;
      const activeIsInputLike =
        tag === "INPUT" || tag === "SELECT" || tag === "TEXTAREA";
      const activeIsSlider =
        activeIsInputLike &&
        active.type &&
        active.type.toLowerCase() === "range";

      if (activeIsSlider || activeIsInputLike) {
        evt.preventDefault();
        if (tag !== "TEXTAREA") {
          active.blur();
        }
      } else {
        evt.preventDefault();
      }

      const tiles = getWallTiles();
      if (!tiles.length) return;

      const cols = getCurrentGridCols();

if (isArrow) {
  const total = tiles.length;
  const colsSafe = Math.max(1, cols || 1);
  const row = Math.floor(tvFocusIndex / colsSafe);
  const col = tvFocusIndex % colsSafe;

  switch (key) {
    case "ArrowLeft": {
      if (col > 0) {
        // Normal left movement inside the row
        tvFocusIndex--;
      } else if (row > 0) {
        // At the left edge: wrap to rightmost tile in the row above
        const prevRowEnd = row * colsSafe - 1;
        tvFocusIndex = Math.min(prevRowEnd, total - 1);
      }
      break;
    }

    case "ArrowRight": {
      const atRowRightEdge = col === colsSafe - 1;
      const atLastTile = tvFocusIndex === total - 1;

      if (!atRowRightEdge && !atLastTile && tvFocusIndex < total - 1) {
        // Normal right movement inside the row
        tvFocusIndex++;
      } else {
        // At the right edge (or last tile in a short row):
        // jump to first tile of the next row, if it exists
        const nextRowStart = (row + 1) * colsSafe;
        if (nextRowStart < total) {
          tvFocusIndex = nextRowStart;
        }
        // If nextRowStart >= total, we're already on the last row,
        // so we just stay put.
      }
      break;
    }

    case "ArrowUp": {
      if (tvFocusIndex - colsSafe >= 0) {
        tvFocusIndex -= colsSafe;
      }
      break;
    }

    case "ArrowDown": {
      if (tvFocusIndex + colsSafe < total) {
        tvFocusIndex += colsSafe;
      }
      break;
    }
  }

  applyTvSelection(true);
  return;
}

      if (isOkKey) {
        if (tvFocusIndex < 0 || tvFocusIndex >= tiles.length) {
          tvFocusIndex = 0;
        }
        const tile = tiles[tvFocusIndex];
        const url = tile && tile.dataset && tile.dataset.url;
        if (url) {
          window.open(url, "_blank", "noopener");
        }
      }
    }



    function initSliderTooltips() {
      const sliders = document.querySelectorAll(".slider-group input[type=range]");
      sliders.forEach((slider) => {
        const group = slider.closest(".slider-group");
        if (!group) return;

        const tip = document.createElement("div");
        tip.className = "slider-tooltip";
        tip.textContent = slider.value;
        group.appendChild(tip);

        let hideTimer = null;

        function updateTip() {
          const min = slider.min !== "" ? parseFloat(slider.min) : 0;
          const max = slider.max !== "" ? parseFloat(slider.max) : 100;
          const val = slider.value !== "" ? parseFloat(slider.value) : min;
          const span = max > min ? (val - min) / (max - min) : 0;

          const sliderRect = slider.getBoundingClientRect();
          const groupRect = group.getBoundingClientRect();
          const x = sliderRect.left + span * sliderRect.width;
          const offsetX = x - groupRect.left;

          tip.style.left = offsetX + "px";
          tip.textContent = slider.value;
        }

        function showTip() {
          if (hideTimer !== null) {
            clearTimeout(hideTimer);
            hideTimer = null;
          }
          updateTip();
          tip.classList.add("visible");
          // Auto-hide shortly after last interaction even if some events are missed
          hideTimer = setTimeout(() => {
            tip.classList.remove("visible");
          }, 800);
        }

        function hideTip() {
          if (hideTimer !== null) {
            clearTimeout(hideTimer);
            hideTimer = null;
          }
          tip.classList.remove("visible");
        }

        slider.addEventListener("input", showTip);
        slider.addEventListener("change", showTip);

        // Show when user actively interacts with the control
        slider.addEventListener("pointerdown", showTip);
        slider.addEventListener("touchstart", showTip);
        slider.addEventListener("focus", showTip);

        // Hide as soon as interaction ends or pointer/focus leaves
        slider.addEventListener("pointerup", hideTip);
        slider.addEventListener("pointercancel", hideTip);
        slider.addEventListener("mouseleave", hideTip);
        slider.addEventListener("mouseout", hideTip);
        slider.addEventListener("blur", hideTip);
        slider.addEventListener("touchend", hideTip);
        slider.addEventListener("touchcancel", hideTip);

        if (group) {
          group.addEventListener("pointerleave", hideTip);
          group.addEventListener("mouseleave", hideTip);
          group.addEventListener("mouseout", hideTip);
        }

        // As a safety net, also hide on global pointer/touch end
        document.addEventListener("pointerup", hideTip);
        document.addEventListener("touchend", hideTip);
      });
    }


    function applyUiDefaultsFromHeader() {
      const cfg = window.MyAnythingListConfig || {};

      const gridSlider = document.getElementById("gridSizeSlider");
      if (gridSlider && typeof cfg.GRID === "number") {
        const clamped = Math.max(1, Math.min(8, cfg.GRID));
        gridSlider.value = String(clamped);
        gridCols = clamped;
        applyGridFromSlider();
      }

      const qrXSlider = document.getElementById("qrXSlider");
      if (qrXSlider && typeof cfg.QR_X === "number") {
        const val = Math.max(0, Math.min(100, cfg.QR_X));
        qrXSlider.value = String(val);
        qrOffsetX = val / 100;
      }

      const qrYSlider = document.getElementById("qrYSlider");
      if (qrYSlider && typeof cfg.QR_Y === "number") {
        const val = Math.max(0, Math.min(100, cfg.QR_Y));
        qrYSlider.value = String(val);
        qrOffsetY = val / 100;
      }

      const qrSizeSlider = document.getElementById("qrSizeSlider");
      if (qrSizeSlider && typeof cfg.QR_SIZE === "number") {
        const val = Math.max(15, Math.min(100, cfg.QR_SIZE));
        qrSizeSlider.value = String(val);
        const raw = val / 100;
        qrSizeFrac = Math.max(0.15, raw);
      }

      const aspectSelect = document.getElementById("aspectSelect");
      if (aspectSelect && typeof cfg.Aspect_Ratio === "string") {
        const ar = cfg.Aspect_Ratio;
        if (ar === "9x16" || ar === "16x9") {
          aspectSelect.value = ar;
        }
        if (ar === "9x16") {
          document.body.classList.add("aspect-vertical");
          document.body.classList.remove("aspect-horizontal");
        } else if (ar === "16x9") {
          document.body.classList.add("aspect-horizontal");
          document.body.classList.remove("aspect-vertical");
        }
      }

      updateQrLayout();
    }
function updateOverlayVisibility() {
      document.querySelectorAll(".tile").forEach((tile) => {
        const overlay = tile.querySelector(".tile-footer-overlay");
        const pill = overlay.querySelector(".pill-type");
        const urlText = overlay.querySelector(".url-text");
        const hasType = pill && !pill.classList.contains("hidden");
        const hasUrl = urlText && !urlText.classList.contains("hidden");
        overlay.classList.toggle("hidden", !(hasType || hasUrl));
      });
    }

    function updateQrLayout() {
      const tiles = document.querySelectorAll(".tile");
      if (!tiles.length) return;
      const style = getComputedStyle(document.documentElement);
      const qrMinFrac = parseFloat(style.getPropertyValue("--qr-min-frac")) || 0.18;
      const qrMaxFrac = parseFloat(style.getPropertyValue("--qr-max-frac")) || 0.9;

      tiles.forEach((tile) => {
        const thumb = tile.querySelector(".tile-thumb");
        const qrWrapper = tile.querySelector(".qr-code");
        if (!thumb || !qrWrapper) return;
        const rect = thumb.getBoundingClientRect();
        const usableWidth = rect.width;
        const usableHeight = rect.height;
        if (!usableWidth || !usableHeight) return;

        const overlay = tile.querySelector(".tile-footer-overlay");
        let overlayHeight = 0;
        const overlayActive = overlay && !overlay.classList.contains("hidden");
        if (overlayActive) overlayHeight = overlay.getBoundingClientRect().height || 0;

        const minSide = Math.min(usableWidth, usableHeight);
        let frac = qrSizeFrac;
        if (isNaN(frac)) frac = qrMinFrac;
        frac = Math.max(qrMinFrac, Math.min(qrMaxFrac, frac));

        const margin = 4;
        const size = minSide * frac;
        let minX = margin;
        let maxX = usableWidth - size - margin;
        if (maxX < minX) { const c = (usableWidth - size)/2; minX = maxX = c; }

        let minY = margin;
        // Make QR vertical position purely relative to the tile height so
        // it feels consistent from very large to very small tiles.
        let maxY = usableHeight - size - margin;
        if (maxY < minY) {
          const c = (usableHeight - size) / 2;
          minY = maxY = Math.max(0, c);
        }

        const left = minX + (maxX - minX) * qrOffsetX;
        const top = minY + (maxY - minY) * qrOffsetY;

        qrWrapper.style.width = size + "px";
        qrWrapper.style.height = size + "px";
        qrWrapper.style.left = left + "px";
        qrWrapper.style.top = top + "px";
      });
    }

    function openEditor() {
      const textarea = document.getElementById("url-editor");
      if (editorListText && editorListText.length) {
        textarea.value = editorListText;
      } else {
        textarea.value = currentUrls.join("\n");
      }
      document.getElementById("modalBackdrop").classList.add("active");
      textarea.focus();
    }

    function closeEditor() {
      document.getElementById("modalBackdrop").classList.remove("active");
    }

    function saveEditor() {
      const textarea = document.getElementById("url-editor");
      const raw = textarea.value || "";
      editorListText = raw;

      // Extract all valid URLs from non-comment lines using a regex.
      const urlRegex = /\bhttps?:\/\/[^\s<>"')]+/gi;
      const urls = [];

      const lines = raw.split(/\r?\n/);
      for (const rawLine of lines) {
        const line = rawLine.trim();
        if (!line || line.startsWith("#")) continue;

        let match;
        while ((match = urlRegex.exec(line)) !== null) {
          // Trim common trailing punctuation that might cling to URLs.
          let url = match[0].replace(/[),.]+$/, "");
          urls.push(url);
        }
        urlRegex.lastIndex = 0;
      }

      if (!urls.length) return;

      currentUrls = urls;
      closeEditor();
      rebuildWall();
    }

    function downloadEditor() {
      const textarea = document.getElementById("url-editor");
      const text = textarea.value || "";
      const blob = new Blob([text], { type: "text/plain;charset=utf-8" });
      const url = URL.createObjectURL(blob);
      const a = document.createElement("a");
      a.href = url;
      a.download = "_MyAnythingList.txt";
      document.body.appendChild(a);
      a.click();
      a.remove();
      URL.revokeObjectURL(url);
    }


    window.addEventListener("load", async () => {
      applyResolutionFromSelect();
      await initBranding();
      await updateFeedsFromFile();

      // On touch-capable devices, default to touch nav mode (no TV outline).
      setupTouchNavMode();

      // Initialize slider value tooltips for touch/desktop
      initSliderTooltips();

      // Apply header-defined UI defaults (sliders & aspect ratio)
      applyUiDefaultsFromHeader();

      // Re-poll every minute for changes to _MyAnythingList.txt
      setInterval(updateFeedsFromFile, 60 * 1000);

      // Run initial grid & QR layout once after data loads
      autoChooseGridColumns();
      applyGridFromSlider();
      updateQrLayout();

      // If config or TV-like device requests fullscreen, try once.
      try {
        const cfg = window.MyAnythingListConfig || {};
        const mode = String((cfg.Mode || "computer")).toLowerCase();
        const immersive = !!cfg.Immersive;
        const tvFullRequested = (mode === "tv" || immersive);

        if ((tvFullRequested || tvLikeUserAgent) && typeof enterFullscreen === "function") {
          enterFullscreen();
        }
      } catch (e) {
        console.warn("Fullscreen request may have been blocked by the browser:", e);
      }
    
      // Info button / README modal wiring
      window.addEventListener("load", () => {
const infoButton = document.getElementById("infoButton");
      const infoModal = document.getElementById("infoModal");
      const infoModalClose = document.getElementById("infoModalClose");
      const infoCurrentLanguage = document.getElementById("infoCurrentLanguage");

      function getCurrentLanguageCode() {
        if (window.MyAnythingListConfig && typeof window.MyAnythingListConfig.defaultLanguage === "string") {
          return window.MyAnythingListConfig.defaultLanguage;
        }
        if (window.currentLanguage) return window.currentLanguage;
        return "en";
      }

      function openInfoModal() {
        if (!infoModal) return;
        const lang = getCurrentLanguageCode();
        if (infoCurrentLanguage) {
          infoCurrentLanguage.textContent = lang;
        }
        infoModal.style.display = "flex";
      }

      function closeInfoModal() {
        if (!infoModal) return;
        infoModal.style.display = "none";
      }

      if (infoButton) {
        infoButton.addEventListener("click", (ev) => {
          ev.preventDefault();
          ev.stopPropagation();
          openReadmeWithFallback();
        });
      }
      if (infoModalClose) {
        infoModalClose.addEventListener("click", closeInfoModal);
      }
      if (infoModal) {
        infoModal.addEventListener("click", (e) => {
          if (e.target === infoModal) {
            closeInfoModal();
          }
        });
      }

});

    window.addEventListener("resize", () => {
      autoChooseGridColumns();
      applyGridFromSlider();
      updateQrLayout();
    });

    document.getElementById("editButton").addEventListener("click", openEditor);
    document.getElementById("editorCancel").addEventListener("click", closeEditor);
    document.getElementById("editorSave").addEventListener("click", saveEditor);
    const downloadBtn = document.getElementById("editorDownload");
    if (downloadBtn) downloadBtn.addEventListener("click", downloadEditor);

    document.getElementById("qrToggleButton").addEventListener("click", (ev) => {
      showQr = !showQr;
      ev.currentTarget.textContent = showQr ? "Hide QR Codes" : "Show QR Codes";
      document.querySelectorAll(".qr-code").forEach((el) => el.classList.toggle("hidden", !showQr));
      updateQrLayout();
    });

    document.getElementById("linksToggleButton").addEventListener("click", (ev) => {
      showUrls = !showUrls;
      ev.currentTarget.textContent = showUrls ? "Hide URLs" : "Show URLs";
      document.querySelectorAll(".url-text").forEach((el) => el.classList.toggle("hidden", !showUrls));
      updateOverlayVisibility();
      updateQrLayout();
    });

    document.getElementById("typesToggleButton").addEventListener("click", (ev) => {
      showTypes = !showTypes;
      ev.currentTarget.textContent = showTypes ? "Hide Types" : "Show Types";
      document.querySelectorAll(".pill-type").forEach((el) => el.classList.toggle("hidden", !showTypes));
      updateOverlayVisibility();
      updateQrLayout();
    });

    document.getElementById("gridSizeSlider").addEventListener("input", (ev) => {
      gridCols = parseInt(ev.target.value, 10) || 1;
      userGridOverride = true;
      applyGridFromSlider();
      updateQrLayout();
    });

    document.getElementById("qrXSlider").addEventListener("input", (ev) => {
      const v = Number(ev.target.value);
      qrOffsetX = v / 100;
      if (window.MyAnythingListConfig) {
        window.MyAnythingListConfig.QR_X = v;
      }
      updateQrLayout();
    });

    document.getElementById("qrYSlider").addEventListener("input", (ev) => {
      const v = Number(ev.target.value);
      qrOffsetY = v / 100;
      if (window.MyAnythingListConfig) {
        window.MyAnythingListConfig.QR_Y = v;
      }
      updateQrLayout();
    });

    document.getElementById("qrSizeSlider").addEventListener("input", (ev) => {
      const v = Number(ev.target.value);
      const raw = v / 100;
      qrSizeFrac = Math.max(0.15, raw);
      if (window.MyAnythingListConfig) {
        window.MyAnythingListConfig.QR_SIZE = v;
      }
      updateQrLayout();
    });

    document.getElementById("aspectSelect").addEventListener("change", (ev) => {
      const aspectSelect = ev.currentTarget;
      const resSel = document.getElementById("resolutionSelect");
      if (aspectSelect.value === "9x16") {
        resSel.value = "1080x1920";
      } else {
        resSel.value = "3840x2160";
      }
      if (window.MyAnythingListConfig) {
        window.MyAnythingListConfig.Aspect_Ratio = aspectSelect.value;
        window.MyAnythingListConfig.Output_Resolution = resSel.value;
      }
      applyResolutionFromSelect();
    });

    document.getElementById("resolutionSelect").addEventListener("change", (ev) => {
      if (window.MyAnythingListConfig) {
        window.MyAnythingListConfig.Output_Resolution = ev.target.value;
      }
      applyResolutionFromSelect();
    });

    
function openReadmeWithFallback() {
  // Simplest possible behavior for local + web:
  // Always open the generic README file next to this HTML file.
  // For your define.com deployment, use the same filename at the site root.
  const local = "./_MyAnythingListREADME.html";
  window.open(local, "_blank");
}

function openRequirementsWithFallback() {
  // Simplest possible behavior for local + web:
  // Always open the generic Requirements file next to this HTML file.
  const local = "./_MyAnythingListRequirements.html";
  window.open(local, "_blank");
}

const requirementsButton = document.getElementById("requirementsButton");
    if (requirementsButton) {
      requirementsButton.addEventListener("click", (ev) => {
        ev.preventDefault();
        ev.stopPropagation();
        openRequirementsWithFallback();
      });
    }

    
});
document.getElementById("gearToggle").addEventListener("click", (ev) => {
      ev.stopPropagation();

      // Toggle immersive UI + fullscreen for everyone
      document.documentElement.classList.toggle("immersive");
      document.body.classList.toggle("immersive");
      toggleFullscreen();

      // TV-like devices keep scrollbars hidden via the tv-locked class set on load.
      autoChooseGridColumns();
      applyGridFromSlider();
      updateQrLayout();
    });

    window.addEventListener("keydown", handleTvKeys);
  </script>

  <div id="infoModal" class="modal-backdrop" style="display:none;">
    <div class="modal">
      <div class="modal-header">
        <h2>_MyAnythingList README</h2>
        <button id="infoModalClose" class="modal-close" aria-label="Close">×</button>
      </div>
      <div class="modal-body">
        <p>This is a quick, on-screen README in your current language. For the full specification, open the language-specific requirements document from your home server's <code>/spec</code> directory.</p>
        <p>Current language: <span id="infoCurrentLanguage">en</span></p>
        <p>You can also open the full spec in a new tab:</p>
        <pre><code>/_MyAnythingListRequirements_v3.3_universal_tv_input_globalpacks.&lt;lang&gt;.html</code></pre>
      </div>
    </div>
  </div>
<script>
  // Final safety wiring for the README (i) button on define.com
  window.addEventListener("DOMContentLoaded", function () {
    var infoButton = document.getElementById("infoButton");
    if (infoButton) {
      infoButton.addEventListener("click", function (ev) {
        ev.preventDefault();
        ev.stopPropagation();
        // README lives in the same S3 folder as index.html:
        // https://s3.amazonaws.com/www.define.com/_MyAnythingListREADME.html
        window.open("./_MyAnythingListREADME.html", "_blank");
      });
    }

    // If you ever want to guarantee R as well, you can also wire it here:
    var requirementsButton = document.getElementById("requirementsButton");
    if (requirementsButton) {
      requirementsButton.addEventListener("click", function (ev) {
        ev.preventDefault();
        ev.stopPropagation();
        window.open("./_MyAnythingListRequirements.html", "_blank");
      });
    }
  });
</script>

</body>
</html>