view mrjunejune/test/snapshots/tools_file_converter.snapshot @ 264:04fee26ecce0

add authenticated JRPG conversation platform Add reusable auth/session storage, owned conversation recovery, guest quotas, admin workflows, URL-routed conversation UI, mobile frame support, and parallel browser acceptance. Co-authored-by: Copilot <[email protected]>
author MrJuneJune <me@mrjunejune.com>
date Fri, 07 Aug 2026 07:34:12 -0700
parents 60a876c4587a
children
line wrap: on
line source

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>File Format Converter</title>
    <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="theme-color" content="#f7f3e8">
<link rel="icon" type="image/svg+xml" href="/public/epi_all_colors.svg">
<link rel="manifest" href="/public/manifest.json">
<link rel="apple-touch-icon" href="/public/epi_all_colors.svg">

<link rel="preload" href="/public/fonts/Roboto-Regular.ttf" as="font"  crossorigin>
<link rel="preload" href="/public/fonts/Roboto-Thin.ttf"as="font" crossorigin>

<!-- <link rel="preload" href="/public/fonts/atkinson-regular.woff" as="font" type="font/woff" crossorigin> -->
<!-- <link rel="preload" href="/public/fonts/atkinson-bold.woff" as="font" type="font/woff" crossorigin> -->

<!-- <link rel="preload" href="/public/fonts/more-sugar.extras.otf" as="font" type="font/otf" crossorigin> -->
<link rel="preload" href="/public/fonts/more-sugar.regular.otf" as="font" type="font/otf" crossorigin>
<link rel="preload" href="/public/fonts/more-sugar.thin.otf" as="font" type="font/otf" crossorigin>
<link rel="preload" href="/public/epi_all_colors.svg" as="image">

<link rel="stylesheet" href="/public/design-system/styles/tokens.css" />
<link rel="stylesheet" href="/public/design-system/styles/themes.css" />
<link rel="preload" href="/base.css" as="style" />
<link rel="stylesheet" href="/base.css" />
<link rel="stylesheet" href="/public/design-system/styles/components.css" />
<script
  type="module"
  src="/public/design-system/components/index.js"
></script>

<script src="/public/pwa-register.js" defer></script>

    <style>
        .container {
            max-width: 800px;
            margin: 2rem auto;
            padding: var(--zenbu-sys-padding-xl);
        }

        .converter-section {
            border-radius: var(--zenbu-sys-radius-control);
            border: 2px solid var(--lightgray);
            padding: var(--zenbu-sys-padding-xl);
            margin-bottom: 2rem;
        }

        .converter-section h2 {
            margin-top: 0;
            color: var(--black);
        }

        .file-input-wrapper {
            margin: 1rem 0;
        }

        .file-input-wrapper label {
            display: block;
            margin-bottom: 0.5rem;
            font-weight: 600;
        }

        input[type="file"] {
            padding: var(--zenbu-sys-padding-sm);
            border: 2px dashed #ccc;
            border-radius: var(--zenbu-sys-radius-control-small);
            background: white;
            font-size: var(--zenbu-sys-font-size-md);
        }

        button {
            background: var(--purple);
            font-family: "More Thin", sans-serif;
            color: var(--gray-gradient);
            border: none;
            border-radius: var(--zenbu-sys-radius-control-small);
            cursor: pointer;
            margin-top: 1rem;
        }

        button:hover {
            background: var(--orange);
        }

        button:disabled {
            background: var(--gray);
            cursor: not-allowed;
        }

        .result {
            margin-top: 1rem;
            padding: var(--zenbu-sys-padding-md);
            background: white;
            border-radius: var(--zenbu-sys-radius-control-small);
            display: none;
        }

        .result.show {
            display: block;
        }

        .result.success {
            border-left: 4px solid var(--blue);
        }

        .result.error {
            border-left: 4px solid var(--red);
        }

        .download-link {
            display: inline-block;
            margin-top: 0.5rem;
            color: var(--awesome);
            text-decoration: none;
        }

        .download-link:hover {
            text-decoration: underline;
        }

        .loading {
            display: none;
            margin-top: 1rem;
        }

        .loading.show {
            display: block;
        }

        /* Mobile responsive */
        @media (max-width: 720px) {
            .container {
                padding: var(--zenbu-sys-padding-md);
                margin: 1rem auto;
            }

            .converter-section {
                padding:
                  var(--zenbu-sys-padding-lg)
                  var(--zenbu-sys-padding-md);
            }

            .converter-section h2 {
                font-size: var(--zenbu-sys-font-size-2xl);
            }

            .file-input-wrapper label {
                font-size: var(--zenbu-sys-font-size-md);
            }


            .result {
                padding: var(--zenbu-sys-padding-md);
                font-size: var(--zenbu-sys-font-size-md);
            }
        }
    </style>
</head>
<body>
    <style>
  :root {
    --header-background: var(--white);
    --header-color: var(--black);
    --link-hover-accent: var(--awesome);
  }

  #themeControl {
    position: fixed;
    top: 20px;
    left: 20px;
    z-index: 1000;
    transition: transform 0.2s ease;
  }

  #themeControl:hover {
    transform: scale(1.05);
  }

  #themeToggle {
    display: flex;
    flex-direction: column;
    padding: 0;
    border: 0;
    background: transparent;
  }

  /* Professional header */
  header {
    margin: auto;
    padding: 1.5em 1em;
    font-family: "More", sans-serif;
    width: 720px;
    max-width: calc(100% - 2em);
    text-align: center;
  }

  header h1 {
    margin: 0;
    font-size: 1.8em;
    font-weight: 700;
    letter-spacing: -0.5px;
  }

  header h1 a {
    text-decoration: none;
    color: var(--header-color);
  }

  header h1 a::before {
    display: none;
  }

  /* Mobile responsiveness */
  @media (max-width: 720px) {
    #themeControl {
      top: 15px;
      left: 15px;
    }

    header {
      padding: 1em;
    }

    header h1 {
      font-size: 1.5em;
    }
  }

  @media (max-width: 480px) {
    #themeControl {
      top: 10px;
      left: 10px;
    }

    #themeToggle img {
      height: 40px;
      width: 40px;
    }

    header h1 {
      font-size: 1.3em;
    }
  }

  #logo {
    width: 300px;
  }

  /* 1. DEFINE THE DEFAULTS (Light Mode) */
  :root {
    --logo-invert: invert(0);
    --epi-grayscale: grayscale(0) brightness(1);
  }
  
  /* 2. MANUAL DARK OVERRIDE */
  html[data-zen-theme="ink"] {
    --logo-invert: invert(1);
    --epi-grayscale: grayscale(1);
  }
  
  /* 3. MANUAL LIGHT OVERRIDE */
  html[data-zen-theme="paper"] {
    --logo-invert: invert(0);
    --epi-grayscale: brightness(2.9) grayscale(1);
  }

  html[data-zen-theme="playful"] {
    --logo-invert: invert(0);
    --epi-grayscale: saturate(1.25);
  }
  
  /* 4. SYSTEM PREFERENCE */
  @media (prefers-color-scheme: dark) {
    :root:not([data-zen-theme]) {
      --logo-invert: invert(1);
    }
  }
  
  /* 5. APPLY TO ELEMENTS */
  #logo {
    -webkit-filter: var(--logo-invert);
    filter: var(--logo-invert);
    transition: filter 0.3s ease;
  }
  
  .epi-logo {
    -webkit-filter: var(--epi-grayscale);
    filter: var(--epi-grayscale);
    transition: filter 0.3s ease;
  }
</style>

<zen-button id="themeControl" appearance="plain" size="xl">
  <button
    id="themeToggle"
    type="button"
    aria-label="Change site theme"
  >
    <img
      id="epiChan"
      class="epi-logo"
      alt=""
      src="/public/epi_all_colors.svg"
      height="50"
      width="50"
    >
    <span id="themeName" class="zen-visually-hidden" aria-live="polite">Auto</span>
  </button>
</zen-button>

<header>
  <h1><a href="/" data-zen-link-effect="none">MrJuneJune</a></h1>
</header>
<script src="/index.js"></script>


    <div class="container">
        <h1>File Format Converter</h1>
        <p>Convert your images and videos to different formats using FFmpeg</p>

        <div class="converter-section">
            <h2>Image to WebP Converter</h2>
            <p>Upload an image file (PNG, JPG, GIF, etc.) to convert it to WebP format</p>

            <div class="file-input-wrapper">
                <label for="imageInput">Choose an image file:</label>
                <zen-input appearance="plain" size="md">
                  <input type="file" id="imageInput" accept="image/*">
                </zen-input>
            </div>

            <zen-button appearance="plain" size="md">
              <button id="convertImageBtn" onclick="convertImageToWebP()">Convert to WebP</button>
            </zen-button>

            <div class="loading" id="imageLoading">Converting... Please wait.</div>

            <div class="result" id="imageResult">
                <p id="imageMessage"></p>
                <a id="imageDownload" class="download-link" style="display: none;">Download WebP Image</a>
            </div>
        </div>

        <div class="converter-section">
            <h2>Video to MP4 Converter</h2>
            <p>Upload a video file (AVI, MOV, MKV, etc.) to convert it to MP4 format</p>

            <div class="file-input-wrapper">
                <label for="videoInput">Choose a video file:</label>
                <zen-input appearance="plain" size="md">
                  <input type="file" id="videoInput" accept="video/*">
                </zen-input>
            </div>

            <zen-button appearance="plain" size="md">
              <button id="convertVideoBtn" onclick="convertVideoToMP4()">Convert to MP4</button>
            </zen-button>

            <div class="loading" id="videoLoading">Converting... Please wait.</div>

            <div class="result" id="videoResult">
                <p id="videoMessage"></p>
                <a id="videoDownload" class="download-link" style="display: none;">Download MP4 Video</a>
            </div>
        </div>
        <div style="display: flex; align-items: center; justify-content: center; margin: 30px 0px;">
  <small>&copy; 2026 June Park</small>
</div>

    </div>
    <script src="/tools/file_converter/index.js"></script>
</body>
</html>