/* Picture Grid Web — flat panels like the Mac app: #F8F8F8, or dark gray in dark mode. */
:root {
  --panel: #F8F8F8;
  --card: #FFFFFF;
  --text: #1D1D1F;
  --secondary: #86868B;
  --hairline: rgba(0, 0, 0, 0.1);
  --placeholder: rgba(0, 0, 0, 0.06);
  --accent: #0A84FF;
  --bar-height: 52px;
  color-scheme: light dark;
}
@media (prefers-color-scheme: dark) {
  :root {
    --panel: #1E1E1E;
    --card: #2B2B2B;
    --text: #F5F5F7;
    --secondary: #98989D;
    --hairline: rgba(255, 255, 255, 0.12);
    --placeholder: rgba(255, 255, 255, 0.07);
  }
}

* { box-sizing: border-box; }
/* The splash while starting: the icon on light grey (dark grey in dark mode). */
.splash { position: fixed; inset: 0; z-index: 100; display: grid; place-items: center; background: #EBEBED; transition: opacity 0.4s ease; }
.splash img { width: 96px; height: 96px; border-radius: 22px; box-shadow: 0 4px 18px rgba(0, 0, 0, 0.12); }
.splash.gone { opacity: 0; pointer-events: none; }
@media (prefers-color-scheme: dark) { .splash { background: #2A2A2C; } }
/* Like an app: no text selection (menus, buttons, labels), except where you type. */
body { -webkit-user-select: none; user-select: none; -webkit-touch-callout: none; }
input, textarea { -webkit-user-select: text; user-select: text; }
html, body { margin: 0; background: var(--panel); color: var(--text); overflow-x: clip; } /* (clip, not hidden: hidden would stop the bar sticking) */
body {
  font: 15px/1.4 -apple-system, BlinkMacSystemFont, "Helvetica Neue", sans-serif;
  -webkit-font-smoothing: antialiased;
  -webkit-tap-highlight-color: transparent;
}
button { font: inherit; color: inherit; }

/* MARK: Top bar */
.bar {
  position: sticky; top: 0; z-index: 10;
  display: flex; align-items: center; gap: 4px;
  height: calc(var(--bar-height) + env(safe-area-inset-top));
  padding: env(safe-area-inset-top) max(8px, env(safe-area-inset-right)) 0 max(8px, env(safe-area-inset-left));
  background: var(--panel);
  border-bottom: 1px solid var(--hairline);
}
.bar h1 {
  flex: 1; margin: 0; font-size: 15px; font-weight: 600;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.icon-button {
  width: 44px; height: 44px; flex: none; /* (44: the smallest comfortable size for a finger) */
  display: grid; place-items: center;
  border: 0; border-radius: 10px; background: transparent; cursor: pointer;
}
.icon-button:hover:not(:disabled) { background: var(--placeholder); }
.icon-button:disabled { opacity: 0.25; cursor: default; }
.icon-button svg, .viewer-button svg { width: 20px; height: 20px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.icon-button circle { fill: currentColor; stroke: none; }

/* The ⋯ menu: like every other menu (on the shared backdrop, growing out of its button). */
.menu {
  position: fixed; right: max(8px, env(safe-area-inset-right)); top: calc(var(--bar-height) + env(safe-area-inset-top) - 4px);
  min-width: 240px; padding: 6px;
  background: var(--card); border-radius: 14px;
  box-shadow: 0 8px 30px rgba(0, 0, 0, 0.25);
  transform-origin: calc(100% - 22px) 0; animation: hold-in 0.22s cubic-bezier(0.2, 0.9, 0.3, 1.15);
}
.hold-menu-layer.closing .menu { transform: scale(0.92); transition: transform 0.14s; }
.menu button {
  display: block; width: 100%; padding: 11px 12px; text-align: left;
  border: 0; border-radius: 9px; background: none; color: var(--text); font-size: 16px; cursor: pointer;
}
/* A line above each item that has something visible before it (hidden items don't count), but
   none straight under a heading (which has its own line above). */
.menu > :not([hidden]) ~ button { border-top: 1px solid var(--hairline); border-radius: 0; }
.menu > .menu-heading + button { border-top: 0; }
.menu button:hover { background: var(--placeholder); }
.menu button[hidden] { display: none; }
.menu { max-height: calc(100vh - 90px); overflow-y: auto; }
.menu .menu-status { padding: 6px 12px 8px; font-size: 12px; color: var(--secondary); }
.menu .menu-heading { padding: 10px 12px 3px; border-top: 1px solid var(--hairline); font-size: 12px; font-weight: 600; color: var(--secondary); }
.menu hr { display: none; } /* (each item already has its own line above it) */
.menu .dot { display: inline-block; width: 9px; height: 9px; border-radius: 50%; margin-right: 8px; vertical-align: 1px; }

/* A short note at the bottom, e.g. "4 pictures per row" */
.toast {
  position: fixed; left: 50%; bottom: calc(28px + env(safe-area-inset-bottom)); z-index: 30;
  transform: translate(-50%, 10px); opacity: 0; pointer-events: none;
  /* Centred, and never wider than the screen: a long message wraps into a neat centred block
     (a pill when it's one line). */
  width: max-content; max-width: calc(100vw - 48px); box-sizing: border-box;
  padding: 8px 14px; border-radius: 18px; text-align: center; line-height: 1.3;
  background: var(--card); color: var(--text); font-size: 14px; font-weight: 500;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.18);
  transition: opacity 0.2s, transform 0.2s;
}
.toast.shown { opacity: 1; transform: translate(-50%, 0); }
body.picking .toast { bottom: calc(90px + env(safe-area-inset-bottom)); }

/* MARK: Grid — pictures keep their proportions, a fixed number per row */
/* At least a screen tall, so a short page (an empty folder) covers the one sliding away. */
main { min-height: 100vh; min-height: 100lvh; touch-action: pan-x pan-y; }
.grid {
  display: grid;
  grid-template-columns: repeat(var(--columns), minmax(0, 1fr));
  gap: var(--gap);
  padding: 0 calc(var(--gap) + env(safe-area-inset-right)) 0 calc(var(--gap) + env(safe-area-inset-left));
}
.grid:first-child { padding-top: var(--gap); }
.grid:last-child { padding-bottom: calc(var(--gap) + env(safe-area-inset-bottom)); }
.grid + .grid { margin-top: var(--gap); }

.tile {
  position: relative; width: 100%;
  border-radius: var(--radius); overflow: hidden;
  background: var(--placeholder);
  box-shadow: var(--shadow);
  cursor: pointer;
}
.tile > img, .tile > canvas, .tile > video {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; display: block;
}
.badge {
  position: absolute; right: 5px; bottom: 5px; z-index: 1;
  padding: 1px 6px; border-radius: 99px;
  background: rgba(0, 0, 0, 0.45); color: white;
  font-size: 10px; font-weight: 600; font-variant-numeric: tabular-nums;
}
.empty { min-height: var(--empty-height, 0); }

/* MARK: Folder tiles — a square card with four pictures, the name in white over them */
.folder-tile {
  position: relative; width: 100%; aspect-ratio: 1;
  background: var(--card);
  border-radius: var(--radius); overflow: hidden;
  box-shadow: var(--shadow);
  cursor: pointer;
}
.folder-tile .mosaic {
  position: absolute; inset: var(--pad);
  display: grid; grid-template: 1fr 1fr / 1fr 1fr; gap: var(--inner-gap);
  border-radius: var(--inner-radius); overflow: hidden;
}
.folder-tile .mosaic > div { position: relative; background: var(--placeholder); border-radius: var(--inner-radius); overflow: hidden; }
.folder-tile.cover .mosaic { inset: 0; grid-template: 1fr / 1fr; border-radius: 0; }
.folder-tile.cover .mosaic > div { border-radius: 0; }
/* An empty folder: one soft square with a folder outline (Lucide "folder"). */
.folder-tile.empty .mosaic { grid-template: 1fr / 1fr; }
.folder-tile .empty-mark { display: grid; place-items: center; }
.folder-tile .empty-mark svg { width: 34%; height: 34%; fill: none; stroke: var(--secondary); stroke-width: 1.5; stroke-linejoin: round; opacity: 0.6; }
.folder-tile .mosaic img, .folder-tile .mosaic canvas, .folder-tile .mosaic video {
  position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; display: block;
}
.folder-tile .name {
  position: absolute; left: var(--pad); right: var(--pad); bottom: var(--pad);
  padding: 20% 6% 5%;
  border-radius: 0 0 var(--inner-radius) var(--inner-radius);
  background: linear-gradient(transparent, rgba(0, 0, 0, 0.4));
  color: white; font: 9px "Courier New", Courier, monospace;
  text-shadow: 0 0.5px 1.5px rgba(0, 0, 0, 0.35);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.folder-tile.cover .name { left: 0; right: 0; bottom: 0; border-radius: 0; padding-left: 8%; padding-bottom: 7%; }
.folder-tile:active, .tile:active { filter: brightness(0.94); }

/* MARK: Messages (sign in, empty folders) */
.message {
  max-width: 420px; margin: 18vh auto 0; padding: 0 24px; text-align: center;
}
.message h2 { margin: 0 0 6px; font-size: 20px; }
.message p { margin: 0 0 18px; color: var(--secondary); }
.button {
  display: inline-block; padding: 9px 18px; border: 0; border-radius: 9px;
  background: var(--accent); color: white; font-weight: 600; cursor: pointer;
}
.button.plain { background: var(--placeholder); color: var(--text); }
.chooser { max-width: 520px; margin: 24px auto; padding: 0 16px; }
.chooser .path { color: var(--secondary); margin-bottom: 10px; word-break: break-all; }
.chooser ul { list-style: none; margin: 0 0 18px; padding: 0; border: 1px solid var(--hairline); border-radius: 10px; overflow: hidden; background: var(--card); }
.chooser li { padding: 11px 14px; border-top: 1px solid var(--hairline); cursor: pointer; display: flex; justify-content: space-between; }
.chooser li:first-child { border-top: 0; }
.chooser li:hover { background: var(--placeholder); }
.chooser .tag { color: var(--accent); font-size: 12px; }
.chooser .actions { display: flex; gap: 8px; justify-content: flex-end; }

/* MARK: Viewer */
.viewer {
  position: fixed; inset: 0; z-index: 20;
  touch-action: none;
}
/* The viewer's background: it fades as you swipe down, showing the folder behind. */
.viewer-backdrop { position: absolute; inset: 0; background: var(--panel); }
.viewer.dragging .viewer-button, .viewer.dragging .viewer-share { opacity: 0; pointer-events: none; }
/* Three slides side by side (previous, current, next); the row follows your finger. */
.viewer-track { position: absolute; inset: 0; display: flex; will-change: transform; }
.viewer-stage { position: relative; flex: 0 0 100%; overflow: hidden; display: grid; place-items: center; padding: max(24px, env(safe-area-inset-top)) 24px max(24px, env(safe-area-inset-bottom)); }
/* Pictures and videos: centred in their slide, as large as fits (never taller or wider). */
.viewer-stage > img, .viewer-stage > canvas, .viewer-stage > video {
  position: absolute; inset: 0; margin: auto; display: block;
  width: auto; height: auto; object-fit: contain;
  max-width: calc(100% - 48px);
  max-height: calc(100% - max(24px, env(safe-area-inset-top)) - max(24px, env(safe-area-inset-bottom)));
}
.viewer-button {
  position: absolute; width: 40px; height: 40px; border: 0; border-radius: 50%;
  display: grid; place-items: center; cursor: pointer;
  background: var(--card); color: var(--text);
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.15);
  transition: opacity 0.2s;
}
.viewer-button.close { top: calc(14px + env(safe-area-inset-top)); left: calc(14px + env(safe-area-inset-left)); }
.viewer-button.prev { left: 14px; top: 50%; transform: translateY(-50%); }
.viewer-button.next { right: 14px; top: 50%; transform: translateY(-50%); }
.viewer.chrome-hidden .viewer-button { opacity: 0; pointer-events: none; }
@media (hover: none) { .viewer-button.prev, .viewer-button.next { display: none; } }
/* With a mouse, the arrows show at the sides: pictures leave room for them. */
@media (hover: hover) { .viewer-stage > img, .viewer-stage > canvas, .viewer-stage > video { max-width: calc(100% - 136px); } }
.spinner {
  width: 22px; height: 22px; border-radius: 50%;
  border: 2px solid var(--placeholder); border-top-color: var(--secondary);
  animation: spin 0.8s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* ?timings */
.timings {
  position: fixed; left: 8px; bottom: calc(8px + env(safe-area-inset-bottom)); z-index: 40; margin: 0;
  padding: 8px 10px; border-radius: 8px; max-width: calc(100vw - 16px); overflow: hidden;
  background: rgba(0, 0, 0, 0.75); color: #9f9; font: 11px/1.45 ui-monospace, Menlo, monospace;
  pointer-events: none; white-space: pre;
}
.viewer-stage > img.preview { filter: blur(0.4px); }


/* Share buttons, bottom right of the viewer */
.viewer-share { position: absolute; right: calc(14px + env(safe-area-inset-right)); bottom: calc(14px + env(safe-area-inset-bottom)); display: flex; gap: 10px; transition: opacity 0.2s; }
.viewer-share .viewer-button { position: relative; }
.viewer.chrome-hidden .viewer-share { opacity: 0; pointer-events: none; }
.viewer-button.busy svg { opacity: 0.25; }
.viewer-button.busy::after {
  content: ""; position: absolute; inset: 3px; border-radius: 50%;
  border: 2px solid transparent; border-top-color: var(--accent); animation: spin 0.8s linear infinite;
}
.viewer-button.ready { background: var(--accent); color: white; }

.menu button:disabled { color: var(--secondary); cursor: default; }
.menu button:disabled:hover { background: none; color: var(--secondary); }
.menu .group-item { display: flex; align-items: center; }

/* The refresh button spins while checking. */
#refresh.spinning svg { animation: spin 0.8s linear infinite; }

/* A switch in the ⋯ menu (Keep Offline): green when on, light grey when off. */
.menu button[role="switch"] { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.menu-label small { display: block; font-size: 11px; color: var(--secondary); }
.switch { position: relative; flex: none; width: 36px; height: 22px; border-radius: 11px; background: rgba(120, 120, 128, 0.22); transition: background 0.2s; }
.switch::after { content: ""; position: absolute; top: 2px; left: 2px; width: 18px; height: 18px; border-radius: 50%; background: white; box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25); transition: transform 0.2s; }
.switch.on { background: #34C759; }
.switch.on::after { transform: translateX(14px); }
.menu button[role="switch"]:hover { background: var(--placeholder); color: var(--text); }
.menu button[role="switch"]:disabled .switch { opacity: 0.55; }
.viewer-share .viewer-button[hidden] { display: none; }
/* A video's own controls, along the bottom: the scrubber across the screen, then the frame
   arrows (left), play (middle), sound and full screen (right). Its share buttons go top right. */
.video-bar { position: absolute; left: calc(16px + env(safe-area-inset-left)); right: calc(16px + env(safe-area-inset-right)); bottom: calc(12px + env(safe-area-inset-bottom)); transition: opacity 0.2s; }
.video-bar[hidden] { display: none; }
.viewer.chrome-hidden .video-bar, .viewer.dragging .video-bar { opacity: 0; pointer-events: none; }
.video-row { display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; }
.video-group { display: flex; gap: 10px; }
.video-group.right { justify-content: flex-end; }
.video-bar .viewer-button { position: relative; touch-action: manipulation; }
.play-button { width: 54px; height: 54px; }
.play-button svg { width: 24px; height: 24px; fill: currentColor; }
#video-play .when-playing, #video-play.playing .when-paused { display: none; }
#video-play.playing .when-playing { display: block; }
#video-sound .when-off, #video-sound.off .when-on { display: none; }
#video-sound.off .when-off { display: block; }
/* The scrubber: a thin track, filled up to a red needle topped with a ball to grab. The whole
   strip responds, not just the ball; dragging makes the ball bigger and shows the time. */
.scrubber { position: relative; height: 46px; margin: 0 14px 6px; touch-action: none; cursor: pointer; --at: 0; }
.scrub-track { position: absolute; left: 0; right: 0; top: 30px; height: 5px; border-radius: 3px; background: rgba(120, 120, 128, 0.28); overflow: hidden; }
.scrub-played { height: 100%; width: calc(var(--at) * 100%); background: rgba(120, 120, 128, 0.75); }
.scrub-needle { position: absolute; top: 8px; left: calc(var(--at) * 100%); width: 0; height: 34px; pointer-events: none; }
.scrub-needle::before { content: ""; position: absolute; left: -1.5px; top: 6px; bottom: 0; width: 3px; border-radius: 2px; background: #FF3B30; }
.scrub-knob { position: absolute; left: -8px; top: -2px; width: 16px; height: 16px; border-radius: 50%; background: #FF3B30; box-shadow: 0 1px 4px rgba(0, 0, 0, 0.35); transition: transform 0.15s cubic-bezier(0.2, 0.9, 0.3, 1.3); }
.scrubber.active .scrub-knob { transform: scale(1.45); }
.scrub-time { position: absolute; bottom: 42px; left: 0; transform: translateX(-50%); padding: 3px 8px; border-radius: 8px; background: var(--card); box-shadow: 0 1px 6px rgba(0, 0, 0, 0.2); font-size: 13px; font-variant-numeric: tabular-nums; white-space: nowrap; opacity: 0; transition: opacity 0.15s; }
.scrubber.active .scrub-time { opacity: 1; }
/* The video itself sits between the top buttons and these controls. */
.viewer-stage.video-slide > img, .viewer-stage.video-slide > video {
  top: calc(64px + env(safe-area-inset-top)); bottom: calc(128px + env(safe-area-inset-bottom));
  max-height: calc(100% - 192px - env(safe-area-inset-top) - env(safe-area-inset-bottom));
}
/* Pressed: the button dips and darkens (held arrows stay pressed while they repeat). */
.video-bar .viewer-button, .viewer-share .viewer-button { transition: opacity 0.2s, transform 0.12s, background-color 0.12s; }
.video-bar .viewer-button:active, .video-bar .viewer-button.pressed, .viewer-share .viewer-button:active { transform: scale(0.86); background: var(--placeholder); }
.viewer.is-video .viewer-share { top: calc(14px + env(safe-area-inset-top)); bottom: auto; }
.viewer.is-video .frame-choice { top: calc(66px + env(safe-area-inset-top)); bottom: auto; transform-origin: calc(100% - 70px) -32px; }
/* The frame menu's backdrop: a tap on it only closes the menu. */
.frame-choice-layer { position: absolute; inset: 0; z-index: 3; }

/* The page being left, sliding away (it sits under the top bar). */
.page-leaving { position: fixed; inset: 0; z-index: 4; pointer-events: none; overflow: hidden; }
.page-leaving-inner { position: absolute; left: 0; right: 0; min-height: 100vh; }
/* (flow-root: a message's top margin stays inside, so the background covers above it too) */
main { position: relative; z-index: 5; background: var(--panel); display: flow-root; }
/* A picture growing from its tile when opened. */
.flyer { position: fixed; z-index: 1; object-fit: cover; pointer-events: none; }


/* Adding pictures: progress at the bottom, and a ring on the + button while it works. */
.progress-note {
  position: fixed; left: 50%; bottom: calc(24px + env(safe-area-inset-bottom)); z-index: 30; transform: translateX(-50%);
  width: min(320px, calc(100vw - 32px)); padding: 10px 14px 12px; border-radius: 14px;
  background: var(--card); box-shadow: 0 2px 12px rgba(0, 0, 0, 0.18); font-size: 14px; font-weight: 500; text-align: center;
}
.progress-bar { margin-top: 8px; height: 4px; border-radius: 2px; background: var(--placeholder); overflow: hidden; }
.progress-bar > div { height: 100%; width: 0; background: var(--accent); border-radius: 2px; transition: width 0.2s; }
#add.spinning-ring { position: relative; }
#add.spinning-ring svg { opacity: 0.3; }
#add.spinning-ring::after { content: ""; position: absolute; inset: 7px; border-radius: 50%; border: 2px solid transparent; border-top-color: var(--accent); animation: spin 0.8s linear infinite; }
.icon-button[hidden] { display: none; }

/* After extracting a frame: add it to the folder, or share it. */
.frame-choice {
  position: absolute; right: calc(14px + env(safe-area-inset-right)); bottom: calc(66px + env(safe-area-inset-bottom)); z-index: 3;
  width: 230px; padding: 6px; border-radius: 14px; background: var(--card); box-shadow: 0 6px 24px rgba(0, 0, 0, 0.22);
  /* It grows out of the scissors below it (the middle of the three buttons, 70px from the right). */
  transform-origin: calc(100% - 70px) calc(100% + 32px);
  animation: hold-in 0.24s cubic-bezier(0.2, 0.9, 0.3, 1.15);
}
.frame-choice-title { padding: 6px 10px 8px; font-size: 12px; color: var(--secondary); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.frame-choice button { display: block; width: 100%; padding: 10px; border: 0; border-radius: 9px; background: none; text-align: left; font-size: 15px; cursor: pointer; }
.frame-choice button:hover { background: var(--placeholder); }
.frame-choice button.cancel { color: var(--secondary); }

/* The viewer's Edit button, top right. */
.viewer-button.edit-button { top: calc(14px + env(safe-area-inset-top)); right: calc(14px + env(safe-area-inset-right)); width: auto; padding: 0 16px; border-radius: 20px; font-size: 15px; font-weight: 600; }
.viewer-button[hidden] { display: none; }

/* MARK: The editor */
.editor { position: fixed; inset: 0; z-index: 40; display: flex; flex-direction: column; background: var(--panel); touch-action: none; user-select: none; -webkit-user-select: none; }
/* Opening and closing: the editor fades in and out, its bars slide in from and out to the edges. */
.editor { animation: editor-fade 0.28s ease-out; }
.editor .editor-top { animation: editor-from-top 0.3s cubic-bezier(0.2, 0.8, 0.2, 1); }
.editor .editor-tools { animation: editor-from-bottom 0.3s cubic-bezier(0.2, 0.8, 0.2, 1); }
@keyframes editor-fade { from { opacity: 0; } }
@keyframes editor-from-top { from { transform: translateY(-100%); } }
@keyframes editor-from-bottom { from { transform: translateY(100%); } }
.editor.closing { opacity: 0; pointer-events: none; transition: opacity 0.28s ease 0.04s; }
.editor.closing .editor-top { transform: translateY(-100%); transition: transform 0.28s ease-in; }
.editor.closing .editor-tools, .editor.closing .editor-panel { transform: translateY(100%); transition: transform 0.28s ease-in; }
.editor.closing .editor-stage { transform: scale(0.97); transition: transform 0.3s ease; }
.editor-top { display: flex; align-items: center; justify-content: space-between; height: calc(52px + env(safe-area-inset-top)); padding: env(safe-area-inset-top) 12px 0; border-bottom: 1px solid var(--hairline); }
.editor-title { font-weight: 600; }
.editor-text { border: 0; background: none; font-size: 16px; padding: 8px 6px; cursor: pointer; color: var(--text); }
.editor-text.strong { color: var(--accent); font-weight: 600; }
.editor-stage { position: relative; flex: 1; overflow: hidden; }
.editor-image { position: absolute; display: block; }
.editor-guide { position: absolute; pointer-events: none;
  background:
    linear-gradient(to right, transparent calc(33.33% - 0.5px), rgba(90, 200, 250, 0.85) calc(33.33% - 0.5px), rgba(90, 200, 250, 0.85) calc(33.33% + 0.5px), transparent calc(33.33% + 0.5px), transparent calc(66.66% - 0.5px), rgba(90, 200, 250, 0.85) calc(66.66% - 0.5px), rgba(90, 200, 250, 0.85) calc(66.66% + 0.5px), transparent calc(66.66% + 0.5px)),
    linear-gradient(to bottom, transparent calc(33.33% - 0.5px), rgba(90, 200, 250, 0.85) calc(33.33% - 0.5px), rgba(90, 200, 250, 0.85) calc(33.33% + 0.5px), transparent calc(33.33% + 0.5px), transparent calc(66.66% - 0.5px), rgba(90, 200, 250, 0.85) calc(66.66% - 0.5px), rgba(90, 200, 250, 0.85) calc(66.66% + 0.5px), transparent calc(66.66% + 0.5px)); }
.crop-box { position: absolute; border: 1.5px solid #5AC8FA; box-shadow: 0 0 0 9999px rgba(0, 0, 0, 0.45); cursor: move; touch-action: none; }
.crop-grid { position: absolute; inset: 0; pointer-events: none;
  background:
    linear-gradient(to right, transparent calc(33.33% - 0.5px), rgba(255, 255, 255, 0.7) calc(33.33% - 0.5px), rgba(255, 255, 255, 0.7) calc(33.33% + 0.5px), transparent calc(33.33% + 0.5px), transparent calc(66.66% - 0.5px), rgba(255, 255, 255, 0.7) calc(66.66% - 0.5px), rgba(255, 255, 255, 0.7) calc(66.66% + 0.5px), transparent calc(66.66% + 0.5px)),
    linear-gradient(to bottom, transparent calc(33.33% - 0.5px), rgba(255, 255, 255, 0.7) calc(33.33% - 0.5px), rgba(255, 255, 255, 0.7) calc(33.33% + 0.5px), transparent calc(33.33% + 0.5px), transparent calc(66.66% - 0.5px), rgba(255, 255, 255, 0.7) calc(66.66% - 0.5px), rgba(255, 255, 255, 0.7) calc(66.66% + 0.5px), transparent calc(66.66% + 0.5px)); }
.crop-handle { position: absolute; width: 34px; height: 34px; margin: -17px; }
.crop-handle::after { content: ""; position: absolute; inset: 11px; border-radius: 3px; background: #5AC8FA; box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3); }
.h-lt { left: 0; top: 0; cursor: nwse-resize; } .h-rt { left: 100%; top: 0; cursor: nesw-resize; }
.h-lb { left: 0; top: 100%; cursor: nesw-resize; } .h-rb { left: 100%; top: 100%; cursor: nwse-resize; }
.h-l { left: 0; top: 50%; cursor: ew-resize; } .h-r { left: 100%; top: 50%; cursor: ew-resize; }
.h-t { left: 50%; top: 0; cursor: ns-resize; } .h-b { left: 50%; top: 100%; cursor: ns-resize; }
.h-l::after, .h-r::after { inset: 8px 13px; } .h-t::after, .h-b::after { inset: 13px 8px; }
.editor-panel { display: flex; flex-direction: column; justify-content: flex-end; overflow: hidden; border-top: 1px solid var(--hairline); }
.editor-panel-inner { flex: none; display: flex; flex-wrap: wrap; gap: 8px; justify-content: center; padding: 12px 14px; }
.editor-panel-inner .editor-tool { flex: 1 1 0; min-width: 0; }
/* Crop: corner pin (left) and landscape / portrait (right) above a slider of proportions. */
.crop-top { display: flex; justify-content: space-between; width: 100%; }
.round-tool { width: 40px; height: 40px; border: 0; border-radius: 50%; display: grid; place-items: center; background: var(--placeholder); color: var(--text); cursor: pointer; transition: background 0.15s, color 0.15s, transform 0.12s; }
.round-tool:active { transform: scale(0.9); }
.round-tool.on { background: var(--accent); color: white; }
.round-tool:disabled { opacity: 0.35; cursor: default; }
.round-tool svg { width: 22px; height: 22px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.aspect-slider { position: relative; width: 100%; height: 50px; touch-action: none; cursor: pointer; --n: 5; }
.aspect-slider.off { opacity: 0.35; pointer-events: none; }
.aspect-track { position: absolute; left: 18px; right: 18px; top: 12px; height: 2px; border-radius: 1px; background: rgba(120, 120, 128, 0.4); }
.aspect-tick, .aspect-label, .aspect-knob { position: absolute; left: calc(18px + (100% - 36px) * var(--i) / var(--n)); transform: translateX(-50%); }
.aspect-tick { top: 7px; width: 2px; height: 12px; border-radius: 1px; background: rgba(120, 120, 128, 0.55); }
.aspect-label { top: 26px; padding: 4px 6px; border: 0; background: none; font-size: 12px; font-weight: 600; letter-spacing: 0.02em; color: var(--secondary); cursor: pointer; }
.aspect-label.on { color: var(--text); }
.aspect-knob { top: 4px; width: 18px; height: 18px; border-radius: 50%; background: var(--accent); box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3); pointer-events: none; transition: left 0.2s cubic-bezier(0.2, 0.9, 0.3, 1.2); }
/* The corner pin: the outline over the picture, dimmed outside, a grid, four dots and a magnifier. */
.pin-layer { position: absolute; inset: 0; pointer-events: none; }
.pin-layer[hidden] { display: none; }
.pin-lines { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; }
.pin-dim { fill: rgba(0, 0, 0, 0.45); }
.pin-edge { fill: none; stroke: #5AC8FA; stroke-width: 1.5; }
.pin-grid { fill: none; stroke: rgba(255, 255, 255, 0.7); stroke-width: 0.75; }
.pin-dot { position: absolute; width: 44px; height: 44px; margin: -22px 0 0 -22px; pointer-events: auto; touch-action: none; cursor: grab; }
.pin-dot::after { content: ""; position: absolute; inset: 12px; border-radius: 50%; background: white; border: 2.5px solid #5AC8FA; box-shadow: 0 1px 4px rgba(0, 0, 0, 0.4); transition: transform 0.12s; }
.pin-dot.held::after { transform: scale(1.3); }
.pin-loupe { position: absolute; width: 112px; height: 112px; border-radius: 50%; border: 3px solid white; box-shadow: 0 4px 16px rgba(0, 0, 0, 0.4); pointer-events: none; }
.pin-loupe[hidden] { display: none; }
/* Reset: top middle of the picture's area, like Photos. */
.editor-reset { position: absolute; top: 8px; left: 50%; transform: translateX(-50%); z-index: 2; border: 0; background: none; padding: 6px 10px; font-size: 16px; font-weight: 400; color: #FFCC00; cursor: pointer; }
.editor-reset:disabled { opacity: 0.35; cursor: default; }
.editor.settling .editor-image, .editor.settling .editor-guide, .editor.settling .crop-box { transition: left 0.25s, top 0.25s, width 0.25s, height 0.25s; }
.editor-panel[hidden] { display: none; }
.chip { border: 0; border-radius: 99px; padding: 7px 13px; font-size: 14px; background: var(--placeholder); color: var(--text); cursor: pointer; }
.chip.on { background: var(--accent); color: white; }
.chip:disabled { opacity: 0.4; }
.scrub { position: relative; width: min(340px, 100%); height: 34px; border-radius: 8px; overflow: hidden; background: var(--placeholder); display: flex; align-items: center; justify-content: space-between; padding: 0 12px; font-size: 14px; cursor: ew-resize; touch-action: none; }
.scrub-fill { position: absolute; top: 0; bottom: 0; background: rgba(10, 132, 255, 0.25); }
.scrub-mid { position: absolute; left: calc(50% - 1px); top: 0; bottom: 0; width: 2px; background: rgba(120, 120, 128, 0.35); }
.scrub-title, .scrub-value { position: relative; font-variant-numeric: tabular-nums; }
.editor-tools { display: flex; gap: 2px; overflow-x: auto; padding: 8px 8px calc(8px + env(safe-area-inset-bottom)); border-top: 1px solid var(--hairline); scrollbar-width: none; }
.editor-tools::-webkit-scrollbar { display: none; }
.editor-tool { flex: 1 0 auto; min-width: 64px; display: flex; flex-direction: column; align-items: center; gap: 3px; padding: 6px 4px; border: 0; border-radius: 10px; background: none; color: var(--text); font-size: 11px; cursor: pointer; }
.editor-tool svg { width: 22px; height: 22px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.editor-tool.active { color: var(--accent); background: var(--placeholder); }

/* No browser menu (Save to Photos, Copy…) when holding a picture: the app's own instead. */
.tile, .tile img, .tile canvas, .folder-tile, .folder-tile img { -webkit-touch-callout: none; -webkit-user-select: none; user-select: none; }
.tile.held { transform: scale(1.03); transition: transform 0.15s; z-index: 1; }
.hold-menu-layer { position: fixed; inset: 0; z-index: 30; background: rgba(0, 0, 0, 0.15); }
.hold-menu { position: fixed; padding: 6px; border-radius: 14px; background: var(--card); box-shadow: 0 8px 30px rgba(0, 0, 0, 0.25); animation: hold-in 0.22s cubic-bezier(0.2, 0.9, 0.3, 1.15); }
.hold-menu-layer { animation: fade-in 0.18s ease-out; }
.hold-menu-layer.closing { opacity: 0; transition: opacity 0.14s; }
.hold-menu-layer.closing .hold-menu { transform: scale(0.92); transition: transform 0.14s; }
@keyframes hold-in { from { opacity: 0; transform: scale(0.6); } to { opacity: 1; transform: none; } }
@keyframes fade-in { from { opacity: 0; } }
/* Choosing a folder's cover: numbered pictures and a bar at the bottom. */
.pick-badge { position: absolute; top: 6px; right: 6px; z-index: 2; width: 24px; height: 24px; border-radius: 50%; display: grid; place-items: center; background: var(--accent); color: white; font-size: 13px; font-weight: 700; box-shadow: 0 0 0 2px white, 0 1px 4px rgba(0, 0, 0, 0.3); pointer-events: none; animation: hold-in 0.2s ease-out; }
body.picking .tile { cursor: pointer; }
body.picking .folder-tile { opacity: 0.4; }
.pick-bar { position: fixed; left: 12px; right: 12px; bottom: calc(12px + env(safe-area-inset-bottom)); z-index: 25; display: flex; align-items: center; gap: 8px; padding: 8px; border-radius: 14px; background: var(--card); box-shadow: 0 6px 24px rgba(0, 0, 0, 0.22); animation: pick-up 0.25s cubic-bezier(0.2, 0.9, 0.3, 1); }
@keyframes pick-up { from { transform: translateY(120%); } }
.pick-bar button { border: 0; background: none; font-size: 16px; padding: 8px 10px; color: var(--text); cursor: pointer; }
.pick-bar .pick-done { color: var(--accent); font-weight: 600; }
.pick-bar .pick-done:disabled { opacity: 0.4; }
.pick-text { flex: 1; text-align: center; font-size: 14px; font-weight: 600; line-height: 1.25; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pick-text small { display: block; font-weight: 400; color: var(--secondary); font-size: 12px; }
.hold-item { display: flex; align-items: center; justify-content: space-between; width: 100%; padding: 11px 12px; border: 0; border-radius: 9px; background: none; color: var(--text); font-size: 16px; cursor: pointer; text-align: left; }
.hold-item + .hold-item { border-top: 1px solid var(--hairline); border-radius: 0; }
.hold-separator { height: 1px; margin: 4px 0; background: var(--hairline); }
.hold-item:disabled { opacity: 0.4; cursor: default; }
.hold-item:hover { background: var(--placeholder); }
.hold-item > span:first-child { min-width: 0; margin-right: 10px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.hold-item svg { flex: none; width: 20px; height: 20px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.hold-item.busy { opacity: 0.5; }
.hold-item.ready { color: var(--accent); }

/* MARK: The app's dialog (New Folder, Sign Out, sign in again…) */
.dialog-layer { position: fixed; inset: 0; z-index: 60; display: grid; place-items: center; padding: 24px; background: rgba(0, 0, 0, 0.25); animation: fade-in 0.18s ease-out; }
.dialog-layer.closing { opacity: 0; transition: opacity 0.15s; }
.dialog { width: min(300px, 100%); padding: 20px 18px 14px; border-radius: 16px; background: var(--card); box-shadow: 0 10px 40px rgba(0, 0, 0, 0.3); text-align: center; animation: hold-in 0.22s cubic-bezier(0.2, 0.9, 0.3, 1.15); }
.dialog h3 { margin: 0 0 6px; font-size: 17px; font-weight: 600; }
.dialog p { margin: 0 0 14px; font-size: 14px; line-height: 1.35; color: var(--secondary); }
.dialog input { width: 100%; box-sizing: border-box; margin: 2px 0 14px; padding: 10px 12px; border: 1px solid var(--hairline); border-radius: 10px; background: var(--panel); color: var(--text); font: inherit; font-size: 16px; outline: none; }
.dialog input:focus { border-color: var(--accent); }
.dialog-buttons { display: flex; gap: 8px; }
.dialog-buttons button { flex: 1; padding: 11px 10px; border: 0; border-radius: 10px; font-size: 16px; cursor: pointer; }
.dialog-cancel { background: var(--placeholder); color: var(--text); }
.dialog-confirm { background: var(--accent); color: white; font-weight: 600; }
.dialog-confirm.destructive { background: #FF3B30; }

/* MARK: Rearranging: the picture being dragged (lifted, following the finger) and its place. */
.drag-ghost { position: fixed; z-index: 35; margin: 0; pointer-events: none; transform-origin: center; transform: scale(1.06); box-shadow: 0 12px 30px rgba(0, 0, 0, 0.35); transition: none; }
.drag-source { opacity: 0.25; }

/* A video that can't play yet: a spinner over it, and its controls greyed out. */
.dots-spinner svg { display: block; width: 100%; height: 100%; fill: var(--text); animation: spin 0.9s steps(12) infinite; }
/* Over the middle of the video (which sits between the top buttons and its controls). */
.video-spinner { position: absolute; left: 0; right: 0; margin: auto; z-index: 2; width: 40px; height: 40px;
  top: calc(64px + env(safe-area-inset-top)); bottom: calc(128px + env(safe-area-inset-bottom)); }
.video-spinner svg { fill: white; filter: drop-shadow(0 0 1.5px rgba(0, 0, 0, 0.35)); }
.video-spinner[hidden] { display: none; }
.video-bar.loading, #extract-frame.loading { opacity: 0.35; pointer-events: none; transition: opacity 0.25s; }

/* Press-and-hold menu: sharing and editing as a row of icons; Delete in red. */
.hold-row { display: flex; gap: 6px; padding-bottom: 6px; margin-bottom: 2px; border-bottom: 1px solid var(--hairline); }
.hold-item.hold-icon { flex: 1; justify-content: center; padding: 12px 0; border-radius: 10px; background: var(--placeholder); }
.hold-item.hold-icon + .hold-item.hold-icon { border-top: 0; border-radius: 10px; }
.hold-item.hold-icon svg { width: 22px; height: 22px; }
.hold-row + .hold-item { border-top: 0; }
.hold-separator + .hold-item { border-top: 0; }
.hold-item.danger { color: #FF3B30; }

/* A panel (tags, moving): title, a scrolling list, buttons at the bottom. */
.sheet-layer { display: grid; place-items: center; padding: 16px; }
.sheet.menu { position: static; display: flex; flex-direction: column; width: min(340px, 100%); max-height: min(70vh, 560px); min-width: 0; padding: 0; overflow: hidden; animation: hold-in 0.22s cubic-bezier(0.2, 0.9, 0.3, 1.15); transform-origin: center; }
.sheet-head { display: flex; align-items: center; gap: 4px; padding: 14px 16px 10px; border-bottom: 1px solid var(--hairline); }
.sheet-head h3 { flex: 1; margin: 0; font-size: 17px; font-weight: 600; text-align: center; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sheet-head:has(.sheet-up) { display: grid; grid-template-columns: 34px 1fr 34px; }
.sheet.menu .sheet-up { width: 34px; height: 34px; margin: -6px 0 -6px -8px; padding: 0; border: 0; border-radius: 50%; background: none; color: var(--text); display: grid; place-items: center; cursor: pointer; }
.sheet.menu .sheet-up[hidden] { display: grid; visibility: hidden; } /* (keeps the title centred) */
.sheet-up svg, .sheet-folder { width: 20px; height: 20px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.sheet-folder { flex: none; color: var(--secondary); margin-right: 10px; }
.sheet-list { flex: 1; overflow-y: auto; padding: 4px 8px; }
.sheet.menu .sheet-row { display: flex; align-items: center; width: 100%; padding: 12px 8px; border: 0; background: none; color: var(--text); font-size: 16px; text-align: left; cursor: pointer; border-radius: 0; }
.sheet.menu .sheet-row + .sheet-row { border-top: 1px solid var(--hairline); }
.sheet-label { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sheet-check { color: var(--accent); font-weight: 700; }
.sheet-chevron { color: var(--secondary); font-size: 20px; }
.sheet-empty { margin: 16px 8px; color: var(--secondary); font-size: 14px; text-align: center; }
.sheet-spinner { margin: 20px auto; }
.sheet-foot { display: flex; gap: 8px; padding: 10px 12px 12px; border-top: 1px solid var(--hairline); }
.sheet.menu .sheet-foot button { flex: 1; padding: 11px 10px; border: 0; border-radius: 10px; font-size: 16px; text-align: center; cursor: pointer; }
.sheet.menu .sheet-foot .dialog-cancel { background: var(--placeholder); color: var(--text); }
.sheet.menu .sheet-foot .dialog-confirm { background: var(--accent); color: white; font-weight: 600; }
.sheet.menu .sheet-foot button:disabled { opacity: 0.4; }

/* Selecting several: a circle on each picture, filled with a tick when chosen. */
body.selecting .grid .tile::after { content: ""; position: absolute; right: 6px; bottom: 6px; z-index: 2; width: 22px; height: 22px; box-sizing: border-box; border-radius: 50%; border: 2px solid white; background: rgba(0, 0, 0, 0.15); box-shadow: 0 1px 3px rgba(0, 0, 0, 0.35); pointer-events: none; }
body.selecting .grid .tile.selected::after { border-color: white; background: var(--accent) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='3.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E") center / 14px no-repeat; }
body.selecting .grid .tile.selected img, body.selecting .grid .tile.selected canvas { opacity: 0.75; }
.pick-bar .pick-action { width: 40px; height: 40px; padding: 0; display: grid; place-items: center; border-radius: 50%; color: var(--accent); }
.pick-bar .pick-action.danger { color: #FF3B30; }
.pick-bar .pick-action:disabled { opacity: 0.35; }
.pick-bar .pick-action svg { width: 22px; height: 22px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
/* While dragging: empty spaces (and the spare spots at the end) show as dashed outlines. */
.grid .empty.trailing { aspect-ratio: 1; }
body.rearranging .grid .empty { border-radius: var(--radius); outline: 2px dashed rgba(120, 120, 128, 0.35); outline-offset: -2px; }
