/* App styles. Also loaded by www/design/ so the board renders the shipped components. */
:root {
  color-scheme: light;
  --bg: #efece6;
  --fg: #1a1916;
  --muted: #6b6560;
  --line: #ddd6cc;
  --btn: #1a1916;
  --on-btn: #f3f1ec;
  --tile: #ddd6cc;
  --panel: #f6f3ed;
  --scrim: rgba(26, 25, 22, .4);
  --hit: rgba(26, 25, 22, .06);
  --size: 36px;
  --rail: 52px;
}
@media (prefers-color-scheme: dark) {
  :root {
    color-scheme: dark;
    --bg: #000;
    --fg: #f3f1ec;
    --muted: #8a847c;
    --line: #2a2825;
    --btn: #f3f1ec;
    --on-btn: #000;
    --tile: #1a1917;
    --panel: #121110;
    --scrim: rgba(0, 0, 0, .55);
    --hit: rgba(243, 241, 236, .08);
  }
}
* { box-sizing: border-box; }
html, body, #app { margin: 0; height: 100%; background: var(--bg); color: var(--fg); touch-action: manipulation; overscroll-behavior: none; }
/* An interface, not a document: nothing selects or brings up the callout on a hold — except what is there to be read or typed. */
body { font: 15px/1.3 -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; user-select: none; -webkit-user-select: none; -webkit-touch-callout: none; }
input, textarea, .pv-text { user-select: text; -webkit-user-select: text; }
button, input { font: inherit; color: inherit; }
.root { display: flex; flex-direction: column; height: 100%; position: relative; background: var(--bg); }
.hdr {
  flex: none; position: relative; z-index: 5;
  display: flex; justify-content: space-between; align-items: center;
  padding: calc(8px + env(safe-area-inset-top, 0px)) 12px 8px;
  min-height: var(--top);
  background: var(--bg); border-bottom: 1px solid var(--line);
  transition: transform .2s, opacity .2s;
}
.root { --top: calc(52px + env(safe-area-inset-top, 0px)); }
.root:has(.photos) .hdr { position: absolute; top: 0; left: 0; right: 0; }
.root.away:not(.picking) .hdr { transform: translateY(-100%); opacity: 0; pointer-events: none; }
.body { flex: 1; min-height: 0; display: flex; flex-direction: column; }
.ttl { position: absolute; left: 52px; right: 52px; text-align: center; pointer-events: none; line-height: 1.15; } /* a button (12 + --size) and 4px on each side */
.ttl .app { display: block; font-size: 15px; font-weight: 650; letter-spacing: -0.02em; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } /* a long name is cut, never a second line under the icons */
.ttl .place { display: block; font-size: 11px; font-weight: 500; opacity: 0.5; margin-top: 2px; pointer-events: auto; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pv .hdr .ttl { right: 124px; } /* share, delete, download (3 × --size) on the right: the title stops short of them */
.ttl .place .sep { opacity: 0.45; margin: 0 4px; }
.hdr .acts { display: flex; }
.crumb { background: none; border: 0; padding: 0; font: inherit; color: inherit; cursor: pointer; }
.crumb:hover { opacity: 1; }
.ghost {
  width: var(--size); height: var(--size); border: 0; border-radius: 999px;
  background: transparent; display: grid; place-items: center; pointer-events: auto;
}
.hdr .txt { height: var(--size); padding: 0 8px; border: 0; background: transparent; font-size: 14px; font-weight: 600; }
.picking .hdr .ttl { left: 100px; right: 124px; } /* ✕ All on the left, three acts on the right */
.ghost svg { width: 20px; height: 20px; display: block; }
.lock {
  flex: 1; min-height: 0; display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 12px; padding: 24px 24px 80px;
}
.lock .name { font-size: 28px; font-weight: 650; letter-spacing: -0.04em; }
.lock .who { margin-top: -8px; font-size: 14px; background: none; border: 0; color: var(--muted); }
.lock .go {
  margin-top: 10px; height: 44px; padding: 0 28px; border: 0; border-radius: 999px;
  background: var(--btn); color: var(--on-btn); font-size: 16px; font-weight: 600;
}
.lock .alt { font-size: 12px; background: none; border: 0; opacity: 0.65; }
.lock .field {
  width: 220px; height: 44px; margin-top: 8px;
  border: 0; border-bottom: 1px solid var(--line);
  background: transparent; color: var(--fg);
  text-align: center; font-size: 17px; letter-spacing: 0.12em; font-weight: 500;
}
.lock .err { font-size: 12px; color: #c45c4c; text-align: center; max-width: 260px; }
.q-row {
  display: flex; align-items: center; gap: 12px;
  height: 56px; padding: 0 20px; width: 100%;
  border: 0; border-bottom: 1px solid var(--line);
  background: none; text-align: left; cursor: pointer; position: relative;
}
.q-row svg { width: 18px; height: 18px; flex: 0 0 18px; }
.q-row .body { flex: 1; min-width: 0; }
.q-row .name {
  font-weight: 600; font-size: 15px; letter-spacing: -0.02em;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.q-row .meta { font-size: 12px; color: var(--muted); margin-top: 1px; }
.q-row .chev.off { visibility: hidden; }
.q-row.on { background: var(--hit); }
/* Selecting (long press, ⌘-click): the picked rows and tiles wear a check; the header counts them and acts on them all. */
.picked::after { content: "✓"; position: absolute; z-index: 1; width: 22px; height: 22px; border-radius: 999px; display: grid; place-items: center; background: var(--btn); color: var(--on-btn); font-size: 13px; font-weight: 700; }
.q-row.picked { background: var(--hit); }
.q-row.picked::after { right: 18px; top: 17px; }
.q-row.picked .chev { visibility: hidden; }
.th.picked::after { right: 6px; top: 6px; }
.th.picked img { transform: scale(.9); }
/* a hold is ours: no image drag ghost, no tap flash, and the pointer lands on the row or tile itself, never a child.
   While selecting, a sideways swipe on a row or a tile sweeps it (pan-y leaves us every gesture but the vertical scroll). */
.q-row, .th { -webkit-tap-highlight-color: transparent; }
.picking .q-row, .picking .th { touch-action: pan-y; }
.q-row > *, .th > * { pointer-events: none; }
img { -webkit-user-drag: none; }
.sheet button.row { width: 100%; padding: 0; border: 0; background: none; color: inherit; text-align: left; cursor: pointer; }
.split { display: flex; height: 100%; overflow-x: auto; }
.split > .pane { flex: 0 0 250px; overflow-y: auto; border-right: 1px solid var(--line); }
.split > .pane:last-child { flex: 1 0 250px; min-width: 250px; border-right: 0; }
.pane.pv-pane { display: flex; }
.pv { flex: 1; min-width: 0; display: flex; flex-direction: column; height: 100%; background: var(--bg); }
.pane .pv .hdr { padding-top: 8px; min-height: 52px; } /* inside the columns the shell's header already sits under the status bar */
.pv .hdr .acts { gap: 2px; }
.pv .hdr .alt { height: 32px; padding: 0 12px; border: 1px solid var(--line); border-radius: 999px; background: transparent; font-size: 13px; }
.pv-body { flex: 1; min-height: 0; position: relative; display: flex; align-items: center; justify-content: center; overflow: auto; overscroll-behavior: none; }
.pv-body .th { position: absolute; inset: 0; aspect-ratio: auto; display: grid; place-items: center; }
.pv-body .th[data-act] { cursor: pointer; }
.pv-body .th img[data-fid] { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain; opacity: 0; transition: opacity .18s ease; }
.pv-body .th img[data-fid].on { opacity: 1; }
.pv-glyph svg { width: 44px; height: 44px; opacity: .5; }
.pv-text { align-self: stretch; width: 100%; height: 100%; margin: 0; padding: 16px 20px calc(24px + env(safe-area-inset-bottom, 0px)); overflow: auto; overscroll-behavior: none; font: 14px/1.6 ui-monospace, SFMono-Regular, Menlo, monospace; white-space: pre-wrap; word-break: break-word; }
.pv-frame { width: 100%; height: 100%; border: 0; background: #fff; } /* a page or a pdf paints on white whatever the scheme: its own colours, not ours */
/* The player sits in a box of its own: the box is what goes fullscreen (media.js bindFullscreen). */
.pv-video { position: relative; width: 100%; height: 100%; overflow: hidden; background: #000; }
video.pv-player { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain; background: #000; }
.pv-sound { display: grid; gap: 20px; justify-items: center; width: 100%; padding: 24px; }
.pv-sound .pv-glyph svg { width: 72px; height: 72px; }
audio.pv-player { width: min(100%, 480px); }
.pv-note { padding: 32px 24px; text-align: center; color: var(--muted); font-size: 13px; display: grid; gap: 6px; }
.lightbox .pv { width: 100%; height: 100%; }
.mosaic { display: grid; gap: 2px; }
.mosaic.p { grid-template-columns: repeat(3, 1fr); }
@media (min-width: 768px) { .mosaic.p { grid-template-columns: repeat(5, 1fr); } }
.th { aspect-ratio: 1; background: var(--tile); overflow: hidden; position: relative; }
.th.t0 { background: #cfc8bc } .th.t1 { background: #b9b2a6 } .th.t2 { background: #a39c90 }
.th.t3 { background: #8e877c } .th.t4 { background: #7a7469 } .th.t5 { background: #676157 }
.th.t6 { background: #524d45 } .th.t7 { background: #3f3b35 }
.th img { width: 100%; height: 100%; object-fit: cover; display: block; }
.th img.blur { position: absolute; inset: -10%; width: 120%; height: 120%; filter: blur(10px); }
.th img[data-pid] { position: absolute; inset: 0; opacity: 0; transition: opacity .18s ease; }
.th img[data-pid].on { opacity: 1; }
.th .play { position: absolute; left: 6px; bottom: 6px; width: 22px; height: 22px; border-radius: 999px; background: rgba(0,0,0,.55); pointer-events: none; }
.th .play::before { content: ""; position: absolute; left: 8px; top: 6px; border: 5px solid transparent; border-left: 8px solid #fff; }
@media (prefers-color-scheme: light) {
  .th.t0 { background: #e7e2d8 } .th.t1 { background: #ddd6cc } .th.t2 { background: #d3cbc0 }
  .th.t3 { background: #c9c0b4 } .th.t4 { background: #bfb5a8 } .th.t5 { background: #b5aa9c }
  .th.t6 { background: #ab9f90 } .th.t7 { background: #a19484 }
}
.ph { width: 100%; background: var(--tile); }
/* Photos: full-bleed mosaic + rail. Header overlays them (rail is fullscreen); it hides on scroll down and returns on scroll up. */
.photos { flex: 1; min-height: 0; display: flex; position: relative; }
.photos .view { padding-top: var(--top); }
.photos .view > [data-label] { overflow: hidden; }
/* the search bar: it covers the header, the pane below it holds what it finds. ✕ clears the field (shown with text), Cancel leaves.
   Its glyph sits where the header's glyphs sit (8px into a 36px button, their colour), Cancel ends where its buttons end. */
.bar {
  display: flex; align-items: center; gap: 8px; height: 100%; flex: 1; min-width: 0;
  padding: 0 0 0 8px;
  background: none; border: 0;
}
.bar > svg { width: 20px; height: 20px; flex: none; }
.bar input { flex: 1; min-width: 0; height: 100%; border: 0; background: none; color: var(--fg); font-size: 17px; letter-spacing: -0.02em; outline: none; -webkit-appearance: none; }
.bar input::-webkit-search-cancel-button { display: none; }
.bar .clear { width: 28px; height: 28px; font-size: 12px; background: var(--hit); }
.bar .n { flex: none; color: var(--muted); font-size: 13px; font-variant-numeric: tabular-nums; }
.bar .n:empty { display: none; }
.bar input:placeholder-shown ~ .clear, .bar input:placeholder-shown ~ .n { display: none; }
.bar .cancel { flex: none; height: 32px; padding: 0 12px; border: 0; border-radius: 999px; background: var(--btn); color: var(--on-btn); font-size: 13px; font-weight: 600; }
/* rail: nothing while browsing; the tint, the year badges and the month chip while the grid scrolls or the rail is slid (.live: a finger
   or a pressed mouse sliding on it — no :hover, WebKit keeps that lit after a touch), a second past the last scroll on every screen */
.rail {
  position: absolute; top: 0; right: 0; bottom: 0; z-index: 2; width: var(--rail);
  display: flex; flex-direction: column;
  padding: 26px 0 0;
  font-size: 11px; text-align: center; color: var(--muted);
  user-select: none; touch-action: none; cursor: row-resize; transition: background .15s;
}
.rail.live, .rail.scrolling { background: var(--hit); }
.rail-y {
  display: flex; align-items: flex-start; justify-content: center;
  pointer-events: none;
}
.rail-y span {
  transform: translateY(-50%);
  padding: 2px 7px; border-radius: 999px; font-weight: 500; color: var(--fg);
  background: color-mix(in srgb, var(--bg) 65%, transparent); backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px);
  opacity: 0; transition: opacity .15s;
}
.rail-y.on span { background: color-mix(in srgb, var(--fg) 75%, transparent); color: var(--bg); }
.rail.live .rail-y span, .rail.scrolling .rail-y span { opacity: 1; }
.chip-date {
  position: absolute; right: 0; z-index: 4;
  width: 78px; transform: translateY(-100%);
  font-size: 11px; font-weight: 600; text-align: center;
  padding: 4px 2px 6px;
  background: var(--panel); color: var(--fg);
  border-bottom: 2px solid var(--fg);
  border-radius: 8px 8px 0 0;
  pointer-events: none; white-space: nowrap;
  opacity: 0; transition: opacity .15s;
}
.rail.live ~ .chip-date, .rail.scrolling ~ .chip-date { opacity: 1; }
/* the photo search: its view over the gallery, its rail the full height beside it, as the gallery's */
#seekpane { position: absolute; inset: 0; z-index: 3; }
#seekpane .railbox { position: absolute; top: 0; right: 0; bottom: 0; width: var(--rail); z-index: 4; }
.scrim { position: absolute; inset: 0; background: var(--scrim); z-index: 8; }
/* the sheet: a card from the bottom edge, never taller than the page, scrolls inside. --gutter centres the content on wide screens. */
.sheet {
  --gutter: max(16px, calc(50% - 360px));
  position: absolute; left: 0; right: 0; bottom: 0; z-index: 9;
  max-height: calc(100% - 32px); overflow: hidden auto; overscroll-behavior: none;
  padding: 18px var(--gutter) calc(16px + env(safe-area-inset-bottom, 0px));
  display: grid; gap: 12px; align-content: start;
  background: var(--panel); color: var(--fg); box-shadow: 0 28px 70px rgba(0, 0, 0, .35);
  border-top: 1px solid var(--line); border-radius: 16px 16px 0 0;
}
.sheet h2 { margin: 0; font-size: 17px; font-weight: 650; letter-spacing: -0.02em; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sheet .row { display: flex; align-items: center; gap: 10px; min-height: 36px; }
.sheet .row svg { width: 18px; height: 18px; flex: 0 0 18px; }
.sheet .row .body { flex: 1; min-width: 0; }
.sheet .name { font-weight: 600; font-size: 14px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sheet .meta { font-size: 12px; color: var(--muted); }
.sheet input, .sheet select { height: 36px; border: 0; border-bottom: 1px solid var(--line); background: transparent; color: var(--fg); font-size: 14px; outline: none; min-width: 0; }
.sheet input { flex: 1; }
.sheet .go { height: 34px; padding: 0 16px; border: 0; border-radius: 999px; background: var(--btn); color: var(--on-btn); font-size: 13px; font-weight: 600; }
.sheet .alt { height: 34px; padding: 0 12px; border: 1px solid var(--line); border-radius: 999px; background: transparent; font-size: 13px; }
/* the search pane, Files and Photos alike: under the header, over the screen, from its top edge; the field is the header. Empty query:
   chips (Photos) or rows (Files: Go to, Commands); text: what it finds. --gutter centres the rows on wide screens. */
.view.searchpane { --gutter: max(16px, calc(50% - 360px)); position: absolute; inset: 0; z-index: 3; padding-top: var(--top); padding-bottom: env(safe-area-inset-bottom, 0px); background: var(--bg); }
.searchpane .hits { padding: 8px var(--gutter) 6px; }
.searchpane .grp { font-size: 10px; letter-spacing: 0.12em; text-transform: uppercase; color: var(--muted); padding: 10px 4px 4px; }
.searchpane .hit {
  display: flex; justify-content: space-between; align-items: baseline; gap: 12px;
  padding: 8px 6px; font-size: 16px; border-radius: 8px;
  width: 100%; background: none; border: 0; text-align: left;
}
.searchpane .hit > span:first-child { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.searchpane .hit.on, .searchpane .hit:hover { background: var(--hit); }
.searchpane .hit .k { flex: none; font-size: 11px; color: var(--muted); letter-spacing: 0.06em; text-transform: uppercase; }
/* a file hit: its name, where it lives as crumbs (Photos › 2024) on the line below */
.searchpane .hit .in { display: block; margin-top: 2px; font-size: 12px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; }
.searchpane .hit .in .sep { opacity: .45; margin: 0 4px; }
.searchpane .seek-note { padding: 56px 24px; text-align: center; color: var(--muted); display: grid; gap: 12px; justify-items: center; font-size: 13px; font-variant-numeric: tabular-nums; }
.searchpane .seek-note .go { height: 40px; padding: 0 22px; border: 0; border-radius: 999px; background: var(--btn); color: var(--on-btn); font-weight: 600; }
.searchpane .facets { padding: 12px var(--gutter) 24px; display: grid; gap: 14px; }
.searchpane .hits .facets { padding: 4px 0 12px; }
.searchpane .hits .facets:empty { display: none; }
.searchpane .facet .meta { font-size: 12px; color: var(--muted); margin-bottom: 6px; }
.searchpane .facet .meta:empty { display: none; }
/* the acts of the folder in view come first, and this line is where they end */
.searchpane .facets hr { height: 1px; margin: 0; border: 0; background: var(--line); }
/* settings: sections of rows — name, a line of meta, one act at the right */
.settings { --gutter: max(16px, calc(50% - 360px)); padding: 8px var(--gutter) calc(24px + env(safe-area-inset-bottom, 0px)); overscroll-behavior: none; }
.settings .section { padding: 14px 0 6px; }
.settings h2 { margin: 0 0 4px; font-size: 12px; letter-spacing: .1em; text-transform: uppercase; color: var(--muted); font-weight: 600; }
.settings .row { display: flex; align-items: center; gap: 12px; min-height: 56px; padding: 8px 0; border-bottom: 1px solid var(--line); }
.settings .row .body { flex: 1; min-width: 0; }
.settings .name { font-size: 15px; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } /* a long name is cut like its meta, never five lines beside two buttons */
.settings .meta { font-size: 12px; color: var(--muted); margin-top: 2px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.settings .section.wrap .meta { white-space: normal; overflow-wrap: anywhere; }
.settings .row .alt { flex: none; height: 32px; padding: 0 12px; border: 1px solid var(--line); border-radius: 999px; background: transparent; font-size: 13px; white-space: nowrap; }
.settings .row svg { width: 18px; height: 18px; flex: 0 0 18px; }
.settings .row input { flex: 1 1 0; min-width: 0; height: 32px; padding: 0 12px; border: 1px solid var(--line); border-radius: 999px; background: transparent; color: var(--fg); font-size: 13px; outline: none; -webkit-appearance: none; } /* a row of fields (Follow a link) fits the width: nothing scrolls sideways; the pill of the buttons beside it */
.settings .row input:focus { border-color: var(--fg); }
.settings .row input[type="password"] { flex: 0 1 110px; }
.settings .row .go { flex: none; height: 32px; padding: 0 14px; border: 0; border-radius: 999px; background: var(--btn); color: var(--on-btn); font-size: 13px; font-weight: 600; white-space: nowrap; }
.settings { overflow-x: hidden; }
.settings .row.pick { flex-wrap: wrap; row-gap: 8px; }
.settings .row.pick .body { flex: 1 1 160px; } /* the name keeps its room: too many choices go under it */
.settings .choices { display: flex; flex-wrap: wrap; gap: 6px; }
.settings .row .alt.on { background: var(--btn); border-color: var(--btn); color: var(--on-btn); }
.settings .row.sub { padding-left: 16px; } /* a burst under its day (Activity) */
.settings pre.diag { max-height: 50vh; overflow-y: auto; margin: 8px 0; padding-bottom: 8px; border-bottom: 1px solid var(--line); font: 11px/1.5 ui-monospace, SFMono-Regular, Menlo, monospace; white-space: pre-wrap; word-break: break-word; color: var(--muted); user-select: text; -webkit-user-select: text; }
/* the drive's gauge under the Files root: the household's bytes against what is included, a segment per drive, this one
   bright. On an iPhone it drops into the home indicator's band (34 px): 14 px from the edge, the line just clear of it */
.foot { flex: none; padding: 12px 32px max(12px, calc(env(safe-area-inset-bottom, 0px) - 20px)); }
.gauge .track { display: flex; gap: 2px; height: 3px; border-radius: 2px; overflow: hidden; background: var(--tile); mask-image: linear-gradient(90deg, #000 70%, transparent); } /* no right edge: the terabyte included is not a wall */
.gauge .track i { display: block; height: 100%; background: var(--fg); opacity: .35; }
.gauge .track i.me { opacity: 1; }
.gauge .meta { margin-top: 8px; font-size: 12px; color: var(--muted); text-align: center; }
.gauge .meta .link { padding: 0; border: 0; background: none; font: inherit; color: var(--fg); text-decoration: underline; text-underline-offset: 2px; }
/* A chip: a word and its count, in the search's facets and under a picture (the words it looks like). */
.chips { display: flex; flex-wrap: wrap; gap: 6px; }
.chip { height: 30px; padding: 0 12px; border: 0; border-radius: 999px; background: var(--tile); color: inherit; font-size: 13px; cursor: pointer; }
.chip span { color: var(--muted); margin-left: 4px; font-variant-numeric: tabular-nums; }
.chip.on { background: var(--btn); color: var(--on-btn); }
.chip.on span { color: inherit; opacity: .7; }
/* Photo search: one line per family, its name at the left, lined up with the grid — the same empty or above the hits,
   on a phone or a desk. A line never wraps, it slides sideways; a count holds its width (inline min-width, in digits).
   A chip without a photo under the other filters dims in place; a funnel's step (a city, a month) is outlined. */
.searchpane .facets.rows { grid-template-columns: minmax(0, 1fr); gap: 8px; padding: 12px 0 12px 16px; }
.searchpane .facets.rows .facet { display: flex; align-items: flex-start; gap: 8px; }
.searchpane .facets.rows .facet .meta { display: block; flex: none; width: 56px; margin: 0; line-height: 30px; }
.searchpane .facets.rows .chips { flex: 1; min-width: 0; flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; padding-right: 16px; }
.searchpane .facets.rows .chip { flex: none; white-space: nowrap; }
.searchpane .facets.rows .chip span { display: inline-block; text-align: left; }
.searchpane .facets.rows .chip:disabled { opacity: .35; }
.searchpane .facets.rows .chip.sub:not(.on) { background: none; box-shadow: inset 0 0 0 1px var(--line); }
.busy {
  position: fixed; bottom: calc(16px + env(safe-area-inset-bottom, 0px)); left: 50%; transform: translateX(-50%); z-index: 40;
  padding: 8px 16px; border-radius: 999px; background: var(--panel);
  color: var(--fg); font-size: 13px; pointer-events: none;
  border: 1px solid var(--line);
  white-space: nowrap; max-width: calc(100vw - 32px); overflow: hidden; text-overflow: ellipsis; /* a pill is one line, whatever it says */
}
/* the work pill (photos.js): same pill, digits that keep their width, the progress as a fill behind the text */
#workbadge {
  white-space: nowrap; font-variant-numeric: tabular-nums; overflow: hidden; pointer-events: auto; cursor: pointer; user-select: none;
  background: linear-gradient(90deg, var(--line) var(--p, 0%), transparent 0), var(--panel);
  transition: background-position .3s;
}
#workbadge .pct { display: inline-block; min-width: 3.4ch; text-align: right; }
.view { position: relative; flex: 1; min-height: 0; overflow: auto; scrollbar-width: none; overscroll-behavior: none; }
.view::-webkit-scrollbar { display: none; }
.lightbox { position: fixed; inset: 0; z-index: 50; background: #000; display: grid; place-items: center; }
.lightbox .pv img, .lightbox .pv video { max-width: 100%; max-height: 100%; object-fit: contain; }
/* a photo: header (Back, name, date, the star) · Google's caption · the picture · its look-alikes in a carousel, four in view, snapping */
/* minmax(0,1fr): the carousel's tiles are square and definite, so an auto column would grow to the whole strip. */
.lightbox.photo { grid-template-columns: minmax(0, 1fr); grid-template-rows: auto auto 1fr auto auto; place-items: stretch; color: #f3f1ec; }
.lightbox.photo .hdr { background: #000; z-index: 2; }
.lightbox.photo .star { font-size: 20px; color: inherit; cursor: pointer; }
/* always in the grid, empty when Google kept nothing: the rows below keep their places */
.lightbox.photo .about { padding: 0 16px; text-align: center; font-size: 13px; line-height: 1.35; background: #000; }
.lightbox.photo .about:not(:empty) { padding: 8px 16px; }
.lightbox.photo .about .people { opacity: .7; }
.lightbox.photo .about .was { font-size: 11px; opacity: .5; }
.lightbox.photo .media { min-height: 0; position: relative; z-index: 0; overflow: hidden; background: #000; }
.lightbox.photo .media > * { position: absolute; inset: 0; width: 100%; height: 100%; max-height: none; object-fit: contain; }
.lightbox.photo .media img.full, .lightbox.photo .media video { opacity: 0; pointer-events: none; }
.lightbox.photo .media img.full.on, .lightbox.photo .media video.on { opacity: 1; pointer-events: auto; transition: opacity .18s ease; }
/* A Live Photo's motion: over the still, never in the way of the tap that closes the viewer. */
.lightbox.photo .media video.live { opacity: 1; pointer-events: none; }
.lightbox.photo .media:has(video.on) .warm, .lightbox.photo .media:has(img.full.on) .warm { opacity: 0; }
.lightbox.photo .media video:not(.on)::-webkit-media-controls { display: none; }
.lightbox.photo .media .note { display: grid; place-items: center; color: #fff; font-size: 13px; pointer-events: none; }
.lightbox .playbar, .lightbox .look { position: relative; z-index: 2; background: #000; }
.lightbox .scrub { display: flex; gap: 2px; height: 48px; }
.lightbox .scrub .slot { flex: 1; min-width: 0; padding: 0; border: 0; background: #1a1a1a; overflow: hidden; cursor: pointer; }
.lightbox .scrub .slot img, .lightbox .scrub .slot canvas { width: 100%; height: 100%; object-fit: cover; display: block; }
.lightbox .scrub .slot.on { outline: 2px solid #fff; outline-offset: -2px; }
.lightbox .playbar .t { font-size: 11px; opacity: .55; padding: 4px 8px 8px; font-variant-numeric: tabular-nums; }

.lightbox .grab { display: flex; justify-content: center; align-items: center; width: 100%; height: 18px; padding: 0; border: 0; background: none; cursor: ns-resize; touch-action: none; }
.lightbox .grab::before { content: ""; width: 36px; height: 4px; border-radius: 999px; background: rgba(255,255,255,.4); }
.lightbox .look { padding-bottom: env(safe-area-inset-bottom, 0px); }
.lightbox .look.off .similar { display: none; }
/* The words the picture looks like, under its caption: the search's chips, centred like the caption, on the viewer's black. */
.lightbox.photo .about .tags { justify-content: center; margin-top: 10px; }
.lightbox.photo .about .tags:first-child { margin-top: 0; }
.lightbox.photo .about .chip { background: #1a1a1a; color: #f3f1ec; }
.lightbox.photo .about .chip span { color: rgba(243,241,236,.55); }
/* One tile tall, always: a status message leaves the strip the height it has with look-alikes in it. */
.lightbox .similar { display: flex; gap: 2px; height: calc((100vw - 6px) / 4); overflow: auto hidden; overscroll-behavior: none; scroll-snap-type: x mandatory; scrollbar-width: none; background: #000; }
.lightbox .similar::-webkit-scrollbar { display: none; }
.lightbox .similar .th { flex: 0 0 calc((100% - 6px) / 4); scroll-snap-align: start; cursor: pointer; }
@media (min-width: 768px) {
  .lightbox .similar { height: calc((100vw - 14px) / 8); }
  .lightbox .similar .th { flex-basis: calc((100% - 14px) / 8); }
}
.lightbox .similar-status { flex: 1; display: grid; place-items: center; padding: 0 12px; font-size: 12px; color: rgba(243,241,236,.6); text-align: center; }

/* § import: tick rows in the Takeout sheet, full-window dropzone while dragging files */
.sheet label.row { cursor: pointer; }
.sheet input[type="checkbox"] { flex: 0 0 16px; width: 16px; height: 16px; margin: 0; border: 0; accent-color: var(--fg); }
.dropzone {
  position: fixed; inset: 12px; z-index: 45; display: none; align-items: center; justify-content: center;
  border: 2px dashed var(--fg); border-radius: 16px; background: var(--scrim); color: var(--fg);
  font-size: 17px; font-weight: 600; pointer-events: none;
}
body.dropping .dropzone { display: flex; }

/* Palette forced by the deck (html[data-scheme]); the OS decides otherwise */
html[data-scheme="light"] {
  color-scheme: light;
  --bg: #efece6; --fg: #1a1916; --muted: #6b6560; --line: #ddd6cc; --btn: #1a1916; --on-btn: #f3f1ec;
  --tile: #ddd6cc; --panel: #f6f3ed; --scrim: rgba(26, 25, 22, .4); --hit: rgba(26, 25, 22, .06);
}
html[data-scheme="dark"] {
  color-scheme: dark;
  --bg: #0c0c0b; --fg: #f3f1ec; --muted: #8a847c; --line: #3a3632; --btn: #f3f1ec; --on-btn: #0c0c0b;
  --tile: #1c1b19; --panel: #161513; --scrim: rgba(0, 0, 0, .45); --hit: rgba(243, 241, 236, .08);
}
html[data-scheme="light"] .th.t0 { background: #e7e2d8 } html[data-scheme="light"] .th.t1 { background: #ddd6cc } html[data-scheme="light"] .th.t2 { background: #d3cbc0 } html[data-scheme="light"] .th.t3 { background: #c9c0b4 }
html[data-scheme="light"] .th.t4 { background: #bfb5a8 } html[data-scheme="light"] .th.t5 { background: #b5aa9c } html[data-scheme="light"] .th.t6 { background: #ab9f90 } html[data-scheme="light"] .th.t7 { background: #a19484 }
html[data-scheme="dark"] .th.t0 { background: #cfc8bc } html[data-scheme="dark"] .th.t1 { background: #b9b2a6 } html[data-scheme="dark"] .th.t2 { background: #a39c90 } html[data-scheme="dark"] .th.t3 { background: #8e877c }
html[data-scheme="dark"] .th.t4 { background: #7a7469 } html[data-scheme="dark"] .th.t5 { background: #676157 } html[data-scheme="dark"] .th.t6 { background: #524d45 } html[data-scheme="dark"] .th.t7 { background: #3f3b35 }

/* Design B (body.design-b, picked on the deck): quieter chrome on the same DOM */
.design-b .lock .name { display: none; }
.design-b .ttl { text-align: left; left: 52px; }
.design-b .ttl .app { font-size: 17px; }
.design-b .ttl .place { display: inline; font-size: 17px; font-weight: 650; opacity: 1; margin: 0; }
.design-b .ttl .place::before { content: " · "; opacity: .45; }
.design-b .ttl .place:empty::before { content: none; }
.design-b .rail { right: auto; left: 0; }
.design-b .chip-date { right: auto; left: 0; }
.design-b .q-row .meta { margin-top: 0; }
.design-b .q-row { height: 52px; }
