@layer components {
  /* The image viewer (lib/image_viewer.js): the whole screen, black in both themes, the image fitted in the safe areas. */
  .image-viewer {
    position: fixed; inset: 0; width: 100%; height: 100%; max-width: none; max-height: none; margin: 0; padding: 0;
    border: 0; overflow: hidden; overscroll-behavior: contain; color-scheme: dark;
    background: oklch(0.12 0 0); color: oklch(0.97 0 0);
  }
  .image-viewer[open] { display: grid; grid-template-rows: auto minmax(0, 1fr); }
  .image-viewer::backdrop { background: oklch(0.12 0 0); }
  :root:has(dialog.image-viewer[open]) { overflow: hidden; }
  .image-viewer-bar {
    display: flex; align-items: center; gap: 8px;
    padding: calc(8px + var(--safe-top)) calc(12px + var(--safe-right)) 8px calc(16px + var(--safe-left));
  }
  .image-viewer-title {
    flex: 1; min-width: 0; margin: 0; font-size: 14px; font-weight: 600;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  .image-viewer-button {
    width: var(--tap); height: var(--tap); flex: none; display: inline-flex; align-items: center; justify-content: center;
    border: 0; border-radius: var(--radius-md); background: transparent; color: inherit; cursor: pointer;
  }
  .image-viewer-button:hover { background: oklch(1 0 0 / 0.12); }
  .image-viewer-button:active { background: oklch(1 0 0 / 0.2); }
  .image-viewer-button:focus-visible { outline: 2px solid oklch(0.97 0 0); outline-offset: 2px; }
  /* The stage is the image's frame: its content box is what the image may fill. */
  .image-viewer-stage {
    container-type: size; display: grid; place-items: center; min-height: 0;
    padding: 0 calc(16px + var(--safe-right)) calc(16px + var(--safe-bottom)) calc(16px + var(--safe-left));
  }
  .image-viewer-stage > img { grid-area: 1 / 1; display: block; max-width: 100%; max-height: 100%; object-fit: contain; }
  /* Original size known: the box is exactly the fitted image, never larger than the original. */
  .image-viewer[data-sized] .image-viewer-stage > img {
    width: min(100cqw, calc(var(--image-width) * 1px), calc(100cqh * var(--image-width) / var(--image-height)));
    height: auto; max-height: none; aspect-ratio: var(--image-width) / var(--image-height);
  }
  .image-viewer-preview[hidden] { display: none; }
  .image-viewer-image:not([data-loaded]) { visibility: hidden; }
  /* Optional parts, hidden unless the viewer is filled with them (a gallery, a caption, an animation). */
  .image-viewer [hidden] { display: none; }
  .image-viewer-heading { display: contents; }
  .image-viewer-count { flex: none; font-size: 14px; color: oklch(0.8 0 0); font-variant-numeric: tabular-nums; }
  .image-viewer-nav {
    position: absolute; top: 50%; translate: 0 -50%; z-index: 1; background: oklch(0 0 0 / 0.5);
    border-radius: 999px;
  }
  .image-viewer-nav--previous { left: calc(16px + var(--safe-left)); }
  .image-viewer-nav--next { right: calc(16px + var(--safe-right)); }
  .image-viewer[data-gallery] .image-viewer-stage { padding-inline: calc(72px + var(--safe-left)) calc(72px + var(--safe-right)); }
  .image-viewer-foot {
    display: flex; flex-direction: column; align-items: center; gap: 10px;
    padding: 0 calc(16px + var(--safe-right)) calc(16px + var(--safe-bottom)) calc(16px + var(--safe-left));
  }
  .image-viewer-caption { margin: 0; text-align: center; font-size: 14px; color: oklch(0.85 0 0); }
  .image-viewer-play {
    display: inline-flex; align-items: center; gap: 6px; min-height: var(--tap); padding: 0 16px;
    border: 1px solid oklch(1 0 0 / 0.25); border-radius: 999px; background: oklch(0 0 0 / 0.72); color: inherit;
    font-size: 14px; font-weight: 500; cursor: pointer;
  }
  .image-viewer-play:hover { background: oklch(1 0 0 / 0.12); }
  .image-viewer-play:focus-visible { outline: 2px solid oklch(0.97 0 0); outline-offset: 2px; }
  @media (max-width: 767px) {
    .image-viewer-nav { display: none; }
    .image-viewer[data-gallery] .image-viewer-stage { padding-inline: calc(16px + var(--safe-left)) calc(16px + var(--safe-right)); }
  }
  @media (prefers-reduced-motion: no-preference) {
    .image-viewer[open] { animation: image-viewer-in 0.14s ease-out; }
  }
  @keyframes image-viewer-in { from { opacity: 0; } }
}
