* { box-sizing: border-box; }

body {
    margin: 0;
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
    font-size: 14px;
    color: #24292f;
    background: #f6f8fa;
    height: 100vh;
    display: flex;
    flex-direction: column;
}

.topbar {
    display: flex;
    align-items: baseline;
    gap: 12px;
    padding: 10px 16px;
    background: #24292f;
    color: #fff;
    flex: 0 0 auto;
}
.brand { font-weight: 600; font-size: 16px; }
.tagline { color: #b9c0c8; font-size: 12px; flex: 1 1 auto; }
.repo { color: #9dc7ff; text-decoration: none; font-size: 12px; }
.repo:hover { text-decoration: underline; }

.layout {
    flex: 1 1 auto;
    display: grid;
    /* the model pane's width is a variable so the splitter can move
       it, and so collapsing is just setting it to zero */
    grid-template-columns: var(--model-width, minmax(320px, 38%)) 6px 1fr;
    gap: 12px;
    padding: 12px;
    min-height: 0;
}
/* Each pane is pinned to its own column. Without this, hiding the
   model pane takes it out of the flow and everything after it slides
   left -- the output pane lands in the six-pixel splitter column and
   the page looks empty. */
.pane-input  { grid-column: 1; }
.splitter    { grid-column: 2; }
.pane-output { grid-column: 3; }

/* Narrow: the panes stack, and the splitter turns on its side. The
   model pane's size then lives in --model-height, which is what the
   drag and the arrow keys write in this layout. */
@media (max-width: 860px) {
    .layout {
        grid-template-columns: 1fr;
        grid-template-rows: var(--model-height, minmax(200px, 40%)) 6px 1fr;
    }
    .pane-input  { grid-column: 1; grid-row: 1; }
    .splitter    { grid-column: 1; grid-row: 2; cursor: row-resize; }
    .pane-output { grid-column: 1; grid-row: 3; }
    .layout.is-collapsed { grid-template-rows: 0 6px 1fr; }
}

/* ---- resizing ------------------------------------------------- */

/* Reading a model and reading its diagram want opposite amounts of
   room, so the split is the user's to set -- and to collapse
   entirely, which is what you want once the diagram is the thing you
   are looking at. */
.splitter {
    background: #d0d7de;
    cursor: col-resize;
    border-radius: 3px;
    transition: background .15s;
}
.splitter:hover, .splitter:focus, .splitter.is-dragging { background: #0969da; outline: none; }

/* Collapsing zeroes the model pane's track -- the COLUMN one only
   where there are columns. Below 860px every pane shares column 1,
   so zeroing it would take the output pane down with it; the stacked
   layout collapses the row instead (above). */
@media (min-width: 861px) {
    .layout.is-collapsed { grid-template-columns: 0 6px 1fr; }
}
.layout.is-collapsed .pane-input { display: none; }

.iconbtn {
    font: inherit;
    font-size: 11px;
    line-height: 1;
    padding: 3px 6px;
    border: 1px solid #d0d7de;
    background: #fff;
    border-radius: 4px;
    cursor: pointer;
    color: #57606a;
}
.iconbtn:hover { border-color: #0969da; color: #0969da; }

/* The visualizer's own splitter between the simulator and the graph.
   The widget implements the dragging itself; WebGME supplies the
   styling that makes it visible, and without this it is an invisible
   strip nobody would think to grab.

   Colour only -- NO width. The widget lays those two panels out as
   floats summing to exactly 100% (19.5 + 0.5 + 80), so a min-width
   here pushes the total over and wraps the graph underneath the
   simulator, off the bottom of the page. */
#viewDiagram #hfsmVizHandle {
    background: #d0d7de;
    transition: background .15s;
}
#viewDiagram #hfsmVizHandle:hover { background: #0969da; }

/* ... and the one inside the simulator, between the event controls
   and the selected-state view. Same rule: colour only. Those two
   panels are 49.75% each with a 0.5% handle, so a height here would
   push the column past 100%. */
#viewDiagram #simulatorHandle {
    background: #d0d7de;
    transition: background .15s;
}
#viewDiagram #simulatorHandle:hover { background: #0969da; }

/* The search box and the pan/zoom control ask for z-index 9999 and
   99999. Those beat a bootstrap modal (1050), so the simulator's
   dialogs -- the guard prompt, the payload form, "really change the
   layout?" -- came up UNDERNEATH them.

   Rather than bid higher for the modal, the two are brought down to
   just above cytoscape's canvases (which top out at 4) and this
   toolbar. Dialogs then win by the ordinary rules, which is what
   those rules are for. Scoped to the diagram view, so nothing here
   reaches the widget running inside WebGME. */
#viewDiagram .search { z-index: 20; }   /* the wrapper carries it, not the input */
#viewDiagram .cy-panzoom { z-index: 21; }

/* The widget's toolbar -- print, zoom to fit, auto-layout. WebGME
   puts it in the panel header; here it floats over the top-right of
   the graph, which is the only spare corner.

   The z-index has to clear cytoscape's canvases. The topmost is the
   edgehandles layer, which the widget puts at 4 (its `stackOrder`
   option) -- and being transparent, it let the toolbar show through
   while quietly swallowing every click on it. 10 leaves room for
   another canvas without going near the panzoom control's 99999. */
.viz-toolbar {
    position: absolute;
    top: 8px;
    right: 12px;
    z-index: 10;
    display: flex;
    gap: 4px;
    background: rgba(255, 255, 255, .92);
    border: 1px solid #d0d7de;
    border-radius: 5px;
    padding: 4px 6px;
}
.viz-toolbar .split-panel-toolbar-btn {
    cursor: pointer;
    padding: 3px 6px;
    border-radius: 4px;
    color: #57606a;
    font-size: 14px;
}
.viz-toolbar .split-panel-toolbar-btn:hover { background: #eaeef2; color: #0969da; }

.pane {
    display: flex;
    flex-direction: column;
    min-height: 0;
    min-width: 0;
    background: #fff;
    border: 1px solid #d0d7de;
    border-radius: 6px;
    overflow: hidden;
}
.pane-head {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 8px 10px;
    border-bottom: 1px solid #d0d7de;
    background: #f6f8fa;
}
.pane-head h2 { margin: 0; font-size: 13px; text-transform: uppercase; letter-spacing: .04em; color: #57606a; }
.controls { margin-left: auto; display: flex; align-items: center; gap: 8px; }
/* a flex item ignores [hidden], which is display:none from the UA
   sheet and therefore lower priority than the rule above */
.controls [hidden] { display: none; }

button, select, .filebtn {
    font: inherit;
    font-size: 13px;
    padding: 4px 10px;
    border: 1px solid #d0d7de;
    border-radius: 6px;
    background: #f6f8fa;
    color: #24292f;
    cursor: pointer;
}
button:hover:not(:disabled), .filebtn:hover { background: #eaeef2; }
button:disabled { opacity: .5; cursor: default; }
button.primary { background: #1f883d; border-color: #1a7f37; color: #fff; font-weight: 600; }
button.primary:hover { background: #1a7f37; }
.filebtn { position: relative; overflow: hidden; display: inline-block; }
.filebtn input { position: absolute; inset: 0; opacity: 0; cursor: pointer; width: 100%; }
/* the real input is transparent, so its focus ring is invisible:
   surface focus on the visible label instead, or keyboard users
   cannot tell where they are */
.filebtn:focus-within {
    outline: 2px solid #0969da;
    outline-offset: 1px;
    background: #eaeef2;
}
/* same for every other control, using the browser default ring */
button:focus-visible,
select:focus-visible,
.opt input:focus-visible {
    outline: 2px solid #0969da;
    outline-offset: 1px;
}

.editor-wrap {
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

#modelInput {
    flex: 1 1 auto;
    min-height: 0;
    border: 0;
    padding: 10px;
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: 12px;
    line-height: 1.5;
    resize: none;
    outline: none;
}

/* CodeMirror fills whichever pane it was mounted into */
.editor-wrap .CodeMirror,
.viewer-body .CodeMirror {
    flex: 1 1 auto;
    height: 100%;
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: 12px;
    line-height: 1.5;
}
.viewer-body .CodeMirror { border: 0; }
/* read-only view: hide the blinking cursor, keep selection usable */
.viewer-body .CodeMirror-cursors { visibility: hidden !important; }

.pane-foot {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 8px 10px;
    border-top: 1px solid #d0d7de;
    background: #f6f8fa;
}
.opt { font-size: 12px; color: #57606a; display: flex; align-items: center; gap: 6px; }
.opt input[type="text"] {
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: 12px;
    padding: 3px 6px;
    border: 1px solid #d0d7de;
    border-radius: 6px;
    width: 150px;
}
.opt.checkbox { cursor: pointer; }
.pane-foot .primary { margin-left: auto; }

.status { font-size: 12px; color: #57606a; }
.status-ok { color: #1a7f37; }
.status-warn { color: #9a6700; }
.status-error { color: #cf222e; font-weight: 600; }

.diagnostics {
    padding: 8px 10px;
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: 12px;
    line-height: 1.5;
    max-height: 30%;
    overflow: auto;
    border-bottom: 1px solid #d0d7de;
    white-space: pre-wrap;
}
.diagnostics-error { background: #ffebe9; color: #82071e; }
.diagnostics-warn { background: #fff8c5; color: #7d4e00; }
.diag-line + .diag-line { margin-top: 6px; }

.results { flex: 1 1 auto; display: flex; min-height: 0; }
/* `display` beats the hidden attribute, so a flex pane that can be
   switched off has to say so explicitly. */
.results[hidden] { display: none; }
.filelist {
    flex: 0 0 240px;
    margin: 0;
    padding: 6px;
    list-style: none;
    overflow: auto;
    border-right: 1px solid #d0d7de;
    background: #f6f8fa;
}
.filelist-group {
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: .04em;
    color: #57606a;
    margin: 8px 4px 2px;
}
.filelist-item {
    display: block;
    width: 100%;
    text-align: left;
    border: 0;
    background: transparent;
    border-radius: 6px;
    padding: 3px 6px;
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: 12px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.filelist-item:hover { background: #eaeef2; }
.filelist-item.active { background: #ddf4ff; color: #0969da; font-weight: 600; }

.viewer { flex: 1 1 auto; display: flex; flex-direction: column; min-width: 0; min-height: 0; }
.viewer-head {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 6px 10px;
    border-bottom: 1px solid #d0d7de;
}
.viewer-name {
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: 12px;
    color: #57606a;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.viewer-actions { margin-left: auto; display: flex; gap: 6px; }
.viewer-body {
    flex: 1 1 auto;
    margin: 0;
    overflow: auto;
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: 12px;
    line-height: 1.5;
    white-space: pre;
    min-height: 0;
    display: flex;
    flex-direction: column;
}

/* the hidden attribute must win over the display below, or the
   overlay shows on page load */
.dropoverlay[hidden] { display: none; }

.dropoverlay {
    position: fixed;
    inset: 0;
    background: rgba(31, 136, 61, .12);
    border: 3px dashed #1f883d;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 20px;
    font-weight: 600;
    color: #1a7f37;
    z-index: 10;
    pointer-events: none;
}

/* ---- Output tabs: generated code, or the model as a diagram ---- */
.tabs {
    display: flex;
    gap: 2px;
    margin-left: 12px;
}
.tab {
    font: inherit;
    padding: 3px 12px;
    border: 1px solid var(--line, #d0d7de);
    background: transparent;
    color: inherit;
    cursor: pointer;
    border-radius: 4px;
}
.tab.is-active {
    background: var(--accent, #0969da);
    border-color: var(--accent, #0969da);
    color: #fff;
}

/* The visualizer sizes itself from its container, so this has to be
   a real box with a height rather than a wrapper that collapses. */
.viewdiagram {
    flex: 1 1 auto;
    min-height: 0;
    position: relative;
    overflow: hidden;
}
.viewdiagram[hidden] { display: none; }

/* ---- editing: palette, menu, drag ghost ------------------------ */

/* The diagram view is a palette strip above the widget. The widget
   draws into an absolutely positioned element that fills its
   container, so it gets a container to itself rather than sharing
   one with the strip. */
.viewdiagram { display: flex; flex-direction: column; }
.viz-host { flex: 1 1 auto; position: relative; min-height: 0; }

.viz-palette {
    flex: 0 0 auto;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 4px;
    padding: 6px 8px;
    border-bottom: 1px solid #d0d7de;
    background: #f6f8fa;
}
.viz-palette-label { font-size: 11px; color: #57606a; margin-right: 4px; }
.viz-part {
    font: inherit;
    font-size: 11px;
    line-height: 1;
    padding: 4px 8px;
    border: 1px solid #d0d7de;
    border-radius: 12px;
    background: #fff;
    cursor: grab;
    /* the drag is ours, so the browser's own must not also start */
    user-select: none;
    -webkit-user-select: none;
}
.viz-part:hover { border-color: #0969da; color: #0969da; }
.viz-part:active { cursor: grabbing; }

/* Follows the pointer during a drag. `pointer-events: none` is not
   cosmetic: with the ghost under the cursor, cytoscape's container
   would stop receiving mousemove and the widget would never learn
   which state the part is over. */
.pg-drag-ghost {
    position: absolute;
    z-index: 10000;
    pointer-events: none;
    font-size: 11px;
    padding: 3px 7px;
    border: 1px solid #0969da;
    border-radius: 12px;
    background: #ddf4ff;
    color: #0969da;
    box-shadow: 0 1px 4px rgba(0, 0, 0, .2);
}

.pg-menu {
    position: absolute;
    z-index: 10001;
    margin: 0;
    padding: 4px 0;
    list-style: none;
    min-width: 160px;
    border: 1px solid #d0d7de;
    border-radius: 6px;
    background: #fff;
    box-shadow: 0 8px 24px rgba(140, 149, 159, .2);
    font-size: 12px;
}
.pg-menu li { padding: 5px 12px; cursor: pointer; }
.pg-menu li:hover, .pg-menu li:focus { background: #0969da; color: #fff; outline: none; }

/* The documentation editor. WebGME opens a rich-text dialog here;
   the attribute is text either way. */
.pg-overlay {
    position: fixed;
    inset: 0;
    z-index: 10002;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(27, 31, 36, .5);
}
.pg-dialog {
    width: min(720px, 90vw);
    background: #fff;
    border-radius: 6px;
    padding: 16px;
    box-shadow: 0 8px 24px rgba(66, 74, 83, .32);
}
.pg-dialog h3 { margin: 0 0 8px; font-size: 14px; }
.pg-doc {
    width: 100%;
    height: 40vh;
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: 12px;
    border: 1px solid #d0d7de;
    border-radius: 6px;
    padding: 8px;
    resize: vertical;
}
.pg-dialog-buttons {
    display: flex;
    justify-content: flex-end;
    gap: 8px;
    margin-top: 12px;
}
.pg-dialog-buttons button {
    font: inherit;
    font-size: 12px;
    padding: 5px 12px;
    border: 1px solid #d0d7de;
    border-radius: 6px;
    background: #f6f8fa;
    cursor: pointer;
}
.pg-dialog-buttons button.primary {
    background: #1f883d;
    border-color: #1f883d;
    color: #fff;
}

/* ------------------- comparing two machines ---------------------

   The diagram says WHERE something changed; this says WHAT. It sits
   over the graph rather than beside it because the graph is the thing
   being read -- a panel that stole a third of the width would make
   every comparison of a large machine start with a zoom-out.
*/

.diff-panel {
    position: absolute;
    top: 8px;
    right: 8px;
    z-index: 30;
    width: min(340px, 42%);
    max-height: calc(100% - 16px);
    display: flex;
    flex-direction: column;
    background: rgba(255, 255, 255, .97);
    border: 1px solid #d0d7de;
    border-radius: 8px;
    box-shadow: 0 6px 20px rgba(66, 74, 83, .22);
    font-size: 12px;
}

.diff-head {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 8px 10px;
    border-bottom: 1px solid #d0d7de;
}
.diff-title {
    font-weight: 600;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.diff-close {
    margin-left: auto;
    flex: none;
    font: inherit;
    font-size: 11px;
    padding: 3px 8px;
    border: 1px solid #d0d7de;
    border-radius: 6px;
    background: #f6f8fa;
    cursor: pointer;
}
.diff-close:hover { background: #eaeef2; }

.diff-counts {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    padding: 8px 10px;
    border-bottom: 1px solid #eaeef2;
    color: #57606a;
}
/* the same three colours the diagram uses, so the count and the
   outline are obviously the same statement */
.diff-count {
    padding: 1px 7px;
    border-radius: 999px;
    border: 1px solid;
    font-size: 11px;
}
.diff-count.is-added { color: #1a7f37; border-color: #1a7f37; }
.diff-count.is-removed { color: #cf222e; border-color: #cf222e; }
.diff-count.is-changed { color: #9a6700; border-color: #bf8700; }
/* deliberately grey: a moved state is not a changed state */
.diff-count.is-moved { color: #57606a; border-color: #d0d7de; }

.diff-list {
    margin: 0;
    padding: 4px 0;
    list-style: none;
    overflow: auto;
    flex: 1 1 auto;
}
.diff-item { border-left: 3px solid transparent; }
.diff-item.is-added { border-left-color: #1a7f37; }
.diff-item.is-removed { border-left-color: #cf222e; }
.diff-item.is-changed { border-left-color: #bf8700; }

.diff-item-head {
    display: flex;
    align-items: baseline;
    gap: 6px;
    width: 100%;
    padding: 4px 10px;
    font: inherit;
    font-size: 12px;
    text-align: left;
    background: none;
    border: 0;
    cursor: pointer;
}
.diff-item-head:hover { background: #f6f8fa; }
/* a shape as well as a colour, so the three are still distinct to
   someone who cannot tell red from green */
.diff-badge {
    flex: none;
    width: 1em;
    font-weight: 700;
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
}
.is-added .diff-badge { color: #1a7f37; }
.is-removed .diff-badge { color: #cf222e; }
.is-changed .diff-badge { color: #9a6700; }
.diff-what {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.diff-kind {
    margin-left: auto;
    flex: none;
    color: #8c959f;
    font-size: 10px;
}

.diff-details {
    margin: 0 0 4px 0;
    padding: 0 10px 0 28px;
    list-style: none;
    color: #57606a;
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: 11px;
}
.diff-details li {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.diff-note {
    padding: 6px 10px;
    border-top: 1px solid #eaeef2;
    color: #9a6700;
    font-size: 11px;
}

/* what to compare against */
.compare-menu {
    position: absolute;
    z-index: 60;
    min-width: 200px;
    padding: 4px 0;
    background: #fff;
    border: 1px solid #d0d7de;
    border-radius: 8px;
    box-shadow: 0 6px 20px rgba(66, 74, 83, .22);
}
.compare-menu button {
    display: block;
    width: 100%;
    padding: 5px 12px;
    font: inherit;
    font-size: 12px;
    text-align: left;
    background: none;
    border: 0;
    cursor: pointer;
}
.compare-menu button:hover,
.compare-menu button:focus { background: #f6f8fa; outline: none; }
