/* ═══════════════════════════════════════════════════════════════════════════
   SPECTER — chrome.css
   Brief #6: fullscreen editor, viewport tool stack, foot bar, drone pad,
   account and language popovers, and the responsive behaviour down to a phone.
   (Brief #41 / §52.1 — the icon rail down the left edge is gone; everything it
   held stands in the tab bar, the project bar and the account menu.)
   §17.7 §17.8 §17.9 §17.10 §17.11 §17.12 §17.13 §17.14 §17.15
   Loaded after app.css, so it is allowed to override it.
   ═════════════════════════════════════════════════════════════════════════ */

/* ── §17.8 fullscreen editor ──────────────────────────────────────────────
   The editor fills the window. It is a class on <body>, so the project bar and
   the tab bar slide away instead of the editor being re-parented — no re-mount,
   no lost WebGL context, no reloaded model.                                 */
.projbar, .tabbar {
  transition: max-height var(--t-3) var(--ease), opacity var(--t-1) var(--ease),
              transform var(--t-3) var(--ease), padding var(--t-3) var(--ease);
  max-height: 220px;
}
/* §29.7 — traka kartica je natpis, ne površina. Visinu joj daje tekst i
   ništa drugo: sve u njoj je centrirano po sredini i ništa se ne rasteže na
   visinu najvišeg suseda. Mereno pre: 109 px, od čega 74 px praznog. */
.tabbar { align-items: center; min-height: 44px; }
.tabbar > * { align-self: center; }
.tabbar > button { flex: 0 0 auto; }
/* dugmad koja `chrome.js` dodaje na kraj trake stoje uz desnu ivicu */
.tabbar > .chrome-client { margin-left: auto; }
/* §31.2 — traka kartica se PRELAMA, ne kliza. `.tabs` u core.css nosi
   `overflow-x:auto`, pa je na uskom ekranu pola sekcija bilo iza poteza
   prstom u stranu koji niko ne zna da postoji: mereno na 844×390 traka je
   tražila 1098 px u prozoru od 786 — „Klijent" presečen, a QR / AR,
   Komentari i Ponuda 294 px van ekrana. Ovde nema tačke preloma: gde staje
   u jedan red, ostaje jedan red (mereno 44 px na 1920), a gde ne staje,
   prelomi se (65 px na 844×390, 109 px na 390×844) i sve je vidljivo. */
/* ══════════════ §38.2 – §38.4 — KLIZNA TRAKA ═══════════════════════════
   Ovde je pisalo `flex-wrap: wrap` — traka se prelamala u dva i tri reda čim
   je ekran uzak. To je bilo bolje od nevidljivog klizanja, ali nije bilo
   dobro: tri reda kartica pojedu trećinu telefona pre nego što se ijedan
   komad vidi.

   Sada je JEDAN red koji kliza, i to se VIDI: traka bledi na strani na kojoj
   ima još sadržaja, vuče se prstom, mišem (prevlačenje) i točkićem. Bledi
   kraj je jedina razlika između „kliza" i „nema ničega dalje" — bez njega je
   ovo isti kvar od pre (§31.2).

   Maska se stavlja SAMO na trake koje nemaju iskačuću decu: maska pravi novi
   kontekst isecanja, pa bi meni „+ Novi projekat" nestao iza svoje trake —
   to je bio §29.2. Zato traka projekta i dalje ostaje `overflow:visible`, a
   kliza njena grupa dugmadi. */
.slidebar { flex-wrap: nowrap !important; overflow-x: auto; overflow-y: hidden;
  scrollbar-width: none; -ms-overflow-style: none; overscroll-behavior-x: contain;
  scroll-behavior: smooth; }
.slidebar::-webkit-scrollbar { width: 0; height: 0; display: none; }
.slidebar > * { flex: 0 0 auto; }
.slidebar.is-drag { scroll-behavior: auto; cursor: grabbing; user-select: none; }
.slidebar.can-r { mask-image: linear-gradient(90deg, #000 calc(100% - 36px), transparent);
  -webkit-mask-image: linear-gradient(90deg, #000 calc(100% - 36px), transparent); }
.slidebar.can-l { mask-image: linear-gradient(90deg, transparent, #000 36px);
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 36px); }
.slidebar.can-l.can-r {
  mask-image: linear-gradient(90deg, transparent, #000 36px, #000 calc(100% - 36px), transparent);
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 36px, #000 calc(100% - 36px), transparent); }
/* na dodirnom ekranu prst već zna šta radi; kod miša pokazivač to kaže */
@media (pointer: fine) { .slidebar.can-l, .slidebar.can-r { cursor: grab; } }

#tabbar { overflow: visible; }
#tabbar.slidebar { overflow-x: auto; }

/* §29.2 — traka projekta NE SME da iseče svoju decu: meni „+ Novi projekat"
   visi iz nje, a `overflow` na roditelju pravi novi kontekst isećanja i meni
   nestaje iza trake bez obzira na `z-index`. Mereno: `elementFromPoint` na
   vrhu otvorenog menija vraćao je dugme ispod njega, ne meni. */
.projbar { overflow: visible; }
.projbar .newwrap { position: relative; z-index: 130; }
/* §52.1 — `.app` više nema šta da animira u kolonama: jedna je i uvek 1fr.
   Prelaz preko `grid-template-columns` je pratio traku ikonica koja se širila
   pri prelasku mišem; trake nema, pa nema ni prelaza koji je držao. */

/* §52.1 R7 — `min-height` UVEK pobedi `max-height`, i to je ovde gutalo ceo
   posao. Traka projekta nosi `min-height:52px`, traka kartica `min-height:44px`
   (a od §53.3 i njena dugmad 44 px na dodiru), pa je `max-height:0` bilo
   primenjeno — `getComputedStyle` ga je uredno vraćao — a visina ostajala.
   Mereno na 1440 × 900: prikaz 610 → 640 px umesto 610 → 736.
   Zato se ovde OBE mere spuštaju na nulu; bez `min-height:0` gornja tri reda
   ne rade ništa. */
.app-body.editor-full .projbar,
.app-body.editor-full .tabbar {
  max-height: 0; min-height: 0; opacity: 0; padding-top: 0; padding-bottom: 0;
  overflow: hidden; transform: translateY(-8px); pointer-events: none;
}
/* i dugmad u njima, koja od §53.3 nose svojih 44 px */
.app-body.editor-full .projbar button,
.app-body.editor-full .tabbar button,
.app-body.editor-full .tabbtn { min-height: 0; }
.app-body.editor-full .app-content { padding: 0; }
.app-body.editor-full .viewport { border-radius: 0; border-width: 0; }

/* the exit affordance only exists while fullscreen is on.
   §31.2 — parkira se NA SVOM MESTU, ne iznad ivice. `translateY(-140%)` ga je
   izbacivao iz `.viewport`, koji iseca (`overflow:hidden`), pa je na svakoj od
   sedam mera stajalo „viri 27 px". Nevidljivo dugme se ne vidi ni ovako ni
   onako, a ovako ne visi iz svog roditelja i ne prima klik dok je ugašeno. */
.full-exit {
  position: absolute; top: 10px; left: 50%;
  transform: translateX(-50%) translateY(-8px) scale(.96);
  z-index: 30; display: flex; align-items: center; gap: 8px;
  padding: 6px 14px; border-radius:var(--r-pill); font-size:var(--fs-12); font-weight: 600;
  background: color-mix(in srgb, var(--ink) 90%, transparent); color: var(--on-ink);
  transition: transform var(--t-2) var(--ease), opacity var(--t-1) var(--ease);
  opacity: 0; pointer-events: none;
}
.app-body.editor-full .full-exit { transform: translateX(-50%); opacity: 1; pointer-events: auto; }
.app-body.editor-full .viewport:hover .full-exit { opacity: 1; }

/* ── §17.10 tool rail: four essentials, then an expander ──────────────────
   The stack used to run past the bottom of the window on a laptop and hide
   behind the foot bar. Only the tools a joiner touches constantly are out;
   the rest are behind the arrow, and the stack is height-capped so it can
   never reach the foot bar.                                                */
.vp-tools { max-height: calc(100% - 122px); }
.vp-tools.collapsed .rest { display: none !important; }
/* ── §41.7 — dugme „još alata" mora da OSTANE na dohvat ─────────────────────
   Mereno pre: na 1440 px prvi klik otvara traku (4 → 20 alata), a drugi ne
   zatvara ništa (20 → 20). Razlog je da otvorena traka počne da KLIZA unutar
   svoje ćelije, pa dugme siđe ispod donje ivice — `getBoundingClientRect` i
   dalje vraća pravougaonik, ali na tom mestu klik pada na omotač koji seče.

   Probano je lepljivo dno (`position:sticky; bottom:0`) i izmereno da ne radi:
   dugme je završavalo na y=857 dok je sama traka bila 188…578, dakle vezalo se
   za prozor umesto za traku. Rešenje je jednostavnije i bolje za oko — otvorena
   traka se PRELAMA U KOLONE umesto da kliza. Ništa ne izlazi iz vidnog polja,
   pa nema šta ni da se lepi.                                                */
.vp-hud .z-l > #vp-tools:not(.collapsed) {
  flex-wrap: wrap !important; overflow: visible; max-height: 100%;
}
/* U prelomljenoj traci `width:100%` znači „širina cele trake", a ne „širina
   kolone" — dugme je izlazilo iz nje i završavalo nad platnom: **mereno,
   `#vp-more` na x=483…617 dok traka staje na 528, i `elementFromPoint` vraća
   `canvas`.** U prelomu je široko koliko i alat pored njega. */
.vp-hud .z-l > #vp-tools:not(.collapsed) > .vp-more { width: 42px; }

/* ══ T2c — ALATNICA CRTA VAN SVOJE ZONE, i to već SKLOPLJENA ═══════════════
   `#vp-tools` (7 dugmadi sklopljeno: poništi, vrati, 4 osnovna alata, „još
   alata") nosi i klasu `.slidebar` (§38.2 — `chrome.js` je dodaje svakoj
   traci sa liste, jer je traka NA TELEFONU vodoravna i stvarno klizi). Ta
   klasa piše `flex-wrap:nowrap !important`, jače od običnog `flex-wrap:wrap`
   koji ovaj fajl već ima niže (red sa `column-gap`) — pa se traka NIKAD nije
   prelamala u kolone dok je sklopljena, samo dok je razvijena
   (`:not(.collapsed)` gore ima sopstveni `!important` koji parira slajdbaru).
   Sadržaj (302–309 px za 7 dugmadi) je onda crtao preko `overflow:visible`
   niz platno i preko panela ispod, u istoj koloni.

   Izmereno uživo (editor ploče otvoren, isti raspored kao gore): sedmo
   dugme („još alata") crtalo je 93 px preko panela na 1440×900, 188 px na
   1024×768, 14 px na 1920×1080. Popravka vraća prelamanje TAČNO tamo gde ga
   `:not(.collapsed)` iznad već ima — samo za `.collapsed`, i samo van
   telefonske širine/visine (isti uslov kao `.vp-hud .z-l{display:contents}`
   u telefonskom preseku, obrnut, da vodoravna traka na telefonu ostane
   netaknuta). Izmereno posle: 0 px preko panela na sve tri širine (−16 do
   −27 px, tj. razmak), 0 zaklonjenih dugmadi (`elementFromPoint` na svih
   7). */
@media (min-width: 761px) and (min-height: 561px) {
  .vp-hud .z-l > #vp-tools.collapsed { flex-wrap: wrap !important; }
  .vp-hud .z-l > #vp-tools.collapsed > .vp-more { width: 42px; }
}
.vp-more {
  display: flex; align-items: center; justify-content: center;
  width: 100%; height: 24px; margin-top: 3px; border-radius: var(--r-6);
  color: var(--mut); background: var(--surface-4); font-size:var(--fs-12);
  transition: background var(--t-1), color var(--t-1), transform var(--t-1) var(--ease);
  flex: 0 0 auto;
}
.vp-more:hover { background: var(--acc-soft); color: var(--acc); }
.vp-tools:not(.collapsed) .vp-more { transform: rotate(180deg); }

/* ── §17.15 orbit hint, snap chips and zoom in one translucent foot bar ── */
.vp-foot {
  position: absolute; left: 0; right: 0; bottom: 0; top: auto; z-index: 14;
  display: flex; align-items: center; gap: 8px; flex-wrap: nowrap;
  padding: 7px 10px calc(7px + var(--safe-b));
  background: color-mix(in srgb, var(--surface) 60%, transparent);
  backdrop-filter: blur(12px) saturate(1.25);
  -webkit-backdrop-filter: blur(12px) saturate(1.25);
  border-top: 1px solid color-mix(in srgb, var(--line) 70%, transparent);
  overflow-x: auto; overflow-y: visible; scrollbar-width: none;
}
.vp-foot::-webkit-scrollbar { display: none; }
.vp-foot > * { flex: 0 0 auto; }
.vp-foot #tool-hint {
  border: 0; background: transparent; color: var(--mut-2); font-size:var(--fs-11);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  flex: 1 1 auto; min-width: 60px;
}
/* the two snap chips are settings, not decoration — make them read */
#snap-chip, #rot-chip {
  border-color: var(--acc-line-2); color: var(--acc); font-weight: 600;
  background: color-mix(in srgb, var(--acc) 8%, transparent);
}
#snap-chip.off { border-color: var(--border); color: var(--mut); background: transparent; }

/* ══ §41.10 — ČIP JE PREKIDAČ, POLJE JE BROJ ═══════════════════════════════
   Čip je do sada pisao i broj („SNAP 32 mm", „⟳ 15°"). Otkad broj stoji u
   polju pored njega, to je ista vrednost napisana dvaput — i skupo je: dva
   čipa i dva polja tražili su 810 px u donjoj traci široj 712 px na 1440,
   pa je `node tools/fit.js --only app` javio šest nedohvatljivih kontrola
   („1", „5", „15", „45", polje rotacije i „−" za umanjenje), izguranih pod
   desni panel i pod ručku. Čip zato zadržava svoj JEDINI posao — snap je
   prekidač, rotacija otvara puni spisak koraka — i to kaže znakom i opisom.
   Tekst čipova i dalje piše `ui.js`; ovde se samo ne prikazuje, jer isti
   podatak stoji čitljivije dva santimetra desno. */
#snap-chip, #rot-chip { font-size: 0; padding: 0 9px; }
#snap-chip::after { content: '⌗'; font-size: var(--fs-14); }
#rot-chip::after { content: '▾'; font-size: var(--fs-12); }
#snap-chip.off::after { opacity: .55; }
.snap-edit {
  width: 78px; height: 26px; padding: 0 7px; font-family: var(--mono);
  font-size:var(--fs-12); text-align: center; border: 1px solid var(--acc);
  border-radius: var(--r-6); background: var(--surface); color: var(--ink);
}

/* ══ §41.10 — SNAP I ROTACIJA IMAJU POLJE KOJE SE VIDI ═══════════════════════
   Do sada se korak menjao duplim klikom na čip (`editableChip`) — potez koji
   niko ne pronađe, i vlasnik ga nije pronašao. Sada pored oznake stoji pravo
   polje: ukucaš broj, `Enter` primeni, vrednost se pamti. Uz njega četiri
   koraka koja stolar zaista koristi, jedan pritisak svaki:
       SNAP  1 · 8 · 16 · 32 mm     (debljina ploče i sistem 32)
       ROT   1 · 5 · 15 · 45 °      (kosine, ger i četvrt kruga)              */
.stepf {
  display: flex; align-items: center; gap: 4px; flex: 0 0 auto;
  height: 26px; padding: 0 5px 0 7px; border-radius: var(--r-pill);
  border: 1px solid var(--acc-line-2);
  background: color-mix(in srgb, var(--acc) 8%, transparent);
}
.stepf-l {
  font-family: var(--mono); font-size:var(--fs-9); letter-spacing: .12em;
  color: var(--acc); font-weight: 700;
}
/* `.vp-foot` ispred nije ukras nego jedini način da ovo uopšte važi: u
   `core.css` stoji `input[type=text]{ width:100%; padding:13px 14px; … }`, a
   to je specifičnije od gole klase. **Mereno: polje je bilo široko 215 px
   umesto 46, pa je donja traka tražila 871 px u prikazu od 698 — otuda
   nedohvatljivi „−" i „+" u `fit.js`.** */
.vp-foot .stepf-i {
  width: 46px; height: 20px; padding: 0 4px; text-align: center;
  font-family: var(--mono); font-size:var(--fs-11); color: var(--ink);
  border: 1px solid var(--line); border-radius: var(--r-5);
  background: var(--surface); -moz-appearance: textfield; flex: 0 0 auto;
}
.vp-foot .stepf-i::-webkit-outer-spin-button,
.vp-foot .stepf-i::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.vp-foot .stepf-i:focus { outline: 0; border-color: var(--acc); box-shadow: 0 0 0 2px var(--acc-soft); }
.stepf-u { font-family: var(--mono); font-size:var(--fs-9); color: var(--mut); }
.stepf-q { display: flex; align-items: center; gap: 2px; }
.stepf-q button {
  min-width: 22px; height: 18px; padding: 0 4px; border: 0; border-radius: var(--r-5);
  background: transparent; color: var(--mut-2); cursor: pointer;
  font-family: var(--mono); font-size:var(--fs-9); line-height: 1;
  transition: background var(--t-1), color var(--t-1);
}
.stepf-q button:hover { background: var(--surface-3); color: var(--ink); }
.stepf-q button.on { background: var(--acc); color: var(--on-solid); }
/* Brzi izbor je dodatak, polje je zahtev. Donja traka je široka koliko i 3D
   prikaz, a on je na 1440 px sa oba panela otvorena širok 712 px — u njega su
   dva polja SA brzim izborom tražila 810 px, pa je `node tools/fit.js --only
   app` javio da su „1 · 5 · 15 · 45", polje rotacije i dugmad za uvećanje
   izgurani pod desni panel i pod ručku. Zato brzi izbor izlazi tek kad prikaz
   ima mesta za njega; upis radi na svakoj širini. */
@media (max-width: 1600px) { .stepf-q { display: none; } }

/* ── §17.11 drone flight pad ─────────────────────────────────────────── */
.vp-drone {
  position: absolute; right: 14px; bottom: 62px; z-index: 16;
  display: none; grid-template-columns: repeat(3, 38px); grid-template-rows: repeat(3, 38px);
  gap: 4px; opacity: 0; transform: scale(.9); transform-origin: 100% 100%;
  transition: opacity var(--t-1) var(--ease), transform var(--t-1) var(--ease);
}
.vp-drone.on { display: grid; opacity: 1; transform: none; }
.vp-drone button {
  display: flex; align-items: center; justify-content: center; font-size:var(--fs-15);
  border-radius: var(--r-8); color: var(--ink-3);
  background: color-mix(in srgb, var(--surface) 80%, transparent);
  border: 1px solid var(--line);
  backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px);
  transition: background var(--t-0), color var(--t-0), transform var(--t-0);
}
.vp-drone button:active { background: var(--acc); color: var(--on-solid); transform: scale(.94); }
.vp-drone .up { grid-area: 1/2; }  .vp-drone .left  { grid-area: 2/1; }
.vp-drone .down { grid-area: 3/2; } .vp-drone .right { grid-area: 2/3; }
.vp-drone .rise { grid-area: 1/3; } .vp-drone .sink  { grid-area: 3/3; }
.vp-drone .mid { grid-area: 2/2; font-family: var(--mono); font-size:var(--fs-9); color: var(--mut); }

/* ── §17.13 account top-right · §17.14 language bottom-left ───────────── */
.chrome-tr {
  position: fixed; top: calc(9px + var(--safe-t)); right: calc(13px + var(--safe-r));
  z-index: 60; display: flex; align-items: center; justify-content: center;
}
.chrome-bl {
  position: fixed; left: calc(13px + var(--safe-l)); bottom: calc(13px + var(--safe-b));
  z-index: 60; display: flex; align-items: center; justify-content: center;
}
/* The control is centred inside whatever slot it sits in. Note this must NOT
   set `position`: .chrome-tr / .chrome-bl carry the same element and are
   `fixed`; a later `position:relative` here would win on equal specificity
   and drop both controls back into the page flow. Being fixed already makes
   them the containing block for the popover. */
.pop-host { display: flex; align-items: center; justify-content: center; }
.pop-btn {
  display: flex; align-items: center; justify-content: center; gap: 7px;
  height: 38px; padding: 0 12px; border-radius: var(--r-pill);
  border: 1px solid var(--line);
  background: color-mix(in srgb, var(--surface) 88%, transparent);
  backdrop-filter: blur(12px) saturate(1.2); -webkit-backdrop-filter: blur(12px) saturate(1.2);
  box-shadow: var(--sh-1); color: var(--ink); font-size:var(--fs-13); font-weight: 600;
  transition: border-color var(--t-1), box-shadow var(--t-1), transform var(--t-0);
}
.pop-btn:hover { border-color: var(--border-2); box-shadow: var(--sh-2); }
.pop-btn:active { transform: scale(.97); }
/* ══ §42.6 — KRUG NALOGA IMA BELU I TAMNU POLOVINU ══════════════════════════
   Bio je jedna puna tamna tačka na svetloj traci i nestajao je u tamnoj temi.
   Sada je krug presečen po sredini: leva polovina je boja podloge, desna boja
   mastila — i svako slovo inicijala stoji na svojoj polovini, u boji koja se
   na njoj čita. U tamnoj temi se polovine i slova zamene, pa je znak isti a
   kontrast ostaje na obe strane.                                            */
.pop-btn .ini {
  width: 24px; height: 24px; border-radius: 50%; overflow: hidden;
  display: grid; grid-template-columns: 1fr 1fr; place-items: stretch;
  font-size:var(--fs-10); font-weight: 700;
  border: 1px solid var(--ink); background: var(--surface);
}
.pop-btn .ini > i {
  display: grid; place-items: center; font-style: normal; line-height: 1;
}
.pop-btn .ini > i:first-child { background: var(--surface); color: var(--ink); }
.pop-btn .ini > i:last-child  { background: var(--ink);     color: var(--on-ink); }
html[data-theme=dark] .pop-btn .ini { border-color: var(--on-ink); background: var(--ink); }
html[data-theme=dark] .pop-btn .ini > i:first-child { background: var(--ink);    color: var(--on-ink); }
html[data-theme=dark] .pop-btn .ini > i:last-child  { background: var(--on-ink); color: var(--ink); }
.pop-btn .flag { font-size:var(--fs-17); line-height: 1; }
.pop-btn .cap { font-family: var(--mono); font-size:var(--fs-11); letter-spacing: .1em; text-transform: uppercase; }

/* ══ §41.11 / §27.4 — MENI IDE IZNAD SVEGA, I TO NIJE STVAR BROJA ═══════════
   Meni jezika je stajao na `z-index:61` unutar `.vp-hud`, koji sam ima
   `z-index:12` i `overflow:hidden`. Broj unutar tuđeg sloja ne znači ništa:
   **mereno, `elementFromPoint` na sredini otvorenog menija vraćao je `canvas`
   3D prikaza na 1440 px, `div.panel-bd` na 1024 i `div.insp` na 844.** Isto i
   za meni snapa (`div.z-br`) i za meni naloga (`p.tiny`).

   Zato se svaki iskačući meni, čim se otvori, **izmešta u fiksni sloj**:
   `position:fixed` i broj iz lestvice u `core.css` (`--z-pop`). Fiksan
   element ne pripada nijednom roditeljskom kontekstu slaganja i nijedan
   `overflow` ga ne seče. Isti potez je već dokazan na meniju „+ Novi
   projekat" (§29.2), samo je sada pravilo, a ne izuzetak. Položaj računa
   `Chrome.lift()` iz pravougaonika dugmeta, i drži ga u prozoru.            */
.pop {
  position: absolute; min-width: 244px; z-index: var(--z-pop);
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-12);
  box-shadow: var(--sh-4); padding: 6px; overflow: hidden;
  opacity: 0; pointer-events: none;
  transition: opacity var(--t-0) var(--ease), transform var(--t-0) var(--ease);
}
.pop.tr { top: calc(100% + 8px); right: 0; transform-origin: top right; transform: scale(.94) translateY(-6px); }
.pop.bl { bottom: calc(100% + 8px); left: 0; transform-origin: bottom left; transform: scale(.94) translateY(6px); }
.pop.open { opacity: 1; transform: none; pointer-events: auto; }

/* Jedan sloj za sve što iskoči — meni jezika, naloga, snapa, pogleda.
   `!important` na pomacima nije nemar: pravila koja ove menije vezuju za
   njihovo dugme (`.pop.bl{bottom:calc(100%+8px)}`, `.vv-menu{top:calc(100%+
   6px);right:0}`) imaju veću specifičnost, pa bi ostatak starog položaja
   preživeo i razvukao podignut meni preko pola ekrana. */
.pop.lifted, .menu-lift {
  position: fixed !important; z-index: var(--z-pop) !important;
  right: auto !important; bottom: auto !important;
  margin: 0 !important;
}
.pop.lifted { transform-origin: top left; overflow: auto; }
.pop.lifted.open { transform: none; }
.menu-lift { overflow: auto; }
/* Meni pogleda OSTAJE dete svog omotača — iz njega se klik na `[data-camera]`
   penje do `.vp-views`, koji ga i hvata. Fiksan položaj mu je dovoljan: nad
   njim nema roditelja sa `transform` ili `backdrop-filter`, pa ga `overflow`
   HUD-a ne seče. Ovo je razlika između „podigni" i „iščupaj": čupa se samo
   ono što stoji u traci sa `backdrop-filter`, jer ona jeste sadržalac. */
.pop-hd { padding: 9px 11px 10px; border-bottom: 1px solid var(--line-2); margin-bottom: 5px; }
.pop-hd .nm { font-size:var(--fs-14); font-weight: 700; letter-spacing: -.02em; }
.pop-hd .em { font-family: var(--mono); font-size:var(--fs-11); color: var(--mut); margin-top: 2px;
  overflow: hidden; text-overflow: ellipsis; }
.pop-item {
  display: flex; align-items: center; gap: 10px; width: 100%;
  padding: 9px 11px; border-radius: var(--r-8); font-size:var(--fs-14); color: var(--ink-3);
  transition: background var(--t-1), color var(--t-1); text-align: left;
}
.pop-item:hover { background: var(--surface-3); color: var(--ink); }
.pop-item.on { background: var(--acc-soft); color: var(--acc); font-weight: 600; }
.pop-item .ic { width: 18px; text-align: center; opacity: .75; font-size:var(--fs-14); }
.pop-item .sub { margin-left: auto; font-family: var(--mono); font-size:var(--fs-10); color: var(--mut); }
.pop-item.danger { color: var(--danger); }
.pop-item.danger:hover { background: var(--danger-soft); }
.pop-sep { height: 1px; background: var(--line-2); margin: 5px 7px; }
.pop-pane { padding: 2px 11px 10px; }
.pop-pane .row-kv { display: flex; justify-content: space-between; gap: 12px;
  font-size:var(--fs-13); padding: 6px 0; border-bottom: 1px solid var(--line-3); }
.pop-pane .row-kv b { font-weight: 600; }
.pop-back { display: flex; align-items: center; gap: 7px; padding: 7px 11px;
  font-size:var(--fs-12); color: var(--mut); }
.pop-back:hover { color: var(--ink); }
.lang-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 2px; }

/* ═══════════════ responsive — every size, down to a phone ═══════════════ */

@media (max-width: 1360px) {
  .editor { --w-left-open: 250px; --w-right-open: 292px; }
}

/* Narrow: the docks stop stealing width and float over the scene. This is
   what removes the "empty unused space" at this size — §17.7. */
@media (max-width: 1100px) {
  .editor { grid-template-columns: 0 1fr 0 !important; --rail-w: 10px; }
  .editor .dock[data-dock=left],
  .editor .dock[data-dock=right] {
    /* §21.8 — an overlay dock covers the SCENE, never the bottom dock.
       `bottom: 0` made it the full height of the editor, so the left and the
       right dock each lay across the bottom one — measured 320 × 210 and
       292 × 210 at 1100 px. The grid already knows where the bottom row
       starts, so the overlay stops exactly there. */
    position: absolute; top: 0; bottom: var(--h-bottom, 0px);
    /* §30.5 — širina preklopnog doka je bila zakucana na 320 px, pa promena
       veličine na tabletu i telefonu nije imala gde da se vidi ni kad bi je
       neko izvukao. Sada prati istu promenljivu koju piše `shell.js` — i
       svaka strana svoju, jer levi i desni panel nisu iste širine. */
    width: min(320px, 78vw); z-index: 20;
    background: var(--surface); border: 1px solid var(--line);
    border-radius: var(--r-12); box-shadow: var(--sh-3); padding: 6px;
    transition: transform var(--t-2) var(--ease);
  }
  .editor .dock[data-dock=left]  { left: 0;  width: min(var(--w-left-open, 320px), 78vw);
    transform: translateX(calc(-100% - 12px)); }
  .editor .dock[data-dock=right] { right: 0; width: min(var(--w-right-open, 320px), 78vw);
    transform: translateX(calc(100% + 12px)); }
  /* §30.5 — ručka mora da stoji na UNUTRAŠNJOJ ivici otvorenog preklopa.
     Preklopni dok (z-index 20) je pokrivao ručku (z-index 8) čim se otvori,
     pa se otvoren panel na tabletu i telefonu nije mogao ni uhvatiti — pritisak
     je padao na sam panel. **Mereno pre: 516 px → 516 px, bez ijedne promene.**
     Sklopljen dok je vraća na ivicu ekrana, gde se i izvlači. */
  .editor:not(.hid-left) .grab[data-grab=left] {
    left: min(var(--w-left-open, 320px), 78vw); z-index: 22;
  }
  .editor:not(.hid-right) .grab[data-grab=right] {
    right: min(var(--w-right-open, 320px), 78vw); z-index: 22;
  }
  .editor:not(.hid-left)  .dock[data-dock=left]  { transform: none; }
  .editor:not(.hid-right) .dock[data-dock=right] { transform: none; }
  .editor.hid-left  .dock[data-dock=left]  > .panel,
  .editor.hid-right .dock[data-dock=right] > .panel { opacity: 1; transform: none; }
  /* §31.2 — sklonjen dok se NE DODIRUJE. `translateX(-100% - 12px)` ga izbaci
     iz editora, ali ne i iz prozora: na 1024 px je njegova desna ivica padala
     tačno na tadašnju traku ikonica, pa su strelice „premesti panel" i polje za
     pretragu odgovarali na dodir kroz nju — mereno, `elementFromPoint` na
     njihovoj sredini vraćao je `#rail` (trake po §52.1 više nema, ali sklonjen
     panel i dalje ne sme da prima dodir). `visibility` se nasleđuje, pa jedno
     pravilo gasi ceo panel; 0 s odloženo za trajanje klizanja da se izlazak i
     dalje vidi, a ulazak je trenutan. */
  .editor.hid-left  .dock[data-dock=left],
  .editor.hid-right .dock[data-dock=right] {
    visibility: hidden;
    transition: transform var(--t-2) var(--ease), visibility 0s linear var(--t-2);
  }
  .editor:not(.hid-left)  .dock[data-dock=left],
  .editor:not(.hid-right) .dock[data-dock=right] {
    visibility: visible;
    transition: transform var(--t-2) var(--ease), visibility 0s linear 0s;
  }
  /* Kad donji dok nije otvoren, njegovih 210 px niko ne koristi — a bočni
     preklop ih je i dalje odbijao od svoje visine. Mereno na 844×390: dok
     visok 57 px u editoru od 267 px. */
  .editor.no-bottom .dock[data-dock=left],
  .editor.no-bottom .dock[data-dock=right] { bottom: 0; }
  .split-v { display: none; }
  .fx { display: none; }

  /* ══ §55.18 — PANEL UVEZENOG MODELA JE IZUZETAK ═══════════════════════════
     Ostali lebdeći paneli ispod 1100 px nestaju i to je u redu: sve što nude
     postoji i u dokovima. Panel uvezenog modela nema drugo mesto — jedinica
     izvornog fajla, dimenzije i poravnanje uz komad postoje SAMO u njemu.
     Dok je i on padao pod `.fx { display:none }`, na telefonu je imao visinu
     **0 px**: podešavanja uvezenog modela tamo nisu postojala, a čovek koji
     na telefonu uveze sken nema kako da mu zada razmeru.

     Ovde ne postaje mala kartica nego FIOKA UZ DONJU IVICU: puna širina,
     najviše 45 % visine ekrana, kliza se. Iznad donje trake, ne preko nje.
     Vidljiv je i dalje samo dok je model izabran (§54.12) — ovo menja GDE
     stoji, ne KADA. */
  #imp-panel {
    display: block;
    position: absolute;
    left: 8px; right: 8px; width: auto;
    top: auto; bottom: calc(56px + var(--safe-b, 0px));
    max-height: 45vh; overflow: auto;
    z-index: 16;                      /* iznad alatnice (15), ispod dijaloga */
    -webkit-overflow-scrolling: touch;
  }
  #imp-panel[hidden] { display: none; }
  /* Dugme za zatvaranje je na telefonu jedini izlaz iz panela, pa mora da se
     pogodi prstom. §53.3: najmanje 44 × 44 px, i to se meri. */
  #imp-panel .fx-hd { padding: 10px 12px; }
  #imp-panel .fx-hd .tool.mini {
    min-width: 44px; min-height: 44px;
    display: inline-flex; align-items: center; justify-content: center;
  }

  /* ══ §41.7 / §41.9 / §41.11 — ALATNICA I DONJA TRAKA ISPOD PANELA ═════════
     Ispod 1100 px bočni dokovi lebde preko scene (`z-index:20`), a ceo HUD —
     alatnica, donja traka, dugme za jezik — stoji na `z-index:12`. Dakle sve
     što se nudi nad prikazom bilo je IZA panela. Mereno na 1024×768,
     `elementFromPoint` na sredini kontrole:

         #vp-more  → div.panel-bd < div#dock-left.dock
         #btn-lang → div.panel-bd < div#dock-left.dock

     Zato „dugme za jezik ne radi" i zato se alatnica nije otvarala: klik je
     stizao do panela iznad njih. Dve stvari, obe potrebne:

       · HUD ide iznad preklopnog doka — on je kontrola nad prikazom, a dok je
         privremeni preklop koji se i sam sklanja;
       · i, što je važnije, HUD se SKLANJA otvorenom doku s puta, pa se ne
         preklapaju uopšte. Dok je zatvoren, HUD ima ceo prikaz.             */
  /* `.editor` ispred nije ukras: osnovno pravilo `.vp-hud{z-index:12}` stoji
     NIŽE u ovom fajlu, pa bi na jednakoj specifičnosti pobedilo ono, a ne ovo
     u medija-upitu. Jedna klasa više je ceo lek.

     Probano je i drugo rešenje — da se HUD UVUČE za širinu otvorenog doka, pa
     da se uopšte ne preklapaju. Mereno, ne radi: na 844×390 sa oba bočna doka
     otvorena ostane 64 px donje trake od 714, „⟳" korak odleti na x=859 u
     prozoru od 844, a traka alata (koja je na telefonu zaseban pojas pri dnu)
     se popne na donju traku. Preklop je privremen i sam se sklanja; HUD je
     stalan. Zato HUD stoji IZNAD, a ne pored. */
  .editor .vp-hud { z-index: 24; }
  /* …a ručke idu iznad i HUD-a. One su tanke crtice od 10 px i jedini način da
     se panel uhvati na dodirnom ekranu; otvorena traka alata je na telefonu
     pojas preko cele širine prikaza koji se prelama u redove do 40 vh, pa im
     legne tačno na hvat. **Mereno na 844×390, pošto se traka alata otvori:
     povlačenje leve ručke 300 px → 300 px, klik ne sklapa.** Broj se ponavlja
     na tri selektora jer svaki od njih već postoji sa svojih 22 i veće je
     specifičnosti od kratkog `.editor .grab`. */
  .editor .grab,
  .editor:not(.hid-left) .grab[data-grab=left],
  .editor:not(.hid-right) .grab[data-grab=right],
  .editor .grab.h,
  .editor.no-bottom .grab.h { z-index: 26; }
}

@media (max-width: 900px) {
  .projbar { padding: 8px 12px; gap: 8px; }
  .projbar-btns .btn { padding: 6px 9px; font-size:var(--fs-12); }
  .editor { --h-bottom-open: 168px; }
}

/* ── phone: the toolbar leaves the left edge and becomes a bottom strip you
      scroll sideways with a thumb. A different UX, as asked — §17.12. ──── */
@media (max-width: 760px) {
  /* §52.1 — „jedna staza, jedno dete" više nije izuzetak za telefon nego
     pravilo na svakoj širini; stoji u `app.css` uz `.app`. Ovde je ostalo samo
     ono što je stvarno vezano za usku širinu. */
  .app-content.scene-mode { padding: 6px 6px 0; }
  .tabbar { padding: 0 8px; }
  .tabbar button { font-size:var(--fs-13); padding: 8px 9px; }
  /* §31.1 — na telefonu se traka projekta PRELAMA umesto da kliza. Klizanje
     u stranu znači da „Sken prostora", „QR / AR" i „Ponuda" jednostavno **ne
     postoje** za nekoga ko ne pogodi da traku treba povući prstom — a upravo
     to se i desilo: na iPhone-u „nema menija ni sken prostora niti išta". */
  /* §38.3 — traka projekta i dalje sme da se prelomi (iz nje visi meni), ali
     njena grupa dugmadi kliza umesto da pravi novi red. */
  .projbar { padding: 7px 10px; flex-wrap: wrap; max-height: none; overflow: visible;
    row-gap: 6px; }
  .projbar-btns { width: auto; flex-wrap: nowrap; min-width: 0; padding-right: 0; }
  .projbar .proj { order: -1; width: 100%; }
  .projbar .spacer { display: none; }
  .pop { min-width: min(300px, 92vw); }
  .modal-card { max-height: 88dvh; }
}

/* ══ uzak ILI nizak ekran — jedan te isti raspored ═══════════════════════
   §31.2 — telefon položen (844×390) nije „širok ekran": visine ima 390 px,
   manje nego telefon uspravno ima širine. Sve što je ovde pisalo samo za
   `max-width:760px` važi i za njega, jer je isti problem okrenut za 90°:
   uspravna traka alata i donji dok fiksne visine ne staju. Pravila su ista,
   uslov je proširen — nema drugog rasporeda koji bi se održavao uz ovaj. */
@media (max-width: 760px), (max-height: 560px) {
  /* ── §22.27 — the menu below the editor stays reachable on a phone ─────
     It used to be `display:none` here: on a phone the bottom menu simply did
     not exist, which is not "down by default", it is gone. It is an overlay
     now — parked below the edge, and it slides up on the handle, on a tap, or
     on a swipe up from the bottom (§21.6 already routes that gesture). The
     grid row stays 0, so it never steals height from the model. */
  /* §31.2 — `--h-bottom-open` ovde ne radi ništa: `shell.js` ga piše u sam
     element (`style="--h-bottom-open:210px"`), a to nadjačava svaki list
     stila. Red se zato gasi u samom šablonu mreže. Mereno pre: donji dok je
     lebdeo preko scene, a mreža mu je i dalje čuvala 210 px — od 267 px
     koliko editor ima na 844×390. */
  .editor { --h-bottom-open: 0px; grid-template-rows: 1fr 0px; }
  .editor .dock[data-dock=left],
  .editor .dock[data-dock=right] { bottom: 0; }
  /* §41.7 — ručka donjeg panela je smela da se povuče, ali se to nigde nije
     videlo: visina je bila samo `max-height`, pa je panel merio svoj sadržaj i
     stajao na svom stropu bez obzira šta ručka radi. **Mereno na 844×390:
     203 px → 203 px posle povlačenja.** Visinu sada daje isti broj koji ručka
     piše (`--h-bottom-open`).
     Strop je usklađen sa `shell.js`: tamo je granica `innerHeight * .6`, ovde
     je pisalo 52 vh — pa je na 390 px visine panel već stajao na CSS stropu
     (203 px) dok je ručka mislila da ima do 234 px, i poslednjih 31 px se
     nikad nije video. Jedan broj, na oba mesta: 60 vh. */
  .editor .dock.dock-bottom {
    position: absolute; left: 0; right: 0; bottom: 0; z-index: 21;
    height: max(120px, min(var(--h-bottom-open, 210px), 60vh, 380px));
    max-height: min(60vh, 380px);
    background: var(--surface); border-top: 1px solid var(--line);
    border-radius: var(--r-12) var(--r-12) 0 0;
    box-shadow: var(--sh-3); padding: 6px 6px calc(6px + var(--safe-b));
    overflow: auto; -webkit-overflow-scrolling: touch;
    transform: translateY(calc(100% + 12px));
    transition: transform var(--t-2) var(--ease);
  }
  .editor:not(.no-bottom) .dock.dock-bottom { transform: none; }
  /* the handle is the only part that stays visible while it is down —
     §31.2: a upravo tada ga je `app.css` vraćao u tok (`.editor.no-bottom
     .grab[data-grab=bottom]{position:relative}`, četiri klase prema tri), pa
     je ručka padala u red visine 0 na samom dnu editora. Mereno na 390×844:
     ručka na y=844 u prozoru visokom 844 — jedini način da se donji meni
     otvori bio je van ekrana. */
  /* §41.7 — ručka se pomera IZNAD donje trake i sužava na svoju meru.
     Preko cele širine i na samom dnu ležala je tačno na `.vp-foot`, koji je u
     HUD-u (24) — **mereno na 390×844, `elementFromPoint` na sredini ručke
     vraćao je `div.vp-foot`, i povlačenje nije menjalo ništa: 210 px → 210
     px.** Puna širina joj i nije trebala: crtica je 48 px, a hvat od 160 px
     po sredini je više nego dovoljan prstu. Sada ništa ne pokriva i ništa je
     ne pokriva, pa sloj 26 samo potvrđuje ono što geometrija već rešava. */
  .editor .grab.h,
  .editor.no-bottom .grab.h {
    position: absolute; left: 50%; right: auto; transform: translateX(-50%);
    width: 160px; bottom: calc(40px + var(--safe-b)); height: 22px; z-index: 26;
    display: flex; align-items: center; justify-content: center;
  }
  .split-h { display: none; }

  .vp-tools {
    position: absolute; left: 0; right: 0; top: auto;
    bottom: calc(40px + var(--safe-b));
    max-height: none; height: 56px; width: auto;
    flex-direction: row; align-items: center; gap: 6px;
    padding: 6px 10px; margin: 0; border-radius: 0;
    overflow-x: auto; overflow-y: hidden; scrollbar-width: none;
    -webkit-overflow-scrolling: touch; scroll-snap-type: x proximity;
    background: color-mix(in srgb, var(--surface) 82%, transparent);
    backdrop-filter: blur(14px) saturate(1.3); -webkit-backdrop-filter: blur(14px) saturate(1.3);
    border-top: 1px solid var(--line);
  }
  .vp-tools::-webkit-scrollbar { display: none; }
  .vp-tools .tool { flex: 0 0 auto; width: 44px; height: 44px; font-size:var(--fs-19); scroll-snap-align: center; }
  .vp-tools .hud-sep { flex: 0 0 auto; width: 1px; height: 26px; background: var(--line); margin: 0 2px; }

  /* §30.2 — „skrolujte do ostatka" znači da se dugme **ne vidi** dok neko ne
     pogodi da traka kliza. Dvadeset jedna ikona × 44 px je 924 px u prozoru od
     547 — „Editor komada" je bio četrnaesti po redu i niko ga nije video.
     Sada: osnovnih šest stoji, ostatak izlazi na „⋯" i **prelama se u redove**,
     pa je sve vidljivo bez ijednog poteza u stranu. */
  .vp-tools.collapsed { overflow-x: visible; }
  .vp-tools.collapsed .rest { display: none !important; }
  .vp-tools:not(.collapsed) {
    height: auto; max-height: 40vh; flex-wrap: wrap; justify-content: center;
    overflow-x: hidden; overflow-y: auto; row-gap: 4px;
  }
  .vp-tools:not(.collapsed) .rest { display: flex !important; }
  /* dugme „još" je na telefonu deo reda, ne traka preko cele širine */
  .vp-more {
    display: flex; width: 44px; height: 44px; margin-top: 0; flex: 0 0 auto;
    border-radius: var(--r-8); font-size:var(--fs-16);
    /* §41.7 — u redu koji kliza u stranu dugme se lepi za DESNU ivicu, ne za
       dno: sa dvadeset ikonica ono odleti van vidnog polja i drugi klik nema
       gde da padne. **Mereno na 844×390: prvi klik 4 → 20 alata, drugi 20 →
       20.** Uspravna traka i dalje ima lepljivo dno. */
    position: sticky; right: 0; bottom: auto; left: auto;
    box-shadow: var(--sh-1);
  }

  .vp-foot { height: 40px; padding: 0 8px calc(0px + var(--safe-b)); gap: 6px; }
  .vp-foot #tool-hint { display: none; }
  /* §24.4 — nothing to scroll sideways any more: the views are one pill and a
     drop-down at every width, so the phone needs no special case */
  .vp-explode { left: 8px; right: 8px; bottom: calc(104px + var(--safe-b)); width: auto; }
  .vp-drone { bottom: calc(104px + var(--safe-b)); right: 8px; }
  .chrome-bl { bottom: calc(104px + var(--safe-b)); }
  .cnc-panel { bottom: calc(104px + var(--safe-b)); }
  /* karta praznog stanja se skloni traci alata i donjoj traci s puta */
  .vp-empty { padding: 10px 10px calc(102px + var(--safe-b)); }
}

/* ══ nizak ekran: sve što ima zakucanu visinu mora da popusti ════════════
   §31.2 — telefon položen ima 390 px visine. Toliko traže traka projekta
   (52) + traka kartica (44) + `min-height:320px` na samom pogledu, pa je
   pogled izlazio 43 px ispod donje ivice prozora i s njim cela donja traka:
   SNAP, korak rotacije, zum i jezik bili su ispod ekrana, mereno y=388 u
   prozoru od 390. Ništa se ne krije — sve se skuplja. */
@media (max-height: 560px) {
  /* pogled uzima ono što je ostalo, ne 320 px koliko god da ih nema */
  .viewport { min-height: 0; }

  .projbar { min-height: 42px; max-height: 48px; padding: 4px 10px; gap: 8px; }
  .projbar-acct .pop-btn { height: 28px; }
  .chrome-client .pop-btn.slim,
  .editor-bar .btn,
  .projbar .btn.btn-sm { height: 26px; }
  .tabbar { min-height: 0; }
  .tabbar button { padding: 5px 8px; font-size:var(--fs-12); }
  .tabbtn { height: 24px; padding: 0 9px; font-size:var(--fs-11); }

  /* ── §53.3 — a sada isto to, ali za prst ────────────────────────────────
     Sve gore je pisano za JEDNU meru: 390 px visine na položenom telefonu.
     Sve je istina i dalje — ali je pisano za miša. Prstu treba 44 px, a 44
     px puta sve što je ovde nabrojano ne staje u 390.

     Zato se deli po tome ČEMU kontrola služi:

     · TRAKA KARTICA raste. Kroz nju se stiže do svih deset ekrana; ako se
       ona ne pogađa, program se ne koristi. 26 → 44 px košta 18 px prikaza
       od 390, dakle 4,6 % — a bez toga se četiri od deset ekrana otvaraju iz
       trećeg pokušaja.
     · SVE OSTALO u trakama zadržava svoju visinu, a dobija nevidljivo dete
       koje hvata prst. Piksela je isto, promašaja nema. Širi se samo po
       VISINI: susedi tih dugmadi stoje levo i desno, pa bi širenje u stranu
       otimalo dodir susedu, što je gore od premale mete.

     Sve je pod `pointer: coarse` da nijedno ranije merenje na velikom ekranu
     ne pomeri: nizak PROZOR na stolnom računaru se i dalje klika mišem. */
  @media (pointer: coarse) {
    .tabbar button { min-height: 44px; padding-block: 0; }
    .chrome-client .pop-btn.slim,
    .editor-bar .btn,
    .projbar .btn.btn-sm,
    .projbar-acct .pop-btn,
    .tabbtn { position: relative; }
    .chrome-client .pop-btn.slim::after,
    .editor-bar .btn::after,
    .projbar .btn.btn-sm::after,
    .projbar-acct .pop-btn::after,
    .tabbtn::after { content: ""; position: absolute; left: 0; right: 0;
      top: 50%; height: 44px; transform: translateY(-50%); }
  }

  /* Karta „Počnite novi projekat" je bila viša (364 px) od celog pogleda, pa
     joj je „Uvoz…" ostajao ispod ivice. Ostaju naslov i tri dugmeta — jedina
     tri poteza koja ta karta i nudi; objašnjenje i poziv na prevlačenje su
     rečenice, a rečenica ovde košta dugme. */
  .vp-empty { padding: 6px 6px calc(102px + var(--safe-b)); align-items: flex-start; }
  .vp-empty .vp-empty-card { padding: 12px 14px; max-width: 360px; }
  .vp-empty .vp-empty-ico { display: none; }
  .vp-empty .vp-empty-card p { display: none; }
  /* tri dugmeta u JEDAN red: u dva reda treći („Uvoz…") pada ispod dna karte,
     a karta je tu visoka koliko joj ostane iznad trake alata — mereno 129 px
     za sadržaj od 161 px */
  .vp-empty .vp-empty-card .btn { height: 30px; padding: 0 11px; font-size:var(--fs-12); }
}

/* §52.1 — na niskom ekranu (položen telefon, 844 × 390) uspravna traka ikonica
   se prelamala u dve kolone od 88 px, jer 11 stavki × 42 px traži 526 px a
   visine ima 390. Trake nema, pa nema ni prelamanja: 88 px koje je uzimala
   idu prikazu kao i 58 px na svim ostalim širinama. Određen red mreže
   (`minmax(0,1fr)`) — jedini deo tog pravila koji nije bio zbog trake — sada
   stoji uz `.app` u `app.css`, za sve mere ekrana. */

/* §17.12 — snappy. Anything slower than a fifth of a second on a touch
   device reads as lag. */
@media (pointer: coarse) {
  .editor { transition-duration: var(--t-1); }
  .dock, .dock > .panel { transition-duration: var(--t-0); }
  .btn, .tool, .chip { transition-duration: var(--t-0); }
}

/* ══ §53.3 — TRAKA PROJEKTA ZA PRST ═══════════════════════════════════════
   Traka projekta stoji na SVIH DESET ekrana, pa je svaka njena premala meta
   deset puta premala. Mereno `tools/dodir.js` na 390 × 844:
   `.proj` 40 px · `#btn-account` 44 × 34 · `.tabbtn` 32 px ·
   `.chip.pencil` 31 × 26 · logo 93 × 28. Pet kontrola × deset ekrana = 50
   promašaja od 140 koliko ih je ukupno bilo.

   Šta raste a šta ne: traka je 52 px visoka, pa sve što je u njoj SME da
   naraste do 44 bez ijednog piksela nove visine — to ništa ne košta i radi
   se. Logo i olovka su izuzetak: njima 44 px širine pomera ceo red udesno,
   pa dobijaju nevidljivo dete umesto nove mere. */
@media (pointer: coarse) {
  .projbar .proj,
  #btn-account,
  .projbar-acct .pop-btn { min-height: 44px; }
  #btn-account { min-width: 44px; }

  .projbar-brand,
  .projbar .chip.pencil { position: relative; }
  .projbar-brand::after,
  .projbar .chip.pencil::after { content: ""; position: absolute;
    left: 50%; top: 50%; width: max(100%, 44px); height: 44px;
    transform: translate(-50%, -50%); }
}
/* `.tabbtn` raste samo tamo gde ima visine. Na položenom telefonu (ispod
   561 px) ostaje 24 px i dobija nevidljivo dete — to je pravilo niže u
   fajlu, u bloku za nizak ekran. Ovde je granica napisana izričito da se
   dva pravila ne bore. */
@media (pointer: coarse) and (min-height: 561px) {
  .tabbtn { min-height: 44px; }
}
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}

/* ── §17.4 material mapping dialog ─────────────────────────────────────── */
.mm-list { display: flex; flex-direction: column; gap: 6px; max-height: 46vh; overflow: auto; }
.mm-row {
  display: flex; align-items: center; gap: 10px;
  padding: 8px 10px; border: 1px solid var(--line); border-radius: var(--r-8);
  background: var(--surface);
}
.mm-sw { width: 30px; height: 30px; border-radius: var(--r-6); flex: 0 0 auto;
  border: 1px solid var(--border); box-shadow: inset 0 0 0 1px rgba(255,255,255,.35); }
.mm-id { flex: 1 1 auto; min-width: 0; }
.mm-id b { display: block; font-size:var(--fs-13); font-weight: 600; }
.mm-id em { display: block; font-style: normal; font-size:var(--fs-10); color: var(--mut); margin-top: 2px; }
.mm-pick { flex: 0 0 auto; width: 210px; max-width: 46%; }
@media (max-width: 620px) {
  .mm-row { flex-wrap: wrap; }
  .mm-pick { width: 100%; max-width: none; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   §18.4 / §18.5 — the HUD is a LAYOUT, not a pile of floating boxes.

   Every widget over the 3D view used to be absolutely positioned with its own
   hard-coded offsets, so at 540 px the tool stack sat on the language button,
   the view badges sat on the explode slider, and the slider hung outside the
   viewport. Nothing knew where anything else was.

   Now `chrome.js` moves them all into one grid overlay with named zones. Two
   widgets cannot overlap because they are in different cells, and the layout
   reflows on its own at every width.
   ═════════════════════════════════════════════════════════════════════════ */
.vp-hud {
  position: absolute; inset: 0; z-index: 12;
  display: grid;
  /* ── §21.8 / §18.5 — the middle column has to survive ───────────────────
     `auto 1fr auto` reads as if the centre gets what is left, but an `auto`
     track takes its max-content FIRST and `1fr` only gets the remainder. The
     formula bar made the right column 411 px, the tool rail made the left one
     199 px, and in a 610 px viewport that left the centre at **0 px** —
     measured. A centred child then overflows its own cell in both directions,
     which is how the explode slider (319 px) ended up 151 px inside the
     bottom-right zone. Capping the sides in per cent means the centre can
     never be squeezed out, and the side content shrinks instead. */
  grid-template-columns: minmax(0, 30%) minmax(0, 1fr) minmax(0, 40%);
  /* The bottom row must be capped on the TRACK, not on the cell: an `auto`
     row grows to its content first and a max-height on the child arrives too
     late. 40 % leaves the model the majority of the window at every size. */
  grid-template-rows: auto minmax(0, 1fr) minmax(0, 32%) auto;
  grid-template-areas:
    "tl tc tr"
    "l  c  r"
    "bl bc br"
    "ft ft ft";
  gap: 8px;
  padding: 10px 10px 0;
  pointer-events: none;
  overflow: hidden;              /* the HUD never scrolls the viewport away */
}
/* §41.11 / §42.2 — ĆELIJA NIJE POVRŠINA. Zona je prazan okvir rasporeda, a
   nosila je `pointer-events:auto`, pa je i PRAZNA ćelija hvatala klik. Mereno
   `node tools/fit.js --only app` na 844×390: `elementFromPoint` na dugmadima
   „+ Nova ploča" i „Gotove korpusne jedinice" u kartici praznog stanja vraćao
   je `div.z-tc` — dva dugmeta koja se vide a ne mogu da se pritisnu. Prima
   pokazivač ono što se crta, ne mreža u kojoj stoji.                         */
.vp-hud > * { pointer-events: none; min-width: 0; max-width: 100%; }
/* §21.8 — a widget may never be wider than the cell it was put in; that is
   the only thing that makes "different cells cannot overlap" actually true. */
.vp-hud > * > * { max-width: 100%; pointer-events: auto; }

.vp-hud .z-tl { grid-area: tl; align-self: start; }
.vp-hud .z-tc { grid-area: tc; justify-self: center; align-self: start; }
.vp-hud .z-tr { grid-area: tr; justify-self: end;    align-self: start; }
.vp-hud .z-l  { grid-area: l;  align-self: center;   justify-self: start; }
.vp-hud .z-r  { grid-area: r;  align-self: center;   justify-self: end; }
/* §27.3 — the bottom zones carry `height:100%`, and that is not decoration.
   A percentage max-height on a child resolves against nothing when the parent
   is `height:auto`, so `.cnc-panel { max-height:100% }` was silently ignored
   and the panel grew past the HUD and got clipped by its `overflow:hidden`.
   Measured before: zone 185 px, panel 391 px, 206 px of it cut off — the
   transport buttons of the tool-path simulation were among the parts lost.
   With a definite height on the zone the cap resolves and the panel scrolls
   inside itself instead. The zones stay bottom-aligned through the flex
   `justify-content`, not through `align-self`. */
.vp-hud .z-bl { grid-area: bl; justify-self: start; height: 100%;
                display: flex; flex-direction: column; justify-content: flex-end; }
.vp-hud .z-bc { grid-area: bc; justify-self: center; height: 100%;
                display: flex; flex-direction: column; justify-content: flex-end; }
.vp-hud .z-br { grid-area: br; justify-self: end; height: 100%;
                display: flex; flex-direction: column; justify-content: flex-end;
                align-items: flex-end; gap: 8px; }
.vp-hud .z-ft { grid-area: ft; margin: 0 -10px; }

/* inside a zone the widget is plain flow again — no more absolute offsets */
.vp-hud .z-l  > #vp-tools,
.vp-hud .z-bc > .vp-explode,
.vp-hud .z-br > .fx,
.vp-hud .z-br > .vp-drone,
.vp-hud .z-bl > .cnc-panel,
.vp-hud .z-tc > .hint-pill,
.vp-hud .z-ft > .vp-foot {
  position: static !important;
  left: auto !important; right: auto !important;
  top: auto !important; bottom: auto !important;
  transform: none !important;
  margin: 0 !important;
}
.vp-hud .z-l > #vp-tools { max-height: 100%; overflow-y: auto; scrollbar-width: none; }
.vp-hud .z-l > #vp-tools::-webkit-scrollbar { display: none; }
.vp-hud .z-bc > .vp-explode { width: min(320px, 100%); }
.vp-hud .z-br > .fx { width: min(360px, 100%); }
.vp-hud .z-bl > .cnc-panel { width: min(380px, 100%); opacity: 1; }
.vp-hud .z-tc > .hint-pill { position: static !important; }
/* §24.7 — znak valute (`data-cur`) u dugmetu alata: kod od tri slova („RSD")
   stoji tamo gde je bio jedan znak („€"), u mono slogu i u meri koja staje u
   dugme od 42 px. §52.1 — pravilo za traku ikonica je otpalo zajedno sa njom;
   izbor valute stoji u meniju jezika, a svaka cena u programu je u njoj. */
.vp-tools .tool [data-cur] {
  font-family: var(--mono); font-weight: 600; letter-spacing: -.02em;
  line-height: 1; display: inline-block; max-width: 100%;
  font-size: var(--fs-11);
}

/* §24.4 — the views are the one exception to the rule above: the drop-down
   has to hang off them, so they need to BE a containing block. `relative`
   with no offsets moves nothing, so the grid placement is untouched — but
   `static !important` in the list above made the menu resolve against the
   whole HUD and it landed 593 px below the button. */
.vp-hud .z-tr > .vp-views {
  position: relative !important;
  left: auto !important; right: auto !important;
  top: auto !important; bottom: auto !important;
  transform: none !important; margin: 0 !important;
}
/* the drone pad only takes space when it is on */
.vp-hud .z-br > .vp-drone { display: none; }
.vp-hud .z-br > .vp-drone.on { display: grid; }

/* the language chip lives at the left end of the foot bar inside the editor —
   still bottom-left, but in a place that belongs to something */
.vp-foot .lang-inline { margin-right: 2px; }
.vp-foot .lang-inline .pop-btn { height: 26px; padding: 0 8px; box-shadow: none;
  background: transparent; border-color: var(--border); }
.vp-foot .lang-inline .pop { bottom: calc(100% + 8px); left: 0; }

@media (max-width: 760px), (max-height: 560px) {
  /* The tool strip becomes the bottom bar and leaves the grid, so the grid
     has to keep its bottom row clear of it — otherwise the explode slider
     lands on top of the tools, which is exactly what §18.4 is about. */
  .vp-hud { padding: 6px 6px 0; gap: 6px; }
  /* §31.2 — a to je i radilo tako što nije radilo: donje zone nose
     `height:100%` (§27.3), a spoljna margina ne smanjuje kutiju kojoj je
     visina određena — samo je izvuče iz reda. Klizač razbijanja je zato i
     dalje ležao na traci alata (mereno: klizač 285–323, traka 276–332).
     Unutrašnje odstojanje smanjuje sadržaj, pa `justify-content:flex-end`
     spusti widget tačno iznad trake. */
  .vp-hud .z-bl, .vp-hud .z-bc, .vp-hud .z-br {
    margin-bottom: 0; padding-bottom: calc(56px + var(--safe-b));
  }
  .vp-hud .z-l { display: contents; }
  .vp-hud .z-l > #vp-tools { position: absolute !important;
    left: 0 !important; right: 0 !important; bottom: calc(40px + var(--safe-b)) !important;
    z-index: 15; }
  .vp-hud .z-br > .fx { display: none; }
  .vp-hud .z-bc > .vp-explode { width: 100%; }
  .vp-hud .z-bl > .cnc-panel { width: 100%; }
}

/* ── §2.5 / §2.7 — the editor's own top-left cluster ──────────────────────
   `+ Komad` and Uvoz / Izvoz live over the model, where the modelling
   happens. The project bar keeps only `+ Novo` = a new PROJECT. */
.vp-hud .z-tl { display: flex; flex-direction: column; gap: 6px; align-items: flex-start; }
.partwrap { position: relative; }
.partwrap .newmenu { top: calc(100% + 6px); left: 0; }
.editor-io { display: flex; gap: 6px; }
.editor-io .btn,
.partwrap .btn {
  background: color-mix(in srgb, var(--surface) 86%, transparent);
  backdrop-filter: blur(10px) saturate(1.2); -webkit-backdrop-filter: blur(10px) saturate(1.2);
  box-shadow: var(--sh-1);
}
.partwrap .btn-primary { background: var(--ink); color:var(--on-ink); }

/* §2.1 / §12.4 / §30.8 — ovde je stajao ceo raspored trake ikonica: širenje na
   210 px pri prelasku mišem sa natpisom uz svaki znak, mera raširene trake
   izmerena po jeziku (es 131 px je bio najduži: „Informar de un problema"),
   pravilo koje ispod 1100 px zabranjuje širenje, i rezerva za pregledač bez
   `:has()`. §52.1 je traku ugasio, pa je sve to otišlo sa njom — svih 11
   njenih stavki punim imenom stoji u traci kartica, traci projekta i meniju
   naloga, gde nema šta da se širi da bi se ime videlo. */

/* ── §10.3 / §10.8 — material on the part, no scrolling to reach it ────── */
.mat-head { display: flex; gap: 11px; align-items: center; padding: 0 12px 10px; }
.mat-swatch-btn {
  width: 52px; height: 52px; flex: 0 0 auto; border-radius: var(--r-8);
  border: 1px solid var(--border); background: var(--surface-4);
  box-shadow: inset 0 0 0 1px rgba(255,255,255,.4);
  transition: border-color var(--t-1), transform var(--t-0);
}
.mat-swatch-btn:hover { border-color: var(--acc); }
.mat-swatch-btn:active { transform: scale(.96); }
.mat-name { font-size:var(--fs-14); font-weight: 600; cursor: pointer;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mat-name.warn { color: var(--warn); }
.mat-meta { font-size:var(--fs-10); color: var(--mut); margin-top: 3px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mat-picker { padding: 0 12px 10px; }
.mat-picker .inp { width: 100%; margin-bottom: 6px; }
.mat-list { max-height: 240px; overflow: auto; border: 1px solid var(--line);
  border-radius: var(--r-8); }
.mat-row { display: flex; align-items: center; gap: 9px; width: 100%;
  padding: 7px 9px; text-align: left; border-bottom: 1px solid var(--line-3); }
.mat-row:last-child { border-bottom: 0; }
.mat-row:hover { background: var(--surface-3); }
.mat-row.on { background: var(--acc-soft); }
.mat-row .sw { width: 22px; height: 22px; flex: 0 0 auto; border-radius: var(--r-4);
  border: 1px solid var(--border); background: var(--surface-4); }
.mat-row .nm { flex: 1 1 auto; font-size:var(--fs-13); overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap; }
.mat-row .fo { font-size:var(--fs-10); color: var(--mut); flex: 0 0 auto; }
.mat-thick { padding: 4px 12px 14px; }
.mat-thick .inp { width: 110px; margin-top: 5px; font-size:var(--fs-15); }

/* one editor toolbar — §19.2 */
.editor-bar { display: flex; gap: 6px; align-items: center; flex-wrap: wrap; }
.editor-bar .btn {
  background: color-mix(in srgb, var(--surface) 86%, transparent);
  backdrop-filter: blur(10px) saturate(1.2); -webkit-backdrop-filter: blur(10px) saturate(1.2);
  box-shadow: var(--sh-1);
}
.editor-bar .btn-primary { background: var(--ink); color:var(--on-ink); border-color: var(--ink); }

/* ── §21.1 — client actions are a CHILD of the account slot ──────────────
   They used to be a second fixed box pinned to the same corner, which is
   how they ended up sitting on top of the account. One column, one gap,
   and overlapping becomes impossible. */
.chrome-tr { flex-direction: column; align-items: flex-end; gap: 8px; }
.chrome-client { display: flex; gap: 6px; flex-wrap: nowrap; white-space: nowrap; }
.pop-btn.slim { height: 30px; padding: 0 11px; font-size:var(--fs-12); gap: 6px; }
.pop-btn.slim.primary { background: var(--ink); color:var(--on-ink); border-color: var(--ink); }
.pop-btn.slim.primary:hover { background: var(--acc); border-color: var(--acc); }
.chrome-client .chip { padding: 1px 5px; font-size:var(--fs-10); }
/* §29.7 — ovo je pravilo dizalo traku kartica sa 42 px na 109 px: ispod
   760 px `.chrome-client` je postajao KOLONA, tri dugmeta jedno ispod
   drugog, a `.tabs` je flex sa `align-items:stretch` pa je svaka kartica
   rastegnuta na 108 px — otuda ogroman prazan prostor ispod natpisa
   „Scena / CNC program / Mašina…". Ostaje red; traka ionako već kliza
   vodoravno (`overflow-x:auto`), pa se dugmad ne gube. */
@media (max-width: 760px) { .chrome-client { flex-direction: row; align-items: center; } }

/* ── §19.2 — logo top-left of the project bar ──────────────────────────── */
.projbar-brand { flex: 0 0 auto; margin-right: 4px; padding-right: 12px;
  border-right: 1px solid var(--line); }
.projbar-brand .name { font-size:var(--fs-15); }
@media (max-width: 900px) { .projbar-brand .name { display: none; } }

/* ── §21.7 — the tool stack must never run off the top or the bottom ─────
   It sat in a fixed-height cell and simply overflowed, so on a laptop half
   the icons were behind the foot bar. It now scrolls inside its own zone,
   and the expander has a matching retract arrow. */
/* A grid item defaults to min-height:auto, so a tall tool column grew its own
   row and then hung out of the viewport top and bottom — 819 px of icons in a
   556 px window, six of them unreachable. Stretch it to the row, pin its
   min-height to zero so the row cannot grow, and let it scroll inside. */
.vp-hud .z-l {
  align-self: stretch; min-height: 0; height: 100%;
  display: flex; flex-direction: column; justify-content: center; align-items: flex-start;
}
/* §31.2 — a klizanje je isti kvar kao vodoravno klizanje trake kartica: dno
   kolone alata niko ne nađe. Kolona se PRELAMA u drugu kolonu kad joj visina
   ne stigne, i nijedna ikonica se ne stiskuje (`flex:0 0 auto`) — bez toga su
   se 42 px dugmad cedila na 26 i 15 px, pa je sredina dugmeta padala izvan
   njegove kutije. Mereno rašireno na 1920×1080: 21 alat, pre 3 nedohvatljiva
   („Let kroz scenu", „Ceo ekran", „⋯"), posle 0 — u dve kolone, 97 px. */
.vp-tools > * { flex: 0 0 auto; }
.vp-hud .z-l > #vp-tools {
  max-height: 100%; min-height: 0; flex: 0 1 auto;
  flex-wrap: wrap; align-content: flex-start; column-gap: 4px;
  overflow: visible; overscroll-behavior: contain;
  scrollbar-width: none; padding-right: 2px;
}
.vp-hud .z-l > #vp-tools::-webkit-scrollbar { display: none; }
.vp-more.retract { transform: rotate(180deg); }

/* The bottom row is `auto`, so a tall formula bar or CNC panel simply ate the
   whole viewport and squeezed the tool column to nothing. Every bottom cell is
   capped and scrolls inside itself; the model keeps at least half the height. */
.vp-hud .z-bl, .vp-hud .z-bc, .vp-hud .z-br { max-height: 100%; min-height: 0; }
/* §7.6 — the CNC panel grew a transport bar for the tool-path simulation, and
   at 32 % of a 585 px viewport the zone is 187 px: head + reading + transport
   + footer do not fit, and „Nazad" / „Pošalji program" hung 60 px below the
   HUD. While the machine view is open the bottom row takes 56 %, which still
   leaves the model the larger half. Measured after: panel 328 px, footer
   inside the HUD, nothing clipped. */
#viewport.cnc-on .vp-hud { grid-template-rows: auto minmax(0, 1fr) minmax(0, 56%) auto; }
.vp-hud .z-br > .fx { max-height: 100%; overflow: auto; }
/* the CNC panel does NOT scroll as a whole — its head and its transport bar
   have to stay put and only the reading list gives way (§27.1: a button you
   cannot reach is a button that does not work) */
.vp-hud .z-bl > .cnc-panel { max-height: 100%; overflow: visible;
  display: flex; flex-direction: column; min-height: 0; }
/* §21.23 — SPREDA / ODOZGO / SDESNA were sliced down to an 8 px sliver.
   The cap here was `max-height: 22%`, a percentage against a grid row whose
   own height comes from this very element: the row asked the content how
   tall it was, the content asked the row what 22 % of it was, and the pair
   settled at 8 px with a 36 px button bar clipped inside. Measured before
   the fix: .z-tr 8 px tall, every one of the six buttons `clipped: true`.
   A percentage cannot resolve against an indefinite track — the cap has to
   be a real length, so it is one, and the zone is free to hug its buttons. */
.vp-hud .z-tr {
  max-height: min(180px, 40vh); min-height: 0; height: auto;
  overflow: visible; scrollbar-width: none;
}
.vp-hud .z-tr::-webkit-scrollbar { display: none; }


/* ── §21.2 / §21.11 — the right dock must not sit on the model ─────────── */
/* §31.2 — `max-width:100%` važi SAMO dok je dok ćelija mreže. Ispod 1100 px on
   je `position:absolute` dete mreže sa `grid-column:3`, pa mu je sadržavajući
   blok ta kolona — a ona je tada široka 0 px. Sto posto od nule je nula, i dok
   se skupljao na 14 px (koliko drže levo i desno unutrašnje odstojanje i okvir
   pri `border-box`). Mereno: `#dock-right` 14 px širok na 1024, 768 i 844 px,
   inspektor u njemu 24 px — otuda „strelice", „pretraga" i kartice
   Dimenzije / Materijal / Ivice / CNC kao nedohvatljive na svakoj meri ispod
   1100 px. Kapa ostaje tamo gde ima smisla, isecanje ostaje svuda. */
.editor .dock[data-dock=right] { overflow: hidden; }
@media (min-width: 1101px) { .editor .dock[data-dock=right] { max-width: 100%; } }
.editor .dock[data-dock=right] > .panel { min-width: 0; max-width: 100%; }
.editor .dock > .panel .panel-bd { overflow-x: hidden; }
.editor .dock .insp, .editor .dock .dims { min-width: 0; max-width: 100%; }
.editor .dock .dims .ins-f input { min-width: 0; width: 100%; }

/* ── §21.9 — the explode slider background was breaking in half ──────────
   It had a chamfered pseudo-element sized in percentages inside a flex box
   whose width changed with the label, so the two halves drifted apart. One
   solid translucent pill, no pseudo-elements. */
.vp-explode {
  display: flex; align-items: center; gap: 10px;
  padding: 7px 13px; border-radius: var(--r-pill);
  background: color-mix(in srgb, var(--surface) 78%, transparent);
  backdrop-filter: blur(12px) saturate(1.2); -webkit-backdrop-filter: blur(12px) saturate(1.2);
  border: 1px solid var(--line); box-shadow: var(--sh-1);
}
.vp-explode::before, .vp-explode::after { content: none !important; }
.vp-explode .label { flex: 0 0 auto; font-size:var(--fs-9); letter-spacing: .12em; color: var(--mut); }
.vp-explode input[type=range] { flex: 1 1 auto; min-width: 80px; }
.vp-explode .mono { flex: 0 0 auto; font-size:var(--fs-11); min-width: 52px; text-align: right; }

/* ══ §31.2 — prazna scena: karta „Počnite novi projekat" i HUD ═══════════
   Preklop praznog stanja pokriva ceo pogled i prima svaki dodir, iako je od
   njega vidljiva samo karta u sredini — pa se preko alata nije moglo. Sada je
   staklo: klik prolazi kroz njega svuda osim po samoj karti.
   A klizač razbijanja je ležao preko dugmadi karte („+ Nova ploča",
   „Gotovi elementi") jer je HUD iznad preklopa. Nema šta da se razbije dok u
   sceni nema nijednog komada — dok je karta gore, klizača nema. */
#viewport:has(#vp-empty:not([hidden])) .vp-explode { display: none; }
.vp-empty { pointer-events: none; }
.vp-empty .vp-empty-card { pointer-events: auto; max-height: 100%; overflow: auto; }


/* §21.1 — one fixed stack at the top right */
.chrome-stack { flex-direction: column; align-items: flex-end; gap: 8px; }
.chrome-stack > * { flex: 0 0 auto; }
.chrome-client { display: flex; gap: 6px; flex-wrap: nowrap; white-space: nowrap; }

/* ══ §24.4 — the camera views are ONE control, not six ═══════════════════
   IZO / ODOZGO / SPREDA / SDESNA / SLEVA / FIT sat in a row in the corner.
   Six mono labels are ~300 px wide and the corner is not, so below about
   900 px the row scrolled sideways and the first label was cut in half —
   the „text and button go somewhere" the customer reported. A row that has
   to scroll is not a control anybody uses.

   Now it is one pill showing the view you are in, and an arrow. The list
   drops out of it, right-aligned so it can never leave the viewport, and it
   is a COLUMN, so its width is one label wide at any window size. Same
   behaviour at 375 px and at 2560 px — there is no breakpoint here, which is
   the point. */
.vp-hud .z-tr > .vp-views {
  position: relative; display: block; overflow: visible;
  background: none; border: 0; box-shadow: none; padding: 0; max-width: 100%;
}
.vp-hud .vp-views .vv-toggle {
  display: flex; align-items: center; gap: 7px; height: 34px; padding: 0 10px 0 13px;
  border-radius: var(--r-pill); cursor: pointer;
  background: color-mix(in srgb, var(--surface) 82%, transparent);
  backdrop-filter: blur(12px) saturate(1.2); -webkit-backdrop-filter: blur(12px) saturate(1.2);
  border: 1px solid var(--line); box-shadow: var(--sh-1);
  font-family: var(--mono); font-size: var(--fs-10); letter-spacing: .08em;
  color: var(--ink); white-space: nowrap;
  transition: background var(--t-1), border-color var(--t-1);
}
.vp-hud .vp-views .vv-toggle:hover { background: var(--surface); }
.vp-hud .vp-views .vv-arrow {
  font-size: var(--fs-10); line-height: 1; color: var(--ink-3);
  transition: transform var(--t-1);
}
.vp-hud .vp-views.open .vv-toggle { border-color: var(--ink); }
.vp-hud .vp-views.open .vv-arrow { transform: rotate(180deg); }

/* The closed state is `display:none`, not `opacity:0; visibility:hidden`.
   That was tried first and it did not work: the transition on `visibility`
   never advanced inside this HUD subtree, so the cascade said opacity 1 while
   the computed style stayed 0 with `getAnimations()` empty — measured, and
   confirmed by setting `transition:none`, which snapped it to 1/visible at
   once. A menu that is genuinely absent when closed cannot get stuck half
   way, and the fade comes from a keyframe on the way in, which has no
   „previous state" to be stranded in. */
.vp-hud .vp-views .vv-menu {
  position: absolute; top: calc(100% + 6px); right: 0; z-index: 20;
  display: none; flex-direction: column; gap: 2px; padding: 4px;
  min-width: 128px; border-radius: var(--r-sm);
  background: color-mix(in srgb, var(--surface) 94%, transparent);
  backdrop-filter: blur(14px) saturate(1.2); -webkit-backdrop-filter: blur(14px) saturate(1.2);
  border: 1px solid var(--line); box-shadow: var(--sh-2);
  transform-origin: 100% 0;
}
/* no `both` fill: in this subtree the animation's own clock does not always
   run (the same stall the transition hit), and with a fill mode the menu was
   left holding the keyframe's opacity 0 — measured, hit-testable but
   invisible. Without a fill the element falls back to its own style, which is
   fully opaque, so the worst case is that the fade is skipped. */
.vp-hud .vp-views.open .vv-menu {
  display: flex;
  animation: vvIn var(--t-1) var(--ease);
}
@keyframes vvIn {
  from { opacity: 0; transform: translateY(-4px) scale(.98); }
  to   { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
  .vp-hud .vp-views.open .vv-menu { animation: none; }
}
.vp-hud .vp-views .badge {
  flex: 0 0 auto; height: 28px; display: flex; align-items: center;
  padding: 0 11px; border: 0; border-radius: var(--r-xs);
  background: transparent; color: var(--ink-3); cursor: pointer;
  font-family: var(--mono); font-size:var(--fs-10); letter-spacing: .08em;
  white-space: nowrap; transition: background var(--t-1), color var(--t-1);
}
.vp-hud .vp-views .badge:hover { background: var(--surface-3); color: var(--ink); }
.vp-hud .vp-views .badge.on { background: var(--ink); color:var(--on-ink); }

/* §24.1 — the reserved corner is gone. `padding-right: 210px / 150px / 110px`
   existed only because the account button floated over the bar as a fixed box;
   the bar now CONTAINS it (`#projbar-acct`), so there is nothing to avoid and
   nothing to keep in step at three breakpoints. */

/* one style for every button in the client stack and the editor bar */
.chrome-client .pop-btn.slim,
.editor-bar .btn,
.projbar .btn.btn-sm { height: 30px; font-size:var(--fs-12); border-radius: var(--r-pill); }
.chrome-client .pop-btn.slim { border-radius: var(--r-pill); }

/* ══ the project bar is ONE line ═════════════════════════════════════════
   It was `flex-wrap: wrap`, so as soon as the corner was reserved for the
   account stack the chips and the QR / AR button dropped to a second row and
   nothing lined up any more. One row, the project name is the part that
   gives way, and the whole bar scrolls sideways if it truly has to. */
.projbar {
  /* §29.2 — `overflow-x:auto` uz `overflow-y:visible` NE POSTOJI: čim je jedna
     osa `auto`, CSS drugu diže na `auto` — pa je traka dobila i vertikalni
     okvir isecanja, i meni „+ Novi projekat" je nestajao **iza trake**, bez
     obzira što mu je `z-index:120`. Mereno: `elementFromPoint` na vrhu
     otvorenog menija vraća dugme ispod njega, a ne meni.
     Vodoravno klizanje sada nosi UNUTRAŠNJI omotač (`.projbar-scroll`), a
     sama traka ne iseča ništa — pa meni sme da visi iz nje. */
  flex-wrap: nowrap; overflow: visible;
  min-height: 52px; max-height: 62px; align-items: center;
}
.projbar::-webkit-scrollbar { display: none; }
.projbar > * { flex: 0 0 auto; }
.projbar .proj { flex: 0 1 auto; min-width: 0; }
.projbar .proj .pname, .projbar .proj .psub { overflow: hidden; text-overflow: ellipsis; }
.projbar .spacer { flex: 1 1 auto; min-width: 8px; }
.projbar-btns { flex: 0 0 auto; flex-wrap: nowrap; }

/* ══════════════════════════════════════════════════════════════════════════
   §42.3 – §42.5 — GORNJI LEVI UGAO, I DESNI KRAJ TRAKE

   „upada projekti iza ili ispred logoa i skučeno je, ne vidi se tekst novi
    projekat" · „razmak od Sačuvaj do naloga je prevelik" · „Sken prostora ide
    LEVO od naloga"

   Tri merene stvari:

     §42.3  Dugme „Projekti" je nosilo `order:-1` ispod 760 px, pa je izlazilo
            **ispred logoa**, i uz to se stiskalo na `flex:0 1 auto` bez donje
            granice. **Mereno na 390×844: `.proj` širine 16 px, na x=2, dok je
            logo na x=26 — dakle levo od njega, i od cele reči „PROJEKTI"
            vidljiv samo znak ▾.** Redosled se vraća u redosled DOM-a, a dugme
            dobija donju širinu ispod koje ne ide.

     §42.3  „+ Novi projekat" je ispod 620 px gubio tekst (`font-size:0`) i
            ostajao goli „+". **Mereno na 390 px: natpis 0×0 px.** Ostaje reč
            „Novi" — kraća, ali napisana; ceo naziv je u opisu i u meniju.

     §42.4  Razmak do naloga pravio je `.spacer`, koji uzima sve što pretekne.
            **Mereno na 1920 px: 992 px praznog između trake i naloga.** Gura
            se samo koliko treba da desna grupa stane uz ivicu, a ritam trake
            je isti `gap` kao svuda drugde, sa gornjom granicom.

     §42.5  Grupa sa „◎ Sken prostora" je ispod 980 px imala `order:9` dok
            nalog nema `order`, pa je po pravilima flexbox-a padala **iza**
            naloga. Nalog sada nosi najveći red i uvek je poslednji.         */
/* ══ §45.4 — GORNJA TRAKA SE RASPOREĐUJE, NE GOMILA ═══════════════════════
   Mereno `node tools/navbar.js` na 1920×1080: traka ide 58 → 1920 (1862 px),
   a sadržaj se završava na **1547,9 px** — dakle **372 px praznog** na desnom
   kraju, dok je istovremeno **naslov projekta odsečen za 77 px (24 %)** a
   sažetak za 55 px, i to usred cifre („…83.6"). Prazan prostor je stajao
   pored teksta koji nije imao gde da stane.

   Višak sada dobija SREDINA — ime projekta i njegov sažetak, jedino što u
   ovoj traci ima šta da pokaže sa više mesta. Levi kraj (znak, „Novi",
   „Sačuvaj") i desni (QR, nalog) ostaju svoje veličine, pa se ništa ne
   pomera dok se prozor menja. Time otpada i §42.4 („prevelik razmak od
   Sačuvaj do naloga"): razmaka nema, jer ga pojede naslov. */
.projbar { gap: 10px; }
.projbar .spacer { max-width: 40px; }
/* ime projekta uzima sav višak, do granice posle koje bi gutalo ceo red */
.projbar .proj { flex: 1 1 auto; max-width: 820px; }
/* sažetak („182 delova · 379 bušenja · 83,66 m²") sme da poraste do pune mere;
   odsečen broj se čita kao pogrešan podatak, pa se radije skrati cela stavka */
.projbar #project-meta { flex: 0 1 auto; min-width: 0; max-width: 420px; }
/* Prazna grupa ne sme da učestvuje u redu: `chrome.js` preseli „QR nalog" u
   traku kartica, pa `.projbar-btns` ostane prazan `div` koji i dalje troši
   `gap` sa obe strane. */
.projbar .projbar-btns:empty { display: none; }
/* Nalog ide na DESNU IVICU, a ne odmah iza poslednjeg čipa. Mereno na 1920:
   sadržaj se završavao na 1502,8 px u traci širokoj 1862 — **417 px praznog**
   posle naloga. `margin-left:auto` to prazno pretvara u razmak PRE naloga, pa
   se traka drži obe ivice na svakoj širini. */
.projbar #projbar-acct { margin-left: auto; }
/* Grupa dugmadi i čipovi smeju da se skupe — grupa kliza u sebi (§38.3), a čip
   ima tri tačke. Bez toga red PRERASTE traku, a `position:sticky` na nalogu ga
   onda zakuca preko onoga što je preteklo: **mereno na 1024 px, `.chip` i
   `#projbar-acct` se preklapaju, a „◎ Sken prostora" počinje na x=1117 u
   prozoru od 1024.** */
.projbar-btns { order: 9; flex: 0 1 auto; min-width: 0; }
.projbar .chip { flex: 0 1 auto; min-width: 0; }
.projbar-acct { order: 10; }
.projbar .proj { min-width: 96px; }
/* logo i prva radnja se ne dodiruju — jedan predah, pa traka počinje */
.projbar-brand { margin-right: 2px; }
/* natpis „Novi projekat" ostaje NAPISAN na svakoj širini; ako nema mesta,
   skraćuje se sa tri tačke, a ne u znak. Nijedno ime se ne piše u CSS-u, pa
   ovo radi na svih trinaest jezika. */
.projbar #btn-new { max-width: 150px; }
.projbar #btn-new > span {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; display: inline-block;
  vertical-align: bottom; max-width: 108px;
}

@media (max-width: 980px) {
  /* §42.5 — grupa i dalje dobija svoj red (tako je i bilo), ali NALOG ide pre
     nje. Cela greška je bila u tome što grupa ima `order:9`, a nalog nije imao
     nijedan — dakle 0 — pa je po pravilima flexbox-a ispadao PRE grupe, i
     „◎ Sken prostora" je završavao desno od naloga, pa i preko njega:
     **mereno na 390 px, sken x=322 · nalog x=338; na 844 px se `.projbar-btns`
     i `#projbar-acct` preklapaju.** Sada je nalog poslednji na prvom redu, a
     grupa sama u svom — dakle levo od naloga i ispod njega, nikad desno. */
  /* Ovde traka JOŠ NE prelama (`flex-wrap:nowrap` važi do 760 px), pa
     `flex:1 0 100%` ne pravi novi red nego preliv: **mereno na 844×390,
     „◎ Sken prostora" na x=714 u traci širine 744.** Grupa se zato skuplja i
     kliza u sebi (ona je `.slidebar`, §38.3); svoj red dobija tek tamo gde
     traka zaista prelama. Nalog ostaje poslednji (`order:10`), pa je grupa
     levo od njega — što je i tražено. */
  .projbar .projbar-btns { order: 9; flex: 0 1 auto; width: auto; min-width: 0; }
}
@media (max-width: 760px) {
  /* §42.3 — traka ovde PRELAMA, pa svaki red mora da bude smišljen:

       1. znak, „+ Novi projekat", „Sačuvaj", čipovi, nalog
       2. projekat — ceo red, jer mu ime i jeste ono što se čita
       3. „◎ Sken prostora" i „QR / AR" — kliza ako ne stane

     Projekat je do sada imao `order:-1`, dakle išao je PRE loga — doslovna
     vlasnikova primedba „upada projekti iza ili ispred logoa". Sada je iza
     prvog reda, cele širine, pa se ne stiska ni na koga: **mereno na 390 px,
     16 px širine pre, ceo red posle.** Nalog zatvara prvi red, grupa ide
     ispod njega — nikad desno od njega (§42.5). */
  /* Selektori su namerno za jednu klasu duži: blok `@media (max-width:980px)`
     stoji NIŽE u fajlu i takođe važi na 390 px, pa bi na jednakoj
     specifičnosti pobedio on.

     Isti razlog i za `flex-wrap`. Gore u fajlu piše `.projbar{flex-wrap:wrap}`
     baš za telefon, ali NIŽE stoji `.projbar{flex-wrap:nowrap}` iz pravila
     „traka je jedan red" — jednaka specifičnost, kasniji pobeđuje, pa se traka
     na telefonu nikad nije prelomila: **mereno na 390 px, `flex-wrap:nowrap` i
     „◎ Sken prostora" na x=582 u prozoru od 390.** */
  .projbar { flex-wrap: wrap; max-height: none; row-gap: 6px; }
  .projbar .proj { order: 5; flex: 1 0 100%; width: 100%; max-width: none; min-width: 0; }
  .projbar .projbar-acct { order: 4; }
  .projbar .projbar-btns { order: 9; flex: 1 0 100%; width: 100%; }
}

/* ══ §24.1 — the header, at every width ══════════════════════════════════
   The bar is one row that never wraps and never scrolls the account off the
   end: the account is pinned last and everything before it gives way in a
   fixed order — first the project's subtitle, then the chips, then the
   button labels, then the brand name. What is left at 375 px is the mark,
   two icon buttons, the project name and the account, and they all fit.

   `position: sticky` on the account inside a scrolling row keeps it visible
   even in the one case where the row does have to scroll (a very long
   project name on a very narrow screen), which is the whole reason it used
   to be `fixed` in the first place. */
.projbar-acct {
  flex: 0 0 auto; display: flex; align-items: center;
  position: sticky; right: 0; z-index: 3; margin-left: 6px;
  padding-left: 8px;
  background: linear-gradient(to right, transparent, var(--surface-2) 10px);
}
.projbar-acct .pop-host { position: relative; }
.projbar-acct .pop-btn { height: 34px; }

/* A chip carries a sentence sometimes („5 materijala iz ovog projekta nije u
   vašoj biblioteci"), and a sentence in a one-line bar pushes everything
   after it off the end — measured at 1280 px: 107 px of the row hanging past
   the window. Capped and elided; the whole text is the tooltip and the dialog
   it opens. */
.projbar .chip {
  max-width: 210px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

@media (max-width: 1180px) {
  /* the subtitle (client · city) is the first thing a joiner already knows */
  .projbar .proj .psub { display: none; }
  .projbar .proj { max-width: 180px; }
}
@media (max-width: 980px) {
  /* Chips are shortcuts to something that has its own screen: the counts
     chip opens the estimate, the material chip opens the mapping dialog (and
     the same warning arrives as a toast on import), the database chip is a
     one-off notice. On a narrow bar they are what gives way — measured at
     375 px they ran to x=515 in a 375 px window and pushed the account under
     them. */
  .projbar #project-meta,
  .projbar #db-chip,
  .projbar #mat-chip { display: none; }
  /* §38.6 — ovde je stajalo `display:none`, sa obrazloženjem da QR / AR postoji
     i u traci kartica. Ali u toj grupi je i **„◎ Sken prostora"**, koga nema
     nigde drugde — pa na telefonu dugmeta za sken prostorije jednostavno NIJE
     BILO. Mereno: `.projbar-btns` širine 0 px na 390 i na 844 px, sken
     „nevidljivo". Grupa sada ostaje i kliza (§38.3): stane koliko stane, a
     ostatak se izvuče prstom. */
  /* Grupa dobija SVOJ red i u njemu kliza. Bez toga se, na 390 px, popela
     ispod dugmeta naloga — mereno: „◎ Sken prostora" ispod `#btn-account`. */
  .projbar-btns { display: flex; order: 9; width: 100%; min-width: 0; flex: 1 0 100%; }
  .projbar-btns .btn { white-space: nowrap; }
  .projbar #save-chip { max-width: 92px; overflow: hidden; text-overflow: ellipsis;
    white-space: nowrap; }
}
@media (max-width: 820px) {
  .projbar .brand .name { display: none; }  /* the mark alone is the logo */
  .projbar .brand .tag { display: none; }
  .projbar .proj { max-width: 140px; }
  .projbar-acct .pop-btn .cap { display: none; }   /* initials only */
  .projbar-acct .pop-btn { padding: 0 9px; }
}
@media (max-width: 620px) {
  /* §42.3 — „Sačuvaj" postaje svoj znak, jer je znak ⤓ svima isti i jer se ta
     radnja radi retko. „+ Novi projekat" NE postaje znak: to je prva radnja u
     programu i vlasnikova primedba je doslovno „ne vidi se tekst novi
     projekat". Natpis ostaje i skraćuje se sa tri tačke — **mereno na 390 px:
     0×0 px pre, 74 px natpisa posle** — a nijedna reč se ne piše u CSS-u, pa
     to važi na svih trinaest jezika. */
  .projbar #btn-new { font-size: var(--fs-12); padding: 0 11px; max-width: 116px; }
  .projbar #btn-new::after { content: none; }
  .projbar #btn-new > span { max-width: 74px; }
  .projbar [data-act="save-as"] { font-size: 0; padding: 0 10px; }
  .projbar [data-act="save-as"]::after { content: '⤓'; font-size: var(--fs-14); }
  .projbar .chip.pencil { display: none; }   /* F2, and the project button */
  /* the save state is also the Sačuvaj button's own state */
  .projbar #save-chip { display: none; }
}

/* ══ camera views sit right in the corner ════════════════════════════════ */
.vp-hud { padding: 6px 6px 0; }
.vp-hud .z-tr { margin: 0; }
.vp-hud .z-tr > .vp-views { opacity: 1 !important; }

/* the project button must be one line high, not a paragraph.
   §45.4 — `max-width:260px` je bio i razlog zašto je naslov projekta bio
   **odsečen za 77 px (24 %)** dok je desno od njega stajalo 417 px praznog:
   dugme nije smelo da poraste ni kad ima gde. Sada raste do 820 px i uzima
   višak trake, a ispod 1200 px se vraća na staru meru jer tamo viška nema. */
.projbar .proj { flex: 1 1 auto; max-width: min(820px, 42%); }
@media (max-width: 1200px) { .projbar .proj { max-width: 260px; } }
/* Nalog se NE SME skupiti — mereno: kad je ime projekta smelo da uzme sav
   višak, nalog je pao sa 103,5 px na 8 px, tj. nestao sa trake. */
.projbar #projbar-acct { flex: 0 0 auto; min-width: 96px; }
.projbar .proj .label,
.projbar .proj .pname,
.projbar .proj .psub { white-space: nowrap; display: block; max-width: 100%; }
.projbar .proj .pname { line-height: 1.15; }


/* QR / AR, Komentari, Ponuda: one group, on the tab-bar line */
#tabbar { display: flex; align-items: stretch; gap: 2px; }
#tabbar > .chrome-client {
  margin-left: auto; display: flex; align-items: center; gap: 6px;
  padding: 6px 0 6px 12px; position: static;
}
/* §12.4 — visina po sadržaju, ne zakucana: „Komentari 2" i „Ponuda" su na
   nemačkom i ruskom viši od 30 px i seklo im se dno za 3 px. */
.tabbtn {
  display: inline-flex; align-items: center; gap: 6px; min-height: 30px; height: auto;
  padding-block: 3px;
  padding: 0 13px; border-radius: var(--r-pill); font-size:var(--fs-13); font-weight: 600;
  border: 1px solid var(--border); background: var(--surface); color: var(--ink-3);
  white-space: nowrap;
  transition: border-color var(--t-1), color var(--t-1), background var(--t-1);
}
.tabbtn:hover { border-color: var(--acc); color: var(--acc); }
.tabbtn.primary { background: var(--ink); border-color: var(--ink); color: var(--on-ink); }
.tabbtn.primary:hover { background: var(--acc); border-color: var(--acc); color: var(--on-solid); }
.tabbtn .chip { padding: 1px 5px; font-size:var(--fs-10); }

/* §24.1 — the second reserved corner. There were two of these, 100 lines
   apart, each keeping the bar clear of the fixed account button; the bar
   contains the account now, so both are gone. */
@media (max-width: 760px) {
  #tabbar > .chrome-client { padding-left: 8px; }
  .tabbtn { min-height: 28px; height: auto; padding: 3px 10px; font-size:var(--fs-12); }
}

/* ══ §19.10 — the stock screen ══════════════════════════════════════════ */
.stock-head { display: flex; flex-direction: column; gap: 12px; margin-bottom: 12px; }
.stock-head .inp { min-width: 260px; flex: 1 1 260px; max-width: 420px; }
.stock-kpis { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 10px; }
.stock-kpi { background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-8);
  padding: 11px 13px; }
.stock-kpi b { display: block; font-size:var(--fs-19); font-weight: 700; letter-spacing: -.03em; }
.stock-kpi span { display: block; font-family: var(--mono); font-size:var(--fs-10); letter-spacing: .1em;
  text-transform: uppercase; color: var(--mut); margin-top: 3px; }

.c-stock2 { display: grid; align-items: center; gap: 10px;
  grid-template-columns: minmax(150px, 2.2fr) 56px 68px 82px 74px 68px 96px 118px; }
.c-stock2 .nm { font-size:var(--fs-13); font-weight: 600; min-width: 0; }
.c-stock2 .nm em { display: block; font-style: normal; font-size:var(--fs-10);
  color: var(--mut); margin-top: 2px; }
.c-stock2 .dim { font-size:var(--fs-12); color: var(--ink-3); text-align: right; }
.c-stock2 .dim.warn { color: var(--warn); font-weight: 600; }
.tbl-foot { display: flex; justify-content: space-between; align-items: center;
  padding: 10px 14px; border-top: 1px solid var(--line); font-size:var(--fs-12); color: var(--mut); }

.move-row { display: grid; grid-template-columns: 24px 1fr auto auto; gap: 10px;
  align-items: center; padding: 7px 0; border-bottom: 1px solid var(--line-3); }
.move-row:last-child { border-bottom: 0; }
.move-row .ic { width: 22px; height: 22px; border-radius: 50%; display: grid; place-items: center;
  font-size:var(--fs-12); background: var(--surface-4); color: var(--ink-3); }
.move-row .ic.ok { background: var(--ok-soft); color: var(--ok); }
.move-row .ic.warn { background: var(--warn-soft); color: var(--warn); }
.move-row .nm { font-size:var(--fs-13); min-width: 0; }
.move-row .nm em { display: block; font-style: normal; font-size:var(--fs-10); color: var(--mut); }
.move-row .q { font-size:var(--fs-12); font-weight: 600; }
.move-row .q.ok { color: var(--ok); } .move-row .q.warn { color: var(--warn); }
.move-row .d { font-size:var(--fs-10); color: var(--mut); white-space: nowrap; }

@media (max-width: 1100px) {
  .c-stock2 { grid-template-columns: minmax(120px, 2fr) 52px 62px 70px 66px 108px; }
  .c-stock2 > :nth-child(6), .c-stock2 > :nth-child(7) { display: none; }
}
@media (max-width: 700px) {
  .c-stock2 { grid-template-columns: 1fr 62px 96px; }
  .c-stock2 > :nth-child(2), .c-stock2 > :nth-child(4) { display: none; }
}


/* ══ §19.9 — the cutting list is a document, so let it be seen ══════════
   The floating chrome (account stack, client buttons, language chip) belongs
   to the 3D editor. On the cut list it is just something in front of the
   drawing, so it steps aside; the list gets the full width and its own
   scroll. */
.app-body[data-view="cut"] #chrome-stack,
.app-body[data-view="cut"] #chrome-lang { opacity: .25; transition: opacity var(--t-1) var(--ease); }
.app-body[data-view="cut"] #chrome-stack:hover,
.app-body[data-view="cut"] #chrome-lang:hover { opacity: 1; }
.app-body[data-view="cut"] .app-content { padding: 10px 12px calc(10px + var(--safe-b)); }

#cut-host { height: 100%; min-height: 0; }
#cut-host .nest { height: 100%; }
.view[data-view="cut"] { height: 100%; }

/* ══ §19.3 – §19.7 — the part editor panel ══════════════════════════════ */
.pe-panel {
  width: min(340px, 100%);
  background: color-mix(in srgb, var(--surface) 92%, transparent);
  backdrop-filter: blur(14px) saturate(1.3); -webkit-backdrop-filter: blur(14px) saturate(1.3);
  border: 1px solid var(--line); border-left: 3px solid var(--acc);
  border-radius: var(--r-10); box-shadow: var(--sh-3);
  opacity: 0; transform: translateY(12px) scale(.985);
  transition: opacity var(--t-1) var(--ease), transform var(--t-1) var(--ease);
  max-height: 100%; overflow: auto;
}
.pe-panel.in { opacity: 1; transform: none; }
.pe-hd { display: flex; align-items: flex-start; gap: 10px; padding: 12px 12px 8px; }
.pe-title { font-size:var(--fs-15); font-weight: 700; letter-spacing: -.02em; margin-top: 2px; }
.pe-sec { padding: 10px 14px; border-top: 1px solid var(--line-2); }
.pe-edges { display: grid; grid-template-columns: 1fr 1fr; gap: 5px; margin-top: 7px; }
.pe-edge {
  padding: 7px 9px; border: 1px solid var(--border); border-radius: var(--r-6);
  font-size:var(--fs-12); background: var(--surface); color: var(--ink-3);
  transition: border-color var(--t-1), background var(--t-1), color var(--t-1);
}
.pe-edge:hover { border-color: var(--acc); color: var(--acc); }
.pe-edge.on { background: var(--danger); border-color: var(--danger); color: var(--on-solid); font-weight: 600; }
.pe-ctl { display: grid; grid-template-columns: 86px 1fr 46px; gap: 8px;
  align-items: center; margin-top: 7px; }
.pe-ctl .lbl { font-size:var(--fs-11); color: var(--mut); }
.pe-ctl .v { font-size:var(--fs-11); text-align: right; color: var(--ink-3); }
.pe-ctl input[type=range] { width: 100%; }
.pe-ft { display: flex; gap: 8px; padding: 10px 12px 12px; border-top: 1px solid var(--line-2); }
.pe-ft .btn { flex: 1; }
[data-ul-mirror].on { background: var(--acc); border-color: var(--acc); color: var(--on-solid); }
@media (max-width: 760px) { .pe-panel { width: 100%; max-height: 46vh; } }

/* ══ §T2 — EDITOR PLOČE: ZAGLAVLJE I PODNOŽJE STOJE, KLIZA SAMO TELO ═══════
   Panel je bio JEDNA kutija za klizanje: mereno na 1440 × 900, kutija 243 px
   za 1226 px sadržaja, a dugme „Primeni oblik" na y = 1142 — 242 px ISPOD
   dna prozora od 900 px. Do njega se nije stizalo ni klizanjem panela, jer je
   panel bio niži od svog sadržaja a dugme deo tog sadržaja. Isto na 1920
   (kutija 300 : sadržaj 887) i na 1024 (200 : 1024).

   Dva razloga, oba popravljena ovde:

   1. DONJI RED HUD-A NIJE IMAO SVOJU VISINU. Red je `auto`, a `.z-bl` uzima
      `max-height:100%` od njega — dakle onoliko koliko red slučajno ispadne.
      Panel mašine je taj isti problem već rešio klasom `cnc-on`; editor ploče
      dobija svoju, `pe-on`, i isti postupak — i isti udeo, 56 %, da se dva
      panela istog radnog prostora ne ponašaju različito.
   2. KLIZALO JE SVE. Sada kliza samo ono što sme: telo editora oblika
      (`#pep-body`) i kutija sa ređe korišćenim odeljcima (`#pe-rest`).
      Zaglavlje panela, prekidač režima, podnožje editora oblika sa „Primeni
      oblik" i podnožje panela sa „Gotovo" STOJE — dugme koje se mora tražiti
      klizanjem je za čoveka sa papira dugme koje ne postoji (§46.5).

   ZAŠTO 56 %, A NE VIŠE. Alatnica (`#vp-tools`) stoji u istoj koloni, u redu
   iznad, i sa 7 dugmadi je visoka 309 px; kad njen red ostane kraći, ona se
   `overflow:visible` **preliva preko panela ispod sebe**. Mereno: na 68 %
   preklapala je 162 / 232 / 262 px panela na 1920 / 1440 / 1024, na 56 %
   **41 / 133 / 179 px**, a nijedna kontrola panela se time ne gubi (mereno
   `elementFromPoint` nad svakom: 0 zaklonjenih). „Primeni oblik" je i na
   56 % dohvatljivo bez klizanja na sve tri širine — jer je uz to izbačeno
   dvostruko zaglavlje (v. niže). Samo prelivanje alatnice je zaseban nalaz i
   stoji u `docs/CEKLISTA.md` kao T2c. */
#viewport.pe-on .vp-hud { grid-template-rows: auto minmax(0, 1fr) minmax(0, 56%) auto; }

/* §T2 · §46.5 — JEDNO ZAGLAVLJE, NE DVA. Panel je ime komada i njegove mere
   pisao DVAPUT: `.pe-hd` („EDITOR KOMADA · Ploča · 2742 × 509 × 18 mm") i,
   odmah ispod, `.pep-hd` („EDITOR PLOČE · 2742 × 509 × 18 mm"). To je 34 px
   visine za podatak koji već stoji red iznad — a tih 34 px su tačno ono što
   je na 1024 × 768 falilo da „Primeni oblik" uđe u prozor. Zaglavlje editora
   oblika se zato ne crta dok je usidren u panelu komada; kad panela nema,
   ono se vidi kao i pre. */
#pe-panel > .pe-poly > .pep-hd { display: none; }

/* `overflow-y:auto`, a ne `hidden`, i to je mereno: na 844 × 390 zona je 103 px
   — manje nego što zaglavlje, prekidač režima i dva podnožja UOPŠTE mogu da
   stanu. Sa `hidden` bi tu bilo odsečeno 218 px i „Primeni oblik" ne bi
   postojao ni uz klizanje. Ovako se na uskom ekranu panel vrati na jednu
   kutiju za klizanje (kao pre), a svuda gde ima mesta stoje i zaglavlje i
   podnožje. Gore je isečeno dugme nego dugme do kog se kliza. */
.pe-panel { display: flex; flex-direction: column; min-height: 0; overflow-y: auto; }
.pe-panel > .pe-hd,
.pe-panel > .pe-ft { flex: 0 0 auto; }
/* Editor oblika ima prednost — on je ono što je u rukama dok je otvoren.
   `min-height:0` mu dozvoljava da se skupi (telo unutra kliza), a pod od
   134 px je IZMEREN, nije pogođen: prekidač režima 39 + podnožje sa „Primeni
   oblik" 52 = 91 px koji se ne skupljaju, plus 43 px za jedan red polja.
   Bez tog poda bi na 844 × 390 (zona 103 px) podnožje ispalo iz svoje kutije
   i preklopilo odeljke ispod. */
.pe-panel > .pe-poly { flex: 1 1 auto; min-height: min(134px, 100%);
  display: flex; flex-direction: column; }
/* ostali odeljci se skupljaju prvi (stostruko brže), ali nikad ispod trake u
   kojoj se vidi bar jedan naslov — panel koji nestane nije rešenje */
.pe-panel > .pe-rest { flex: 0 100 auto; min-height: 44px; overflow-y: auto;
  overscroll-behavior: contain; }
.pe-poly > .pep-hd,
.pe-poly > .pep-modes,
.pe-poly > .pep-hint,
.pe-poly > .pep-ft { flex: 0 0 auto; }
.pe-poly > .pep-body { flex: 1 1 auto; min-height: 0; overflow-y: auto;
  overscroll-behavior: contain; padding-bottom: 9px; }
/* podnožje editora oblika je linija razdvajanja od odeljaka ispod njega */
.pe-poly > .pep-ft { border-top: 1px solid var(--line-3); }

/* ═══════════════ §19.8 — boolean dialog ═══════════════ */
.bool-list { display: flex; flex-direction: column; gap: 6px; margin-top: 10px;
  max-height: 46vh; overflow: auto; }
.bool-row { display: grid; grid-template-columns: auto minmax(0, 1fr) auto;
  gap: 10px; align-items: center; padding: 9px 11px; cursor: pointer;
  border: 1px solid var(--line); border-radius:var(--r-8); background: var(--card); }
.bool-row:hover { border-color: var(--blue); }
.bool-row .nm { min-width: 0; font-weight: 600; font-size:var(--fs-13); }
.bool-row .nm em { display: block; font-style: normal; font-weight: 400;
  font-size:var(--fs-12); color: var(--mut); font-family: var(--mono);
  margin-top: 2px; overflow-wrap: anywhere; }
.bool-row .chip { font-size:var(--fs-10); letter-spacing: .06em; padding: 3px 7px;
  border-radius: var(--r-pill); font-family: var(--mono); white-space: nowrap; }
.bool-row .chip.ok { background: rgba(31,95,208,.12); color: var(--blue); }
.bool-row .chip.warn { background: rgba(196,120,26,.15); color: #b4700f; }

/* ═══════════════ §20.1 — Materijali ═══════════════ */
.mat-head { display: flex; gap: 10px; align-items: center; flex-wrap: wrap;
  margin-bottom: 12px; }
.mat-head .inp { flex: 1 1 240px; min-width: 0; max-width: 420px; }
.mat-head .tiny { color: var(--mut); white-space: nowrap; }
.mat-card { position: relative; }
.mat-card .ft { display: flex; justify-content: space-between; align-items: center;
  gap: 8px; font-size:var(--fs-11); }
.mat-card .ft .mono { color: var(--mut); }
.mat-card .thb { font-weight: 700; padding: 2px 7px; border-radius: var(--r-pill); }
.mat-card .thb.file { background: rgba(31,95,208,.12); color: var(--blue); }
.mat-card .thb.typed { background: rgba(31,122,74,.14); color: #1f7a4a; }
.mat-flag { position: absolute; top: 7px; right: 7px; font-size:var(--fs-9);
  letter-spacing: .06em; padding: 2px 6px; border-radius: var(--r-pill);
  background: rgba(196,120,26,.16); color: #b4700f; font-family: var(--mono); }
.mat-empty { grid-column: 1 / -1; padding: 26px 18px; text-align: center;
  border: 1px dashed var(--line); border-radius:var(--r-10); color: var(--mut); }
.ins-f.th-f input { font-weight: 700; }
.mat-note { margin: 2px 0 4px; color: var(--mut); line-height: 1.45; }

/* §2.6 — the pencil that opens the project details */
/* §12.4 — ista priča kao `.tabbtn`: `line-height:1` uz zakucanu visinu čipa
   seče dno slova sa donjim produžetkom (ć, ц, ş) za 3 px. */
.projbar .chip.pencil { padding: 3px 9px; font-size:var(--fs-13); line-height: 1.2;
  height: auto; min-height: 26px; border-color: var(--line); color: var(--mut); }
.projbar .chip.pencil:hover { color: var(--acc); border-color: var(--acc-line-2); }
.projbar .psub { display: block; font-size:var(--fs-11); color: var(--mut);
  font-family: var(--mono); letter-spacing: .02em; margin-top: 1px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 260px; }

/* ══════════════════ §2.3 — the section menu previews itself ═══════════════
   A tab was a full-screen swap and nothing else, so you had to leave the scene
   to find out whether the cutting list had anything in it. Hovering a tab now
   drops this panel under the bar with the live figures of that area. It is
   `position:absolute` against the app column, never blocks the click, and only
   exists where hovering means something (`pointer:fine`, wired in ui.js). */
.tab-peek {
  position: absolute; z-index: 40; margin-top: 4px;
  min-width: 190px; max-width: 300px;
  padding: 10px 12px 11px;
  background: color-mix(in srgb, var(--surface) 94%, transparent);
  backdrop-filter: blur(14px) saturate(1.2);
  -webkit-backdrop-filter: blur(14px) saturate(1.2);
  border: 1px solid var(--line); border-radius: var(--r-10);
  box-shadow: var(--sh-3);
  opacity: 0; transform: translateY(-6px); pointer-events: none;
  transition: opacity var(--t-1) var(--ease), transform var(--t-1) var(--ease);
}
.tab-peek.on { opacity: 1; transform: none; pointer-events: auto; }
.tab-peek .tp-h { font-size: var(--fs-13); font-weight: 700; letter-spacing: -.01em; }
.tab-peek .tp-d { font-size: var(--fs-12); color: var(--mut); margin-top: 3px; line-height: 1.45; }
.tab-peek .tp-facts { display: flex; flex-wrap: wrap; gap: 4px 10px; margin-top: 9px;
  padding-top: 8px; border-top: 1px solid var(--line); }
.tab-peek .tp-f { font-family: var(--mono); font-size: var(--fs-11); color: var(--mut); }
.tab-peek .tp-f b { color: var(--ink); font-weight: 700; }

/* the bar is the anchor, so the panel can sit under the tab it belongs to */
.app-main { position: relative; }

/* on a touch screen a tap is a tap — never a preview */
@media (pointer: coarse) { .tab-peek { display: none; } }

/* §15.2b — the equation bar is dragged by its header */
.fx-hd { cursor: grab; user-select: none; touch-action: none; }
.fx.dragging { cursor: grabbing; box-shadow: var(--sh-4); }
.fx.dragging .fx-hd { cursor: grabbing; }
/* Once it has been moved it leaves its HUD cell and is placed against the
   editor. The zone rule that neutralises positioning inside the HUD
   (`.vp-hud .z-br > .fx { position: static !important }`) has to be beaten
   explicitly — that rule is why the first attempt saved a position and then
   did not move a pixel. */
.vp-hud .z-br > .fx[data-moved],
.fx[data-moved] {
  position: absolute !important;
  left: var(--fx-x) !important; top: var(--fx-y) !important;
  right: auto !important; bottom: auto !important;
  margin: 0 !important; z-index: 22;
}


/* ══ §29.2 / §27.4 — meni koji visi iz trake ═══════════════════════════════
   Meni se pozicionira skriptom u odnosu na svoje dugme i stoji u FIKSNOM
   sloju: tako ga nijedan roditelj sa `overflow` ne može preseći i nijedan
   `stacking context` gurnuti iza sebe. Jedan sloj za sve iskačuće menije,
   uzet iz iste lestvice kao modal (200) i traka (100). */
.newmenu.open { position: fixed; z-index: var(--z-pop); }


/* ══════════════════════════════════════════════════════════════════════════
   §41.8 — RAZMAK JE JEDNAK SA OBE STRANE POVLAČNE LINIJE
   „padding jednak od ivice do te linije i od linije do druge ivice"

   Dve stvari, i obe se mere:

     1. linija po sredini SVOJE kutije — to je već važilo (3 / 3 px), i
        ostaje;
     2. linija po sredini PROCEPA koji deli — a to nije važilo. Editor ima
        `gap:8px` između panela i prikaza; splitter je bio `left:calc(var(
        --w-left) + 1px)` i širok 9 px, pa je linija od 2 px padala na 4.5 px
        od panela i 1.5 px od prikaza. **Mereno na 1024 px: 1.5 / 4.5 px.**

   Zato procep dobija ime (`--ed-gap`) i splitter se računa iz njega: kutija
   je široka koliko treba da se uhvati, ali joj je SREDINA sredina procepa,
   pa je razmak sa obe strane isti na svakoj širini.                        */
.editor { --ed-gap: 8px; --split-w: 10px; }
.split-v { width: var(--split-w); }
.split-h { height: var(--split-w); }
.split-v[data-split=left] {
  left: calc(var(--w-left) + var(--ed-gap) / 2 - var(--split-w) / 2);
}
.split-v[data-split=right] {
  right: calc(var(--w-right) + var(--ed-gap) / 2 - var(--split-w) / 2);
}
.split-h[data-split=bottom] {
  bottom: calc(var(--h-bottom) + var(--ed-gap) / 2 - var(--split-w) / 2);
}

/* ══ §42.7 — RAZMACI BOČNIH PANELA ═════════════════════════════════════════
   „još nisi sredio paddinge editora za one sa strane"

   Zaglavlje svakog bočnog panela je nosilo `padding:8px 8px 8px 12px` — dakle
   12 px levo i 8 px desno, na svakom panelu u editoru. Naslov je počinjao
   dalje od ivice nego što je dugme sa druge strane završavalo, i to se vidi
   jer je ispod njega telo panela sa svojih ravnih 8 px (`.tree`) odnosno
   12 px (`.insp`). Jedan broj za ceo panel, isti levo i desno, i telo i
   zaglavlje počinju na istoj uspravnoj liniji.                              */
.editor { --panel-pad: 10px; }
.editor .panel .panel-hd { padding: 8px var(--panel-pad); }
.editor .panel .tree,
.editor .panel .insp { padding-left: var(--panel-pad); padding-right: var(--panel-pad); }


/* ══ §30.6 — pilula u svojoj ćeliji: po sredini, po meri teksta ══════════ */
.vp-hud .z-tc { justify-self: center; }
.vp-hud .z-tc > .hint-pill { width: max-content; max-width: 100%; margin-inline: auto; }

/* ══ §30.3 — editor popunjava svoj prostor ═══════════════════════════════
   `.view` je bila `height:auto`, pa je editor — koji traži `height:100%` —
   računao 100 % od NIČEGA i ostajao niži od strane. Ispod njega je ostajao
   pojas praznog papira. Mereno: sadržaj 565 px, editor 461 px, 98 px praznog. */
.app-content.scene-mode { display: flex; flex-direction: column; }
.app-content.scene-mode > .view[data-view=scene] { flex: 1 1 auto; min-height: 0; height: auto; }
.app-content.scene-mode > .view[data-view=scene] > .editor { height: 100%; min-height: 0; }


/* ══════════════════════════════════════════════════════════════════════════
   §41.10 — NA USKOM TELEFONU DONJA TRAKA PRELAMA, NE KLIZA

   Klizanje u stranu je ovde ista greška kao na traci projekta (§31.1): ono što
   je izašlo iz vidnog polja za korisnika ne postoji. Sa dva nova polja za upis
   traka na 390 px traži 477 px u prikazu od 360 — **mereno, `node tools/fit.js
   --only app` je javio „−" kao nedohvatljivo dugme.** Uspravan telefon ima
   visine napretek, pa traka dobija drugi red i sve stoji na ekranu.

   Sve što je iznad nje mora da se popne za tu razliku, jer je do sada računalo
   sa trakom od 40 px: traka alata, ručka donjeg panela, klizač razbijanja i
   pad za let. Ovaj blok stoji na KRAJU fajla namerno — pravila koja pomera
   pisana su niže od mesta gde bi inače stajao. */
@media (max-width: 620px) {
  .vp-hud .z-ft > .vp-foot {
    flex-wrap: wrap; height: auto; overflow: visible; row-gap: 4px;
    padding-top: 5px; padding-bottom: calc(5px + var(--safe-b));
  }
  .vp-hud .z-l > #vp-tools { bottom: calc(76px + var(--safe-b)) !important; }
  .editor .grab.h,
  .editor.no-bottom .grab.h { bottom: calc(76px + var(--safe-b)); }
  .vp-hud .z-bl, .vp-hud .z-bc, .vp-hud .z-br { padding-bottom: calc(92px + var(--safe-b)); }
  .vp-explode { bottom: calc(140px + var(--safe-b)); }
  .vp-drone { bottom: calc(140px + var(--safe-b)); }
  .cnc-panel { bottom: calc(140px + var(--safe-b)); }
}

/* §45.4 — na telefonu se traka prelama; tamo „gurni nalog udesno" pravi rupu
   od 63 px usred prelomljenog reda umesto da je zatvori. Mereno na 390 px. */
@media (max-width: 620px) {
  .projbar #projbar-acct { margin-left: 0; }
}

/* §45.1/N6 — sažetak („182 delova · 379 bušenja · 83,66 m²") se ranije sekao
   USRED CIFRE („…83.6"), pa se odsečen broj čitao kao pogrešan podatak. Tri
   tačke su znak da tekst ide dalje; bez njih je to tvrdnja. */
.projbar #project-meta,
.projbar .chip {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* ══════════ §53.3 — PRST, POSLEDNJI PROLAZ ═══════════════════════════════
   Ovaj blok stoji NA KRAJU fajla namerno. Sve u njemu je jednako specifično
   kao pravilo koje ispravlja (`.tabbtn`, `#explode`, `.chip.pencil`…), pa
   odlučuje redosled u fajlu. Ista pravila 900 linija iznad nisu radila —
   mereno: `.tabbtn` je i sa `min-height:44px` ostajao 32 px, jer ga je
   `.tabbtn{ min-height:30px }` niže u fajlu tiho vraćao.

   Redosled merenja koji je do ovoga doveo: 276 → 140 → 79 meta ispod 44 px.
   Ono što je ostalo posle drugog prolaza bilo je tačno dve vrste:
   kontrole koje je prepisalo pravilo niže u fajlu, i kontrole kojima
   nevidljivo dete nije pomoglo jer se širilo u tuđ prostor — susedni čvor
   koji se crta kasnije uzme dodir sebi. Te druge rastu, jer je jedina
   poštena mera ona koju prst zaista pogodi. */
@media (pointer: coarse) {

  /* Rastu — imaju gde. */
  .tabbar .tabbtn,
  .chrome-client .tabbtn { min-height: 44px; min-width: 44px; }
  .projbar .chip.pencil { min-height: 44px; min-width: 44px; padding: 0 9px; }
  #btn-part-edit,
  #vv-toggle,
  #btn-lang,
  .btn.btn-sm { min-height: 44px; min-width: 44px; }
  #macros-chip-why { min-height: 44px; }

  /* Klizač debljine sloja je bio 18 px visok — prst na njemu ne pogađa
     ručicu nego traku pored nje. Traka ostaje tanka, kutija dobija 44. */
  input[type=range] { min-height: 44px; }

  /* Ručka panela: nevidljivo dete jeste bilo 44 px, ali je pola njega padalo
     na panel koji se crta posle nje, pa je izmereno 32 px. Ručka se diže
     iznad oba suseda — iznad cepača (9) i iznad panela — samo na dodiru. */
  .grab { z-index: 12; }
}

/* ── §53.3 · treći prolaz: HUD i ručke ─────────────────────────────────── */
@media (pointer: coarse) {
  /* Zum u traci nad scenom: bio 24 × 27. Susedi su mu „−", broj i „+" — broj
     nije meta, pa širenje u njegov prostor ništa ne otima. */
  .hud-group > button { min-height: 44px; min-width: 44px; }

  /* SNAP i korak rotacije nose glif u `::after` (r. 176–177), pa nevidljivo
     dete mora na `::before`. Da je stavljeno na `::after`, glif bi nestao —
     jedan bi kvar zamenio drugi. */
  #snap-chip, #rot-chip { position: relative; min-height: 44px; min-width: 44px; }
  #snap-chip::before, #rot-chip::before { content: ""; position: absolute;
    left: 50%; top: 50%; width: max(100%, 44px); height: 44px;
    transform: translate(-50%, -50%); }
  /* Sama visina je morala da poraste uz nevidljivo dete: dete je davalo 44 px,
     ali ga je traka nad scenom isecala na 34 — mereno. Traka time raste sa 34
     na 44 px, i to je jedini piksel koji je ceo ovaj posao uzeo sceni. */

  /* Ručka panela: nevidljivo dete je isecao roditelj (mereno 32 px umesto
     44), pa se umesto njega širi SAMA šipka — tačnije traka u kojoj stoji.
     Sklopljen panel je time pun dodirni cilj od 44 px, a ne igla od 14.
     Šipka koja se vidi ostaje 4 px: menja se prostor, ne izgled. */
  .editor { --rail-w: 44px; }
}
