After testing the V09 redesign live on the Pi at onefinity.local
(1920x1080, Chrome fullscreen) several real bugs surfaced. This
commit fixes all of them.
Layout fits at 1920x1080
- Cap .app-shell at 100vh height with overflow:hidden so child
flex containers actually constrain to one screen.
- Make .control-page / .program-page / .console-page use
flex 1 1 auto + min-height 0 + overflow hidden so the page total
no longer grows to ~36 000 px when the gcode-viewer is mounted.
- Override clusterize.css default max-height: 200px on the
.clusterize-scroll element with max-height: none + flex 1 1 0 +
height 100% so the gcode listing fills the available column.
E-Stop in the header
- The legacy estop.pug SVG had width=130 height=130 but no
viewBox, so CSS-only sizing did nothing and the SVG content
spilled ~26 px off the right edge of the screen and ~70 px
below the header. Add viewBox="0 0 130 130" plus
preserveAspectRatio so CSS sizing actually shrinks the inner
geometry. Drop the octagonal clip-path (the SVG already
carries its own yellow safety ring + EMERGENCY/STOP text).
3D toolpath preview (path-viewer)
- The legacy .path-viewer.small CSS clamped the canvas to
340 x 150 floated into the corner. In the new program-body
grid we want it to fill the 600 px right column. Override
with width 100%, height auto, float none, !important.
- Make orbit.js wheel/touchstart/touchmove listeners
{passive: false} so OrbitControls.preventDefault() actually
works and the page no longer scrolls while panning the 3D
view on a touch screen.
Vue 1 template + reactivity bugs exposed by the live data
- Replace v-else-if (Vue 1 has no v-else-if) in
control-view.pug with three sibling v-if templates that
mutually exclude on w.enabled and state['2an'] == 3.
- axis-vars._get_motor_id: guard motor.axis.toLowerCase()
against undefined motors (initial config is [{}, {}, ...]).
- axis-vars._check_is_enabled: prefer config.motors[i].axis
when present, fall back to state[N + 'an'] only for
recognised axes (x/y/z/a) so undefined == undefined
doesn't mistakenly enable b/c rows.
- program-mixin: tolerate state.files / state.gcode_list
being undefined right after connect.
App-shell race conditions
- Skip the early parse_hash() in app.js ready() when the
initial hash is in the settings family. Those Svelte
components read settings.units / settings.probing-prompts /
motion.* etc. and crash on first paint with the empty
placeholder config. Stay on loading-view until update()
completes and routes us in itself.
Misc
- src/static/js/ui.js: null-guard the legacy burger menu code
(#menuLink no longer exists). Was throwing 'Cannot set
properties of null (setting onclick)'.
- src/static/css/Audiowide.css: switch the gstatic font URL
from http:// to https:// so it isn't blocked as mixed
content under the home.muehe.org HTTPS proxy.
- Macro buttons: drop the default 6 px yellow border-left.
The stripe now only appears via .has-color when
state.macros[i].color is actually configured. Removes the
asymmetric/lopsided look from the screenshot.
Tested live on http://10.1.10.55/ and via the HTTPS proxy at
https://onefinity.home.muehe.org/.
2057 lines
34 KiB
Stylus
2057 lines
34 KiB
Stylus
// =====================================================================
|
||
// V09 redesign tokens & chrome
|
||
// =====================================================================
|
||
//
|
||
// The new shell wraps everything in `.app-shell { .app-head | .app-body }`.
|
||
// Inner views use the shared tokens below for jog/macro tiles, status
|
||
// chips and segmented controls. Anything legacy that's still needed by
|
||
// settings/admin/motor/tool/io templates remains lower in this file.
|
||
|
||
$ink = #0f172a
|
||
$ink-soft = #334155
|
||
$muted = #64748b
|
||
$muted-2 = #94a3b8
|
||
$line = #e5e7eb
|
||
$line-soft = #f1f5f9
|
||
$bg = #ffffff
|
||
$body-bg = #f1f5f9
|
||
|
||
$accent = #fde047
|
||
$accent-ink = $ink
|
||
$accent-text = #0ea5e9
|
||
|
||
// Jog tile palette — V09 (flat soft slate, no shadow)
|
||
$jog-bg = #3f4b63
|
||
$jog-hover = #4a5777
|
||
$jog-dir = #5b6885
|
||
$jog-dir-hov = #6a779a
|
||
$jog-ghost = #8c97ad
|
||
$jog-ghost-hov = #9ba6bb
|
||
$jog-ink = #fff
|
||
$jog-ghost-ink = $ink
|
||
|
||
body
|
||
margin 0
|
||
font-family 'Inter', system-ui, -apple-system, sans-serif
|
||
background $body-bg
|
||
color $ink
|
||
|
||
[v-cloak]
|
||
display none
|
||
|
||
tt
|
||
color #000
|
||
background #eee
|
||
padding 2px
|
||
|
||
.button-success:not([disabled])
|
||
background-color #1cb841
|
||
|
||
.button-error:not([disabled])
|
||
background-color #ca3c3c
|
||
|
||
.button-warning:not([disabled])
|
||
background-color #df7514
|
||
|
||
.button-secondary:not([disabled])
|
||
background-color #42b8dd
|
||
|
||
.button-submit:not([disabled])
|
||
background-color #add1ad
|
||
color #fff
|
||
|
||
.button-blue:not([disabled])
|
||
background-color #0078e7
|
||
color #fff
|
||
|
||
.clear
|
||
clear left
|
||
clear right
|
||
|
||
// =====================================================================
|
||
// App shell
|
||
// =====================================================================
|
||
.app-shell
|
||
display flex
|
||
flex-direction column
|
||
height 100vh // cap at viewport so children that ask for 1fr/flex:1
|
||
width 100%
|
||
overflow hidden
|
||
background $body-bg
|
||
|
||
.app-body
|
||
flex 1
|
||
min-height 0
|
||
display flex
|
||
flex-direction column
|
||
padding 18px
|
||
overflow auto // settings/motor pages can scroll inside the body
|
||
|
||
> *
|
||
flex 1 1 auto
|
||
min-height 0
|
||
|
||
.app-head
|
||
flex 0 0 96px
|
||
height 96px
|
||
display flex
|
||
align-items center
|
||
gap 18px
|
||
padding 0 24px
|
||
background $bg
|
||
border-bottom 1px solid $line
|
||
position relative
|
||
z-index 30
|
||
|
||
.brand-blk
|
||
display flex
|
||
align-items center
|
||
gap 14px
|
||
|
||
.brand-logo
|
||
width 42px
|
||
height 42px
|
||
border-radius 8px
|
||
background repeating-linear-gradient(135deg, #a7c7a3 0 6px, transparent 6px 14px)
|
||
|
||
.brand-name
|
||
font-weight 900
|
||
font-size 22px
|
||
letter-spacing -0.01em
|
||
|
||
.head-spacer
|
||
flex 1
|
||
|
||
// Underline-ribbon tabs
|
||
.tabs-host
|
||
display inline-flex
|
||
gap 0
|
||
margin-right auto
|
||
padding-left 18px
|
||
align-items stretch
|
||
height 96px
|
||
|
||
.ktab
|
||
position relative
|
||
height 96px
|
||
padding 0 26px
|
||
display inline-flex
|
||
align-items center
|
||
gap 0.55rem
|
||
background transparent
|
||
border none
|
||
text-decoration none
|
||
color $ink-soft
|
||
font-size 1.05rem
|
||
font-weight 700
|
||
cursor pointer
|
||
transition color .15s
|
||
|
||
.fa
|
||
font-size 1.1rem
|
||
color $muted-2
|
||
transition color .15s
|
||
|
||
&:hover
|
||
color $ink
|
||
.fa
|
||
color $ink-soft
|
||
|
||
&.active
|
||
color $ink
|
||
.fa
|
||
color $ink
|
||
|
||
&.active::after
|
||
content ""
|
||
position absolute
|
||
left 14px
|
||
right 14px
|
||
bottom 0
|
||
height 5px
|
||
background $accent
|
||
border-radius 5px 5px 0 0
|
||
|
||
.ktab-badge
|
||
background #fee2e2
|
||
color #991b1b
|
||
font-size 0.7rem
|
||
padding 3px 8px
|
||
border-radius 9999px
|
||
font-weight 800
|
||
line-height 1
|
||
|
||
&.active .ktab-badge
|
||
background $accent
|
||
color $accent-ink
|
||
|
||
// System pill (collapses old chip-soup)
|
||
.sys-btn
|
||
display inline-flex
|
||
align-items center
|
||
gap 0.55rem
|
||
height 54px
|
||
padding 0 1.1rem
|
||
border-radius 14px
|
||
background $line-soft
|
||
border 1px solid $line
|
||
color $ink
|
||
font-size 0.9rem
|
||
font-weight 600
|
||
cursor pointer
|
||
user-select none
|
||
|
||
&:hover
|
||
background #e2e8f0
|
||
|
||
.pip
|
||
width 9px
|
||
height 9px
|
||
border-radius 9999px
|
||
background #22c55e
|
||
|
||
.pip.amber
|
||
background #f59e0b
|
||
|
||
.pip.red
|
||
background #dc2626
|
||
|
||
.fa-chevron-down
|
||
color $muted-2
|
||
font-size 12px
|
||
|
||
&.open
|
||
background #e2e8f0
|
||
|
||
.pi-temp-warning
|
||
align-self center
|
||
margin 0 4px
|
||
color #dc2626
|
||
font-size 24px
|
||
|
||
.state-badge
|
||
display inline-flex
|
||
align-items center
|
||
gap 0.6rem
|
||
height 54px
|
||
padding 0 1.1rem
|
||
border-radius 14px
|
||
background #dcfce7
|
||
color #166534
|
||
font-weight 800
|
||
font-size 1rem
|
||
letter-spacing 0.04em
|
||
|
||
.dot
|
||
width 10px
|
||
height 10px
|
||
border-radius 9999px
|
||
background currentColor
|
||
position relative
|
||
|
||
.dot::after
|
||
content ""
|
||
position absolute
|
||
inset -3px
|
||
border-radius 9999px
|
||
border 2px solid currentColor
|
||
opacity 0.5
|
||
animation pulse-dot 1.6s ease-out infinite
|
||
|
||
&.warn
|
||
background #fef3c7
|
||
color #92400e
|
||
|
||
&.bad
|
||
background #fee2e2
|
||
color #991b1b
|
||
|
||
&.busy
|
||
background #dbeafe
|
||
color #1e40af
|
||
|
||
&.unknown
|
||
background $line-soft
|
||
color $muted
|
||
|
||
&.unknown .dot::after
|
||
display none
|
||
|
||
@keyframes pulse-dot
|
||
0%
|
||
transform scale(0.7)
|
||
opacity 0.6
|
||
100%
|
||
transform scale(2.2)
|
||
opacity 0
|
||
|
||
@media (prefers-reduced-motion: reduce)
|
||
.state-badge .dot::after
|
||
animation none
|
||
|
||
// System popover
|
||
.sys-popover
|
||
position absolute
|
||
top 96px
|
||
right 240px
|
||
width 360px
|
||
background $bg
|
||
border 1px solid $line
|
||
border-radius 14px
|
||
box-shadow 0 18px 40px rgba(15, 23, 42, 0.18)
|
||
padding 12px
|
||
z-index 40
|
||
display flex
|
||
flex-direction column
|
||
gap 10px
|
||
|
||
.sp-row
|
||
display grid
|
||
grid-template-columns 32px 1fr auto
|
||
gap 12px
|
||
align-items center
|
||
|
||
.sp-icon
|
||
width 32px
|
||
height 32px
|
||
border-radius 8px
|
||
background $line-soft
|
||
color $ink-soft
|
||
display inline-flex
|
||
align-items center
|
||
justify-content center
|
||
|
||
img
|
||
width 18px
|
||
height 18px
|
||
|
||
.fa.sp-warn
|
||
color #f59e0b
|
||
|
||
.sp-label
|
||
font-size 0.7rem
|
||
text-transform uppercase
|
||
letter-spacing 0.1em
|
||
color $muted-2
|
||
font-weight 800
|
||
|
||
.sp-val
|
||
font-size 0.95rem
|
||
color $ink
|
||
font-weight 600
|
||
|
||
.sp-act
|
||
height 36px
|
||
padding 0 12px
|
||
border-radius 8px
|
||
background $line-soft
|
||
border 1px solid $line
|
||
color $ink
|
||
font-size 0.8rem
|
||
font-weight 700
|
||
cursor pointer
|
||
text-decoration none
|
||
display inline-flex
|
||
align-items center
|
||
gap 4px
|
||
|
||
.sp-act:hover
|
||
background #e2e8f0
|
||
|
||
.video
|
||
width 100%
|
||
height 180px
|
||
border-radius 8px
|
||
background #000
|
||
overflow hidden
|
||
position relative
|
||
|
||
img
|
||
width 100%
|
||
height 100%
|
||
object-fit cover
|
||
|
||
.sp-foot
|
||
display flex
|
||
gap 8px
|
||
margin-top 4px
|
||
padding-top 10px
|
||
border-top 1px solid $line-soft
|
||
|
||
.sp-shutdown, .sp-save
|
||
flex 1
|
||
height 40px
|
||
border-radius 10px
|
||
border 1px solid $line
|
||
background $line-soft
|
||
color $ink
|
||
font-weight 700
|
||
cursor pointer
|
||
|
||
.sp-shutdown
|
||
background #fef2f2
|
||
color #991b1b
|
||
border-color #fecaca
|
||
|
||
.sp-save:not([disabled])
|
||
background $accent
|
||
color $ink
|
||
border-color $accent
|
||
|
||
.error
|
||
background red
|
||
color #fff
|
||
|
||
.warn
|
||
background orange
|
||
|
||
.success
|
||
background green
|
||
|
||
.fa
|
||
font-size 150%
|
||
|
||
.modal-mask .fa
|
||
font-size inherit
|
||
|
||
.fa.error
|
||
background inherit
|
||
color red
|
||
|
||
.fa.warn
|
||
background inherit
|
||
color orange
|
||
|
||
.fa.success
|
||
background inherit
|
||
color green
|
||
|
||
.load-on
|
||
background-color #ccffcc
|
||
color #000
|
||
|
||
@keyframes attention
|
||
50%
|
||
opacity 0.5
|
||
|
||
.attention
|
||
background-color #f5e138
|
||
color #000
|
||
animation attention 2s step-start 0s infinite
|
||
|
||
span.unit
|
||
font-size 60%
|
||
|
||
.status
|
||
color #eee
|
||
text-align center
|
||
padding 0.125em
|
||
font-weight bold
|
||
margin-bottom 0.5em
|
||
text-transform uppercase
|
||
|
||
&.connecting
|
||
color orange
|
||
&.disconnected
|
||
color red
|
||
&.connected
|
||
color green
|
||
|
||
#overlay
|
||
position fixed
|
||
top 0
|
||
left 0
|
||
width 100%
|
||
height 100%
|
||
background-color rgba(0, 0, 0, 0.7)
|
||
z-index 2000
|
||
color white
|
||
font-weight bold
|
||
font-size 24pt
|
||
text-align center
|
||
text-transform uppercase
|
||
|
||
span
|
||
position relative
|
||
top 50%
|
||
|
||
// Form rules used by the settings/admin/motor/tool/io templates that
|
||
// still rely on Pure form classes.
|
||
.app-body .pure-control-group
|
||
label.units
|
||
width 6em
|
||
text-align left
|
||
|
||
textarea
|
||
width 24em
|
||
height 12em
|
||
|
||
> select, > input:not([type=checkbox])
|
||
min-width 300px
|
||
|
||
> tt
|
||
min-width 15.25em
|
||
padding 0.7em 1em
|
||
border-radius 3px
|
||
display inline-block
|
||
|
||
@keyframes blink
|
||
50%
|
||
fill #ff9d00
|
||
|
||
// E-Stop in the header — wraps the legacy <estop> SVG component.
|
||
// Sized to fit the 96px header with breathing room. The SVG carries
|
||
// its own yellow safety ring and EMERGENCY/STOP text; we only frame
|
||
// it with a soft drop shadow and a hover/active hit target.
|
||
.app-head .estop
|
||
width 80px
|
||
height 80px
|
||
display inline-flex
|
||
align-items center
|
||
justify-content center
|
||
border-radius 9999px
|
||
cursor pointer
|
||
transition transform 0.06s, filter 0.15s
|
||
flex 0 0 auto
|
||
// Make sure the SVG's internal coordinate space scales correctly
|
||
overflow visible
|
||
|
||
&:hover
|
||
filter brightness(1.05)
|
||
|
||
&:active
|
||
transform scale(0.96)
|
||
|
||
svg
|
||
width 80px
|
||
height 80px
|
||
cursor pointer
|
||
display block
|
||
|
||
.button:hover
|
||
filter brightness(120%)
|
||
|
||
.app-head .estop.active .ring
|
||
animation blink 2s step-start 0s infinite
|
||
|
||
.app-head .estop:hover .button circle
|
||
fill #b72424 !important
|
||
|
||
#macros
|
||
width 104%
|
||
|
||
.warning-box
|
||
display flex
|
||
background-color #F3FF00
|
||
border-radius 5px
|
||
border 0
|
||
margin-bottom 10px
|
||
margin-right 130px
|
||
margin-top 10px
|
||
align-items center
|
||
justify-content center
|
||
|
||
.new-gcode
|
||
height 13rem
|
||
width 23rem
|
||
resize none
|
||
border-radius 10px
|
||
padding 20px
|
||
resize none
|
||
|
||
.flex-row-container
|
||
display flex
|
||
flex-direction row
|
||
width 710px
|
||
margin-bottom 1rem
|
||
|
||
.tabs
|
||
margin-top 5px
|
||
width 850px
|
||
padding 20px
|
||
|
||
.macros-view
|
||
padding 30px
|
||
width 95%
|
||
|
||
.macros-tab-content
|
||
padding-bottom 20px
|
||
border-radius 5px
|
||
|
||
.macros-form
|
||
padding-left 30px
|
||
|
||
.config-button
|
||
height 40px
|
||
width 150px
|
||
font-weight normal
|
||
border-radius 3px
|
||
border 0
|
||
margin-right 10px
|
||
display flex
|
||
align-items center
|
||
justify-content space-around
|
||
|
||
.submit-macros
|
||
height 50px
|
||
width 140px
|
||
color #000
|
||
margin-top 30px
|
||
font-weight normal
|
||
border 0
|
||
|
||
|
||
.path-viewer
|
||
table
|
||
margin 0.25em
|
||
width 100%
|
||
|
||
.path-viewer-toolbar
|
||
> *
|
||
margin 0.25em
|
||
|
||
.tool-button
|
||
display inline-block
|
||
cursor pointer
|
||
border 2px solid transparent
|
||
border-radius 2px
|
||
text-align center
|
||
|
||
&:hover
|
||
opacity 0.7
|
||
border 2px inset #eee
|
||
|
||
&.active
|
||
border 2px inset #888
|
||
background #ddd
|
||
|
||
img
|
||
max-height 32px
|
||
vertical-align bottom
|
||
|
||
.fa
|
||
font-size 28px
|
||
display inline-block
|
||
width 32px
|
||
|
||
.path-viewer-messages
|
||
margin 0.125em 0
|
||
|
||
th, td
|
||
padding 0.125em
|
||
|
||
&.level
|
||
text-transform capitalize
|
||
|
||
.path-viewer-content
|
||
background-color #333
|
||
background linear-gradient(to bottom, #666 0%, #222 100%);
|
||
margin-bottom 0.5em
|
||
|
||
&.small
|
||
.path-viewer-content
|
||
width 340px
|
||
height 150px
|
||
float right
|
||
margin-top -88px
|
||
|
||
.console
|
||
.console-wrapper
|
||
max-height 400px
|
||
overflow-y auto
|
||
|
||
.message
|
||
white-space pre
|
||
|
||
table
|
||
width 100%
|
||
margin 0.5em 0
|
||
border-collapse collapse
|
||
|
||
td, th
|
||
border 1px solid #ddd
|
||
padding 2px
|
||
|
||
&:first-child
|
||
border-left 0
|
||
|
||
&:last-child
|
||
border-right 0
|
||
|
||
tr
|
||
> td
|
||
margin 0 0.125em
|
||
background-color #fff
|
||
|
||
tr.log-error td
|
||
color red
|
||
|
||
tr.log-warning td
|
||
color orange
|
||
|
||
tr.log-debug td
|
||
color green
|
||
|
||
.indicators
|
||
padding 1em 0
|
||
text-align center
|
||
|
||
table
|
||
display inline-block
|
||
vertical-align top
|
||
margin 0.5em
|
||
empty-cells show
|
||
border 3px solid #bbb
|
||
|
||
td, th
|
||
padding 4px
|
||
white-space nowrap
|
||
|
||
tr:nth-child(odd)
|
||
background #f7f7f7
|
||
|
||
th
|
||
text-align left
|
||
|
||
td
|
||
text-align right
|
||
|
||
&.inputs, &.outputs
|
||
td:nth-child(1), td:nth-child(5)
|
||
text-align center
|
||
|
||
th.header
|
||
height 2.5em
|
||
border-bottom 3px solid #ccc
|
||
text-align center
|
||
|
||
th.separator
|
||
background #ccc
|
||
border 1px solid #ccc
|
||
padding 1px
|
||
|
||
&.motor_fault
|
||
td, th
|
||
text-align center
|
||
min-width 1.75em
|
||
|
||
.fa-eraser
|
||
cursor pointer
|
||
|
||
&:hover
|
||
opacity 0.5
|
||
|
||
.io
|
||
&.active
|
||
color green
|
||
|
||
&.inactive
|
||
color black
|
||
|
||
&.warn
|
||
background-color transparent
|
||
color orange
|
||
|
||
tt.save
|
||
display inline-block
|
||
border-radius 2px
|
||
background #1cb841
|
||
color rgba(0, 0, 0, 0.8)
|
||
padding 0.25em
|
||
line-height initial
|
||
|
||
.modbus-program button
|
||
margin 0.25em 0
|
||
|
||
.pure-form .modbus-regs
|
||
input, select
|
||
border none
|
||
box-shadow none
|
||
border-radius 0
|
||
background transparent
|
||
padding 0 0.5em
|
||
height 1.75em
|
||
line-height 1.75em
|
||
|
||
input
|
||
text-align right
|
||
width 6em
|
||
|
||
button
|
||
margin 2px
|
||
|
||
th, td
|
||
border 1px solid #ccc
|
||
line-height 1.75em
|
||
|
||
th
|
||
padding 0.5em
|
||
|
||
&.fixed-regs td, td.reg-index, td.modbus-status
|
||
padding 0 0.5em
|
||
|
||
td.reg-index, td.reg-addr, td.reg-value
|
||
text-align right
|
||
|
||
tr:nth-child(even):not(.warn)
|
||
background-color #f3f3f3
|
||
|
||
|
||
// Legacy `.tabs` selector retained only for #macros (Settings → Macros)
|
||
// which uses .tabs as a content container with a <select> inside; the
|
||
// old radio-based tab system has been removed.
|
||
#macros .tabs
|
||
clear both
|
||
|
||
|
||
.motor.slave
|
||
.tmpl-input-axis .units::after
|
||
content "(slave motor)"
|
||
white-space nowrap
|
||
|
||
fieldset.limits, fieldset.homing, fieldset.motion .pure-control-group,
|
||
fieldset.power .pure-control-group.tmpl-input-enabled
|
||
display none
|
||
|
||
fieldset.motion .pure-control-group.tmpl-input-reverse
|
||
display inherit
|
||
|
||
|
||
.admin-general-view, .admin-network-view
|
||
h2:not(:first-of-type)
|
||
margin-top 2em
|
||
|
||
a
|
||
text-decoration none
|
||
|
||
.tip
|
||
font-style italic
|
||
font-size 90%
|
||
line-height 1.5
|
||
white-space pre-line
|
||
|
||
.modal-mask
|
||
position fixed
|
||
z-index 9998
|
||
top 0
|
||
left 0
|
||
width 100%
|
||
height 100%
|
||
background-color rgba(0, 0, 0, .25)
|
||
display table
|
||
transition opacity .3s ease
|
||
|
||
.modal-wrapper
|
||
display table-cell
|
||
vertical-align middle
|
||
|
||
.modal-container
|
||
width 380px
|
||
margin 0px auto
|
||
padding 20px 30px
|
||
background-color #fff
|
||
border-radius 2px
|
||
box-shadow 0 2px 8px rgba(0, 0, 0, .33)
|
||
transition all .3s ease
|
||
font-family Helvetica, Arial, sans-serif
|
||
|
||
|
||
.modal-header
|
||
text-decoration underline
|
||
|
||
.modal-footer
|
||
text-align right
|
||
|
||
.footer
|
||
width 100%
|
||
display flex
|
||
justify-content center
|
||
|
||
.modal-enter, .modal-leave
|
||
opacity 0
|
||
|
||
.modal-enter .modal-container
|
||
transform scale(1.1)
|
||
|
||
.modal-leave .modal-container
|
||
transform scale(0.9)
|
||
|
||
.file-upload
|
||
display none
|
||
|
||
.error-message
|
||
&.modal-mask .modal-wrapper .modal-container
|
||
width auto
|
||
max-width 800px
|
||
|
||
.modal-header h3
|
||
white-space nowrap
|
||
overflow hidden
|
||
text-overflow ellipsis
|
||
|
||
.estop
|
||
float right
|
||
transform scale(0.75)
|
||
margin-top -30px
|
||
|
||
.console
|
||
margin-bottom 1em
|
||
clear both
|
||
|
||
|
||
.wifi-confirm table
|
||
th
|
||
text-align right
|
||
|
||
th, td
|
||
padding 0 4px
|
||
|
||
|
||
.cheat-sheet
|
||
table
|
||
border-collapse collapse
|
||
margin-bottom 0.5em
|
||
|
||
*
|
||
text-align left
|
||
|
||
th, td
|
||
border 1px solid #eee
|
||
padding 4px
|
||
|
||
tr.header-row
|
||
background #eee
|
||
|
||
tr:nth-child(even)
|
||
background #f7f7f7
|
||
|
||
tr.unimplemented
|
||
background #ffff9b
|
||
|
||
tr.spacer-row
|
||
background transparent
|
||
|
||
th, td
|
||
border none
|
||
height 1em
|
||
|
||
|
||
// Compact-width fallback (e.g. 1366×768) — stack the right column
|
||
// under the jog grid and tighten the macro row.
|
||
@media only screen and (max-width: 1820px)
|
||
.control-page .control-grid
|
||
grid-template-columns 1fr
|
||
|
||
.control-page .right-col
|
||
grid-template-rows auto auto
|
||
|
||
.control-page .macro-row
|
||
grid-template-columns repeat(4, 1fr)
|
||
|
||
.reset-variants
|
||
padding-left 40px
|
||
padding-bottom 20px
|
||
display grid
|
||
grid-template-rows repeat(4, auto)
|
||
grid-template-columns min-content auto
|
||
grid-gap 20px 10px
|
||
|
||
input[type="radio"]
|
||
width 30px
|
||
height 30px
|
||
|
||
label
|
||
font-size 16pt
|
||
align-self center
|
||
|
||
.pure-form-aligned .pure-control-group label:not(.extra)
|
||
width 12em
|
||
|
||
.pure-form-aligned .pure-control-group label.extra
|
||
width 8em
|
||
|
||
input.input-name
|
||
width 300px
|
||
height 40px
|
||
border-top-right-radius 8px
|
||
border-bottom-right-radius 8px
|
||
border-top-left-radius 5px
|
||
border-bottom-left-radius 5px
|
||
border-width 1px
|
||
border-color #434242
|
||
padding-left 10px
|
||
margin-left 2px
|
||
|
||
.input-container
|
||
display flex
|
||
height 50px
|
||
align-items center
|
||
|
||
|
||
p.title
|
||
font-size 20px
|
||
padding-top 20px
|
||
font-weight 600
|
||
|
||
|
||
input.input-color
|
||
height 45px
|
||
width 45px
|
||
border 1px solid #fdfdfd
|
||
border-top-left-radius 8px
|
||
border-bottom-left-radius 8px
|
||
|
||
button
|
||
border-radius 8px
|
||
border-width 1px
|
||
border 1
|
||
|
||
.input-field
|
||
margin-top 10px
|
||
|
||
select .heading-option
|
||
font-weight bold
|
||
background-color #f0f0f0
|
||
color #555
|
||
|
||
// =====================================================================
|
||
// CONTROL page (V09)
|
||
// =====================================================================
|
||
.control-page
|
||
flex 1 1 auto
|
||
min-height 0
|
||
display flex
|
||
flex-direction column
|
||
gap 14px
|
||
overflow hidden
|
||
|
||
.control-page .control-grid
|
||
display grid
|
||
grid-template-columns 720px 1fr
|
||
gap 18px
|
||
flex 1
|
||
min-height 0
|
||
|
||
// Card primitive
|
||
.control-page .jog-card
|
||
.control-page .dro-card
|
||
.control-page .stat-card
|
||
.program-page .program-card
|
||
.console-page .console-card
|
||
background $bg
|
||
border 1px solid $line
|
||
border-radius 18px
|
||
|
||
.control-page .jog-card
|
||
display flex
|
||
flex-direction column
|
||
padding 18px
|
||
min-height 0
|
||
|
||
.control-page .jog-head
|
||
display flex
|
||
align-items center
|
||
justify-content space-between
|
||
margin-bottom 14px
|
||
|
||
.control-page .jog-title
|
||
font-size 18px
|
||
font-weight 700
|
||
color $ink
|
||
|
||
.step-pre
|
||
color $muted
|
||
|
||
.step
|
||
color $accent-text
|
||
font-family 'JetBrains Mono', monospace
|
||
font-weight 700
|
||
margin-left 4px
|
||
|
||
.unit
|
||
color $muted-2
|
||
font-size 0.85em
|
||
margin-left 2px
|
||
|
||
// Step segmented control
|
||
.step-seg
|
||
display inline-flex
|
||
background $line-soft
|
||
border 1px solid $line
|
||
border-radius 14px
|
||
padding 4px
|
||
|
||
button
|
||
height 48px
|
||
min-width 64px
|
||
padding 0 1rem
|
||
border-radius 11px
|
||
font-size 1rem
|
||
font-weight 800
|
||
color $ink-soft
|
||
background transparent
|
||
border none
|
||
cursor pointer
|
||
|
||
button.active
|
||
background $ink
|
||
color $accent
|
||
|
||
// Jog grid
|
||
.control-page .jog-grid
|
||
display grid
|
||
grid-template-columns repeat(4, 1fr)
|
||
grid-template-rows repeat(4, 1fr)
|
||
gap 10px
|
||
flex 1
|
||
min-height 0
|
||
|
||
.jbtn
|
||
border-radius 16px
|
||
display flex
|
||
flex-direction column
|
||
align-items center
|
||
justify-content center
|
||
gap 4px
|
||
user-select none
|
||
-webkit-tap-highlight-color transparent
|
||
cursor pointer
|
||
font-weight 700
|
||
font-size 1.05rem
|
||
border none
|
||
background $jog-bg
|
||
color $jog-ink
|
||
transition transform 0.06s, background 0.15s
|
||
min-height 0
|
||
min-width 0
|
||
|
||
.ico
|
||
font-size 1.6rem
|
||
|
||
.lbl
|
||
font-size 0.8rem
|
||
color inherit
|
||
opacity 0.85
|
||
font-weight 600
|
||
|
||
&:hover:not([disabled])
|
||
background $jog-hover
|
||
|
||
&:active:not([disabled])
|
||
transform scale(0.97)
|
||
|
||
&[disabled]
|
||
opacity 0.45
|
||
cursor not-allowed
|
||
|
||
&.dir
|
||
background $jog-dir
|
||
|
||
&.dir:hover:not([disabled])
|
||
background $jog-dir-hov
|
||
|
||
&.ghost
|
||
background $jog-ghost
|
||
color $jog-ghost-ink
|
||
|
||
&.ghost:hover:not([disabled])
|
||
background $jog-ghost-hov
|
||
|
||
// DRO + status
|
||
.control-page .right-col
|
||
display grid
|
||
grid-template-rows 1fr 158px
|
||
gap 18px
|
||
min-height 0
|
||
|
||
.control-page .dro-card
|
||
overflow hidden
|
||
display flex
|
||
flex-direction column
|
||
|
||
.control-page .dro-head, .control-page .dro-row
|
||
display grid
|
||
grid-template-columns 84px 1.4fr 1fr 1fr 170px 170px 280px
|
||
column-gap 0.75rem
|
||
align-items center
|
||
padding 14px 22px
|
||
|
||
.control-page .dro-head
|
||
background #f8fafc
|
||
border-bottom 1px solid $line
|
||
font-size 0.78rem
|
||
font-weight 800
|
||
text-transform uppercase
|
||
letter-spacing 0.1em
|
||
color $muted-2
|
||
|
||
.control-page .dro-row
|
||
border-bottom 1px solid $line-soft
|
||
flex 1
|
||
min-height 0
|
||
|
||
&:last-child
|
||
border-bottom none
|
||
|
||
.control-page .dro-row.warn
|
||
background rgba(254, 243, 199, 0.4)
|
||
|
||
.control-page .dro-row.error
|
||
background rgba(254, 226, 226, 0.4)
|
||
|
||
.dro-axis
|
||
font-weight 900
|
||
font-size 46px
|
||
line-height 1
|
||
text-transform uppercase
|
||
|
||
.dro-axis.axis-x
|
||
color #dc2626
|
||
|
||
.dro-axis.axis-y
|
||
color #16a34a
|
||
|
||
.dro-axis.axis-z
|
||
color #2563eb
|
||
|
||
.dro-axis.axis-a
|
||
color #ea580c
|
||
|
||
.dro-axis.axis-b
|
||
color #06b6d4
|
||
|
||
.dro-axis.axis-c
|
||
color #d946ef
|
||
|
||
.dro-axis.axis-w
|
||
color #7c3aed
|
||
|
||
.dro-pos
|
||
font-family 'JetBrains Mono', monospace
|
||
font-size 36px
|
||
font-weight 800
|
||
letter-spacing -0.01em
|
||
|
||
.dro-pos .u
|
||
font-size 14px
|
||
color $muted-2
|
||
font-weight 500
|
||
margin-left 6px
|
||
|
||
.dro-sec
|
||
font-family 'JetBrains Mono', monospace
|
||
font-size 18px
|
||
color $muted
|
||
font-weight 600
|
||
|
||
// Status chips
|
||
.chip
|
||
display inline-flex
|
||
align-items center
|
||
gap 0.4rem
|
||
padding 0.4rem 0.7rem
|
||
border-radius 9999px
|
||
font-size 0.78rem
|
||
font-weight 700
|
||
|
||
.chip-green
|
||
background #dcfce7
|
||
color #166534
|
||
|
||
.chip-amber
|
||
background #fef3c7
|
||
color #92400e
|
||
|
||
.chip-red
|
||
background #fee2e2
|
||
color #991b1b
|
||
|
||
.chip-slate
|
||
background #e2e8f0
|
||
color #334155
|
||
|
||
.chip-blue
|
||
background #dbeafe
|
||
color #1e40af
|
||
|
||
// Per-axis action buttons
|
||
.icon-btn
|
||
width 72px
|
||
height 72px
|
||
border-radius 14px
|
||
display inline-flex
|
||
align-items center
|
||
justify-content center
|
||
color $ink-soft
|
||
background $line-soft
|
||
border 1px solid $line
|
||
font-size 1.45rem
|
||
cursor pointer
|
||
|
||
&:hover:not([disabled])
|
||
background #e2e8f0
|
||
|
||
&[disabled]
|
||
opacity 0.45
|
||
cursor not-allowed
|
||
|
||
.actions-cell
|
||
display flex
|
||
justify-content flex-end
|
||
gap 10px
|
||
|
||
// Status strip
|
||
.control-page .status-strip
|
||
display grid
|
||
grid-template-columns repeat(4, 1fr)
|
||
gap 18px
|
||
min-height 0
|
||
|
||
.control-page .stat-card
|
||
padding 18px 22px
|
||
display flex
|
||
flex-direction column
|
||
justify-content center
|
||
position relative
|
||
|
||
.stat-label
|
||
font-size 11px
|
||
font-weight 800
|
||
text-transform uppercase
|
||
letter-spacing 0.14em
|
||
color $muted-2
|
||
|
||
.stat-val
|
||
font-family 'JetBrains Mono', monospace
|
||
font-size 30px
|
||
font-weight 800
|
||
margin-top 6px
|
||
color $ink
|
||
|
||
.stat-val.ok
|
||
color #166534
|
||
|
||
.stat-val.warn
|
||
color #92400e
|
||
|
||
.stat-val.bad
|
||
color #991b1b
|
||
|
||
.stat-val.busy
|
||
color #1e40af
|
||
|
||
.stat-sub
|
||
font-size 13px
|
||
color $muted
|
||
margin-top 2px
|
||
|
||
.control-page .stat-tappable
|
||
cursor pointer
|
||
transition border-color 0.15s
|
||
|
||
&:hover
|
||
border-color $accent-text
|
||
|
||
.tap-hint
|
||
margin-left 6px
|
||
color $muted-2
|
||
font-size 14px
|
||
|
||
&.open
|
||
border-color $accent
|
||
box-shadow 0 0 0 3px rgba(253, 224, 71, 0.35)
|
||
|
||
// Macro row
|
||
.control-page .macro-row
|
||
display grid
|
||
grid-template-columns repeat(8, 1fr)
|
||
gap 12px
|
||
flex 0 0 auto
|
||
|
||
.macro-btn
|
||
height 84px
|
||
border-radius 14px
|
||
border 1px solid transparent
|
||
color #fff
|
||
background $jog-bg
|
||
font-weight 800
|
||
font-size 1rem
|
||
display flex
|
||
align-items center
|
||
justify-content center
|
||
gap 0.6rem
|
||
cursor pointer
|
||
overflow hidden
|
||
text-shadow 0 0 3px rgba(0, 0, 0, 0.6)
|
||
transition transform 0.06s, background 0.15s
|
||
|
||
&:hover:not([disabled])
|
||
background $jog-hover
|
||
|
||
&:active:not([disabled])
|
||
transform translateY(2px)
|
||
|
||
&[disabled]
|
||
opacity 0.45
|
||
cursor not-allowed
|
||
|
||
// Per-macro color stripe is opt-in via :class="has-color" set by
|
||
// the template only when state.macros[i].color is configured.
|
||
&.has-color
|
||
border-left-width 6px
|
||
border-left-style solid
|
||
|
||
.mnum
|
||
display inline-flex
|
||
align-items center
|
||
justify-content center
|
||
width 28px
|
||
height 28px
|
||
border-radius 8px
|
||
background $accent
|
||
color $accent-ink
|
||
font-size 0.85rem
|
||
font-weight 900
|
||
text-shadow none
|
||
flex 0 0 auto
|
||
|
||
.mname
|
||
white-space nowrap
|
||
overflow hidden
|
||
text-overflow ellipsis
|
||
|
||
// Override drawer
|
||
.override-drawer
|
||
position fixed
|
||
left 18px
|
||
right 18px
|
||
bottom 0
|
||
height 0
|
||
background $bg
|
||
border 1px solid $line
|
||
border-bottom none
|
||
border-radius 18px 18px 0 0
|
||
box-shadow 0 -10px 30px rgba(15, 23, 42, 0.18)
|
||
overflow hidden
|
||
transition height 0.2s, padding 0.2s
|
||
z-index 60
|
||
padding 0 22px
|
||
|
||
&.open
|
||
height 220px
|
||
padding 18px 22px
|
||
|
||
.override-drawer .od-head
|
||
display flex
|
||
align-items center
|
||
justify-content space-between
|
||
margin-bottom 14px
|
||
|
||
.override-drawer .od-title
|
||
font-size 1.1rem
|
||
font-weight 800
|
||
color $ink
|
||
|
||
.override-drawer .od-close
|
||
width 40px
|
||
height 40px
|
||
border-radius 10px
|
||
background $line-soft
|
||
border 1px solid $line
|
||
font-size 1.2rem
|
||
cursor pointer
|
||
|
||
.override-drawer .od-row
|
||
display grid
|
||
grid-template-columns 90px 1fr 80px 140px
|
||
gap 14px
|
||
align-items center
|
||
margin-bottom 10px
|
||
|
||
label
|
||
font-weight 700
|
||
color $ink-soft
|
||
|
||
input[type="range"]
|
||
width 100%
|
||
height 36px
|
||
|
||
.od-val
|
||
font-family 'JetBrains Mono', monospace
|
||
font-weight 700
|
||
text-align right
|
||
|
||
.override-drawer .od-reset
|
||
height 40px
|
||
padding 0 12px
|
||
border-radius 10px
|
||
background $line-soft
|
||
border 1px solid $line
|
||
color $ink
|
||
font-weight 700
|
||
cursor pointer
|
||
|
||
&:hover
|
||
background #e2e8f0
|
||
|
||
// =====================================================================
|
||
// PROGRAM page (V09)
|
||
// =====================================================================
|
||
.program-page
|
||
flex 1 1 auto
|
||
min-height 0
|
||
display flex
|
||
flex-direction column
|
||
overflow hidden
|
||
|
||
.program-card
|
||
flex 1
|
||
display flex
|
||
flex-direction column
|
||
min-height 0
|
||
overflow hidden
|
||
background $bg
|
||
border 1px solid $line
|
||
border-radius 18px
|
||
|
||
.action-bar
|
||
display flex
|
||
align-items center
|
||
gap 12px
|
||
padding 18px
|
||
flex-wrap wrap
|
||
border-bottom 1px solid $line-soft
|
||
|
||
.action-btn
|
||
height 84px
|
||
padding 0 22px
|
||
border-radius 14px
|
||
background $jog-bg
|
||
color #fff
|
||
border none
|
||
cursor pointer
|
||
display inline-flex
|
||
flex-direction column
|
||
align-items center
|
||
justify-content center
|
||
gap 4px
|
||
font-weight 800
|
||
font-size 0.9rem
|
||
letter-spacing 0.04em
|
||
transition background 0.15s, transform 0.06s
|
||
|
||
&:hover:not([disabled])
|
||
background $jog-hover
|
||
|
||
&:active:not([disabled])
|
||
transform translateY(2px)
|
||
|
||
&[disabled]
|
||
opacity 0.45
|
||
cursor not-allowed
|
||
|
||
.ico
|
||
font-size 1.4rem
|
||
|
||
&.run
|
||
background #16a34a
|
||
|
||
&.run:hover:not([disabled])
|
||
background #15803d
|
||
|
||
&.stop
|
||
background $ink
|
||
|
||
&.stop:hover:not([disabled])
|
||
background #1e293b
|
||
|
||
&.danger
|
||
background #fee2e2
|
||
color #7f1d1d
|
||
|
||
&.danger:hover:not([disabled])
|
||
background #fecaca
|
||
|
||
&.danger .ico
|
||
color #dc2626
|
||
|
||
.file-bar
|
||
display flex
|
||
align-items center
|
||
gap 10px
|
||
padding 14px 18px
|
||
flex-wrap wrap
|
||
border-bottom 1px solid $line-soft
|
||
|
||
.file-btn
|
||
height 54px
|
||
padding 0 18px
|
||
border-radius 12px
|
||
background $line-soft
|
||
border 1px solid $line
|
||
font-weight 700
|
||
color $ink
|
||
font-size 0.9rem
|
||
display inline-flex
|
||
align-items center
|
||
gap 0.4rem
|
||
cursor pointer
|
||
|
||
&:hover:not([disabled])
|
||
background #e2e8f0
|
||
|
||
&[disabled]
|
||
opacity 0.45
|
||
cursor not-allowed
|
||
|
||
.file-select
|
||
height 54px
|
||
padding 0 16px
|
||
border-radius 12px
|
||
background $bg
|
||
border 1px solid $line
|
||
font-weight 600
|
||
color $ink
|
||
font-size 0.9rem
|
||
cursor pointer
|
||
|
||
&.primary
|
||
border 2px solid $accent-text
|
||
flex 1
|
||
min-width 300px
|
||
|
||
.program-body
|
||
flex 1 1 auto
|
||
display grid
|
||
grid-template-columns 1fr 600px
|
||
min-height 0
|
||
overflow hidden
|
||
|
||
> .gcode
|
||
border-right 1px solid $line-soft
|
||
background #fafafa
|
||
padding 0
|
||
margin 0
|
||
overflow hidden
|
||
min-height 0
|
||
display flex
|
||
flex-direction column
|
||
|
||
// 3D toolpath preview — fill the entire 600px column. Override the
|
||
// legacy `.path-viewer.small` rule which would clamp the canvas to
|
||
// 340x150 and float it into the corner.
|
||
> .path-viewer
|
||
overflow hidden
|
||
min-height 0
|
||
display flex
|
||
flex-direction column
|
||
|
||
.path-viewer-content
|
||
flex 1 1 auto
|
||
width 100% !important
|
||
height auto !important
|
||
min-height 0
|
||
float none !important
|
||
margin 0 !important
|
||
|
||
&.small .path-viewer-content
|
||
width 100% !important
|
||
height auto !important
|
||
float none !important
|
||
margin 0 !important
|
||
|
||
.progress-bar
|
||
height 28px
|
||
background #fff
|
||
border-top 1px solid $line-soft
|
||
position relative
|
||
|
||
> div
|
||
height 28px
|
||
background #f2ac45
|
||
color $ink
|
||
text-align center
|
||
line-height 28px
|
||
font-weight 700
|
||
|
||
// Restored layout for the program-page gcode-viewer (uses clusterize.js)
|
||
.program-body .gcode
|
||
font-family 'JetBrains Mono', monospace
|
||
font-size 13px
|
||
line-height 1.55
|
||
|
||
.clusterize
|
||
flex 1 1 0
|
||
min-height 0
|
||
overflow hidden
|
||
display flex
|
||
flex-direction column
|
||
height 100%
|
||
|
||
.clusterize-scroll
|
||
flex 1 1 0
|
||
min-height 0
|
||
height 100%
|
||
max-height none // override clusterize.css default of 200px
|
||
width 100%
|
||
overflow auto
|
||
|
||
ul
|
||
margin 0
|
||
padding 0
|
||
list-style none
|
||
|
||
li
|
||
line-height 18px
|
||
padding 1px 18px
|
||
|
||
li:nth-child(even)
|
||
background #f4f4f5
|
||
|
||
li.highlight
|
||
background #dbeafe
|
||
|
||
li > b
|
||
font-weight normal
|
||
color #f59e0b
|
||
min-width 4em
|
||
display inline-block
|
||
padding 0 0.25em
|
||
|
||
// =====================================================================
|
||
// CONSOLE page (V09)
|
||
// =====================================================================
|
||
.console-page
|
||
flex 1 1 auto
|
||
display flex
|
||
min-height 0
|
||
overflow hidden
|
||
|
||
.console-card
|
||
flex 1
|
||
display flex
|
||
flex-direction column
|
||
min-height 0
|
||
overflow hidden
|
||
background $bg
|
||
border 1px solid $line
|
||
border-radius 18px
|
||
|
||
.console-card .ptab-bar
|
||
display flex
|
||
align-items center
|
||
gap 6px
|
||
border-bottom 1px solid $line
|
||
flex 0 0 auto
|
||
padding 0 18px
|
||
background $bg
|
||
|
||
.ptab
|
||
height 60px
|
||
padding 0 22px
|
||
font-weight 700
|
||
color $muted
|
||
border-bottom 3px solid transparent
|
||
font-size 1rem
|
||
display inline-flex
|
||
align-items center
|
||
gap 0.4rem
|
||
background transparent
|
||
border-top none
|
||
border-left none
|
||
border-right none
|
||
cursor pointer
|
||
|
||
&:hover
|
||
color $ink
|
||
|
||
&.active
|
||
color $ink
|
||
border-bottom-color $ink
|
||
|
||
.ptab-badge
|
||
background $accent
|
||
color $accent-ink
|
||
font-size 0.7rem
|
||
padding 2px 7px
|
||
border-radius 9999px
|
||
font-weight 900
|
||
|
||
.mdi-pane
|
||
flex 1
|
||
min-height 0
|
||
padding 18px
|
||
display flex
|
||
flex-direction column
|
||
gap 14px
|
||
|
||
.mdi-input
|
||
display flex
|
||
align-items center
|
||
gap 0.6rem
|
||
background #0b1220
|
||
color #86efac
|
||
border 1px solid #1e293b
|
||
border-radius 14px
|
||
padding 18px 22px
|
||
font-family 'JetBrains Mono', monospace
|
||
font-size 1.3rem
|
||
font-weight 600
|
||
|
||
.prompt
|
||
color #475569
|
||
|
||
input
|
||
flex 1
|
||
background transparent
|
||
border none
|
||
color inherit
|
||
font-family inherit
|
||
font-size inherit
|
||
outline none
|
||
|
||
.mdi-send
|
||
height 48px
|
||
padding 0 18px
|
||
border-radius 10px
|
||
background #16a34a
|
||
color #fff
|
||
border none
|
||
font-weight 800
|
||
cursor pointer
|
||
font-size 0.95rem
|
||
letter-spacing 0.05em
|
||
|
||
.mdi-send[disabled]
|
||
opacity 0.45
|
||
cursor not-allowed
|
||
|
||
.mdi-keys
|
||
display grid
|
||
grid-template-columns repeat(8, 1fr)
|
||
gap 8px
|
||
flex 0 0 auto
|
||
|
||
.mkey
|
||
height 64px
|
||
border-radius 12px
|
||
background $bg
|
||
border 1px solid $line
|
||
font-weight 800
|
||
font-size 1.05rem
|
||
color $ink
|
||
cursor pointer
|
||
font-family 'JetBrains Mono', monospace
|
||
|
||
&:hover
|
||
background $line-soft
|
||
|
||
.mkey.send
|
||
background #16a34a
|
||
color #fff
|
||
border-color #15803d
|
||
grid-column span 2
|
||
font-family 'Inter', sans-serif
|
||
|
||
.mkey.send[disabled]
|
||
opacity 0.45
|
||
cursor not-allowed
|
||
|
||
.mkey.clear
|
||
background #fee2e2
|
||
color #7f1d1d
|
||
border-color #fca5a5
|
||
font-family 'Inter', sans-serif
|
||
|
||
.mdi-history
|
||
flex 1
|
||
background $bg
|
||
border 1px solid $line
|
||
border-radius 14px
|
||
padding 12px 18px
|
||
overflow auto
|
||
font-family 'JetBrains Mono', monospace
|
||
font-size 0.95rem
|
||
|
||
.mdi-empty
|
||
color $muted-2
|
||
|
||
.h-row
|
||
display grid
|
||
grid-template-columns 1fr auto
|
||
gap 14px
|
||
padding 6px 0
|
||
border-bottom 1px solid $line-soft
|
||
align-items center
|
||
cursor pointer
|
||
|
||
&:last-child
|
||
border-bottom none
|
||
|
||
.h-cmd
|
||
color $ink
|
||
font-weight 700
|
||
|
||
.h-status
|
||
color $muted-2
|
||
|
||
.messages-pane
|
||
flex 1
|
||
min-height 0
|
||
padding 18px
|
||
display flex
|
||
flex-direction column
|
||
gap 12px
|
||
overflow auto
|
||
|
||
.msg-empty
|
||
color $muted
|
||
text-align center
|
||
padding 40px
|
||
|
||
.msg
|
||
background $bg
|
||
border 1px solid $line
|
||
border-radius 14px
|
||
padding 18px 22px
|
||
display grid
|
||
grid-template-columns 54px 1fr
|
||
gap 18px
|
||
align-items flex-start
|
||
|
||
.msg.warn
|
||
border-left 6px solid #f59e0b
|
||
|
||
.msg.warn .mi
|
||
background #fef3c7
|
||
color #92400e
|
||
|
||
.msg.info
|
||
border-left 6px solid #0ea5e9
|
||
|
||
.msg.info .mi
|
||
background #dbeafe
|
||
color #1e40af
|
||
|
||
.msg .mi
|
||
width 54px
|
||
height 54px
|
||
border-radius 12px
|
||
display inline-flex
|
||
align-items center
|
||
justify-content center
|
||
font-size 1.4rem
|
||
|
||
.msg .mtitle
|
||
font-weight 800
|
||
font-size 1.05rem
|
||
color $ink
|
||
|
||
.msg .mtime
|
||
font-size 0.8rem
|
||
color $muted-2
|
||
margin-top 2px
|
||
|
||
.indicators-pane
|
||
flex 1
|
||
min-height 0
|
||
padding 18px
|
||
overflow auto
|
||
|
||
// =====================================================================
|
||
// SETTINGS shell
|
||
// =====================================================================
|
||
.settings-shell
|
||
flex 1
|
||
display grid
|
||
grid-template-columns 280px 1fr
|
||
gap 14px
|
||
min-height 0
|
||
|
||
.settings-rail
|
||
background $bg
|
||
border 1px solid $line
|
||
border-radius 14px
|
||
padding 10px
|
||
display flex
|
||
flex-direction column
|
||
gap 4px
|
||
align-self start
|
||
height fit-content
|
||
position sticky
|
||
top 18px
|
||
|
||
.set-item
|
||
height 48px
|
||
padding 0 14px
|
||
border-radius 10px
|
||
display flex
|
||
align-items center
|
||
gap 0.6rem
|
||
color $ink-soft
|
||
font-weight 700
|
||
cursor pointer
|
||
text-decoration none
|
||
font-size 0.95rem
|
||
|
||
.fa
|
||
width 18px
|
||
text-align center
|
||
color $muted-2
|
||
|
||
.set-item:hover
|
||
background $line-soft
|
||
|
||
.set-item.active
|
||
background $ink
|
||
color #fff
|
||
|
||
.fa
|
||
color $accent
|
||
|
||
.set-section
|
||
margin 8px 4px 4px
|
||
font-size 0.7rem
|
||
text-transform uppercase
|
||
letter-spacing 0.12em
|
||
color $muted-2
|
||
font-weight 800
|
||
|
||
.set-rail-foot
|
||
display flex
|
||
flex-direction column
|
||
gap 6px
|
||
margin-top 6px
|
||
padding-top 8px
|
||
border-top 1px solid $line-soft
|
||
|
||
.sp-shutdown, .sp-save
|
||
height 40px
|
||
border-radius 10px
|
||
border 1px solid $line
|
||
background $line-soft
|
||
color $ink
|
||
font-weight 700
|
||
cursor pointer
|
||
|
||
.sp-shutdown
|
||
background #fef2f2
|
||
color #991b1b
|
||
border-color #fecaca
|
||
|
||
.sp-save:not([disabled])
|
||
background $accent
|
||
color $ink
|
||
border-color $accent
|
||
|
||
.settings-content
|
||
background $bg
|
||
border 1px solid $line
|
||
border-radius 14px
|
||
padding 18px
|
||
min-height 0
|
||
overflow auto
|
||
|
||
h1, h2, h3
|
||
margin-top 0
|