:root {
  --cream: #f3efe6;
  --paper: #fbf9f4;
  --ink: #14130f;
  --muted: #6f6857;
  --line: #ddd6c7;
  --line2: #cfc7b5;
  --go: #1f6f4a;
  --no: #9a2b2b;
  --dark: #070709;
  --shadow: 0 20px 60px rgba(20, 19, 15, 0.28);
}
* { box-sizing: border-box; }
html, body { margin: 0; }
body { background: var(--cream); color: var(--ink); min-height: 100vh;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; }
a { color: inherit; }
.skip-link { position:fixed; left:14px; top:10px; z-index:500; transform:translateY(-160%); padding:11px 15px;
  border-radius:9px; background:var(--ink); color:var(--cream); font-weight:700; text-decoration:none; }
.skip-link:focus { transform:none; }
:where(button, a, input, select, [tabindex]):focus-visible { outline:3px solid #2774d8; outline-offset:3px; }

/* ============ chrome (brand + view toggle + filters) ============ */
.chrome { position: sticky; top: 0; z-index: 30; background: var(--cream);
  border-bottom: 1px solid var(--line); padding: 14px 22px 10px; transition: opacity .4s; }
.bar { display: flex; align-items: center; justify-content: space-between; gap: 16px; max-width: 1280px; margin: 0 auto; }
.logo { margin:0; font-weight: 800; letter-spacing: 0.17em; font-size: clamp(20px, 3vw, 28px); line-height:1; transition: color .35s; }
.views { position: relative; display: inline-flex; background: var(--paper); border: 1px solid var(--line); border-radius: 999px; padding: 4px; }
.view { position: relative; z-index: 1; flex: 1 1 0; min-width: 134px; text-align: center; white-space: nowrap; font: inherit; font-size: 13.5px;
  font-weight: 600; color: var(--muted); border: none; background: none; cursor: pointer; padding: 8px 16px; border-radius: 999px; transition: color .35s; }
.view .ic { opacity: .85; }
.view.is-active { color: var(--cream); }
.slider { position: absolute; top: 4px; bottom: 4px; left: 4px; width: calc(50% - 4px); background: var(--ink); border-radius: 999px; z-index: 0; transition: left .5s cubic-bezier(.55,0,.2,1), background .35s; }
body[data-view="closet"] .slider { left: 50%; }

.toolbar { max-width: 1280px; margin: 12px auto 0; display: flex; flex-wrap: wrap; align-items: center; gap: 9px; }
.filter-panel { display:contents; }
.filter-sheet-head, .filter-sheet-actions, .filter-sheet-backdrop, .mobile-summary { display:none; }
#q { flex: 1 1 220px; min-width: 170px; padding: 11px 15px; font-size: 16px; border: 1.5px solid var(--line); border-radius: 11px; background: var(--paper); color: var(--ink); outline: none; }   /* 16px: below it iOS Safari zooms the page on focus */
#q:focus { border-color: var(--ink); }
.facets { display: flex; flex-wrap: wrap; gap: 9px; }
.facet { position: relative; }
.facet-btn { font: inherit; font-size: 14px; font-weight: 600; cursor: pointer; padding: 10px 14px; border: 1.5px solid var(--line);
  border-radius: 11px; background: var(--paper); color: var(--ink); display: inline-flex; align-items: center; gap: 7px; transition: background .3s, color .3s, border-color .3s; }
.facet-btn:hover { border-color: var(--line2); }
.facet.has-sel .facet-btn { border-color: var(--ink); }
.facet-btn .cnt { font-size: 11px; font-weight: 800; background: var(--ink); color: var(--cream); border-radius: 999px; padding: 1px 7px; min-width: 18px; text-align: center; }
.facet-btn .car { color: var(--muted); font-size: 11px; }
.facet-pop { position: absolute; z-index: 40; top: calc(100% + 6px); left: 0; width: 264px; max-height: 360px; display: none; flex-direction: column;
  background: var(--paper); border: 1px solid var(--line2); border-radius: 13px; box-shadow: var(--shadow); overflow: hidden; }
.facet.open .facet-pop { display: flex; }
.facet-search { margin: 10px; padding: 8px 11px; font-size: 16px; border: 1px solid var(--line); border-radius: 8px; background: var(--cream); outline: none; color: var(--ink); }   /* 16px: avoid iOS focus-zoom */
.facet-list { overflow-y: auto; padding: 2px 6px 8px; }
.facet-help { margin:9px 10px 4px; color:var(--muted); font-size:12px; line-height:1.35; }
.facet-loading { padding:14px 10px; color:var(--muted); font-size:12.5px; }
.opt { display: flex; align-items: center; gap: 9px; padding: 8px 9px; border-radius: 8px; cursor: pointer; font-size: 14px; color: var(--ink); }
.opt:hover { background: var(--cream); }
.opt input { accent-color: var(--ink); width: 15px; height: 15px; }
.opt .ov { flex: 1; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.opt .oc { color: var(--muted); font-size: 12px; font-variant-numeric: tabular-nums; }
.opt.hide { display: none; }
.sort { font-size: 13px; color: var(--muted); display: inline-flex; align-items: center; gap: 6px; margin-left: auto; }
.sort select { font: inherit; font-size: 14px; padding: 9px 11px; border: 1.5px solid var(--line); border-radius: 10px; background: var(--paper); color: var(--ink); }

.active { flex:1 0 100%; max-width: 1280px; margin: 1px auto 0; display: flex; flex-wrap: wrap; gap: 7px; }
.chip { font-size: 13px; font-weight: 600; background: var(--ink); color: var(--cream); border: none; border-radius: 999px; padding: 6px 8px 6px 12px; cursor: pointer; display: inline-flex; align-items: center; gap: 7px; }
.chip-face { width: 19px; height: 19px; border-radius: 50%; object-fit: cover; object-position: 50% 30%; flex: none; margin: -3px 0 -3px -6px; }   /* the guest chip wears their face — negative margins keep the pill height unchanged */
/* browse-with-a-filter escape hatch: same glass as the picks chip, and its MIRROR — top-left at the picks
   chip's top:64 line, tucked under the Filters trio it undoes. (Bottom corners are taken in browse: the title
   card rides bottom-left, the loupe bottom-right.) Touch-only like the chip — desktop clears via the doorway
   menu chips, and its vertical pill stack owns this corner. CSS gates the CONTEXT (closet view, browsing, not
   the intro); app.js render() gates the STATE ([hidden] unless a filter is on). */
.clear-filter { display: none; position: fixed; left: 12px; top: 64px; z-index: 55;
  align-items: center; gap: 8px; height: 44px; padding: 0 16px; border-radius: 999px; cursor: pointer;
  background: rgba(16,16,20,.44); border: 1px solid rgba(243,239,234,.16); color: rgba(243,239,234,.85);
  font: 600 12.5px "Helvetica Neue", Arial, sans-serif; letter-spacing: .02em;
  backdrop-filter: blur(16px); -webkit-backdrop-filter: blur(16px); }
.clear-filter .cfx { font-size: 13px; opacity: .75; }
body.is-touch[data-view="closet"]:not(.closet-inspecting):not(.closet-intro) .clear-filter:not([hidden]) { display: inline-flex; }
.clear-filter:active { background: rgba(28,28,34,.6); }
.chip .x { opacity: .7; font-size: 14px; }
.chip:hover .x { opacity: 1; }
.chip.clear { background: none; color: var(--no); border: 1.5px solid var(--no); padding: 5px 13px; }
.status { flex:1 0 100%; max-width: 1280px; margin: 1px auto 0; color: var(--muted); font-size: 13.5px; }
.status b { color: var(--ink); }

/* ============ the wall ============ */
main.wall { max-width: 1280px; margin: 0 auto; }
.grid { display: grid; gap: 22px 16px; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); padding: 18px 20px 48px; }
.tile { position: relative; border: none; background: none; padding: 0; cursor: pointer; text-align: left; font: inherit; color: inherit; display: block;
  /* offscreen tiles skip layout+paint entirely — scroll work tracks the ~35 visible tiles, not all ~1,327.
     `auto` memoizes each tile's real size once rendered (all tiles are equal-height per layout), so the
     scrollbar stays put; 280px only sizes never-rendered tiles below the fold. Older browsers ignore both. */
  content-visibility: auto; contain-intrinsic-size: auto 280px; }
.art { position: relative; width: 100%; border-radius: 8px; overflow: hidden; background: var(--paper); border: 1px solid var(--line); box-shadow: 0 6px 18px rgba(20,19,15,.10); transition: transform .12s, box-shadow .12s; }
/* hold a rock-solid 5:7 box via padding (iOS Safari can collapse an aspect-ratio box around an <img>) */
.art::before { content: ''; display: block; padding-bottom: 140%; }
.tile:hover .art { transform: translateY(-3px); box-shadow: 0 14px 30px rgba(20,19,15,.20); }
.art img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; display: block; }
.ph { position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; padding: 12px; background: linear-gradient(180deg, rgba(20,19,15,.04), rgba(20,19,15,0) 30%), var(--paper); }
.ph .c { font-weight: 800; letter-spacing: .12em; font-size: 10px; color: var(--muted); }
.ph .n { font-weight: 800; font-size: clamp(32px, 6vw, 44px); line-height: 1; margin: 8px 0; }
.ph .pt { font-family: Georgia, serif; font-size: 12.5px; line-height: 1.25; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }
.badge { position: absolute; top: 8px; left: 8px; font-weight: 800; font-size: 11px; letter-spacing: .03em; padding: 4px 8px; border-radius: 999px; background: rgba(20,19,15,.82); color: var(--cream); }
/* # of Criterion Closet picks — top-right (clear of the SPINE badge), gold accent, revealed only under the "Closet picks" sort */
.pick-badge { display: none; position: absolute; top: 8px; right: 8px; font-weight: 800; font-size: 11px; letter-spacing: .03em; padding: 4px 8px; border-radius: 999px; background: rgba(20,19,15,.86); color: #e6c074; box-shadow: 0 1px 6px rgba(20,19,15,.3); }
#grid.sort-picks .pick-badge { display: inline-block; }
/* The title sits in a FIXED-height slot (exactly two 18px lines = 36px). A normal block honours `height`
   reliably on iOS — unlike min-height on a -webkit-line-clamp box — so short and long titles reserve the
   identical space and every tile is the same height. Long titles clamp to 2 lines with an ellipsis. */
.cap { padding: 9px 3px 0; }
.cap .t-wrap { display: block; height: 36px; overflow: hidden; }
.cap .t { font-family: Georgia, "Times New Roman", serif; font-size: 15px; font-weight: 600; line-height: 18px;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.cap .y { color: var(--muted); font-size: 12.5px; line-height: 16px; display: block; margin-top: 3px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }   /* keep the year·country to one line */
.none { grid-column: 1 / -1; text-align: center; padding: 60px 18px; color: var(--muted); }
.none h3 { font-family: Georgia, serif; color: var(--ink); font-size: 22px; margin: 0 0 8px; }

.site-foot { text-align: center; color: var(--muted); font-size: 11.5px; padding: 14px 18px 28px; }
.dot { margin: 0 5px; opacity: .5; }

/* ============ The Closet — full-viewport overlay ============ */
.closet-overlay { position: fixed; inset: 0; z-index: 40; background: var(--dark);
  opacity: 0; transform: scale(1.06); pointer-events: none;
  transition: opacity .5s cubic-bezier(.55,0,.2,1), transform .55s cubic-bezier(.55,0,.2,1); }
.closet-overlay #closet-frame-host { position:absolute; inset:0; }
.closet-overlay iframe { width: 100%; height: 100%; border: 0; display: block; background: var(--dark); }
/* Share the inspected film — a top-level button (iOS Safari blocks Web Share inside an iframe), shown only while inspecting. */
/* Transparent tap-target laid over the closet's HUD share icon. Invisible (the icon shows through from the iframe
   below); it exists only so the share fires from the top-level page, which iOS requires. JS sets its rect + display. */
.share-hit { display: none; position: fixed; z-index: 56; background: transparent; border: 0; padding: 0; margin: 0; cursor: none; -webkit-tap-highlight-color: transparent; }   /* cursor:none — desktop inspect draws its own ring; don't swap it for the OS hand here */
.share-toast { position: fixed; left: 50%; bottom: 32px; transform: translate(-50%, 12px); background: rgba(20,20,26,.92); color: #f1ece0; font: inherit; font-size: 13.5px; font-weight: 500; letter-spacing: .2px; padding: 10px 18px; border-radius: 999px; border: 1px solid rgba(255,255,255,.14); -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px); box-shadow: 0 10px 30px rgba(0,0,0,.45); white-space: nowrap; opacity: 0; pointer-events: none; z-index: 60; transition: opacity .2s ease, transform .2s ease; }
.share-toast.show { opacity: 1; transform: translate(-50%, 0); }
/* the control hint rides TOP-centre, directly under the Closet Picks pill (that pill is top:20 with a
   46px min-height → its bottom edge is 66, so 76 leaves a 10px gap) — the two read as one centred stack. */
.closet-prompt { position: absolute; left: 50%; top: 76px; bottom: auto; transform: translateX(-50%); z-index: 2;
  background: rgba(12,12,14,.72); color: #e8e3d6; border: 1px solid rgba(244,241,234,.16); border-radius: 999px;
  padding: 9px 18px; font-size: 13px; opacity: 0; transition: opacity .4s; pointer-events: none; }
.closet-prompt b { color: #fff; }

.flash { position: fixed; inset: 0; background: var(--dark); opacity: 0; pointer-events: none; transition: opacity .26s ease; z-index: 90; }
.flash.on { opacity: .92; }

/* loading veil — hides the one-time label generation so titles never pop in */
.closet-loader { position: fixed; inset: 0; z-index: 85; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 11px;
  background: radial-gradient(120% 120% at 50% 36%, #16161c 0%, #07070a 78%); opacity: 0; pointer-events: none; transition: opacity .5s ease; }
.cl-brand { font-weight: 800; letter-spacing: .34em; font-size: 15px; color: #cfc9bb; }
.cl-sub { font-family: Georgia, "Times New Roman", serif; font-style: italic; font-size: 14.5px; color: #8c887e; animation: clpulse 1.4s ease-in-out infinite; }
@keyframes clpulse { 0%, 100% { opacity: .5 } 50% { opacity: 1 } }
/* appear INSTANTLY to cover loading (no fade-in, or the splash bleeds through while it ramps up);
   the fade only plays on the way out, when the base .5s transition takes over as the class is removed */
body.closet-loading #closet-loader { opacity: 1; pointer-events: auto; transition: none; }

/* ---- closet mode: go full immersive, float the chrome over the 3D ---- */
body[data-view="closet"] .closet-overlay { opacity: 1; transform: none; pointer-events: auto; }
/* in the closet, touch never scrolls the page — one-finger drag is look */
body[data-view="closet"] { overflow: hidden; overscroll-behavior: none; }
body[data-view="closet"] .closet-overlay, body[data-view="closet"] #closet-frame, body[data-view="closet"] .chrome { touch-action: none; }
/* in the List, drop the fixed closet iframe out of hit-testing immediately so iOS can't catch a scroll
   on it. The flash blink masks the swap; going back to the closet, opacity still fades in. */
body[data-view="wall"] .closet-overlay { visibility: hidden; }
body[data-view="closet"] .closet-prompt { opacity: 1; }
/* mobile: keep the how-to tiny and at the TOP so it never collides with the bottom HUD */
/* mobile: no top hint — the "Enter the Closet" splash already teaches the controls */
body.is-touch .closet-prompt { display: none !important; }
@media (pointer: coarse) { .closet-prompt { display: none !important; } }
body[data-view="closet"] main.wall,
body[data-view="closet"] .site-foot { display: none; }

/* the chrome becomes a centered glassmorphic panel (this is the "Esc menu"). The big
   100vmax shadow dims the whole view but captures no clicks, so clicking the dimmed
   closet around the card re-locks you back in. */
/* CSS-3D stage: the menu is a FIXED object bolted in the doorway — only the camera moves around it */
#chrome-stage, #chrome-cam { display: contents; }
body[data-view="closet"] #chrome-stage {
  display: block; position: fixed; inset: 0; z-index: 60; overflow: hidden; pointer-events: none;
}
body[data-view="closet"] #chrome-cam {
  display: block; position: absolute; top: 50%; left: 50%; width: 0; height: 0;
  transform-style: preserve-3d; transform-origin: 0 0;
}
body[data-view="closet"] .chrome {
  position: absolute; top: 0; left: 0; pointer-events: auto;
  opacity: 0;   /* hidden until the world projection places it — never flashes at the top-left during load */
  width: 520px; border-bottom: none;
  border: 1px solid rgba(255,255,255,.16); border-radius: 22px;
  background: rgba(19,19,25,.64);
  backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px);   /* lighter blur, no saturate: the panel's transform is rewritten every look-frame, re-sampling the live WebGL behind it */
  box-shadow: 0 30px 90px rgba(0,0,0,.5), inset 0 1px 0 rgba(255,255,255,.08);
  padding: 18px 22px 16px; transition: opacity .2s ease, filter .35s ease;
  transform-style: flat;
}
body.closet-loading .chrome { opacity: 0 !important; }   /* keep the menu out of the loading veil */
body[data-view="wall"] .chrome { opacity: 1; transition: none; }   /* List top bar is always solid — no fade-from-closet that can stick */
/* while the splash is up, keep the shell's chrome/prompt/cursor out of the way — but ONLY in the closet:
   if the intro flag lingers after toggling to the List, the List's top bar must still show. */
body[data-view="closet"].closet-intro .chrome,
body[data-view="closet"].closet-intro .closet-prompt,
body[data-view="closet"].closet-intro #x-cursor,
body[data-view="closet"].closet-intro .esc-hint { opacity: 0 !important; pointer-events: none !important; }
/* inspect: the doorway menu is a WORLD object, so for a film near a wall (far-left/right of the shelf) it
   projects straight onto the left summary card. Fade it out while holding a case — the closet's own inspect
   HUD owns the screen, and the menu fades back in (its .2s transition) the moment the case goes back. */
body[data-view="closet"].closet-inspecting .chrome { opacity: 0 !important; pointer-events: none !important; }

/* a List/Closet switch pinned top-right. On a phone it stays up the whole time in the closet (the
   doorway panel's toggle isn't reachable there); on ANY platform it also shows on the start-screen
   splash, while the room loads (the escape hatch if the load drags), and in the Esc menu. It now also
   rides desktop browse, sharing the corner with the Esc pill rather than colliding with it (see below). */
.closet-toggle { display: none; position: fixed; top: 12px; right: 12px; z-index: 70; gap: 0; padding: 4px;
  background: rgba(20,20,26,.5); border: 1px solid rgba(255,255,255,.16); border-radius: 999px;
  backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px); opacity: .9; transition: opacity .2s; }
body.is-touch[data-view="closet"] .closet-toggle,
body[data-view="closet"].closet-intro .closet-toggle,
body.closet-loading[data-view="closet"] .closet-toggle { display: inline-flex; }
body.is-touch[data-view="closet"]:not(.closet-intro) .closet-toggle { top: 17px; }   /* centre-align with the 42px circle stack (top 16 + 21 = 37 = 17 + 40/2) — the base top:12 sat it 5px high */
/* on the splash, sit it exactly where the List view's bar toggle lands — same top, and right-aligned to
   the centred max-width:1280 bar (22px gutter ≤1324px, growing past that) — so toggling doesn't jump */
body[data-view="closet"].closet-intro .closet-toggle { top: 14px; right: calc(22px + max(0px, (100vw - 1324px) / 2)); opacity: 1; }
@media (max-width: 640px) { body[data-view="closet"].closet-intro .closet-toggle { top: 10px; right: 12px; } }
.closet-toggle:active { opacity: 1; }
body.closet-inspecting .closet-toggle { display: none !important; }   /* inspect: the closet's own "Add to a list" pill owns the top-right corner instead */
/* DESKTOP BROWSE: the way back to the List sits in the corner, now alone there (the Esc pill is retired) —
   so it keeps the 12px gutter and mirrors the quickbar opposite it: that bar is top:15 with a 50px height,
   centre 40; this pill is 42 tall, so 40 - 21 = 19. The two read as one line across the top. */
body[data-view="closet"]:not(.is-touch):not(.closet-intro):not(.closet-inspecting):not(.closet-loading):not(.closet-menu) .closet-toggle {
  display: inline-flex; top: 19px; right: 12px; }
.ct-btn { font: inherit; font-size: 13.5px; font-weight: 600; white-space: nowrap; cursor: pointer;
  border: none; background: none; color: rgba(243,239,230,.72); padding: 8px 16px; border-radius: 999px; }   /* no line-height override → matches .view height exactly */
.ct-btn.is-active { background: var(--cream); color: var(--ink); }
/* closet view: a vertical pill-stack top-left — Filters (spins to the menu) + Buy me a coffee */
.closet-actions { display: none; position: fixed; top: 17px; left: 12px; z-index: 70;   /* top tuned so the first pill's centre lines up with the taller List/Closet toggle */
  flex-direction: column; align-items: flex-start; gap: 8px; }
body[data-view="closet"] .closet-actions { display: flex; }
body[data-view="closet"].closet-intro .closet-actions,
body.closet-inspecting .closet-actions { display: none; }            /* hide on the splash and while holding a case */
.closet-filter, .closet-coffee, .closet-discord, .closet-dice {
  display: inline-flex; align-items: center; gap: 7px; text-decoration: none;
  padding: 7px 12px 7px 11px; background: rgba(20,20,26,.5); border: 1px solid rgba(255,255,255,.16); border-radius: 999px;
  backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px); color: rgba(243,239,230,.92);
  font: inherit; font-size: 13.5px; font-weight: 600; cursor: pointer; opacity: .9;
  transition: opacity .2s, transform .12s, background .15s; }
.closet-filter:hover, .closet-coffee:hover, .closet-discord:hover, .closet-dice:hover { opacity: 1; background: rgba(34,34,42,.62); transform: translateY(-1px); }
.closet-filter:active, .closet-coffee:active, .closet-discord:active, .closet-dice:active { transform: translateY(0); }
/* the Share pill — FROSTED glass (it floats in the pill-stack over the room, so it follows the chrome language, not
   the cream of committed panel/modal actions); a brighter cream hairline + label + full opacity mark it as the goal
   among the quieter sibling pills. Shown only at 6/6 (app.js clears [hidden]); [S] hint auto-hides on touch. */
.closet-share { display: inline-flex; align-items: center; gap: 7px; padding: 7px 13px 7px 12px; border-radius: 999px;
  font: inherit; font-size: 13.5px; font-weight: 700; cursor: pointer;
  background: rgba(22,19,14,.6); border: 1px solid rgba(243,238,228,.26); color: rgba(243,238,228,.96);
  backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px);
  box-shadow: 0 6px 18px -8px rgba(0,0,0,.5); transition: background .15s, border-color .15s, transform .12s; animation: shareIn .42s cubic-bezier(.2,.9,.3,1) both; }
.closet-share[hidden] { display: none; }
.closet-share:hover { background: rgba(30,26,19,.7); border-color: rgba(243,238,228,.4); transform: translateY(-1px); }
.closet-share:active { transform: translateY(0); }
.closet-share .cf-key { color: rgba(243,238,228,.72); border-color: rgba(243,238,228,.32); }
@keyframes shareIn { from { opacity: 0; transform: translateY(-7px) scale(.95); } to { opacity: 1; transform: none; } }
/* Filters + Random share the top of the stack. Desktop: stacked (Random keeps its label + R key). Mobile: side-by-side, dice icon-only — "just the dice icon next to Filters". */
.ca-top { display: flex; flex-direction: column; align-items: flex-start; gap: 8px; }
body.is-touch .ca-top { flex-direction: row; align-items: center; }

/* ───── browse chrome, two modes (desktop pointer-lock) ─────
   LOOK-AROUND (locked): the pills recede into a quiet keycap legend — you press the key, you don't click.
   CURSOR (Esc → free): they stay the familiar clickable menu (the frosted pills); coffee lives there. */
/* the legend is the DEFAULT browse chrome (fresh step-in AND while looking around); the clickable pills appear only
   after a deliberate Esc (body.closet-menu). Desktop only — touch keeps the tappable pills. */
body:not(.is-touch) .closet-actions, body:not(.is-touch) .ca-top { gap: 9px; }
/* ONE frosted-glass card holds the desktop legend/menu (same language as the tray + Polaroid) — a quiet labelled
   key-card while you look around, the SAME card enlarged + centred when you Esc to the cursor menu. Replaces the old
   dark corner blob / oval entirely; the card itself grounds the labels against the bright spines. */
body:not(.is-touch) .closet-actions {
  pointer-events: none;                                    /* display-only legend; the keys do the work (a click falls through → re-lock) */
  padding: 9px 12px 8px; border-radius: 13px;
  background: rgba(13,12,15,.54);
  -webkit-backdrop-filter: blur(11px) saturate(1.1) brightness(.9); backdrop-filter: blur(11px) saturate(1.1) brightness(.9);
  border: 1px solid rgba(243,238,228,.13);
  box-shadow: inset 0 1px 0 rgba(255,250,240,.14), 0 16px 40px -18px rgba(0,0,0,.7); }
body:not(.is-touch) .closet-actions::before { display: none; }
body:not(.is-touch) .closet-share,
body:not(.is-touch) .closet-filter,
body:not(.is-touch) .closet-dice,
body:not(.is-touch) .closet-discord,
body:not(.is-touch) .closet-coffee {
  background: none; border: none; box-shadow: none; padding: 0; gap: 9px; opacity: 1; transform: none;
  -webkit-backdrop-filter: none; backdrop-filter: none; }   /* compact, content-width rows, left-aligned (the icon sits right after its label) */
body:not(.is-touch) .closet-actions .cf-ic { order: 1; display: block; width: 18px; height: 18px; opacity: .9; }   /* icon TRAILS on the right — a clear, language-independent cue (carries meaning for non-English readers) */
body:not(.is-touch) .closet-actions .cf-tx {
  font: 600 11.5px/1 inherit; letter-spacing: .16em; text-transform: uppercase; color: rgba(243,238,228,.9); }   /* the action label is the hero */
body:not(.is-touch) .closet-actions .cf-key {                                  /* the keyboard key LEADS on the left — big keycap */
  order: -1; margin: 0; padding: 0; width: 22px; height: 22px; flex: 0 0 auto; display: inline-grid; place-items: center;
  border: 1px solid rgba(243,238,228,.42); border-radius: 5px; background: rgba(12,10,7,.5);
  font: 600 10.5px/1 inherit; line-height: 1; letter-spacing: 0; color: rgba(243,238,228,.97); text-shadow: 0 1px 2px rgba(0,0,0,.7); }
body:not(.is-touch) .closet-share .cf-key { border-color: rgba(243,238,228,.75); color: #fff; box-shadow: 0 0 16px rgba(243,238,228,.16); }
body:not(.is-touch) .closet-share .cf-tx { color: rgba(243,238,228,.94); }
body:not(.is-touch) .closet-coffee, body:not(.is-touch) .closet-discord { display: none; }                         /* coffee → the cursor menu (its B shortcut still works for those who know it) */
.ca-esc { display: none; }
/* the Esc hint rides the TOP-RIGHT on its own, styled to MATCH the top-left legend card — same frosted glass, same
   keycap + uppercase label — just the one Esc row. Shown through BROWSE (locked or free-cursor — Safari never locks),
   hidden on the splash / while inspecting (Esc means "put it back" there) / in the centered menu (the corner's toggle
   returns). Display-only. */
body[data-view="closet"]:not(.is-touch):not(.closet-intro):not(.closet-inspecting):not(.closet-loading):not(.closet-menu) .ca-esc { display: inline-flex; align-items: center; gap: 10px; cursor: pointer;
  position: fixed; top: 17px; right: 12px; z-index: 71; margin: 0; padding: 9px 13px 8px 11px; border-radius: 13px;
  background: rgba(13,12,15,.54); border: 1px solid rgba(243,238,228,.13);
  -webkit-backdrop-filter: blur(11px) saturate(1.1) brightness(.9); backdrop-filter: blur(11px) saturate(1.1) brightness(.9);
  box-shadow: inset 0 1px 0 rgba(255,250,240,.14), 0 16px 40px -18px rgba(0,0,0,.7); }
.ca-esc kbd { display: inline-grid; place-items: center; height: 22px; padding: 0 6px; flex: 0 0 auto;   /* the keycap, matched to the legend's */
  font: 600 10.5px/1 "Helvetica Neue",Arial,sans-serif; letter-spacing: 0; color: rgba(243,238,228,.97);
  border: 1px solid rgba(243,238,228,.42); border-radius: 5px; background: rgba(12,10,7,.5); text-shadow: 0 1px 2px rgba(0,0,0,.7); }
.ca-esc .ca-esc-lab { font: 600 11.5px/1 "Helvetica Neue",Arial,sans-serif; letter-spacing: .16em; text-transform: uppercase; color: rgba(243,238,228,.9); }   /* the label, matched to the legend's */
/* Esc always means "Menu" now (Your Picks moved to the V shortcut) — no label swap. */

/* Esc → the cursor MENU: the legend lifts off the corner into a bigger, CENTERED menu over a blurred + dimmed
   library — Share / Filters / Random, plus a quieter Buy-me-a-coffee. (Look-around keeps the small top-left legend.)
   A click on the room re-locks into look-around. */
#closet-frame { transition: filter .35s ease; }
body[data-view="closet"].closet-menu:not(.closet-inspecting):not(.closet-intro):not(.closet-loading) #closet-frame { filter: blur(5px) brightness(.5); }
body[data-view="closet"].closet-menu:not(.closet-inspecting):not(.closet-intro):not(.closet-loading) .chrome { filter: blur(4px) brightness(.5); }   /* the doorway menu panel recedes with the room (it's a shell element, not inside the iframe, so the room filter doesn't reach it) */
body[data-view="closet"].closet-menu .closet-toggle { display: inline-flex; }
body[data-view="closet"].closet-menu .closet-coffee { display: inline-flex; margin-top: 8px; }
body[data-view="closet"].closet-menu .closet-discord { display: inline-flex; }   /* sits with coffee at the foot of the Esc menu */
body[data-view="closet"].closet-menu .closet-actions {
  top: 50%; left: 50%; right: auto; bottom: auto; transform: translate(-50%, -50%);   /* the cursor menu lifts to the CENTRE over the dimmed room */
  gap: 18px; padding: 24px 30px 22px; border-radius: 18px; pointer-events: auto; animation: closetMenuIn .35s ease both; }
@keyframes closetMenuIn { from { opacity: 0; } to { opacity: 1; } }
body[data-view="closet"].closet-menu .ca-top { gap: 18px; }
/* Safari-only click-catcher behind the centred pause card (z just under .closet-actions) → click off the card to dismiss */
.pause-backdrop { display: none; position: fixed; inset: 0; z-index: 69; }
body[data-view="closet"].freelook.closet-menu:not(.closet-inspecting):not(.closet-intro) .pause-backdrop { display: block; }
/* pause-menu status: your 4 picks above the actions — a cover once filled, a heart until then. Centred-menu only. */
.ca-picks { display: none; }
body[data-view="closet"].closet-menu .ca-picks { display: flex; align-self: stretch; gap: 11px; justify-content: center; margin-bottom: 4px; padding-bottom: 20px; border-bottom: 1px solid rgba(243,238,228,.13); }
.ca-picks .cap-slot { position: relative; width: 92px; aspect-ratio: .69; border-radius: 7px; padding: 0; display: flex; align-items: center; justify-content: center; overflow: hidden; background: rgba(243,238,228,.05); border: 1px solid rgba(243,238,228,.14); }
.ca-picks .cap-slot.filled { overflow: visible; cursor: pointer; background: #0a0806; border-color: rgba(243,238,228,.5); box-shadow: 0 8px 22px rgba(0,0,0,.5); }
.ca-picks .cap-slot img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; border-radius: 6px; display: block; }
.ca-picks .cap-heart { width: 30px; height: 30px; fill: rgba(243,238,228,.28); }
.ca-picks .cap-x { position: absolute; top: -7px; right: -7px; width: 20px; height: 20px; border-radius: 50%; z-index: 4; text-align: center;
  background: rgba(18,13,9,.92); color: rgba(243,236,224,.9); font: 700 12px/18px Arial; border: 1px solid rgba(243,238,228,.28);
  cursor: pointer; -webkit-backdrop-filter: blur(4px); backdrop-filter: blur(4px); }
.ca-picks .cap-x::after { content: ''; position: absolute; inset: -6px; }   /* bigger tap target for the destructive remove */
body[data-view="closet"].closet-menu .closet-actions::before { display: none; }   /* no oval — the frosted card grounds the centred menu over the dimmed room */
body[data-view="closet"].closet-menu .closet-share, body[data-view="closet"].closet-menu .closet-filter,
body[data-view="closet"].closet-menu .closet-dice, body[data-view="closet"].closet-menu .closet-coffee, body[data-view="closet"].closet-menu .closet-discord { gap: 16px; }
body[data-view="closet"].closet-menu .closet-actions .cf-ic { width: 24px; height: 24px; opacity: .95; }                          /* bigger, clear icon in the centred menu */
body[data-view="closet"].closet-menu .closet-actions .cf-key { width: 30px; height: 30px; border-radius: 8px; font-size: 14px; }   /* big keycap */
body[data-view="closet"].closet-menu .closet-actions .cf-tx { font-size: 20px; letter-spacing: .12em; }                          /* the action label leads */
body[data-view="closet"].closet-menu .closet-coffee .cf-key { width: 26px; height: 26px; font-size: 12px; }   /* coffee is the quietest item — a smaller badge still */
body[data-view="closet"].closet-menu .closet-coffee .cf-tx, body[data-view="closet"].closet-menu .closet-discord .cf-tx { font-size: 15px; color: rgba(243,238,228,.5); }
body[data-view="closet"].closet-menu .closet-share:hover .cf-tx, body[data-view="closet"].closet-menu .closet-filter:hover .cf-tx,
body[data-view="closet"].closet-menu .closet-dice:hover .cf-tx, body[data-view="closet"].closet-menu .closet-coffee:hover .cf-tx,
body[data-view="closet"].closet-menu .closet-discord:hover .cf-tx { color: #fff; transition: color .15s ease; }
/* the icon lifts with the label — the desktop reset strips these items' background, so the base pill hover
   never lands and the label/icon ARE the whole affordance. */
body[data-view="closet"].closet-menu .closet-discord:hover .cf-ic, body[data-view="closet"].closet-menu .closet-coffee:hover .cf-ic { opacity: 1; transition: opacity .15s ease; }
body[data-view="closet"].closet-menu .closet-share:hover .cf-key, body[data-view="closet"].closet-menu .closet-filter:hover .cf-key,
body[data-view="closet"].closet-menu .closet-dice:hover .cf-key, body[data-view="closet"].closet-menu .closet-coffee:hover .cf-key { border-color: rgba(243,238,228,.85); color: #fff; transition: border-color .15s ease, color .15s ease; }
body.is-touch .closet-dice .cf-tx { display: none; }
body.is-touch .closet-dice { padding: 6px 8px; }
body.is-touch .closet-dice .cf-ic { width: 20px; height: 20px; }   /* icon-only on mobile → larger pips fill the button */
.cf-ic { width: 15px; height: 15px; display: block; flex: none; }
.cf-key { font-size: 10.5px; font-weight: 700; line-height: 1.25; color: rgba(243,239,230,.62);
  border: 1px solid rgba(255,255,255,.24); border-radius: 5px; padding: 0 5px; margin-left: 1px; }
body.is-touch .cf-key { display: none; }                             /* key hints are desktop-only */
/* Keycaps retired everywhere: the room is read as mouse-driven, so the shortcuts stay live but stop
   advertising themselves — the pill/quickbar labels (Filters, Random, Picks, Share) carry the meaning
   on their own. Covers the action pills (S/F/R/B), the quickbar (/ F R V) and the mobile picks chip (V).
   The Esc cap is deliberately NOT in here — it's the one keycap that stays, since the top-right pill is
   also the mouse route into the menu (see .ca-esc, app.js). Delete this block for every keycap back. */
.cf-key,
.picks-chip .pc-key,
.closet-quickbar kbd { display: none !important; }
/* Desktop already carries your picks in the top-centre CLOSET PICKS marquee, which shows the covers as they
   fill. A second Picks button in the corner said the same thing worse, so the corner bar is tools only. */
#closet-picks-quick { display: none; }   /* your picks are already stated: the top-centre marquee on desktop, the corner chip on a phone. A third copy in the tool bar was just noise. */
@media (max-width: 640px) { .closet-actions { top: 16px; } }
/* MOBILE chrome: the labelled pill-stack collapses to compact frosted icon-circles in a row; the bottom SHEET's
   gold button owns Share, so the desktop Share pill is dropped here. */
body.is-touch .closet-share { display: none; }
body.is-touch .closet-actions { flex-direction: row; align-items: center; }
body.is-touch .closet-filter .cf-tx, body.is-touch .closet-coffee .cf-tx { display: none; }
body.is-touch .closet-filter, body.is-touch .closet-coffee, body.is-touch .closet-dice {
  width: 42px; height: 42px; padding: 0; border-radius: 50%; justify-content: center; opacity: 1;
  background: rgba(16,16,20,.44); border: 1px solid rgba(243,239,234,.16);
  backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px); }
body[data-view="closet"] .bar { max-width: none; }
body[data-view="closet"] .logo { color: #f3efe6; font-size: 19px; }
body[data-view="closet"] .toolbar { max-width: none; margin-top: 15px; justify-content: flex-start; }
/* prominent "Buy me a coffee" CTA, bottom-right of the doorway glass panel — closet view only (never the List bar) */
.chrome-foot { display: none; }
body[data-view="closet"] .chrome-foot { display: flex; justify-content: space-between; align-items: center; margin-top: 16px; }
/* the way out of the doorway console: turns you back onto the shelves (postMessage 'room' → returnToRoom).
   Closet-view only — on the wall there is no room to swivel back to. */
.chrome-back { display: none; }
body[data-view="closet"] .chrome-back { display: inline-flex; align-items: center; gap: 8px; min-height: 34px; padding: 0 13px 0 10px;
  border: 1px solid rgba(243,238,228,.22); border-radius: 999px; background: rgba(243,238,228,.06); color: rgba(243,238,228,.9);
  font: 600 11.5px/1 "Helvetica Neue",Arial,sans-serif; letter-spacing: .12em; text-transform: uppercase; cursor: pointer;
  transition: background .16s, border-color .16s, color .16s; }
body[data-view="closet"] .chrome-back:hover { background: rgba(243,238,228,.13); border-color: rgba(243,238,228,.4); color: #fff; }
/* PHONE: the doorway console is only ~304px wide, and the footer once overflowed its right edge by 39px with
   the coffee pill hanging outside the panel entirely. The row is shrunk to fit; wrap stays as the fallback. */
body.is-touch[data-view="closet"] .chrome-foot { flex-wrap: wrap; justify-content: space-between; gap: 8px; }   /* Back on the left, coffee on the right — stacked in the middle they read as one indecisive pair. They fit
     on one row now they're shrunk; wrap stays as the fallback if a narrower phone can't take both. */
body.is-touch[data-view="closet"] .chrome-back { min-height: 32px; padding: 0 12px; font-size: 10.5px; letter-spacing: .1em; }
body.is-touch[data-view="closet"] .chrome-coffee { padding: 9px 15px; font-size: 13px; }
/* the phone's filter opener IS this row — at #6f6857 on the dark console it read as disabled text, not a control */
body.is-touch[data-view="closet"] .mobile-summary { color: rgba(243,239,230,.92); }
body.is-touch[data-view="closet"] #mobile-summary-text { color: rgba(243,239,230,.92); }
/* Two real labels, one shown per width — NOT a ::after content swap, which puts the visible word outside the
   DOM and leaves two sources of truth for it. display:none drops the unused one from the a11y tree too, so the
   button announces exactly what it reads. The long form cannot fit the phone: it needs ~345px of the ~297px
   console once the Discord mark and Donate are in the row (the original 39px overflow). */
.chrome-back .cb-short { display: none; }
body.is-touch[data-view="closet"] .chrome-back .cb-long { display: none; }
body.is-touch[data-view="closet"] .chrome-back .cb-short { display: inline; }
.chrome-back .cb-ic { width: 15px; height: 15px; display: block; flex: none; }
body.freelook[data-view="closet"] .chrome-back { cursor: none !important; }   /* the ring reticle owns the cursor across the console */
/* Discord sits beside Donate as the console's second CTA — the MARK only, at every width, matching the phone.
   Deliberately the quieter of the two: flat blurple, no glow, no label. Two competing haloes at the console's
   bottom-right read as a banner ad, and the coffee pill is the one that has to keep its pull. Same translate3d/backface as the coffee pill: it lives in
   the same #chrome-cam preserve-3d subtree, where WebKit otherwise leaves the fill unpainted until a layer is
   forced (the black-slab-until-hover bug). */
.chrome-cta { display: flex; align-items: center; gap: 10px; }
.chrome-discord { display: none; }
body[data-view="closet"] .chrome-discord {
  display: inline-flex; align-items: center; justify-content: center; text-decoration: none;
  width: 44px; height: 44px; padding: 0; border-radius: 50%;
  background: rgba(88,101,242,.22); color: #b3bbff;
  border: 1px solid rgba(124,135,255,.45); cursor: pointer;
  transition: filter .2s ease, transform .12s ease;
  transform: translate3d(0, 0, 0); backface-visibility: hidden; }
.chrome-discord span { display: none; }   /* the mark carries it on every width — the label was the odd one out beside a single gold CTA */
body[data-view="closet"] .chrome-discord:hover { transform: translate3d(0, -2px, 0);
  background: rgba(88,101,242,.34); border-color: rgba(150,159,255,.65); color: #d2d7ff; }
body[data-view="closet"] .chrome-discord:active { transform: translate3d(0, 0, 0); }
.cd-ic { width: 22px; height: 22px; display: block; flex: none; }   /* half the circle, as on the phone — at 18px the mark floated in too much blurple */
/* PHONE: the console is only ~304px and Back + Donate already had to shrink to share one row, so the mark
   comes down with everything else. */
body.is-touch[data-view="closet"] .chrome-cta { gap: 8px; }
body.is-touch[data-view="closet"] .chrome-discord { width: 38px; height: 38px; }   /* squared to the Donate pill's height so the pair sits on one line */
body.is-touch[data-view="closet"] .cd-ic { width: 19px; height: 19px; }
body.freelook[data-view="closet"] .chrome-discord { cursor: none !important; }

/* TINTED GLASS, not a solid fill. Both CTAs were opaque saturated chips on a translucent console, so they read
   as pasted on rather than part of it. They now take the Back button's material — a low-alpha wash behind a
   hairline border — in their OWN hue, so the colour still identifies them at a glance without the panel losing
   its glass. The gold keeps a faint glow (it is still the primary action); the blurple carries none. */
.chrome-coffee {
  display: inline-flex; align-items: center; gap: 9px; text-decoration: none;
  padding: 12px 22px; border-radius: 999px;
  background: rgba(235,159,27,.15); color: #f2ce8e;
  font: inherit; font-size: 15px; font-weight: 700; letter-spacing: .2px;
  border: 1px solid rgba(243,190,92,.42);
  box-shadow: 0 6px 18px -8px rgba(235,159,27,.5), inset 0 1px 0 rgba(255,255,255,.1);
  cursor: pointer; transition: transform .12s ease, box-shadow .2s ease, filter .2s ease;
  /* Safari paint fix: this button sits inside #chrome-cam's preserve-3d subtree, and WebKit would leave its
     gradient + big shadow unpainted (it rendered as a black slab) until something promoted it to its own layer.
     :hover was doing that by accident, via its transform — so it stayed black until you moved onto it, then was
     fine forever. Claim the layer up front instead. Hover/active keep the same 3d form so the transition holds. */
  transform: translate3d(0, 0, 0); backface-visibility: hidden; }
.chrome-coffee:hover { transform: translate3d(0, -2px, 0);
  background: rgba(235,159,27,.24); border-color: rgba(247,201,110,.62); color: #f8dfae;
  box-shadow: 0 10px 26px -8px rgba(235,159,27,.6), inset 0 1px 0 rgba(255,255,255,.14); }
.chrome-coffee:active { transform: translate3d(0, 0, 0); }
.cc-ic { width: 18px; height: 18px; display: block; flex: none; }
body[data-view="closet"] #q { flex: 1 1 200px; background: rgba(255,255,255,.07); border-color: rgba(255,255,255,.16); color: #f3efe6; }
body[data-view="closet"] #q:focus { border-color: rgba(255,255,255,.5); }
body[data-view="closet"] #q::placeholder { color: rgba(243,239,230,.5); }
body[data-view="closet"] .sort { display: none; }       /* sorting is meaningless walking the shelves */
body[data-view="closet"] .status { display: block; max-width: none; color: rgba(243,239,230,.62); margin: 11px 0 0; }
body[data-view="closet"] .status b { color: #f3efe6; }
body[data-view="closet"] .active { max-width: none; margin: 12px 0 0; }
/* the doorway menu is always usable: you aim the pointer-lock crosshair at a control and click. */
/* the pointer-lock cursor, drawn ON TOP of the doorway menu (z above it) so you can see where you point */
#x-cursor { position: fixed; left: 50%; top: 50%; width: 15px; height: 15px; margin: -7.5px 0 0 -7.5px; z-index: 100;
  pointer-events: none; opacity: 0; border-radius: 50%; border: 2px solid rgba(255,255,255,.92);
  background: rgba(255,255,255,.16); box-shadow: 0 0 0 1px rgba(0,0,0,.5), 0 1px 5px rgba(0,0,0,.55);
  transition: opacity .2s, transform .1s, border-color .1s, background .1s; }
body[data-view="closet"].closet-locked:not(.closet-inspecting) #x-cursor { opacity: 1; }
#x-cursor.over { border-color: #6dffb0; background: rgba(109,255,176,.32); transform: scale(1.4);
  box-shadow: 0 0 11px rgba(109,255,176,.6), 0 0 0 1px rgba(0,0,0,.4); }
/* Safari (no pointer lock): the ring FOLLOWS the cursor over the doorway menu (not fixed at centre) and the OS arrow
   is hidden there — so the cursor stays the consistent green ring from the 3D room onto the glassmorphic menu. */
body.freelook #x-cursor.free-show, body:not(.is-touch).closet-inspecting #x-cursor.free-show { opacity: 1; }   /* the ring also rides the persistent picks marquee during inspect (all desktop engines — the chip is shell DOM the closet's own ring can't reach) */
body.freelook #x-cursor, body:not(.is-touch).closet-inspecting #x-cursor { transition: transform .1s, border-color .1s, background .1s; }   /* snap opacity (no .2s fade) so the room↔menu and room↔marquee ring handoffs are instant */
body.freelook #chrome.ring-on, body.freelook #chrome.ring-on * { cursor: none; }   /* hide the OS arrow only while the ring is actually tracking (set on mousemove) — so summoning the menu with the keyboard (e.g. F) never leaves you with NO cursor until you jiggle the mouse */
body.freelook[data-view="closet"] .closet-quickbar, body.freelook[data-view="closet"] .closet-quickbar button,
body.freelook[data-view="closet"] #clear-filter, body.freelook[data-view="closet"] #picks-chip,
body.freelook[data-view="closet"] .ca-esc { cursor: none !important; }   /* the ring reticle tracks across the browse chrome too (see __safariRing) — no OS arrow doubling it */
body.freelook #chrome, body.freelook #chrome * { -webkit-user-select: none; user-select: none; }   /* a look-drag over the glass must not highlight the filter labels */
body.freelook #chrome input, body.freelook #chrome textarea { -webkit-user-select: text; user-select: text; }   /* …but keep the search box selectable/editable */

.xhair-on { position: relative; }
.facet-btn.xhair-on, .lpill.xhair-on, .ltool.xhair-on, .view.xhair-on, .opt.xhair-on, .ic-more.xhair-on {
  box-shadow: 0 0 0 2px #f3efe6, 0 0 16px rgba(243,239,230,.55) !important; border-radius: 8px;
}
#q.xhair-on { box-shadow: 0 0 0 2px #f3efe6, 0 0 16px rgba(243,239,230,.5); }
body[data-view="closet"] .views { background: rgba(255,255,255,.12); border-color: rgba(255,255,255,.18); }
/* mobile closet already has the top-right List/Closet switch — drop the in-panel toggle so "THE CLOSET" isn't squeezed */
body.is-touch[data-view="closet"] .views { display: none; }
body[data-view="closet"] .view { color: rgba(243,239,230,.72); }
body[data-view="closet"] .view.is-active { color: var(--ink); }
body[data-view="closet"] .slider { background: var(--cream); }
body[data-view="closet"] .facet-btn { background: rgba(28,28,34,.62); color: #f1ece0; border-color: rgba(255,255,255,.16); }
body[data-view="closet"] .facet-btn:hover { border-color: rgba(255,255,255,.4); }
body[data-view="closet"] .facet.has-sel .facet-btn { border-color: var(--cream); }
body[data-view="closet"] .facet-btn .cnt { background: var(--cream); color: var(--ink); }
body[data-view="closet"] .facet-btn .car { color: rgba(243,239,230,.6); }

/* the doorway menu stays visible while you mouse-look (it's a world object) — only the
   "click to look" prompt fades. The menu's own visibility is driven by the world projection. */
body.closet-locked .closet-prompt { opacity: 0; pointer-events: none; }
body.prompt-hidden .closet-prompt { opacity: 0 !important; }   /* wins over the touch opacity → splash entry suppresses it */
body.closet-inspecting .closet-prompt { opacity: 0 !important; pointer-events: none; }   /* gone once you're holding a DVD */

/* the one cue you need while pointer-locked: how to get out */
.esc-hint { position: fixed; top: 16px; left: 50%; z-index: 80; transform: translateX(-50%) translateY(-8px);
  background: rgba(10,10,12,.34); color: rgba(243,239,230,.6); border: 1px solid rgba(255,255,255,.07); border-radius: 999px;
  padding: 5px 13px; font-size: 11.5px; font-weight: 500; opacity: 0; pointer-events: none;
  transition: opacity .35s, transform .35s; backdrop-filter: blur(4px); -webkit-backdrop-filter: blur(4px); }
.esc-hint kbd { background: #f3efe6; color: #14130f; border-radius: 5px; padding: 2px 8px; font-weight: 800; font-size: 12px; font-family: inherit; margin-right: 7px; }
/* the "Aim the crosshair at the menu & click" toast sat at the top of the screen the whole time you were
   pointer-locked — persistent instructional clutter. Suppressed on every platform (touch already hid it):
   the #x-cursor reticle makes aim-and-click self-evident, and Esc still exits pointer-lock natively. */
.esc-hint { display: none !important; }

/* ============ verdict overlay (wall) ============ */
.overlay { position: fixed; inset: 0; background: rgba(20,19,15,.55); display: flex; align-items: center; justify-content: center; padding: 20px; z-index: 100; }
.overlay.hidden { display: none; }
.card { width: 100%; max-width: 430px; background: var(--paper); border-radius: 20px; box-shadow: var(--shadow); padding: 30px 30px 24px; position: relative; text-align: center; animation: pop .16s ease-out; max-height: 92vh; overflow: auto; }
@keyframes pop { from { transform: scale(.96); opacity: .5 } to { transform: scale(1); opacity: 1 } }
.card .close { position: absolute; top: 12px; right: 15px; border: none; background: none; font-size: 25px; line-height: 1; color: var(--muted); cursor: pointer; }
.hero { width: 168px; margin: 4px auto 18px; }
.hero .art { box-shadow: 0 16px 34px rgba(20,19,15,.32); border-radius: 7px; }   /* 5:7 comes from .art::before */
.spine-line { font-weight: 800; font-size: clamp(40px, 12vw, 58px); line-height: 1; margin: 6px 0 4px; }
.spine-line small { font-size: .42em; color: var(--muted); vertical-align: super; }
.card .film { font-family: Georgia, "Times New Roman", serif; font-size: 23px; font-weight: 600; margin: 2px 0 3px; }
.card .credit { color: var(--muted); font-size: 14.5px; margin-bottom: 9px; }
.syn-wrap { margin: 0 0 14px; }
.card .syn { font-size: 14.5px; line-height: 1.55; color: var(--ink); text-align: left; margin: 0;
  display: -webkit-box; -webkit-line-clamp: 4; -webkit-box-orient: vertical; overflow: hidden; }   /* collapsed preview */
.card .syn.expanded { display: block; -webkit-line-clamp: unset; }
.syn-more { background: none; border: none; padding: 4px 0 0; margin: 0; cursor: pointer; font: inherit;
  font-size: 13px; font-weight: 700; color: var(--muted); text-decoration: underline; text-underline-offset: 2px; }
.syn-more[hidden] { display: none; }
.tags { display: flex; flex-wrap: wrap; gap: 6px; justify-content: center; margin: 0 0 16px; }   /* metadata chips, sat under the byline */
.tag { font-size: 12px; font-weight: 500; color: var(--muted); background: var(--cream); border: 1px solid var(--line); border-radius: 999px; padding: 4px 11px; cursor: pointer; }
.tag:hover { border-color: var(--ink); color: var(--ink); }
.actions { display: grid; gap: 9px; }
.btn { display: block; text-decoration: none; padding: 13px 16px; border-radius: 11px; font-weight: 600; font-size: 15px; border: 1.5px solid var(--ink); }
.btn.primary { background: var(--ink); color: var(--cream); }
.btn.ghost { background: transparent; color: var(--ink); }
.btn.ghost:hover { background: rgba(20,19,15,.05); }
.minor { margin-top: 15px; font-size: 12.5px; color: var(--muted); }
.minor a { text-decoration: underline; }

/* ============ Your Lists (custom collections) ============ */
.lists-row { flex:1 0 100%; max-width: 1280px; margin: 5px auto 0; }
.lists-head { font-size: 11px; font-weight: 800; letter-spacing: .12em; text-transform: uppercase; color: var(--muted); margin: 0 0 7px; }
.lists-pills { display: flex; flex-wrap: wrap; gap: 7px; align-items: center; }
.lpill { min-height:38px; font: inherit; font-size: 13px; font-weight: 600; cursor: pointer; padding: 7px 12px; border-radius: 999px;
  border: 1.5px solid var(--line); background: var(--paper); color: var(--ink); display: inline-flex; align-items: center; gap: 7px; transition: background .25s, border-color .25s, color .25s; }
.lpill:hover { border-color: var(--line2); }
.lpill .lc { font-size: 11px; font-weight: 800; color: var(--muted); background: var(--cream); border-radius: 999px; padding: 1px 7px; min-width: 17px; text-align: center; }
.lpill.on { background: var(--ink); color: var(--cream); border-color: var(--ink); }
.lpill.on .lc { background: rgba(255,255,255,.22); color: var(--cream); }
.lpill.new { border-style: dashed; color: var(--muted); }
.lpill.new:hover { color: var(--ink); border-color: var(--ink); }
.list-tools { display: flex; flex-wrap: wrap; gap: 7px; margin-top: 10px; align-items: center; }
.ltool { font: inherit; font-size: 12.5px; font-weight: 600; cursor: pointer; padding: 6px 11px; border-radius: 8px; border: 1.5px solid var(--line); background: var(--paper); color: var(--ink); }
.ltool:hover { border-color: var(--line2); }
.ltool.done { background: transparent; border-color: var(--go); color: var(--go); font-weight: 800; }   /* green outline + green tick */
.ltool.add { color: #1c8a52; border-color: rgba(28,138,82,.5); }
.ltool.rm  { color: #b3413f; border-color: rgba(179,65,63,.5); }
.ltool.danger { color: var(--no); border-color: var(--no); }

/* dark variants inside the glass panel */
body[data-view="closet"] .lists-head { color: rgba(243,239,230,.55); }
body[data-view="closet"] .lpill { background: rgba(255,255,255,.07); border-color: rgba(255,255,255,.16); color: #f1ece0; }
body[data-view="closet"] .lpill .lc { background: rgba(255,255,255,.14); color: #f1ece0; }
body[data-view="closet"] .lpill.on { background: var(--cream); color: var(--ink); border-color: var(--cream); }
body[data-view="closet"] .lpill.on .lc { background: rgba(20,19,15,.16); color: var(--ink); }
body[data-view="closet"] .lpill.new { color: rgba(243,239,230,.6); }
body[data-view="closet"] .ltool { background: rgba(255,255,255,.07); border-color: rgba(255,255,255,.16); color: #f1ece0; }
body[data-view="closet"] .ltool.done { background: rgba(109,255,176,.08); border-color: #57d99a; color: #6dffb0; }   /* bright green outline + tick on the dark panel */
/* add/remove films is a List-view action — the closet doorway panel only shows it once you're already building (Done) */
body[data-view="closet"] .ltool.add,
body[data-view="closet"] .ltool.rm { display: none; }

/* add/remove mode on the wall: tiles become add/remove targets with a clear green/red affordance */
.edit-tag { position: absolute; top: 8px; left: 8px; right: 8px; display: none; justify-content: center;
  padding: 5px 0; border-radius: 8px; font-size: 12.5px; font-weight: 800; letter-spacing: .02em;
  color: #fff; z-index: 2; pointer-events: none; }   /* the shadow lives on the hovered badge only → always-on badges stay cheap */
/* Add AND Remove mode show the badge/outline only on the hovered tile — a shadowed badge + outline on
   every tile tanks scroll, and a remove list can be huge. The "Building/Removing …" banner is the cue.
   Only edit-in (already-added) keeps a flat, shadow-free badge so you can see what's in the list. */
.tile.edit-add:hover .edit-tag,
.tile.edit-rm:hover .edit-tag,
.tile.edit-in .edit-tag { display: flex; }
.tile.edit-add .edit-tag { background: #1c8a52; }
.tile.edit-rm  .edit-tag { background: #b3413f; }
.tile.edit-in  .edit-tag { background: rgba(20,19,15,.72); }
.tile.edit-in  .art { opacity: .82; }
/* the cover you're pointing at gets an unmistakable colour wash + bold ring + bigger badge */
.tile.edit-add:hover .art,
.tile.edit-rm:hover  .art { outline: 3px solid #1c8a52; outline-offset: 2px; }
.tile.edit-rm:hover  .art { outline-color: #c0403e; }
.tile.edit-add:hover .art::after,
.tile.edit-rm:hover  .art::after { content: ''; position: absolute; inset: 0; z-index: 1; pointer-events: none; }
.tile.edit-add:hover .art::after { background: rgba(20,120,70,.40); box-shadow: inset 0 0 0 2px rgba(255,255,255,.18); }
.tile.edit-rm:hover  .art::after { background: rgba(150,30,30,.46); box-shadow: inset 0 0 0 2px rgba(255,255,255,.18); }
.tile.edit-add:hover .edit-tag,
.tile.edit-rm:hover  .edit-tag { transform: scale(1.06); box-shadow: 0 4px 14px rgba(0,0,0,.45); }
body.building .tile .art { cursor: pointer; }
body.building .tile:active .art { transform: scale(.97); }
body.removing-mode .tile .art { cursor: pointer; }

/* "add to a list" control on the verdict card */
.card-lists { margin: 2px 0 18px; text-align: left; }
.card-lists .cl-head { font-size: 11px; font-weight: 800; letter-spacing: .1em; text-transform: uppercase; color: var(--muted); margin-bottom: 8px; }
.card-lists .lpill { font-size: 12.5px; }

.bar-l { display: flex; align-items: center; gap: 10px; }

/* keep facet dropdowns from spilling off a narrow screen */
.facet-pop { max-width: calc(100vw - 20px); }

/* ============ mobile / small screens ============ */
/* mobile "Filters" disclosure — keeps the List clean by default (desktop hides this button) */
.filters-btn { display: none; }
.filters-btn .fb-count { font-size: 11px; font-weight: 800; background: var(--ink); color: var(--cream); border-radius: 999px; padding: 1px 7px; }
.filters-btn .fb-car { color: var(--muted); font-size: 11px; transition: transform .2s; }
body.filters-open .filters-btn .fb-car { transform: rotate(180deg); }

@media (max-width: 640px) {
  .grid { grid-template-columns: repeat(auto-fill, minmax(116px, 1fr)); gap: 16px 10px; padding: 12px 12px 44px; }
  .chrome { padding: 10px 12px 8px; }
  .bar { gap: 10px; }
  .bar-l { min-width: 0; }                                  /* let the logo shrink so the toggle keeps its gutter */
  .logo { font-size: clamp(15px, 4.6vw, 22px); letter-spacing: .12em; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .views { flex: 0 0 auto; }                                /* the toggle keeps its size; the logo gives way */
  /* iOS Safari sizes native <button> by its own intrinsic metrics, so the List toggle came out shorter &
     narrower than the closet one. Pin EVERYTHING explicitly & symmetrically — same pill height, same button
     height, content width with no flex grow/shrink — so both toggles render identically. */
  .views, .closet-toggle { height: 40px; align-items: center; }
  .view, .ct-btn { height: 30px; box-sizing: border-box; flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center;
    padding: 0 12px; font-size: 12.5px; line-height: 1; white-space: nowrap; -webkit-appearance: none; appearance: none; }
  .view { min-width: 0; }
  /* content-width buttons ⇒ the 50% sliding pill no longer fits; use a solid active highlight (same as the closet switch) */
  .slider { display: none; }
  .view.is-active { background: var(--ink); }
  .view .ic { display: none; }
  .toolbar { gap: 7px; margin-top: 9px; }
  #q { flex: 1 1 130px; min-width: 120px; font-size: 16px; padding: 10px 13px; }   /* keep ≥16px so iOS doesn't zoom on focus */
  .facet-btn { padding: 9px 11px; font-size: 13px; }
  .sort { margin-left: 0; }
  .card { max-width: 94vw; padding: 22px 18px 18px; }
  .hero { width: 132px; }
  .cap .t { font-size: 13.5px; }
  /* the doorway glass panel: keep it inside the viewport when the closet is opened on a phone */
  body[data-view="closet"] .chrome { width: min(520px, 92vw); padding: 14px 16px 12px; }

  /* the List: show the compact "Filters" button and collapse the heavy rows until it's tapped */
  body[data-view="wall"] .filters-btn { display: inline-flex; align-items: center; gap: 7px; font: inherit;
    font-size: 13px; font-weight: 600; cursor: pointer; padding: 9px 13px; border: 1.5px solid var(--line);
    border-radius: 11px; background: var(--paper); color: var(--ink); white-space: nowrap; }
  body[data-view="wall"] .filters-btn.has-sel { border-color: var(--ink); }
  body[data-view="wall"]:not(.filters-open) .facets,
  body[data-view="wall"]:not(.filters-open) .sort,
  body[data-view="wall"]:not(.filters-open) .lists-row,
  body[data-view="wall"]:not(.filters-open) .active,
  body[data-view="wall"]:not(.filters-open) .status { display: none; }
  body[data-view="wall"].filters-open .facets { width: 100%; margin-top: 2px; }
}
@media (max-width: 380px) {
  .grid { grid-template-columns: repeat(auto-fill, minmax(104px, 1fr)); }
  .view, .ct-btn { font-size: 12px; padding: 0 9px; }
}

/* touch: hide the pointer-lock-only cursors/hints that don't apply without a mouse */
body.is-touch #x-cursor, body.is-touch .esc-hint { display: none !important; }

/* ---- in-page trailer player ---- */
.trailer-modal { position: fixed; inset: 0; z-index: 200; display: flex; align-items: center; justify-content: center;
  background: rgba(6,6,8,.92); backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px); animation: tmIn .2s ease; }
.trailer-modal[hidden] { display: none; }
@keyframes tmIn { from { opacity: 0 } to { opacity: 1 } }
.tm-frame { width: min(92vw, 1120px); aspect-ratio: 16 / 9; background: #000; border-radius: 10px; overflow: hidden;
  box-shadow: 0 24px 90px rgba(0,0,0,.65); }
.tm-frame iframe { width: 100%; height: 100%; border: 0; display: block; }
.tm-close { position: fixed; top: 16px; right: 20px; z-index: 201; width: 44px; height: 44px; border-radius: 999px; cursor: pointer;
  border: 1px solid rgba(255,255,255,.22); background: rgba(20,20,26,.72); color: #f3efe6; font-size: 24px; line-height: 38px; text-align: center;
  backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px); transition: transform .12s; }
.tm-close:hover { transform: scale(1.08); }

/* ---------- Closet Picks marquee — a machined object; covers seated in carved wells (gallery restraint) ---------- */
/* THE PICKS TRAY — one design, both platforms: a summoned sheet that slides DOWN from the top, hidden until the chip is tapped */
.picks-tray { position:fixed; left:50%; top:0; transform:translateX(-50%) translateY(-101%); z-index:110;
  width:min(440px,94vw); display:flex; flex-direction:column; align-items:stretch; gap:0;
  padding:max(14px,env(safe-area-inset-top)) 22px 6px; border-radius:0 0 28px 28px;   /* small bottom pad — the grab strip fills the rest of the bottom */
  background:rgba(6,6,8,.20);
  backdrop-filter:blur(44px) saturate(1.15) brightness(.80); -webkit-backdrop-filter:blur(44px) saturate(1.15) brightness(.80);
  box-shadow:inset 1px 0 0 rgba(243,238,228,.14), inset -1px 0 0 rgba(243,238,228,.14), inset 0 -1px 0 rgba(243,238,228,.16), 0 36px 80px -20px rgba(0,0,0,.9);   /* sides + bottom only — no top line (the sheet blends into the screen's top edge it drops from) */
  font-family:"Helvetica Neue",Arial,sans-serif; opacity:0; pointer-events:none;
  transition:transform .44s cubic-bezier(.5,0,.78,.12), opacity .18s ease .26s; }   /* DISMISS: slide up + off (ease-in accelerates it away), with the fade HELD until the slide is underway → reads as a retract, not a vanish */
.picks-tray[hidden]{ display:none; }
body.picks-open .picks-tray, .picks-tray.reveal { transform:translateX(-50%) translateY(0); opacity:1; pointer-events:auto;
  transition:transform .38s cubic-bezier(.24,.88,.26,1), opacity .22s ease; }   /* SUMMON: slide down + settle (ease-out) + fade in. .reveal = the brief auto-open flash when a film is added */
/* legacy floating-bar bits — folded away (the sheet uses .cm-head · .cm-slots · .cm-add) */
.cm-status, .cm-label, .cm-count, .cm-divider, .cm-cta { display:none; }
.cm-grab { position:relative; display:block; width:100%; height:44px; margin:6px auto 0; order:99; cursor:grab; background:none; border:none; padding:0; touch-action:none; -webkit-tap-highlight-color:transparent; }   /* full-width, tall hit area → the WHOLE bottom strip dismisses (no dead zone below the visual handle) */
.cm-grab::before { content:""; position:absolute; left:50%; top:50%; transform:translate(-50%,-50%); width:36px; height:3px; border-radius:99px; background:rgba(243,238,228,.28); transition:background .15s ease, width .15s ease; }
.cm-grab:hover::before { background:rgba(243,238,228,.5); width:46px; }
.cm-grab:active::before, .cm-grab.dragging::before { background:rgba(243,238,228,.68); }
.cm-grab.dragging { cursor:grabbing; }
.cm-grab:focus-visible { outline:none; }
.cm-grab:focus-visible::before { background:rgba(243,238,228,.55); box-shadow:0 0 0 2px rgba(243,238,228,.35); }
.cm-head { display:block; text-align:center; margin:4px 0; }
.cm-eyebrow { font:600 10px "Helvetica Neue",Arial,sans-serif; letter-spacing:3.2px; text-transform:uppercase; color:rgba(243,238,228,.48); }
.cm-sub { font:600 21px/1.2 "Helvetica Neue",Helvetica,Arial,sans-serif; color:rgba(243,238,228,.92); margin-top:5px; letter-spacing:-.012em; }   /* semibold to match the site (was a thin 200 that read as a different typeface) */

.cm-slots { position:relative; z-index:1; display:flex; flex-wrap:wrap; justify-content:center; gap:10px; margin:16px 0 18px; }
.cm-slot { position:relative; flex:0 0 calc((100% - 30px) / 4); aspect-ratio:2/3; border-radius:7px; border:none; padding:0;   /* ONE row of four — the four picks read as a single hand (this sized-for-six 3-per-row left #4 stranded on its own line) */
  background:rgba(0,0,0,.28);   /* translucent recess — dark enough to read but glass shows through */
  box-shadow: inset 0 1px 5px rgba(0,0,0,.65), inset 0 0 0 1px rgba(255,255,255,.05);
  display:grid; place-items:center; overflow:hidden; }
.cm-slot .cm-idx { display:inline-flex; }
.cm-slot .cap-heart { width:30px; height:30px; fill:rgba(243,238,228,.28); }   /* same heart watermark as the landing card wells + the Esc-menu row */
.cm-slot.is-filled { cursor:pointer; overflow:visible; touch-action:none;   /* drag-to-reorder owns the gesture (the sheet has its own grab handle) */
  box-shadow:0 8px 26px rgba(0,0,0,.6), 0 2px 6px rgba(0,0,0,.35); }
/* drag-to-reorder: the lifted source dims in place; the slot it would take gets a quiet cream ring */
.cm-slot.drag-src, .cap-slot.drag-src { opacity:.3; }
.cm-slot.drag-over, .cap-slot.drag-over { outline:2px solid rgba(243,238,228,.6); outline-offset:2px; }
.ca-picks .cap-slot.filled { touch-action:none; }
.cm-slot img, .cap-slot img { -webkit-user-drag:none; user-select:none; -webkit-user-select:none; }   /* the covers are drag HANDLES, not draggable images */
.cm-slot.is-filled img { position:absolute; inset:0; width:100%; height:100%; object-fit:cover; border-radius:4px; }
.cm-frame { position:absolute; inset:0; border-radius:4px; pointer-events:none;
  box-shadow:inset 0 0 0 1px rgba(255,247,232,.18), inset 0 1px 0 rgba(255,255,255,.1); }
/* justadded: only the newly-landed slot springs — existing slots are stable across innerHTML re-renders */
.cm-slot.justadded { animation:ptLand .5s cubic-bezier(.28,1.18,.38,1); z-index:3; }
@keyframes ptLand {
  /* pure transform spring — opacity/box-shadow omitted to stay on GPU compositor */
  0% { transform:scale(1.12); }
  100% { transform:scale(1); } }
/* remove ✕ — persistent in the closet (no hover under pointer-lock) + on touch */
.cm-x { position:absolute; top:-7px; right:-7px; width:19px; height:19px; border-radius:50%; z-index:4;
  background:rgba(18,13,9,.92); color:rgba(243,236,224,.9); font:700 11px/17px Arial; text-align:center; opacity:0; transition:opacity .15s;
  border:1px solid rgba(243,238,228,.28); backdrop-filter:blur(4px); -webkit-backdrop-filter:blur(4px); }
.cm-x::after { content:''; position:absolute; inset:-8px; }   /* extend the tap target to ~33px (this is the destructive remove) without enlarging the visible dot */
.cm-slot.is-filled:hover .cm-x, body.is-touch .cm-x, body[data-view="closet"] .cm-x { opacity:1; }
/* full → SWAP: the tray opens in "replace mode" — the four covers WIGGLE (the universal "editable" cue), inviting
   a tap to swap the new film in. Staggered durations/phases so it reads as organic jiggle, not a synced rock. */
.picks-tray.replacing .cm-slot.is-filled .cm-x { opacity:0 !important; pointer-events:none; }   /* tapping REPLACES, not removes → hide the × */
.picks-tray.replacing .cm-slot.is-filled { animation:slotWiggle .3s ease-in-out infinite; }
.picks-tray.replacing .cm-slot.is-filled:nth-child(2n) { animation-duration:.34s; animation-delay:-.17s; }
.picks-tray.replacing .cm-slot.is-filled:nth-child(3n) { animation-duration:.27s; animation-delay:-.09s; }
.picks-tray.replacing .cm-slot.is-filled:active { animation:none; }
@keyframes slotWiggle { 0% { transform:rotate(-0.6deg); } 50% { transform:rotate(0.6deg); } 100% { transform:rotate(-0.6deg); } }
.cm-slot.justswapped { animation:justSwapped .9s ease; z-index:3; }
@keyframes justSwapped { 0% { box-shadow:0 0 0 3px rgba(243,238,228,.85); } 100% { box-shadow:0 0 0 0 rgba(243,238,228,0); } }
@media (prefers-reduced-motion: reduce) { .picks-tray.replacing .cm-slot.is-filled { animation:none; } .cm-slot.justswapped { animation:none; } }

.cm-cta { display:none; align-items:center; gap:10px; white-space:nowrap; cursor:pointer; border:0; padding:0; background:none;
  font-family:Georgia,'Times New Roman',serif; font-size:19px; letter-spacing:.01em; color:#efe7da; }
.cm-cta .cm-arrow { font-size:15px; color:rgba(239,231,218,.52); transform:translateY(.5px); }
.cm-cta:hover { color:#fff; }
.picks-tray.full { box-shadow: inset 1px 0 0 rgba(243,238,228,.2), inset -1px 0 0 rgba(243,238,228,.2), inset 0 -1px 0 rgba(243,238,228,.22), 0 36px 80px -20px rgba(0,0,0,.9); }   /* sides + bottom only — no top line */
/* Share CTA — cream fill (matches the + chip), share glyph, shown once Picks have begun (both platforms) */
.cm-add { display:none; position:relative; z-index:2; width:100%; align-items:center; justify-content:center; gap:10px; cursor:pointer; margin:0;   /* sit ABOVE the covers (z-index:1) so their drop shadows don't fall on the CTA */
  height:54px; border-radius:15px; border:none; color:#1a140c;
  background:linear-gradient(180deg,#f7f2ea,#e8e1d2); font:600 16.5px "Helvetica Neue",Arial,sans-serif; letter-spacing:.2px;
  box-shadow:0 12px 28px -12px rgba(0,0,0,.6), inset 0 1px 0 rgba(255,255,255,.6); }
.cm-add .cm-add-ic { width:18px; height:18px; flex:0 0 auto; }
.picks-tray.full .cm-add, .picks-tray.has-picks .cm-add { display:inline-flex; }   /* share from the FIRST pick — an unfinished Polaroid is still worth sending (the auto-print still waits for four) */
.cm-add[hidden] { display:none; }   /* a stale hidden attr must still hide it — author rule beats the UA [hidden], like .closet-share[hidden] */

/* a pick just landed → the sheet flares for a beat */
.picks-tray.justadded { animation:trayFlare .75s cubic-bezier(.4,0,.6,1); }
@keyframes trayFlare {
  0%,100%{}
  30%{ box-shadow:inset 0 0 0 1.5px rgba(243,238,228,.5), inset 0 1px 0 rgba(255,252,242,.6), 0 36px 80px -20px rgba(0,0,0,.9), 0 0 44px rgba(243,238,228,.09); } }
/* the cover that flies from the held case into its slot */
.pt-fly { position:fixed; z-index:130; border-radius:4px; pointer-events:none; box-shadow:0 16px 36px rgba(0,0,0,.6);
  transform-origin:0 0; will-change:transform, opacity;
  transition:transform .58s cubic-bezier(.4,0,.16,1), box-shadow .5s, opacity .18s ease .42s; }   /* GPU-composited: the flight animates transform (translate+scale), not left/top/width/height, so it never paints on the main thread over the live canvas */
/* ===== MOBILE: picks are SUMMONED, never persistent =====
   - a whisper-light progress CHIP rides top-right (browse + inspect)
   - inspect shows only the floating + FAB (the title caption is the closet's #hud)
   - tapping the chip slides up the Picks panel (your four · remove · share), over a backdrop — dismissible
   So the title and the collection are never on screen together. */
.picks-chip { display:none; position:fixed; top:64px; right:12px; z-index:60; align-items:center; gap:11px;   /* right:12 = flush under the view toggle's right edge; gap 11 matches the closet tracker's label→dots separation */
  height:44px; padding:0 15px 0 16px; border-radius:999px; cursor:pointer;   /* 44 = the tap minimum — this is the press that opens the Polaroid */
  background:rgba(16,16,20,.44); border:1px solid rgba(243,239,234,.16);
  backdrop-filter:blur(16px); -webkit-backdrop-filter:blur(16px); }
body.is-touch[data-view="closet"]:not(.closet-intro) .picks-chip { display:inline-flex; left:12px; right:auto; top:17px; }   /* touch: the chip takes the LEFT corner ON THE TOGGLE'S OWN LINE — the two read as one row across the top */   /* touch only: the summon chip rides top-right. desktop browses without it — picks live in the inspect pill + auto-open at four */
body.is-touch.closet-inspecting .picks-chip { display:none !important; }   /* mobile inspect: the dots move into the fused tracker in the title block. DESKTOP keeps this chip through inspect — one continuous marquee, no browse↔inspect handoff */
body:not(.is-touch).closet-inspecting .picks-chip { cursor:none; }   /* inspect's ring (via #x-cursor) is the only pointer over the chip — never the OS hand */
.picks-chip .pc-lead { font:700 10px/1 "Helvetica Neue",Arial,sans-serif; letter-spacing:.15em; text-transform:uppercase; color:rgba(243,239,234,.82); flex:0 0 auto; }   /* names the chip — .82 is this label's settled voice (the desktop CLOSET PICKS header uses it); .7 still read grey over the glass */
.pc-dots { display:flex; gap:6px; }
.pc-dots i { width:7.5px; height:7.5px; border-radius:50%; background:rgba(243,239,234,.24); }
.pc-dots i.on { background:#f3eee4; box-shadow:0 0 5px rgba(243,238,228,.5); }
/* complete — all four picked: the chip lights up + the label brightens (stays CREAM — gold was tried and vetoed;
   the bigger dots + firmer glass above carry the presence now) */
.picks-chip.complete { border-color:rgba(243,238,228,.7); box-shadow:0 0 14px -3px rgba(243,238,228,.4); }
.picks-chip.complete .pc-lead { color:rgba(243,238,228,.9); }
.picks-chip.complete .pc-dots i.on { box-shadow:0 0 7px rgba(243,238,228,.75); }
/* DESKTOP browse: the top-centre "CLOSET PICKS" marquee is THIS shell chip — shell DOM rides OVER the doorway
   glass (z65 > the stage's 60), which the closet's own pill (iframe DOM, under all shell chrome) never can.
   Styled to the closet tracker's exact look (min-height 46, ::before "Closet ", 8px dots, the V keycap on
   keyboard-driven engines); the closet hides its browse pill when embedded and keeps owning INSPECT, where the
   glass is hidden anyway — same spot, so the handoff is invisible. */
.picks-chip .pc-key { display:none; }
body:not(.is-touch)[data-view="closet"].closet-started:not(.closet-intro):not(.closet-loading) .picks-chip {
  display:inline-flex; top:20px; left:50%; right:auto; transform:translateX(-50%); z-index:65;
  min-height:46px; height:auto; padding:0 21px 0 19px; border-radius:23px; gap:13px;
  border-color:rgba(243,238,228,.22); background:rgba(22,19,14,.64); box-shadow:0 10px 26px -14px rgba(0,0,0,.72); }
body:not(.is-touch) .picks-chip .pc-lead::before { content:"Closet\00a0"; }
body:not(.is-touch) .picks-chip .pc-lead { font-size:11.5px; letter-spacing:.16em; color:rgba(243,238,228,.82); }
body:not(.is-touch) .picks-chip .pc-dots { gap:6.5px; }
body:not(.is-touch) .picks-chip .pc-dots i { width:8px; height:8px; }
body:not(.is-touch):not(.freelook) .picks-chip .pc-key { display:inline-grid; place-items:center; width:22px; height:22px; flex:0 0 auto;
  border:1px solid rgba(243,238,228,.42); border-radius:5px; background:rgba(12,10,7,.5);
  font:600 10.5px/1 "Helvetica Neue",Arial,sans-serif; letter-spacing:0; color:rgba(243,238,228,.97); text-shadow:0 1px 2px rgba(0,0,0,.7); }   /* EXACTLY the closet tracker's keycap (which copies the legend's .cf-key) — hidden on Safari, where the chip is clicked, not keyed */

/* (.inspect-add — the old gold mobile-inspect FAB — removed: superseded by the in-iframe #pickbtn chip, and no
   #inspect-add element exists anymore, so the gold rules were dead. The guarded JS hooks are harmless no-ops.) */

.picks-backdrop { display:none; position:fixed; inset:0; z-index:109; background:rgba(6,5,4,.08); opacity:0;
  pointer-events:none; transition:opacity .3s; }
body[data-view="closet"] .picks-backdrop { display:block; }   /* both platforms: dim behind the summoned sheet + click-to-close */
body.picks-open .picks-backdrop { opacity:1; pointer-events:auto; }

@media (max-width:560px) {
  /* full-width: the summoned top sheet spans the screen edge-to-edge */
  .picks-tray { left:0; right:0; width:100%; max-width:none; transform:translateY(-101%); padding-left:16px; padding-right:16px; }
  body.picks-open .picks-tray, .picks-tray.reveal { transform:translateY(0); }
  /* one row of four — same hand as desktop, just tighter */
  .cm-slots { flex-wrap:wrap; gap:10px; margin:14px 0 14px; }
  .cm-slot { flex:0 0 calc((100% - 30px) / 4); width:auto; height:auto; aspect-ratio:2/3; border-radius:7px; }
  .cm-slot.is-filled { box-shadow:0 10px 32px rgba(0,0,0,.62), 0 3px 8px rgba(0,0,0,.38); }
  .cm-slot.is-filled img { border-radius:6px; }
  .cm-frame { border-radius:6px; }
  .cm-idx { font-size:20px; color:rgba(239,231,218,.3); }
  .cm-grab { margin:8px auto 0; }
}
/* The tray is now SUMMONED on both platforms (hidden until the chip is tapped → body.picks-open; or the brief
   .reveal flash when a film lands). It is no longer shown persistently during inspect on desktop — you add via
   the inspect chip's + (same as mobile), and review by summoning. (base .picks-tray is opacity:0 / pointer-events:none) */

/* the drop-target: the next empty slot, glowing, ghosting the film you're inspecting — click to drop it in */
.cm-slot.drop { cursor:pointer; overflow:visible;
  box-shadow: inset 0 2px 3px rgba(0,0,0,.85), 0 0 0 1.5px rgba(243,238,228,.7), 0 0 16px rgba(243,238,228,.35);
  animation:dropPulse 1.5s ease-in-out infinite; }
.cm-slot.drop .cm-idx { display:none; }
.cm-slot.drop .cm-ghost { position:absolute; inset:0; width:100%; height:100%; object-fit:cover; border-radius:4px; opacity:.34; }
.cm-slot.drop .cm-plus { position:absolute; inset:0; z-index:2; display:grid; place-items:center; font:200 26px/1 "Helvetica Neue",Arial,sans-serif; color:#fff; text-shadow:0 1px 5px rgba(0,0,0,.7); }
@keyframes dropPulse {
  0%,100% { box-shadow: inset 0 2px 3px rgba(0,0,0,.85), 0 0 0 1.5px rgba(243,238,228,.5), 0 0 11px rgba(243,238,228,.24); }
  50%     { box-shadow: inset 0 2px 3px rgba(0,0,0,.85), 0 0 0 1.5px rgba(243,238,228,.9), 0 0 22px rgba(243,238,228,.46); } }

/* ---------- The Polaroid (share artifact + recipient view) ---------- */
@font-face { font-family:'Caveat'; src:url('/assets/Caveat.ttf') format('truetype'); font-weight:400 700; font-display:swap; }

/* While the Polaroid is up, the page underneath still measures 1500-3300px tall, so it scrolls behind the
   overlay and carries a scrollbar the whole time. Lock it to the viewport for the duration. */
html.po-open, body.po-open { overflow:hidden; }
.polaroid-overlay { position:fixed; inset:0; z-index:120; display:flex; align-items:center; justify-content:center; }
.polaroid-overlay[hidden]{ display:none; }
.po-backdrop { position:absolute; inset:0; background:rgba(8,6,4,.86); -webkit-backdrop-filter:blur(8px); backdrop-filter:blur(8px); opacity:1; }
.po-drop .po-backdrop { animation:poFade .4s ease; }                                  /* recipient: a quick dim behind the dropped photo */
.po-printing .po-backdrop { animation:poFade var(--print-dur,2.2s) ease-in both; }    /* the room dims GRADUALLY over the whole print, then holds dark for the develop */
@keyframes poFade { from{opacity:0} to{opacity:1} }
/* the clip "viewport": while printing, everything above the slot line (the tray's bottom edge, --slot-y) is hidden,
   so the Polaroid reads as fed OUT of that slot. Dropped once it's fully printed (nothing sits above the slot then). */
/* scroll container: tall content (Polaroid + 6 named picks + actions) exceeds a phone viewport, so the stage
   scrolls. margin:auto on the stage centres it when it fits and falls back to top-aligned + scrollable when it
   doesn't (avoids the flexbox align-items:center top-clipping bug). The × + slot are overlay children → stay fixed. */
.po-clip { position:absolute; inset:0; display:flex; overflow-y:auto; overflow-x:hidden; overscroll-behavior:contain; -webkit-overflow-scrolling:touch; scroll-padding:24px 0; }
.po-printing .po-clip { clip-path:inset(var(--slot-y,0px) 0 0 0); }
/* the printer itself: a frosted device bar whose BOTTOM edge is the exit slot (echoes the picks tray's frosted glass,
   cream-lit). Its bottom sits exactly on --slot-y; the photo ratchets out of the dark mouth in ::before. */
.po-slot { position:absolute; left:50%; top:var(--slot-y,0px); transform:translate(-50%,-100%);
  width:min(508px,95vw); height:32px; z-index:3; opacity:0; pointer-events:none; border-radius:6px 6px 13px 13px;
  background:linear-gradient(180deg, rgba(40,37,34,.62) 0%, rgba(22,20,18,.80) 64%, rgba(12,11,10,.9) 100%);
  -webkit-backdrop-filter:blur(9px) saturate(1.15) brightness(.9); backdrop-filter:blur(9px) saturate(1.15) brightness(.9);
  box-shadow:inset 0 1px 0 rgba(243,238,228,.22), inset 0 -3px 7px rgba(0,0,0,.55), 0 10px 26px -8px rgba(0,0,0,.7), 0 1px 0 rgba(243,238,228,.07); }
/* the exit mouth — a thin black recess along the bottom edge; the photo slides out of here */
.po-slot::before { content:''; position:absolute; left:13px; right:13px; bottom:3px; height:6px; border-radius:4px;
  background:linear-gradient(180deg,#060504,#161310 55%,#060504);
  box-shadow:inset 0 2px 4px rgba(0,0,0,.95), 0 1px 0 rgba(243,238,228,.16); }
/* the soft shadow the device casts onto the freshly-emerged top of the photo */
.po-slot::after { content:''; position:absolute; left:50%; bottom:-17px; transform:translateX(-50%);
  width:calc(100% - 40px); height:22px; background:linear-gradient(180deg, rgba(0,0,0,.5), rgba(0,0,0,0)); }
.po-printing .po-slot { opacity:1; }
.po-ready .po-slot { opacity:0; transform:translate(-50%,-118%); transition:opacity .5s ease, transform .5s ease; }   /* the device lifts away as the print is done */

.po-stage { position:relative; display:flex; flex-direction:column; align-items:center; gap:18px; padding:58px 22px 44px; margin:auto; }   /* top pad clears the fixed × ; bottom pad gives the scroll a comfortable end */
.po-side { display:flex; flex-direction:column; align-items:center; gap:inherit; }   /* a real column even stacked (gap:inherit echoes the stage gap, so spacing is unchanged) — it must be one box so the fit-to-screen zoom can shrink the ACCESSORY content as a unit while the print keeps its size. Landscape desktop restyles it as the right-hand panel — see the media query below. */

.polaroid { --w:min(86vw, 420px); width:var(--w); background:#f7f3ea; padding:10px 10px 48px; position:relative;   /* thin border, deep chin — the photo is the object; a fat white margin read as a flat PNG, not a print you pulled from the closet */
  border-radius:3px; transform:rotate(-1.6deg);
  box-shadow:0 2px 2px rgba(0,0,0,.18), 0 30px 60px rgba(0,0,0,.6); }
.polaroid .po-cmark { position:absolute; left:10px; bottom:8px; pointer-events:none;
  font:700 13px/1 "Helvetica Neue",Helvetica,Arial,sans-serif; letter-spacing:-.055em; color:#23211c; opacity:.55; }
  /* the imprint, set in the chin's left corner — flush with the photo's own left edge (the print's 10px side
     padding) so it reads as part of the object's furniture, not a sticker. LETTERFORMS, not the dark app tile:
     a black rounded square on a cream chin reads as a sticker stuck on, where inked type reads as printed.
     Sized and dropped to share the address's optical centre: at 16px/bottom:7 it hung ~7px BELOW the text's ink
     and stood twice its height, so the two marks read as unrelated things rather than one printed line. */
.polaroid .po-brand { position:absolute; left:0; right:0; bottom:9px; text-align:center; pointer-events:none;
  font:700 9.5px "Helvetica Neue",Arial,sans-serif; letter-spacing:.1em; color:rgba(35,33,28,.62); }
  /* the ADDRESS, not the name: a Polaroid that travels should say where it came from in a form you can type.
     Bigger, far less tracking and nearly twice the contrast (.32 -> .62) — at 8px/.32em it was decorative
     texture rather than something a viewer could actually read off a screenshot. */   /* the maker's mark, embossed-quiet on the chin edge — attribution that survives a crop to just the print */
/* recipient (a shared link, no tray): the original gentle drop. Your OWN share prints instead (poPrint, below). */
.po-drop .polaroid { animation:poDrop .5s cubic-bezier(.2,.8,.25,1); }
@keyframes poDrop { from{ transform:translateY(-26px) rotate(-5deg) scale(.96); opacity:0 } to{ transform:rotate(-1.6deg); opacity:1 } }
/* the PRINT: the photo RATCHETS out of the slot bit by bit — a stepper-motor cadence of 6 kicks, each a quick feed
   then a held pause, like a real printer advancing the sheet line by line. The cubic-bezier makes each feed snap and
   settle; the equal-value keyframe pairs are the pauses between. A tiny overshoot on the last kick drops it free. */
.po-printing .polaroid { animation:poPrint var(--print-dur,2.2s) cubic-bezier(.33,.78,.32,1) forwards; will-change:transform; }
@keyframes poPrint {   /* --feed is the exact start offset (px, set in JS); 6 even kicks divide it, each a feed + a pause */
  0%   { transform:translateY(var(--feed,-106%))               rotate(-1.6deg); }   /* tucked behind the slot */
  6%   { transform:translateY(calc(var(--feed,-106%) * .833))  rotate(-1.6deg); }   /* kick 1 (first strip emerges) */
  17%  { transform:translateY(calc(var(--feed,-106%) * .833))  rotate(-1.6deg); }   /* pause */
  23%  { transform:translateY(calc(var(--feed,-106%) * .667))  rotate(-1.6deg); }   /* kick 2 */
  34%  { transform:translateY(calc(var(--feed,-106%) * .667))  rotate(-1.6deg); }
  40%  { transform:translateY(calc(var(--feed,-106%) * .5))    rotate(-1.6deg); }   /* kick 3 */
  51%  { transform:translateY(calc(var(--feed,-106%) * .5))    rotate(-1.6deg); }
  57%  { transform:translateY(calc(var(--feed,-106%) * .333))  rotate(-1.6deg); }   /* kick 4 */
  68%  { transform:translateY(calc(var(--feed,-106%) * .333))  rotate(-1.6deg); }
  74%  { transform:translateY(calc(var(--feed,-106%) * .167))  rotate(-1.6deg); }   /* kick 5 */
  85%  { transform:translateY(calc(var(--feed,-106%) * .167))  rotate(-1.6deg); }
  92%  { transform:translateY(7px)                             rotate(-1.6deg); }   /* kick 6 — nudges past, dropping free of the rollers */
  100% { transform:translateY(0)                               rotate(-1.6deg); } }
/* actions + caption hint hold back until the photo has printed AND developed — then they fade up */
.po-actions, .po-hint, .po-credit { position:relative; z-index:1; opacity:0; transform:translateY(7px); transition:opacity .5s ease, transform .5s ease; }   /* sit ABOVE the rotated photo (a stacking context) so its drop shadow can't fall over the buttons */
.po-actions { pointer-events:none; }                      /* don't let a stray click hit Share mid-print */
.po-ready .po-actions, .po-ready .po-hint, .po-ready .po-credit { opacity:1; transform:none; }
.po-ready .po-actions { pointer-events:auto; }
/* THE VIRAL HOOK — the four picks NAMED, a Wrapped-style tracklist under the Polaroid (light type on the dark backdrop) */
.po-list { position:relative; z-index:1; width:min(86vw,420px); margin-top:6px; text-align:left;
  opacity:0; transform:translateY(7px); transition:opacity .5s ease, transform .5s ease; }
.po-ready .po-list { opacity:1; transform:none; }
.pl-head { font:700 10.5px "Helvetica Neue",Arial,sans-serif; letter-spacing:.26em; text-transform:uppercase; color:rgba(231,201,161,.82); text-align:center; margin-bottom:12px; }   /* warm gold — matches the shared card, ties the list to the Polaroid's flash */
.pl-head .pl-count { color:rgba(231,201,161,.5); }   /* the "· 2 of 4" still-choosing suffix — same gold, quieter */
.pl-films { list-style:none; margin:0; padding:0; display:flex; flex-direction:column; gap:11px; }
.pl-films li { display:flex; align-items:flex-start; gap:11px; min-width:0; }
/* a short list centres UNDER the print: two rows ranged left below a centred Polaroid looked like the column
   had lost its other half; four rows are dense enough to hold their own edge. The BLOCK centres, not the rows —
   centring each row individually detaches the numbers from each other, so 1 and 2 land at different x depending
   on how long their titles are. Shrink-to-fit + auto margins keeps the number column intact. */
.pl-films.pl-short { width:max-content; max-width:100%; margin-inline:auto; }
.pl-n { flex:0 0 auto; width:15px; text-align:center; font:700 13px/1.32 "Helvetica Neue",Arial,sans-serif; color:rgba(231,201,161,.5); }
/* title on its own line (ellipsis only on extreme titles); director · year always on the line below — the meta is the payload, it must never clip */
.pl-film { min-width:0; display:flex; flex-direction:column; gap:1px; }
.pl-t { min-width:0; overflow:hidden; white-space:nowrap; text-overflow:ellipsis; font:700 14.5px/1.32 "Helvetica Neue",Arial,sans-serif; color:#f3ece0; }
.pl-meta { min-width:0; overflow:hidden; white-space:nowrap; text-overflow:ellipsis; font:500 12.5px/1.2 "Helvetica Neue",Arial,sans-serif; color:rgba(243,236,224,.64); }   /* .64 keeps the Director · Year (the payload) above the AA contrast floor on the dark veil */
.polaroid .photo { position:relative; width:100%; aspect-ratio:1/1; overflow:hidden; background:#0a0806;
  box-shadow:inset 0 0 0 1px rgba(0,0,0,.5), inset 0 2px 16px rgba(0,0,0,.45); }
/* the closet CORNER (two spine-walls meeting, shelves receding) — blurred so the picks stay the hero but the
   closet's own identity reads through */
.polaroid .wall { position:absolute; inset:-8%; background:url('/polaroid-wall.jpg') center/cover;
  filter:blur(2px) brightness(.66) saturate(1.04) contrast(1.03) sepia(.10); }   /* whisper bokeh — THE reference grade (the owner picked this look; a darker/saturated pass turned the beige wall mustard and was reverted). The PNG generator mirrors these numbers exactly. */
.polaroid .flash { position:absolute; inset:0;
  background:radial-gradient(76% 64% at 50% 50%, rgba(255,233,200,.34) 0%, rgba(255,206,150,.08) 46%, rgba(0,0,0,0) 74%); }
/* the four picks as a composed fan — slot positions are fixed; app.js maps each pick to one in order */
.polaroid .picks { position:absolute; inset:0; }
.polaroid .fanshadow { position:absolute; width:74%; height:30%; transform:translate(-50%,-50%); z-index:0;
  background:radial-gradient(closest-side, rgba(0,0,0,.5), rgba(0,0,0,.2) 56%, rgba(0,0,0,0) 80%); filter:blur(15px); }
.polaroid .fs-top { left:49%; top:37%; }
.polaroid .fs-bot { left:52%; top:72%; }
.polaroid .pick { position:absolute; width:var(--pw, 31.5%); aspect-ratio:.71; left:var(--x); top:var(--y); object-fit:cover;   /* --pw set per-count by FAN_LAYOUTS — fewer covers, bigger covers */
  transform-origin:50% 50%; transform:translate(-50%,-50%) rotate(var(--r,0deg)); z-index:var(--z,1);
  border-radius:2px; border:1px solid rgba(249,245,238,.5);   /* a hairline case-edge catching light — the old 2px solid white read as little photo mats, not DVD cases (the shadows below do the separation; the shared PNG never had mats either) */
  box-shadow:0 5px 11px rgba(0,0,0,.46), 0 18px 32px rgba(0,0,0,.46), inset 0 0 0 1px rgba(0,0,0,.14);
  filter:brightness(var(--b,1.05)) saturate(1.06) contrast(1.03); }
.polaroid .grade { position:absolute; inset:0; pointer-events:none;
  background:radial-gradient(112% 100% at 50% 48%, rgba(0,0,0,0) 52%, rgba(20,12,4,.5) 100%),
            linear-gradient(0deg, rgba(70,40,90,.05), rgba(255,220,170,.05)); }
.polaroid .grain { position:absolute; inset:0; opacity:.5; mix-blend-mode:overlay; pointer-events:none;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='2'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='.5'/%3E%3C/svg%3E"); }
.polaroid .develop { position:absolute; inset:0; z-index:6; pointer-events:none; background:#ece7d8; opacity:0; }
.polaroid.developing .develop { animation:poDevelop 1.7s ease forwards; }
.polaroid.developing .photo > :not(.develop):not(.wall) { animation:poSettle 1.9s ease forwards; }   /* exclude .wall — poSettle ends at filter:none, which would wipe the wall's bokeh blur */
@keyframes poDevelop { 0%{opacity:1} 100%{opacity:0} }
@keyframes poSettle { 0%{filter:contrast(.62) brightness(1.3) saturate(.35)} 100%{filter:none} }

.polaroid .caption { margin-top:24px; min-height:38px; display:flex; justify-content:center; align-items:baseline; gap:9px; transform:rotate(-1deg); }
.po-sig { font-family:'Caveat', cursive; font-size:40px; line-height:1.22; color:#23211c; outline:none; min-width:96px; max-width:280px; text-align:center; border-bottom:1.5px dashed rgba(35,33,28,.22); padding:3px 2px 4px; white-space:nowrap; overflow:hidden; }   /* line-height + vertical padding so Caveat's ascenders/descenders (it holds a NAME) aren't clipped. min-width 96: a 1-letter signature keeps a composed dashed baseline (24px left four floating dashes) */
.po-sig:empty:before { content:attr(data-ph); color:rgba(35,33,28,.42); }   /* the "sign here" prompt was fading into the chin at .3 */
.po-sig.ro { border-bottom:none; }   /* recipient view — read-only, no underline */
.po-sig:focus { border-bottom-color:rgba(35,33,28,.62); background:rgba(35,33,28,.05); border-radius:2px 2px 0 0; }   /* a real focus indicator on the only text field in the share flow (we set outline:none above) */

.po-actions { display:flex; gap:12px; flex-wrap:wrap; justify-content:center; }
.po-btn { display:inline-flex; align-items:center; justify-content:center; font:700 14px "Helvetica Neue",Arial,sans-serif; cursor:pointer; padding:13px 22px; border-radius:12px; border:1.5px solid transparent; transition:background .2s, border-color .2s, transform .1s; white-space:nowrap; text-decoration:none; }   /* inline-flex + no underline so an <a> (Buy me a coffee) sits identical to the buttons */
.po-btn:active { transform:translateY(1px); }
.po-btn.primary { background:linear-gradient(180deg,#f7f2ea,#e8e1d2); color:#1a140c; border-color:transparent;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.6); }   /* cream — matches the +chip and the tray's Share CTA (no gold) */
.po-btn.primary:hover { background:linear-gradient(180deg,#fdf9f1,#ece5d7); }
.po-btn.ghost { background:transparent; color:#f3ece0; border-color:rgba(243,236,224,.32); }
.po-btn.ghost:hover { border-color:#f3ece0; }
.po-credit { display:flex; align-items:center; justify-content:center; flex-wrap:nowrap; white-space:nowrap; gap:9px; font:500 13px "Helvetica Neue",Arial,sans-serif; color:rgba(243,236,224,.45); }   /* the makers' credit — ONE line of small print: names + the tip link (the email earned its keep nowhere and made it wrap) */
.po-credit[hidden] { display:none; }   /* display:flex would otherwise defeat the hidden attribute (recipient mode) */
.po-coffee { display:inline-flex; align-items:center; gap:7px; font:600 13px "Helvetica Neue",Arial,sans-serif; color:rgba(243,236,224,.62); text-decoration:none; padding:4px 0; }   /* the tip link inside the credit — one shade up from it, mug in the Esc menu's register */
.po-coffee:hover { color:#f3ece0; }
.po-cup { width:15px; height:15px; flex:none; }   /* the Esc menu's mug (stroke inherits the quiet ink, wakes with it on hover) */
.po-hint { font:500 13px "Helvetica Neue",Arial,sans-serif; color:rgba(243,236,224,.6); text-align:center; max-width:340px; }
.po-close { position:absolute; top:14px; right:16px; z-index:2; width:44px; height:44px; border-radius:50%;
  background:rgba(255,255,255,.08); border:1px solid rgba(243,236,224,.2); color:#f3ece0; font-size:22px; line-height:1; cursor:pointer;
  opacity:0; pointer-events:none; transition:opacity .45s ease; }   /* hidden during the print + develop — only appears once the photo's fully developed */
.po-developed .po-close { opacity:1; pointer-events:auto; }
.po-close:hover { background:rgba(255,255,255,.16); }

/* A stable path to the three core tools; the spatial doorway remains the flourish behind these controls. */
.closet-quickbar { display:none; position:fixed; left:12px; top:15px; z-index:72; padding:4px; gap:3px; border:1px solid rgba(255,255,255,.16);
  border-radius:999px; background:rgba(12,12,16,.52); color:#f2eee5; backdrop-filter:blur(16px); -webkit-backdrop-filter:blur(16px); }
body.closet-started[data-view="closet"]:not(.closet-intro):not(.closet-loading) .closet-quickbar { display:flex; }
body.closet-inspecting .closet-quickbar { opacity:0; pointer-events:none; }
.closet-quickbar button { min-height:40px; display:inline-flex; align-items:center; gap:8px; padding:0 13px; border:0; border-radius:999px;
  background:transparent; color:inherit; cursor:pointer; font:700 12px "Helvetica Neue",Arial,sans-serif; }
.closet-quickbar button:hover { background:rgba(255,255,255,.1); }
/* the Esc menu's marks, carried onto the corner bar — same SVG paths as .cf-ic, sized to sit beside the label.
   The coffee action rides along icon-only (it has no label to lose), closing the bar. */
.closet-quickbar .cqb-ic { width:15px; height:15px; display:block; flex:none; opacity:.82; }
.closet-quickbar button:hover .cqb-ic, .closet-quickbar .cqb-coffee:hover .cqb-ic,
.closet-quickbar .cqb-discord:hover .cqb-ic { opacity:1; }
.cqb-coffee, .cqb-discord { min-height:40px; display:inline-flex; align-items:center; justify-content:center; padding:0 12px;
  border-radius:999px; color:inherit; cursor:pointer; }
.cqb-coffee:hover, .cqb-discord:hover { background:rgba(255,255,255,.1); }
.closet-quickbar kbd { padding:2px 6px; border:1px solid rgba(255,255,255,.2); border-radius:5px; color:rgba(242,238,229,.64); background:rgba(0,0,0,.16); font:700 10px inherit; }
/* Random is back on the phone: with Picks out of this bar there's room, and it's one of the three tools worth reaching for. */
.cqb-count { color:#f2eee5; font-size:10px; }   /* white, same voice as the quickbar labels (gold was tried and retired) */
body.closet-started[data-view="closet"]:not(.closet-menu) .closet-actions { display:none; }

/* The top-right Esc/MENU pill is retired — Esc itself still opens the menu (closet/main.js posts
   'pausetoggle' for BOTH engines, so the key never depended on this pill). The corner's actions now read
   off the top-left quickbar instead. */
.ca-esc { display: none !important; }
.shared-picks-reopen { position:fixed; right:14px; bottom:16px; z-index:86; min-height:44px; padding:0 16px; border:1px solid rgba(255,255,255,.2);
  border-radius:999px; background:rgba(12,12,16,.78); color:#f3efe6; cursor:pointer; font:700 12px inherit; backdrop-filter:blur(14px); -webkit-backdrop-filter:blur(14px); }
.shared-picks-reopen[hidden] { display:none; }
.pl-film-btn { width:100%; min-height:44px; display:flex; align-items:center; gap:10px; padding:3px 5px; border:0; background:none; color:inherit; cursor:pointer; text-align:left; }

/* Progressive catalogue mounting: the sentinel is also an explicit keyboard fallback. */
.grid-more { grid-column:1/-1; justify-self:center; min-width:180px; min-height:44px; margin:4px 0 8px; padding:0 18px;
  border:1px solid var(--line2); border-radius:999px; background:var(--paper); color:var(--ink); cursor:pointer; font:700 13px inherit; }
.grid-more:hover { border-color:var(--ink); }

/* Shared List-card actions and richer guest/edition context. */
.card-quick { display:grid; grid-template-columns:1fr 1fr; gap:8px; margin:13px 0 16px; }
.card-quick button { min-height:42px; border:1px solid var(--line2); border-radius:10px; background:var(--cream); color:var(--ink); cursor:pointer; font:700 13px inherit; }
.card-quick button.on { background:var(--ink); color:var(--cream); border-color:var(--ink); }
.card-section { margin-top:17px; text-align:left; }
.card-section-title { margin-bottom:8px; color:var(--muted); font-size:10.5px; font-weight:800; letter-spacing:.14em; text-transform:uppercase; }
.card-section .actions { text-align:center; }
.edition-options { display:flex; flex-wrap:wrap; gap:7px; margin-bottom:9px; }
.edition-option { min-height:40px; padding:0 12px; border:1px solid var(--line); border-radius:999px; background:var(--cream); color:var(--muted); cursor:pointer; font:700 12px inherit; }
.edition-option[aria-pressed="true"] { background:var(--ink); border-color:var(--ink); color:var(--cream); }
.card-more { margin-top:11px; border-top:1px solid var(--line); padding-top:10px; text-align:left; }
.card-more summary { min-height:38px; display:flex; align-items:center; justify-content:space-between; cursor:pointer; color:var(--muted); font-size:13px; font-weight:700; list-style:none; }
.card-more summary::after { content:"+"; font-size:18px; }
.card-more[open] summary::after { content:"−"; }
.card-more-body { padding:3px 0 4px; color:var(--muted); font-size:12.5px; line-height:1.7; text-align:center; }
.card-guests { margin:16px 0 4px; padding-top:14px; border-top:1px solid var(--line); text-align:left; }
.guest-faces { display:flex; gap:7px; overflow-x:auto; padding:2px 2px 8px; }
.guest-face { flex:0 0 auto; width:44px; height:44px; padding:0; overflow:hidden; border:2px solid transparent; border-radius:50%; background:var(--cream); cursor:pointer; }
.guest-face[aria-pressed="true"] { border-color:var(--ink); }
.guest-face img { width:100%; height:100%; object-fit:cover; object-position:50% 30%; }
.guest-visit { padding:10px; border:1px solid var(--line); border-radius:12px; background:var(--cream); }
.guest-visit strong { display:block; margin-bottom:7px; font-size:13px; }
.guest-visit-frame { aspect-ratio:16/9; overflow:hidden; border-radius:8px; background:#000; }
.guest-visit-frame iframe { width:100%; height:100%; border:0; }
.guest-browse { width:100%; min-height:40px; margin-top:8px; border:1px solid var(--ink); border-radius:9px; background:transparent; cursor:pointer; font:700 12.5px inherit; }
.card-loading { min-height:34px; display:flex; align-items:center; justify-content:center; color:var(--muted); font-size:12px; }

/* Taste Twin is the earned epilogue to four Picks. */
/* The deck. On every width except the phone it is INVISIBLE to layout — display:contents drops it out of the
   box tree so .po-list and .po-taste stay direct flex children of .po-side exactly as before, and `order`
   restores their original sequence (list, actions, hint, taste, credit) since wrapping moved taste up. This is
   why the desktop panel needed no other change: nothing about it actually moved. */
.po-deck { display:contents; }
.po-taste { order:1; }
.po-credit { order:2; }
.po-tabs { display:none; }
.po-taste { width:100%; padding:15px 16px; border:1px solid rgba(231,201,161,.2); border-radius:14px; background:rgba(231,201,161,.06); color:#f3ece0; transition:opacity .5s ease; }   /* JS ramps opacity on unhide — the twin fades in with the panel, or later once it's computed */
.po-taste[hidden] { display:none; }
.pt-kicker { color:rgba(231,201,161,.78); font-size:10px; font-weight:800; letter-spacing:.2em; text-transform:uppercase; }
.pt-twin { display:flex; align-items:center; gap:10px; margin-top:9px; }
.pt-twin img { width:42px; height:42px; border-radius:50%; object-fit:cover; object-position:50% 30%; }
.pt-initials { width:42px; height:42px; display:grid; flex:0 0 auto; place-items:center; border-radius:50%; background:rgba(231,201,161,.16); color:#e7c9a1; font:800 13px inherit; font-style:normal; }
.pt-initials[hidden] { display:none; }
.pt-twin strong { display:block; font-size:16px; }
.pt-twin span { display:block; margin-top:2px; color:rgba(243,236,224,.62); font-size:12px; }
.pt-rec-label { margin-top:12px; color:rgba(243,236,224,.55); font-size:10.5px; font-weight:700; letter-spacing:.08em; text-transform:uppercase; }
.pt-recs { display:grid; grid-template-columns:repeat(3,1fr); gap:7px; margin-top:12px; }
.pt-rec { min-width:0; padding:0; border:0; background:none; color:inherit; cursor:pointer; text-align:left; }
.pt-rec img { width:100%; aspect-ratio:.71; border-radius:5px; object-fit:cover; box-shadow:0 5px 14px rgba(0,0,0,.34); }
.pt-rec span { display:block; margin-top:4px; overflow:hidden; color:rgba(243,236,224,.74); font-size:10.5px; line-height:1.2; white-space:nowrap; text-overflow:ellipsis; }

/* The close control belongs to the card's scrollport, so it never disappears above a long mobile detail. */
.card .close { position:sticky; top:0; z-index:5; display:flex; align-items:center; justify-content:center; width:44px; height:44px;
  margin:-18px -18px -26px auto; border:1px solid rgba(20,19,15,.12); border-radius:50%; background:rgba(251,249,244,.92);
  color:var(--muted); font-size:25px; line-height:1; cursor:pointer; backdrop-filter:blur(8px); -webkit-backdrop-filter:blur(8px); }
.tag { min-height:40px; display:inline-flex; align-items:center; justify-content:center; }

@media (max-width:640px) {
  body.filters-open { overflow:hidden; }
  .filter-panel { display:none; }
  /* …EXCEPT on the doorway console. In closet view that panel IS the filter UI — the deployed build shows
     Decade / Country / Language / Director / Format right on it. Collapsing them behind the summary row left
     the console looking empty: you spun to it and there were no filters to pick. */
  body[data-view="closet"]:not(.filters-open) .filter-panel { display:contents; }
  body[data-view="closet"] .mobile-summary { display:none; }
  body[data-view="closet"] .filter-panel .facets { display:flex; flex-wrap:wrap; gap:6px; margin:2px 0 6px; }
  body[data-view="closet"] .filter-panel .facet-btn { min-height:34px; font-size:12.5px; padding:0 11px; }
  body[data-view="closet"] .filter-panel .filter-sheet-head,
  body[data-view="closet"] .filter-panel .filter-sheet-actions { display:none; }   /* sheet furniture — the console has its own frame */
  body.filters-open .filter-panel { position:fixed; left:0; right:0; bottom:0; z-index:145; display:block; max-height:min(78svh,680px);
    padding:0 16px max(14px,env(safe-area-inset-bottom)); overflow-y:auto; border-radius:22px 22px 0 0; background:var(--paper);
    box-shadow:0 -24px 70px rgba(20,19,15,.28); }
  .filter-sheet-backdrop:not([hidden]) { position:fixed; inset:0; z-index:140; display:block; background:rgba(20,19,15,.48); }
  .filter-sheet-head { position:sticky; top:0; z-index:3; display:flex; align-items:center; justify-content:space-between; margin:0 -16px 14px;
    padding:16px 16px 12px; border-bottom:1px solid var(--line); background:rgba(251,249,244,.96); backdrop-filter:blur(12px); -webkit-backdrop-filter:blur(12px); }
  .filter-sheet-head h2 { margin:2px 0 0; font:700 25px/1.05 Georgia,"Times New Roman",serif; }
  .filter-sheet-kicker { color:var(--muted); font-size:9.5px; font-weight:800; letter-spacing:.14em; text-transform:uppercase; }
  .filter-sheet-close { width:44px; height:44px; border:1px solid var(--line); border-radius:50%; background:var(--cream); color:var(--ink); cursor:pointer; font-size:24px; }
  body.filters-open .filter-panel .facets { display:flex; width:100%; gap:7px; margin:0 0 10px; }
  body.filters-open .filter-panel .facet { flex:1 1 calc(50% - 7px); }
  body.filters-open .filter-panel .facet-btn { width:100%; min-height:42px; justify-content:center; }
  body.filters-open .filter-panel .facet-pop { position:static; width:100%; max-width:none; max-height:min(38svh,330px); margin:7px 0 4px; box-shadow:none; }
  body.filters-open .filter-panel .sort { display:flex; width:100%; margin:4px 0 12px; }
  body.filters-open .filter-panel .sort select { flex:1; min-height:42px; }
  body.filters-open .filter-panel .lists-row,
  body.filters-open .filter-panel .active,
  body.filters-open .filter-panel .status { display:flex; width:100%; }
  body.filters-open .filter-panel .lists-row { display:block; margin:10px 0 6px; }
  body.filters-open .filter-panel .status { margin:11px 0; }
  .filter-sheet-actions { position:sticky; bottom:calc(-1 * max(14px,env(safe-area-inset-bottom))); z-index:3; display:grid; grid-template-columns:1fr 1.4fr;
    gap:8px; margin:12px -16px calc(-1 * max(14px,env(safe-area-inset-bottom))); padding:12px 16px max(14px,env(safe-area-inset-bottom));
    border-top:1px solid var(--line); background:rgba(251,249,244,.97); backdrop-filter:blur(12px); -webkit-backdrop-filter:blur(12px); }
  .filter-sheet-actions button { min-height:46px; border:1px solid var(--ink); border-radius:11px; background:transparent; color:var(--ink); cursor:pointer; font:700 14px inherit; }
  .filter-sheet-actions #filter-sheet-apply { background:var(--ink); color:var(--cream); }
  .mobile-summary { width:100%; min-height:31px; display:flex; align-items:center; justify-content:space-between; margin:5px 0 0; padding:2px 1px 0;
    border:0; background:none; color:var(--muted); cursor:pointer; font:600 12px inherit; text-align:left; }
  .mobile-summary strong { color:var(--ink); }
  /* Phone chrome lives TOP-LEFT, mirroring the view toggle opposite it — a full-width bar pinned to the bottom
     buried the room's own title card and put the controls under the thumb that's trying to look around.
     Picks holds the corner; the tools sit beneath it as INDIVIDUAL frosted icon buttons — the language the
     deployed build already uses for its dice, rather than one slab of bar. Labels are dropped at this size:
     the icons carry them, and five labelled pills wrapped onto two rows. */
  .closet-quickbar { left:12px; right:auto; top:64px; bottom:auto; justify-content:flex-start; width:auto;
    max-width:calc(100vw - 24px); flex-wrap:wrap; gap:8px;
    background:none; border:none; box-shadow:none; padding:0;
    -webkit-backdrop-filter:none; backdrop-filter:none; }
  .closet-quickbar button, .closet-quickbar .cqb-coffee, .closet-quickbar .cqb-discord {
    flex:0 0 auto; width:42px; height:42px; min-height:42px; padding:0; gap:0; justify-content:center;
    background:rgba(10,10,13,.78); border:1px solid rgba(255,255,255,.22); border-radius:999px;
    -webkit-backdrop-filter:blur(14px) saturate(.9); backdrop-filter:blur(14px) saturate(.9);
    color:rgba(246,243,236,.98); opacity:1; box-shadow:0 6px 18px -8px rgba(0,0,0,.8);
    transition:transform .12s, background .15s; }
  .closet-quickbar button:active, .closet-quickbar .cqb-coffee:active, .closet-quickbar .cqb-discord:active { transform:translateY(1px); }
  /* the two OUTBOUND links sit top-right under the view toggle, away from the three tools that act on the room */
  .closet-quickbar .cqb-coffee { position:fixed; top:64px; right:62px; }
  .closet-quickbar .cqb-discord { position:fixed; top:64px; right:12px; }
  /* ONE plate for all the phone chrome. The Picks pill, the view toggle's glass and the tool buttons were three
     different tints (.44 / .5 / .78) with three different blurs, so they read as separate systems floating at
     different depths over the same room. Same surface for all three now. */
  .picks-chip, .closet-toggle, .closet-quickbar button,
  .closet-quickbar .cqb-coffee, .closet-quickbar .cqb-discord {
    background:rgba(10,10,13,.78); border:1px solid rgba(255,255,255,.22);
    -webkit-backdrop-filter:blur(14px) saturate(.9); backdrop-filter:blur(14px) saturate(.9);
    box-shadow:0 6px 18px -8px rgba(0,0,0,.8); opacity:1; }
  .closet-quickbar button > span, .closet-quickbar .cqb-count { display:none; }   /* icon-only: the label would double the width of every target */
  .closet-quickbar .cqb-ic { width:18px; height:18px; }
  .closet-quickbar kbd { display:none; }
  .card { padding-top:22px; }
  .card .close { margin:-12px -8px -32px auto; }
  .card-quick { position:sticky; bottom:-18px; z-index:4; margin:13px -8px 10px; padding:8px; border-radius:13px;
    background:rgba(251,249,244,.94); box-shadow:0 -8px 22px rgba(20,19,15,.06); backdrop-filter:blur(9px); -webkit-backdrop-filter:blur(9px); }
  .card-quick button { min-height:44px; }
  .tag { min-height:36px; padding-inline:12px; }
  .po-taste { padding:12px; }
  /* Keep Share above the fold on the twin pane. The co-pick row is the height sink — full-width thirds render
     ~143px tall, which pushed the actions 11px under on a 13 and 17px on an SE. Narrowing the ROW (rather than
     capping cover height) buys ~23px back without cropping the posters, whose titles run to the artwork edges. */
  .pt-recs { max-width:272px; margin-left:auto; margin-right:auto; gap:6px; margin-top:9px; }
  .pt-rec-label { margin-top:9px; }
  .pt-twin { margin-top:7px; }
}

/* Portrait phones: fit the core card on screen — Polaroid + four named picks + Share/Save — while the earned Taste
   Twin epilogue can scroll below. The Polaroid is height-capped (svh, the URL-bar-visible viewport, so it never overflows or
   resizes mid-scroll) and shrinks on short phones to make room for the list; the list + spacing tighten to suit.
   The scroll container above stays as a fallback for very small devices. */
@media (max-width: 640px) {
  .po-stage { gap:8px; padding:36px 18px 12px; margin:auto; }
  .polaroid-overlay { overflow-y:auto; align-items:flex-start; }   /* + stage margin:auto = centred when it fits, scrollable when it doesn't (the fallback for very small phones — nothing ever unreachable) */
  /* The print is sized to the VERTICAL budget the rest of the column leaves it (svh minus tracklist/buttons/hint/credit,
     ÷ the print's ~1.26 aspect). The tracklist charges only for rows that EXIST ([data-n], set per open) — a 1-pick
     print grows into its unused rows. 1st width decl = parse-time fallback for engines without svh (iOS 15.0–15.3);
     a var()-based version would NOT fall back (invalid-at-computed-value-time voids the width entirely). */
  /* the REVEAL got its budget back (the credit moved to the launch screen; the buttons slimmed): −34px of
     chrome per count and a wider cap — the print is the wow, everything else is small print */
  .polaroid, .po-list { width:min(88vw, 344px); }
  .polaroid, .po-list { width:min(88vw, 344px, calc((100svh - 324px - clamp(0px, (100svh - 664px) / 2, 20px)) / 1.26)); }
  .polaroid-overlay[data-n="3"] .polaroid, .polaroid-overlay[data-n="3"] .po-list { width:min(88vw, 344px, calc((100svh - 290px - clamp(0px, (100svh - 664px) / 2, 20px)) / 1.26)); }
  .polaroid-overlay[data-n="2"] .polaroid, .polaroid-overlay[data-n="2"] .po-list { width:min(88vw, 344px, calc((100svh - 256px - clamp(0px, (100svh - 664px) / 2, 20px)) / 1.26)); }
  .polaroid-overlay[data-n="1"] .polaroid, .polaroid-overlay[data-n="1"] .po-list { width:min(88vw, 344px, calc((100svh - 222px - clamp(0px, (100svh - 664px) / 2, 20px)) / 1.26)); }
  .polaroid { padding:11px 11px 34px; }
  .polaroid .caption { margin-top:11px; min-height:24px; }
  .po-sig { font-size:30px; }
  .po-list { margin-top:0; margin-top:clamp(0px, (100svh - 664px) / 2, 20px); }   /* taller phones: the spare height opens the print->header joint (the visibly tightest one) instead of pooling as dead margin outside the column; 664px = the smallest modern phone, where it stays 0 */
  .pl-head { margin-bottom:9px; }
  .pl-films { gap:8px; }   /* the rows were packed at 6px for the old six-row list — four rows can breathe */
  /* centred billing block, exactly like the shared PNG: no numbers, title + director·year centred under the print */
  .pl-films li { gap:0; justify-content:center; }
  /* the centring has to go on the BUTTON: it is width:100%, so centring the li moved nothing, and inside it the
     row fell back to flex-start — which is why the titles were ranged left under a centred print. */
  .pl-film-btn { justify-content:center; }
  .pl-n { display:none; }
  /* pane 2 IS the picks — a "Closet Picks" heading over it only repeats the pane you swiped to */
  .pl-head { display:none; }
  .pl-film { align-items:center; text-align:center; }
  .pl-t { font:700 14px/1.25 "Helvetica Neue",Arial,sans-serif; }    /* the NAMES are the wow's second half — they grow with the print */
  .pl-meta { font:500 11.5px/1.18 "Helvetica Neue",Arial,sans-serif; }
  .po-actions { gap:10px; margin-top:10px; }   /* the action row gets real AIR above it — the uniform stage gap read as one cramped block */
  .po-btn { padding:9px 16px; font-size:13px; }   /* compact pills — the reveal owns this screen, the buttons serve it */
  /* PHONE: films OR twin, never both. Stacked, the twin card plus its three co-pick covers doubled the height
     of an already-tall column and pushed Share off the fold — the reveal has to be reachable, not scrolled to.
     The panes swap in place (no translated track), so .po-list keeps the width rules that tie it to the print. */
  .po-deck { display:block; position:relative; }
  .po-stage { touch-action:pan-y; padding-bottom:44px; }
  /* the swipe surface is the whole stage — pane 1's deck is empty. The padding RESERVES the pinned dots' band:
     they are position:fixed and so out of flow, and without it the list and the twin ran underneath them on
     short phones (-19px on a 320). */
  /* Hide BOTH by default and let each pane opt IN. Listing what to hide per pane meant every new pane had to
     remember to hide everything else — the wallpaper pane didn't, and rendered the list and the twin under a
     full-bleed photo. Opt-in can't fail that way: a pane with no rule here simply shows the print alone. */
  .po-deck > .po-list, .po-deck > .po-taste { display:none; }
  .po-deck.po-films > .po-list { display:block; }
  .po-deck.po-twin > .po-taste { display:block; }
  /* Last pane: the PHOTO, frame off — full bleed, untilted, no chin, no marks. A wallpaper wants the image and
     nothing else. The 1:1 crop is kept deliberately: everything inside .photo is positioned in PERCENTAGES of
     it, so stretching it tall would spread the fan apart rather than fill — the composition is square. */
  /* The print is sized per PICK COUNT (data-n), which is right for the list but wrong here: the twin card is
     the same height whatever you picked, so at two picks the bigger print plus a full-size card ran 28px off
     the bottom of an SE. Size this pane for the card instead — ~330px, near the four-row allowance. */
  .polaroid-overlay.pane-twin .polaroid {
    width:min(88vw, 344px, calc((100svh - 330px - clamp(0px, (100svh - 664px) / 2, 20px)) / 1.26)); }
  /* Fewer picks leave spare height on the list pane, so the names take it — they are the payload. */
  .polaroid-overlay[data-n="1"] .pl-t { font-size:19px; }
  .polaroid-overlay[data-n="1"] .pl-meta { font-size:14px; }
  .polaroid-overlay[data-n="2"] .pl-t { font-size:17.5px; }
  .polaroid-overlay[data-n="2"] .pl-meta { font-size:13.5px; }
  .polaroid-overlay[data-n="3"] .pl-t { font-size:15.5px; }
  .polaroid-overlay[data-n="3"] .pl-meta { font-size:12.5px; }
  .polaroid-overlay.pane-wall .polaroid { width:100vw; padding:0; background:none; border-radius:0;
    box-shadow:none; transform:rotate(0deg); }
  .polaroid-overlay.pane-wall .polaroid .photo { box-shadow:none; }
  .polaroid-overlay.pane-wall .polaroid .caption,
  .polaroid-overlay.pane-wall .polaroid .po-brand,
  .polaroid-overlay.pane-wall .polaroid .po-cmark { display:none; }
  /* SHARE ONLY, and only on pane 1. Share posts a URL, not a file — the recipient can open the picks and make
     their own — so a screenshot cannot stand in for it. Save image CAN be screenshotted (and iOS puts "Save to
     Photos" inside the share sheet anyway), so it stays off: one control costs a third of the height two did,
     and the screenshot view stays clean. */
  .po-actions { display:none; }
  .polaroid-overlay.pane-print .po-actions,
  .polaroid-overlay.pane-wall .po-actions { display:flex; }   /* pane 1 AND the wallpaper pane carry Share + Save — the two panes built for taking the image away */
  /* Pane 1 is the SCREENSHOT view, so the print takes the height the list was holding: no head, no four rows.
     324px of allowance covers a full list; without it ~165px is enough for the dots, the actions and the gaps.
     The width eases rather than jumping, so swiping reads as the print opening up, not as a reflow. */
  .polaroid-overlay.pane-print .polaroid {
    width:min(92vw, 392px, calc((100svh - 152px - clamp(0px, (100svh - 664px) / 2, 20px)) / 1.26)); }   /* 108 -> 152: one Share pill sits under the print again, above the pinned dots */
  /* Every pane change plays the swipe: the print carries its own slide (the deck children already had one, so
     print->wall and wall->print were the two transitions with NO motion at all — they just snapped). A separate
     keyframe preserves the print's tilt; animating to transform:none would flatten it for the duration. */
  .polaroid.po-swap { animation:poPaneCard .3s cubic-bezier(.2,.8,.25,1); }
  .polaroid { transition:width .3s cubic-bezier(.2,.8,.25,1), padding .3s cubic-bezier(.2,.8,.25,1),
    transform .3s cubic-bezier(.2,.8,.25,1), background-color .3s ease, box-shadow .3s ease; }
  .po-deck > .po-list, .po-deck > .po-taste { animation:poPane .28s cubic-bezier(.2,.8,.25,1); }
  /* Dots, not a tab bar. A labelled bar cost ~35px of a column already fighting for height, and the gesture is
     the interaction — the dots only have to say "there is a second page" and show which one you're on. They
     stay real buttons (tappable, focusable, labelled) so the pane is reachable without the gesture too. */
  /* Dots are PINNED to the viewport, not laid out after the content. In flow they sat wherever that pane's
     content ended, so they jumped every swipe — the one element that should be the fixed point of the deck was
     the one moving most. Fixed bottom = identical y on every pane. */
  .po-tabs { position:fixed; left:50%; bottom:22px; transform:translateX(-50%); z-index:6;
    display:flex; gap:7px; align-items:center; padding:6px; }
  .po-tab { appearance:none; border:0; padding:0; cursor:pointer; width:7px; height:7px; border-radius:50%;
    background:rgba(243,236,224,.3); transition:background .18s ease, transform .18s ease; }
  .po-tab.is-on { background:rgba(243,236,224,.92); transform:scale(1.15); }
  .po-tab-t { position:absolute; width:1px; height:1px; margin:-1px; padding:0; overflow:hidden;
    clip-path:inset(50%); white-space:nowrap; }   /* label stays for screen readers, off the screen for everyone else */
  .po-hint { display:none; }   /* the chin's "sign it" patch IS the hint on mobile — a third line of small print under the buttons just read as clutter (desktop keeps it in the side panel) */
  .po-credit { display:none; }   /* the makers' credit lives on the LAUNCH screen now — down here it was stealing height from the print (desktop keeps it in the side panel) */
}

/* LANDSCAPE DESKTOP: the print develops dead-CENTRE (under the printer slot), then on reveal the Polaroid slides LEFT
   while the named tracklist + actions fan out as a panel on the RIGHT. Geometry: the stage is a centred row
   [Polaroid · gap · panel]; centred, the Polaroid's centre sits LEFT of screen-centre by (gap+panel)/2, so during the
   print/develop we shift the whole stage RIGHT by exactly that to park the Polaroid under the centre slot — then drop
   the shift on .po-ready and the Polaroid glides to its left seat as the right panel fades in. One transform does it. */
@media (min-width: 920px) and (orientation: landscape) {
  .polaroid-overlay { --po-gap: 48px; --po-side-w: 442px; }   /* wide enough for the three-button row (Share · Save image · Buy me a coffee) to hold one line */
  .po-stage { flex-direction:row; align-items:center; gap:var(--po-gap);
    transform:translateX(calc((var(--po-gap) + var(--po-side-w)) / 2));   /* print/develop phase: park the Polaroid dead-centre under the slot */
    transition:transform .75s cubic-bezier(.4,.72,.28,1); will-change:transform; }
  .po-ready .po-stage { transform:none; }   /* reveal: un-shift → the Polaroid slides LEFT to its row seat */
  .po-side { display:flex; flex-direction:column; align-items:flex-start; gap:18px; width:var(--po-side-w); flex:none;
    opacity:0; transform:translateX(-14px); transition:opacity .55s ease .12s, transform .55s ease .12s; }   /* hidden + nudged left during the centred print; settles in from the right on reveal (slight delay trails the slide) */
  .po-ready .po-side { opacity:1; transform:none; }
  .po-side .po-list { margin-top:0; width:100%; }   /* the list now heads the right panel (not under the photo) */
  .po-side .po-actions, .po-side .po-hint, .po-side .po-credit { justify-content:flex-start; text-align:left; align-self:stretch; }   /* left-align the panel contents (was centred under the photo) */
  /* the panel is a left-ragged column — the header must share the rows' left edge (its base centring floated it
     off-axis), and the list earns desktop sizing beside a 420px print (the base sizes are tuned for under-photo mobile) */
  .po-side .pl-head { text-align:left; font-size:13.5px; margin-bottom:16px; }   /* the panel's title, not just an eyebrow — needs presence next to the 17px film titles */
  .po-side .pl-films { gap:14px; }
  .po-side .pl-films.pl-short { width:100%; margin-inline:0; }   /* the panel is a left-ragged column by design — the under-print centring must not follow the list in here */
  .po-side .pl-n { width:17px; font-size:14.5px; }
  .po-side .pl-t { font-size:17px; }
  .po-side .pl-meta { font-size:14px; }
  .polaroid { flex:none; }   /* keep the photo its intrinsic width — don't let the row stretch/shrink it */
}

/* Reduced motion: neuter the decorative entrances/pulses (tray slide, the cover's flight to the tray, the Polaroid
   drop + develop, the INFINITE drop-slot pulse, the flares/pops) → they appear in place, instantly. The drop slot
   keeps its static cream ring (its base box-shadow), just without the pulse. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration:.01ms !important; animation-iteration-count:1 !important; transition-duration:.01ms !important; scroll-behavior:auto !important; }
}

@keyframes poPane { from { opacity:0; transform:translateX(var(--po-pane-from, 30px)); } to { opacity:1; transform:none; } }
@keyframes poPaneCard { from { opacity:.4; transform:translateX(var(--po-pane-from, 30px)) rotate(var(--po-tilt, -1.6deg)); }
                        to   { opacity:1; transform:rotate(var(--po-tilt, -1.6deg)); } }
@media (prefers-reduced-motion: reduce) { .po-deck > .po-list, .po-deck > .po-taste, .polaroid.po-swap { animation:none; } }

/* SHORT PHONES (SE-class, <=700px tall): even the films pane only clears by 13px there, so the twin pane needs
   a second trim. Both panes must keep Share reachable without scrolling — the whole point of splitting them. */
@media (max-width: 640px) and (max-height: 700px) {
  .pt-recs { max-width: 202px; margin-top: 7px; }
  .pt-rec-label { margin-top: 7px; }
  .po-taste { padding: 10px; }
  .pt-rec span { margin-top: 3px; font-size: 10px; }
}

/* VERY short phones (<=600px tall, e.g. a 320x568 SE): the twin card still ran under the pinned dots. Trim the
   co-pick covers again rather than shrink an already-small print — the names stay, since they are the payload. */
@media (max-width: 640px) and (max-height: 600px) {
  .pt-recs { max-width: 170px; }
}
