/* ══════════════════════════════════════════════════════════════════════════
   THE FREE-PLACEMENT OVERLAY - selection, drag, resize, marquee
   ──────────────────────────────────────────────────────────────────────────

   Chrome for `src/components/editor/deck/DeckFreeOverlay.vue`, which is the
   direct-manipulation layer over one slide: press a free box to select it, drag
   it, pull it by one of eight handles, sweep a marquee over several.

   ── THE FILENAME IS LOAD-BEARING, TWICE

   `scripts/bundle-css.mjs` partitions the public and admin bundles on the
   literal `/css/admin` in the href and on nothing else, so a sheet named
   `editor-free.css` would ship the deck editor's chrome to every marketing
   visitor with a completely green build. And `tests/editorCssIsolation.spec.ts`
   sweeps `admin-editor*` against every other sheet on the page, which is the
   check that catches the collision below.

   ── EVERY CLASS HERE STARTS `edtf-`, AND THAT IS NOT A STYLE PREFERENCE

   All `public/css/admin*.css` concatenate into ONE admin bundle that every admin
   page loads, and the editor sheets are linked late, so a bare class name here
   is a global rule that wins at equal specificity on screens this file has never
   heard of. Round 1 of the editor shipped `.edt-page` and flipped the Person
   page's Hebrew sale panel to left-to-right at full viewport height, silently.
   So: no `.tpl*`, no `.slide*`, no `.edt-canvas*`, no bare state class. The one
   state names in here - `is-selected`, `is-on`, `is-error` - are only ever
   written as a COMPOUND (`.edtf-box.is-selected`, `.edtf-seg__btn.is-on`,
   `.edtf-notes__item.is-error`), which cannot reach an element that does not also
   carry `.edtf-box`.

   ── NOTHING HERE DECLARES `container-type`

   `.edt-canvas__inner` carries the page's only `container-type: inline-size` and
   1cqw must stay 19.2px. A second container anywhere between the page root and a
   `.tpl` re-bases every size in the template vocabulary silently, and the slide
   then looks plausible at every width while being wrong at all of them. The
   overlay is a SIBLING of the canvas rather than a child of it, so it could not
   reach a `.tpl` even if it tried, and `tests/editorDeckFreeOverlay.spec.ts`
   asserts the string is absent from this file and from the component.

   ── NOTHING HERE IS INSIDE THE RTL ISLAND EITHER

   `.edt-canvas__inner` is the page's one `dir="rtl"` element. This overlay sits
   outside it, so its chrome reads English left to right like the rest of
   `/editor`, and the geometry below is PHYSICAL left/top rather than the logical
   pair the slide vocabulary prefers - these are picture coordinates on a fixed
   stage, taken from a pointer, and they do not mirror when the slide's Hebrew
   does.

   Breakpoints, where any were needed, would be the repo's two: 1024px and 767px.
   None is: the Deck tab is not rendered below 767px at all (EditorShell puts a
   notice there instead) and the overlay simply tracks whatever size the canvas
   has been given.
   ══════════════════════════════════════════════════════════════════════════ */

/* ── The layer itself ───────────────────────────────────────────────────────
 *
 * A sibling of `<SlideCanvas>` inside `.edtd-stagewrap`, which is already
 * `position: relative`. INERT: the root covers the whole stage so the component
 * has something to measure against, and it must not take a press away from the
 * canvas on the 111 slides that carry no free box at all. The interactive frame
 * inside it is the only thing that accepts a pointer. */
.edtf-overlay {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

/* The measured `.tpl` rectangle, in pixels, from a dynamic `:style` binding -
 * the same "genuinely computed value" carve-out `SlideCanvas.vue` takes for its
 * transform. Everything inside is positioned in PERCENT of this box, so the
 * canvas's own scale never enters the arithmetic. */
.edtf-frame {
  position: absolute;
  pointer-events: auto;
  /* The frame takes focus so the arrow keys can nudge, and a focus ring around
     the whole slide would read as an error. The selected box draws its own. */
  outline: none;
  /* A box dragged past the edge must still be visible as a hatched sliver, so
     this box does not clip. The `.tpl` box itself does, in the room and on the
     canvas, which is exactly what the hatch is warning about. */
  overflow: visible;
}

/* ── One box ────────────────────────────────────────────────────────────────
 *
 * An OUTLINE, never a fill: the thing underneath is the slide, and the whole
 * point of the surface is that the owner is looking at it. Quiet until hovered,
 * loud when selected. */
.edtf-box {
  position: absolute;
  box-sizing: border-box;
  border: 1px dashed rgba(0, 113, 227, 0.35);
  border-radius: 2px;
  background: transparent;
  cursor: move;
  /* Not `touch-action: none` on the element the pointer starts on and nothing
     else: the deck editor has no phone layout, and a stylus or a trackpad
     gesture that scrolls the pane while a box is being dragged is a bad enough
     surprise to be worth the one declaration. */
  touch-action: none;
}

.edtf-box:hover {
  border-color: rgba(0, 113, 227, 0.7);
  background: rgba(0, 113, 227, 0.06);
}

.edtf-box.is-selected {
  border: 1px solid var(--edt-accent);
  background: rgba(0, 113, 227, 0.08);
  box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.65);
}

/* Which part the box plays, on the selected box only. Above the outline rather
 * than inside it, because a chip inside covers the first line of the slide's own
 * text - which is the text the owner is placing the box against. */
.edtf-box__tag {
  position: absolute;
  bottom: 100%;
  left: -1px;
  margin-bottom: 3px;
  padding: 1px 5px;
  border-radius: 3px;
  background: var(--edt-accent);
  color: #fff;
  font-family: var(--font-mono);
  font-size: 0.62rem;
  line-height: 1.5;
  white-space: nowrap;
  pointer-events: none;
}

/* ── The eight handles ──────────────────────────────────────────────────────
 *
 * Drawn in SCREEN space rather than in percent, so a handle stays 10px at a
 * canvas scale of about 0.25 instead of shrinking with the slide until it cannot
 * be hit. They are pointer-only chrome and are `aria-hidden` in the template:
 * the keyboard path to the same numbers is the arrow-key nudge and the
 * properties panel's numeric fields. */
.edtf-handle {
  position: absolute;
  inline-size: 10px;
  block-size: 10px;
  margin: -5px 0 0 -5px;
  box-sizing: border-box;
  border: 1px solid var(--edt-accent);
  border-radius: 2px;
  background: #fff;
  touch-action: none;
}

.edtf-handle--nw {
  left: 0;
  top: 0;
  cursor: nwse-resize;
}

.edtf-handle--n {
  left: 50%;
  top: 0;
  cursor: ns-resize;
}

.edtf-handle--ne {
  left: 100%;
  top: 0;
  cursor: nesw-resize;
}

.edtf-handle--w {
  left: 0;
  top: 50%;
  cursor: ew-resize;
}

.edtf-handle--e {
  left: 100%;
  top: 50%;
  cursor: ew-resize;
}

.edtf-handle--sw {
  left: 0;
  top: 100%;
  cursor: nesw-resize;
}

.edtf-handle--s {
  left: 50%;
  top: 100%;
  cursor: ns-resize;
}

.edtf-handle--se {
  left: 100%;
  top: 100%;
  cursor: nwse-resize;
}

/* ── The part of a box that is off the frame ────────────────────────────────
 *
 * `.tpl { overflow: hidden }` CLIPS it, and nothing measures the loss: the
 * `.tpl` box is inset from the 1920x1080 stage by `.slide--display`'s padding,
 * so a clipped box still has a rectangle inside the stage and the overflow probe
 * never fires. Content is simply not on the projector with nothing to say so,
 * which is the same shape as the failure the whole template system was built
 * after. Hence a hatch, live, while the gesture is happening rather than after
 * publish - and hence red, which nothing else on this surface is. */
.edtf-escape {
  position: absolute;
  pointer-events: none;
  background: repeating-linear-gradient(
    45deg,
    rgba(198, 40, 40, 0.42) 0,
    rgba(198, 40, 40, 0.42) 4px,
    rgba(198, 40, 40, 0.1) 4px,
    rgba(198, 40, 40, 0.1) 8px
  );
  outline: 1px solid rgba(198, 40, 40, 0.6);
}

/* ── The two brandmark corners ──────────────────────────────────────────────
 *
 * The bare 10x mark sits at the physical top left of the SLIDE and the terminal
 * chevron at the physical bottom right, both inset 3cqw, both drawn by the room
 * and by neither the editor canvas nor the fit probe. A free box parked on one
 * of them looks perfect here and lands on furniture in front of a class, and
 * nothing else in the system sees that collision. Faint on purpose: it is a
 * reserve, not an error, and a box may legitimately overlap the outer edge of
 * one. */
.edtf-reserve {
  position: absolute;
  pointer-events: none;
  border: 1px dashed rgba(25, 26, 35, 0.22);
  border-radius: 3px;
  background: rgba(25, 26, 35, 0.05);
}

/* ── The marquee ────────────────────────────────────────────────────────────
 *
 * A sweep over empty stage. It selects every box whose DRAWN rectangle it
 * touches, which is why it is drawn as a filled band rather than as a bare
 * outline: the fill is the area being asked about. */
.edtf-marquee {
  position: absolute;
  pointer-events: none;
  border: 1px solid var(--edt-accent);
  background: rgba(0, 113, 227, 0.12);
}

/* ── The properties panel ─────────────────────────────────────────────────────
   The side-column card that edits the SELECTED block: its numbers, its stacking,
   the role it plays and how it looks. Its shell repeats `.edtd-steps`
   (admin-editor-deck.css) rather than inventing a second card look, because the
   two sit one above the other in the same column and a second radius or a second
   inset line reads as a mistake.

   NO COLOUR PICKER AND NO HEX ANYWHERE. Every look control writes a modifier
   CLASS that resolves against the slide vocabulary's own tokens, so a skin swap
   keeps working; a hex written here would survive `tpl--dark` redefining
   `--tpl-ink` and go invisible on the projector with nothing to say so.

   `.is-on` and `.is-error` are ALWAYS compounded with their own `.edtf-*` name.
   A bare state class is a global claim on that word inside the one admin bundle,
   which is exactly what tests/editorCssIsolation.spec.ts exists to catch. */
.edtf-panel {
  padding: 0.85rem 0.95rem;
  border-radius: 12px;
  background: var(--edt-surface-solid);
  box-shadow: inset 0 0 0 1px var(--edt-line);
}

.edtf-panel__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.6rem;
  margin-bottom: 0.5rem;
}

.edtf-panel__title {
  margin: 0;
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--edt-ink);
}

.edtf-panel__count {
  font-size: 0.76rem;
  color: var(--edt-ink-3);
}

.edtf-panel__empty {
  margin: 0;
  font-size: 0.78rem;
  line-height: 1.6;
  color: var(--edt-ink-2);
}

.edtf-notes {
  list-style: none;
  margin: 0 0 0.6rem;
  padding: 0;
  display: grid;
  gap: 0.35rem;
}

.edtf-notes__item {
  padding: 0.45rem 0.6rem;
  border-radius: 8px;
  font-size: 0.73rem;
  line-height: 1.55;
  background: rgba(200, 140, 0, 0.08);
  box-shadow: inset 0 0 0 1px rgba(200, 140, 0, 0.25);
  color: #7a5300;
}

.edtf-notes__item.is-error {
  background: rgba(200, 40, 40, 0.06);
  box-shadow: inset 0 0 0 1px rgba(200, 40, 40, 0.22);
  color: #96231f;
}

/* `min-inline-size: 0` is load-bearing, not tidying. A <fieldset> carries an
   intrinsic min-content floor that ignores its flex or grid basis, so without
   this the group refuses to shrink and pushes the whole side column wider than
   the workspace allows. */
.edtf-group {
  border: 0;
  margin: 0 0 0.7rem;
  padding: 0;
  min-inline-size: 0;
}

.edtf-group__legend {
  padding: 0;
  margin: 0 0 0.35rem;
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--edt-ink-3);
}

.edtf-nums {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.4rem 0.5rem;
}

.edtf-num {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
}

.edtf-num__label {
  font-size: 0.72rem;
  color: var(--edt-ink-3);
}

.edtf-num__box {
  display: flex;
  align-items: center;
  gap: 0.25rem;
  padding: 0.3rem 0.45rem;
  border-radius: 8px;
  background: var(--edt-surface);
  box-shadow: inset 0 0 0 1px var(--edt-line);
}

/* The native spinners are kept deliberately: they step by 0.25, which is the
   same grid a drag snaps to, so the keyboard and the pointer agree. */
.edtf-num__input {
  inline-size: 100%;
  min-inline-size: 0;
  border: 0;
  background: transparent;
  color: var(--edt-ink);
  font-size: 0.8rem;
}

.edtf-num__unit {
  font-size: 0.72rem;
  color: var(--edt-ink-3);
}

.edtf-fit {
  margin-top: 0.5rem;
}

.edtf-row {
  display: flex;
  flex-wrap: wrap;
  gap: 0.3rem;
}

.edtf-z {
  flex: 1 1 auto;
  min-inline-size: 0;
  font-size: 0.73rem;
  padding: 0.3rem 0.4rem;
}

.edtf-select {
  inline-size: 100%;
  padding: 0.35rem 0.45rem;
  border-radius: 8px;
  border: 0;
  background: var(--edt-surface);
  box-shadow: inset 0 0 0 1px var(--edt-line);
  color: var(--edt-ink);
  font-size: 0.8rem;
}

.edtf-seg {
  display: flex;
  flex-wrap: wrap;
  gap: 2px;
  padding: 2px;
  border-radius: 9px;
  background: var(--edt-surface);
  box-shadow: inset 0 0 0 1px var(--edt-line);
}

.edtf-seg__btn {
  flex: 1 1 auto;
  min-inline-size: 0;
  border: 0;
  background: transparent;
  border-radius: 7px;
  padding: 0.28rem 0.4rem;
  font-size: 0.73rem;
  color: var(--edt-ink-2);
  cursor: pointer;
}

.edtf-seg__btn:hover:not(:disabled) {
  background: rgba(25, 26, 35, 0.04);
}

.edtf-seg__btn.is-on {
  background: var(--edt-surface-solid);
  color: var(--edt-ink);
  font-weight: 600;
  box-shadow: inset 0 0 0 1px var(--edt-line);
}

.edtf-seg__btn:disabled {
  opacity: 0.5;
  cursor: default;
}

.edtf-check {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  font-size: 0.78rem;
  color: var(--edt-ink-2);
  cursor: pointer;
}

.edtf-check__box {
  margin: 0;
  inline-size: 0.9rem;
  block-size: 0.9rem;
  accent-color: var(--edt-accent);
}

.edtf-check__text {
  line-height: 1.4;
}

.edtf-slider {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  margin-top: 0.45rem;
}

.edtf-slider__label {
  display: flex;
  justify-content: space-between;
  gap: 0.5rem;
  font-size: 0.72rem;
  color: var(--edt-ink-3);
}

.edtf-slider__value {
  font-variant-numeric: tabular-nums;
  color: var(--edt-ink);
}

.edtf-slider__input {
  inline-size: 100%;
  margin: 0;
  accent-color: var(--edt-accent);
}

.edtf-hint {
  margin: 0.35rem 0 0;
  font-size: 0.73rem;
  line-height: 1.55;
  color: var(--edt-ink-2);
}

/* ── The stage toolbar, and typing in place ───────────────────────────────────
   `.edtf-tools` is the strip above the canvas: undo, redo, and the five "add a
   block" buttons. `.edtf-text` is the floating field that opens on a double
   click.

   THE FIELD IS ABSOLUTE AGAINST `.edtd-stagewrap`, which admin-editor-deck.css
   already makes `position: relative`, and it is drawn AFTER the overlay in
   document order - which is what puts it above the frame without either of them
   declaring a stacking context. It is deliberately NOT inside
   `.edt-canvas__inner`: that element carries the page's only
   `container-type: inline-size`, 1cqw must stay 19.2px, and a second container
   anywhere between the page root and a `.tpl` silently re-bases every size in
   the slide vocabulary - the slide then looks plausible at every width while
   being wrong at all of them.

   The min width is the floor under a two-word kicker, whose measured box is
   narrower than the field's own toolbar. */
.edtf-tools {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.4rem;
}

.edtf-tools__status {
  font-size: 0.74rem;
  line-height: 1.5;
  color: var(--edt-ink-3);
}

.edtf-add {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.4rem;
}

.edtf-add__label {
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--edt-ink-3);
}

.edtf-text {
  position: absolute;
  box-sizing: border-box;
  min-inline-size: 260px;
  max-inline-size: 100%;
  padding: 0.4rem;
  border-radius: 10px;
  background: var(--edt-surface-solid);
  box-shadow:
    0 8px 24px rgba(25, 26, 35, 0.18),
    inset 0 0 0 1px var(--edt-accent);
}

.edtf-text__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  margin-bottom: 0.35rem;
}

.edtf-text__role {
  font-family: var(--font-mono);
  font-size: 0.68rem;
  color: var(--edt-ink-3);
}

.edtf-text__done {
  flex: none;
}

.edtf-text__hint {
  margin: 0.35rem 0 0;
  font-size: 0.7rem;
  line-height: 1.5;
  color: var(--edt-ink-2);
}
