/* ---------- THE LORE LOUNGE CAMERA ----------
   M-25 (Mark, 2026-08-24: "lable this Lore Lounge Camera  its for the cellar
   and any where else we need this set up"). The camera is one machine that
   mounts wherever it is needed, so its look cannot live in a room's sheet.
   These rules were in cellar.css, which made the camera the Cellar's by
   construction, the same claim the old CELLAR CAMERA title made.

   MOVED, NEVER REWRITTEN. Every rule below is the rule that shipped, in the
   order it shipped in, so the Cellar's surface is the same surface and the
   eyes shots (tools/cellar/eyes.mjs) prove it pixel for pixel. A lift that
   improved something on the way would be a lift nobody could check.

   THE ORDER IS LOAD-BEARING IN ONE PLACE and it is preserved: `.imgad.imgad-
   wide` stands above the base `.imgad`, exactly as it did, and its own
   comment says why.

   ONE RESIDUE, named rather than left to be found. The chips wear
   `.cellar-pill-13`, which is declared in cellar.css and is genuinely shared
   with the Lab and the Capture window, so it could not come across with a
   camera lift. It is a class named for one room that a house machine needs,
   and it wants a rename in a pass that can touch those files too.

   Note there are TWO things called the camera in this app: the older scene
   modal owns `.cam-scrim`, `.cam`, `.cam-head`, `.cam-ta`, `.cam-opt` and
   `.cam-lever` in scene.css. No selector here collides with one of those. */

/* THE THREE WINDOWS (Mark, 2026-08-20). Equal thirds of the panel, square,
   always three — the painter's hard cap made visible. They keep their size
   whether they hold a face or nothing, because a row that reflows when you
   fill it is a row that never looks like the same row twice.

   THE CLASSES ARE cam-* NOW, because the windows are the CAMERA's and the
   camera is standard (rooms/camera.js, 2026-08-23). They are drawn in the
   Cellar's left rail and in its backstage modal from one place, and Novel
   Forge stands on the same ones when its lane comes. The rules below did not
   change when they were renamed; only the prefix did. */
/* The cap is what lets ONE shape serve two widths. In the left rail the
   panel is narrower than this and the windows fill it, exactly as they
   always did; in the modal, which is three times as wide, uncapped squares
   grew to a third of the window each and the camera read as three holes with
   a prompt above them. Same rule, same shape, honest at both sizes. */
/* THE ROW IS AS WIDE AS THE BRUSH SEES. The column count is not a layout
   choice, it is the brush's reference cap drawn (data/brushes.js), so it
   comes off the row's own count rather than being written three times here.
   The windows keep their size as the count changes — a four-window row is
   wider, not smaller, because a reference you cannot make out is not one. */
.cam-slots{display:grid; grid-template-columns:repeat(var(--cam-refs,3),1fr); gap:8px; max-width:420px;}
.cam-slots[data-cam-refs="4"]{--cam-refs:4; max-width:560px;}
/* A brush that cannot see gets a sentence where the windows were, not an
   empty row: an empty window promises a reference this painter never receives. */
.cam-slots-none{font-size:var(--t-small); color:var(--muted); line-height:1.5;
  padding:10px 12px; border:1px dashed var(--edge); border-radius:var(--r-md); max-width:420px;}
/* The index a Klein prompt can address by name ("image 0"). Quiet, and in the
   corner the cross is not in, so a full slot never has two things fighting. */
.cam-slot-n{position:absolute; top:4px; left:4px; z-index:1; font-size:var(--t-label);
  font-weight:var(--w-semi); color:var(--muted); line-height:1; pointer-events:none;}
/* Over a picture the number needs its own ground, and the house's answer to
   that is a veil of --panel (the listening window's own move) rather than a
   shadow — a shadow is a colour, and a colour has one home. */
.cam-slot-full .cam-slot-n{color:var(--ink); background:var(--panel);
  padding:2px 5px; border-radius:var(--r-sm);}
/* The price rides the chip, because the chip is where the spending decision
   is made and a paragraph away is not where the eye is. */
.cam-brush-price{margin-left:6px; opacity:.7; font-size:var(--t-label);}

/* ---------- THE CARRY ----------
   A picture under the cursor, and the window it is over. The ghost is a
   plain element following the pointer (actions/house.js owns the gesture) —
   it sits above everything including the camera, because it IS the cursor
   for as long as it exists, and a cursor behind a window is not one.
   It never takes a pointer event: elementFromPoint has to see the window
   underneath it, and a ghost that answered would name itself as the drop. */
.cam-ghost{position:fixed; top:0; left:0; z-index:200; pointer-events:none;
  width:64px; height:64px; border-radius:var(--r-sm); overflow:hidden;
  border:1px solid var(--accent); background:var(--panel); opacity:.85;}
.cam-ghost img{width:100%; height:100%; object-fit:cover;}
/* While carrying, nothing selects: a drag across a modal full of words
   otherwise paints half the room blue on the way past. */
body.cam-carrying{user-select:none; cursor:grabbing;}
body.cam-carrying .cam-thumb{cursor:grabbing;}
/* The window under the pointer says so. It is the same accent the chosen
   chip wears, so "this is the one that will take it" reads the same way
   everywhere in the room. */
.cam-slot.cam-slot-drop{border-color:var(--accent); box-shadow:inset 0 0 0 2px var(--accent);}
.cam-thumb{cursor:grab;}

/* ---------- THE RACKS IN ADVANCED ----------
   Every rack is the same row, so they read as one control repeated rather
   than four controls that happen to sit together. They span the Advanced
   grid because a chip row wraps and a half-width one wraps twice. */
.imgad-rack{grid-column:1/-1;}
/* The cost rides inside the generate button, after its words. Muted against
   the accent ground so the button still reads as one thing and the number is
   a fact rather than a shout. */
[data-cam-cost]{opacity:.8;}

/* ---------- THE CAMERA IS TWO COLUMNS ----------
   What it paints on the left, the pictures it paints FROM on the right
   (Mark, 2026-08-23). The window keeps its own scroll; the panel keeps a
   separate one, so scrolling the clipboard does not move the prompt away. */
/* `.imgad.imgad-wide` rather than `.imgad-wide`: the base `.imgad` is
   declared further down this sheet and would otherwise win on source order
   alone, leaving the panel wrapped underneath the prompt. Caught by the
   probe measuring where the panel actually landed — the markup was right and
   the layout was not, which is a distinction no node count can make. */
.imgad.imgad-wide{display:grid; grid-template-columns:minmax(0,1fr) 300px; gap:0;
  width:min(1040px, 96vw); max-width:96vw; align-items:stretch;}
.imgad-main{display:flex; flex-direction:column; gap:14px; min-width:0; padding-right:14px;}
.imgad-side{min-width:0; border-left:1px solid var(--edge); padding-left:14px;
  display:flex; flex-direction:column; gap:8px; max-height:70vh;}
/* BELOW ~900px THE PANEL FOLDS UNDER rather than collapsing behind a toggle:
   a collapse hides the library from the person it was built for, and the
   window already scrolls. Same content, same order, one column. */
@media (max-width: 900px){
  .imgad.imgad-wide{grid-template-columns:minmax(0,1fr); width:96vw;}
  .imgad-main{padding-right:0;}
  .imgad-side{border-left:0; border-top:1px solid var(--edge); padding-left:0; padding-top:12px; max-height:none;}
}

/* ---------- THE CLIPBOARD ----------
   Anatomy ported from homebidpros' Glance Clipboard: a head, a stack of
   board sections, each with its own head and grid, and a note under an empty
   grid saying how to fill it. Its two-board divider does not come across —
   see rooms/camera.js for why. */
/* The two faces of the panel. A segmented pair, the house's own control for
   this job, matching the reference's `.seg` rather than inventing a tab. */
.clip-tabs{display:flex; gap:2px; padding:2px; border:1px solid var(--edge);
  border-radius:var(--r-pill); background:var(--inset);}
.clip-tab{flex:1; padding:5px 8px; border:0; border-radius:var(--r-pill); cursor:pointer;
  background:none; color:var(--muted); font-size:var(--t-tiny); font-weight:var(--w-med);}
.clip-tab.on{background:var(--accent); color:var(--onAccent);}
.clip-head{display:flex; align-items:center; justify-content:space-between; gap:8px;}
/* The search, and the credit that rides every result. Pexels asks for
   attribution and the name is the licence being kept, not a caption. */
.pexels-search{display:flex; gap:6px; width:100%;}
.pexels-q{flex:1; min-width:0; font-size:var(--t-small); padding:5px 8px;}
.pexels-by{position:absolute; left:0; right:0; bottom:0; padding:2px 5px;
  font-size:var(--t-label); color:var(--ink); background:var(--panel);
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis; pointer-events:none;}
.clip-board-add{font-size:var(--t-label); color:var(--accent); background:none; border:0; cursor:pointer; padding:2px 4px;}
.clip-new-row{display:flex; align-items:center; gap:6px; flex:1; min-width:0;}
.clip-board-name{flex:1; min-width:0; font-size:var(--t-small); padding:5px 8px;}
.clip-board-ok{font-size:var(--t-label); color:var(--accent); background:none; border:0; cursor:pointer;}
.clip-board-x{font-size:var(--t-small); color:var(--muted); background:none; border:0; cursor:pointer;}
.clip-body{flex:1; min-height:0; overflow-y:auto; overflow-x:hidden;}
.clip-stack{display:flex; flex-direction:column; gap:12px;}
.clip-board{display:flex; flex-direction:column; gap:5px;}
.clip-board-head{display:flex; align-items:center; gap:6px; min-height:22px;}
.clip-board-title{font-size:var(--t-tiny); font-weight:var(--w-semi); color:var(--ink2);
  background:none; border:0; cursor:pointer; padding:0; text-align:left;}
.clip-board-title.on{color:var(--accent);}
.clip-board-n{font-size:var(--t-label); color:var(--muted);}
.clip-board-edit{margin-left:auto; font-size:var(--t-label); color:var(--muted);
  background:none; border:0; cursor:pointer; padding:2px 3px;}
.clip-board-edit:hover{color:var(--accent);}
/* The drop ground. It lights with the same accent a window does, because it
   is the same carry and the same answer to "this is what will take it". */
.clip{border:1px dashed transparent; border-radius:var(--r-md); padding:3px;}
.clip.is-drop{border-color:var(--accent); background:var(--inset);}
.clip-grid{display:grid; grid-template-columns:repeat(2,1fr); gap:6px;}
.clip-i{position:relative; border-radius:var(--r-sm); overflow:hidden; aspect-ratio:1;
  border:1px solid var(--edge); background:var(--inset); cursor:grab;}
.clip-i-hit{position:absolute; inset:0; width:100%; height:100%; padding:0; border:0; background:none; cursor:inherit;}
.clip-i .cam-pic{width:100%; height:100%; object-fit:cover; display:block;}
.clip-i-name{position:absolute; left:0; right:0; bottom:0; padding:2px 5px;
  font-size:var(--t-label); color:var(--ink); background:var(--panel);
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis; pointer-events:none;}
.clip-i-x{position:absolute; top:2px; right:2px; width:17px; height:17px; line-height:1;
  border-radius:var(--r-round); border:1px solid var(--edge); background:var(--panel);
  color:var(--muted); font-size:var(--t-tiny); cursor:pointer; opacity:0;}
.clip-i:hover .clip-i-x,.clip-i-x:focus{opacity:1;}
.clip-i-x:hover{color:var(--accent); border-color:var(--accent);}
.clip-note{font-size:var(--t-label); color:var(--muted); line-height:1.5; margin:2px 0 0;}
.cam-slot{position:relative; aspect-ratio:1; border-radius:var(--r-md);
  border:var(--bd) solid var(--edge); background:var(--panel); overflow:hidden;
  display:grid; place-items:center; padding:0;}
.cam-slot-empty{border-style:dashed; color:var(--muted);}
.cam-slot-empty:hover{border-color:var(--accent); color:var(--accent);}
.cam-slot-plus{font-size:var(--t-head); line-height:1;}
.cam-pic{width:100%; height:100%; object-fit:cover; display:block;}
.cam-slot-x{position:absolute; top:4px; right:4px; width:18px; height:18px;
  border-radius:var(--r-round); border:var(--bd) solid var(--edge);
  background:var(--panel); color:var(--muted); font-size:var(--t-tiny); line-height:1;
  display:grid; place-items:center; opacity:0; transition:opacity .12s ease;}
.cam-slot-full:hover .cam-slot-x,.cam-slot-x:focus{opacity:1;}
.cam-slot-x:hover{color:var(--accent); border-color:var(--accent);}
.cam-slots-note{text-align:center;}

/* ---------- the tray ----------
   ONE horizontal strip, sections in order, each scrolling on its own so a
   long RECENT never pushes VIEWS off the bottom of a modal. It replaced a
   readout of model ids and endpoints that stood exactly here, which is to
   say: at the moment of choosing a picture, the room used to offer text
   about the plumbing. */
.cam-tray{display:flex; flex-direction:column; gap:10px; margin-top:10px;}
.cam-tray-sec{display:flex; flex-direction:column; gap:5px;}
.cam-tray-label{opacity:.8;}
.cam-tray-row{display:flex; gap:7px; overflow-x:auto; padding-bottom:3px;}
.cam-tray-empty{color:var(--muted); font-size:var(--t-small); line-height:1.5;}
.cam-thumb-wrap{display:flex; flex-direction:column; gap:3px; flex:0 0 auto;}
.cam-thumb{position:relative; width:58px; height:58px; padding:0; overflow:hidden;
  border-radius:var(--r-sm); border:var(--bd) solid var(--edge); background:var(--panel);
  display:grid; place-items:center; cursor:grab;}
.cam-thumb:hover{border-color:var(--accent);}
.cam-thumb-name{position:absolute; left:0; right:0; bottom:0; padding:2px 3px;
  font-size:var(--t-tiny); line-height:1.2; text-align:center; color:var(--onAccent);
  background:var(--accent); overflow:hidden; text-overflow:ellipsis; white-space:nowrap;}
/* quiet on purpose: keeping is an offer, not an instruction */
.cam-keep{font-size:var(--t-tiny); color:var(--muted); text-align:center; padding:0;
  max-width:58px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;}
.cam-keep:hover{color:var(--accent);}
.cam-naming{display:flex; gap:6px; align-items:center;}
.cam-naming-field{flex:1; min-width:0;}
.cam-naming-ok{font-size:var(--t-small); color:var(--accent); white-space:nowrap;}
.cam-naming-x{color:var(--muted); font-size:var(--t-body); line-height:1; padding:0 4px;}
.cam-verbatim{opacity:.75;}

/* ---------- the image admin ----------
   28 attributes. Title is written 25 / -.025em and renders at 26 / --ls-head.
   The -.025em to --ls-head is the declared snap. Radius 7 on a thumb is
   written 7 and rendered at 9 (--r-sm). Shadow 0 30px 90px stays literal. */
/* THE CAMERA SITS UNDER THE HOUSE DIALOG'S 95, like every other scrim in
   this stylesheet says it does (.cellar-mod-scrim's own comment: "z-index 84
   under the house dialog's 95"; door.css says the same at 80). It was at
   120, ABOVE the dialog, which meant every word the app said while the
   camera was open was drawn behind it: the "all your windows are full"
   refusal, and the notice naming what a brush change set down. Both looked
   from the outside exactly like the app doing nothing.
   Found by measuring, not by looking — the message was on screen, visible
   and correct, and elementFromPoint at its own centre answered the camera. */
.imgad-scrim{position:fixed; inset:0; z-index:88; display:flex; align-items:center;
  justify-content:center; padding:14px; pointer-events:none;}
.imgad-scrim>*{pointer-events:auto;}
/* the brush and reference rows: house chips, never native chrome (the OS
   drew the old dropdown's list itself, whatever the stylesheet said) */
.imgad-chips{display:flex; flex-wrap:wrap; gap:7px;}
/* THE SLUGLINE'S PULLDOWNS (Mark, 2026-09-01: "like a pulldown and you pic
   one"): one quiet row, five narrow selects, the SHOT chips under them. */
.imgad-slugline{display:flex; flex-direction:column; gap:9px;}
.imgad-dd-row{display:grid; grid-template-columns:repeat(auto-fit,minmax(108px,1fr)); gap:7px;}
.imgad-dd{display:flex; flex-direction:column; gap:4px; min-width:0;}
.imgad-select{width:100%; min-width:0; padding:7px 8px; border:var(--bd) solid var(--edge); border-radius:var(--r-md);
  background:var(--inset); color:var(--text); font-family:var(--font-ui); font-size:var(--t-label); cursor:pointer;}
.imgad-select:focus{border-color:var(--accent); outline:none;}
.imgad{width:100%; max-width:760px; max-height:94vh; overflow-y:auto; display:flex;
  flex-direction:column; gap:15px; padding:20px; border:var(--bd) solid var(--edge);
  border-radius:var(--r-xl); background:var(--panel); box-shadow:0 30px 90px var(--shad);}
.imgad-head{display:flex; align-items:flex-start; justify-content:space-between; gap:16px;}
.imgad-title{font-size:var(--t-title); font-weight:var(--w-semi);
  letter-spacing:var(--ls-head); margin-top:4px;}
.imgad-x{width:34px; height:34px; flex:none; border-radius:var(--r-md);
  border:var(--bd) solid var(--edge); color:var(--muted);}
.imgad-pair{display:grid; grid-template-columns:repeat(auto-fit,minmax(230px,1fr)); gap:10px;}
.imgad-field{display:flex; flex-direction:column; gap:6px;}
.imgad-field-7{display:flex; flex-direction:column; gap:7px;}
.imgad-select{padding:10px; border:var(--bd) solid var(--edge); border-radius:var(--r-md);
  background:var(--inset); color:var(--ink); font-size:var(--t-tiny);}
.imgad-prompt-head{display:flex; align-items:center; justify-content:space-between; gap:10px;}
.imgad-ta{width:100%; resize:vertical; padding:11px 12px; border:var(--bd) solid var(--accent);
  border-radius:var(--r-md); background:var(--inset); color:var(--ink2);
  font-size:var(--t-small); line-height:1.5;}
/* The SENT-SOURCES panel left with the pills (2026-08-23). It printed the
   references the last dry run said it would send, under a heading, as a
   second picture of something the three windows already show — and it could
   disagree with them, because it was a snapshot of a preview. */
.imgad-adv{display:grid; grid-template-columns:repeat(auto-fit,minmax(105px,1fr)); gap:9px;
  padding:12px; border:var(--bd) solid var(--edge); border-radius:var(--r-md); background:var(--inset);}
.imgad-num{display:flex; flex-direction:column; gap:5px; min-width:100px;}
.imgad-input{padding:9px 10px; border:var(--bd) solid var(--edge); border-radius:var(--r-md);
  background:var(--inset); font-size:var(--t-tiny);}
.imgad-grok{grid-column:1/-1; font-size:var(--t-tiny); line-height:1.5; color:var(--muted);}
/* THE SHAPE ON THE SIZE CHIP (M-14): a small outlined box in the ratio the
   chip names, standing above the number. One class per ratio because the
   set is static data (data/brushes.js ASPECTS). The outline rides
   currentColor on purpose: the chip's own token ink (.chip's --muted,
   .chip-on's --onAccent) colours shape and label together, so selection
   carries onto both without a second colour home. Auto's dash says no
   shape is chosen. The 11px height is the size of a thing, not a step of
   the scale, the type law's named exclusion. */
.imgad-chip-shaped{display:inline-flex; flex-direction:column; align-items:center; gap:4px;}
.cam-aspect-shape{height:11px; flex:none; border:var(--bd) solid currentColor;}
.cam-aspect-shape-auto{aspect-ratio:1/1; border-style:dashed;}
.cam-aspect-shape-1x1{aspect-ratio:1/1;}
.cam-aspect-shape-4x3{aspect-ratio:4/3;}
.cam-aspect-shape-3x2{aspect-ratio:3/2;}
.cam-aspect-shape-16x9{aspect-ratio:16/9;}
.cam-aspect-shape-2x3{aspect-ratio:2/3;}
/* THE SHOT TILES. The nine-shot sheet is the SHOT row's own grammar, so each
   chip wears its picture above its label the way a SIZE chip wears its ratio
   shape. It is a PICTURE and not a colour, so nothing here paints it: the
   rules are size, fit and the rounded corner every tile in the app has. The
   unlit chips sit back a little so the lit one reads as the pick without a
   second colour being introduced for it. */
.cam-shot-tile{width:44px; height:30px; flex:none; object-fit:cover; border-radius:var(--r-sm); opacity:.72;}
.cellar-pill-13.on .cam-shot-tile{opacity:1;}
.imgad-actions{display:flex; align-items:center; justify-content:flex-end; gap:9px; flex-wrap:wrap;}
