:root {
  --chrome: #e8ebee;
  --chrome-2: #f3f5f7;
  --panel: #fbfbfc;
  --line: #cdd4da;
  --line-soft: #e1e5e9;
  --ink: #1d2226;
  --muted: #5d6873;
  --faint: #9aa3ab;
  --accent: #1a6fc4;
  --invalid: #e03131; /* what has no valid geometry left; the literal of colors.INVALID, tied by its test */
  --accent-soft: #dbe8f6;
  --accent-edge: #afcdee;
  --file: #1f5fa6;
  --font: "Segoe UI", system-ui, -apple-system, sans-serif;
  --mono: "Cascadia Mono", Consolas, "Courier New", monospace;
}

* { box-sizing: border-box; }
[hidden] { display: none !important; }
html, body { height: 100%; margin: 0; }
body {
  font: 12.5px/1.35 var(--font);
  color: var(--ink);
  background: var(--chrome);
  overflow: hidden;
  user-select: none;
}
button { font: inherit; color: inherit; cursor: default; }
button:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.mono { font-family: var(--mono); font-variant-numeric: tabular-nums; }

#app {
  display: grid;
  grid-template-rows: 34px 88px 30px minmax(0, 1fr) 24px;
  height: 100vh;
}

/* Top bar: File, Quick Access Toolbar, ribbon tabs */
#topbar {
  display: flex;
  align-items: stretch;
  gap: 6px;
  background: var(--chrome-2);
  border-bottom: 1px solid var(--line);
}
.file-button {
  border: 0;
  padding: 0 20px;
  background: var(--file);
  color: #fff;
  font-weight: 600;
}
.file-button:hover, .file-button[aria-expanded="true"] { background: #184f8c; }
#qat {
  display: flex;
  align-items: center;
  gap: 1px;
  padding: 0 8px 0 2px;
  border-right: 1px solid var(--line-soft);
}
.qat-btn {
  width: 28px;
  height: 26px;
  display: grid;
  place-items: center;
  border: 1px solid transparent;
  border-radius: 3px;
  background: none;
}
.qat-btn svg { width: 17px; height: 17px; }
.qat-btn:hover:not(:disabled) { background: var(--accent-soft); border-color: var(--accent-edge); }
.qat-btn:disabled { color: var(--faint); }
#ribbon-tabs { display: flex; align-items: flex-end; gap: 2px; }
.tab {
  padding: 6px 14px 7px;
  border: 1px solid transparent;
  border-bottom: 0;
  border-radius: 3px 3px 0 0;
  background: none;
  color: var(--muted);
}
.tab:hover { color: var(--ink); }
.tab[aria-selected="true"] {
  margin-bottom: -1px;
  background: var(--panel);
  border-color: var(--line);
  color: var(--ink);
  font-weight: 600;
}
.app-version { margin-left: auto; align-self: center; color: var(--muted); }
/* The "?" button of the top bar: flat, next to the version, and it carries the right margin
   the version used to give the pair (M15-62). */
#help-button {
  align-self: center;
  width: 24px;
  height: 24px;
  margin: 0 12px 0 6px;
  padding: 0;
  border: 0;
  border-radius: 3px;
  background: none;
  color: var(--muted);
  line-height: 1;
}
#help-button:hover { background: var(--accent-soft); color: var(--ink); }
#help-button:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

/* File menu */
#file-menu {
  position: fixed;
  top: 34px;
  left: 0;
  z-index: 20;
  min-width: 250px;
  padding: 4px 0;
  background: #fff;
  border: 1px solid var(--line);
  box-shadow: 0 8px 22px rgba(20, 32, 44, 0.18);
}
.menu-item {
  display: flex;
  justify-content: space-between;
  gap: 24px;
  width: 100%;
  padding: 7px 16px;
  border: 0;
  background: none;
  text-align: left;
}
.menu-item:hover:not(.later), .menu-item:focus-visible { background: var(--accent-soft); }
.menu-item.later { color: var(--faint); }
.menu-item kbd { font: 11.5px var(--mono); color: var(--muted); }
.menu-sep { height: 1px; margin: 4px 0; background: var(--line-soft); }
/* File > Milestone Samples: the item unfolds its list in place, indented under it, so it
   reads as what it is -- a second step, not another command (M14-27). */
.menu-sublist { padding: 2px 0; background: #f6f8fa; border-block: 1px solid var(--line-soft); }
.menu-subitem { padding-left: 32px; font-family: var(--mono); font-size: 12px; }
.menu-note { padding: 7px 16px 7px 32px; color: var(--muted); }

/* Ribbon */
#ribbon {
  display: flex;
  background: var(--panel);
  border-bottom: 1px solid var(--line);
  overflow-x: auto;
}
.rb-panel {
  display: grid;
  grid-template-rows: minmax(0, 1fr) 18px;
  padding: 4px 6px 0;
  border-right: 1px solid var(--line-soft);
}
.rb-buttons { display: flex; gap: 2px; }
.rb-btn {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  min-width: 54px;
  max-width: 80px;
  padding: 4px 6px;
  border: 1px solid transparent;
  border-radius: 3px;
  background: none;
}
.rb-btn svg { width: 22px; height: 22px; }
.rb-label { font-size: 11.5px; line-height: 1.15; text-align: center; }
.rb-btn:hover { background: var(--accent-soft); border-color: var(--accent-edge); }
.rb-btn.active { background: #c5daf1; border-color: #8db6e0; }
.rb-btn.later { color: var(--faint); }
.rb-btn.later:hover { background: #eef0f2; border-color: var(--line-soft); }
.rb-panel-label {
  padding-top: 1px;
  border-top: 1px solid var(--line-soft);
  color: var(--muted);
  font-size: 11px;
  text-align: center;
  white-space: nowrap;
}

/* Options Bar */
#options-bar {
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 0 10px;
  background: var(--chrome-2);
  border-bottom: 1px solid var(--line);
  white-space: nowrap;
}
.ob-context { padding-right: 14px; border-right: 1px solid var(--line); color: var(--muted); font-weight: 600; }
.ob-item { display: flex; align-items: center; gap: 6px; }
.ob-item input.field-input { width: 84px; }
.ob-item select.field-input { width: auto; min-width: 150px; }
.check { display: flex; align-items: center; gap: 5px; }

/* Side panels */
#workspace { display: grid; grid-template-columns: 276px minmax(0, 1fr); min-height: 0; }
#side {
  display: grid;
  grid-template-rows: minmax(0, 1.25fr) minmax(0, 1fr);
  min-height: 0;
  background: var(--panel);
  border-right: 1px solid var(--line);
}
.panel { display: grid; grid-template-rows: 26px minmax(0, 1fr); min-height: 0; }
.panel + .panel { border-top: 1px solid var(--line); }
.panel-title {
  margin: 0;
  padding: 5px 8px;
  overflow: hidden;
  background: var(--chrome-2);
  border-bottom: 1px solid var(--line-soft);
  font-size: 12px;
  font-weight: 600;
  text-overflow: ellipsis;
  white-space: nowrap;
}
#properties-body, #browser-body { overflow: auto; }
.type-selector { padding: 8px; border-bottom: 1px solid var(--line-soft); }
.type-selector select { width: 100%; height: 26px; }
.type-selector.static { font-weight: 600; }
.prop-count { padding: 5px 8px; color: var(--muted); border-bottom: 1px solid var(--line-soft); }
.prop-group-title { padding: 4px 8px; background: #edf0f3; border-bottom: 1px solid var(--line-soft); font-weight: 600; }
.prop-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  align-items: center;
  min-height: 27px;
  border-bottom: 1px solid var(--line-soft);
}
.prop-label { padding: 0 8px; color: var(--muted); }
/* The read-only note under "Automatic slab": it explains, it does not offer anything to
   edit, so it reads as prose and not as a field (M14-19). */
.prop-note { padding: 8px; color: var(--muted); line-height: 1.45; }
.prop-value { padding: 2px 6px 2px 0; overflow: hidden; text-overflow: ellipsis; }
.prop-caveat { margin: 4px 8px; padding: 4px 7px; background: #fff4e5; border: 1px solid #f0b46a; border-radius: 2px; color: #8a4b00; font-size: 12px; }
/* A value the file still holds but Plan will not take again: a Top Constraint level that is
   no longer above its base. The palette keeps showing it, flagged with "(not above the base)"
   and in the red of what is invalid, the same red the plan and the 3D paint that wall with
   (M14-17, FI-M14-02). The option is coloured for the open list, and properties.js puts the
   class on the <select> as well while that is the value in force, because Windows paints a
   closed select with the control's colour and not with the option's. */
select.prop-stale, option.prop-stale { color: var(--invalid); }
/* Un <option> sin color propio hereda el del <select>, así que al desplegar Top Constraint se
   veía la lista entera en rojo: solo la opción caducada lo lleva (crítico de K3 r4, C-39). */
select.prop-stale option:not(.prop-stale) { color: var(--ink); }
select.prop-stale { border-color: var(--invalid); }
.field-input {
  width: 100%;
  height: 22px;
  padding: 0 5px;
  background: #fff;
  border: 1px solid var(--line);
  border-radius: 2px;
  color: var(--ink);
  font: inherit;
  user-select: text;
}
.field-input:focus { border-color: var(--accent); outline: 2px solid var(--accent); outline-offset: -1px; }

.tree, .tree ul { margin: 0; padding: 0; list-style: none; }
.tree { padding: 6px 4px; }
.tree ul { padding-left: 14px; }
.tree-node, .tree-leaf { display: block; padding: 2px 4px; border-radius: 2px; }
button.tree-leaf { width: 100%; text-align: left; background: none; border: 0; font: inherit; color: inherit; cursor: default; }
.tree-node::before { content: "▾ "; color: var(--muted); }
.tree-leaf.active { font-weight: 700; }
.tree-leaf.later { color: var(--faint); }

/* Views */
#views {
  display: grid;
  grid-template-columns: var(--split, 50%) 5px minmax(0, 1fr);
  min-width: 0;
  min-height: 0;
}
#pane-2d { grid-column: 1; grid-row: 1; }
#divider { grid-column: 2; grid-row: 1; }
#pane-3d { grid-column: 3; grid-row: 1; }
#views.max-2d { grid-template-columns: minmax(0, 1fr) 0 0; }
#views.max-3d { grid-template-columns: 0 0 minmax(0, 1fr); }
#views.max-2d #divider, #views.max-2d #pane-3d,
#views.max-3d #divider, #views.max-3d #pane-2d { display: none; }
#views.max-3d #pane-3d { grid-column: 3; }

.pane { display: grid; grid-template-rows: 26px minmax(0, 1fr); min-width: 0; min-height: 0; background: #fff; }
.pane-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 2px 0 8px;
  background: var(--chrome-2);
  border-top: 2px solid transparent;
  border-bottom: 1px solid var(--line);
}
.pane.active .pane-head { border-top-color: var(--accent); }
.pane-title { font-weight: 600; }
.pane-max {
  width: 26px;
  height: 21px;
  display: grid;
  place-items: center;
  border: 1px solid transparent;
  border-radius: 3px;
  background: none;
  color: var(--muted);
}
.pane-max svg { width: 14px; height: 14px; }
.pane-max:hover { background: var(--accent-soft); border-color: var(--accent-edge); color: var(--ink); }
.pane-body { position: relative; min-width: 0; min-height: 0; overflow: hidden; }
.pane-body canvas { position: absolute; top: 0; left: 0; display: block; }
#c-model { pointer-events: none; }
#c-overlay:focus { outline: none; }
#c-overlay.panning { cursor: grabbing !important; }
.view3d-canvas { width: 100%; height: 100%; cursor: grab; touch-action: none; }
.view3d-canvas:focus { outline: none; }
.pane-body.placeholder {
  display: grid;
  place-items: center;
  background: repeating-linear-gradient(135deg, #f7f8fa 0 12px, #f0f2f4 12px 24px);
  color: var(--muted);
}
.placeholder p { margin: 0; padding: 10px 14px; background: #fff; border: 1px solid var(--line); border-radius: 3px; }
#divider { background: var(--line); cursor: col-resize; }
#divider:hover, #divider.dragging { background: var(--accent); }

/* Status bar */
#statusbar {
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 0 10px;
  background: var(--chrome-2);
  border-top: 1px solid var(--line);
  color: var(--muted);
  white-space: nowrap;
}
#status-prompt { flex: 1; overflow: hidden; color: var(--ink); text-overflow: ellipsis; }
/* The second fixed slot (Q-M15b-1): what Plan keeps saying until it is done with, and the
   only part of the status bar that can carry a button. It does not grow, so it never pushes
   the prompt out of the bar. */
.status-notice { display: flex; align-items: center; gap: 8px; max-width: 60%; overflow: hidden; color: var(--ink); }
.status-notice-text { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.status-notice-warn .status-notice-text { color: #684c00; }
.status-notice-error .status-notice-text { color: #8a1f11; }
.status-notice .btn-small { padding: 0 6px; font-size: 11px; line-height: 18px; }
/* M15c-16, M15c-18, M15c-22: los segmentos permanentes. No llevan boton y no se cortan con
   puntos suspensivos como el hueco fijo, porque su mitad visible es corta a proposito: la
   frase entera vive en el title. El de error va en rojo, que es lo que distingue «tu trabajo
   esta a salvo» de «no lo esta» de un vistazo. */
/* M15c-15: donde el navegador elige la impresora, en vez de un desplegable que no elige. */
.print-readonly { color: var(--ink-dim, #666); font-style: italic; }
.status-segment { padding: 0 6px; white-space: nowrap; color: var(--ink); }
.status-segment-warning { color: #684c00; }
.status-segment-error { color: #8a1f11; font-weight: 600; }
.status-chip { padding: 0 5px; background: #fff3cd; border: 1px solid #e8cf84; border-radius: 2px; color: #684c00; font-family: var(--mono); }

/* Temporary dimensions of the selection */
.seldims { position: absolute; inset: 0; pointer-events: none; }
.seldim { position: absolute; transform: translate(-50%, -50%); pointer-events: auto; }
.seldim-value {
  padding: 1px 6px;
  background: #fff;
  border: 1px solid var(--accent);
  border-radius: 3px;
  color: #12314f;
  font: 12px var(--mono);
  cursor: pointer;
}
.seldim-value:hover { background: var(--accent-soft); }
.seldim-input {
  width: 82px;
  padding: 1px 4px;
  border: 1px solid var(--accent);
  border-radius: 3px;
  font: 12px var(--mono);
  user-select: text;
}

/* Right-click menu */
#context-menu {
  position: fixed;
  z-index: 22;
  min-width: 190px;
  padding: 4px 0;
  background: #fff;
  border: 1px solid var(--line);
  box-shadow: 0 8px 22px rgba(20, 32, 44, 0.18);
}
.color-field { display: flex; align-items: center; gap: 8px; }
.color-field input[type="color"] { width: 42px; height: 22px; padding: 0; border: 1px solid var(--line); background: #fff; }
.link-button { border: 0; background: none; color: var(--accent); text-decoration: underline; padding: 0; }

/* Listening dimension and snap readout */
.tempdim {
  position: absolute;
  z-index: 5;
  display: flex;
  gap: 8px;
  padding: 4px 6px;
  background: #fff;
  border: 1px solid var(--accent);
  border-radius: 3px;
  box-shadow: 0 2px 8px rgba(20, 32, 44, 0.18);
  transform: translate(-50%, -100%);
}
.tempdim label { display: flex; align-items: center; gap: 4px; color: var(--muted); font-size: 11px; }
.td-input {
  width: 76px;
  height: 22px;
  padding: 0 4px;
  border: 1px solid var(--line);
  border-radius: 2px;
  font: 12px var(--mono);
  color: var(--ink);
  user-select: text;
}
.td-input:focus { outline: 2px solid var(--accent); outline-offset: -1px; }
.td-input.invalid { border-color: #c0392b; outline-color: #c0392b; }
.status-snap { color: #0a4f4b; font-weight: 600; min-width: 90px; }
.ob-hint { color: var(--faint); }

/* Warnings */
.status-warn {
  padding: 0 7px;
  background: #fff4e5;
  border: 1px solid #f0b46a;
  border-radius: 2px;
  color: #8a4b00;
  font-weight: 600;
}
.status-warn:hover, .status-warn[aria-expanded="true"] { background: #ffe6c2; }
#warnings-panel {
  position: fixed;
  right: 12px;
  bottom: 30px;
  z-index: 25;
  width: 380px;
  max-height: 50vh;
  overflow: auto;
  background: #fff;
  border: 1px solid var(--line);
  box-shadow: 0 8px 22px rgba(20, 32, 44, 0.18);
}
.wp-head { padding: 7px 10px; background: var(--chrome-2); border-bottom: 1px solid var(--line-soft); font-weight: 600; }
.wp-list { margin: 0; padding: 0; list-style: none; }
.wp-item {
  display: grid;
  gap: 2px;
  width: 100%;
  padding: 7px 10px;
  border: 0;
  border-bottom: 1px solid var(--line-soft);
  background: none;
  text-align: left;
}
.wp-item:hover, .wp-item:focus-visible { background: #fff4e5; }
/* The fix a warning offers, under its row: one click, one exec (M15-18). */
.wp-fix {
  margin: 0 10px 7px;
  padding: 3px 8px;
  border: 1px solid var(--line);
  border-radius: 3px;
  background: var(--chrome-2);
  font: inherit;
  font-size: 11.5px;
}
.wp-fix:hover, .wp-fix:focus-visible { background: #fff4e5; }

/* Toasts */
#toasts { position: fixed; right: 14px; bottom: 34px; z-index: 30; display: grid; gap: 6px; }
.toast {
  max-width: 400px;
  padding: 8px 12px;
  background: #1f2a33;
  border-radius: 3px;
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.25);
  color: #f2f5f7;
  transition: opacity 0.2s, transform 0.2s;
}
.toast-warn { background: #5c3e00; }
.toast-error { background: #7a1f19; }
.toast.leaving { opacity: 0; transform: translateY(4px); }

@media (prefers-reduced-motion: reduce) {
  .toast { transition: none; }
}

/* Generic dialog buttons, first used by Print */
.btn {
  padding: 6px 14px;
  border: 1px solid var(--line);
  background: #fff;
  border-radius: 3px;
  font: inherit;
  cursor: default;
}
.btn:hover:not(:disabled) { background: var(--accent-soft); border-color: var(--accent-edge); }
.btn:disabled { color: var(--faint); cursor: default; }
.btn-primary { background: var(--accent); border-color: var(--accent); color: #fff; }
.btn-primary:hover:not(:disabled) { background: var(--file); border-color: var(--file); }

/* Print dialog: a plain fixed overlay, not a native <dialog> — see printDialog.js for why.
   Shown or hidden with visibility + pointer-events rather than a display toggle, mostly
   so a field change can repaint the preview without fighting the stylesheet; the fix for
   this Electron build's real requestAnimationFrame stall lives in view3d.js and main.mjs,
   not in how this overlay is toggled. */
.print-dialog {
  position: fixed;
  inset: 0;
  z-index: 40;
  display: grid;
  place-items: center;
  background: rgba(20, 28, 36, 0.45);
  visibility: hidden;
  pointer-events: none;
}
.print-dialog.is-open {
  visibility: visible;
  pointer-events: auto;
}
.print-dialog-inner {
  display: grid;
  grid-template-rows: auto 1fr auto auto;
  width: min(920px, 92vw);
  max-height: 88vh;
  border: 1px solid var(--line);
  border-radius: 4px;
  box-shadow: 0 12px 40px rgba(20, 32, 44, 0.3);
  background: #fff;
  color: var(--ink);
  font: 13px/1.4 var(--font);
}
.print-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 10px 14px;
  border-bottom: 1px solid var(--line);
  background: var(--chrome-2);
}
.print-header h2 { margin: 0; font-size: 15px; }
.dialog-x { border: 0; background: none; font-size: 18px; line-height: 1; padding: 2px 6px; color: var(--muted); }
.dialog-x:hover { color: var(--ink); }
.print-body { display: grid; grid-template-columns: 220px minmax(0, 1fr); gap: 16px; padding: 14px; overflow: auto; min-height: 0; }
.print-fields { display: grid; gap: 10px; align-content: start; }
.print-field { display: grid; gap: 3px; font-size: 12px; color: var(--muted); }
.print-field .field-input { width: 100%; }
.print-preview { display: grid; place-items: start center; background: var(--chrome-2); border: 1px solid var(--line-soft); padding: 14px; min-height: 0; }
.print-page { width: 100%; max-width: 480px; background: #fff; box-shadow: 0 2px 10px rgba(0, 0, 0, 0.18); }
.print-page svg { display: block; width: 100%; height: auto; }
.print-page-count { grid-column: 1 / -1; margin-top: 8px; color: var(--muted); font-size: 12px; }
.print-warning {
  margin: 0 14px;
  padding: 8px 12px;
  background: #fff4e5;
  border: 1px solid #f0b84a;
  border-radius: 3px;
  color: #6b4a06;
  display: grid;
  gap: 6px;
}
.print-warning-fixes { display: flex; gap: 8px; flex-wrap: wrap; }
.print-warning-fixes button { padding: 3px 10px; border: 1px solid #d69a2d; background: #fff; border-radius: 3px; font: inherit; cursor: default; }
.print-warning-fixes button:hover { background: #ffe8bf; }
.print-footer { display: flex; justify-content: flex-end; gap: 8px; padding: 12px 14px; border-top: 1px solid var(--line); }

/* A small, generic confirm dialog (dialogs.js): created and removed on demand, unlike
   the print dialog, since it is opened rarely and briefly. */
.confirm-dialog {
  position: fixed;
  inset: 0;
  z-index: 50;
  display: grid;
  place-items: center;
  background: rgba(20, 28, 36, 0.45);
}
.confirm-dialog-inner {
  display: grid;
  gap: 14px;
  width: min(380px, 90vw);
  padding: 18px;
  border: 1px solid var(--line);
  border-radius: 4px;
  box-shadow: 0 12px 40px rgba(20, 32, 44, 0.3);
  background: #fff;
  color: var(--ink);
  font: 13px/1.4 var(--font);
}
.confirm-dialog-inner h2 { margin: 0; font-size: 15px; }
.confirm-dialog-inner p { margin: 0; color: var(--muted); }
.confirm-dialog-footer { display: flex; justify-content: flex-end; gap: 8px; }
.select-levels-list { display: grid; gap: 8px; max-height: 220px; overflow: auto; }

/* The '?' shortcuts sheet: wider than the plain confirm dialog, two columns. */
.shortcuts-dialog-inner { width: min(720px, 92vw); max-height: 85vh; overflow: auto; }
.shortcuts-columns { display: grid; grid-template-columns: 1fr 1fr; gap: 24px; }
.shortcuts-columns h3 { margin: 0 0 8px; font-size: 12px; text-transform: uppercase; letter-spacing: 0.04em; color: var(--muted); }
.shortcuts-table { width: 100%; border-collapse: collapse; font-size: 12px; }
.shortcuts-table td { padding: 4px 0; vertical-align: top; }
.shortcuts-table td:first-child { width: 40%; white-space: nowrap; padding-right: 10px; color: var(--accent); }
/* The About section of the same sheet: version and declared limits (M14-29). */
.about-section { margin-top: 20px; padding-top: 12px; border-top: 1px solid var(--line-soft); }
.about-section h3 { margin: 0 0 8px; font-size: 12px; text-transform: uppercase; letter-spacing: 0.04em; color: var(--muted); }
.about-line { margin: 0 0 4px; font-size: 12px; }
@media (max-width: 560px) {
  .shortcuts-columns { grid-template-columns: 1fr; }
}
