/* ============================================================================
 * app.css — Web Viewer App stylesheet
 *
 * Extracted from inline <style> in index.php (2026-06 split). One file
 * because the CSS is a tight, single-app stylesheet — splitting by topic
 * would add HTTP round-trips without making maintenance easier.
 *
 * Loaded via <link rel="stylesheet" href="css/app.css?v=N"> in index.php.
 * The ?v=N query bumps in lockstep with the JS asset versions in session.md.
 * ========================================================================= */

*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

:root {
  color-scheme: dark;
  --bg:        #141414;
  --surface:   #1e1e1e;
  --surface2:  #2a2a2a;
  --border:    #333;
  --text:      #ddd;
  --text-dim:  #aaa;
  --accent:    #0d84ff;
  --accent-bg: rgba(13,132,255,.18);
  --danger:    #e04040;
  --danger-bg: rgba(224,64,64,.18);
  --sidebar-w: 210px;
  --toolbar-h: 48px;
  --status-h:  34px;
  /* Anon justified gallery: row height (driven by thumb-size slider).
     Bleed is 0 now that flex-grow fills each row — kept as a knob in case
     we want the tease back later. */
  --tile-row-h: 200px;
  --tile-bleed: 0px;
}

html, body { height: 100%; overflow: hidden; background: var(--bg); color: var(--text);
  font: 13px/1.4 system-ui, -apple-system, sans-serif; }

#app  { display: grid; height: 100vh;
        grid-template-rows: var(--toolbar-h) 1fr var(--status-h); }
#main { display: grid; grid-template-columns: var(--sidebar-w) 4px 1fr; overflow: hidden; min-width: 0; }

/* ── RESIZE HANDLE ── */
#resize-handle { cursor: col-resize; background: var(--border); transition: background .15s; position: relative; z-index: 10; }
#resize-handle:hover, #resize-handle.dragging { background: var(--accent); }

/* ── TOOLBAR ── */
#toolbar {
  display: flex; align-items: center; gap: 8px;
  padding: 0 12px; background: var(--surface); border-bottom: 1px solid var(--border);
  min-width: 0;
}
#toolbar h1 { font-size: 15px; font-weight: 700; color: #fff; flex-shrink: 0; }
#toolbar .divider { width: 1px; height: 20px; background: var(--border); flex-shrink: 0; }
#toolbar-folder { font-size: 12px; color: var(--text-dim); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; flex: 1; min-width: 0; }

.tb-btn {
  padding: 4px 11px; border-radius: 5px; border: 1px solid var(--border);
  background: var(--surface2); color: var(--text); cursor: pointer; font-size: 12px;
  white-space: nowrap; transition: background .1s; flex-shrink: 0;
}
.tb-btn:hover  { background: #333; }
.tb-btn:active { background: #444; }
.tb-btn.danger { border-color: var(--danger); color: var(--danger); }
.tb-btn.danger:hover { background: var(--danger-bg); }
.tb-btn:disabled { opacity: .4; cursor: default; }
/* Small notification dot on the gear button when a storage compression
   job is running or sampling. Pulses gently so it draws the eye but
   doesn't shout. gallery-storage-poll.js toggles the class. */
#btn-config { position: relative; }
#btn-config.has-storage-job::after {
  content: ''; position: absolute; top: 2px; right: 2px;
  width: 8px; height: 8px; border-radius: 50%;
  background: #3b82f6; box-shadow: 0 0 0 2px var(--bg);
  animation: bf-storage-dot 1.6s ease-in-out infinite;
}
@keyframes bf-storage-dot {
  0%, 100% { opacity: 1; }
  50%      { opacity: .35; }
}
/* Subtle barber-pole stripes on the storage progress bar while running.
   The bar's inline style sets background:var(--accent); this rule layers
   a translucent diagonal stripe gradient over it and slides the gradient
   position to animate. Solid-color fallback if animation is disabled. */
#storage-progress-bar.running {
  background-image: linear-gradient(
    45deg,
    rgba(255,255,255,0.18) 25%,
    transparent             25%,
    transparent             50%,
    rgba(255,255,255,0.18) 50%,
    rgba(255,255,255,0.18) 75%,
    transparent             75%,
    transparent
  );
  background-size: 16px 16px;
  animation: bf-storage-stripes 1.2s linear infinite;
}
@keyframes bf-storage-stripes {
  0%   { background-position: 0 0; }
  100% { background-position: 16px 0; }
}
@media (prefers-reduced-motion: reduce) {
  #storage-progress-bar.running { animation: none; }
}
.tb-btn.active-mode { border-color: var(--accent); color: var(--accent); }

#admin-toolbar { display: none; align-items: center; gap: 6px; }
#admin-toolbar.visible { display: flex; }

/* ── SPLIT BUTTON ── */
.split-btn { position: relative; display: flex; flex-shrink: 0; }
.split-btn .split-main { border-right: none; border-radius: 5px 0 0 5px; padding-right: 9px; }
.split-btn .split-arrow { border-radius: 0 5px 5px 0; padding: 4px 7px; border-left: 1px solid var(--bg); }
.split-menu {
  display: none; position: absolute; top: calc(100% + 4px); left: 0;
  background: var(--surface); border: 1px solid var(--border); border-radius: 6px;
  overflow: hidden; z-index: 200; min-width: 160px;
  box-shadow: 0 4px 16px rgba(0,0,0,.4);
}
.split-menu.open { display: block; }
.split-menu-item { padding: 8px 14px; font-size: 12px; cursor: pointer; white-space: nowrap; color: var(--text);
  background: transparent; border: none; text-align: left; width: 100%; font-family: inherit;
}
.split-menu-item:hover:not(:disabled) { background: var(--surface2); }
.split-menu-item:disabled { opacity: 0.4; cursor: not-allowed; }

/* ── SIDEBAR ── */
#sidebar { background: var(--surface); border-right: 1px solid var(--border); display: flex; flex-direction: column; overflow: hidden; container-type: inline-size; container-name: sidebar; }
#sb-folders { flex: 1; min-height: 0; display: flex; flex-direction: column; }
/* 50/50 split between pinned (system items + Faces) and Albums tree.
   Each half scrolls independently; neither can push the other off-screen.
   min-height:0 lets the flex children actually shrink below content size. */
#folder-list-top { flex: 1 1 50%; min-height: 0; overflow-y: auto; box-shadow: inset 0 1px 0 0 #7d7d7d, 0 1px 0 0 #7d7d7d; }
/* When the top panel has no expandable subtree visible (Faces collapsed,
   no named groups, admin view), shrink to content so Albums claims the
   freed space instead of locking a 50% gap. */
#folder-list-top.sb-top-fit { flex: 0 1 auto; }
#folder-list { flex: 1 1 50%; min-height: 0; overflow-y: auto; padding-bottom: 8px; }
/* Shared Expand-All button (Faces header + depth-0 anon Album rows).
   Text by default, icon when sidebar is narrow. Marker classes
   (.sb-faces-expand-all, .sb-folder-expand-all) carry behavior only. */
.sb-expand-all {
  background: var(--surface2,#141414); border: 1px solid var(--border,#444);
  border-radius: 4px; color: var(--text-dim); cursor: pointer;
  padding: 2px 8px; font-size: 11px; line-height: 1.2;
}
.sb-expand-all:hover { color: var(--text); }
.sb-expand-all .sb-eax-icon { display: none; }
@container sidebar (max-width: 200px) {
  .sb-expand-all .sb-eax-text { display: none; }
  .sb-expand-all .sb-eax-icon { display: inline; }
}
.sb-heading { padding: 10px 12px 5px; font-size: 10px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--text-dim); display: flex; align-items: center; }
.sb-new-folder { margin-left: auto; background: transparent; border: none; color: var(--text-dim); cursor: pointer; font-size: 14px; line-height: 1; padding: 0 2px; border-radius: 3px; }
.sb-new-folder:hover { color: var(--text); background: rgba(255,255,255,.08); }
#folder-search-wrap { display:flex; align-items:center; margin:4px 8px 6px; background:var(--surface2); border:1px solid var(--border); border-radius:6px; padding:0 6px; }
#folder-search { flex:1; background:transparent; border:none; outline:none; color:var(--text); font-size:12px; padding:5px 4px; }
#folder-search::placeholder { color:var(--text-dim); }
#folder-search-clear { background:none; border:none; color:var(--text-dim); cursor:pointer; font-size:11px; padding:2px; display:none; }
#folder-search-clear:hover { color:var(--text); }
.sb-search-item { padding:6px 10px; cursor:pointer; border-radius:4px; margin:1px 4px; }
.sb-search-item:hover { background:var(--surface2); }
.sb-search-item .sb-sr-name { font-size:13px; color:var(--text); }
.sb-search-item .sb-sr-path { font-size:11px; color:var(--text-dim); margin-top:1px; }

.sb-item {
  display: flex; align-items: center;
  padding: 5px 12px; cursor: pointer; font-size: 12px; user-select: none;
  border-left: 2px solid transparent;
}
.sb-item:hover { background: var(--surface2); }
.sb-item.active { border-left-color: var(--accent); background: var(--accent-bg); color: #fff; }
/* Secondary highlight: folder containing the last-clicked selected photo
   in the right pane. Distinct from .active (which means "currently being
   filtered"). Used to follow selection from vfolders (Duplicates/Starred/
   Faces) back to the source gallery folder without changing the filter. */
.sb-item.contains-selected:not(.active) {
  border-left-color: var(--accent);
  background: rgba(255,255,255,.04);
}
.sb-item .sb-count { color: var(--text-dim); font-size: 11px; flex-shrink: 0; }
.sb-item.active .sb-count { color: rgba(255,255,255,.6); }
.sb-item .sb-count-sub { color: #d9a86a; opacity: .75; margin-left: 2px; font-size: 12px; }
.sb-item .sb-name  { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Large inline icon prefix for system rows (Starred, etc.) so they sit
   at roughly the same visual height as the top-level face thumbs. */
.sb-row-icon {
  display: inline-block; font-size: 22px; line-height: 1;
  width: 24px; text-align: center; margin-right: 6px; vertical-align: middle;
}
/* Tighter vertical spacing for face vFolder children (anon view). */
.sb-face-item { padding-top: 2px; padding-bottom: 2px; }
/* Top-level (depth 0) face rows carry a face-crop thumb, so they get
   more breathing room. Nested children stay compact. */
.sb-face-item.sb-face-top { padding-top: 6px; padding-bottom: 6px; }
.sb-face-thumb {
  flex-shrink: 0; width: 28px; height: 28px; border-radius: 7px;
  background-color: var(--surface2); background-size: cover;
  background-position: center; background-repeat: no-repeat;
  margin-right: 8px;
}
/* Nested face children get half-size thumbs so the parent row still
   reads as the primary anchor of the subtree. */
.sb-face-thumb.sb-face-thumb-sm {
  width: 18px; height: 18px; border-radius: 5px; margin-right: 6px;
}
/* Anon-only cover thumbs on gallery folder rows. Mirror the face-thumb
   sizing — 28px on top-level (e.g. "Stefs Photos"), 18px on every nested
   level. Cover photo is picked subtree-wide (most-starred, fallback newest
   mtime) and hydrated as a background-image post-render. */
.sb-folder-thumb {
  flex-shrink: 0; width: 28px; height: 28px; border-radius: 7px;
  background-color: var(--surface2); background-size: cover;
  background-position: center; background-repeat: no-repeat;
  margin-right: 8px;
}
.sb-folder-thumb.sb-folder-thumb-sm {
  width: 18px; height: 18px; border-radius: 5px; margin-right: 6px;
}
.sb-chevron {
  flex-shrink: 0; width: 16px; height: 16px;
  display: flex; align-items: center; justify-content: center;
  background: transparent; border: none; color: var(--text-dim);
  cursor: pointer; font-size: 8px; padding: 0; margin-right: 2px;
  border-radius: 3px; line-height: 1;
}
.sb-chevron:hover { color: var(--text); background: rgba(255,255,255,.08); }
.sb-item.active .sb-chevron { color: rgba(255,255,255,.6); }
.sb-chevron-gap { flex-shrink: 0; display: inline-block; width: 16px; margin-right: 2px; }
/* Admin folder action buttons */
.sb-admin-btn, .sb-detect {
  flex-shrink: 0; padding: 1px 5px; border-radius: 3px; border: 1px solid var(--border);
  background: transparent; color: var(--text-dim); cursor: pointer; font-size: 10px;
  opacity: 0; transition: opacity .1s; margin-left: 3px;
}
.sb-item:hover .sb-admin-btn, .sb-item:hover .sb-detect { opacity: 1; }
.sb-item.active .sb-admin-btn, .sb-item.active .sb-detect { border-color: rgba(255,255,255,.3); color: rgba(255,255,255,.7); opacity: 0; }
.sb-item.active:hover .sb-admin-btn, .sb-item.active:hover .sb-detect { opacity: 1; }
.sb-admin-btn.danger { color: var(--danger); }
.sb-admin-btn.danger:hover { border-color: var(--danger); background: var(--danger-bg); }
/* Admin lock icon — toggle folder privacy. Always-visible (unlike admin-btn
   which is hover-revealed) so admins can scan the tree at a glance to see
   which folders are private. White (subtle) when public, red when private. */
.sb-lock-btn {
  flex-shrink: 0; padding: 0 4px; margin-left: 4px;
  background: transparent; border: none; cursor: pointer;
  color: rgba(255,255,255,.45); display: inline-flex; align-items: center;
  line-height: 1; transition: color .12s;
}
.sb-lock-btn svg { display: block; }
.sb-lock-btn:hover { color: #fff; }
.sb-lock-btn.is-private { color: var(--danger); }
.sb-lock-btn.is-private:hover { color: var(--danger); }
.sb-item.active .sb-lock-btn { color: rgba(255,255,255,.7); }
.sb-item.active .sb-lock-btn.is-private { color: var(--danger); }
.sb-trash .sb-name { color: var(--text-dim); }
.sb-trash.active .sb-name { color: #fff; }
.sb-trash:hover .sb-name { color: var(--danger); }

/* ── GRID ── */
/* overflow-x: clip lets the anon justified grid bleed past the right edge
   intentionally — the tile on the right is half-visible as a "more here" tease.
   Admin grid stays inside the viewport, so clip is a no-op for them. */
#content { overflow-y: auto; overflow-x: clip; scrollbar-gutter: stable; padding: 0 10px 10px; }
#grid    { display: grid; gap: 4px; grid-template-columns: repeat(auto-fill, minmax(var(--thumb-size, 168px), 1fr)); }

/* ── JUSTIFIED GRID (anon only) ──
   Fixed row height (--tile-row-h, driven by the thumb-size slider).
   Each tile's width = rowH × (originalW / originalH) — set inline per cell.
   Container is widened past 100% by --tile-bleed so flex-wrap packs an
   extra partial tile that hangs off the right edge. --tile-bleed = 0 on
   mobile so narrow screens don't suffer the bleed. */
#grid.justified {
  display: flex; flex-wrap: wrap;
  /* gap: <row> <column> — vertical (between rows) stays at 1px,
     horizontal (between tiles in a row) is 2x. */
  gap: 4px 1px;
  grid-template-columns: unset;
  width: calc(100% + var(--tile-bleed, 0px));
}
#grid.justified .cell {
  aspect-ratio: unset;
  height: var(--tile-row-h, 200px);
  /* Base width = row height × per-cell aspect (set inline as --aspect).
     flex-grow is proportional to aspect so any leftover row-space is
     distributed across all tiles in the row, preserving their relative
     widths and eliminating right-edge gaps. max-width caps the stretch
     at 1.6× so a sparse last row doesn't blow up a single tile. */
  flex: var(--aspect, 1) 0 calc(var(--tile-row-h, 200px) * var(--aspect, 1));
  max-width: calc(var(--tile-row-h, 200px) * var(--aspect, 1) * 1.6);
  /* Anon doesn't select — kill the 2px transparent border so adjacent
     tiles sit truly 1px apart (otherwise gap+border = 5px visible). */
  border: 0;
  border-radius: 0;
}
#grid.justified .cell:hover { border: 0; }

/* ── DUPLICATE GROUPS ── */
.dup-group  { margin-bottom: 10px; background: var(--surface2); border-radius: 6px; overflow: hidden; grid-column: 1 / -1; }
.dup-header { padding: 5px 10px; font-size: 11px; color: var(--text-dim); border-bottom: 1px solid var(--border); }
.dup-thumbs { display: flex; flex-wrap: wrap; gap: 6px; padding: 8px; }
.dup-thumbs .cell { width: 210px; height: 210px; flex-shrink: 0; aspect-ratio: unset; }

.cell {
  position: relative; background: var(--surface2); border-radius: 4px;
  overflow: hidden; cursor: pointer; user-select: none;
  border: 2px solid transparent; transition: border-color .1s; aspect-ratio: 1;
}
.cell:hover   { border-color: #555; }
.cell.focused { outline: 2px solid var(--accent); outline-offset: -2px; }
.cell.selected { border-color: var(--accent); }
.cell.selected .check { opacity: 1; }
/* Brief pulse used when navigating from the Problem Reports panel to a
   photo — draws the eye to the highlighted cell after the lightbox closes. */
.cell.rep-flash { animation: cellFlash 1.8s ease-out 1; }
@keyframes cellFlash {
  0%   { box-shadow: 0 0 0 4px rgba(251,191,36,0); }
  15%  { box-shadow: 0 0 0 4px rgba(251,191,36,.85); }
  100% { box-shadow: 0 0 0 4px rgba(251,191,36,0); }
}
.cell img { width: 100%; height: 100%; object-fit: cover; display: block; background: #111; }
.cell .info {
  position: absolute; bottom: 0; left: 0; right: 0;
  background: linear-gradient(transparent, rgba(0,0,0,.75));
  padding: 16px 6px 5px; font-size: 10px; color: #ccc; line-height: 1.3;
}
.cell .info .fname { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.cell .info .fsize { color: var(--text-dim); }
.check {
  position: absolute; top: 5px; right: 5px; opacity: 0; transition: opacity .1s;
  width: 20px; height: 20px; border-radius: 50%;
  background: var(--accent); display: flex; align-items: center; justify-content: center;
  font-size: 12px; color: #fff; font-weight: 700; box-shadow: 0 1px 4px rgba(0,0,0,.4);
}
.cell-preview {
  position: absolute; top: 5px; left: 5px; opacity: 0; transition: opacity .1s;
  width: 22px; height: 22px; border-radius: 50%; border: none;
  background: rgba(0,0,0,.55); color: #fff; font-size: 12px;
  display: flex; align-items: center; justify-content: center;
  cursor: pointer; z-index: 2; padding: 0;
}
.cell:hover .cell-preview { opacity: 1; }
.cell .stars-badge {
  position: absolute; left: 0; right: 0; bottom: 0;
  background: linear-gradient(transparent, rgba(0,0,0,.75));
  padding: 14px 6px 5px; font-size: 11px; color: #fff;
  text-align: center; line-height: 1.2; pointer-events: none;
  text-shadow: 0 1px 2px rgba(0,0,0,.6);
}
.cell .stars-badge .star { color: #f5c518; margin-left: 3px; }

/* ── PAGINATION ── */
/* Sticky top of #content scroll container — always reachable while
   scrolling the grid. Background matches the page so thumbs underneath
   don't bleed through. Margin pulls it into #content's top padding. */
#pagination-top {
  position: sticky; top: 0; z-index: 5;
  display: flex; align-items: center; gap: 10px;
  padding: 8px 0 8px; margin: 0 -10px;
  padding-left: 10px; padding-right: 10px;
  background: var(--bg);
  color: var(--text-dim); font-size: 13px;
}
#pagination-top.hidden { display: none; }

/* Grid search box (left side of pagination-top row). 3-zone flex layout:
   search-wrap (flex:1, capped input inside), centered pagination controls,
   right spacer (flex:1) — equal-width flex zones keep the controls truly
   centered while the search stays left-aligned. Native type="search" gives
   the ✕ clear control in webkit; we don't render our own. */
#grid-search-wrap { flex: 1; display: flex; align-items: center; min-width: 0; }
#pagination-top-controls { display: flex; align-items: center; gap: 10px; }
#pagination-top-spacer { flex: 1; }
#grid-search {
  width: 100%; max-width: 360px;
  padding: 5px 10px;
  border-radius: 5px;
  border: 1px solid var(--border);
  background: var(--surface2);
  color: var(--text);
  font-size: 12px;
  outline: none;
}
#grid-search::placeholder { color: var(--text-dim); }
#faces-tuning-row.hidden { display: none !important; }
.fg-pot-block { margin: 0 0 10px 0; }
.fg-pot-toggle {
  display: flex; align-items: center; gap: 6px;
  width: 100%; padding: 6px 12px; margin-left: 16px;
  background: var(--surface2); border: 1px dashed var(--border);
  border-left: 4px dashed var(--accent); border-radius: 4px;
  color: var(--text-dim); font-size: 12px; font-style: italic;
  cursor: pointer; text-align: left;
}
.fg-pot-toggle:hover { background: var(--surface); color: var(--text); }
.fg-pot-toggle .fg-pot-arrow {
  display: inline-block; width: 10px; text-align: center;
  font-style: normal; color: var(--accent);
}
.fg-pot-toggle strong { color: var(--text); font-weight: 600; font-style: normal; }
.fg-pot-children { margin-top: 6px; }
.fg-pot-children.hidden { display: none; }
.fg-nest-children { margin-top: 6px; }
.fg-nest-children.hidden { display: none; }
.page-btn { padding: 5px 14px; border-radius: 5px; border: 1px solid var(--border); background: var(--surface2); color: var(--text); cursor: pointer; font-size: 12px; transition: background .1s; }
.page-btn:hover:not(:disabled) { background: #333; }
.page-btn:disabled { opacity: .4; cursor: default; }
#page-info-top { font-size: 12px; min-width: 90px; text-align: center; }

/* ── STATUS BAR ── */
#statusbar { display: flex; align-items: center; gap: 14px; padding: 0 14px; background: var(--surface); border-top: 1px solid var(--border); font-size: 12px; color: var(--text-dim); min-width: 0; }
#status-sel  { color: var(--accent); font-weight: 600; flex-shrink: 0; }
#status-info { font-size: 11px; color: var(--text-dim); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; flex: 1; }
#status-hint { margin-left: auto; font-size: 11px; flex-shrink: 0; }

/* ── LIGHTBOX ── */
#screensaver { display: none; position: fixed; inset: 0; z-index: 900; background: #000; overflow: hidden; cursor: pointer; }
#ss-hint { position: absolute; bottom: 24px; left: 50%; transform: translateX(-50%); color: rgba(255,255,255,.35); font-size: 13px; pointer-events: none; white-space: nowrap; }
.ss-card { position: absolute; top: 0; left: 0; border-radius: 6px; box-shadow: 0 8px 32px rgba(0,0,0,.8); overflow: hidden; pointer-events: auto; cursor: pointer; will-change: transform, opacity; transition: box-shadow .15s; }
.ss-card img { display: block; height: auto; }
.ss-card.ss-hovered { opacity: 1 !important; box-shadow: 0 0 0 3px #fff, 0 8px 40px rgba(0,0,0,.9); z-index: 100; cursor: grab; }
#ss-hud { position: absolute; bottom: 16px; left: 50%; transform: translateX(-50%); display: flex; gap: 20px; background: rgba(0,0,0,.65); padding: 10px 22px; border-radius: 28px; border: 1px solid rgba(255,255,255,.15); opacity: 0; transition: opacity .4s; pointer-events: none; white-space: nowrap; z-index: 200; }
#ss-hud.visible { opacity: 1; pointer-events: auto; }
.sb-divider { height: 1px; background: var(--border); margin: 6px 10px; }
#ss-folder-label { position: absolute; top: 20px; left: 24px; color: rgba(255,255,255,.7); font-size: 13px; background: rgba(0,0,0,.45); padding: 5px 14px; border-radius: 20px; border: 1px solid rgba(255,255,255,.12); pointer-events: none; z-index: 200; display: none; }
.ss-hud-group { display: flex; align-items: center; gap: 6px; }
.ss-hud-label { color: rgba(255,255,255,.5); font-size: 12px; }
.ss-hud-btn { background: rgba(255,255,255,.1); border: 1px solid rgba(255,255,255,.2); color: #fff; border-radius: 14px; padding: 4px 11px; font-size: 13px; cursor: pointer; }
.ss-hud-btn.ss-active { background: rgba(255,255,255,.28); border-color: rgba(255,255,255,.65); }
.ss-hud-btn:hover { background: rgba(255,255,255,.22); }
.ss-hud-sep { width: 1px; background: rgba(255,255,255,.2); align-self: stretch; margin: 0 4px; }
/* Screensaver mode picker (fly-out menu under toolbar button). Positioned
   by JS on open so it follows the button's current viewport position. */
#ss-menu { position: fixed; display: none; background: var(--surface); border: 1px solid var(--border); border-radius: 10px; box-shadow: 0 8px 32px rgba(0,0,0,.5); padding: 6px; z-index: 1500; min-width: 260px; }
#ss-menu.open { display: block; }
.ss-menu-opt { display: flex; flex-direction: column; background: transparent; border: 0; color: var(--text); padding: 10px 14px; border-radius: 6px; cursor: pointer; width: 100%; text-align: left; font: inherit; }
.ss-menu-opt + .ss-menu-opt { margin-top: 2px; }
.ss-menu-opt:hover { background: var(--surface2); }
.ss-menu-opt.active { background: rgba(255,255,255,.06); }
.ss-menu-opt .ss-menu-title { font-weight: 600; font-size: 13px; }
.ss-menu-opt .ss-menu-desc { font-size: 11px; color: var(--text-dim); margin-top: 2px; }
/* Polaroid mode — white-framed card, photos drop in via CSS transition.
   Padding leaves the classic bottom strip below the image. */
/* .ss-polaroid-pos = translating wrapper (absolute on the screensaver).
   .ss-polaroid = inner visible polaroid that rotates. Split exists so
   translate and rotate can run with different timing functions during
   the entry animation — translate ease-out (snap into place), rotate
   ease-in (twist concentrates near the END, like a card flipped onto
   a table). CSS transition:transform applies ONE timing to the whole
   matrix, so nesting is the only way to give the two motions distinct
   curves. position:relative on .ss-polaroid so the caption div can
   anchor to it. */
.ss-polaroid-pos { position: absolute; top: 0; left: 0; will-change: transform; }
.ss-polaroid { position: relative; background: #f5f5f0; padding: 12px 12px 48px 12px; box-shadow: 0 12px 36px rgba(0,0,0,.7); border-radius: 2px; cursor: pointer; will-change: transform; }
.ss-polaroid img { display: block; width: 100%; height: auto; }
.ss-polaroid:hover { box-shadow: 0 0 0 2px #fff, 0 12px 40px rgba(0,0,0,.9); }
/* Polaroid caption — handwritten names of the people in the photo, sat in
   the polaroid's bottom strip (the 48px-tall area below the image, in the
   padding zone). Font-size set inline per-polaroid so it scales with size.
   The 2-line clamp handles "John, Mary, and Jane" on small polaroids; the
   outer flex centers vertically inside the strip. pointer-events:none so
   clicks pass through to the polaroid (which routes to its folder). */
/* overflow:hidden on the CAPTION div (not just the span) — `align-items:
   center` lets a content-sized span overhang both top + bottom of the
   strip if its text wraps to 2 tall lines. Clipping at the strip's box
   guarantees nothing escapes the polaroid's bottom. */
.ss-polaroid-caption { position: absolute; left: 12px; right: 12px; bottom: 0; height: 48px; display: flex; align-items: center; justify-content: center; padding: 0 10px; pointer-events: none; overflow: hidden; }
/* line-height 0.9 — Caveat's EM box is loose, glyphs sit well inside it,
   so lines can pack tighter than the default 1.0-1.2 without descender
   collision. Two lines of 24px text at 0.9 = 43.2px, fits the 48px strip
   with breathing room. padding-right gives Caveat's handwriting tails
   (g, y, e, etc.) safe space before the line-clamp overflow:hidden clips. */
.ss-polaroid-caption span { font-family: 'Caveat', cursive; font-weight: 500; color: #1c1c1c; text-align: center; line-height: 0.9; max-height: 100%; padding: 0 6px 0 2px; overflow: hidden; word-break: break-word; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; }
/* Conveyor mode — 4 rows pinned to the viewport, each is a relative
   container; cells are absolutely positioned and translated by JS each
   frame. overflow:hidden clips off-screen cells while they enter/exit
   so we don't have to mask globally. pointer-events on the row so hover
   pause-on-this-row works without bubbling to siblings. */
.ss-conveyor-row { position: absolute; left: 0; right: 0; overflow: hidden; pointer-events: auto; }
.ss-conveyor-cell { position: absolute; top: 0; left: 0; cursor: pointer; will-change: transform; overflow: hidden; }
.ss-conveyor-cell img { display: block; width: 100%; height: 100%; object-fit: cover; }
.ss-conveyor-cell:hover { box-shadow: 0 0 0 2px #fff; z-index: 5; }
/* Faces showcase — two crossfading SQUARE frames, each background-image
   positioned by cropDivToFace so the face fills the frame with some context
   padding. Square because cropDivToFace forces square crops; 80vmin keeps
   the frame inside both viewport dimensions on any aspect. Large name
   overlay sits below the frame. No corner badge — the face IS the
   showcase. */
#ss-faces-stage { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; cursor: pointer; }
.ss-faces-frame { position: absolute; width: 80vmin; height: 80vmin; background-color: var(--surface2); background-size: cover; background-position: center; background-repeat: no-repeat; opacity: 0; transition: opacity 1.2s ease-in-out; border-radius: 14px; box-shadow: 0 24px 72px rgba(0,0,0,.75); }
.ss-faces-name { position: absolute; left: 0; right: 0; bottom: max(4vh, 32px); text-align: center; color: #fff; font-size: clamp(24px, 4vw, 44px); font-weight: 600; letter-spacing: .5px; text-shadow: 0 2px 18px rgba(0,0,0,.9); z-index: 200; pointer-events: none; }
.ss-faces-notice { color: rgba(255,255,255,.7); display: flex; align-items: center; justify-content: center; height: 100%; font-size: 18px; padding: 24px; text-align: center; }
#modal { display: none; position: fixed; inset: 0; z-index: 500; background: rgba(0,0,0,.88); align-items: center; justify-content: center; }
/* Peek-from-screensaver: modal must paint above #screensaver (z 900). The
   modal creates its own stacking context (position:fixed + z-index), so
   bumping #modal alone brings every child along — including modal-star,
   modal-faces-toggle, modal-all-rects, etc. Stays below post-enhance
   (10001) and compare (10002). */
#modal.ss-peek { z-index: 1100; }
#modal.open { display: flex; }
#modal-img  { max-width: 92vw; max-height: 88vh; object-fit: contain; border-radius: 4px; box-shadow: 0 8px 40px rgba(0,0,0,.6); }
#modal-info { position: fixed; bottom: 16px; left: 50%; transform: translateX(-50%); background: rgba(0,0,0,.7); padding: 6px 14px; border-radius: 20px; font-size: 12px; color: #ddd; white-space: nowrap; }
#modal-info a { color: var(--accent); text-decoration: none; margin-left: 10px; }
#modal-info a:hover { text-decoration: underline; }
#modal-select { display: none; position: fixed; bottom: 16px; right: 20px; background: rgba(0,0,0,.65); border: 1px solid rgba(255,255,255,.25); color: #ddd; font-size: 12px; cursor: pointer; padding: 6px 14px; border-radius: 20px; transition: border-color .15s, color .15s; }
#modal-select.show { display: block; }
#modal-select.is-selected { border-color: var(--accent); color: var(--accent); }
#modal-copy-path { display: none; position: fixed; bottom: 54px; right: 20px; background: rgba(0,0,0,.65); border: 1px solid rgba(255,255,255,.25); color: #ddd; font-size: 12px; cursor: pointer; padding: 6px 14px; border-radius: 20px; transition: border-color .15s, color .15s; }
#modal-copy-path.show { display: block; }
#modal-copy-path:hover { border-color: var(--accent); color: var(--accent); }
#modal-enhance { display: none; position: fixed; bottom: 92px; right: 20px; background: rgba(0,0,0,.65); border: 1px solid rgba(255,255,255,.25); color: #ddd; font-size: 12px; cursor: pointer; padding: 6px 14px; border-radius: 20px; transition: border-color .15s, color .15s; }
#modal-enhance.show { display: block; }
#modal-enhance:hover { border-color: var(--accent); color: var(--accent); }
#modal-enhance:disabled { opacity: .6; cursor: default; }
#modal-original-toggle { display: none; position: fixed; background: rgba(0,0,0,.65); border: 1px solid rgba(255,255,255,.25); color: #ddd; font-size: 12px; cursor: pointer; padding: 6px 16px; border-radius: 20px; transition: border-color .15s, color .15s; z-index: 5; white-space: nowrap; }
#modal-original-toggle.show { display: block; }
#modal-original-toggle:hover { border-color: var(--accent); color: var(--accent); }
#modal-original-toggle .mot-sep { opacity: .5; margin: 0 6px; }
#modal-original-toggle .mot-action { font-weight: 600; }
#modal-replace { display: none; position: fixed; bottom: 130px; right: 20px; background: rgba(0,0,0,.65); border: 1px solid rgba(255,255,255,.25); color: #ddd; font-size: 12px; cursor: pointer; padding: 6px 14px; border-radius: 20px; transition: border-color .15s, color .15s; }
#modal-replace.show { display: block; }
#modal-replace:hover { border-color: var(--accent); color: var(--accent); }
#modal-replace:disabled { opacity: .6; cursor: default; }
#modal-replace-keep { display: none; position: fixed; bottom: 168px; right: 20px; background: rgba(0,0,0,.65); border: 1px solid rgba(255,255,255,.25); color: #ddd; font-size: 12px; cursor: pointer; padding: 6px 14px; border-radius: 20px; transition: border-color .15s, color .15s; }
#modal-replace-keep.show { display: block; }
#modal-replace-keep:hover { border-color: var(--accent); color: var(--accent); }
#modal-replace-keep:disabled { opacity: .6; cursor: default; }
#modal-faces-toggle { display: none; position: fixed; bottom: 206px; right: 20px; background: rgba(0,0,0,.65); border: 1px solid rgba(255,255,255,.25); color: #ddd; font-size: 12px; cursor: pointer; padding: 6px 14px; border-radius: 20px; transition: border-color .15s, color .15s; }
#modal-faces-toggle.show { display: block; }
#modal-faces-toggle:hover { border-color: var(--accent); color: var(--accent); }
#modal-mark-orphans { display: none; position: fixed; bottom: 244px; right: 20px; background: rgba(0,0,0,.65); border: 1px solid rgba(239,68,68,.5); color: #fca5a5; font-size: 12px; cursor: pointer; padding: 6px 14px; border-radius: 20px; transition: border-color .15s, color .15s; }
#modal-mark-orphans.show { display: block; }
#modal-mark-orphans:hover { border-color: rgba(239,68,68,.9); color: #fecaca; }
/* Show-all overlay layered atop the lightbox photo. JS positions it to match
   #modal-img's getBoundingClientRect() (mirrors #modal-original-toggle). */
#modal-all-rects { display: none; position: fixed; pointer-events: none; z-index: 6; }
#post-enhance-overlay { display: none; position: fixed; inset: 0; z-index: 10001; background: rgba(0,0,0,.92); align-items: center; justify-content: center; }
#post-enhance-overlay.open { display: flex; }
#pe-img { max-width: 92vw; max-height: 80vh; object-fit: contain; border-radius: 4px; box-shadow: 0 8px 40px rgba(0,0,0,.6); }
#pe-hint { position: fixed; top: 16px; left: 50%; transform: translateX(-50%); background: rgba(20,20,20,.85); border: 1px solid rgba(255,255,255,.15); color: #ddd; font-size: 13px; padding: 8px 16px; border-radius: 6px; max-width: 92vw; text-align: center; }
#pe-hint strong { color: #fff; }
#pe-close { position: fixed; top: 14px; right: 18px; background: rgba(0,0,0,.5); border: none; color: #ccc; font-size: 22px; cursor: pointer; border-radius: 50%; width: 36px; height: 36px; display: flex; align-items: center; justify-content: center; }
#pe-close:hover { color: #fff; background: rgba(255,255,255,.15); }
#compare-overlay { display: none; position: fixed; inset: 0; z-index: 10002; background: rgba(0,0,0,.96); flex-direction: column; padding: 50px 20px 12px; box-sizing: border-box; }
#compare-overlay.open { display: flex; }
#cmp-close { position: fixed; top: 14px; right: 18px; background: rgba(0,0,0,.5); border: none; color: #ccc; font-size: 22px; cursor: pointer; border-radius: 50%; width: 36px; height: 36px; display: flex; align-items: center; justify-content: center; z-index: 4; }
#cmp-close:hover { color: #fff; background: rgba(255,255,255,.15); }
#cmp-title { position: fixed; top: 18px; left: 50%; transform: translateX(-50%); color: #ddd; font-size: 13px; max-width: 60vw; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
#cmp-stage { position: relative; flex: 1; width: 100%; min-height: 0; user-select: none; touch-action: none; cursor: ew-resize; overflow: hidden; }
#cmp-img-before, #cmp-img-after { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain; display: block; pointer-events: none; }
#cmp-img-before { clip-path: inset(0 50% 0 0); z-index: 2; }
#cmp-img-after { z-index: 1; }
#cmp-divider { position: absolute; top: 0; bottom: 0; left: 50%; width: 1px; background: rgba(255,255,255,.3); transform: translateX(-0.5px); z-index: 3; pointer-events: none; box-shadow: 0 0 4px rgba(0,0,0,.45); }
#cmp-stage.snapping #cmp-divider { transition: left .15s ease-out; }
#cmp-stage.snapping #cmp-img-before { transition: clip-path .15s ease-out; }
#cmp-handle { position: absolute; top: 50%; left: 50%; transform: translate(-50%,-50%); width: 42px; height: 42px; border-radius: 50%; background: #fff; color: #111; font-size: 16px; font-weight: 700; display: flex; align-items: center; justify-content: center; box-shadow: 0 2px 12px rgba(0,0,0,.6); pointer-events: auto; cursor: ew-resize; touch-action: none; }
.cmp-label { display: none; }
.cmp-dims { font-size: 10px; letter-spacing: 0; color: #bbb; margin-top: 2px; font-weight: normal; }
.cmp-label-before { left: 12px; }
.cmp-label-after { right: 12px; }
/* BEFORE / AFTER chip pickers above the stage. */
#cmp-pickers { display: flex; flex-direction: column; gap: 4px; padding: 6px 0 8px; flex-shrink: 0; }
.cmp-picker-row { display: flex; gap: 6px; align-items: center; flex-wrap: wrap; }
.cmp-picker-label { font-size: 10px; color: var(--text-dim); width: 50px; flex-shrink: 0; letter-spacing: 1px; }
.cmp-chip { font-size: 11px; padding: 4px 10px; border-radius: 12px; border: 1px solid var(--border); background: #1a1a1c; color: #ccc; cursor: pointer; }
.cmp-chip:hover { border-color: rgba(255,255,255,.35); }
.cmp-chip.active { border-color: var(--accent); background: var(--accent); color: #fff; }
/* Action bar: relatively-positioned canvas. JS pins each side's inner
   edge to the divider with a fixed gap; clamps so neither group hijacks
   off the bar's left/right edge. BEFORE anchors by `right`, AFTER by
   `left` — JS sets the pixel values; the defaults here are only a
   pre-paint fallback. */
#cmp-actions { position: relative; padding: 8px 0 4px; min-height: 50px; }
/* Negative `top` lifts each group so the label overlaps the bottom edge
   of the image above, and the buttons land just under it. */
.cmp-side { position: absolute; top: -44px; z-index: 5; display: flex; flex-direction: column; align-items: center; gap: 6px; transition: left .04s linear, right .04s linear; }
.cmp-side-before { right: 50%; }
.cmp-side-after  { left: 50%; }
.cmp-side-label { color: #fff; font-size: 13px; font-weight: 600; text-align: center; letter-spacing: .5px; white-space: nowrap; background: rgba(0,0,0,.6); padding: 4px 10px; border-radius: 4px; }
.cmp-side-dims { font-size: 10px; letter-spacing: 0; color: #bbb; margin-top: 2px; font-weight: normal; }
.cmp-side-buttons { display: flex; gap: 8px; }
#cmp-actions button { font-size: 13px; padding: 8px 16px; border-radius: 6px; border: 1px solid var(--border); background: #2a2a2c; color: #ddd; cursor: pointer; }
#cmp-actions button:disabled { opacity: .4; cursor: not-allowed; }
#cmp-actions button[id^="cmp-select"]:not(:disabled) { border-color: var(--accent); background: var(--accent); color: #fff; }
#cmp-actions button[id^="cmp-delete"]:not(:disabled) { color: #d99; }
#cmp-actions #cmp-approve { border-color: var(--accent); background: var(--accent); color: #fff; }
#enhance-dialog { display: none; position: fixed; inset: 0; z-index: 10000; background: rgba(0,0,0,.6); align-items: center; justify-content: center; }
#enhance-dialog.open { display: flex; }
#enhance-dialog .ed-box { background: #1d1d1f; border: 1px solid rgba(255,255,255,.15); border-radius: 10px; padding: 18px 20px; width: 760px; max-width: 94vw; max-height: 88vh; display: flex; flex-direction: column; box-shadow: 0 12px 40px rgba(0,0,0,.5); }
#enhance-dialog h3 { margin: 0 0 4px; font-size: 15px; color: #eee; }
#enhance-dialog .ed-sub { margin: 0 0 12px; font-size: 12px; color: #999; word-break: break-all; }
#enhance-dialog .ed-body { display: flex; gap: 12px; flex: 1; min-height: 0; }
#enhance-dialog .ed-library { width: 260px; flex-shrink: 0; display: flex; flex-direction: column; border: 1px solid rgba(255,255,255,.1); border-radius: 6px; background: #111; min-height: 280px; }
#enhance-dialog .ed-lib-head { display: flex; justify-content: space-between; align-items: center; padding: 6px 8px; border-bottom: 1px solid rgba(255,255,255,.08); font-size: 12px; color: #aaa; }
#enhance-dialog .ed-lib-head-btns { display: inline-flex; gap: 4px; }
#enhance-dialog .ed-lib-head button { font-size: 11px; padding: 3px 8px; background: #2a2a2c; border: 1px solid rgba(255,255,255,.15); border-radius: 4px; color: #ddd; cursor: pointer; }
#enhance-dialog .ed-lib-head button:hover:not(:disabled) { border-color: rgba(255,255,255,.35); color: #fff; }
#enhance-dialog .ed-lib-head button:disabled { opacity: .4; cursor: default; }
#enhance-dialog .ed-lib-list { flex: 1; overflow-y: auto; padding: 4px; }
#enhance-dialog .ed-row { border-radius: 4px; margin-bottom: 2px; }
#enhance-dialog .ed-row:hover { background: rgba(255,255,255,.04); }
#enhance-dialog .ed-row-disabled .ed-row-main { opacity: 0.4; }
#enhance-dialog .ed-row-disabled input[type=checkbox] { cursor: not-allowed; }
#enhance-dialog .ed-row-main { display: flex; align-items: center; gap: 6px; padding: 5px 6px; cursor: pointer; font-size: 12px; color: #ddd; }
#enhance-dialog .ed-row-main input[type=checkbox] { margin: 0; flex-shrink: 0; }
#enhance-dialog .ed-row-grab { color: #555; flex-shrink: 0; cursor: grab; user-select: none; font-size: 11px; letter-spacing: -2px; width: 12px; text-align: center; }
#enhance-dialog .ed-row:hover .ed-row-grab { color: #888; }
#enhance-dialog .ed-row.dragging { opacity: .4; }
#enhance-dialog .ed-row.drag-over { border-top: 2px solid var(--accent); }
#enhance-dialog .ed-name { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#enhance-dialog .ed-name-input { flex: 1; background: #1a1a1c; border: 1px solid rgba(255,255,255,.2); border-radius: 3px; color: #ddd; font-size: 12px; padding: 2px 4px; font-family: inherit; }
#enhance-dialog .ed-row-actions { display: inline-flex; gap: 3px; margin-left: auto; flex-shrink: 0; opacity: 0; transition: opacity .1s; }
#enhance-dialog .ed-row:hover .ed-row-actions, #enhance-dialog .ed-row.editing .ed-row-actions { opacity: 1; }
#enhance-dialog .ed-row-actions button { font-size: 10px; line-height: 1; padding: 2px 5px; background: transparent; border: 1px solid rgba(255,255,255,.15); border-radius: 3px; color: #aaa; cursor: pointer; }
#enhance-dialog .ed-row-actions button:hover { color: #fff; border-color: rgba(255,255,255,.3); }
#enhance-dialog .ed-row-actions .ed-del { color: #d77; border-color: rgba(220,100,100,.25); }
#enhance-dialog .ed-row-actions .ed-del:hover { color: #f88; border-color: rgba(220,100,100,.5); }
#enhance-dialog .ed-row-body { display: none; width: calc(100% - 12px); margin: 0 6px 6px; box-sizing: border-box; min-height: 110px; max-height: 260px; background: #1a1a1c; border: 1px solid rgba(255,255,255,.2); border-radius: 4px; color: #ddd; font-size: 12px; padding: 6px; font-family: inherit; resize: vertical; }
#enhance-dialog .ed-row.editing .ed-row-body { display: block; }
#enhance-dialog .ed-preview { flex: 1; display: flex; flex-direction: column; min-width: 0; min-height: 0; gap: 6px; }
#enhance-dialog .ed-prev-head { font-size: 12px; color: #aaa; margin: 0; }
#enhance-dialog .ed-blocks-head { margin-top: 4px; }
#enhance-dialog textarea#ed-freeform { width: 100%; box-sizing: border-box; min-height: 70px; max-height: 160px; resize: vertical; background: #111; border: 1px solid rgba(255,255,255,.2); border-radius: 6px; color: #ddd; font-size: 13px; padding: 8px 10px; font-family: inherit; flex-shrink: 0; }
#enhance-dialog .ed-blocks { flex: 1; min-height: 120px; overflow-y: auto; border: 1px solid rgba(255,255,255,.15); border-radius: 6px; background: #0e0e10; padding: 6px; display: flex; flex-direction: column; gap: 4px; }
#enhance-dialog .ed-blocks-empty { color: #666; font-size: 12px; padding: 16px 12px; text-align: center; font-style: italic; }
#enhance-dialog .ed-block { background: #1a1a1c; border: 1px solid rgba(255,255,255,.1); border-radius: 4px; padding: 6px 8px; }
#enhance-dialog .ed-block.dragging { opacity: .4; }
#enhance-dialog .ed-block.drag-over { border-color: var(--accent); }
#enhance-dialog .ed-block-head { display: flex; align-items: center; gap: 6px; font-size: 12px; color: #ddd; cursor: grab; }
#enhance-dialog .ed-block-grab { color: #666; flex-shrink: 0; user-select: none; font-size: 11px; letter-spacing: -2px; width: 12px; text-align: center; }
#enhance-dialog .ed-block-name { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#enhance-dialog .ed-block-toggle { background: transparent; border: none; color: #999; cursor: pointer; font-size: 11px; padding: 2px 6px; }
#enhance-dialog .ed-block-toggle:hover { color: #fff; }
#enhance-dialog .ed-block-body { display: none; font-size: 11px; color: #aaa; padding: 6px 4px 0; white-space: pre-wrap; max-height: 160px; overflow-y: auto; line-height: 1.4; }
#enhance-dialog .ed-block.expanded .ed-block-body { display: block; }
#enhance-dialog .ed-footer { display: flex; justify-content: space-between; align-items: flex-end; margin-top: 14px; gap: 12px; }
#enhance-dialog .ed-opts-wrap { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
#enhance-dialog .ed-prov, #enhance-dialog .ed-prov-opts { display: flex; align-items: center; gap: 10px; font-size: 12px; color: #ccc; flex-wrap: wrap; }
#enhance-dialog .ed-prov span, #enhance-dialog .ed-prov-opts span { color: #aaa; }
#enhance-dialog .ed-prov label, #enhance-dialog .ed-prov-opts label { display: inline-flex; align-items: center; gap: 4px; cursor: pointer; }
#enhance-dialog .ed-prov input, #enhance-dialog .ed-prov-opts input { margin: 0; }
#enhance-dialog .ed-res { display: flex; align-items: center; gap: 8px; font-size: 12px; color: #ccc; }
#enhance-dialog .ed-res span { color: #aaa; }
#enhance-dialog .ed-res label { display: inline-flex; align-items: center; gap: 4px; cursor: pointer; }
#enhance-dialog .ed-res input { margin: 0; }
#enhance-dialog .ed-aspect { display: flex; align-items: center; gap: 6px; font-size: 12px; color: #ccc; cursor: pointer; }
#enhance-dialog .ed-aspect input { margin: 0; }
#enhance-dialog .ed-actions { display: flex; gap: 8px; }
#enhance-dialog .ed-footer button { font-size: 13px; cursor: pointer; padding: 7px 16px; border-radius: 6px; border: 1px solid rgba(255,255,255,.2); background: #2a2a2c; color: #ddd; }
#enhance-dialog .ed-footer button.primary { background: var(--accent); border-color: var(--accent); color: #fff; }
#enhance-dialog .ed-footer button:disabled { opacity: .6; cursor: default; }
#modal-close { position: fixed; top: 14px; right: 18px; background: rgba(0,0,0,.5); border: none; color: #ccc; font-size: 22px; cursor: pointer; border-radius: 50%; width: 36px; height: 36px; display: flex; align-items: center; justify-content: center; }
#modal-close:hover { color: #fff; background: rgba(255,255,255,.15); }
/* Anchored inline by JS to the image's rendered top-left corner so it
   sits inside the photo, not at the viewport edge (image is centered +
   letterboxed by max-width/max-height + object-fit:contain). */
#modal-star { display: none; position: fixed; background: rgba(0,0,0,.6); border: 1px solid rgba(255,255,255,.18); color: #eee; font-size: 20px; cursor: pointer; border-radius: 50%; width: 34px; height: 34px; align-items: center; justify-content: center; transition: color .15s, background .15s, transform .12s, border-color .15s; z-index: 510; }
#modal-star.show { display: flex; }
#modal-star:hover { color: #ffd54f; background: rgba(0,0,0,.78); border-color: rgba(255,213,79,.55); transform: scale(1.08); }
#modal-star.is-starred { color: #ffd54f; border-color: rgba(255,213,79,.55); }
/* Report-problem pill — JS-anchored to #modal-img's bottom-right (mirrors
   #modal-star top-left). Anon-only; admins don't see it. Amber hue to read
   as a warning without competing with the star's gold accent. */
#modal-report { display: none; position: fixed; background: rgba(0,0,0,.6); border: 1px solid rgba(255,255,255,.18); color: #eee; font-size: 18px; cursor: pointer; border-radius: 50%; width: 34px; height: 34px; align-items: center; justify-content: center; transition: color .15s, background .15s, transform .12s, border-color .15s; z-index: 510; line-height: 1; }
#modal-report.show { display: flex; }
#modal-report:hover { color: #fbbf24; background: rgba(0,0,0,.78); border-color: rgba(251,191,36,.55); transform: scale(1.08); }
/* Faces preview overlay star — mirrors #modal-star but sits above the
   faces overlay (z-index 9999). JS-anchored to #fp-img top-left. */
#fp-star { display: none; position: fixed; background: rgba(0,0,0,.6); border: 1px solid rgba(255,255,255,.18); color: #eee; font-size: 20px; cursor: pointer; border-radius: 50%; width: 34px; height: 34px; align-items: center; justify-content: center; transition: color .15s, background .15s, transform .12s, border-color .15s; z-index: 10000; }
#fp-star.show { display: flex; }
#fp-star:hover { color: #ffd54f; background: rgba(0,0,0,.78); border-color: rgba(255,213,79,.55); transform: scale(1.08); }
#fp-star.is-starred { color: #ffd54f; border-color: rgba(255,213,79,.55); }
.modal-nav { position: fixed; top: 50%; transform: translateY(-50%); background: rgba(0,0,0,.45); border: none; color: #ccc; font-size: 28px; cursor: pointer; padding: 12px 8px; border-radius: 4px; line-height: 1; z-index: 12; }
.modal-nav:hover { color: #fff; background: rgba(255,255,255,.12); }
#modal-prev { left: 10px; }
#modal-next { right: 10px; }

/* ── MODALS (shared) ── */
.overlay {
  display: none; position: fixed; inset: 0; z-index: 600;
  background: rgba(0,0,0,.7); align-items: center; justify-content: center;
}
.overlay.open { display: flex; }
.modal-box {
  background: var(--surface); border: 1px solid var(--border); border-radius: 8px;
  padding: 20px; display: flex; flex-direction: column; gap: 12px;
}
.modal-box h3 { font-size: 14px; font-weight: 700; }
.modal-box p  { font-size: 12px; color: var(--text-dim); }
.form-row { display: flex; flex-direction: column; gap: 4px; }
.form-row label { font-size: 11px; color: var(--text-dim); }
.form-row input {
  padding: 7px 10px; border-radius: 5px; border: 1px solid var(--border);
  background: var(--surface2); color: var(--text); font-size: 13px; width: 100%;
}
.form-row input:focus { outline: none; border-color: var(--accent); }
.form-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 4px; }
.ef-row { display:flex; align-items:center; justify-content:space-between; background:var(--surface2); border-radius:5px; padding:6px 10px; font-size:12px; gap:8px; }
.ef-row span { color:var(--text-dim); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; flex:1; }
.ef-row button { flex-shrink:0; }
.btn-primary { padding: 6px 14px; border-radius: 5px; border: 1px solid var(--accent); background: transparent; color: var(--accent); cursor: pointer; font-size: 12px; }
.btn-primary:hover { background: var(--accent-bg); }
.btn-primary:disabled { opacity: 0.4; cursor: not-allowed; }
.btn-primary:disabled:hover { background: transparent; }
.btn-cancel  { padding: 6px 14px; border-radius: 5px; border: 1px solid var(--border); background: transparent; color: var(--text-dim); cursor: pointer; font-size: 12px; }
.btn-cancel:hover { background: var(--surface2); color: var(--text); }
.btn-danger  { padding: 6px 14px; border-radius: 5px; border: 1px solid var(--danger); background: transparent; color: var(--danger); cursor: pointer; font-size: 12px; }
.btn-danger:hover { background: var(--danger-bg); }

/* ── LOGIN MODAL ── */
#login-modal .modal-box { width: 320px; }

/* ── SETTINGS MODAL ── */
#settings-modal .modal-box { width: 380px; }
.settings-row {
  display: flex; align-items: center; gap: 20px;
  padding: 12px 0; border-bottom: 1px solid var(--border);
}
.settings-row:last-of-type { border-bottom: none; }
.settings-row-left { flex: 1; min-width: 0; }
.settings-label { font-size: 13px; color: var(--text); }
.settings-desc  { font-size: 11px; color: var(--text-dim); margin-top: 3px; line-height: 1.4; }
.settings-control { flex-shrink: 0; }
.thumb-slider-wrap { display: flex; align-items: center; gap: 8px; }
.thumb-slider-wrap input[type=range] { width: 140px; accent-color: var(--accent); cursor: pointer; }
.thumb-slider-val { font-size: 12px; color: var(--text-dim); min-width: 36px; text-align: right; }
.settings-control select {
  padding: 5px 8px; border-radius: 5px; border: 1px solid var(--border);
  background: var(--surface2); color: var(--text); font-size: 13px; cursor: pointer;
  min-width: 80px;
}
.settings-control select:focus { outline: none; border-color: var(--accent); }

/* ── HELP MODAL ── */
#help-modal .modal-box { width: 480px; max-height: 80vh; overflow-y: auto; }

/* ── CONFIG MODAL ── fixed size so switching sections doesn't resize/recenter
   the box; the sidebar stays pinned and only the content pane changes. */
#config-modal .modal-box { width: 900px; max-width: 92vw; height: 670px; max-height: 92vh; }
.help-section { margin-top: 8px; border: 1px solid var(--border); border-radius: 6px; overflow: hidden; }
.help-toggle {
  width: 100%; display: flex; align-items: center; justify-content: space-between;
  padding: 9px 12px; background: var(--surface2); border: none; color: var(--text);
  font-size: 11px; font-weight: 700; letter-spacing: .07em; text-transform: uppercase;
  cursor: pointer; text-align: left;
}
.help-toggle:hover { background: #333; }
.help-toggle .help-chevron { font-size: 10px; color: var(--text-dim); transition: transform .2s; }
.help-toggle.open .help-chevron { transform: rotate(180deg); }
.help-body { display: none; padding: 10px 12px 6px; }
.help-body.open { display: block; }
.help-row { display: flex; gap: 10px; font-size: 12px; margin-bottom: 6px; line-height: 1.4; }
.help-key { flex-shrink: 0; width: 110px; font-weight: 600; color: var(--text); }
.help-desc { color: var(--text-dim); }

/* ── UPLOAD MODAL ── */
#upload-modal .modal-box { width: 420px; }
.progress-bar-wrap { background: var(--surface2); border-radius: 4px; height: 8px; overflow: hidden; }
.progress-bar-fill { height: 100%; background: var(--accent); border-radius: 4px; transition: width .2s; width: 0%; }
#upload-current { font-size: 11px; color: var(--text-dim); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
#upload-slots {
  margin-top: 6px; display: flex; flex-direction: column; gap: 2px;
  background: var(--surface2); border-radius: 4px; padding: 6px 8px;
  font-size: 10.5px; color: var(--text-dim);
}
.upload-slot-row { display: flex; align-items: center; gap: 6px; white-space: nowrap; overflow: hidden; }
.upload-slot-row .slot-dot { font-size: 9px; color: var(--accent); flex-shrink: 0; transition: opacity .2s; opacity: 0.25; }
.upload-slot-row.active .slot-dot { opacity: 1; }
.upload-slot-row .slot-name { overflow: hidden; text-overflow: ellipsis; }

/* ── DELETE CONFIRM ── */
#delete-modal .modal-box { width: 400px; }
#delete-list { max-height: 160px; overflow-y: auto; border: 1px solid var(--border); border-radius: 4px; padding: 6px 10px; font-size: 11px; color: var(--text-dim); line-height: 1.8; }

/* ── RENAME MODAL ── */
#rename-modal .modal-box { width: 380px; }

/* ── SHARED FOLDER PICKER (used by move + upload flows) ── */
#folder-picker-modal .modal-box { width: 420px; }
#folder-picker-search {
  width: 100%; box-sizing: border-box; padding: 8px 12px; margin-bottom: 10px;
  border-radius: 5px; border: 1px solid var(--border);
  background: var(--surface2); color: var(--text); font-size: 13px;
}
#folder-picker-search:focus { outline: none; border-color: var(--accent); }
#folder-picker-tree {
  border: 1px solid var(--border); border-radius: 4px; max-height: 360px;
  overflow-y: auto; background: var(--surface2); padding: 4px 0;
}
.fp-node { display: block; }
.fp-row {
  display: flex; align-items: center; gap: 6px;
  padding: 6px 10px; cursor: pointer; font-size: 13px;
  user-select: none;
}
.fp-row:hover { background: rgba(255,255,255,.06); }
.fp-row.selected { background: var(--accent-bg); color: #fff; }
.fp-chevron {
  flex-shrink: 0; width: 14px; text-align: center; font-size: 10px;
  color: var(--text-dim); transition: transform .12s ease;
  display: inline-block;
}
.fp-chevron.leaf { visibility: hidden; }
.fp-node.expanded > .fp-row > .fp-chevron:not(.leaf) { transform: rotate(90deg); }
.fp-icon { flex-shrink: 0; font-size: 13px; }
.fp-label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fp-children { display: none; padding-left: 16px; border-left: 1px dotted rgba(255,255,255,.08); margin-left: 14px; }
.fp-node.expanded > .fp-children { display: block; }
.fp-row.fp-search-hidden { display: none; }
.fp-empty { padding: 14px 12px; font-size: 12px; color: var(--text-dim); text-align: center; }
#folder-picker-new-area { margin-top: 10px; }
#btn-folder-picker-new {
  background: none; border: 1px dashed var(--border); color: var(--text-dim);
  padding: 6px 10px; border-radius: 4px; font-size: 12px; cursor: pointer; width: 100%;
}
#btn-folder-picker-new:hover { color: var(--text); border-color: var(--accent); }
#folder-picker-new-row { display: none; gap: 6px; align-items: center; }
#folder-picker-new-row.open { display: flex; }
#folder-picker-new-input {
  flex: 1; padding: 6px 10px; border-radius: 4px;
  border: 1px solid var(--border); background: var(--surface2); color: var(--text); font-size: 12px;
}
#folder-picker-new-input:focus { outline: none; border-color: var(--accent); }
.fp-new-btn { padding: 6px 10px; border-radius: 4px; border: 1px solid var(--border); background: var(--surface2); color: var(--text); cursor: pointer; font-size: 12px; }
.fp-new-btn:hover { background: rgba(255,255,255,.08); }

/* ── EMPTY / LOADING ── */
#empty { display: none; flex-direction: column; align-items: center; justify-content: center; height: 60vh; color: var(--text-dim); gap: 8px; font-size: 14px; }
#empty.show { display: flex; }
#empty .big { font-size: 40px; }
#loading { display: none; flex-direction: column; align-items: center; justify-content: center; height: 60vh; color: var(--text-dim); gap: 10px; }
#loading.show { display: flex; }
.spinner { width: 32px; height: 32px; border: 3px solid var(--border); border-top-color: var(--accent); border-radius: 50%; animation: spin .7s linear infinite; }
@keyframes spin { to { transform: rotate(360deg); } }

/* ── FACES PANEL ── */
#faces-controls {
  display: flex; align-items: center; gap: 8px; padding: 10px 0 12px; flex-wrap: wrap;
  /* Pin to the top of the scroll container (#content) so Rescan / Re-cluster
     / Hide-named / Reset stay reachable while triaging long face-group lists. */
  position: sticky; top: 0; z-index: 5;
  background: var(--bg);
  border-bottom: 1px solid var(--border);
  margin-bottom: 6px;
}
#faces-progress-wrap {
  background: var(--surface2); border-radius: 4px; height: 6px;
  overflow: hidden; margin-bottom: 4px;
}
#faces-progress-bar {
  height: 100%; background: var(--accent); border-radius: 4px; width: 0%; transition: width .3s;
}
#faces-status { font-size: 11px; color: var(--text-dim); }
#faces-merge-bar {
  display: none; align-items: center; gap: 8px;
  padding: 8px 0; border-top: 1px solid var(--border); margin-bottom: 12px;
}
#faces-merge-bar.visible { display: flex; }
#faces-merge-count { font-size: 11px; color: var(--text-dim); }

.face-group {
  background: var(--surface2); border-radius: 6px; margin-bottom: 10px;
  border: 2px solid transparent; overflow: hidden;
}
.face-group.fg-selected { border-color: var(--accent); }
/* Subtle hue tints over the grey base: Orphaned = warm/orange hint,
   Strangers (system) = cool/blue hint. Just a whisper of color. */
.face-group.fg-orphans { background: #2f2a24; }
.face-group.fg-system  { background: #24272f; }
.face-group.fg-potentially {
  border-left: 4px dashed var(--accent);
  margin-left: 16px;
  opacity: 0.95;
}
.face-group.fg-potentially .fg-suggest-prefix {
  font-style: italic; font-weight: 400; color: var(--text-dim); margin-right: 4px;
}
.face-group.fg-potentially .fg-suggest-name {
  font-weight: 600;
}
.fg-header {
  display: flex; align-items: flex-start; gap: 10px; padding: 10px 12px;
}
.fg-merge-label { cursor: pointer; padding-top: 3px; flex-shrink: 0; }
.fg-thumbs { display: flex; gap: 4px; flex-wrap: nowrap; flex-shrink: 0; }
.fg-crop {
  width: 60px; height: 60px; border-radius: 4px; object-fit: cover;
  background: var(--border); flex-shrink: 0;
}
.fg-thumb {
  width: 72px; height: 60px; border-radius: 4px;
  background: var(--border) center / cover no-repeat;
  flex-shrink: 0; overflow: hidden;
  cursor: pointer; transition: outline 0.1s;
}
.fg-thumb:hover { outline: 2px solid var(--accent); outline-offset: -2px; }
.fg-meta { flex: 1; min-width: 0; }
.fg-label { font-size: 16px; font-weight: 600; margin-bottom: 6px; }
.fg-actions { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.fg-actions-row2 { margin-top: 6px; }
.fg-name-btn, .fg-nest-btn { padding: 3px 8px !important; font-size: 11px !important; }
.fg-count { font-size: 11px; color: var(--text-dim); }
.fg-expand-btn { padding: 3px 8px !important; font-size: 11px !important; }
.fg-delete-btn {
  padding: 3px 7px; border-radius: 3px; border: 1px solid var(--border);
  background: none; color: var(--text-dim); cursor: pointer; font-size: 11px;
}
.fg-delete-btn:hover { border-color: var(--danger); color: var(--danger); background: var(--danger-bg); }

.fg-photos {
  display: none; flex-wrap: wrap; gap: 8px; padding: 8px 12px 12px;
  border-top: 1px solid var(--border);
}
.fg-photos.open { display: flex; }
.fg-photo-item {
  display: flex; flex-direction: column; align-items: center; gap: 4px; width: 100px;
}
.fg-photo-item img { width: 100px; height: 100px; object-fit: cover; border-radius: 4px; background: var(--border); }
.fg-photo-name { font-size: 9px; color: var(--text-dim); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; width: 100%; text-align: center; }
.fg-remove-btn {
  padding: 2px 6px; font-size: 10px; border-radius: 3px; border: 1px solid var(--border);
  background: none; color: var(--text-dim); cursor: pointer;
}
.fg-remove-btn:hover { border-color: var(--danger); color: var(--danger); background: var(--danger-bg); }
.fg-empty { font-size: 12px; color: var(--text-dim); padding: 8px; }

/* ── TOAST ── */
#toast { position: fixed; bottom: 50px; left: 50%; transform: translateX(-50%); background: #222; border: 1px solid #444; border-radius: 24px; padding: 18px 44px; font-size: 24px; line-height: 1.3; font-weight: 500; color: #f0f0f0; z-index: 900; opacity: 0; transition: opacity .2s; pointer-events: none; max-width: 80vw; max-height: 60vh; text-align: center; overflow-wrap: anywhere; box-sizing: border-box; }
#toast .toast-sub { display: block; font-size: 0.7em; opacity: 0.72; margin-top: 0.5em; font-weight: 400; line-height: 1.35; color: #d0d0d0; }
#toast.show { opacity: 1; pointer-events: auto; cursor: pointer; }
#toast.error { background: #4a0f0f; border-color: #ff4747; color: #ffd9d9; padding: 18px 44px; font-size: 24px; font-weight: 600; box-shadow: 0 0 0 0 rgba(255,71,71,0.6); }
#toast.error.show { animation: toastErrorPulse 1.1s ease-out infinite; }
@keyframes toastErrorPulse {
  0%   { box-shadow: 0 0 0 0   rgba(255,71,71,0.65); border-color: #ff4747; }
  70%  { box-shadow: 0 0 0 14px rgba(255,71,71,0);    border-color: #ff8585; }
  100% { box-shadow: 0 0 0 0   rgba(255,71,71,0);    border-color: #ff4747; }
}


/* ── MOBILE ── */
@media (max-width: 600px) {
  #btn-hamburger { display: flex !important; }
  #btn-config, #btn-help { display: none; }
  #status-hint { display: none; }
  #resize-handle { display: none; }
  #main { grid-template-columns: 1fr; }
  /* No bleed on narrow screens — every horizontal pixel counts. */
  :root { --tile-bleed: 0px; }

  #sidebar {
    position: fixed;
    top: var(--toolbar-h); bottom: var(--status-h);
    left: -230px; width: 220px; z-index: 400;
    transition: left .25s ease;
    box-shadow: 4px 0 24px rgba(0,0,0,.6);
  }
  #sidebar.mobile-open { left: 0; }

  #sidebar-backdrop {
    display: none; position: fixed; inset: 0;
    background: rgba(0,0,0,.5); z-index: 399;
  }
  #sidebar-backdrop.visible { display: block; }

  .modal-box { width: 94vw !important; max-width: none !important; }
  .modal-nav { padding: 20px 14px; font-size: 32px; }
  #modal-prev { left: 0; border-radius: 0 4px 4px 0; }
  #modal-next { right: 0; border-radius: 4px 0 0 4px; }
  #modal-info { font-size: 11px; max-width: 80vw; text-align: center; }
}
::-webkit-scrollbar { width: 6px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: #444; border-radius: 3px; }
