:root { color-scheme: light; --panel: #d7d4ce; --panel-dark: #bdb9b1; --border: #aaa59b; --button: #ece9e3; --orange: #ff8618; --green: #18ff28; --green-dark: #02bf19; --black: #050505; --text: #2e2e2e; --ink: #242424; --line: #aaa59b; --muted: #5e5a52; font-family: Arial, Helvetica, sans-serif; } * { box-sizing: border-box; } html, body { width: 100vw; height: 100vh; height: 100dvh; margin: 0; overflow: hidden; background: #c8c4bc; color: var(--text); } #app { width: 100vw; height: 100vh; height: 100dvh; overflow: hidden; } button { border: 1px solid #bdb8ad; border-radius: 5px; background: linear-gradient(#f7f5ef, #ddd9d1); color: #303030; font: inherit; } button:active { transform: translateY(1px); } button[data-icon-name] { display: grid; grid-template-rows: minmax(18px, 1fr) auto; place-items: center; gap: 2px; min-width: 0; overflow: hidden; } button[data-icon-name] img, .gmoccapy-icon-fallback { display: block; width: min(26px, 78%); height: min(26px, 78%); object-fit: contain; pointer-events: none; } button[data-icon-name] span { max-width: 100%; min-width: 0; overflow: hidden; font-size: inherit; line-height: 1; text-align: center; text-overflow: ellipsis; white-space: nowrap; } .gmoccapy-icon-fallback { display: grid; place-items: center; border: 1px solid #938d84; background: #f5f2ea; color: #38332e; font-size: 9px; font-weight: 700; } .profile-select-label { display: grid; gap: 1px; min-width: 210px; color: var(--muted); font-size: 11px; font-weight: 700; text-transform: uppercase; } .profile-select-label select { min-height: 28px; border: 1px solid var(--line); border-radius: 3px; background: #f7f5ef; color: var(--ink); font: inherit; font-size: 12px; } .gmoccapy-shell { display: grid; grid-template-columns: minmax(0, 1.34fr) minmax(0, 0.58fr) minmax(0, 0.56fr) 108px; grid-template-rows: 40px minmax(0, 1fr) minmax(0, 0.82fr) minmax(110px, 0.48fr) 68px; grid-template-areas: "title title title title" "preview dro dro side" "preview gcode gcode side" "info override spindle side" "bottom bottom bottom side"; width: 100%; height: 100%; min-width: 0; min-height: 0; border: 1px solid var(--border); background: var(--panel); } .titlebar { grid-area: title; display: flex; align-items: center; gap: 10px; min-width: 0; padding: 4px 12px; background: #cfcbc3; border-bottom: 1px solid var(--border); } .brand-dot { display: grid; place-items: center; flex: 0 0 auto; width: 26px; height: 26px; border: 2px solid #ffcf00; border-radius: 50%; color: #e21d1d; font-size: 10px; font-weight: 700; } .title-stack { display: flex; flex: 1; align-items: baseline; justify-content: center; gap: 16px; min-width: 0; } .title-stack strong { overflow: hidden; font-size: 17px; text-overflow: ellipsis; white-space: nowrap; } .title-stack span, .run-state { overflow: hidden; font-size: 14px; color: #4d4d4d; text-overflow: ellipsis; white-space: nowrap; } .run-state { min-width: 76px; text-align: right; text-transform: uppercase; } .current-line-indicator { display: grid; grid-template-columns: auto minmax(44px, auto); align-items: center; gap: 8px; flex: 0 0 auto; min-width: 0; padding: 4px 8px; border: 1px solid #8d887f; background: #f7f1d0; color: #171717; } .current-line-indicator span { min-width: 0; overflow: hidden; font-size: 11px; font-weight: 700; text-overflow: ellipsis; text-transform: uppercase; white-space: nowrap; } .current-line-indicator strong { color: #005bab; font: 700 20px/1 "Courier New", monospace; text-align: right; } .preview-panel { grid-area: preview; position: relative; overflow: hidden; background: var(--black); border-right: 2px solid #8d887f; border-bottom: 2px solid #8d887f; } .program-path { position: absolute; inset: 9px 0 auto 0; z-index: 2; color: #f6f6f6; text-align: center; font-size: 13px; line-height: 1.2; pointer-events: none; } .toolpath-preview { width: 100%; height: calc(100% - 64px); margin-top: 32px; display: block; touch-action: none; cursor: grab; } .toolpath-preview:active { cursor: grabbing; } .tool-preview-card { position: absolute; top: 34px; left: 10px; z-index: 2; display: grid; grid-template-columns: auto auto; gap: 2px 8px; min-width: 154px; max-width: 230px; padding: 7px 9px; border: 1px solid #316e74; background: rgba(4, 20, 22, 0.86); color: #e7ffff; font: 12px/1.25 "Courier New", monospace; pointer-events: none; } .tool-preview-card strong { grid-row: span 3; align-self: center; color: #21f2f2; font-size: 22px; } .tool-preview-card span { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; } .rtcp-preview-badge { position: absolute; right: 8px; bottom: 62px; left: 8px; z-index: 2; overflow: hidden; padding: 4px 6px; border: 1px solid #215b2b; background: rgba(2, 16, 5, 0.82); color: var(--green); font: 11px/1.25 "Courier New", monospace; text-align: center; text-overflow: ellipsis; white-space: nowrap; pointer-events: none; } .rtcp-preview-badge[data-rtcp-preview-state="off"] { border-color: #4b4b4b; color: #b7c7b8; } .preview-toolbar { position: absolute; right: 0; bottom: 0; left: 0; display: grid; grid-template-columns: repeat(5, 1fr); gap: 6px; padding: 6px; background: var(--panel); border-top: 1px solid var(--border); } .preview-toolbar button, .bottom-controls button, .status-sidebar button { min-height: 42px; font-weight: 700; } .preview-toolbar button[data-icon-name] img { width: min(24px, 80%); height: min(24px, 80%); } .dro-panel { grid-area: dro; display: grid; grid-template-rows: 1fr auto; min-width: 0; min-height: 0; overflow: hidden; border-left: 2px solid #8d887f; border-bottom: 2px solid #8d887f; background: var(--black); } .dro-grid { display: grid; grid-template-columns: 1fr 1fr; grid-template-rows: repeat(3, minmax(0, 1fr)); gap: 1px; min-height: 0; background: #111111; } .dro-row { display: grid; grid-template-columns: 30px 46px minmax(92px, 1fr) 58px; align-items: center; min-width: 0; min-height: 0; padding: 4px 7px; background: var(--black); color: var(--green); } .dro-axis { font-size: clamp(24px, 2vw, 32px); font-weight: 800; line-height: 1; } .dro-mode, .dro-dtg { color: var(--green); font-size: 10px; line-height: 1.25; } .dro-row strong { overflow: hidden; text-align: right; font-size: clamp(24px, 2.5vw, 38px); line-height: 1; font-variant-numeric: tabular-nums; text-overflow: clip; white-space: nowrap; } .tcp-strip { display: flex; gap: 6px; justify-content: space-between; min-width: 0; padding: 6px 9px; background: #080808; color: var(--green); font-size: 13px; font-weight: 700; } .tcp-strip span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .tcp-strip [data-rtcp-value="tcp"] { flex: 1.2 1 190px; } .tcp-strip [data-rtcp-value="tool-axis"] { flex: 1 1 150px; } .tcp-strip [data-rtcp-value="state"] { flex: 0 0 auto; } .gcode-panel { grid-area: gcode; display: grid; grid-template-rows: auto auto auto minmax(96px, 1fr) 20px 54px; min-width: 0; min-height: 0; overflow: hidden; background: #f6f4ef; border-top: 2px solid var(--border); border-bottom: 2px solid var(--border); } .gcode-header { display: grid; grid-template-columns: minmax(0, 1fr) auto auto; gap: 8px; align-items: center; min-width: 0; padding: 6px 9px; border-bottom: 1px solid #d5d0c7; background: #eeeae3; font-size: 13px; } .linuxcnc-source-row { display: grid; grid-template-columns: minmax(260px, 1fr) auto minmax(180px, 1fr); align-items: center; gap: 8px; min-width: 0; padding: 5px 8px; border-bottom: 1px solid #d5d0c7; background: #f6f4ef; font-size: 12px; } .linuxcnc-source-row label { display: grid; grid-template-columns: auto minmax(150px, 240px); align-items: center; gap: 6px; min-width: 0; } .linuxcnc-source-row select { min-width: 0; max-width: 100%; } .linuxcnc-source-row [data-linuxcnc-gcode-source="status"] { min-width: 0; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; } .machine-project-row { display: grid; grid-template-columns: minmax(170px, 1.1fr) minmax(150px, 0.9fr) minmax(150px, 0.8fr) minmax(190px, 1.2fr); align-items: center; gap: 8px; min-width: 0; padding: 4px 8px; border-bottom: 1px solid #d5d0c7; background: #ebe7df; color: #3a3732; font: 11px/1.2 "Courier New", monospace; } .machine-project-row span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .machine-project-row [data-program-validation="summary"] { color: #005bab; font-weight: 700; } .gcode-header strong, .gcode-header span { min-width: 0; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; } .gcode-header [data-active-program-line] { color: #005bab; font-weight: 700; } .gcode-list { min-height: 0; margin: 0; padding: 6px 8px 3px; overflow: auto; list-style: none; font-family: "Courier New", monospace; font-size: 13px; color: #55514a; } .gcode-row { display: grid; grid-template-columns: 42px minmax(0, 1fr); gap: 6px; min-height: 34px; line-height: 1.25; padding: 2px 4px; border-left: 3px solid transparent; } .gcode-row.active { background: #21a553; color: #0c2b17; border-left-color: #2ebf63; } .gcode-row[data-line-status="done"] { background: #eeeeee; border-left-color: #b8b8b8; } .gcode-row[data-line-status="running"] { background: #21a553; border-left-color: #2ebf63; } .gcode-row.active span, .gcode-row.active code, .gcode-row.active small, .gcode-row[data-line-status="running"] span, .gcode-row[data-line-status="running"] code, .gcode-row[data-line-status="running"] small { color: #ffffff; } .gcode-row code { min-width: 0; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; } .gcode-row small { grid-column: 2; min-width: 0; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; color: #6d695f; font: 11px/1.2 "Courier New", monospace; } .gcode-progress { display: grid; grid-template-columns: 120px 1fr; align-items: center; gap: 8px; padding: 1px 8px 3px; font-size: 11px; color: #777; } .gcode-progress div { height: 6px; background: #d0d0d0; } .gcode-progress i { display: block; height: 100%; background: #3888df; } .mdi-panel { display: grid; grid-template-rows: 27px minmax(0, 1fr); gap: 2px; min-width: 0; min-height: 0; padding: 3px 8px 5px; border-top: 1px solid #cbc6bd; background: #e7e3dc; } .mdi-command-row { display: grid; grid-template-columns: 44px minmax(0, 1fr) 64px; gap: 6px; align-items: center; min-width: 0; } .mdi-command-row strong { color: #222; font-size: 13px; } .mdi-command-row input { min-width: 0; height: 25px; padding: 3px 8px; border: 1px solid #8e897f; border-radius: 3px; background: #111; color: var(--green); font: 14px/1.1 "Courier New", monospace; } .mdi-command-row button { min-height: 25px; font-size: 12px; font-weight: 700; } .mdi-history { display: flex; gap: 4px; min-width: 0; overflow: hidden; } .mdi-history button { flex: 0 1 auto; min-width: 0; min-height: 19px; padding: 2px 6px; overflow: hidden; color: #303030; font: 11px/1.1 "Courier New", monospace; text-overflow: ellipsis; white-space: nowrap; } .status-sidebar { grid-area: side; display: grid; grid-template-rows: repeat(9, minmax(42px, 1fr)) minmax(42px, auto); gap: 5px; padding: 6px; border-left: 2px solid var(--border); background: var(--panel); min-width: 0; min-height: 0; } .sidebar-button { min-width: 0; min-height: 0; padding: 3px; font-size: 12px; line-height: 1.1; } .sidebar-button[data-icon-name] img { width: min(34px, 82%); height: min(34px, 82%); } .sidebar-button.estop { color: #c30000; } .sidebar-button.power { color: var(--green-dark); font-size: 15px; } .sidebar-button[data-entry-status="blocked"], .sidebar-button[data-entry-status="active-blocked"] { border-color: #a9a49b; background: linear-gradient(#e1ded7, #cac5bb); color: #69645d; opacity: 0.78; } .sidebar-button[data-active="true"] { border-color: #278b37; background: linear-gradient(#f6fff5, #aee9ae); color: #075f16; } .sidebar-button[data-entry-tone="emergency"][data-entry-status="emergency"], .sidebar-button.estop[data-active="true"] { border-color: #8e0000; background: linear-gradient(#ffdfd8, #ff675b); color: #5f0000; } .sidebar-button[data-entry-tone="power"][data-active="true"] { border-color: #1e7b2c; background: linear-gradient(#e7ffe7, #58e364); color: #064e12; } .sidebar-button[data-entry-tone="reset"], .sidebar-button[data-entry-tone="reset-required"] { border-color: #a8740b; background: linear-gradient(#fff7d4, #efc45c); color: #5a3b00; } .sidebar-button[data-entry-tone="tcp"][data-active="true"] { border-color: #14647a; background: linear-gradient(#e4fbff, #68d5e6); color: #073f4d; } .sidebar-button[data-entry-tone="identity"][data-active="true"] { border-color: #66625a; background: linear-gradient(#f6f4ee, #d1ccc2); color: #222; } .sidebar-button[data-entry-status="active-blocked"][data-active="true"] { border-color: #a9a49b; background: linear-gradient(#e1ded7, #cac5bb); color: #69645d; } .status-sidebar time { padding: 4px 0; text-align: center; color: #4c4c4c; font-size: 14px; line-height: 1.35; } .info-tabs { grid-area: info; min-width: 0; min-height: 0; overflow: auto; border-top: 2px solid var(--border); border-right: 2px solid var(--border); background: #eeeae3; } .axis-first-screen-strip { display: grid; grid-template-columns: repeat(5, minmax(96px, 1fr)); gap: 3px; padding: 5px 6px; border-bottom: 1px solid #aaa59b; background: #151515; color: #e9f8e9; font: 11px/1.2 "Courier New", monospace; } .axis-first-screen-strip span { min-width: 0; overflow: hidden; padding: 3px 5px; border: 1px solid #3e5f43; background: #071108; text-overflow: ellipsis; white-space: nowrap; } .axis-first-screen-strip b { color: var(--green); font-weight: 700; } .axis-first-screen-strip [data-axis-ui-capability-ready="false"] { border-color: #7a6840; background: #1b1508; color: #f0d58c; } .tabs { display: grid; grid-template-columns: 1fr 1fr 1fr; border-bottom: 1px solid var(--border); } .tabs button { border: 0; border-right: 1px solid var(--border); border-radius: 0; background: #e0ddd6; min-height: 32px; padding: 4px 5px; font-size: 12px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .tabs button.active { background: #f3f0ea; } .info-grid { display: grid; grid-template-columns: max-content 1fr; gap: 1px 8px; margin: 6px 8px; font-size: 12px; line-height: 1.15; } .info-grid dt { font-weight: 700; } .info-grid dd { margin: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .info-grid [data-rtcp-diagnostic] { font-family: "Courier New", monospace; font-size: 12px; } .override-panel { grid-area: override; display: grid; grid-template-columns: 1fr; grid-template-rows: repeat(4, minmax(0, 1fr)); gap: 6px; padding: 6px; border-top: 2px solid var(--border); border-right: 1px solid var(--border); background: #eeeae3; min-width: 0; min-height: 0; } .meter-card, .override-control, .cooling, .spindle { display: grid; align-content: start; gap: 1px; padding: 5px 6px; background: #f8f5ef; border: 1px solid var(--border); min-width: 0; min-height: 0; overflow: hidden; } .meter-card h2, .override-control h2, .cooling h2, .spindle h2 { margin: 0; font-size: 12px; line-height: 1.15; text-align: center; } .meter-card strong, .override-control strong, .spindle strong { display: block; overflow: hidden; font-size: clamp(16px, 1.45vw, 22px); line-height: 1.05; text-overflow: ellipsis; white-space: nowrap; } .meter-card { grid-template-columns: auto minmax(0, 1fr); align-content: center; align-items: end; } .meter-card h2 { grid-column: 1 / -1; } .meter-card strong { display: inline; font-size: clamp(18px, 1.6vw, 24px); line-height: 1; } .meter-card span { padding-left: 5px; font-size: 12px; line-height: 1.1; white-space: nowrap; } .stepper { display: grid; grid-template-columns: 30px minmax(48px, 1fr) 30px 36px; gap: 2px; align-items: center; margin-top: 1px; } .stepper div { min-width: 0; padding: 5px 4px; background: var(--orange); border: 1px solid #b4651c; text-align: center; font-weight: 700; font-size: 13px; white-space: nowrap; } .stepper button { min-width: 0; min-height: 26px; padding: 2px 4px; font-size: 12px; } .toggle-row { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 3px; min-width: 0; } .toggle-row button { min-width: 0; min-height: 24px; padding: 2px 3px; overflow: hidden; font-size: 11px; font-weight: 700; text-overflow: ellipsis; white-space: nowrap; } .toggle-row button[data-active="true"] { background: #ffd25f; border-color: #a76e00; } .status-chip { min-width: 0; overflow: hidden; padding: 2px 4px; background: #ebe6dc; border: 1px solid #c6bfb3; color: #4f4a42; font: 10px/1.2 "Courier New", monospace; text-overflow: ellipsis; white-space: nowrap; } .spindle-coolant-panel { grid-area: spindle; display: grid; grid-template-columns: 76px minmax(0, 1fr); gap: 6px; min-width: 0; min-height: 0; padding: 6px; background: #eeeae3; border-top: 2px solid var(--border); } .cooling { display: grid; grid-template-rows: auto 1fr 1fr; gap: 4px; } .cooling button.active { background: #39ef37; } .spindle-range { height: 18px; margin-top: 4px; background: #bdbdbd; border: 1px solid #898989; } .spindle-direction { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 3px; min-width: 0; } .spindle-direction button, .cooling button { min-width: 0; min-height: 38px; padding: 2px; font-size: 10px; } .spindle-direction button[data-active="true"], .cooling button[data-active="true"] { border-color: #278b37; background: #39ef37; } .spindle-range i { display: block; height: 100%; background: #24e83d; } .bottom-controls { grid-area: bottom; display: grid; grid-template-columns: repeat(18, minmax(44px, 1fr)); gap: 5px; padding: 6px 8px; border-top: 2px solid var(--border); background: var(--panel); min-width: 0; } .bottom-controls button { font-size: clamp(10px, 0.72vw, 12px); line-height: 1.05; min-width: 0; padding: 3px 4px; white-space: normal; } .bottom-controls button[data-icon-name] img { width: min(24px, 82%); height: min(24px, 82%); } .program-file-input { display: none; } @media (max-width: 1180px) { .gmoccapy-shell { grid-template-columns: minmax(0, 1.18fr) minmax(0, 0.7fr) minmax(0, 0.62fr) 96px; } .titlebar { gap: 6px; padding: 4px 8px; } .profile-select-label { min-width: 160px; } .current-line-indicator strong { font-size: 16px; } .dro-row strong { font-size: 21px; } .dro-row { grid-template-columns: 22px 36px minmax(66px, 1fr) 44px; } .info-grid, .gcode-list { font-size: 12px; } .linuxcnc-source-row { grid-template-columns: minmax(180px, 1fr) auto minmax(140px, 1fr); } .linuxcnc-source-row label { grid-template-columns: auto minmax(120px, 1fr); } .machine-project-row { grid-template-columns: minmax(130px, 1fr) minmax(120px, 0.9fr) minmax(120px, 0.8fr) minmax(140px, 1fr); } .tabs button, .meter-card h2, .override-control h2, .cooling h2, .spindle h2 { font-size: 12px; } .axis-first-screen-strip { grid-template-columns: repeat(2, minmax(90px, 1fr)); } } @media (max-height: 720px) { .gmoccapy-shell { grid-template-rows: 40px minmax(0, 1fr) minmax(0, 1fr) minmax(84px, 0.4fr) 58px; } .preview-toolbar button, .bottom-controls button, .status-sidebar button { min-height: 34px; } .gcode-panel { grid-template-rows: auto auto auto minmax(0, 1fr) 18px 48px; } .gcode-list { padding: 4px 6px 2px; font-size: 12px; } .gcode-row { min-height: 24px; } .gcode-row small { display: none; } .bottom-controls { grid-template-columns: repeat(18, minmax(36px, 1fr)); } } @media (max-height: 420px) { .gmoccapy-shell { grid-template-rows: 24px minmax(24px, 0.14fr) minmax(0, 1.92fr) 0 28px; } .titlebar { gap: 4px; padding: 2px 5px; } .title-stack strong { font-size: 10px; } .title-stack span, .run-state { font-size: 8px; } .profile-select-label { min-width: 96px; font-size: 8px; } .profile-select-label select { min-height: 16px; font-size: 8px; } .current-line-indicator { padding: 1px 4px; } .current-line-indicator span { font-size: 8px; } .current-line-indicator strong { font-size: 9px; } .info-tabs, .override-panel, .spindle-coolant-panel { display: none; } .gcode-panel { grid-template-rows: auto auto minmax(0, 1fr) 12px; } .gcode-header { gap: 4px; padding: 1px 3px; font-size: 8px; } .linuxcnc-source-row { gap: 4px; padding: 1px 3px; font-size: 8px; grid-template-columns: minmax(120px, 1fr) auto minmax(72px, 0.82fr); } .linuxcnc-source-row label { gap: 4px; grid-template-columns: auto minmax(72px, 1fr); } .linuxcnc-source-row button, .linuxcnc-source-row select { min-height: 16px; font-size: 8px; } .machine-project-row { display: none; } .gcode-list { padding: 2px 4px; font-size: 8px; line-height: 1; } .gcode-row { gap: 4px; min-height: 8px; padding: 0 2px; border-left-width: 2px; } .gcode-row span { font-size: 8px; } .gcode-row code { font-size: 8px; } .mdi-panel { display: none; } .dro-panel { grid-template-rows: 1fr; } .dro-grid { grid-template-columns: repeat(6, minmax(0, 1fr)); grid-template-rows: 1fr; } .dro-row { grid-template-columns: auto minmax(0, 1fr); gap: 3px; padding: 1px 4px; align-items: center; } .dro-axis { font-size: 8px; } .dro-mode, .dro-dtg, .tcp-strip { display: none; } .dro-row strong { font-size: 9px; line-height: 1; } .bottom-controls { gap: 3px; padding: 2px 3px; } .bottom-controls button { font-size: 8px; line-height: 1; min-height: 18px; padding: 1px 2px; } button[data-icon-name] { grid-template-rows: 1fr; } button[data-icon-name] img, .gmoccapy-icon-fallback { width: 12px; height: 12px; } button[data-icon-name] span { display: none; } }