/* GlassFX — THE WORLD WORKSPACE, AND THE REDESIGNED NAVIGATION.
   ══════════════════════════════════════════════════════════════════════
   Loaded after app.css and stage.css, so it may correct them.
   ══════════════════════════════════════════════════════════════════════ */

/* ══ THE GIZMO LAYER ═════════════════════════════════════════════════
   The gizmo draws an SVG of PROJECTED WORLD GEOMETRY — so it sits in the
   scene and shrinks with distance, but stays pixel-crisp at any size.
   The layer takes no pointers; the gizmo's own handles do. */
.gfx-gizmo-layer { position: absolute; inset: 0; pointer-events: none; z-index: 40; }
.gfx-gizmo-layer svg { position: absolute; inset: 0; overflow: visible; }
.gfx-gizmo-layer .gw-hit { pointer-events: auto; }
body[data-stage="present"] .gfx-gizmo-layer { display: none; }

/* ══ THE PROJECT BIN ═════════════════════════════════════════════════ */

.gfx-binhead {
  font-size: 10px; letter-spacing: .14em; text-transform: uppercase;
  color: var(--ink-3); margin: 10px 2px 4px;
}
.gfx-binhead:first-child { margin-top: 2px; }

.gfx-x {
  flex: 0 0 auto; width: 20px; height: 20px;
  background: none; border: 0; border-radius: 4px;
  color: var(--ink-4); display: grid; place-items: center; cursor: default;
}
.gfx-item:hover .gfx-x { color: var(--ink-3); }
.gfx-x:hover { color: var(--warn) !important; background: var(--ink-5); }

/* ══ THREE WORKSPACES ════════════════════════════════════════════════
   WORLD, COMPOSER, ANIMATOR are not three programs — they are three sets
   of panels over one viewport, and switching is one attribute on <body>.
   That is why adding a fourth costs nothing. */
.bar-tab[data-tab="world"].is-on { border-bottom-color: var(--acc); }

/* ── DROP FILES ON THE PANEL ──────────────────────────────────────── */
.gfx-drop {
  border: 1px dashed var(--ink-4); border-radius: var(--r-ctl);
  padding: 10px 8px; margin: 2px 0 6px;
  color: var(--ink-3); font-size: 11px; text-align: center;
  transition: border-color .18s, background .18s, color .18s;
}
.gfx-drop.is-over {
  border-color: var(--acc); background: var(--acc-2); color: var(--ink-1);
}

/* ══ THE TREE — SHOW, LOCK, GROUP, REORDER ═════════════════════════
   BOTH FLAGS ARE WORKSHOP STATE. The eyeball takes a thing out of the
   workshop viewport so you can work behind it; the padlock stops it
   being grabbed by accident. Neither reaches the visitor — a flag that
   dropped an object from the SHOW would let one click silently empty a
   presentation already with a client.

   THE GLYPHS CARRY THE STATE, so they have to differ at 14 px — see the
   note over the paths in icons.js. That was the real fault: the open and
   closed padlocks were a pixel apart and nobody could read the column.

   THE TWO COLUMNS ARE ALSO ALWAYS THERE. They used to fade in on hover,
   which looked tidy and cost more than it bought: you cannot decide
   whether to click an eyeball you have to go looking for, and a HIDDEN
   row's eyeball is the only way to get it back. Both now sit in a fixed
   column at the end of every row, so the state of a whole list reads
   down one straight edge without touching anything. */

.gfx-flags {
  display: flex; align-items: center; gap: 2px;
  flex: 0 0 auto; margin-left: auto; padding-left: 6px;
  border-left: 1px solid var(--ink-5);   /* it reads as a column, not as two loose buttons */
}
.gfx-flag {
  width: 22px; height: 22px; border-radius: 4px;
  background: none; border: 0; padding: 0;
  color: var(--ink-3); display: grid; place-items: center;
  cursor: pointer; opacity: 1;            /* ALWAYS VISIBLE — dim is off, lit is on */
  transition: color .14s, background .14s;
}
.gfx-flag:hover { background: var(--ink-5); color: var(--ink-1); }

/* A SET FLAG IS LIT AND PLATED. Plated as well as coloured, so a lit row
   is legible at a glance on a screen that does not show the colour —
   the state is never colour alone. */
.gfx-flag--eye.is-on {
  color: var(--warn);
  background: rgb(224 102 60 / .16);
}
.gfx-flag--lock.is-on {
  color: var(--acc);
  background: rgb(201 162 39 / .16);
}

/* a hidden row reads as absent without disappearing */
.gfx-item.is-hidden .n { opacity: .45; }
.gfx-item.is-hidden .n em { text-decoration: line-through; }
/* a locked row reads as fixed */
.gfx-item.is-locked .i { color: var(--acc); }

/* ── the group head ── */
.gfx-group {
  color: var(--ink-3);
  border-top: 1px solid var(--ink-5);
  margin-top: 3px;
}
.gfx-group .n { font-size: 11px; letter-spacing: .06em; }
.gfx-sub2 { padding-left: 30px; }

/* ── drag to reorder ──────────────────────────────────────────────
   THE LIST ORDER IS THE SHOW'S ORDER, so reordering has to be direct.
   The icon is the handle: grabbing a row anywhere else still selects
   it, which is what you want nine times out of ten. */
.gfx-grip { cursor: grab; }
.gfx-item.is-locked .gfx-grip { cursor: default; }
body.gfx-dragging .gfx-grip { cursor: grabbing; }

.gfx-item.is-dragging {
  opacity: .85;
  background: var(--ink-5);
  box-shadow: 0 6px 18px rgb(0 0 0 / .45), inset 2px 0 0 var(--acc);
}
.gfx-row { transition: background .12s; }

/* A FILE IS BEING DRAGGED OVER THE WINDOW. The little zones in the
   panels are a hint; the whole window takes a drop, and what the file is
   decides where it goes. */
body.gfx-dropping #stage { box-shadow: inset 0 0 0 2px var(--acc); }
body.gfx-dropping .gfx-drop { border-color: var(--acc); color: var(--ink-1); }

/* ══ TYPING ON A CARD IN THE ROOM ═══════════════════════════════════
   Double-clicking the words edits the words. While a run is live it
   gets a caret, a ring so you can see what you are inside, and it stops
   being see-through — a half-transparent field you are typing into is
   hard to read against a scan. */
.gfx-slide [data-field].is-editing {
  outline: 1.5px solid var(--acc);
  outline-offset: 3px;
  border-radius: 3px;
  background: rgb(11 10 9 / .78);
  cursor: text;
  user-select: text; -webkit-user-select: text;
}
/* composing only: an empty run keeps a target to double-click, so a
   slide with no sub-heading can still be given one without the panel */
body[data-stage="compose"] .gfx-slide [data-field].is-empty::before {
  content: attr(data-placeholder);
  opacity: .32;
  font-style: italic;
}
body[data-stage="compose"] .gfx-slide [data-field] { cursor: text; }

/* while a run is being typed into, the gizmo's grab-arms stand down —
   they are invisible and several pixels wide, and they lie exactly over
   the words */
body.gfx-typing .gw-gizmo,
body.gfx-typing .gw-hit,
body.gfx-typing .gw-giz-css { pointer-events: none !important; }

/* ══ PAGES AND THE TOUR ═════════════════════════════════════════════
   The tour list is a list like every other one in the build — same row,
   same grip, same flags column — with three things added that only a
   tour needs: a stop number, a "nothing framed on this yet" state, and
   a strip you can drop onto. */

/* A THING WITH NO SHOT ON IT. Not an error and not greyed out: it is a
   normal half-built state, and it is marked on the row because the list
   is where the author is looking while they build. A tour that reaches
   it will arrive and not move, which is the one fact worth saying. */
.gfx-item.is-unset .n em { color: var(--warn); opacity: .9; }
.gfx-item.is-unset .i { color: var(--warn); }

/* A STOP POINTING AT SOMETHING THAT IS GONE. Shown rather than swallowed
   — quietly dropping it is how a tour silently gets shorter. */
.gfx-item.is-dead { opacity: .75; }
.gfx-item.is-dead .i, .gfx-item.is-dead .n b { color: var(--warn); }

/* THE STOP NUMBER. A tour IS an order, so the position is the one number
   worth printing — mono, so a ten-stop list stays in one straight
   column, and dim, because it is a label and not a control. */
.gfx-stopn {
  flex: 0 0 auto; min-width: 15px; text-align: right;
  font-family: var(--mono); font-size: 10.5px; color: var(--ink-3);
}
.gfx-item.is-live .gfx-stopn { color: var(--acc); }

/* WHERE YOU DROP. It is always there rather than appearing mid-drag,
   because a target that only exists once you are already dragging
   cannot be found by someone who does not know it is there. */
.gfx-tourdrop {
  border: 1px dashed var(--ink-4); border-radius: var(--r-ctl);
  padding: 8px 10px; margin: 6px 0 2px;
  color: var(--ink-3); font-size: 11.5px; line-height: 1.5; text-align: center;
  transition: border-color .12s, color .12s, background .12s;
}
.gfx-tourdrop b { color: var(--ink-2); font-weight: 500; }
.gfx-tourdrop.is-empty { text-align: left; }
.gfx-tourdrop.is-over { border-color: var(--acc); color: var(--ink-1); background: rgb(201 162 39 / .10); }
.gfx-tourlist.is-over { box-shadow: inset 0 0 0 1px var(--acc); border-radius: var(--r-ctl); }

/* WHAT IS IN YOUR HAND while you carry a row to the tour. It follows the
   pointer and MUST NOT BE UNDER IT — elementFromPoint is how the drop
   finds its target, and a ghost that catches the ray would report itself
   as the thing under the pointer and no drop would ever land. */
.gfx-carry {
  position: fixed; z-index: 9999; pointer-events: none;
  transform: translate(12px, 10px);
  background: var(--ink-5); border: 1px solid var(--acc);
  border-radius: var(--r-ctl); padding: 5px 9px;
  color: var(--ink-1); font-size: 11.5px;
  box-shadow: 0 8px 22px rgb(0 0 0 / .5);
}

/* the five ways into Pages sit three-and-two rather than two-by-two */
.gfx-btnrow--top.gfx-waysin { grid-template-columns: 1fr 1fr 1fr; }

/* A ROW IS A CONTROL, NOT A PARAGRAPH. Without this, dragging one into
   the tour starts a native text selection instead and Chrome answers by
   cancelling the pointer, so the drop never lands. `touch-action` is the
   same argument for a finger: a drag across a row must not be read as a
   scroll of the rail behind it. */
.gfx-item, .gfx-tourdrop {
  user-select: none; -webkit-user-select: none;
  touch-action: none;
}
/* except the name, while it is being renamed in place */
.gfx-item .nm.is-renaming { user-select: text; -webkit-user-select: text; }

/* ══ THE SLIDE BUILDER ══════════════════════════════════════════════
   OVER THE PICTURE, because glass is entirely what shows through it and
   cannot be judged against a dark rail. It is itself glass, for the same
   reason: the pane and the slide are standing on the same scan, so the
   pane is a working sample of the thing being built.

   Small, draggable, and it never takes the whole picture — a builder
   that covers what it is building is the problem it was made to fix. */
.gl-pane {
  position: absolute; left: 14px; bottom: 14px; z-index: 520;
  width: 268px; max-height: calc(100% - 28px);
  display: flex; flex-direction: column;
  background: rgb(11 10 9 / .62);
  backdrop-filter: blur(18px) saturate(1.25);
  -webkit-backdrop-filter: blur(18px) saturate(1.25);
  border: 1px solid rgb(242 238 230 / .16);
  border-radius: 12px;
  box-shadow: 0 18px 50px rgb(0 0 0 / .5), inset 2px 2px 1px -3px rgb(255 255 255 / .8);
  color: var(--ink-2); font-size: 11px;
  pointer-events: auto;
}
.gl-pane[hidden] { display: none; }

.gl-head {
  display: flex; align-items: center; gap: 7px;
  padding: 8px 8px 8px 10px;
  border-bottom: 1px solid rgb(242 238 230 / .10);
  cursor: grab; user-select: none;
}
body.gfx-dragging .gl-head { cursor: grabbing; }
.gl-head .gl-i { color: var(--acc); display: flex; }
.gl-head .gl-t { flex: 1 1 auto; color: var(--ink-1); letter-spacing: .04em; font-size: 10.5px; text-transform: uppercase; }
.gl-x {
  width: 20px; height: 20px; border: 0; border-radius: 4px; padding: 0;
  background: none; color: var(--ink-3); display: grid; place-items: center; cursor: pointer;
}
.gl-x:hover { background: rgb(242 238 230 / .10); color: var(--ink-1); }

.gl-body { overflow-y: auto; padding: 8px 10px 10px; }
.gl-who {
  color: var(--ink-1); font-size: 11.5px; margin-bottom: 7px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* ── THE PRESET CHIPS ──────────────────────────────────────────────
   EACH ONE IS WEARING ITS OWN BOX, drawn by the same applyBox that
   dresses the slide. No swatch, no screenshot: the chip IS the look,
   over the same scan the slide is standing on. */
.gl-chips { display: flex; flex-wrap: wrap; gap: 5px; margin-bottom: 9px; }
.gl-chip {
  font: inherit; font-size: 10px; letter-spacing: .03em;
  color: var(--ink-1); cursor: pointer;
  /* every visual property comes from applyBox — nothing here may set
     one, or a chip would stop telling the truth */
}
.gl-chip:hover { color: #fff; }

.gl-h {
  color: var(--ink-3); font-size: 9.5px; letter-spacing: .09em; text-transform: uppercase;
  margin: 10px 0 4px; padding-top: 7px;
  border-top: 1px solid rgb(242 238 230 / .08);
}
.gl-h:first-of-type { border-top: 0; padding-top: 0; }

.gl-row { display: flex; align-items: center; gap: 7px; height: 22px; }
.gl-row .gl-l { flex: 0 0 66px; color: var(--ink-3); }
.gl-row .gl-v {
  flex: 0 0 40px; text-align: right;
  font-family: var(--mono); font-size: 10px; color: var(--ink-2);
}
.gl-row input[type="range"] {
  flex: 1 1 auto; min-width: 0; height: 16px; margin: 0;
  accent-color: var(--acc); cursor: pointer;
}
.gl-row input[type="checkbox"] { accent-color: var(--acc); cursor: pointer; margin: 0; }
.gl-tint { flex: 1 1 auto; display: flex; align-items: center; gap: 6px; min-width: 0; }
.gl-sw {
  flex: 0 0 22px; width: 22px; height: 16px; padding: 0;
  border: 1px solid rgb(242 238 230 / .22); border-radius: 3px;
  background: none; cursor: pointer;
}
.gl-sel {
  flex: 1 1 auto; min-width: 0; font: inherit; font-size: 10.5px;
  background: rgb(0 0 0 / .35); color: var(--ink-1);
  border: 1px solid rgb(242 238 230 / .14); border-radius: 4px;
  padding: 2px 4px; cursor: pointer;
}

.gl-btn {
  display: block; width: 100%; margin-top: 9px; font: inherit; font-size: 10.5px;
  background: rgb(242 238 230 / .07); color: var(--ink-2);
  border: 1px solid rgb(242 238 230 / .16); border-radius: 5px;
  padding: 6px 8px; cursor: pointer;
}
.gl-btn:hover { border-color: var(--acc); color: var(--ink-1); }
.gl-off, .gl-note { color: var(--ink-3); font-size: 10.5px; line-height: 1.5; margin-top: 8px; }
.gl-off b { color: var(--ink-2); font-weight: 500; }
.gl-note { padding-top: 8px; border-top: 1px solid rgb(242 238 230 / .08); }

/* ══ GUIDES ═════════════════════════════════════════════════════════
   THE AXIS IS A COLOUR, and the same three colours the gizmo's arms
   already use — red X, green Y, blue Z. An author who has dragged an
   arrow once already knows which is which, so the buttons and the rows
   need no other label. */
.gfx-ax { border-left-width: 3px; }
.gfx-ax--x { border-left-color: #ff4d4d; }
.gfx-ax--y { border-left-color: #5dd25d; }
.gfx-ax--z { border-left-color: #5b9dff; }
/* ARMED IS OBVIOUS. A mode you are in without being told is the thing
   that makes a click-to-place tool feel broken — you click, something
   unexpected happens, and nothing ever said you were armed. */
.gfx-ax.is-on {
  background: var(--acc); border-color: var(--acc); color: #17130a; font-weight: 600;
}
.gfx-ax.is-on:hover { filter: brightness(1.08); color: #17130a; }
/* and the picture says so too, all the way to the pointer */
body.gfx-arming #stage { box-shadow: inset 0 0 0 2px var(--acc); }
body.gfx-arming #application-canvas { cursor: crosshair; }

.gfx-guide select {
  flex: 0 0 82px; font: inherit; font-size: 11px;
  background: var(--ink-6, rgb(0 0 0 / .3)); color: var(--ink-1);
  border: 1px solid var(--ink-4); border-radius: var(--r-ctl); padding: 3px 4px;
}
.gfx-guide { border-left: 3px solid transparent; padding-left: 5px; }
.gfx-guide--x { border-left-color: #ff4d4d; }
.gfx-guide--y { border-left-color: #5dd25d; }
.gfx-guide--z { border-left-color: #5b9dff; }

/* THE TICKED ORDER, ON THE ROW. Ctrl-clicking down a list in the order
   you want to visit is how a tour actually gets built, so the order has
   to be visible WHILE you build it — not revealed after the fact by
   whatever lands in the Tour panel. */
.gfx-tick {
  flex: 0 0 auto; min-width: 15px; height: 15px; padding: 0 3px;
  display: grid; place-items: center;
  border-radius: 8px; background: var(--acc); color: #17130a;
  font-family: var(--mono); font-size: 9.5px; font-weight: 700;
}

/* ── BUILDING ONE BUTTON ───────────────────────────────────────────
   Three short rows rather than a wide grid: the rail is 330 px and a
   dropdown, a label and a target do not fit across it without every
   one of them becoming too small to read. */
.gfx-btnspec {
  border: 1px solid var(--ink-5); border-radius: var(--r-ctl);
  padding: 6px 7px; margin-bottom: 5px; background: rgb(0 0 0 / .18);
}
.gfx-btnspec.is-off { opacity: .5; }
.gfx-btnspec-h { display: flex; align-items: center; gap: 6px; }
.gfx-btnspec-h .gfx-grip { color: var(--ink-3); display: flex; }
.gfx-btnspec-h input[type="checkbox"] { accent-color: var(--acc); cursor: pointer; margin: 0; }
.gfx-btnspec-label {
  flex: 1 1 auto; min-width: 0; font: inherit; font-size: 11.5px;
  background: rgb(0 0 0 / .3); color: var(--ink-1);
  border: 1px solid var(--ink-4); border-radius: 4px; padding: 3px 6px;
}
.gfx-btnspec-h button {
  flex: 0 0 auto; width: 22px; height: 22px; padding: 0;
  background: none; border: 0; border-radius: 4px;
  color: var(--ink-3); display: grid; place-items: center; cursor: pointer;
}
.gfx-btnspec-h button:hover { background: var(--ink-5); color: var(--warn); }
.gfx-btnspec-r { display: flex; gap: 5px; margin-top: 5px; }
.gfx-btnspec-r select, .gfx-btnspec-r input {
  flex: 1 1 auto; min-width: 0; font: inherit; font-size: 11px;
  background: rgb(0 0 0 / .3); color: var(--ink-1);
  border: 1px solid var(--ink-4); border-radius: 4px; padding: 3px 4px; cursor: pointer;
}
.gfx-btnspec-r select[data-f="style"] { flex: 0 0 82px; }
.gfx-btnspec-says {
  margin-top: 5px; color: var(--ink-3); font-size: 10.5px; line-height: 1.4;
}

/* A WARNING IN A PANEL. Amber, not red: an author who ticks walk before
   building the floor has not done anything wrong, they have done the
   two things in the order that makes sense to them. Being told is
   useful; being stopped is not. */
.gfx-empty.gfx-warn {
  border-left: 3px solid var(--warn);
  padding-left: 8px; margin: 6px 0;
  color: var(--ink-2);
}
.gfx-empty.gfx-warn b { color: var(--warn); }

/* ══ PHASE 1 — METRES: the grid's labels, the datum, calibrate ═══════
   The grid itself is drawn by the engine (app.drawLines, faded with
   distance). Only the two axis letters and the legend are DOM, projected
   every frame the way slides are. Workshop only. */
.gfx-grid-labels { position: absolute; inset: 0; pointer-events: none; z-index: 41; }
body[data-stage="present"] .gfx-grid-labels { display: none !important; }
.gfx-grid-ax {
  position: absolute; left: 0; top: 0; margin: -9px 0 0 6px;
  font: 600 11px/18px system-ui, sans-serif; letter-spacing: .08em;
  padding: 0 5px; border-radius: 3px; background: rgba(8,8,12,.55);
}
.gfx-grid-ax--x { color: #ff7a70; }
.gfx-grid-ax--z { color: #7fb0ff; }
.gfx-grid-legend {
  position: absolute; left: 10px; bottom: 10px;
  font: 10.5px/16px system-ui, sans-serif; letter-spacing: .06em; text-transform: uppercase;
  color: var(--ink-3); background: rgba(8,8,12,.45); padding: 1px 7px; border-radius: 3px;
}

/* the frame line in The world panel, and a scan that is not calibrated */
.gfx-frame b { color: var(--ink-1); }
.gfx-uncal b { color: var(--warn); }
.gfx-datum.is-legacy b { color: var(--warn); }

/* calibrate: the little form that appears after the two clicks */
.gfx-cal { border: 1px solid var(--acc-2); border-radius: var(--r-ctl); padding: 8px; margin: 6px 0; }
.gfx-cal__step { font-size: 11.5px; line-height: 1.45; color: var(--ink-2); margin: 2px 0 6px; }
.gfx-cal__step b { color: var(--ink-1); }
.gfx-cal__row { display: flex; align-items: center; gap: 8px; margin: 4px 0; font-size: 11px; color: var(--ink-2); }
.gfx-cal__row span { flex: 1 1 auto; }
.gfx-cal__row input[type="number"] {
  width: 84px; background: var(--ink-5); color: var(--ink-1); border: 1px solid var(--ink-4);
  border-radius: 4px; padding: 3px 6px; font: 12px system-ui, sans-serif;
}
.gfx-cal__tick input { order: -1; }
.gfx-cal__step.is-done { color: var(--ink-3); }
.gfx-cal__step.is-now { color: var(--ink-1); border-left: 2px solid var(--acc); padding-left: 6px; }
.gfx-btn.is-on { background: var(--acc); border-color: var(--acc); color: #17130a; font-weight: 600; }
