  /* ---- Self-hosted fonts ----
     Previously loaded from fonts.googleapis.com, which told Google every
     visitor's IP and page on every load - an odd footnote for a site whose
     pitch is that nothing about you goes anywhere. Served from here instead,
     the page makes no third-party requests at all. Both faces are variable
     fonts under the SIL Open Font License; the licences sit next to the
     files in /fonts. */
  @font-face {
    font-family: "Fraunces";
    font-style: normal;
    font-display: swap;
    font-weight: 100 900;
    src: url(/fonts/fraunces-latin-opsz-normal.woff2) format("woff2-variations");
    unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
  }
  @font-face {
    font-family: "Instrument Sans";
    font-style: normal;
    font-display: swap;
    font-weight: 400 700;
    src: url(/fonts/instrument-sans-latin-wght-normal.woff2) format("woff2-variations");
    unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
  }

  /* ---- Tokens: dark-first (the brand default), light = parchment ---- */
  :root {
    --bg: #141120;
    --bg-glow: #1a1530;
    --surface: #1d1832;
    --surface-2: #262040;
    --border: #322a52;
    --text: #edeaf6;
    --muted: #9b94b8;
    --accent: #8b5cf6;
    --accent-strong: #a37ff8;
    --accent-soft: rgba(139, 92, 246, 0.14);
    --gold: #e8b44f;
    --danger: #f0918d;
    --shadow: 0 20px 60px rgba(0, 0, 0, 0.45);
    --focus-ring: 0 0 0 3px rgba(139, 92, 246, 0.45);
  }
  @media (prefers-color-scheme: light) {
    :root:not([data-theme="dark"]) {
      --bg: #f6f2e9;
      --bg-glow: #f0eadd;
      --surface: #fffdf7;
      --surface-2: #f3eee2;
      --border: #ddd4c2;
      --text: #241f38;
      --muted: #6e6787;
      --accent: #6d3fd4;
      --accent-strong: #5a2fc0;
      --accent-soft: rgba(109, 63, 212, 0.10);
      --gold: #b3801e;
      --danger: #b3403b;
      --shadow: 0 16px 44px rgba(60, 45, 20, 0.12);
      --focus-ring: 0 0 0 3px rgba(109, 63, 212, 0.35);
    }
  }
  :root[data-theme="light"] {
    --bg: #f6f2e9;
    --bg-glow: #f0eadd;
    --surface: #fffdf7;
    --surface-2: #f3eee2;
    --border: #ddd4c2;
    --text: #241f38;
    --muted: #6e6787;
    --accent: #6d3fd4;
    --accent-strong: #5a2fc0;
    --accent-soft: rgba(109, 63, 212, 0.10);
    --gold: #b3801e;
    --danger: #b3403b;
    --shadow: 0 16px 44px rgba(60, 45, 20, 0.12);
    --focus-ring: 0 0 0 3px rgba(109, 63, 212, 0.35);
  }

  * { box-sizing: border-box; }
  /* A class that sets display (grid, flex) outranks the user-agent's
     [hidden] { display: none }, so hidden elements would still paint. */
  [hidden] { display: none !important; }
  body {
    background: var(--bg);
    background-image: radial-gradient(ellipse 70% 45% at 50% -5%, var(--bg-glow), transparent 70%);
    color: var(--text);
    font-family: "Instrument Sans", "Segoe UI", system-ui, sans-serif;
    font-size: 16px;
    line-height: 1.55;
    min-height: 100vh;
    display: flex;
    flex-direction: column;
    align-items: center;
    padding: 0 20px;
  }

  header {
    width: 100%;
    max-width: 640px;
    padding: 28px 0 0;
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 12px;
  }
  .wordmark {
    color: inherit;
    text-decoration: none;
    font-family: "Fraunces", Georgia, serif;
    font-weight: 600;
    font-size: 1.35rem;
    letter-spacing: 0.01em;
    display: flex;
    align-items: baseline;
    gap: 8px;
  }
  .wordmark .hat-icon { color: var(--accent); align-self: center; transform: translateY(1px); }
  .pair-tag {
    font-size: 0.72rem;
    font-weight: 600;
    letter-spacing: 0.09em;
    text-transform: uppercase;
    color: var(--muted);
    border: 1px solid var(--border);
    border-radius: 999px;
    padding: 4px 12px;
    white-space: nowrap;
  }
  /* nowrap plus the wordmark overflows a 375px viewport, and the register
     below states the same count twice over. */
  @media (max-width: 460px) {
    .pair-tag { display: none; }
  }

  main {
    width: 100%;
    max-width: 640px;
    flex: 1;
    display: flex;
    flex-direction: column;
    justify-content: center;
    padding: 32px 0 40px;
  }

  h1 {
    font-family: "Fraunces", Georgia, serif;
    font-weight: 500;
    font-size: clamp(1.7rem, 5vw, 2.3rem);
    line-height: 1.15;
    text-align: center;
    margin: 0 0 10px;
    text-wrap: balance;
  }
  .lede {
    text-align: center;
    color: var(--muted);
    margin: 0 0 30px;
    font-size: 0.98rem;
  }

  /* ---- Drop zone ---- */
  .dropzone {
    position: relative;
    border: 1.5px dashed var(--border);
    border-radius: 18px;
    background: var(--surface);
    box-shadow: var(--shadow);
    padding: 56px 28px;
    text-align: center;
    cursor: pointer;
    transition: border-color 160ms ease, box-shadow 160ms ease, background 160ms ease;
    outline: none;
  }
  .dropzone:hover, .dropzone:focus-visible { border-color: var(--accent); }
  .dropzone:focus-visible { box-shadow: var(--shadow), var(--focus-ring); }
  .dropzone.dragover {
    border-color: var(--accent);
    background: linear-gradient(var(--accent-soft), var(--accent-soft)), var(--surface);
    box-shadow: var(--shadow), 0 0 0 6px var(--accent-soft);
  }
  .dropzone .glyphs {
    font-size: 1.5rem;
    letter-spacing: 0.35em;
    margin-bottom: 14px;
    color: var(--accent);
  }
  .dropzone .primary-line { font-size: 1.12rem; font-weight: 600; margin: 0 0 6px; }
  .dropzone .secondary-line { color: var(--muted); font-size: 0.9rem; margin: 0; }
  .dropzone .secondary-line b { color: var(--text); font-weight: 500; }

  .privacy-note {
    text-align: center;
    color: var(--muted);
    font-size: 0.85rem;
    margin-top: 18px;
  }
  .privacy-note .dot { color: var(--gold); }

  /* ---- The register of supported pairs ----
     Each format is named at most twice: once as a source, once as a target.
     Listing it per-pair repeated every name up to eight times over. */
  .register-wrap { margin: 16px 0 0; }
  .register-wrap > summary {
    list-style: none;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 7px;
    padding: 6px 0;
    font-size: 0.85rem;
    color: var(--muted);
    outline: none;
    -webkit-user-select: none;
    user-select: none;
  }
  .register-wrap > summary::-webkit-details-marker { display: none; }
  .register-wrap > summary:hover { color: var(--text); }
  .register-wrap > summary:focus-visible { box-shadow: var(--focus-ring); border-radius: 8px; }
  .register-wrap > summary::after {
    content: "";
    width: 7px;
    height: 7px;
    border-right: 2px solid currentColor;
    border-bottom: 2px solid currentColor;
    transform: translateY(-2px) rotate(45deg);
    transition: transform 160ms ease;
  }
  .register-wrap[open] > summary::after { transform: translateY(1px) rotate(-135deg); }
  @media (prefers-reduced-motion: reduce) {
    .register-wrap > summary::after { transition: none; }
  }
  /* Sliding the panel by animating a measured pixel height does not work here:
     a closed <details> has not laid its content out, so there is nothing to
     measure at the moment the open begins. A grid row animated from 0fr to 1fr
     needs no measurement - the browser resolves the natural height itself. */
  .register-panel {
    display: grid;
    grid-template-rows: 0fr;
    opacity: 0;
    transition: grid-template-rows 260ms cubic-bezier(0.32, 0.72, 0, 1),
                opacity 200ms ease;
  }
  /* The clip must carry no padding: padding cannot shrink, so a padded grid
     item sets a floor the 0fr row can never collapse past. */
  .register-clip { overflow: hidden; min-height: 0; }
  .register-wrap.is-open > .register-panel { grid-template-rows: 1fr; opacity: 1; }
  @media (prefers-reduced-motion: reduce) {
    .register-panel { transition: none; }
  }
  .register {
    margin: 10px 0 0;
    border: 1px solid var(--border);
    border-radius: 14px;
    background: var(--surface);
    padding: 15px 18px;
    display: flex;
    flex-direction: column;
    gap: 15px;
  }
  .reg-group { display: flex; flex-direction: column; gap: 7px; }
  .reg-kind {
    font-size: 0.67rem;
    font-weight: 600;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--muted);
  }
  .reg-line { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
  .reg-dir {
    flex: none;
    width: 32px;
    font-size: 0.73rem;
    color: var(--muted);
  }
  .reg-chip {
    font-size: 0.71rem;
    font-weight: 600;
    letter-spacing: 0.05em;
    color: var(--text);
    background: var(--surface-2);
    border: 1px solid var(--border);
    border-radius: 999px;
    padding: 3px 9px;
    text-decoration: none;
  }
  /* Most chips link to that format's hub. The write-only ones cannot - there
     is nothing to convert from a TIFF - so they stay inert spans and say so by
     not lighting up. */
  a.reg-chip { transition: border-color 0.15s ease, color 0.15s ease; }
  a.reg-chip:hover { border-color: var(--accent); color: var(--accent-strong); }
  a.reg-chip:focus-visible { outline: none; box-shadow: var(--focus-ring); }
  span.reg-chip { color: var(--muted); }
  .reg-note { font-size: 0.73rem; color: var(--muted); }
  @media (max-width: 460px) {
    .register { padding: 14px; }
    .reg-dir { width: 100%; }
  }

  .error-note {
    margin: 18px auto 0;
    max-width: 480px;
    background: var(--surface);
    border: 1px solid var(--border);
    border-left: 3px solid var(--danger);
    border-radius: 12px;
    padding: 14px 18px;
    font-size: 0.92rem;
  }
  .error-note p { margin: 0; }
  .error-note .detected { color: var(--muted); font-size: 0.85rem; margin-top: 4px; }

  /* ---- Card (detected + result stages) ---- */
  .card {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 18px;
    box-shadow: var(--shadow);
    padding: 30px;
    position: relative;
    overflow: hidden;
  }
  .file-line {
    display: flex;
    align-items: center;
    gap: 14px;
    margin-bottom: 22px;
  }
  .file-badge {
    font-weight: 600;
    font-size: 0.78rem;
    letter-spacing: 0.06em;
    background: var(--accent-soft);
    color: var(--accent-strong);
    border-radius: 8px;
    padding: 7px 11px;
    font-variant-numeric: tabular-nums;
  }
  .file-meta { min-width: 0; }
  .file-name {
    font-weight: 600;
    font-size: 0.98rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .file-size { color: var(--muted); font-size: 0.85rem; font-variant-numeric: tabular-nums; }
  .sniff-note {
    color: var(--muted);
    font-size: 0.85rem;
    margin: -12px 0 20px;
  }
  .sniff-note.trust { color: var(--gold); }

  .convert-row { display: flex; flex-wrap: wrap; gap: 12px; align-items: center; }
  .btn {
    font: inherit;
    font-weight: 600;
    border: none;
    border-radius: 12px;
    padding: 13px 26px;
    cursor: pointer;
    transition: background 140ms ease, transform 140ms ease;
    outline: none;
  }
  .btn:focus-visible { box-shadow: var(--focus-ring); }
  .btn-primary { background: var(--accent); color: #fff; }
  .btn-primary:hover { background: var(--accent-strong); }
  .btn-primary:active { transform: scale(0.98); }
  .btn-ghost {
    background: transparent;
    color: var(--muted);
    border: 1px solid var(--border);
  }
  .btn-ghost:hover { color: var(--text); border-color: var(--muted); }
  .to-label { color: var(--muted); font-size: 0.92rem; }
  .demo-note { color: var(--muted); font-size: 0.82rem; margin: 16px 0 0; }
  .format-select { position: relative; display: inline-flex; }
  .format-select select {
    font: inherit;
    font-weight: 600;
    color: var(--text);
    background: var(--surface-2);
    border: 1px solid var(--border);
    border-radius: 12px;
    padding: 13px 44px 13px 18px;
    cursor: pointer;
    -webkit-appearance: none;
    appearance: none;
    outline: none;
    transition: border-color 140ms ease;
  }
  .format-select select:hover { border-color: var(--muted); }
  .format-select select:focus-visible { box-shadow: var(--focus-ring); }
  .format-select option { background: var(--surface); color: var(--text); }
  /* Chevron; the select itself has no native arrow once appearance is stripped. */
  .format-select::after {
    content: "";
    position: absolute;
    right: 18px;
    top: 50%;
    width: 8px;
    height: 8px;
    margin-top: -6px;
    border-right: 2px solid var(--muted);
    border-bottom: 2px solid var(--muted);
    transform: rotate(45deg);
    pointer-events: none;
  }
  #convert-btn, #batch-convert { margin-left: auto; }
  .restart-line { color: var(--muted); font-size: 0.88rem; margin: 14px 0 0; }
  .linkish {
    font: inherit;
    background: none;
    border: none;
    padding: 0;
    color: var(--muted);
    text-decoration: underline;
    text-underline-offset: 3px;
    cursor: pointer;
    outline: none;
  }
  .linkish:hover { color: var(--text); }
  .linkish:focus-visible { box-shadow: var(--focus-ring); border-radius: 4px; }
  /* Narrow screens: let the select fill the row, then Convert spans its own line
     rather than floating alone against the right edge. */
  @media (max-width: 460px) {
    .format-select { flex: 1; }
    .format-select select { width: 100%; }
    #convert-btn, #batch-convert { margin-left: 0; width: 100%; }
  }

  /* ---- Archive and batch ---- */
  .inventory { font-size: 0.92rem; margin: 0 0 18px; color: var(--text); }
  .inventory b { color: var(--accent-strong); font-weight: 600; }
  .inventory .quiet { color: var(--muted); }
  .choice-row { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; }
  .mode-row {
    display: inline-flex;
    gap: 4px;
    padding: 4px;
    margin: 0 0 16px;
    background: var(--surface-2);
    border: 1px solid var(--border);
    border-radius: 12px;
  }
  .mode-btn {
    font: inherit;
    font-size: 0.81rem;
    font-weight: 600;
    color: var(--muted);
    background: none;
    border: none;
    border-radius: 9px;
    padding: 7px 13px;
    cursor: pointer;
    outline: none;
    transition: background 140ms ease, color 140ms ease;
  }
  .mode-btn:hover { color: var(--text); }
  .mode-btn.is-active { background: var(--accent); color: #fff; }
  .mode-btn:focus-visible { box-shadow: var(--focus-ring); }
  .map-list {
    display: flex;
    flex-direction: column;
    gap: 7px;
    /* Long archives scroll inside the card rather than pushing the buttons
       off the bottom of the page. */
    max-height: 320px;
    overflow-y: auto;
    margin: 0 0 18px;
  }
  .map-row {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: center;
    gap: 12px;
    padding: 8px 12px;
    background: var(--surface-2);
    border: 1px solid var(--border);
    border-radius: 11px;
  }
  .map-label { min-width: 0; }
  .map-name {
    font-size: 0.87rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .map-count { font-size: 0.76rem; color: var(--muted); }
  .map-row select {
    font: inherit;
    font-size: 0.8rem;
    font-weight: 600;
    color: var(--text);
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 9px;
    padding: 6px 10px;
    cursor: pointer;
    outline: none;
  }
  .map-row select:focus-visible { box-shadow: var(--focus-ring); }
  .map-row.is-passthrough .map-name { color: var(--muted); }

  /* ---- Result ---- */
  .result-grid {
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    gap: 14px;
    align-items: center;
    margin-bottom: 22px;
  }
  .result-cell { text-align: center; min-width: 0; }
  .thumb-frame {
    background:
      repeating-conic-gradient(var(--surface-2) 0% 25%, transparent 0% 50%) 0 0 / 18px 18px,
      var(--surface);
    border: 1px solid var(--border);
    border-radius: 12px;
    overflow: hidden;
    display: flex;
    align-items: center;
    justify-content: center;
    height: 150px;
  }
  .thumb-frame img { max-width: 100%; max-height: 100%; display: block; }
  .cell-label {
    font-size: 0.72rem;
    font-weight: 600;
    letter-spacing: 0.09em;
    text-transform: uppercase;
    color: var(--muted);
    margin-top: 9px;
  }
  .cell-size { font-size: 0.9rem; font-variant-numeric: tabular-nums; }
  .arrow { color: var(--accent); font-size: 1.3rem; }
  .savings {
    text-align: center;
    font-size: 0.9rem;
    color: var(--muted);
    margin: -8px 0 20px;
    font-variant-numeric: tabular-nums;
  }
  .savings b { color: var(--gold); font-weight: 600; }
  /* Growing is a legitimate outcome (PNG from JPG, BMP from anything), so
     it is stated plainly rather than dressed up as a win. */
  .savings.bigger b { color: var(--muted); }
  .mesh-note {
    text-align: center;
    color: var(--text);
    font-size: 0.95rem;
    margin: 4px 0 20px;
    font-variant-numeric: tabular-nums;
  }

  .quality-row {
    display: flex;
    align-items: center;
    gap: 14px;
    margin-bottom: 22px;
    font-size: 0.9rem;
    color: var(--muted);
  }
  .quality-row label { white-space: nowrap; }
  .quality-row output { font-variant-numeric: tabular-nums; min-width: 3ch; color: var(--text); }
  input[type="range"] {
    flex: 1;
    accent-color: var(--accent);
    cursor: pointer;
  }
  input[type="range"]:focus-visible { outline: none; box-shadow: var(--focus-ring); border-radius: 4px; }

  /* minmax(0,1fr) on both outer tracks keeps them equal, so the Save button
     lands on the true centre of the card rather than the centre of the gap. */
  .action-row {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
    gap: 12px;
    align-items: center;
  }
  #save-btn { grid-column: 2; justify-self: center; }
  #again-btn { grid-column: 3; justify-self: end; }
  .save-status {
    font-size: 0.88rem;
    color: var(--muted);
    text-align: center;
    margin: 12px 0 0;
    min-height: 1.2em;
  }
  @media (max-width: 460px) {
    .action-row { grid-template-columns: 1fr; }
    #save-btn, #again-btn { grid-column: 1; justify-self: stretch; }
  }
  .save-status.ok { color: var(--gold); }
  .alpha-note { color: var(--muted); font-size: 0.82rem; margin: 16px 0 0; }

  #sparkle-canvas {
    position: absolute;
    inset: 0;
    pointer-events: none;
    z-index: 3;
  }

  footer {
    width: 100%;
    max-width: 640px;
    padding: 0 0 26px;
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 12px;
    color: var(--muted);
    font-size: 0.8rem;
  }
  footer .theme-toggle {
    font: inherit;
    background: none;
    border: none;
    color: var(--muted);
    cursor: pointer;
    text-decoration: underline;
    text-underline-offset: 3px;
    padding: 2px;
  }
  footer .theme-toggle:hover { color: var(--text); }
  footer .theme-toggle:focus-visible { outline: none; box-shadow: var(--focus-ring); border-radius: 4px; }

  @media (max-width: 540px) {
    .result-grid { grid-template-columns: 1fr; }
    .arrow { transform: rotate(90deg); justify-self: center; }
    .dropzone { padding: 42px 18px; }
    .card { padding: 22px; }
  }
  @media (prefers-reduced-motion: reduce) {
    * { transition: none !important; }
  }

  /* ---- Pair and hub page copy ----
     Only pages with something written about them carry this; it sits inside
     the drop stage, so it is there for a reader who has not converted yet and
     out of the way the moment they do. */
  .prose {
    margin: 30px 0 0;
    text-align: left;
    color: var(--muted);
    font-size: 0.94rem;
    line-height: 1.68;
  }
  .prose p { margin: 0 0 14px; }
  .prose p:last-child { margin-bottom: 0; }
  .prose h2 {
    font-family: "Fraunces", Georgia, serif;
    font-weight: 500;
    font-size: 1.08rem;
    color: var(--text);
    margin: 26px 0 8px;
  }

  /* Sibling pairs and the format hub. A niche page that ranks is only useful
     if it hands its neighbours something. */
  .related { margin: 30px 0 0; text-align: left; }
  .related h2 {
    font-size: 0.67rem;
    font-weight: 600;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--muted);
    margin: 0 0 10px;
  }
  .related ul {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-wrap: wrap;
    gap: 7px;
  }
  .related a {
    display: inline-block;
    font-size: 0.78rem;
    color: var(--text);
    text-decoration: none;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 999px;
    padding: 5px 11px;
    transition: border-color 0.15s ease, color 0.15s ease;
  }
  .related a:hover { border-color: var(--accent); color: var(--accent-strong); }
  .related a:focus-visible { outline: none; box-shadow: var(--focus-ring); }

  footer .footer-link {
    color: var(--muted);
    text-decoration: none;
  }
  footer .footer-link:hover { color: var(--text); text-decoration: underline; }
  footer .footer-link:focus-visible { outline: none; box-shadow: var(--focus-ring); border-radius: 4px; }
