/* House of Brooklyn HQ — Media and Share information architecture.
   Namespaced so the real photo library and the rest of HQ keep their existing
   layout while the unified mixed-media index is completed. */

#view > .media{width:min(1120px,100%);max-width:1120px;margin-inline:auto;padding-bottom:56px}
/* Title and action on one row. The page used to open with a 66px heading, a
   two-line lede, a principle banner and a Drive panel — four blocks before a
   single file. The work starts in the first viewport now. */
.media-head{display:flex;justify-content:space-between;align-items:center;gap:22px;margin:4px 0 14px}
.media-head h1{font:400 clamp(32px,3.4vw,44px)/1.05 var(--f-d);margin:0;letter-spacing:-.02em}
.media-head .btn{flex:none}.media-head .btn svg{margin-right:7px;vertical-align:-3px}
/* THE TITLE, ON ITS OWN ROW (the Media redesign, 2026-09-27; this supersedes
   punch list item 12's heading cluster). Media is a tab root, so it keeps its
   large serif title (docs/ui-conventions.md); the controls that used to be
   glyphs beside it are now where the mockup puts them -- search in the tray
   above, the folder list and the thumbnail size as the Organize and Layout
   pills, Select as the third pill. The title still gives way first. */
.media-head h1{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* The magnifier, which is the one glyph left: a 44pt target, quiet, in the
   tray beside the upload button. */
.media-hbtn{display:inline-flex;align-items:center;justify-content:center;flex:none;
  width:44px;height:44px;padding:0;border:0;border-radius:999px;background:none;
  color:var(--ink);cursor:pointer}
.media-hbtn:hover{color:var(--accent)}
.media-hbtn[aria-expanded="true"]{color:var(--accent);background:var(--tint)}
.media-hbtn:focus-visible{outline:2px solid var(--focus);outline-offset:2px}
/* The search field, when the magnifier has revealed it, and the type chips:
   each a row of its own under the tabs. The chips scroll sideways, never
   wrap (docs/ui-conventions.md §6). */
.media-searchbar{margin:0 0 12px}
.media-searchbar[hidden]{display:none}
.media-searchbar .media-search{width:100%}
.media-typebar{display:flex;min-width:0;margin:0 0 12px}
.media-typebar .media-types{min-width:0;max-width:100%}
/* Kept for the preview banner and empty states; it is no longer the first
   thing a returning artist reads. */
.media-lede{max-width:640px;margin:0;color:var(--muted);font:400 14px/1.5 var(--f-s);text-wrap:pretty}
.media-principle{display:grid;grid-template-columns:auto 1fr;gap:12px;align-items:start;padding:15px 17px;border:1px solid var(--line);border-radius:13px;background:var(--tint);color:var(--accent)}
.media-principle p{margin:0;color:var(--muted);font:400 13px/1.55 var(--f-s)}.media-principle b{color:var(--ink);font-weight:600}
.media-view-nav{display:flex;align-items:center;gap:25px;margin:6px 0 13px;border-bottom:1px solid var(--line);overflow-x:auto;scrollbar-width:none}
.media-view-nav::-webkit-scrollbar{display:none}
.media-view-nav button,.media-view-nav a{position:relative;display:inline-flex;align-items:center;gap:6px;min-height:44px;padding:5px 0 10px;border:0;background:none;color:var(--muted);text-decoration:none;font:500 14px/1 var(--f-s);cursor:pointer}
.media-view-nav button:hover,.media-view-nav a:hover{color:var(--ink)}.media-view-nav .on{color:var(--ink)}
.media-view-nav .on::after{content:"";position:absolute;left:0;right:0;bottom:-1px;height:2px;border-radius:2px;background:var(--accent)}
.media-view-nav span{display:inline-flex;min-width:19px;height:19px;padding:0 5px;align-items:center;justify-content:center;border-radius:999px;background:var(--warn);color:var(--onsem);font:600 9px/1 var(--f-s)}
.media-search{min-width:0;display:flex;align-items:center;gap:8px;min-height:44px;padding:0 15px;border:1px solid var(--firm);border-radius:999px;background:var(--raised);color:var(--faint)}
.media-search input{flex:1;min-width:0;border:0;outline:0;background:none;color:var(--ink);font:400 14px/1 var(--f-s)}
/* THE TYPE TABS (the Media redesign, 2026-09-27; media-mockup/index.html).
   These were a pill track of six chips with no names and their counts beside
   them. Type is her second filter after search -- "a video, not a photograph"
   -- so each type is a tab with its own mark, its own count and a hairline
   under the row, and the chosen one is underlined in ink. Albums is the one
   door among them (.mtab-go) and goes to the collections.
   The row scrolls sideways and never wraps (docs/ui-conventions.md §6), so
   Artwork, Documents and Everything are one flick along, not gone. */
.media-types{display:flex;gap:4px;padding:0;border:0;border-bottom:1px solid var(--line);border-radius:0;background:none;overflow-x:auto;scrollbar-width:none}
.media-types::-webkit-scrollbar{display:none}
.media-types button,.media-types .mtab-go{flex:none;display:inline-flex;align-items:center;gap:6px;min-height:44px;padding:10px 7px 12px;margin-bottom:-1px;border:0;border-bottom:2.5px solid transparent;border-radius:0;background:none;color:var(--muted);font:400 15.5px/1 var(--f-s);white-space:nowrap;text-decoration:none;cursor:pointer}
.media-types button:hover,.media-types .mtab-go:hover{color:var(--ink)}
.media-types button[aria-pressed="true"]{background:none;box-shadow:none;color:var(--ink);border-bottom-color:var(--ink)}
.media-types svg{flex:none}.media-types b{font-weight:400}
.media-types button[aria-pressed="true"] b{font-weight:600}
.media-types button:focus-visible,.media-types .mtab-go:focus-visible{outline:2px solid var(--focus);outline-offset:-2px}
/* ONE HONEST COUNT. The tab that is already chosen hides its own count,
   because the line under the pills is that same number said properly --
   "60 of 603 shown" -- and the same figure printed twice is the duplicate
   this round removes. */
.media-types button span{margin-left:-1px;color:var(--faint);font:400 12.5px/1 var(--f-s)}
.media-types button span::before{content:"("}
.media-types button span::after{content:")"}
.media-types button[aria-pressed="true"] span{display:none}
.media-count{min-height:25px;padding:2px 2px 8px;color:var(--faint);font:400 12.5px/1.4 var(--f-s)}

/* ============================================================ the Media top bar
   (Media header final, 2026-09-29; supersedes the house tray of 2026-09-27)

   Her wordmark on the left, which is the Home link and not a menu; on the
   right the utility cluster -- upload, the magnifier, her face -- each a 44pt
   target. No name with a chevron: there is no House to choose here. The bar
   scrolls away with the page; nothing in this stack is sticky. */
.media-house{position:relative;display:flex;align-items:center;justify-content:space-between;gap:8px;padding:4px 0 0;min-height:48px}
/* The mark at its own proportions (800x300), about 150 wide, never stretched
   and never rebuilt from a font. It gives way before the controls do. */
.mhouse-mark{display:flex;align-items:center;flex:0 1 auto;min-width:0;min-height:44px;color:var(--ink);text-decoration:none}
.mhouse-mark img{display:block;width:152px;max-width:100%;height:auto}
/* Light on the warm dark ground: her mark is black artwork, so a dark room
   draws it the way the app bar does (app.css .mark img). */
html[data-room="dark"] .mhouse-mark img{filter:invert(1) brightness(1.9)}
.mhouse-said{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font:500 17px/1.2 var(--f-s)}
.mhouse-mark:focus-visible{outline:2px solid var(--focus);outline-offset:3px;border-radius:8px}
.mhouse-act{display:flex;align-items:center;gap:8px;flex:none;margin-left:auto}
/* ONE HOME FOR UPLOAD, and the one filled control on the screen: the plum
   button. There is no upload pill in the action row and no second door. */
.mhouse-up{display:inline-flex;align-items:center;justify-content:center;flex:none;width:44px;height:44px;padding:0;border:0;border-radius:999px;background:var(--cta);color:var(--oncta);cursor:pointer;box-shadow:0 4px 12px rgb(0 0 0/.22)}
.mhouse-up svg{stroke-width:2}
.mhouse-up:focus-visible{outline:2px solid var(--focus);outline-offset:3px}
.mhouse-face{position:relative;display:inline-flex;align-items:center;justify-content:center;flex:none;width:44px;height:44px;padding:0;overflow:hidden;border:2px solid var(--raised);border-radius:999px;background:var(--tile);color:var(--accent);font-size:0;cursor:pointer}
.mhouse-face:focus-visible{outline:2px solid var(--focus);outline-offset:3px}
.mface-pic{display:block;width:100%;height:100%;object-fit:cover;border-radius:999px}
.mface-in{font:600 14px/1 var(--f-s);color:var(--accent)}
/* From 1000px the app bar is on screen (index.html): its wordmark is the Home
   link, its upload opens this same sheet with Media's context, and its face
   is hers. Drawing ours as well put two wordmarks, two uploads and two faces
   on one screen, so only the magnifier, which the app bar lacks, stays. */
@media (min-width:1000px){
  .mhouse-mark,.mhouse-up,.mhouse-face{display:none}
}

/* REVIEW AND TRASH, at the head of the Organize panel: the two rooms the
   house menu used to hold that have no other door on the library. */
.mtree-rooms{display:flex;flex-direction:column;gap:2px;margin:0 0 12px;padding-bottom:10px;border-bottom:1px solid var(--line)}
.mroom{display:flex;align-items:center;gap:12px;min-height:48px;padding:12px 10px;border-radius:12px;color:var(--ink);font:400 16px/1.2 var(--f-s);text-decoration:none}
.mroom:hover,.mroom:active{background:var(--sunk)}
.mroom:focus-visible{outline:2px solid var(--focus);outline-offset:-2px}
.mroom > svg{flex:none;color:var(--muted)}
.mh-l{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* THE BADGE IS THE REVIEW COUNT. It, the Organize pill's and the sentence at
   the top of Review come from one function (reviewTally in
   public/app/media.js), so they cannot disagree. */
.mhouse-badge,.mpill-badge{display:inline-flex;flex:none;align-items:center;justify-content:center;min-width:22px;height:22px;padding:0 6px;border-radius:999px;background:var(--cta);color:var(--oncta);font:700 12px/1 var(--f-s)}
.mhouse-badge[hidden],.mpill-badge[hidden]{display:none}
.mpill-badge{min-width:20px;height:20px;margin-left:-2px;font-size:11px}
.mhouse-count{flex:none;color:var(--muted);font:400 14px/1 var(--f-s)}

/* THREE PILLS, NOT FOUR: Organize, Layout (which teaches the pinch that does
   the same thing with two fingers), Select. They are the one .choice pill
   (Select fills while it is on, like any pick); the plum upload button above
   is still the one primary on this screen. */
.media-acts{gap:10px;margin:14px 0 2px}
.media-acts .choice{min-height:46px;font-size:15.5px;font-weight:400;gap:8px}
.media-acts .choice b{font-weight:400}
/* THE ARTIST DECIDES HOW BIG A PICTURE IS, not the breakpoint.
   This was four fixed columns, then three, then two, so a library of seven
   hundred files was shown four at a time on a screen with room for twelve. The
   chosen size sets --media-tile, a MINIMUM tile width, and the column count follows
   from whatever space there is -- which is the only version of this that works
   at 320px and at 2560px without a second set of rules to keep in step.
   min(100%,...) is what stops a 280px minimum from overflowing a 320px phone. */
/* NEVER ONE COLUMN. A single column of large thumbnails is a slideshow, not a
   library, and it is what `min(100%, …)` gives on a 320px phone at any size
   above about 150px. The tile minimum is additionally clamped to half the row,
   so the artist's choice still decides between two, five or nine columns and
   the floor stays at two. */
.media-grid{display:grid;gap:12px;
  grid-template-columns:repeat(auto-fill,minmax(min(var(--media-tile,168px),(100% - 12px)/2),1fr))}
@media (max-width:719px){.media-grid{gap:9px;
  grid-template-columns:repeat(auto-fill,minmax(min(var(--media-tile,168px),(100% - 9px)/2),1fr))}}
/* Names and meta shrink with the tile, so a small tile is a picture and a
   large one is a picture with a caption you can read. */
@container (max-width:150px){.media-tile-copy{padding:8px 9px 9px}}
.media-tile{min-width:0;padding:0;overflow:hidden;border:1px solid var(--line);border-radius:14px;background:var(--raised);color:var(--ink);text-align:left;cursor:pointer}
.media-tile:hover{border-color:var(--accent);transform:translateY(-1px)}.media-tile:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.media-visual{position:relative;display:flex;align-items:center;justify-content:center;aspect-ratio:1.25/1;overflow:hidden;background:var(--tile)}
/* This device's picture of a file just sent, until HQ has made its own (LOCAL_LOOKS). */
.media-local{position:absolute;left:6px;bottom:6px;max-width:calc(100% - 12px);padding:2px 7px;border-radius:5px;
  background:color-mix(in srgb,#000 58%,transparent);color:#fff;font:500 10px/1.4 var(--f-s);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;pointer-events:none}
.media-visual img,.media-visual video{width:100%;height:100%;object-fit:cover;display:block;pointer-events:none}
.media-file-glyph{display:flex;flex-direction:column;align-items:center;gap:8px;color:var(--accent)}
/* An audio tile names its file (public/app/audio-name.js): the name in two
   lines at most, the song under it, so no two audio tiles look the same. */
.media-audio-tile{gap:6px;padding:0 10px 22px;max-width:100%;box-sizing:border-box;text-align:center}
.media-audio-tile b{font:500 12.5px/1.25 var(--f-s);color:var(--ink);display:-webkit-box;
  -webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;overflow-wrap:anywhere}
.media-audio-tile small{font:400 11px/1.2 var(--f-s);color:var(--muted);white-space:nowrap;
  overflow:hidden;text-overflow:ellipsis;max-width:100%}
.media-file-glyph em{font:600 9px/1 var(--f-s);font-style:normal;letter-spacing:.09em;text-transform:uppercase;color:var(--muted)}
.media-tile-copy{display:block;padding:11px 12px 12px;min-width:0}.media-tile-copy b,.media-tile-copy small{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-family:var(--f-s)}
.media-tile-copy b{font-size:12.5px;font-weight:600}.media-tile-copy small{margin-top:3px;color:var(--muted);font-size:10.5px}
.media-none{grid-column:1/-1;margin:0;padding:36px 18px;border:1px dashed var(--firm);border-radius:14px;color:var(--muted);text-align:center;font:400 13px/1.5 var(--f-s)}
.media-collections{scroll-margin-top:18px;margin-top:46px;padding-top:25px;border-top:1px solid var(--line)}
.media-section-head{display:flex;justify-content:space-between;align-items:flex-end;gap:20px;margin-bottom:15px}.media-section-head h2{max-width:680px;margin:5px 0 0;font:400 clamp(24px,3.1vw,34px)/1.12 var(--f-d)}
.media-collection-grid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:10px}
.media-collection-grid a{display:grid;grid-template-columns:auto 1fr;gap:7px 10px;min-height:112px;padding:16px;border:1px solid var(--line);border-radius:13px;background:var(--raised);color:var(--ink);text-decoration:none}
.media-collection-grid a:hover{border-color:var(--accent)}.media-collection-grid a > span{grid-row:1/3;color:var(--accent)}
.media-collection-grid b,.media-collection-grid small{font-family:var(--f-s)}.media-collection-grid b{align-self:end;font-size:13px}.media-collection-grid small{color:var(--muted);font-size:10.5px;overflow-wrap:anywhere}
.media-boundary{display:flex;align-items:center;justify-content:space-between;gap:22px;margin-top:25px;padding:15px 17px;border-top:1px solid var(--line);border-bottom:1px solid var(--line)}
.media-boundary p{max-width:770px;margin:0;color:var(--muted);font:400 11.5px/1.5 var(--f-s)}.media-boundary b{color:var(--ink);font-weight:600}.media-boundary a{flex:none;color:var(--accent);font:600 11.5px/1.3 var(--f-s)}
.media-viewer .lbstage video,.media-viewer .lbstage iframe{display:block;width:min(1040px,100%);height:min(68vh,720px);border:0;border-radius:8px;background:#111}
.media-audio-view{width:min(680px,100%);padding:50px 30px;border:1px solid rgba(255,255,255,.15);border-radius:14px;color:#fff;text-align:center}
.media-audio-view svg{margin-bottom:25px}.media-audio-view audio{display:block;width:100%}

/* The populated route is visibly a prototype and uses reduced presentation
   copies of Brooklyn's own source media. This notice stays close to the view
   switcher so screenshots cannot accidentally look like stored production data. */
.media-preview-note{display:grid;grid-template-columns:auto minmax(0,1fr) auto;gap:11px 14px;align-items:center;margin:14px 0 0;padding:12px 14px;border:1px solid var(--firm);border-radius:12px;background:var(--raised)}
.media-preview-note > span{display:flex;color:var(--good)}.media-preview-note p{margin:0;color:var(--muted);font:400 11.5px/1.5 var(--f-s)}
.media-preview-note b{color:var(--ink);font-weight:600}.media-preview-note a{color:var(--accent);font:600 11px/1.3 var(--f-s);white-space:nowrap}

/* Type-aware sample artwork. The CSS treatment is deliberately quiet: the
   source media is the hero and file type is obvious without a row of badges. */
.media-demo-visual{position:relative;display:flex;width:100%;height:100%;min-height:0;overflow:hidden}
.media-demo-visual.image img{display:block;width:100%;height:100%;object-fit:cover}.media-demo-visual.image.cover img{object-fit:cover}
.media-demo-visual.image.live img{object-position:50% 26%}.media-demo-visual.image.story img{object-position:center}
.media-demo-play{position:absolute;inset:0;display:grid;place-items:center;background:linear-gradient(180deg,transparent 52%,rgba(17,10,14,.25))}
.media-demo-play i{width:42px;height:42px;border-radius:50%;background:rgba(251,246,241,.92);box-shadow:0 7px 22px rgba(22,10,16,.3)}
.media-demo-play i::after{content:"";display:block;margin:13px 0 0 16px;border-top:8px solid transparent;border-bottom:8px solid transparent;border-left:12px solid #2A1A22}
.media-demo-visual > small{position:absolute;right:8px;bottom:8px;padding:4px 7px;border-radius:999px;background:rgba(24,14,20,.78);color:#FBF6F1;font:600 9px/1 var(--f-m)}
.media-demo-visual.audio{align-items:center;justify-content:center;gap:14px;padding:22px;background:linear-gradient(145deg,var(--lift),var(--sunk));color:var(--accent)}
.media-demo-disc{display:grid;place-items:center;flex:0 0 48px;width:48px;height:48px;border-radius:50%;border:1px solid var(--firm);background:var(--raised)}
.media-demo-wave{display:flex;align-items:center;gap:3px;width:min(68%,180px);height:62px}.media-demo-wave i{flex:1;min-width:2px;border-radius:99px;background:currentColor;opacity:.7}
.media-demo-visual.document{align-items:center;justify-content:center;padding:18px;background:linear-gradient(135deg,var(--sunk),var(--lift));color:var(--ink)}
.media-demo-paper{display:flex;flex-direction:column;justify-content:space-between;width:52%;height:80%;min-width:78px;padding:11px;border:1px solid var(--firm);border-radius:3px;background:var(--ground);box-shadow:7px 8px 0 color-mix(in srgb,var(--accent) 18%,transparent)}
.media-demo-paper i,.media-demo-paper em{font:600 7px/1 var(--f-s);font-style:normal;letter-spacing:.14em;color:var(--muted)}.media-demo-paper b{font:400 clamp(11px,1.2vw,17px)/1.05 var(--f-d)}
.media-tile-copy em{display:block;margin-top:7px;color:var(--accent);font:500 9px/1.2 var(--f-s);font-style:normal;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

/* Collections show recognizable overlapping covers, rather than pretending
   they are folders. */
.media-collection-view,.media-review-view{margin-top:3px}.media-section-head > div > p:last-child{max-width:650px;margin:7px 0 0;color:var(--muted);font:400 13px/1.5 var(--f-s)}
.media-section-head .btn{flex:none}.media-collection-showcase{gap:12px}
.media-collection-card{display:grid;grid-template-rows:150px 1fr;min-width:0;padding:0;overflow:hidden;border:1px solid var(--line);border-radius:15px;background:var(--raised);color:var(--ink);text-align:left;cursor:pointer}
.media-collection-card:hover{border-color:var(--accent);transform:translateY(-1px)}.media-collection-card:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.media-collection-covers{position:relative;display:block;overflow:hidden;background:var(--sunk)}
.media-collection-covers > .media-demo-visual{position:absolute;top:15px;width:54%;height:118px;border:2px solid var(--raised);border-radius:10px;box-shadow:0 5px 15px color-mix(in srgb,var(--ink) 16%,transparent)}
.media-collection-covers > .media-demo-visual:nth-child(1){left:8%;z-index:3;transform:rotate(-4deg)}.media-collection-covers > .media-demo-visual:nth-child(2){left:25%;z-index:2;transform:rotate(2deg)}.media-collection-covers > .media-demo-visual:nth-child(3){left:40%;z-index:1;transform:rotate(6deg)}
.media-collection-covers > .media-demo-visual.audio{padding:10px;gap:5px}.media-collection-covers .media-demo-disc{display:none}.media-collection-covers .media-demo-wave{width:100%;height:48px;gap:2px}.media-collection-covers .media-demo-paper{width:72%;height:82%;padding:7px}.media-collection-covers > i{position:absolute;inset:0;display:grid;place-items:center;color:var(--accent)}
.media-collection-copy{display:flex;flex-direction:column;min-width:0;padding:14px 15px 16px}.media-collection-copy small{color:var(--accent);font:600 9px/1 var(--f-s);letter-spacing:.05em;text-transform:uppercase}
.media-collection-copy b{margin-top:7px;font:400 20px/1.08 var(--f-d)}.media-collection-copy em{margin-top:5px;color:var(--muted);font:500 10px/1 var(--f-s);font-style:normal}
.media-collection-copy p{margin:12px 0 0;color:var(--muted);font:400 11px/1.45 var(--f-s)}

/* Review is a short decision queue, not another asset grid. */
.media-review-intro{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:8px 24px;align-items:end;margin:8px 0 19px}.media-review-intro .eyebrow{grid-column:1/-1;margin:0}
.media-review-intro h2{max-width:720px;margin:0;font:400 clamp(26px,3.2vw,38px)/1.08 var(--f-d)}.media-review-intro > p:not(.eyebrow){max-width:650px;margin:0;color:var(--muted);font:400 13px/1.5 var(--f-s)}
.media-review-counts{grid-column:2;grid-row:2/4;display:grid;grid-template-columns:repeat(2,auto);gap:6px}.media-review-counts span{min-width:92px;padding:10px 12px;border:1px solid var(--line);border-radius:10px;background:var(--raised);color:var(--muted);font:500 9.5px/1.25 var(--f-s)}
.media-review-counts b{display:block;margin-bottom:2px;color:var(--ink);font:400 21px/1 var(--f-d)}
.media-review-list{display:grid;gap:9px}.media-review-card{display:grid;grid-template-columns:112px minmax(0,1fr) auto;gap:15px;align-items:center;padding:10px;border:1px solid var(--line);border-radius:14px;background:var(--raised)}
.media-review-thumb{height:88px;overflow:hidden;border-radius:9px;background:var(--sunk)}.media-review-thumb .media-demo-visual.audio{padding:12px;gap:7px}.media-review-thumb .media-demo-disc{display:none}.media-review-thumb .media-demo-wave{width:100%;height:42px}.media-review-thumb .media-demo-paper{height:88%;padding:6px}
.media-review-copy{min-width:0}.media-review-copy > span{color:var(--accent);font:600 9px/1 var(--f-s);letter-spacing:.06em;text-transform:uppercase}.media-review-copy h3{margin:5px 0 3px;font:500 14px/1.25 var(--f-s)}
.media-review-copy p{margin:0;color:var(--muted);font:400 11px/1.45 var(--f-s)}.media-review-copy small{display:block;margin-top:7px;color:var(--faint);font:500 9.5px/1.2 var(--f-s)}
.media-review-actions{display:flex;gap:7px}.media-review-actions .btn{white-space:nowrap}

/* Collection sheet: a quick contextual view. */
.media-collection-sheet .sheetpanel{max-width:820px}.media-collection-sheet .sheetpanel > .eyebrow{margin:0 0 3px}
.media-collection-dialog-note{max-width:650px;margin:5px 0 14px;color:var(--muted);font:400 13px/1.5 var(--f-s)}
.media-collection-dialog-meta{display:flex;gap:7px;overflow-x:auto;margin-bottom:14px}.media-collection-dialog-meta span{min-width:110px;padding:9px 11px;border:1px solid var(--line);border-radius:9px;background:var(--raised);color:var(--muted);font:500 9px/1.2 var(--f-s);white-space:nowrap}.media-collection-dialog-meta b{display:block;color:var(--ink);font:400 18px/1 var(--f-d)}
.media-collection-dialog-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:9px}.media-collection-dialog-grid > button{min-width:0;padding:0 0 10px;overflow:hidden;border:1px solid var(--line);border-radius:11px;background:var(--raised);color:var(--ink);text-align:left;cursor:pointer}
.media-collection-dialog-grid > button:hover{border-color:var(--accent)}.media-collection-dialog-grid .media-demo-visual{height:106px}.media-collection-dialog-grid button > b,.media-collection-dialog-grid button > small{display:block;margin-inline:10px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-family:var(--f-s)}
.media-collection-dialog-grid button > b{margin-top:9px;font-size:11.5px}.media-collection-dialog-grid button > small{margin-top:3px;color:var(--muted);font-size:9px;text-transform:capitalize}
.media-collection-rule{display:flex;gap:9px;align-items:flex-start;margin-top:15px;padding:11px 12px;border-radius:10px;background:var(--tint);color:var(--accent)}.media-collection-rule p{margin:0;color:var(--muted);font:400 10.5px/1.45 var(--f-s)}.media-collection-rule b{color:var(--ink)}.media-collection-sheet .sheetacts small{color:var(--muted);font:400 10px/1.4 var(--f-s)}

/* The detail view is the decisive Media interaction: the asset stays large,
   while provenance, rights and every relationship remain visible beside it. */
.lightbox.media-viewer{align-items:center;justify-content:center;padding:18px;background:rgba(18,11,16,.96)}
.media-viewer-shell{display:grid;grid-template-columns:minmax(0,1.65fr) minmax(340px,.72fr);width:min(1320px,100%);height:min(880px,calc(100dvh - 36px));overflow:hidden;border:1px solid rgba(251,246,241,.17);border-radius:18px;background:#21171D;box-shadow:0 22px 70px rgba(0,0,0,.42)}
.media-viewer-stage{position:relative;display:grid;place-items:center;min-width:0;min-height:0;padding:28px;background:#120D10;overflow:hidden}
.media-viewer-stage > img,.media-viewer-stage > video,.media-viewer-stage > iframe{display:block;max-width:100%;max-height:100%;border:0;border-radius:8px;object-fit:contain;background:#0E0A0C}.media-viewer-stage > video,.media-viewer-stage > iframe{width:100%;height:100%}
.media-viewer-stage .media-demo-visual{width:100%;height:100%;border-radius:8px}.media-viewer-stage .media-demo-visual.image img{object-fit:contain;background:#120D10}.media-viewer-stage .media-demo-visual.image.live img{object-position:center}.media-viewer-stage .media-demo-visual.audio{width:min(720px,90%);height:280px;border:1px solid rgba(251,246,241,.16);border-radius:16px;background:linear-gradient(145deg,#2B1F26,#171014)}
.media-viewer-stage .media-demo-visual.document{width:min(560px,86%);height:min(650px,88%);border-radius:12px;background:#1A1217}.media-viewer-stage .media-demo-paper{max-width:300px}.media-viewer-type{position:absolute;left:17px;bottom:15px;padding:5px 8px;border:1px solid rgba(251,246,241,.2);border-radius:999px;background:rgba(18,11,16,.74);color:rgba(251,246,241,.78);font:600 9px/1 var(--f-s);text-transform:capitalize}
.media-viewer-info{position:relative;min-width:0;overflow-y:auto;padding:28px 27px 30px;background:#21171D;color:#FBF6F1}.media-viewer-info .lbclose{top:14px;right:14px}.media-viewer-info .eyebrow{margin:2px 48px 9px 0;color:#C8A4B8}.media-viewer-info h2{margin:0 46px 7px 0;font:400 clamp(25px,2.6vw,38px)/1.04 var(--f-d);overflow-wrap:anywhere}
.media-viewer-sub{margin:0;color:rgba(251,246,241,.58);font:400 10.5px/1.5 var(--f-s);overflow-wrap:anywhere}.media-viewer-actions{display:flex;flex-wrap:wrap;gap:7px;margin:18px 0}.media-viewer-actions .btn{min-height:42px;background:rgba(251,246,241,.07);border-color:rgba(251,246,241,.22);color:#FBF6F1}.media-viewer-actions .btn.primary{background:#FBF6F1;border-color:#FBF6F1;color:#2A1A22}
.media-viewer-facts{margin:0;border-top:1px solid rgba(251,246,241,.13)}.media-viewer-facts div{display:grid;grid-template-columns:76px minmax(0,1fr);gap:10px;padding:9px 0;border-bottom:1px solid rgba(251,246,241,.11);font:400 10.5px/1.4 var(--f-s)}.media-viewer-facts dt{color:rgba(251,246,241,.46)}.media-viewer-facts dd{margin:0;color:rgba(251,246,241,.84);overflow-wrap:anywhere}
.media-viewer-section{margin-top:22px}.media-viewer-section > div{display:flex;justify-content:space-between;align-items:baseline;gap:10px}.media-viewer-section h3{margin:0;font:500 12.5px/1.2 var(--f-s)}.media-viewer-section > div small{color:rgba(251,246,241,.42);font:500 9px/1 var(--f-s)}
.media-viewer-chips{display:flex;flex-wrap:wrap;gap:5px;margin:10px 0 0}.media-viewer-chips span{padding:6px 8px;border:1px solid rgba(251,246,241,.17);border-radius:999px;color:rgba(251,246,241,.76);font:500 9.5px/1 var(--f-s)}.media-viewer-chips em{color:rgba(251,246,241,.5);font:400 10.5px/1.4 var(--f-s);font-style:normal}
.media-viewer-section ul{display:grid;gap:6px;margin:10px 0 0;padding:0;list-style:none}.media-viewer-section li{display:flex;gap:7px;align-items:center;color:rgba(251,246,241,.72);font:400 10.5px/1.35 var(--f-s)}.media-viewer-section li svg{flex:none;color:#8FBF9A}
/* What is still being prepared, in the viewer's details panel. A pair per
   stage: what it is, and the one sentence about it. Deliberately quiet -- this
   section only exists when something is unfinished, and it must read as
   information rather than as an alarm. */
.mv-proc-list{display:grid;gap:7px;margin:10px 0 0;padding:0;list-style:none}
.mv-proc-list li{display:grid;grid-template-columns:76px minmax(0,1fr);gap:9px;align-items:baseline}
.mv-proc-list b{color:rgba(251,246,241,.82);font:500 10px/1.35 var(--f-s)}
.mv-proc-list span{color:rgba(251,246,241,.6);font:400 10.5px/1.4 var(--f-s)}
#mv-proc[hidden]{display:none}
#mv-proc .tb.mini{margin-top:11px}
.media-viewer-rule{margin:22px 0 0;padding-top:13px;border-top:1px solid rgba(251,246,241,.12);color:rgba(251,246,241,.46);font:400 9.5px/1.45 var(--f-s)}
.media-add-card{margin:0 0 18px;padding:13px;border:1px solid rgba(251,246,241,.2);border-radius:11px;background:rgba(251,246,241,.06)}.media-add-card[hidden]{display:none}.media-add-card > div:first-child{display:flex;justify-content:space-between;gap:9px;align-items:center}.media-add-card b{font:600 11.5px/1 var(--f-s)}.media-add-card [data-media-add-close]{width:32px;height:32px;border:0;background:none;color:#FBF6F1;font-size:22px;cursor:pointer}.media-add-card p{margin:4px 0 10px;color:rgba(251,246,241,.55);font:400 10px/1.4 var(--f-s)}
.media-add-card > div:nth-of-type(2){display:flex;flex-wrap:wrap;gap:5px}.media-add-card [data-media-collection-choice]{min-height:34px;padding:6px 8px;border:1px solid rgba(251,246,241,.16);border-radius:999px;background:none;color:rgba(251,246,241,.66);font:500 9px/1 var(--f-s);cursor:pointer}.media-add-card [data-media-collection-choice] svg{display:none}.media-add-card [data-media-collection-choice][aria-pressed="true"]{border-color:#FBF6F1;color:#FBF6F1;background:rgba(251,246,241,.08)}.media-add-card [data-media-collection-choice][aria-pressed="true"] svg{display:inline}.media-add-card > .btn{margin-top:10px}.media-add-card > small{display:block;margin-top:7px;color:rgba(251,246,241,.45);font:400 9px/1.3 var(--f-s)}

/* First and fan relationships share one lane, while their data stays separate. */
.reach-context{display:flex;align-items:flex-end;justify-content:space-between;gap:20px;margin:5px 0 28px;padding:15px 0;border-bottom:1px solid var(--line)}
.reach-context p{margin:3px 0 0;max-width:390px;color:var(--muted);font:400 12px/1.45 var(--f-s)}
.reach-context nav{display:flex;gap:4px;padding:3px;border:1px solid var(--line);border-radius:999px;background:var(--sunk)}
.reach-context nav a{min-height:36px;display:flex;align-items:center;padding:7px 11px;border-radius:999px;color:var(--muted);text-decoration:none;font:500 10.5px/1 var(--f-s);white-space:nowrap}
.reach-context nav a:hover{color:var(--ink)}.reach-context nav a.on{background:var(--raised);color:var(--ink);box-shadow:0 1px 5px color-mix(in srgb,var(--ink) 9%,transparent)}

/* The made-collection cards still step by breakpoint; they are cards, not
   thumbnails, and nothing sizes them. .media-grid is deliberately NOT here any
   more -- it was the rule that silently overrode the slider below 900px. */
@media(max-width:900px){.media-collection-grid{grid-template-columns:repeat(3,minmax(0,1fr))}}
@media(max-width:760px){
  .media-types{margin-inline:-2px}.media-collection-grid{grid-template-columns:repeat(2,minmax(0,1fr))}
  .reach-context{align-items:flex-start;flex-direction:column}.reach-context nav{max-width:100%;overflow-x:auto}
  .media-preview-note{grid-template-columns:auto 1fr}.media-preview-note a{grid-column:2}.media-review-intro{grid-template-columns:1fr}.media-review-counts{grid-column:1;grid-row:auto;grid-template-columns:repeat(4,minmax(86px,1fr));overflow-x:auto}.media-review-card{grid-template-columns:88px minmax(0,1fr)}.media-review-thumb{height:78px}.media-review-actions{grid-column:1/-1;justify-content:flex-end}
  .lightbox.media-viewer{padding:0}.media-viewer-shell{grid-template-columns:1fr;grid-template-rows:minmax(280px,44dvh) minmax(0,1fr);height:100dvh;border:0;border-radius:0}.media-viewer-stage{padding:18px}.media-viewer-info{padding:22px 20px calc(30px + env(safe-area-inset-bottom,0px))}.media-viewer-info .lbclose{position:fixed;top:max(10px,env(safe-area-inset-top));right:11px}.media-viewer-stage .media-demo-visual.audio{height:190px}
}
@media(max-width:520px){
  .media-principle{padding:13px}
  .media-view-nav{gap:20px;margin-top:18px}.media-types{border-inline:0;border-radius:0;padding-inline:0;background:none}
  .media-tile{border-radius:11px}.media-tile-copy{padding:9px 10px 10px}.media-collection-grid{grid-template-columns:1fr}
  .media-section-head{align-items:flex-start;flex-direction:column}.media-boundary{align-items:flex-start;flex-direction:column;gap:10px}.media-viewer .lbstage iframe{height:58vh}
  .media-collection-card{grid-template-rows:135px 1fr}.media-collection-dialog-grid{grid-template-columns:repeat(2,minmax(0,1fr))}.media-review-counts{margin-right:-2px}.media-review-card{grid-template-columns:72px minmax(0,1fr);gap:11px}.media-review-thumb{height:70px}.media-review-actions{justify-content:stretch}.media-review-actions .btn{flex:1}.media-viewer-actions .btn{flex:1}.media-viewer-shell{grid-template-rows:minmax(235px,38dvh) minmax(0,1fr)}
}
@media(prefers-reduced-motion:reduce){.media-tile{transition:none}.media-tile:hover{transform:none}.media-collections{scroll-behavior:auto}}

/* Where a move-in starts.
   Sits with the principle note rather than in the toolbar: connecting a Drive
   is something an artist does once, not a control they reach for. */
.media-drive{display:grid;grid-template-columns:1fr auto;gap:18px;align-items:center;margin:13px 0 0;padding:17px 19px;border:1px solid var(--line);border-radius:13px;background:var(--raised)}
.media-drive-copy{min-width:0}
.media-drive-copy .eyebrow{margin:0 0 3px}
.media-drive h2{margin:0 0 5px;color:var(--ink);font:500 16px/1.3 var(--f-s)}
.media-drive p{margin:0;color:var(--muted);font:400 13px/1.55 var(--f-s)}
.media-drive b{color:var(--ink);font-weight:600}
.media-drive-act{display:flex;align-items:center}
/* The deadline, when there is one. A House whose app is internal to the
   artist's own Google organization has none, and says nothing. */
.media-drive-deadline{margin:7px 0 0!important;padding:8px 11px;border-radius:9px;background:var(--tint);color:var(--accent)!important;font-size:12px!important}
.media-drive-said{display:flex;align-items:center;gap:6px;margin:7px 0 0!important;font-size:12px!important}
.media-drive-said.ok{color:var(--good)!important}
.media-drive-said.bad{color:var(--warn)!important}
/* On a phone the button goes under the words rather than squeezing them. */
@media (max-width:719px){
  .media-drive{grid-template-columns:1fr;gap:13px}
  .media-drive-act .btn{width:100%;justify-content:center}
}

/* Choosing where a move-in starts. Ours rather than Google's Picker, which
   would want a Drive token in the page — see the comment in app.js. */
.media-drive-browse{grid-column:1/-1;margin:15px 0 0;padding:15px 0 0;border-top:1px solid var(--line)}
.media-drive-loading{color:var(--faint)!important;font-size:12px!important}
.media-drive-crumbs{display:flex;flex-wrap:wrap;align-items:center;gap:5px;margin:0 0 11px;font:400 12px/1 var(--f-s)}
.media-drive-crumbs button{min-height:28px;padding:0;border:0;background:none;color:var(--link);font:inherit;cursor:pointer;text-decoration:underline}
.media-drive-crumbs b{color:var(--ink);font-weight:600}.media-drive-crumbs i{color:var(--faint);font-style:normal}
.media-drive-folders{display:grid;grid-template-columns:repeat(auto-fill,minmax(210px,1fr));gap:5px;margin:0;padding:0;list-style:none;max-height:290px;overflow-y:auto}
.media-drive-folders button{display:flex;align-items:center;gap:8px;width:100%;min-height:42px;padding:8px 11px;border:1px solid transparent;border-radius:9px;background:none;color:var(--ink);font:400 13px/1.3 var(--f-s);text-align:left;cursor:pointer}
.media-drive-folders button:hover{border-color:var(--line);background:var(--sunk)}
.media-drive-folders button span{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.media-drive-empty{padding:9px 2px;color:var(--faint);font:400 12px/1.5 var(--f-s)}
.media-drive-pick{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:11px;margin:13px 0 0;padding:12px 14px;border-radius:11px;background:var(--tint)}
.media-drive-pick p{margin:0;color:var(--accent)!important;font-size:12.5px!important}

/* How far along a move-in is. A window onto something already running, not a
   thing this page drives — it survives the tab closing. */
.media-drive-progress{grid-column:1/-1;margin:15px 0 0;padding:14px 0 0;border-top:1px solid var(--line)}
.media-drive-prog-head{display:flex;align-items:baseline;justify-content:space-between;gap:11px;margin:0 0 7px}
.media-drive-prog-head b{color:var(--ink);font:500 13.5px/1.35 var(--f-s)}
.media-drive-prog-head span{color:var(--muted);font:500 12px/1 var(--f-m)}
.media-drive-prog-said{margin:8px 0 0!important;color:var(--muted)!important;font-size:12px!important}
.media-drive-prog-said .bad{color:var(--warn)}

/* The Trash: what is waiting, and how long it has. */
.media-trash-list,.media-folder-list{margin:0 0 7px;padding:0;list-style:none;display:grid;gap:5px}
.media-folder-list li{display:grid;grid-template-columns:1fr auto;gap:13px;align-items:center;padding:10px 13px;border:1px solid var(--line);border-radius:11px;background:var(--raised)}
/* A Trash row: a face that slides over its swipe action (Put back to the
   right, Delete now to the left), a long-press menu, and in Select mode a
   checkbox (Phase 3 punch list, item 12). */
.media-trash-list li{border:1px solid var(--line);border-radius:11px;background:var(--raised)}
.mt-face{display:grid;grid-template-columns:1fr auto auto;gap:13px;align-items:center;padding:10px 13px;
  background:var(--raised);border-radius:inherit}
.media-trash-list.selecting .mt-face{grid-template-columns:auto 1fr auto}
.media-trash-list.selecting .mt-acts{display:none}
.mt-pick{display:inline-flex;align-items:center}
.mt-pick[hidden]{display:none}
.mt-pick input{width:22px;height:22px;accent-color:var(--accent)}
.mt-acts{display:flex;gap:6px}
.mt-acts .btn{flex:none}
.mt-headacts{display:flex;gap:8px;flex-wrap:wrap;margin-top:10px}
.mt-headacts .btn{flex:none}
.mt-selbar{position:sticky;top:8px;z-index:3;display:flex;align-items:center;justify-content:space-between;gap:10px;
  margin:0 0 8px;padding:8px 10px 8px 14px;border:1px solid var(--line);border-radius:12px;background:var(--raised);
  font:500 13px var(--f-s);color:var(--ink);box-shadow:0 6px 18px rgba(0,0,0,.08)}
.mt-selbar[hidden]{display:none}
.mt-selbar .btn{flex:none}
.mt-what{min-width:0;display:flex;flex-direction:column;gap:2px}
.mt-what b{color:var(--ink);font:500 13px/1.3 var(--f-s);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.mt-what small{color:var(--faint);font:400 11.5px/1.3 var(--f-s);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.mt-when{color:var(--muted);font:500 11.5px/1 var(--f-m);white-space:nowrap}
.media-section-head.folders{margin-top:26px}
/* The two-step removal. Nothing happens until the second press. */
@media (max-width:719px){
  .mt-face{grid-template-columns:1fr auto}
  .media-trash-list .mt-when{grid-column:1/-1;order:3}
  .media-trash-list.selecting .mt-face{grid-template-columns:auto 1fr}
}


/* The import status line. Present only when an import is running or a
   connection needs attention; silent otherwise, because setup for a job
   already finished is not news. */
.media-driveline{display:flex;align-items:center;justify-content:space-between;gap:15px;margin:0 0 13px;padding:11px 15px;border:1px solid var(--line);border-radius:11px;background:var(--raised)}
.media-driveline.needs{border-color:var(--warn);background:var(--tint)}
.media-driveline p{margin:0;color:var(--muted);font:400 13px/1.45 var(--f-s)}
.media-driveline.needs p{color:var(--accent)}
.media-driveline-prog{flex:1;min-width:0}
.media-driveline-prog .media-drive-prog-head{margin-bottom:5px}
@media (max-width:719px){
  .media-driveline{flex-direction:column;align-items:stretch;gap:9px}
  .media-driveline .btn{width:100%;justify-content:center}
}

/* Selecting and opening are different intentions, so they are different
   controls. The checkbox is always visible — hover-only selection is
   unreachable on a phone and invisible to anyone scanning for it. */
/* The wrapper is the grid item now, so it has to pass its height on. Without
   this the tile keeps its natural height inside a stretched cell and a caption
   that wraps to two lines pushes its own row out of alignment with the rest. */
.media-tile-wrap{position:relative;display:flex;flex-direction:column}
.media-tile-wrap > .media-tile{flex:1;width:100%}
.media-pick{position:absolute;top:8px;left:8px;z-index:2;display:flex;align-items:center;justify-content:center;width:34px;height:34px;border-radius:9px;background:color-mix(in srgb,var(--ground) 82%,transparent);backdrop-filter:blur(3px);cursor:pointer}
.media-pick input{width:18px;height:18px;margin:0;accent-color:var(--accent);cursor:pointer}
.media-tile-wrap.picked .media-tile{outline:2px solid var(--accent);outline-offset:-2px;border-radius:11px}
.media-tile-wrap.picked .media-pick{background:var(--accent)}
.media-tile-wrap.picked .media-pick input{accent-color:var(--ground)}
/* A 34px box holding an 18px control clears the 24px WCAG minimum; the whole
   label is the target, not just the box. */
@media (pointer:coarse){.media-pick{width:44px;height:44px}}

/* What is selected, and what can be done with it. Sticks to the top of the
   grid so the count does not scroll away from the files it describes. */
.media-picked{position:sticky;top:0;z-index:3;display:flex;flex-wrap:wrap;align-items:center;gap:11px;margin:0 0 11px;padding:11px 15px;border:1px solid var(--accent);border-radius:11px;background:var(--raised)}
.media-picked-count{margin:0;flex:1;min-width:150px;color:var(--muted);font:400 13px/1.4 var(--f-s)}
.media-picked-count b{color:var(--ink);font-weight:600}
.media-picked-act{display:flex;flex-wrap:wrap;gap:8px}
.media-picked-note{flex-basis:100%;margin:0;color:var(--faint);font:400 12px/1.5 var(--f-s)}
@media (max-width:719px){
  .media-picked{gap:9px}
  .media-picked-act{width:100%}
  .media-picked-act .btn{flex:1;justify-content:center;min-height:44px}
}

/* More, rather than a silent horizon. The library used to stop at its fetch
   limit and say nothing, so a file past it simply did not exist. */
.media-more{display:flex;justify-content:center;margin:15px 0 0}
.media-more .btn{min-height:44px;padding:0 22px}

/* WHERE THE FILES CAME FROM: the trail back up, and the folders below.
   These are the collections — see media.origins for why they are derived. */
.media-folders{display:flex;flex-direction:column;gap:9px;margin:0 0 14px}
.media-trail{display:flex;flex-wrap:wrap;align-items:center;gap:6px;font:500 12px/1.3 var(--f-s)}
.media-trail a{color:var(--muted);text-decoration:none;padding:3px 7px;border-radius:7px}
.media-trail a:hover{color:var(--ink);background:var(--tile)}
.media-trail a.on{color:var(--ink);background:var(--tile)}
.media-trail span{color:var(--line)}
.media-folder-chips{display:flex;flex-wrap:wrap;gap:7px}
.mfc{display:inline-flex;align-items:center;gap:7px;padding:5px 10px;border:1px solid var(--line);
  border-radius:999px;background:var(--raised);color:var(--ink);text-decoration:none;
  font:500 11.5px/1.2 var(--f-s)}
.mfc:hover{border-color:var(--accent)}
.mfc span{color:var(--muted);font-size:10.5px}
/* A COLLECTION CARD IS A LINK NOW, AND MUST KEEP THE LAYOUT THE BUTTON HAD.
   Two existing rules apply to it the moment it becomes an anchor: the generic
   `.media-collection-grid a` two-column row, and `... a > span` which pins
   every child to grid-row 1/3. Both have to be undone explicitly, or the
   cover collapses to the height of its own image and the card reads as a
   thin strip with a caption under it. */
a.media-collection-card{text-decoration:none;color:inherit}
.media-collection-grid a.media-collection-card{display:grid;grid-template-columns:none;
  grid-template-rows:150px 1fr;gap:0;padding:0;min-height:0}
.media-collection-grid a.media-collection-card > span{grid-row:auto;color:inherit}
.media-collection-covers img{position:absolute;inset:0;width:100%;height:100%;
  object-fit:cover;display:block}
@media(max-width:600px){.media-collection-grid a.media-collection-card{grid-template-rows:135px 1fr}}
.media-loose{margin:14px 0 0;font:400 11.5px/1.5 var(--f-s)}
.media-loose a{color:var(--muted);text-decoration:none;border-bottom:1px solid var(--line)}
.media-loose a:hover{color:var(--ink);border-color:var(--accent)}

/* COLLECTIONS SOMEBODY MADE, above the folders work arrived in. */
.media-make{margin:0 0 14px}
.media-collection-card.made .media-collection-copy small{color:var(--accent)}
.media-viewer-was{margin:6px 0 0;color:var(--muted);font:400 11px/1.5 var(--f-s)}
.media-viewer-was b{color:var(--ink);font-weight:500}
.mvrename{margin-left:9px;padding:3px 9px;border:1px solid var(--line);border-radius:999px;
  background:transparent;color:var(--muted);font:500 10.5px/1.2 var(--f-s);cursor:pointer;
  vertical-align:middle}
.mvrename:hover{color:var(--ink);border-color:var(--accent)}

/* Where a selection goes. Existing collections first; making one is last. */
.media-addto-sheet .sheetpanel{max-width:480px}
.addto-list{display:flex;flex-direction:column;gap:6px;margin:14px 0 0;
  max-height:46vh;overflow:auto}
.addto-one{display:flex;align-items:baseline;justify-content:space-between;gap:12px;
  width:100%;padding:11px 13px;border:1px solid var(--line);border-radius:11px;
  background:var(--raised);color:var(--ink);text-align:left;cursor:pointer}
.addto-one:hover{border-color:var(--accent)}
.addto-one[disabled]{opacity:.5;cursor:default}
.addto-one b{font:500 13px/1.2 var(--f-s)}
.addto-one small{color:var(--muted);font:400 10.5px/1 var(--f-s)}
.addto-said{margin:11px 0 0;color:var(--muted);font:400 11.5px/1.5 var(--f-s)}
.addto-said.bad{color:var(--said-bad)}

/* ===================================================== organizing the library

   The tree beside the grid, the size control, the destination sheet and the
   bottom bar a thumb can reach. Wide screens get the tree standing up; narrow
   ones get the same folders in a sheet, because a 220px column on a 390px
   phone leaves 170px for photographs. */

/* ROOM FOR THE PICTURES.
   The Media page had its own 1120px cap on top of the shell's, which is right
   for a column of prose and wrong for a library: with the tree standing beside
   it the grid was 858px on a 1440px display. The library view takes the width
   the shell already allows wide pages -- the same escape .pgrid and Direct
   take -- and stops there rather than breaking the application's measure. */
@media (min-width:1200px){
  #view > .media:has(.media-library-view){width:100%}
}
.media-shell{display:grid;grid-template-columns:minmax(0,1fr);gap:0}
@media (min-width:1024px){
  .media-shell{grid-template-columns:238px minmax(0,1fr);gap:24px;align-items:start}
  .media-shell.closed{grid-template-columns:minmax(0,1fr)}
  .media-shell.closed .media-tree{display:none}
  .media-tree{position:sticky;top:12px;max-height:calc(100dvh - 40px);overflow:auto;
    padding-right:14px;border-right:1px solid var(--line);scrollbar-width:thin}
  /* Organize STAYS on a wide screen with the tree open (the Media redesign,
     2026-09-27). It used to be hidden there, because a glyph that summons an
     already-visible list reads as broken; the pill is a toggle with a spoken
     state (aria-expanded), so hiding it would instead leave a row of two
     pills where there are three and no way to put the tree away. */
}
/* Below that it is a sheet, opened from the Folders button and closed by it. */
@media (max-width:1023px){
  .media-tree{display:none;margin:0 0 14px;padding:14px;border:1px solid var(--line);
    border-radius:13px;background:var(--raised)}
  .media-shell:not(.closed) .media-tree{display:block}
}
.mtree-top{display:flex;align-items:center;justify-content:space-between;gap:8px;margin-bottom:6px}
.mtree-top .eyebrow{margin:0}
.mtree-close{display:none;width:34px;height:34px;border:0;border-radius:8px;background:none;
  color:var(--muted);cursor:pointer;transform:rotate(180deg)}
.mtree-close:hover{color:var(--ink);background:var(--tile)}
@media (min-width:1024px){.mtree-close{display:inline-flex;align-items:center;justify-content:center}}
.mtree-group + .mtree-group{margin-top:18px}
.mtree-head{margin:0 0 5px;color:var(--faint);font:600 9.5px/1 var(--f-s);letter-spacing:.09em;text-transform:uppercase}
.mtree,.mtree ul{margin:0;padding:0;list-style:none}
.mtree-row{display:flex;align-items:center;gap:2px;padding-left:calc(var(--d,0) * 13px);border-radius:8px}
.mtree-row.on{background:var(--tint)}
.mtree-row.on .mtree-node{color:var(--ink);font-weight:600}
.mtree-twist{display:inline-flex;align-items:center;justify-content:center;flex:none;
  width:22px;height:34px;border:0;background:none;color:var(--faint);cursor:pointer}
.mtree-twist[aria-expanded="true"]{transform:rotate(90deg)}
.mtree-twist:hover{color:var(--ink)}
.mtree-node{display:flex;flex:1;min-width:0;align-items:center;gap:7px;min-height:34px;
  padding:5px 8px 5px 2px;border:0;border-radius:8px;background:none;color:var(--muted);
  text-align:left;font:500 12.5px/1.25 var(--f-s);cursor:pointer}
.mtree-node svg{flex:none;color:var(--accent);opacity:.8}
.mtree-node span{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.mtree-node small{flex:none;color:var(--faint);font:500 10px/1 var(--f-m)}
.mtree-node:hover{color:var(--ink);background:var(--tile)}
.mtree-node:focus-visible{outline:2px solid var(--accent);outline-offset:1px}
/* A destination, said with an outline rather than only with a color. */
.mtree-node.drop{outline:2px dashed var(--accent);outline-offset:-1px;background:var(--tint);color:var(--ink)}
.mtree-none{margin:2px 8px;color:var(--faint);font:400 11.5px/1.4 var(--f-s)}
.mtree-new{margin-top:9px;width:100%;justify-content:center}
@media (pointer:coarse){.mtree-node,.mtree-twist{min-height:44px}}

.media-where{display:flex;flex-wrap:wrap;align-items:center;gap:9px;margin:0 0 12px}
.media-where .media-trail{flex:1;min-width:0}
.media-where-act{flex:none}


/* A tile being dragged fades rather than vanishes: it is still selected. */
.media-tile-wrap.dragging{opacity:.45}
.media-tile-wrap[draggable="true"] .media-tile{cursor:pointer}

/* The bulk bar stays reachable. It is sticky at the top on a desktop, where
   the controls are; on a phone it is a bar at the bottom, in the thumb's
   reach, above the home indicator. */
@media (max-width:760px){
  /* Above the tab bar, not behind it. The application's own navigation is
     fixed to the bottom of the window, so a bulk bar at `bottom:0` puts its
     buttons underneath five tabs -- visible, unpressable, and obviously fine
     on a desktop where the tab bar is not there. */
  .media-picked{position:fixed;left:0;right:0;top:auto;z-index:41;margin:0;
    bottom:calc(58px + env(safe-area-inset-bottom,0px));
    border-radius:14px 14px 0 0;border-width:1px 0 0;
    padding:11px 15px;
    box-shadow:0 -8px 24px color-mix(in srgb,var(--ink) 22%,transparent)}
  .media-picked-act{width:100%}
  .media-picked-act .btn{flex:1 1 44%;justify-content:center;min-height:44px}
  /* Room to scroll past the bar rather than under it. */
  #view > .media{padding-bottom:180px}
}

/* Where you are in the queue, on the stage rather than in the panel: it is
   about the picture, and on a phone the panel is below the fold. */
.media-viewer-where{position:absolute;left:50%;bottom:15px;transform:translateX(-50%);
  margin:0;padding:5px 11px;border-radius:999px;background:rgba(18,11,16,.74);
  border:1px solid rgba(251,246,241,.2);color:rgba(251,246,241,.82);
  font:500 10.5px/1 var(--f-m);white-space:nowrap}
.media-viewer-actions .btn.on{background:#FBF6F1;border-color:#FBF6F1;color:#2A1A22}

/* The destination sheet: one list, filterable, reachable one-handed. */
.media-dest-sheet .sheetpanel{max-width:560px}
.dest-find{margin:0 0 12px}
.dest-head{margin:14px 0 6px;color:var(--faint);font:600 9.5px/1 var(--f-s);letter-spacing:.09em;text-transform:uppercase}
.dest-head:first-child{margin-top:0}
.dest-scroll{max-height:min(46dvh,420px);overflow:auto;margin:0 -4px;padding:0 4px}
.dest-list{display:grid;gap:4px}
.dest-one{display:flex;align-items:center;gap:9px;width:100%;min-height:46px;
  padding:9px 12px 9px calc(12px + var(--d,0) * 14px);border:1px solid var(--line);
  border-radius:10px;background:var(--raised);color:var(--ink);text-align:left;cursor:pointer}
.dest-one:hover{border-color:var(--accent)}
.dest-one:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.dest-one svg{flex:none;color:var(--accent);opacity:.8}
.dest-one b{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font:600 12.5px/1.3 var(--f-s)}
.dest-one small{flex:none;color:var(--faint);font:500 10px/1 var(--f-m)}
.dest-one[hidden]{display:none}
/* Rows after the lists: "New folder or project" (opens a question, then a name),
   and, alone at the foot, taking the folder out of its project in wine red. */
.dest-more,.dest-out{margin-top:14px}
.dest-check{flex:none;display:inline-flex;color:var(--accent)}
.dest-t{flex:1;min-width:0;display:flex;flex-direction:column}
.dest-t b{flex:none}
.dest-sub{margin-top:2px;font:400 11.5px/1.3 var(--f-s);color:var(--muted)}
.dest-one.bad,.dest-one.bad svg{color:var(--destructive)}
.dest-one.bad:hover{border-color:var(--destructive)}

/* A toast that offers Undo has to stay long enough to be pressed.
   Sized to what it says (still capped by .looktoast's max-width): centered
   with left:50%, it could otherwise never be wider than half the screen, and
   the button -- a flex item allowed to shrink -- was crushed into a tall
   pill beside a two-line sentence on a phone. */
.looktoast.with-act{display:flex;align-items:center;gap:12px;width:max-content}
.looktoast.with-act .btn{flex:none}

@media(prefers-reduced-motion:reduce){
  .mtree-twist{transition:none}
  .media-tile-wrap.dragging{opacity:1;outline:2px dashed var(--accent)}
}

/* A thumbnail standing in for the display copy, while that loads. It is a
   400px picture shown large, so it is soft already; the mark is a quiet pulse
   rather than a spinner, and it stops the moment the real one swaps in. */
.lbimg.waiting{filter:saturate(.92)}
.lbimg.waiting::after{content:""}
@media (prefers-reduced-motion:no-preference){
  .lbimg{transition:filter .18s ease}
}

/* ==========================================================================
   A PHONE IS FOR LOOKING AT PHOTOGRAPHS
   ==========================================================================

   Measured on an iPhone 17e at 390x844 before any of this existed: the first
   photograph began 604 points down a 844-point screen. Seventy-two per cent of
   the phone was chrome -- a wordmark, a page title, two buttons, a Drive
   banner, four tabs, a folder button, a search field, a row of type chips, a
   density slider and a count -- and the library itself was a two-column strip
   at the bottom, each tile giving twenty-seven per cent of its own height to a
   filename and a MIME type.

   The rules below are the answer to that measurement. They apply to phones
   only; the desktop layout, where a caption under a thumbnail is useful and
   there is room for the toolbar, is untouched. */
/* PHONE, WHICH IS A SHAPE AND NOT ONLY A WIDTH.
   The same iPhone turned on its side is 844 points wide and 390 tall, so a
   width-only rule handed it the desktop layout: the grid began 534 points down
   a 390-point screen, and the viewer stacked a stage and a details panel into
   a space shorter than the stage alone -- the photograph rendered 410 points
   tall in a 390-point window and overflowed it. Short and not-wide is the same
   situation as narrow, and gets the same layout. */
/* The kind badge is a PHONE thing: it exists for when the caption is not on
   screen (see the comment where app.js renders it). Outside the phone layout
   it had no rule at all, so it rendered as a plain flex item BESIDE the tile's
   image -- taking thirty-odd pixels of width, squeezing the picture off the
   right edge, and showing through as a clipped "vid". Nobody saw it while
   video tiles had no posters; the first one to get a poster showed it. On
   desktop the caption under the tile already says "video", so the badge is
   simply not drawn there. */
.media-kind{display:none}

/* ================================================= the Media tab has no app bar
   (the Media redesign, 2026-09-27.) On a phone Media's own top bar -- her
   wordmark, upload, search, her face -- IS the header, so the app bar steps away on Media exactly as it does on Write
   (public/writing.css) -- and the tab bar stays, untouched. Nothing the bar
   carried is out of reach: upload is the plum button in the tray, the account
   and Appearance are behind the face, and Media is a tab root with no Back.
   The breakpoint is the Writing Room's, deliberately: 999px is the last width
   before the desktop composition (index.html) is in charge of the top of the
   screen. The status-bar inset is the body's own (shell.css). */
@media (max-width:999px){
  body:has(#view > .media) .topbar{display:none}
  body:has(#view > .media) #view{padding-top:6px}
}

@media (max-width:767px), (max-width:1023px) and (max-height:520px){
  /* THE TITLE IS THE TAB ROOT'S TITLE (the Media redesign, 2026-09-27). It was
     22px with a row of glyphs beside it, because the app bar was above it and
     the room for a heading had already been spent. The bar steps away now, so
     "Media" is the serif title a tab root is supposed to have, on its own row,
     under her wordmark. */
  .media-house{padding-top:2px;min-height:46px}
  /* SIXTEEN AT THE SIDES (Media header final): the app's 22 is for reading;
     here the width goes to the photographs. The installed app still keeps
     clear of the sensor housing in landscape (shell.css). */
  body:has(#view > .media){--edge:16px;
    padding-left:max(var(--edge), env(safe-area-inset-left, 0px));
    padding-right:max(var(--edge), env(safe-area-inset-right, 0px))}
  .media-head{display:flex;flex-direction:row;flex-wrap:nowrap;align-items:center;gap:8px;margin:2px 0 4px}
  .media-head h1{flex:1;min-width:0;font-size:32px;line-height:1.08;margin:0;
    overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .media-acts{gap:9px;margin:12px 0 0}
  .media-acts .choice{padding:0 4px;font-size:15px}
  /* Connecting a Drive is a job you finish once. It stays reachable and stops
     being a panel: one line, with its button beside it rather than beneath. */
  .media-driveline{display:flex;flex-direction:row;flex-wrap:nowrap;align-items:center;gap:9px;
    margin:0 0 8px;padding:7px 9px;border-radius:10px}
  .media-driveline .btn{width:auto}
  .media-driveline p{flex:1;min-width:0;margin:0;font-size:11.5px;line-height:1.3}
  .media-driveline .btn{flex:none;min-height:44px;padding-inline:11px;font-size:12px;white-space:nowrap}
  .media-view-nav{margin-top:10px}

  /* The trail gets a line only when it says more than "All media". The
     library's controls are glyphs in the heading row (punch list item 12). */
  .media-where{gap:7px;margin-bottom:9px}
  .media-where.top{display:none}
  .media-searchbar{margin-bottom:9px}
  .media-search{padding:0 12px}
  .media-typebar{margin-bottom:0}
  /* Directly under the tabs, whose own hairline already divides them. */
  .media-typebar .media-types{border-top:0}
  .media-count{margin:0 0 4px;font-size:12.5px;line-height:1.4}

  /* COLUMNS, COUNTED. A phone's grid size is how many across -- four (the
     default), three, two or one -- set by the Layout pill and by the pinch, so
     every tap visibly changes the grid; a minimum width only moved it at two or
     three points in a slider's whole travel. */
  .media-grid{gap:4px;
    grid-template-columns:repeat(var(--media-cols,4),minmax(0,1fr));
    padding-bottom:calc(84px + env(safe-area-inset-bottom,0px))}
  /* The bulk bar floats over the grid, so the grid has to end above it or the
     last row of photographs can never be reached -- which on a phone is the
     row somebody scrolled all that way to get to. */
  .media-library-view:has(.media-picked:not([hidden])) .media-grid{
    padding-bottom:calc(190px + env(safe-area-inset-bottom,0px))}
  .media-tile{border-radius:8px}
  /* The caption goes. Everything in it is still in the tile's accessible name
     and still in the file's own Info, so nothing is lost to a screen reader --
     what is lost is a filename printed under every photograph in a grid whose
     whole job is to show photographs. */
  .media-tile-copy{display:none}
  /* Square, because a grid of mixed aspect ratios is harder to scan. The
     VIEWER shows the whole frame; this crop is for finding, not for judging. */
  .media-visual{aspect-ratio:1/1}

  /* A small mark with a big target. The checkbox was a 34px white slab sitting
     on the subject of the photograph; it is now a 20px mark inside a 44px
     transparent target, which is the size a thumb needs and the size an eye
     does not. */
  .media-pick{top:0;left:0;width:44px;height:44px;border-radius:0;
    background:none;backdrop-filter:none}
  /* A REAL CHECKBOX THAT DOES NOT SHOUT.
     Still <input type="checkbox"> -- keyboard, VoiceOver and the browser's own
     checked semantics are untouched -- but drawn as a 17px ring instead of the
     platform's white slab. Unchecked it is an outline over a soft scrim, dark
     enough to stay visible on a pale photograph and quiet enough not to be the
     first thing the eye lands on. Checked it fills with the House accent, so
     chosen and not chosen are a color apart rather than a shape apart. */
  .media-pick input{appearance:none;-webkit-appearance:none;
    width:17px;height:17px;border-radius:50%;
    border:1.5px solid rgb(255 255 255/.92);
    background:rgb(0 0 0/.22);box-shadow:0 1px 2px rgb(0 0 0/.35)}
  .media-pick input:checked{border-color:var(--accent);background:var(--accent)}
  .media-pick input:checked::after{content:"";display:block;
    width:100%;height:100%;
    background:no-repeat center/9px 9px
      url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="3.4" stroke-linecap="round" stroke-linejoin="round"><path d="m4.8 12.4 4.6 4.6 9.8-10.4"/></svg>')}
  .media-pick input:focus-visible{outline:2px solid var(--accent);outline-offset:3px}
  .media-tile-wrap.picked .media-pick{background:none}

  /* Kind, only where it distinguishes something. */
  .media-kind{display:block;position:absolute;right:5px;bottom:5px;padding:2px 6px;border-radius:5px;
    background:color-mix(in srgb,#000 62%,transparent);color:#fff;
    font:600 9.5px/1.35 var(--f-s);letter-spacing:.02em;text-transform:uppercase;
    max-width:calc(100% - 10px);box-sizing:border-box;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

  /* PINCH TO ZOOM (item 19). The grid keeps scrolling in both directions and
     two fingers become the grid's own zoom rather than the page's; the
     script only ever claims a two-finger touch. */
  .media-grid{touch-action:pan-x pan-y}

  /* A NAME WHERE A PICTURE CANNOT SAY WHAT IT IS (item 19).
     At two columns or one there is room to read, and a document, a recording
     or a video is otherwise an anonymous square. So those tiles carry their
     title (two lines) and one line of detail over the bottom of the square,
     on a dark scrim that reads the same in light and dark. Photographs and
     artwork never do: the picture is the point, and anything laid over it is
     a defect. */
  :root[data-media-roomy]
    .media-tile-wrap:not([data-kind="photo"]):not([data-kind="artwork"]) .media-tile{position:relative}
  :root[data-media-roomy]
    .media-tile-wrap:not([data-kind="photo"]):not([data-kind="artwork"]) .media-tile-copy{
    display:block;position:absolute;left:0;right:0;bottom:0;z-index:1;
    padding:26px 10px 9px;pointer-events:none;
    background:linear-gradient(to top,rgb(0 0 0/.78),rgb(0 0 0/.58) 60%,rgb(0 0 0/0));
    color:#fff}
  :root[data-media-roomy]
    .media-tile-wrap:not([data-kind="photo"]):not([data-kind="artwork"]) .media-tile-copy b{
    display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;line-clamp:2;
    white-space:normal;overflow-wrap:anywhere;font:600 13px/1.3 var(--f-s);color:#fff}
  :root[data-media-roomy]
    .media-tile-wrap:not([data-kind="photo"]):not([data-kind="artwork"]) .media-tile-copy small{
    margin-top:2px;font-size:12px;line-height:1.3;color:rgb(255 255 255/.86)}
  /* The kind badge moves to the top corner so the caption has the bottom. */
  :root[data-media-roomy]
    .media-tile-wrap:not([data-kind="photo"]):not([data-kind="artwork"]) .media-kind{
    top:5px;bottom:auto}
}

/* SONGS A SEARCH NAMES (item 20): a short list of rows above the files, each
   one going to the song in Music, so each ends in a chevron. */
.media-songs{margin:0 0 12px}
.media-songs[hidden]{display:none}
.media-songs-head{margin:0 0 6px;color:var(--muted);font:600 11px/1.3 var(--f-s);
  letter-spacing:.04em;text-transform:uppercase}
.media-songs-list{margin:0;padding:0;list-style:none;border:1px solid var(--line);
  border-radius:12px;overflow:hidden;background:var(--raised)}
.media-songs-list li + li{border-top:1px solid var(--line)}
.media-song{display:flex;align-items:center;gap:11px;min-height:52px;padding:6px 10px 6px 7px;
  color:var(--ink);text-decoration:none}
.media-song:focus-visible{outline:2px solid var(--accent);outline-offset:-2px}
.media-song-art{flex:none;display:flex;align-items:center;justify-content:center;
  width:40px;height:40px;border-radius:7px;overflow:hidden;background:var(--tile);color:var(--muted)}
.media-song-art img{width:100%;height:100%;object-fit:cover;display:block}
.media-song-title{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
  font:600 14px/1.3 var(--f-s)}
.media-none .btn{margin-left:6px;vertical-align:middle}
/* The song's stage (bars + word, read-only) before the chevron. Narrow phones
   let the word go: the bars and the aria-label still say it. */
.msearch-stage{flex:none;font:500 12px/1.2 var(--f-s);color:var(--muted)}
@media (max-width:359px){.msearch-stage .sstage-w{display:none}}

/* Preview: only in select mode, where tapping the tile no longer opens it.
   Out of select mode the tile itself is the way in, so this would be a second
   tab stop on every one of sixty tiles for no gain. */
.media-visual{position:relative}
.media-peek{display:none}
.media-library-view.picking .media-peek{position:absolute;top:4px;right:4px;z-index:2;
  display:flex;align-items:center;justify-content:center;width:38px;height:38px;
  padding:0;border:0;border-radius:9px;cursor:pointer;color:#fff;
  background:color-mix(in srgb,#000 55%,transparent)}
.media-library-view.picking .media-peek:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.media-library-view.picking .media-tile{cursor:copy}
/* The mode is visible on the grid itself, not only on the button that started
   it: a mode nobody can see is a mode somebody will be surprised by. */
.media-library-view.picking .media-pick input{transform:scale(1.15)}

/* Select is a phone control: a mouse does not need a mode to tick a checkbox. */
@media (min-width:768px) and (min-height:521px){
  .media-selectmode{display:none}
}

/* ==========================================================================
   THE PHOTO DOCK
   ==========================================================================

   Measured on an iPhone 17e before this: the viewer carried a stretched pink
   "Add this photo" slab, a stretched Info button beside Close, a chevron
   standing in for More, and then repeated Select, Add, Download, Home and
   Trash at full size inside a 46dvh Info sheet -- five 46px rows that filled
   most of the sheet before a single fact appeared.

   Now: a quiet 44px top strip, five even 64px dock cells, and one panel above
   the dock that holds EITHER details or the secondary actions. Accent is spent
   on two things only -- the selected state, and the final Add inside the
   picker. */
.mv-top{flex:0 0 44px;display:grid;grid-template-columns:1fr auto 1fr;
  align-items:center;gap:8px;padding:0 8px}
.mv-icon{display:inline-grid;place-items:center;width:44px;height:44px;padding:0;
  border:0;border-radius:10px;background:transparent;color:#FBF6F1;cursor:pointer}
.mv-icon:hover{background:rgb(255 255 255/.1)}
.mv-icon:focus-visible{outline:2px solid #fff;outline-offset:2px}
.mv-where{position:static;left:auto;bottom:auto;transform:none;
  margin:0;padding:0;border:0;background:none;
  color:rgba(251,246,241,.82);font:500 12px/1 var(--f-s);
  font-variant-numeric:tabular-nums;text-align:center;white-space:nowrap}
.mv-picked-count{justify-self:end;padding-right:4px;color:var(--accent);
  font:500 11px/1 var(--f-s);white-space:nowrap}

.mv-dock{flex:none;display:grid;grid-template-columns:repeat(5,minmax(0,1fr));
  align-items:stretch;height:calc(64px + env(safe-area-inset-bottom,0px));
  padding:4px 6px calc(6px + env(safe-area-inset-bottom,0px));
  border-top:1px solid rgb(255 255 255/.12);background:#171016;position:relative;z-index:3}
.mv-act{display:flex;flex-direction:column;align-items:center;justify-content:center;
  gap:4px;min-width:0;min-height:44px;padding:4px 1px;border:0;border-radius:10px;
  background:transparent;color:#FBF6F1;cursor:pointer;text-decoration:none;
  font:500 11px/1.1 var(--f-s);white-space:nowrap}
.mv-act span{overflow:hidden;text-overflow:ellipsis;max-width:100%}
.mv-act:hover{background:rgb(255 255 255/.09)}
.mv-act:focus-visible{outline:2px solid #fff;outline-offset:-2px}
/* Selected and open are the only accented states, and each carries its word
   and its ARIA as well as its color. */
/* The House accent is a dusty plum made for a pale page; at 11px on a near
   black dock it goes muddy, so the active cell lifts it rather than using it
   straight. Still one accent, still only for selected and open. */
.mv-act[aria-pressed="true"],.mv-act[aria-expanded="true"]{
  color:color-mix(in srgb,var(--accent) 55%,#FBF6F1);
  background:rgb(255 255 255/.12)}
.mv-act[aria-pressed="true"] svg,.mv-act[aria-expanded="true"] svg{opacity:1}

.mv-mark{position:absolute;right:14px;top:58px;z-index:2;display:flex;
  align-items:center;gap:6px;padding:6px 10px;border-radius:20px;
  background:var(--accent);color:#fff;font:600 11px/1 var(--f-s)}
.mv-mark[hidden]{display:none}

/* The clean look: the strips fold away and the picture takes the room. */
.media-viewer.mv-bare .mv-top,.media-viewer.mv-bare .mv-dock{
  flex-basis:0;height:0;padding-block:0;opacity:0;pointer-events:none;overflow:hidden}
.media-viewer.mv-bare .media-viewer-type,.media-viewer.mv-bare .mv-mark{opacity:0}

@media (max-width:767px), (max-width:1023px) and (max-height:520px){
  .lightbox.media-viewer{padding:0}
  .media-viewer-shell{grid-template-columns:1fr;grid-template-rows:1fr;
    height:100dvh;border:0;border-radius:0}
  /* align-items:stretch is NOT redundant. The desktop rule is
     `display:grid;place-items:center`, and place-items sets align-items --
     which a column flex container reads as "shrink every child to its content
     and center it". The strips came out as a huddle of buttons in the middle
     of the screen instead of bars across it. */
  .media-viewer-stage{display:flex;flex-direction:column;align-items:stretch;
    justify-content:flex-start;padding:0;
    padding-top:env(safe-area-inset-top,0px)}

  /* Everything between the strips is the picture, whole and uncropped. */
  .media-viewer-stage > img,
  .media-viewer-stage > video,
  .media-viewer-stage > iframe,
  .media-viewer-stage > .media-stream-stage,
  .media-viewer-stage > .media-audio-view,
  .media-viewer-stage > .media-demo-visual,
  .media-viewer-stage > .lbmissing{flex:1 1 auto;min-height:0;width:100%;
    max-width:100%;max-height:none;object-fit:contain}
  .media-viewer-stage > .lbmissing{display:flex;align-items:center;
    justify-content:center;padding:24px;text-align:center}
  .media-viewer-stage > .media-viewer-where{display:none}
  .media-viewer-type{left:10px;bottom:calc(74px + env(safe-area-inset-bottom,0px))}

  /* One panel, above the dock, never covering the control that opened it. */
  .media-viewer-info{position:absolute;left:0;right:0;z-index:2;
    bottom:calc(64px + env(safe-area-inset-bottom,0px));
    max-height:52%;overflow:auto;
    padding:7px 18px 18px;border-top:1px solid rgb(255 255 255/.12);
    border-radius:19px 19px 0 0;box-shadow:0 -12px 32px rgb(0 0 0/.34)}
  .media-viewer-info[hidden]{display:none}
  .mv-grip{width:32px;height:4px;margin:0 auto 4px;border-radius:5px;
    background:rgb(255 255 255/.2)}
  .media-viewer-info h2{margin:0 0 7px;font-size:23px}
}

.mv-sheethead{display:flex;align-items:center;justify-content:space-between;
  gap:12px;min-height:44px}
.mv-sheethead .eyebrow{margin:0}
/* A sheet's close is a small control, not the loudest thing in the panel. It
   still carries a 44px target -- the padding is what shrinks, not the box. */
.mv-sheethead .mv-icon{flex:none;margin-right:-6px}
/* THE PANEL SPEAKS THE DOCK'S LANGUAGE.
   These were `.btn`s -- light-surface buttons, on a panel that is #21171D. So
   Edit title, Move to folder and Move to Trash rendered as white slabs with
   white text inside them, unreadable, three times the weight of anything in
   the dock they sat under. They are rows now: a glyph, a label, a hover, and
   nothing else. */
.mv-row{display:flex;align-items:center;gap:13px;width:100%;min-height:48px;
  padding:0 10px;border:0;border-radius:10px;background:transparent;
  color:#FBF6F1;font:500 13.5px/1.3 var(--f-s);text-align:left;cursor:pointer}
.mv-row > span{flex:1;min-width:0}
.mv-row svg{flex:none;opacity:.72}
.mv-row:hover{background:rgb(255 255 255/.07)}
.mv-row:focus-visible{outline:2px solid #FBF6F1;outline-offset:-2px}

/* ---------------------------------------------------------------- desktop
   The same five actions and the same glyphs, as one quiet centered toolbar,
   with details on a rail that is CLOSED until asked for -- the panel used to
   be permanent, which is a third of a wide screen spent on a filename. */
@media (min-width:768px) and (min-height:521px){
  .media-viewer-shell{grid-template-columns:minmax(0,1fr)}
  .media-viewer.mv-info-open .media-viewer-shell{
    grid-template-columns:minmax(0,1fr) 300px}
  .media-viewer-stage{display:flex;flex-direction:column;padding:0}
  .media-viewer-stage > img,
  .media-viewer-stage > video,
  .media-viewer-stage > iframe,
  .media-viewer-stage > .media-stream-stage,
  .media-viewer-stage > .media-audio-view,
  .media-viewer-stage > .media-demo-visual,
  .media-viewer-stage > .lbmissing{flex:1 1 auto;min-height:0;width:100%;
    max-width:100%;max-height:none;object-fit:contain;padding:14px}
  .mv-dock{height:52px;padding:5px 8px;display:flex;justify-content:center;gap:7px}
  .mv-act{flex-direction:row;gap:7px;padding:6px 13px;font-size:12px}
  .media-viewer-info{position:relative;overflow-y:auto;padding:22px 20px 26px}
  .media-viewer-info[hidden]{display:none}
  .mv-grip{display:none}
  .media-viewer-type{bottom:62px}
}
/* Home background is a preference with two states, so it is drawn as one. */
.mvswitch{display:inline-flex;align-items:center;gap:9px;min-height:44px;
  padding:0 13px;border:1px solid var(--line);border-radius:11px;
  background:var(--raised);color:inherit;cursor:pointer;font:500 13px/1 var(--f-s)}
.mvswitch i{width:34px;height:20px;border-radius:999px;background:var(--line);
  position:relative;flex:none}
.mvswitch i::after{content:"";position:absolute;top:2px;left:2px;width:16px;height:16px;
  border-radius:50%;background:var(--ground)}
.mvswitch[aria-checked="true"] i{background:var(--accent)}
.mvswitch[aria-checked="true"] i::after{left:16px}
.mvswitch:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
@media (prefers-reduced-motion:no-preference){
  .mvswitch i,.mvswitch i::after{transition:background .15s ease,left .15s ease}
}

/* The shared destination picker. */
.addto-group{margin:0 0 14px}
.addto-group-head{margin:0 0 7px;color:var(--muted);font:600 10.5px/1 var(--f-s);
  letter-spacing:.09em;text-transform:uppercase}
.addto-one{display:flex;align-items:flex-start;gap:11px;width:100%;min-height:48px;
  margin:0 0 4px;padding:9px 12px;border:1px solid transparent;border-radius:10px;
  background:var(--raised);cursor:pointer;text-align:left}
.addto-one.on{border-color:var(--accent);background:var(--tint)}
.addto-one input{margin:2px 0 0;accent-color:var(--accent);width:19px;height:19px;flex:none}
.addto-one-copy{flex:1;min-width:0}
.addto-one-copy b{display:block;font:600 14px/1.3 var(--f-s)}
.addto-one-copy small{display:block;margin-top:2px;color:var(--muted);font:400 11.5px/1.35 var(--f-s)}
.addto-make{margin:4px 0 12px}
.addto-make summary{min-height:44px;display:flex;align-items:center;cursor:pointer;
  font:500 13px/1 var(--f-s)}
.addto-make-act{display:flex;flex-wrap:wrap;gap:8px;margin-top:9px}
.mv-more-list{display:flex;flex-direction:column;gap:8px;margin:4px 0 12px}
.mv-more-list .btn{width:100%;justify-content:flex-start;min-height:48px}

/* The details panel is dark at every width, so the controls inside it are too.
   The switch and the sheet bar were built from the light surface tokens and
   came out as white slabs with invisible labels on the dark sheet. */
.media-viewer-info .mvswitch,.mv-sheethead .btn{background:rgba(251,246,241,.07);
  border-color:rgba(251,246,241,.22);color:#FBF6F1}
.media-viewer-info .mvswitch i{background:rgba(251,246,241,.26)}
.media-viewer-info .mvswitch i::after{background:#21171D}
.media-viewer-info .mvswitch[aria-checked="true"] i{background:#FBF6F1}
.media-viewer-info .mvswitch[aria-checked="true"] i::after{background:#2A1A22}
.media-viewer-info .mvswitch:focus-visible,.mv-sheethead .btn:focus-visible{
  outline:2px solid #FBF6F1;outline-offset:2px}
.media-viewer-info .media-viewer-chips b{display:block;margin:9px 0 5px;
  color:rgba(251,246,241,.62);font:600 10px/1 var(--f-s);letter-spacing:.08em;
  text-transform:uppercase}

/* A heading focused by script is not a heading somebody tabbed to, so it does
   not draw the ring. Keyboard focus still shows: :focus-visible is untouched. */
.media-viewer-info h2:focus:not(:focus-visible){outline:none}

/* A restriction we actually hold, said before the actions rather than under
   them. Amber, not red: it is a limit on use, not a rejection of the file. */
.media-viewer-limit{display:flex;gap:9px;align-items:flex-start;margin:12px 0 0;
  padding:10px 12px;border:1px solid var(--warn,rgba(214,158,46,.55));border-radius:10px;
  background:rgba(214,158,46,.13);color:#FBF6F1;font:400 12px/1.45 var(--f-s)}
.media-viewer-limit svg{flex:none;margin-top:1px}

/* The viewer takes focus itself when it opens, so a screen reader announces
   the dialog -- but a container is not a control and must not wear a control's
   focus ring. Focus moved by keyboard still shows on every button inside it. */
.lightbox.media-viewer:focus{outline:none}

/* Filling is asked for, never assumed: the default is the whole photograph and
   this is what one press or one double-tap changes it to. */
.media-viewer.mv-fill .lbimg{object-fit:cover}
.mv-lead{display:flex;align-items:center;gap:2px}
.mv-icon[aria-pressed="true"]{color:var(--accent);background:rgb(255 255 255/.1)}
/* A RAW + JPEG pair: the photo's two files, each downloadable (src/pairs.js). */
.mv-file-list li{justify-content:space-between}.mv-file-list li > span{display:grid;gap:2px;min-width:0}.mv-file-list li b{font-weight:500;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.mv-file-list li small{color:rgba(251,246,241,.48);font:500 9.5px/1.2 var(--f-s)}.mv-file-dl{flex:none;display:inline-flex;align-items:center;min-height:32px;padding:0 12px;border:1px solid rgba(251,246,241,.28);border-radius:999px;background:transparent;color:#FBF6F1;font:500 11px/1 var(--f-s);text-decoration:none;white-space:nowrap}.mv-file-dl:hover,.mv-file-dl:focus-visible{border-color:rgba(251,246,241,.6);background:rgba(251,246,241,.08)}[data-mv-files] .mv-row{margin-top:10px}
/* The one viewer (public/viewer.js): PhotoSwipe fills the stage, not the window, and
   stays below the chrome and any sheet opened over it (the overlay stack owns z-order). */
@media (min-width:768px){.media-viewer-stage:has(> .mv-pswp-host){padding:0}}.mv-pswp-host{position:relative;flex:1 1 auto;align-self:stretch;justify-self:stretch;width:100%;height:100%;min-width:0;min-height:0}.mv-pswp-host .pswp{position:absolute;--pswp-root-z-index:auto;z-index:auto;--pswp-bg:#120D10}.mv-pswp-empty{width:100%;height:100%}.pswp img{-webkit-touch-callout:none;-webkit-user-drag:none;user-select:none}
/* A long press in the viewer is the photo's menu, never a text selection. Fields keep theirs. */
.lightbox.media-viewer{-webkit-user-select:none;user-select:none;-webkit-touch-callout:none}.lightbox.media-viewer input,.lightbox.media-viewer textarea,.lightbox.media-viewer [contenteditable="true"]{-webkit-user-select:text;user-select:text}
/* A video slide (viewer plan M6): the picture letterboxed in the stage, and a
   bar of its own controls along the bottom. Every control is a 40px target. */
.hqv{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;color:#FBF6F1}
.hqv-stage{position:absolute;inset:0;display:flex;align-items:center;justify-content:center}
.hqv-stage video,.hqv-stage .hqv-poster,.hqv-stage iframe{width:100%;height:100%;object-fit:contain;border:0;display:block;background:transparent}
.hqv-big{position:absolute;left:50%;top:50%;width:72px;height:72px;margin:-36px 0 0 -36px;border-radius:50%;
  border:0;display:grid;place-items:center;background:rgba(18,11,16,.62);color:#FBF6F1;cursor:pointer;
  -webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px)}
.hqv-big svg{width:34px;height:34px;margin-left:4px}
.hqv-big[hidden],.hqv-bar[hidden],.hqv-note[hidden]{display:none}
.hqv-note{position:absolute;left:16px;right:16px;bottom:24px;margin:0;text-align:center;
  font:400 14px/1.45 var(--f-s,system-ui);color:#DACFD6}
.hqv-bar{position:absolute;left:10px;right:10px;bottom:10px;display:flex;align-items:center;gap:2px;
  padding:4px 6px;border-radius:14px;background:rgba(18,11,16,.72);
  -webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);transition:opacity .18s ease}
.hqv-bar button{flex:0 0 auto;width:40px;height:40px;border:0;border-radius:10px;background:none;
  color:inherit;display:grid;place-items:center;cursor:pointer;padding:0}
.hqv-bar button:hover{background:rgba(251,246,241,.1)}
.hqv-bar button:focus-visible,.hqv-track:focus-visible,.hqv-big:focus-visible{outline:2px solid #FBF6F1;outline-offset:1px}
.hqv-track{position:relative;flex:1 1 auto;min-width:60px;height:40px;cursor:pointer;touch-action:none;border-radius:8px}
.hqv-track::before,.hqv-fill{content:"";position:absolute;left:0;top:50%;height:4px;margin-top:-2px;border-radius:2px}
.hqv-track::before{right:0;background:rgba(251,246,241,.25)}
.hqv-fill{width:0;background:#FBF6F1}
.hqv-knob{position:absolute;top:50%;left:0;width:14px;height:14px;margin:-7px 0 0 -7px;border-radius:50%;
  background:#FBF6F1;box-shadow:0 1px 4px rgba(0,0,0,.4)}
.hqv-time{flex:0 0 auto;display:grid;gap:3px;padding:0 6px;text-align:right;
  font:500 11px/1 ui-monospace,Menlo,monospace;font-variant-numeric:tabular-nums;color:#DACFD6;white-space:nowrap}
.hqv-time b{font-weight:500;color:#FBF6F1}
.hqv-time small{font-size:10px}
/* Tapping the picture hides the chrome; the video's own bar goes with it. */
.media-viewer.mv-bare .hqv-bar{opacity:0;pointer-events:none}

/* A document tile (Phase 3 punch list, item 11; Jay's build-32 report): a
   designed page -- its kind on a colored band, its title -- with its real
   first page laid over it once there is one (public/app/media-docs.js). The
   page is always underneath, so a picture still loading or one that fails
   shows the page, never black and never a glyph floating in nothing. The
   band's colors are the palette's own, so every look and dark mode keep them
   readable. */
.media-doclook{position:relative;display:block;width:72%;height:84%}
.media-doclook > .media-docpaper{width:100%;height:100%}
.media-docpage{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;object-position:top;
  border-radius:3px;opacity:0}
.media-docpage.on{opacity:1}
@media (prefers-reduced-motion:no-preference){.media-docpage{transition:opacity .22s ease}}
.media-docpaper{--doc:var(--muted);position:relative;display:flex;flex-direction:column;align-items:stretch;
  width:72%;height:84%;box-sizing:border-box;overflow:hidden;
  background:var(--raised);border-radius:3px;box-shadow:0 1px 3px rgba(0,0,0,.16),0 6px 16px rgba(0,0,0,.07);
  background-image:repeating-linear-gradient(180deg,transparent 0 calc(1.35em - 1px),var(--line) calc(1.35em - 1px) 1.35em);
  background-position:0 88%;background-repeat:no-repeat;background-size:100% 34%}
.media-docpaper[data-doctype="pdf"]{--doc:var(--mauve)}
.media-docpaper[data-doctype="word"],.media-docpaper[data-doctype="pages"]{--doc:var(--blue)}
.media-docpaper[data-doctype="spreadsheet"]{--doc:var(--ic-sage)}
.media-docpaper[data-doctype="slides"]{--doc:var(--ic-plum)}
/* The kind reads from the right: the tile's select ring sits top left. */
.media-docband{display:block;padding:7% 10%;background:var(--doc);color:var(--raised);text-align:right;
  font:700 clamp(8px,2.1vw,11px)/1 var(--f-s);font-style:normal;letter-spacing:.09em}
.media-docpaper b{margin:11% 10% 0;font:600 clamp(9px,2.6vw,13px)/1.3 var(--f-s);color:var(--ink);overflow:hidden;
  display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow-wrap:break-word;
  -webkit-hyphens:auto;hyphens:auto}

/* A DOCUMENT IN THE VIEWER: the same page, larger, and what opens it -- iOS's
   own preview in the app, PDF.js's pages on the web, Download otherwise. */
.media-viewer-stage > .media-viewer-doc,
.media-viewer-stage > .media-viewer-pdf{flex:1 1 auto;min-height:0;width:100%}
.media-viewer-doc{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:18px;
  padding:24px 16px;box-sizing:border-box}
.media-viewer-docopen{display:block;padding:0;border:0;border-radius:4px;background:none;cursor:pointer}
.media-viewer-docopen:focus-visible,.media-viewer-docgo:focus-visible{outline:2px solid #FBF6F1;outline-offset:3px}
.media-viewer-docpage.media-docpaper{width:auto;height:min(54vh,460px);aspect-ratio:8.5/11;
  box-shadow:0 2px 6px rgba(0,0,0,.4),0 18px 44px rgba(0,0,0,.45)}
.media-viewer-docpage .media-docband{padding:6% 9%;font-size:13px}
.media-viewer-docpage b{margin:10% 9% 0;font-size:17px;-webkit-line-clamp:6;text-align:left}
/* The viewer is dark and the page sits inside a button: its ink is the
   page's own, not whatever the button or the stage hands down. */
.media-viewer-docpage.media-docpaper{background-color:#FFFCF7;color:#2A1F26}
.media-viewer-docpage.media-docpaper b{color:#2A1F26;-webkit-text-fill-color:#2A1F26;opacity:1}
.media-viewer-docgo{display:inline-flex;align-items:center;gap:8px;min-height:44px;padding:0 20px;
  border:1px solid rgb(255 255 255/.22);border-radius:999px;background:rgb(255 255 255/.08);
  color:#FBF6F1;font:600 14px/1 var(--f-s);text-decoration:none;cursor:pointer}
.media-viewer-docgo:hover{background:rgb(255 255 255/.14)}
.media-viewer-docsaid{margin:0;max-width:34ch;color:#DACFD6;font:400 14px/1.45 var(--f-s);text-align:center}
.media-viewer-pdf{display:flex;flex-direction:column;align-items:center;gap:12px;padding:12px;box-sizing:border-box;
  overflow:auto;overscroll-behavior:contain;-webkit-overflow-scrolling:touch}
.media-viewer-pdf > .media-viewer-doc{flex:1 1 auto}
.media-viewer-pdfpage{flex:none;width:min(100%,900px);background:#FFFFFF;border-radius:2px;
  box-shadow:0 2px 10px rgba(0,0,0,.45)}
.media-viewer-pdfpage canvas{display:block;width:100%;height:auto;border-radius:2px}
/* With the Drive panel open from Add media, the one-line reminder above the
   tabs would be a second Connect button for the same act. */
#media-drive-panel:not([hidden]) ~ .media-driveline.needs{display:none}

/* THE ARROWS OVER A PHOTOGRAPH THAT SWIPES (Jay, build 10).
   Swiping is the way through a gallery now, and two chevrons on the picture
   were clutter that also turned up in every screenshot. Hidden from the eye
   and from the finger -- an invisible 46px button at each edge would swallow
   the taps meant for the photo -- but kept for VoiceOver and the keyboard,
   and shown again while the keyboard is on one. */
.media-viewer-stage .lbnav.mv-swipenav:not(:focus-visible){
  opacity:0;pointer-events:none;clip-path:inset(50%)}

/* A picture whose display copy would not load shows its thumbnail in the
   slide, filling it the way the photo would, never an error message
   (public/viewer.js contentErrorElement). */
.pswp__error-msg-container{position:relative}
.pswp__error-msg-container .hqv-fallback{position:absolute;inset:0;width:100%;height:100%;
  object-fit:contain;display:block}

/* ==========================================================================
   A FILE'S QUESTION AND ITS ANSWERS (punch list item 14)
   ==========================================================================

   The Housekeeper's filing chips, wherever a question is asked: under the
   upload drawer's receipt and on Media's Review tab. From a real Dropbox
   upload the chips were squeezed into the narrow second column of a
   two-column row until each drew one letter per line. Here the row stacks
   (the file and its question, then the answers), every grid child may shrink
   below its content (min-width:0), and each chip keeps its own width
   (flex:0 0 auto) and wraps onto the next line as a whole. A chip wider than
   the row breaks between words, never between letters. 44pt targets. */
.filing-host [data-hk-row]{display:grid;grid-template-columns:minmax(0,1fr);row-gap:10px}
.filing-host [data-hk-row] > *{min-width:0}
.filing-host [data-hk-row] .rt{display:flex;flex-direction:row;flex-wrap:wrap;
  justify-content:flex-start;align-items:center;gap:8px;min-width:0;writing-mode:horizontal-tb}
.filing-host [data-hk-row] .rt > *{flex:0 0 auto;width:auto;min-width:44px;min-height:44px;
  max-width:100%;margin:0;white-space:normal;overflow-wrap:break-word;word-break:normal;text-align:left}
.filing-host .hksongs{display:flex;flex-wrap:wrap;gap:8px;margin:8px 0 0}
.filing-host .hksongs > *{flex:0 0 auto;min-height:44px;max-width:100%}
.filing-host .hkmore > summary{min-height:44px}
.filing-later{margin:10px 0 0}
.media-needs-home:empty{display:none}
.media-needs-home{margin:0 0 16px}

/* ======================================================================
   REVIEW, AS A CARD QUEUE (Housekeeper intake v2, public/app/review.js)
   One card at a time on a dark card tinted by the House's own accent, never
   a stock purple; the photograph takes the card's width. Actions sit fixed
   at the bottom where a thumb is; the next card waits underneath.
   ====================================================================== */
.rvq{position:relative;max-width:560px;margin:0 auto;padding:0 0 calc(92px + env(safe-area-inset-bottom))}
/* The card is dark in every look (Jay's approved mockup: "dark cards"),
   tinted by the House's own accent -- a surface a photograph is judged on,
   like the Media viewer. Its palette lives here and nowhere else. */
.rvq-card{--rv-card:color-mix(in srgb,var(--accent) 16%,#1A1114);--rv-on:#FAF1F4;
  --rv-soft:rgba(250,241,244,.74);--rv-faint:rgba(250,241,244,.56);--rv-chip:rgba(250,241,244,.1);
  --rv-chip-line:rgba(250,241,244,.22);--rv-pick:color-mix(in srgb,var(--accent) 38%,#F6D9E2);
  --rv-onpick:#1A1114}
.rvq-head{display:flex;align-items:center;justify-content:space-between;gap:12px;min-height:44px;margin:4px 0 6px;
  /* Review opens scrolled to this header; in the installed app it stops
     below the status bar, not under the clock (as app-shell.css does). */
  scroll-margin-top:calc(env(safe-area-inset-top, 0px) + 12px)}
.rvq-count{margin:0;color:var(--muted);font:500 15px/1.2 var(--f-s)}
.rvq-count b{color:var(--ink);font:400 26px/1 var(--f-d);margin-right:4px;font-variant-numeric:tabular-nums}
.rvq-undo{display:inline-flex;align-items:center;gap:6px;min-height:44px;padding:0 14px;border:1px solid var(--line);
  border-radius:999px;background:var(--raised);color:var(--ink);font:500 14px/1 var(--f-s);cursor:pointer}
.rvq-undo[disabled]{opacity:.45;cursor:default}
.rvq-undo:focus-visible,.rvq-filter:focus-visible,.rvq-tag:focus-visible,.rvq-row:focus-visible,
.rvq-frow:focus-visible{outline:2px solid var(--focus);outline-offset:2px}
.rvq-filters{display:flex;gap:8px;margin:0 0 12px;overflow-x:auto;scrollbar-width:none}
.rvq-filters::-webkit-scrollbar{display:none}
.rvq-filter{display:inline-flex;align-items:center;gap:4px;flex:none;min-height:36px;padding:0 10px;border:1px solid var(--line);
  border-radius:999px;background:var(--raised);color:var(--soft);font:500 13px/1 var(--f-s);cursor:pointer}
.rvq-filter.on{border-color:var(--ink);color:var(--ink)}
.rvq-stage{position:relative;display:grid}
.rvq-stage > .rvq-card{grid-area:1/1}
.rvq-card{position:relative;z-index:2;overflow:hidden;border-radius:22px;background:var(--rv-card);color:var(--rv-on);
  box-shadow:0 18px 40px rgb(0 0 0/.22);transform-origin:50% 100%}
.rvq-card.under{z-index:1;transform:translateY(10px) scale(.96);opacity:.55;pointer-events:none}
.rvq-card.rvq-ghost{min-height:62vh;opacity:.6}
/* The photograph as wide as the card, never letterboxed: a tall frame that
   would push the choices away is cropped top and bottom to fit, not given
   black bars at its sides. */
.rvq-pic{position:relative;display:flex;align-items:center;justify-content:center;
  min-height:180px;background:#0E0A0B}
.rvq-pic img{display:block;width:100%;height:auto;min-height:180px;max-height:min(58vh,560px);object-fit:cover}
.rvq-glyph{color:var(--rv-faint)}
.rvq-kind{position:absolute;left:12px;top:12px;padding:5px 9px;border-radius:999px;background:rgba(0,0,0,.55);
  color:#fff;font:600 11px/1 var(--f-s);letter-spacing:.06em;text-transform:uppercase}
.rvq-body{padding:14px 16px 16px}
.rvq-name{display:flex;flex-wrap:wrap;align-items:baseline;gap:4px 8px;margin:0;font:400 15px/1.35 var(--f-s);word-break:break-word}
.rvq-name b{font-weight:600;color:var(--rv-on)}
.rvq-was{color:var(--rv-faint);text-decoration:line-through;text-decoration-color:var(--rv-chip-line)}
.rvq-arrow{color:var(--rv-faint)}
.rvq-why{margin:6px 0 0;color:var(--rv-soft);font:400 14px/1.4 var(--f-s)}
/* One row each, sliding sideways, so the whole card -- photograph, tags,
   folders -- fits between the filters and the actions without scrolling.
   The row ends as it starts, 16px in from the card's edge: WebKit leaves a
   scrolling flex row's end padding out, so the last chip stopped cut in half
   against the edge. The spacer is the end padding (8px + the 8px gap), and
   a flick comes to rest on a chip's edge. Each end fades over exactly its
   16px of padding: a row at rest or scrolled to its end shows every chip it
   ends on crisp, and a chip that runs on past the edge melts into it rather
   than stopping on a hard cut. */
.rvq-tags,.rvq-chips{display:flex;flex-wrap:nowrap;gap:8px;margin:10px -16px 0;padding:0 0 0 16px;
  overflow-x:auto;scrollbar-width:none;-webkit-overflow-scrolling:touch;
  scroll-snap-type:x proximity;scroll-padding-inline:16px;
  -webkit-mask-image:linear-gradient(to right,transparent,#000 16px,#000 calc(100% - 16px),transparent);
  mask-image:linear-gradient(to right,transparent,#000 16px,#000 calc(100% - 16px),transparent)}
.rvq-tags::after,.rvq-chips::after{content:"";flex:0 0 8px}
.rvq-tags::-webkit-scrollbar,.rvq-chips::-webkit-scrollbar{display:none}
.rvq-tag,.rvq-chips .choice{flex:none;scroll-snap-align:start}
/* The folder or song a card goes to is the app's one pill, .choice (audit 2.13,
   Round R9), in the dark card's own ink: the card hands it these tokens. */
.rvq-chips{--raised:var(--rv-chip);--firm:var(--rv-chip-line);--soft:var(--rv-on);--faint:var(--rv-faint);
  --accent:var(--rv-pick);--onacc:var(--rv-onpick);--focus:var(--rv-on)}
.rvq-tag{min-height:32px;padding:0 11px;border:1px solid var(--rv-chip-line);border-radius:999px;background:transparent;
  color:var(--rv-faint);font:500 13px/1 var(--f-s);cursor:pointer}
.rvq-tag[aria-pressed="true"]{background:var(--rv-chip);color:var(--rv-on);border-color:transparent}
.rvq-folderline{display:flex;align-items:center;justify-content:space-between;gap:10px;margin:8px 0 0}
.rvq-label{margin:0;min-width:0;color:var(--rv-faint);font:500 12px/1.3 var(--f-s);letter-spacing:.04em;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.rvq-all{display:inline-flex;align-items:center;gap:2px;flex:none;min-height:44px;margin-right:-8px;padding:0 8px;border:0;
  background:none;color:var(--rv-on);font:600 14px/1 var(--f-s);cursor:pointer}
.rvq-all:focus-visible{outline:2px solid var(--rv-on);outline-offset:-2px;border-radius:10px}
.rvq-label b{color:var(--rv-soft);font-weight:600}
.rvq-acts{position:fixed;left:0;right:0;bottom:0;z-index:41;display:grid;grid-template-columns:1fr 2fr;gap:10px;
  padding:12px max(16px,env(safe-area-inset-left)) calc(12px + env(safe-area-inset-bottom));
  background:var(--chrome);border-top:1px solid var(--line);-webkit-backdrop-filter:blur(14px);backdrop-filter:blur(14px)}
/* Above the five tabs wherever they are drawn (under 900px), as the Media
   bulk bar is: a Confirm under the tab bar is visible and unpressable. */
@media(max-width:899px){
  .rvq{padding-bottom:calc(92px + 58px + env(safe-area-inset-bottom))}
  /* The photograph gets everything the rest of the card and the bars do not. */
  .rvq-pic img{max-height:max(200px,calc(100dvh - 430px - env(safe-area-inset-bottom,0px) - env(safe-area-inset-top,0px)))}
  /* A card with a row of tags gives the photograph that row's height back. */
  .rvq-card:has(.rvq-tags) .rvq-pic img{max-height:max(180px,calc(100dvh - 486px - env(safe-area-inset-bottom,0px) - env(safe-area-inset-top,0px)))}
  .rvq-acts{bottom:calc(58px + env(safe-area-inset-bottom,0px));padding-bottom:12px}
}
@media(min-width:700px){.rvq-acts{left:50%;right:auto;width:560px;transform:translateX(-50%);border:1px solid var(--line);
  border-radius:20px 20px 0 0}}
.rvq-acts .btn{min-height:52px;font-size:16px}
.rvq-acts .rvq-ok[disabled]{opacity:.42;cursor:default}
@media(prefers-reduced-motion:no-preference){
  .rvq-card{transition:transform .18s cubic-bezier(.2,.7,.2,1),opacity .18s ease}
  .rvq-card.out-ok{transform:translateX(-112%) rotate(-5deg);opacity:0}
  .rvq-card.out-skip{transform:translateY(40px) scale(.94);opacity:0}
}
/* The card that was just answered, leaving: a copy over the page that no
   tap can land on, so the next card is already the one under her thumb. */
.rvq-card.rvq-leaving{position:absolute;z-index:42;margin:0;pointer-events:none}
/* The finish: a reward, not a dead end. */
.rvq-done{display:flex;flex-direction:column;align-items:center;padding:28px 0 8px;text-align:center}
.rvq-mark{width:180px;height:180px;filter:drop-shadow(0 16px 30px rgb(0 0 0/.25))}
@media(prefers-reduced-motion:no-preference){
  .rvq-mark{animation:rvq-pop .5s cubic-bezier(.2,1.4,.4,1) both}
  .rvq-confetti{animation:rvq-drift 1.2s ease-out both;transform-origin:90px 90px}
}
@keyframes rvq-pop{0%{transform:scale(.55);opacity:0}70%{transform:scale(1.05);opacity:1}100%{transform:scale(1)}}
@keyframes rvq-drift{0%{transform:scale(.7);opacity:0}100%{transform:scale(1);opacity:1}}
.rvq-done h2{margin:18px 0 4px;color:var(--ink);font:400 30px/1.1 var(--f-d)}
.rvq-done h2:focus{outline:none}
.rvq-done-count{margin:0 0 22px;color:var(--muted);font:400 15px/1.4 var(--f-s)}
.rvq-next{display:grid;gap:10px;width:100%}
.rvq-row{display:flex;align-items:center;justify-content:space-between;gap:12px;width:100%;min-height:64px;padding:12px 16px;
  border:1px solid var(--line);border-radius:16px;background:var(--raised);color:var(--ink);text-align:left;cursor:pointer}
.rvq-row span:first-child{display:flex;flex-direction:column;gap:3px}
.rvq-row b{font:600 16px/1.2 var(--f-s)}
.rvq-row small{color:var(--muted);font:400 13px/1.3 var(--f-s)}
.rvq-row.primary{background:var(--cta);border-color:var(--cta);color:var(--oncta)}
.rvq-row.primary small{color:var(--oncta);opacity:.8}
.rvq-row[disabled]{opacity:.5;cursor:default}
.rvq-other{width:100%;margin-top:26px;text-align:left}
/* The "All folders" sheet. */
.rvq-sheet .sheetpanel{max-height:86vh}
.rvq-find{margin:6px 0 10px}
.rvq-folders-all{display:grid;gap:2px}
.rvq-frow{display:flex;align-items:center;gap:12px;width:100%;min-height:52px;padding:10px 12px;border:0;border-radius:12px;
  background:none;color:var(--ink);text-align:left;cursor:pointer}
.rvq-frow:hover,.rvq-frow:active{background:var(--sunk)}
.rvq-frow.on{background:var(--tint)}
.rvq-frow > svg{flex:none;color:var(--muted)}
.rvq-fname{display:flex;flex-direction:column;flex:1;min-width:0;gap:2px}
.rvq-fname b{font:500 16px/1.2 var(--f-s);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.rvq-fname small{color:var(--muted);font:400 12px/1.3 var(--f-s);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.rvq-fsug{flex:none;padding:3px 8px;border-radius:999px;background:var(--tint);color:var(--accent);font:600 11px/1 var(--f-s);font-style:normal}
.rvq-new b{color:var(--accent)}
.rvq-newform{display:flex;gap:8px;padding:4px 12px 10px}
.rvq-newform[hidden]{display:none}
.rvq-newform .in{flex:1;min-width:0}
/* The quiet summary after an upload, in the drawer and under Media's header. */
.intake-says{display:flex;align-items:center;justify-content:space-between;gap:12px;margin:10px 0 0;padding:12px 14px;
  border:1px solid var(--line);border-radius:14px;background:var(--raised);color:var(--ink);font:400 14px/1.4 var(--f-s)}
.intake-says .btn{flex:none}
/* The Housekeeper's one-time offers, under the folder list (public/app/tidy.js). */
.mtidy{margin:14px 0 4px;padding-top:12px;border-top:1px solid var(--line)}
.mtidy .eyebrow{margin:0 0 6px}
.mtidy-row{display:flex;align-items:center;justify-content:space-between;gap:10px;width:100%;min-height:56px;padding:10px 12px;
  border:0;border-radius:12px;background:none;color:var(--ink);text-align:left;cursor:pointer}
.mtidy-row:hover,.mtidy-row:active{background:var(--sunk)}
.mtidy-row:focus-visible{outline:2px solid var(--focus);outline-offset:-2px}
.mtidy-row > span:first-child{display:flex;flex-direction:column;gap:3px;min-width:0}
.mtidy-row b{font:500 15px/1.25 var(--f-s)}
.mtidy-row small{color:var(--muted);font:400 13px/1.35 var(--f-s)}
.mtidy-row[aria-busy="true"]{cursor:progress}
.mtidy-item{display:flex;align-items:center}
.mtidy-item .mtidy-row{flex:1;min-width:0}
.upeach{margin:12px 0 0}
.upeach > summary{min-height:44px;display:flex;align-items:center;justify-content:space-between;gap:8px;list-style:none;
  color:var(--muted);font:500 14px/1.3 var(--f-s);cursor:pointer}
.upeach > summary::-webkit-details-marker{display:none}
.upeach > summary svg{flex:none;transition:transform .15s ease}
.upeach[open] > summary svg{transform:rotate(90deg)}
/* Rapid-fire taps: no double-tap-to-zoom wait on any Review control, so a
   second tap a moment after the first is a tap, never swallowed. */
.rvq button,.rvq-acts button,.rvq-sheet button{touch-action:manipulation}

/* A release card's amber line: the date has passed (app/release-review.js). */
.rvq-card .rvq-warn{color:var(--warn,#E8B04A);font-weight:600}

/* The Approved mark (R13) on a tile and on the file in the viewer. */
/* Bottom left: the top left is the Select circle's. */
.media-approved{position:absolute;left:5px;bottom:5px;z-index:1}
.mv-approved{position:absolute;left:14px;top:58px;z-index:2;padding:6px 10px 6px 8px;font-size:11px}
.media-collection-card.handoff .media-collection-covers i{color:var(--good)}
