/* Fabulous — the way back to the drawing.
 *
 * A drawing is dropped, the agent builds CAD from it, and until now the sheet
 * was never seen again: it lived on the server as `plate.pdf` and the only
 * thing on screen was the solid it produced. So there was no way to ask "is
 * that Ø30 the one on the sheet?" and no way to POINT at the one it got wrong.
 *
 * This is that sheet, in two shapes — a card lying on the scene beside the
 * model, and full bleed — with a rectangle tool on it. Full bleed it is the
 * same idiom as `#places` in `app.css`: a fixed backdrop over the viewer, a
 * hairline, the house's graphite ground. Both obey the same rule the rest of
 * the page does: the product does not talk. Four controls and no prose.
 *
 * The control that OPENS it is not here: it is `#sheet-open`, the last pill in
 * the west column, which `app.css` owns — it moved out of the mark-up bar on
 * 2026-08-28, because that bar is hidden for the whole of a turn and the
 * minutes somebody most wants their own sheet are the minutes the agent is
 * reading it. This file styles the overlay and nothing outside it, with the
 * one exception recorded under THE COLUMN: `--dock`, which it writes on the
 * body and `app.css` reads.
 *
 * Everything here is namespaced `sheet-`, and this file is loaded beside
 * `app.css` rather than into it, so a version of the drawing surface can be
 * taken out by removing two tags from `index.html`.
 *
 * THE TOKENS ARE `app.css`'S. Nothing is redefined here except `--sheet-mark`,
 * which is the one colour the system does not already have a name for.
 */

:root {
  /* THE MARK, and it is the one place this product is allowed a colour that
     is not ink or the acid. The acid on a white engineering sheet is
     invisible and ink on one is a dimension — the mark has to be neither. Red is what a
     person reaches for on a printed drawing, and it is drawn at an alpha low
     enough that whatever is under it still reads: the whole point of circling
     a `Ø30 H7` is that somebody can still see the `Ø30 H7`.

     Read back out of CSS by `sheet.js` (`getComputedStyle`) rather than
     written down twice — this repo has paid for a constant kept in two files
     more than once. */
  --sheet-mark: rgb(255 59 48 / 0.7);
}

/* ------------------------------------------------------------- the sheet
 *
 * Opaque enough to READ a dimension over. `#places` sits at 0.82 because a
 * project list only has to be legible over geometry; a scanned drawing is
 * grey type on white paper and every percent of the model showing through it
 * is contrast taken off the thing the user opened this to read.
 */
#sheet {
  position: fixed;
  inset: 0;
  z-index: 15;
  background: rgb(var(--ground-rgb) / 0.95);
  backdrop-filter: blur(10px);
  animation: sheet-in var(--enter) both;
  /* The sheet is a surface you drag on. Without this a drag that leaves the
     canvas selects the page underneath and the pan turns into a text
     selection halfway through. */
  user-select: none;
  -webkit-user-select: none;
  touch-action: none;
}

/* -------------------------------------------------------------- THE PANEL
 *
 * THE SHEET'S SECOND SHAPE, and the one it now opens in. Jules, 2026-08-28:
 * *« ouvrir le plan sur le side pdt un run, pour pouvoir checker son plan pdt
 * un build et le comparer facilement au modèle. »* A full-bleed overlay
 * answers "let me read the sheet" and refuses the question under it — the
 * drawing and the part are never on screen together, so comparing them is two
 * gestures and a memory.
 *
 * IT IS A CARD LYING ON THE SCENE, AND THAT IS THE SECOND ANSWER TO THE SAME
 * QUESTION. The first was a SPLIT: `--dock` on the body, the stage, the veil,
 * the wordmark, the compass and the mark-up bar all shifted by the panel's
 * width, and the viewer resized to what was left. It was built, driven at
 * 1440 x 900, and refused on sight — *« je n'aime pas du tout le viewer […]
 * ça ne va pas, et en plus il y a la prompt bar dessus, ça n'a pas de
 * sens. »* Both halves of that are now rules:
 *
 *   - **nothing outside this card moves.** The viewer keeps every pixel of
 *     its frame, the camera never jumps, opening and closing the drawing
 *     costs the model nothing, and the part simply passes behind the paper
 *     when it is turned. That is what a person means by "put it on the side":
 *     lay it down, do not rebuild the room.
 *   - **nothing that belongs to the model comes in here.** The mark-up bar is
 *     bottom-centre where it has always been. A field that looks like a
 *     prompt bar, sitting on a drawing, in a product whose whole doctrine is
 *     that there is no prompt bar, is the worst sentence this page could say
 *     about itself.
 *
 * The full-bleed shape stays, one button away, because reading a `Ø30 H7` on
 * a scanned A3 wants every pixel of the window.
 */
#sheet.dock {
  /* Inset on all four sides: it is an object ON the scene, and an object
     flush against the window edge reads as a region of the window. The top
     clears the wordmark row; the bottom clears the west pills, so the layer
     switches and the Drawing switch itself stay pressable with it up. */
  top: 84px;
  bottom: auto;
  left: 26px;
  right: auto;
  width: var(--sheet-w, 440px);
  /* THE HEIGHT IS THE DRAWING'S, not the window's — `sheet.js::fitPanel`
     derives it from the raster's aspect at the width the user chose, so a
     landscape A3 gets a short card instead of 724 px of ground with 305 px of
     paper floating in it. */
  height: var(--sheet-h, 520px);
  border: 1px solid var(--rule);
  background: var(--panel);
  /* A CARD, WITH A SHADOW THAT SAYS SO. The full-bleed shape is a veil over
     the page and blurs what is under it; this one is a thing lying on top of
     the scene, and the shadow is what stops it reading as a hole cut in the
     window. */
  backdrop-filter: blur(14px);
  box-shadow: 0 18px 48px rgb(0 0 0 / 0.55);
  animation: sheet-slide var(--enter) both;
}

@keyframes sheet-slide {
  from { opacity: 0; transform: translateX(-16px); }
  to   { opacity: 1; transform: translateX(0); }
}

/* THE EDGE IS A HANDLE, and it is 10 px of hit area on a 2 px line — the
   pointer target every resizable panel has, drawn as nothing at all until a
   cursor is on it. It is what makes the width the user's: an A3 read at a
   third of a laptop is legible and an A4 portrait is not. */
#sheet-grip {
  position: absolute;
  top: 0;
  bottom: 0;
  right: -5px;
  width: 10px;
  z-index: 3;
  cursor: col-resize;
  background: transparent;
  border: 0;
  padding: 0;
}

#sheet:not(.dock) #sheet-grip { display: none; }

#sheet-grip::after {
  content: "";
  position: absolute;
  top: 50%;
  right: 4px;
  width: 2px;
  height: 46px;
  transform: translateY(-50%);
  background: rgb(var(--ink-rgb) / 0);
  transition: background var(--wake);
}

#sheet-grip:hover::after,
#sheet.gripping #sheet-grip::after { background: rgb(var(--ink-rgb) / 0.34); }
#sheet.gripping { border-color: var(--line-live); }

@media (prefers-reduced-motion: reduce) {
  #sheet.dock { animation: none; }
}

#sheet[hidden] { display: none !important; }

@keyframes sheet-in { from { opacity: 0; } to { opacity: 1; } }

@media (prefers-reduced-motion: reduce) {
  #sheet { animation: none; }
}

/* Two canvases, stacked, both the full viewport.
 *
 * ONE CANVAS WOULD HAVE BEEN SIMPLER AND IT IS WRONG TWICE. Redrawing a
 * 1200 x 1700 raster on every `pointermove` is a blit per mouse event; and
 * drawing only the newest segment instead — the usual way out of that — lays
 * a fresh round cap over the previous one, and the mark is TRANSLUCENT — so a
 * stroke beads into a row of dark blobs, one per sample. The paper repaints
 * when the VIEW moves, the ink repaints on every frame of a stroke, and the
 * ink is redrawn whole so its alpha composites exactly once. */
#sheet-paper,
#sheet-ink {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
}

/* The top one takes every pointer: the paper below it is a picture. */
#sheet-ink { cursor: crosshair; }
#sheet.panning #sheet-ink { cursor: grabbing; }
#sheet:not(.selecting) #sheet-ink { cursor: grab; }

/* -------------------------------------------------------------- the tools
 *
 * Four, and the page's own vocabulary for all of them: the pill from
 * `#layers`, the acid for the state that is ON, a warmth behind the type for
 * hover — never the acid, which belongs to the state (`app.css` records what
 * borrowing it for `:hover` cost).
 */
/* NOTHING LIES ACROSS THE DRAWING. Each control carries its own ground.
 *
 * Two passes to get here and the first one is the note worth keeping. Shot in
 * a real browser at 5.6x: this overlay is the ONE place in the product where
 * the ground behind a control is white PAPER, so the page's dark rectangle
 * with `--ink-mute` type on it turned `Undo`, `Clear` and `Close`
 * into grey-on-grey smudges and all but erased `PLATE.PDF`. The obvious fix
 * was a scrim across the top — and at the FITTED zoom that scrim reads as a
 * grey band lying on the sheet, which is a panel drawn over the one thing the
 * user opened this to look at.
 *
 * So there is no bar, only objects: the file name is a pastille (the same one
 * `#place` is, down to the mono and the tracking) and the tools are the pills
 * `#layers` uses, each opaque enough to read on white. That is the house's
 * own answer — no panels, things in corners — and it is the answer that leaves
 * the drawing alone. */
#sheet-bar {
  position: absolute;
  top: 18px;
  left: 26px;
  right: 26px;
  display: flex;
  align-items: center;
  gap: 10px;
  pointer-events: none;   /* the gaps are sheet, not toolbar */
}

/* The SERVER's name for the file, as a pastille. It is the only word on this
   overlay and it is a label, not a sentence — so it is `#place`'s clothes and
   not a button's. */
#sheet-file {
  flex: 0 1 auto;
  margin-right: auto;
  max-width: 40%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  padding: 6px 12px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: rgb(var(--ground-rgb) / 0.9);
  backdrop-filter: blur(6px);
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-mute);
}

#sheet-tools {
  display: flex;
  gap: 6px;
  pointer-events: auto;
}

/* THE PAGER, and it is on the file's side of the row rather than among the
   tools: which page is on the paper is a fact ABOUT the drawing, like its
   name, and not something you do to it. Two arrows and `2 / 4` between them —
   `sheet.js` hides the whole group on a drawing of one page, which is every
   raster and most PDFs, so this is a control that appears only when there is
   somewhere to go. */
#sheet-pager {
  display: flex;
  align-items: center;
  gap: 2px;
  margin-right: auto;
  pointer-events: auto;
}

#sheet-pager button {
  padding: 6px 9px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: rgb(var(--ground-rgb) / 0.9);
  backdrop-filter: blur(6px);
  color: var(--ink-mute);
  font-family: inherit;
  font-size: 13px;
  line-height: 1;
  cursor: pointer;
  transition: background var(--wake), color var(--wake);
}

#sheet-pager button:not(:disabled):hover { background: rgb(var(--ink-rgb) / 0.10); }
#sheet-pager button:disabled { opacity: 0.28; cursor: default; }

#sheet-page {
  min-width: 44px;
  text-align: center;
  padding: 0 4px;
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.1em;
  color: var(--ink-mute);
}

#sheet-tools button {
  padding: 8px 15px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  /* Opaque, not the page's 0.6 — belt as well as the scrim above, because a
     pill IS the thing a hand is aiming at and it must not depend on how far
     the drawing happens to be zoomed. */
  background: rgb(var(--ground-rgb) / 0.9);
  backdrop-filter: blur(6px);
  color: var(--ink-mute);
  font-family: inherit;
  font-size: 12.5px;
  letter-spacing: 0.01em;
  cursor: pointer;
  transition: background var(--wake), color var(--wake), border-color var(--wake);
}

#sheet-tools button:not(:disabled):hover { background: rgb(var(--ink-rgb) / 0.10); }
#sheet-tools button:disabled { opacity: 0.28; cursor: default; }

#sheet-tools button[aria-pressed="true"] {
  border-color: var(--accent-soft);
  color: var(--accent-deep);
}

/* IN THE PANEL IT IS A HEADER AND NOT FLOATING PILLS, and the argument above
   flips because the ground flips with it: the pills carry their own dark
   ground so they can be read over white PAPER, and in the card the top strip
   is the card's own panel — so a pill there is a rectangle drawn on a
   rectangle. A header row with a hairline under it is what a card has.

   It also has to FIT: five pills at 15 px of padding is 430 px of row and the
   panel opens at about 460. The controls lose their borders and become type;
   the two that are about the surface rather than the drawing (full screen,
   close) become glyphs. */
#sheet.dock #sheet-bar {
  top: 0;
  left: 0;
  right: 0;
  height: 42px;
  padding: 0 12px;
  gap: 8px;
  border-bottom: 1px solid var(--rule);
  pointer-events: auto;
}

#sheet.dock #sheet-file {
  padding: 0;
  border: 0;
  background: transparent;
  backdrop-filter: none;
  max-width: 45%;
  color: var(--ink-soft);
}

#sheet.dock #sheet-tools { gap: 2px; }

/* ...AND THE PAGER LOSES ITS PILLS FOR THE SAME REASON THE TOOLS DO: in the
   card the strip is the card's own panel, so a bordered pill on it is a
   rectangle drawn on a rectangle. It also has to fit — the row is 460 px with
   a file name and four controls already in it. */
#sheet.dock #sheet-pager { gap: 0; }

#sheet.dock #sheet-pager button {
  padding: 6px 6px;
  border-color: transparent;
  background: transparent;
  backdrop-filter: none;
}

#sheet.dock #sheet-page { min-width: 36px; }

#sheet.dock #sheet-tools button {
  padding: 6px 8px;
  border-color: transparent;
  background: transparent;
  backdrop-filter: none;
  font-size: 11.5px;
}

#sheet.dock #sheet-tools button:not(:disabled):hover {
  background: rgb(var(--ink-rgb) / 0.10);
}

/* The two that are about the surface and not about the drawing: a glyph
   each, and their words live in the `title` for a hand that hovers. */
#sheet.dock #sheet-mode,
#sheet.dock #sheet-close {
  font-size: 14px;
  line-height: 1;
  padding: 6px 7px;
}


/* ------------------------------------------------------------- the card
 *
 * WHAT ONE SELECTION MEANS: a line to type, and the comment on the model it
 * belongs to. Both optional — a bare rectangle is still "look here" — which is
 * why nothing in here is a required field and why the card can simply be
 * dismissed.
 *
 * IT IS A PANEL, and this overlay has spent two passes arguing that nothing
 * lies across the drawing. The argument holds: a panel that is ABOUT the
 * rectangle the user has just drawn, placed under it, sized to two lines and
 * gone the moment they click away is not chrome on the sheet — it is the
 * gesture finishing. What is forbidden here is a panel that is up when nobody
 * asked for one, and `pick("")` is called by Escape, by a click on bare paper
 * and by Remove.
 */
#sheet-card {
  position: absolute;
  z-index: 4;
  width: min(280px, calc(100% - 32px));
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 11px 12px 12px;
  border: 1px solid var(--rule);
  background: var(--panel);
  backdrop-filter: blur(8px);
  /* The paper is white and this is the house's near-black: the card needs to
     read as a thing lying ON the sheet rather than a hole cut in it. */
  box-shadow: 0 10px 26px rgb(0 0 0 / 0.45);
  animation: sheet-card-in var(--wake) both;
}

#sheet-card[hidden] { display: none !important; }

@keyframes sheet-card-in {
  from { opacity: 0; transform: translateY(-4px); }
  to   { opacity: 1; transform: translateY(0); }
}

@media (prefers-reduced-motion: reduce) {
  #sheet-card { animation: none; }
}

#sheet-card-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
}

/* The number on the card is the number painted in the box's corner, and they
   are one enumeration — the same property the pins' discs and lines rest on. */
#sheet-card-n {
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--accent-deep);
}

#sheet-card-drop {
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--ink-mute);
  font-family: inherit;
  font-size: 11px;
  cursor: pointer;
  transition: color var(--wake);
}

#sheet-card-drop:hover { color: var(--ink); }

/* A place you write, not a control you press — the same clothes as
   `#mark-said`, one step darker because this one sits on a panel. */
#sheet-card-note {
  width: 100%;
  padding: 7px 8px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: rgb(var(--ground-rgb) / 0.55);
  color: var(--ink);
  font-family: inherit;
  font-size: 12.5px;
  line-height: 1.45;
  resize: none;
}

#sheet-card-note:focus {
  outline: none;
  border-color: var(--accent-soft);
}

#sheet-card-note::placeholder { color: rgb(var(--ink-rgb) / 0.38); opacity: 1; }

#sheet-card-pin {
  width: 100%;
  padding: 6px 8px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: rgb(var(--ground-rgb) / 0.55);
  color: var(--ink-soft);
  font-family: inherit;
  font-size: 11.5px;
  cursor: pointer;
}

#sheet-card-pin:disabled { opacity: 0.45; cursor: default; }
#sheet-card-pin:focus { outline: none; border-color: var(--accent-soft); }


/* IN THE PANEL THE CARD IS A DRAWER under the drawing rather than a box over
   it (`sheet.js::placeCard` says why). It is the panel's own width, lined up
   with its border, and it carries the same shadow so the two read as one
   object with something pulled out of it. */
#sheet.dock #sheet-card {
  animation-name: sheet-drawer;
  box-shadow: 0 18px 48px rgb(0 0 0 / 0.55);
}

@keyframes sheet-drawer {
  from { opacity: 0; transform: translateY(-8px); }
  to   { opacity: 1; transform: translateY(0); }
}
