/* ELK Diagram Renderer — Styles
 * ============================================================================
 * Design system: "Atlas".
 *
 * Every colour, radius, shadow and duration is a token declared once in
 * :root and overridden once in body.dark. Rules below reference var()s only —
 * if you find yourself typing a hex value in this file, add a token instead.
 * That is what keeps dark mode to a single block rather than an override per
 * rule, and what makes a palette change a five-line diff.
 *
 * Icons are CSS masks over currentColor (includes/images/ui/, Solar Icon Set,
 * CC BY 4.0), so they inherit text colour and need no dark-mode duplicates.
 * ==========================================================================*/

/* === Sora (display) === */
@font-face { font-family: 'Sora'; font-weight: 400; font-display: swap; src: url('fonts/Sora-Regular.woff2') format('woff2'); }
@font-face { font-family: 'Sora'; font-weight: 500; font-display: swap; src: url('fonts/Sora-Medium.woff2') format('woff2'); }
@font-face { font-family: 'Sora'; font-weight: 600; font-display: swap; src: url('fonts/Sora-SemiBold.woff2') format('woff2'); }

/* === Inter (UI text) === */
@font-face { font-family: 'Inter'; font-weight: 400; font-display: swap; src: url('fonts/Inter-Regular.woff2') format('woff2'); }
@font-face { font-family: 'Inter'; font-weight: 500; font-display: swap; src: url('fonts/Inter-Medium.woff2') format('woff2'); }
@font-face { font-family: 'Inter'; font-weight: 600; font-display: swap; src: url('fonts/Inter-SemiBold.woff2') format('woff2'); }

/* ============================================================================
 * Tokens
 * ==========================================================================*/
:root {
    --font-display: 'Sora', system-ui, sans-serif;
    --font-ui: 'Inter', system-ui, sans-serif;
    --font-mono: 'SFMono-Regular', Consolas, 'Monaco', 'Courier New', monospace;

    /* Surfaces */
    --bg-page: #F2F3F9;
    --bg-chrome: #FFFFFF;
    --bg-toolbar: #FFFFFF;
    --bg-panel: #F8F9FD;
    --bg-statusbar: #F8F9FD;
    --bg-editor: #FFFFFF;
    --bg-canvas: #FFFFFF;
    --bg-track: #EDEFF7;
    --bg-hover: #F3F4FA;
    --bg-overlay: rgba(255, 255, 255, 0.97);

    /* Lines */
    --line: #E2E5F0;
    --line-strong: #D3D8E8;

    /* Text */
    --ink: #191B26;
    --ink-2: #585F76;
    --ink-3: #868DA3;

    /* Accent + semantics */
    --accent: #5B5BD6;
    --accent-ink: #FFFFFF;
    --accent-soft: #EDEDFC;
    --accent-glow: rgba(91, 91, 214, .35);
    --focus: #5B5BD6;
    --ok: #37956B;
    --warn: #C2410C;
    --danger: #DC2626;
    --danger-soft: rgba(220, 38, 38, .10);

    --badge-bg: #EDEFF7;
    --badge-ink: #585F76;
    --switch-off: #DADEEC;
    --switch-on: #5B5BD6;
    --switch-knob: #FFFFFF;
    --switch-knob-on: #FFFFFF;

    /* Geometry */
    --r-sm: 7px;
    --r-md: 9px;
    --r-lg: 12px;
    --btn-size: 30px;
    --btn-radius: 8px;
    --icon-size: 17px;
    --tb-gap: 3px;
    --tb-pad: 9px 12px;

    /* Shell geometry */
    --h-appbar: 52px;
    --h-statusbar: 28px;
    --w-inspector: 246px;

    /* Elevation */
    --e-1: 0 1px 2px rgba(25, 27, 38, .08);
    --e-2: 0 12px 30px rgba(25, 27, 38, .12);
    --e-frame: 0 1px 2px rgba(25, 27, 38, .04), 0 10px 28px rgba(25, 27, 38, .05);

    /* Motion */
    --t-fast: 130ms cubic-bezier(.2, 0, .2, 1);
    --t-slow: 240ms cubic-bezier(.2, 0, .2, 1);

    /* Icons */
    --i-chevron: url('images/ui/alt-arrow-right.svg');
    --i-chevron-down: url('images/ui/alt-arrow-down.svg');
    --i-check: url('images/ui/check-circle.svg');
}

body.dark {
    --bg-page: #0D0F16;
    --bg-chrome: #151824;
    --bg-toolbar: #151824;
    --bg-panel: #12141F;
    --bg-statusbar: #12141F;
    --bg-editor: #151824;
    --bg-canvas: #111317;
    --bg-track: #1D2130;
    --bg-hover: #1A1E2B;
    --bg-overlay: rgba(21, 24, 36, 0.97);

    --line: #232838;
    --line-strong: #333A4E;

    --ink: #E8EAF2;
    --ink-2: #9AA1B8;
    --ink-3: #6E7690;

    --accent: #7C7CF0;
    --accent-ink: #12141F;
    --accent-soft: #1E1F3A;
    --accent-glow: rgba(124, 124, 240, .30);
    --focus: #7C7CF0;
    --ok: #4ECB8F;
    --warn: #FB923C;
    --danger: #F87171;
    --danger-soft: rgba(248, 113, 113, .15);

    --badge-bg: #1D2130;
    --badge-ink: #9AA1B8;
    --switch-off: #2A3042;
    --switch-on: #7C7CF0;
    --switch-knob-on: #12141F;

    --e-1: 0 1px 2px rgba(0, 0, 0, .5);
    --e-2: 0 12px 30px rgba(0, 0, 0, .55);
    --e-frame: 0 1px 2px rgba(0, 0, 0, .3), 0 10px 28px rgba(0, 0, 0, .35);
}

/* ============================================================================
 * Page layout
 * ==========================================================================*/
html, body {
    height: 100%;
    overflow: hidden;
}

body {
    margin: 0;
    padding: 0;
    font-family: var(--font-ui);
    font-size: 13px;
    line-height: 1.5;
    color: var(--ink);
    background-color: var(--bg-page);
    -webkit-font-smoothing: antialiased;
    transition: background-color var(--t-slow), color var(--t-slow);
}

/* The shell owns the whole viewport: app bar / content row / status bar.
   There is no page around it — a tool that fills the window reads as a tool,
   not as a widget embedded in a document. */
#status {
    position: fixed;
    top: calc(var(--h-appbar) + 12px);
    right: 14px;
    z-index: 90;
    padding: 5px 12px;
    font-size: 12px;
    color: var(--ink-3);
    pointer-events: none;
    opacity: 0;
    transition: opacity 0.4s ease;
}
#status.visible { opacity: 1; }

/* Errors persist until the next status message (see setError in app.js) */
#status.error {
    font-weight: 500;
    color: var(--danger);
    background: var(--bg-chrome);
    border: 1px solid var(--line);
    border-left: 3px solid var(--danger);
    border-radius: var(--r-sm);
    box-shadow: var(--e-2);
}

/* ============================================================================
 * App shell
 * ==========================================================================*/
.diagram-body {
    display: grid;
    grid-template-rows: var(--h-appbar) 1fr var(--h-statusbar);
    height: 100%;
    background: var(--bg-chrome);
    overflow: hidden;
}

.diagram-body:fullscreen { height: 100vh; width: 100vw; }
.diagram-body:fullscreen #diagram { height: 100% !important; }

/* === App bar =============================================================
   Three zones, so the three things a user is doing stop competing: document
   identity on the left, workspace controls on the right. */
.app-bar {
    position: relative;
    z-index: 40;
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 0 12px;
    background: var(--bg-toolbar);
    border-bottom: 1px solid var(--line);
}

.ab-left, .ab-right {
    display: flex;
    align-items: center;
    gap: 8px;
    min-width: 0;
}
.ab-right { margin-left: auto; }

.ab-div {
    flex-shrink: 0;
    width: 1px;
    height: 22px;
    background: var(--line);
}

.app-mark {
    display: grid;
    place-items: center;
    flex-shrink: 0;
    width: 26px;
    height: 26px;
    border-radius: 8px;
    background: linear-gradient(140deg, var(--accent), #8A6BEA);
    color: #fff;
    box-shadow: 0 2px 6px var(--accent-glow);
}
.app-mark .ic { width: 15px; height: 15px; }

/* The document's name, leftmost, doubling as the switcher trigger. */
.doc-switcher {
    display: flex;
    align-items: center;
    gap: 7px;
    min-width: 0;
    max-width: 340px;
    height: 32px;
    padding: 0 8px 0 9px;
    border: none;
    border-radius: var(--btn-radius);
    background: transparent;
    color: var(--ink);
    font-family: var(--font-display);
    font-size: 13.5px;
    font-weight: 500;
    letter-spacing: -0.01em;
    cursor: pointer;
    transition: background var(--t-fast);
}
.doc-switcher:hover,
.doc-switcher.open { background: var(--bg-hover); }
.doc-switcher.open { background: var(--bg-track); }
.doc-switcher #diagram-title {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.doc-switcher #diagram-title:empty::before {
    content: "Untitled diagram";
    color: var(--ink-3);
}
.doc-switcher .ic { color: var(--ink-3); }

.type-badge:not(:empty) {
    flex-shrink: 0;
    padding: 2px 7px;
    border-radius: 5px;
    background: var(--badge-bg);
    color: var(--badge-ink);
    font-size: 9.5px;
    font-weight: 600;
    letter-spacing: 0.07em;
    text-transform: uppercase;
}

.tb-plain {
    display: flex;
    align-items: center;
    gap: var(--tb-gap);
}

/* === Mode: a segmented control, not a lone icon you can leave on ========= */
.seg {
    display: flex;
    align-items: center;
    gap: 2px;
    padding: 3px;
    border-radius: var(--r-lg);
    background: var(--bg-track);
}
.seg-btn {
    display: flex;
    align-items: center;
    gap: 6px;
    height: 26px;
    padding: 0 11px 0 9px;
    border: none;
    border-radius: var(--r-sm);
    background: transparent;
    color: var(--ink-2);
    font-family: var(--font-ui);
    font-size: 12px;
    font-weight: 500;
    cursor: pointer;
    transition: background var(--t-fast), color var(--t-fast), box-shadow var(--t-fast);
}
.seg-btn .ic { width: 15px; height: 15px; }
.seg-btn:hover { color: var(--ink); }
/* Which half is lit follows body.edit-mode, so the two can never disagree */
body:not(.edit-mode) #btn-view-mode {
    background: var(--bg-chrome);
    color: var(--ink);
    box-shadow: var(--e-1);
}
body.edit-mode #btn-edit-mode {
    background: var(--accent);
    color: var(--accent-ink);
    box-shadow: 0 2px 8px var(--accent-glow);
}

/* A cluster of related controls. The filled track is what communicates the
   grouping — eleven identical buttons in a row communicate nothing. */
.tb-group {
    display: flex;
    align-items: center;
    gap: var(--tb-gap);
    padding: 3px;
    background: var(--bg-track);
    border-radius: var(--r-lg);
}

/* === Icon buttons ========================================================= */
.tb-btn {
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    width: var(--btn-size);
    height: var(--btn-size);
    padding: 0;
    border: none;
    border-radius: var(--btn-radius);
    background: transparent;
    color: var(--ink-2);
    font: inherit;
    cursor: pointer;
    transition: background var(--t-fast), color var(--t-fast),
                box-shadow var(--t-fast), transform var(--t-fast);
}

/* Icon primitive. A mask over currentColor, so one file serves both themes
   and icons can sit inside labelled buttons as well as square ones. */
.ic {
    display: block;
    flex-shrink: 0;
    width: var(--icon-size);
    height: var(--icon-size);
    background: currentColor;
    -webkit-mask: var(--i) center / contain no-repeat;
    mask: var(--i) center / contain no-repeat;
}
.ic-sm { width: 13px; height: 13px; }

/* Hover lifts the button out of its track on a solid face. */
.tb-btn:hover {
    background: var(--bg-chrome);
    color: var(--ink);
    box-shadow: var(--e-1);
}
.tb-btn:active { transform: scale(0.95); }

/* Font picker. A native <select> — the list runs to ~75 names in optgroups,
 * which a custom popover would have to reimplement (keyboard, type-ahead,
 * scroll) for no gain. The wrapper exists solely to own the chevron: a
 * <select> can't carry a ::after, and the shared icon set is drawn in
 * currentColor, so a background-image would arrive black and disappear in
 * dark mode. As a mask on the wrapper it inherits the wrapper's colour and
 * both themes come free. */
.tb-select-wrap {
    position: relative;
    display: flex;
    align-items: center;
    flex-shrink: 0;
    color: var(--ink-2);
}
.tb-select-wrap::after {
    content: "";
    position: absolute;
    right: 9px;
    width: 13px;
    height: 13px;
    background: currentColor;
    -webkit-mask: var(--i-chevron) center / contain no-repeat;
    mask: var(--i-chevron) center / contain no-repeat;
    transform: rotate(90deg);
    pointer-events: none;
}
.tb-select-wrap:hover { color: var(--ink); }

.tb-select {
    width: 100%;
    max-width: 150px;
    height: var(--btn-size);
    padding: 0 26px 0 10px;
    border: 1px solid var(--line);
    border-radius: var(--btn-radius);
    background: var(--bg-track);
    color: inherit;
    font-family: var(--font-ui);
    font-size: 12px;
    font-weight: 500;
    letter-spacing: -0.005em;
    cursor: pointer;
    appearance: none;
    -webkit-appearance: none;
    transition: background-color var(--t-fast), border-color var(--t-fast),
                box-shadow var(--t-fast);
}
.tb-select:hover {
    background-color: var(--bg-chrome);
    border-color: var(--line-strong);
    box-shadow: var(--e-1);
}
.tb-select:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
.tb-select:disabled { cursor: progress; opacity: 0.55; }
/* Native popup list: the OS paints it, so it only honours these two. */
.tb-select option,
.tb-select optgroup { background: var(--bg-chrome); color: var(--ink); }

/* Icon + text variant: grows to fit its label instead of staying square. */
.tb-btn-label {
    width: auto;
    gap: 6px;
    padding: 0 11px 0 9px;
    font-family: var(--font-ui);
    font-size: 12px;
    font-weight: 500;
    letter-spacing: -0.005em;
    white-space: nowrap;
}

.tb-btn.active {
    background: var(--accent);
    color: var(--accent-ink);
    box-shadow: 0 2px 8px var(--accent-glow);
}

.tb-btn:focus-visible,
.test-btn:focus-visible,
.export-menu button:focus-visible,
.toolbar-toggle:focus-within {
    outline: 2px solid var(--focus);
    outline-offset: 2px;
}

/* Icon assignments. One file per icon: the mask inherits currentColor, so
   there is never a light/dark pair. */
.i-mark   { --i: url('images/ui/widget-5.svg'); }
.i-new    { --i: url('images/ui/add-square.svg'); }
.i-eye    { --i: url('images/ui/eye.svg'); }
.i-pen    { --i: url('images/ui/pen-2.svg'); }
.i-undo   { --i: url('images/ui/undo-left.svg'); }
.i-redo   { --i: url('images/ui/undo-right.svg'); }
.i-code   { --i: url('images/ui/code.svg'); }
.i-panel  { --i: url('images/ui/sidebar-minimalistic.svg'); }
.i-export { --i: url('images/ui/download-minimalistic.svg'); }
.i-full   { --i: url('images/ui/full-screen.svg'); }
#btn-fullscreen.is-fullscreen .i-full { --i: url('images/ui/quit-full-screen.svg'); }
.i-theme  { --i: url('images/ui/moon.svg'); }
body.dark .i-theme { --i: url('images/ui/sun-2.svg'); }
.i-down   { --i: var(--i-chevron-down); }
.i-search { --i: url('images/ui/magnifer.svg'); }
.i-warn   { --i: url('images/ui/danger-triangle.svg'); }
/* Corner brackets alone = fill the screen; the same brackets inside a square
   = fit the drawing within this frame. */
.i-fit      { --i: url('images/ui/full-screen-square.svg'); }
.i-zoom-in  { --i: url('images/ui/magnifer-zoom-in.svg'); }
.i-zoom-out { --i: url('images/ui/magnifer-zoom-out.svg'); }
.i-reset    { --i: url('images/ui/restart.svg'); }

.tb-btn:disabled { opacity: 0.32; cursor: default; }
.tb-btn:disabled:hover { background: transparent; color: var(--ink-2); box-shadow: none; }

/* === Export menu ========================================================== */
.export-wrapper { position: relative; }

.export-menu {
    display: none;
    position: absolute;
    top: 100%;
    right: 0;
    margin-top: 8px;
    min-width: 172px;
    padding: 4px;
    background: var(--bg-chrome);
    border: 1px solid var(--line);
    border-radius: var(--r-md);
    box-shadow: var(--e-2);
    z-index: 100;
}
.export-menu.open { display: block; }

.export-menu button {
    display: block;
    width: 100%;
    padding: 7px 10px;
    border: none;
    border-radius: var(--r-sm);
    background: none;
    text-align: left;
    font-family: var(--font-ui);
    font-size: 12.5px;
    color: var(--ink-2);
    white-space: nowrap;
    cursor: pointer;
    transition: background var(--t-fast), color var(--t-fast);
}
.export-menu button:hover {
    background: var(--bg-track);
    color: var(--ink);
}
.export-menu-sep {
    margin: 4px 6px;
    border: none;
    border-top: 1px solid var(--line);
}

/* === Tooltips toggle ====================================================== */
.toolbar-toggle {
    position: relative;
    display: flex;
    align-items: center;
    gap: 7px;
    padding: 0 10px 0 4px;
    font-size: 12px;
    color: var(--ink-2);
    cursor: pointer;
    user-select: none;
    white-space: nowrap;
}

/* The native control stays in the DOM and keeps its own hit area — it is laid
   exactly over the switch and made transparent, rather than shrunk to 1px.
   Anything that clicks #chk-hover directly still lands on the checkbox. */
.toolbar-toggle input[type="checkbox"] {
    position: absolute;
    left: 4px;
    top: 50%;
    transform: translateY(-50%);
    width: 28px;
    height: 16px;
    margin: 0;
    opacity: 0;
    cursor: pointer;
    z-index: 1;
}

.toolbar-toggle .switch {
    position: relative;
    width: 28px;
    height: 16px;
    flex-shrink: 0;
    background: var(--switch-off);
    border-radius: 999px;
    transition: background var(--t-fast);
    pointer-events: none;
}
.toolbar-toggle .switch::after {
    content: "";
    position: absolute;
    top: 2px;
    left: 2px;
    width: 12px;
    height: 12px;
    background: var(--switch-knob);
    border-radius: 50%;
    box-shadow: var(--e-1);
    transition: transform var(--t-fast), background var(--t-fast);
}
.toolbar-toggle input:checked + .switch { background: var(--switch-on); }
.toolbar-toggle input:checked + .switch::after {
    transform: translateX(12px);
    background: var(--switch-knob-on);
}

/* ============================================================================
 * Document switcher
 *
 * The examples used to be 28 pills in three rows costing ~150px of every
 * session. As a menu off the title they are searchable, grouped and free.
 * ==========================================================================*/
.doc-menu {
    display: none;
    position: absolute;
    top: calc(100% - 4px);
    left: 44px;
    z-index: 70;
    width: 376px;
    max-height: min(452px, calc(100vh - var(--h-appbar) - 40px));
    flex-direction: column;
    background: var(--bg-chrome);
    border: 1px solid var(--line);
    border-radius: var(--r-lg);
    box-shadow: var(--e-2);
    overflow: hidden;
}
.doc-menu.open { display: flex; }

.dm-search {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-shrink: 0;
    padding: 11px 13px;
    border-bottom: 1px solid var(--line);
}
.dm-search .ic { width: 15px; height: 15px; color: var(--ink-3); }
.dm-search input {
    flex: 1;
    min-width: 0;
    border: none;
    outline: none;
    background: transparent;
    color: var(--ink);
    font-family: var(--font-ui);
    font-size: 13px;
}
.dm-search input::placeholder { color: var(--ink-3); }

.dm-scroll { overflow-y: auto; padding: 5px; }

.dm-group {
    padding: 10px 9px 5px;
    color: var(--ink-3);
    font-size: 9.5px;
    font-weight: 600;
    letter-spacing: 0.09em;
    text-transform: uppercase;
}

/* .test-btn keeps its class so the example-loading path is untouched; the
   pill styling is simply replaced by a menu row. */
.dm-item, .test-btn {
    display: flex;
    align-items: center;
    gap: 9px;
    width: 100%;
    padding: 7px 9px;
    border: none;
    border-radius: var(--r-sm);
    background: transparent;
    color: var(--ink);
    font-family: var(--font-ui);
    font-size: 12.5px;
    text-align: left;
    cursor: pointer;
    transition: background var(--t-fast), color var(--t-fast);
}
.dm-item:hover, .test-btn:hover { background: var(--bg-hover); }
.dm-item.active, .test-btn.active {
    background: var(--accent-soft);
    color: var(--accent);
    font-weight: 500;
}
/* The tick reserves its column on every row, so labels stay aligned whether
   or not a row is the current document. */
.dm-item::before, .test-btn::before {
    content: "";
    flex-shrink: 0;
    width: 13px;
    height: 13px;
    background: currentColor;
    -webkit-mask: var(--i-check) center / contain no-repeat;
    mask: var(--i-check) center / contain no-repeat;
    opacity: 0;
}
.dm-item.active::before, .test-btn.active::before { opacity: 1; }
.dm-new::before { display: none; }
.dm-hidden { display: none !important; }

.dm-new { color: var(--accent); font-weight: 500; }
.dm-new .ic { width: 15px; height: 15px; }

.dm-empty {
    padding: 22px 14px;
    color: var(--ink-3);
    font-size: 12px;
    text-align: center;
}

/* ============================================================================
 * Content row (editor + diagram + rails)
 * ==========================================================================*/
.diagram-content {
    display: flex;
    flex-direction: row;
    flex: 1;
    min-height: 0;
    overflow: hidden;
}

.diagram-viewport {
    position: relative;
    flex: 1;
    min-width: 0;
    background: var(--bg-canvas);
    overflow: hidden;
}

/* Edit mode says so on the canvas, not just with one lit-up icon. */
body.edit-mode .diagram-viewport::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 8;
    border: 2px solid var(--accent);
    opacity: 0.4;
    pointer-events: none;
}

#diagram {
    height: 100%;
    overflow: auto;
    background: var(--bg-canvas);
}

#diagram svg {
    width: 100%;
    touch-action: none;
    user-select: none;
    animation: diagramFadeIn 0.5s ease-in-out;
}

/* === Zoom cluster =========================================================
   On the canvas, bottom-right — next to the thing it zooms, which is where
   every canvas tool puts it and nowhere near the legend toggle. */
.zoomer {
    position: absolute;
    right: 16px;
    bottom: 16px;
    z-index: 12;
    display: flex;
    align-items: center;
    gap: 2px;
    padding: 4px;
    background: var(--bg-overlay);
    border: 1px solid var(--line);
    border-radius: 999px;
    box-shadow: var(--e-2);
    backdrop-filter: blur(8px);
}
.zoomer .tb-btn { width: 28px; height: 28px; border-radius: 999px; }
.zoom-val {
    min-width: 48px;
    padding: 0 2px;
    border: none;
    background: transparent;
    color: var(--ink-2);
    font-family: var(--font-ui);
    font-size: 11.5px;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    text-align: center;
    cursor: pointer;
}
.zoom-val:hover { color: var(--ink); }
.zoomer .zsep {
    width: 1px;
    height: 16px;
    margin: 0 3px;
    background: var(--line);
}

@keyframes diagramFadeIn {
    from { opacity: 0; transform: scale(0.99); }
    to   { opacity: 1; transform: scale(1); }
}

/* === SVG fills the page owns ==============================================
   The canvas colour has to match the page surface behind the drawing (it is
   also the knock-out behind edge labels). Node, edge and boundary colours
   belong to the diagram themes in JS, not here. */
.elk-canvas-bg { fill: var(--bg-canvas); }
.elk-boundary-bg { fill: #f0f2f5; }
body.dark .elk-boundary-bg { fill: #222244; }
body.dark .elk-boundary-title-text { fill: #ffffff !important; }

/* === Tooltippable elements (view mode) === */
[data-tooltip] { cursor: pointer; }

.elk-hover-enabled .elk-edge-line,
.elk-hover-enabled [data-rel-label],
.elk-hover-enabled .elk-node {
    cursor: pointer;
}

/* === Tooltip === */
#elk-rel-tooltip {
    position: fixed;
    pointer-events: none;
    opacity: 0;
    transition: opacity 0.15s;
    padding: 6px 12px;
    border-radius: var(--r-sm);
    font-size: 12.5px;
    font-weight: 500;
    white-space: nowrap;
    z-index: 9999;
    box-shadow: var(--e-2);
}

/* ============================================================================
 * Editor panel (live editor split-pane)
 * ==========================================================================*/
.editor-panel {
    display: none;
    width: 40%;
    min-width: 280px;
    max-width: 50%;
    flex-shrink: 0;
    position: relative;
    background: var(--bg-editor);
    border-right: 1px solid var(--line);
}

.editor-panel.open {
    display: flex;
    flex-direction: column;
}

.editor-resize-handle {
    position: absolute;
    top: 0;
    right: -3px;
    width: 6px;
    height: 100%;
    cursor: col-resize;
    z-index: 10;
    transition: background var(--t-fast);
}
.editor-resize-handle:hover,
.editor-resize-handle.active {
    background: var(--accent-glow);
}

.editor-panel textarea {
    flex: 1;
    resize: none;
    border: none;
    outline: none;
    padding: 14px 16px;
    font-family: var(--font-mono);
    font-size: 12.5px;
    line-height: 1.65;
    color: var(--ink);
    background: transparent;
    caret-color: var(--accent);
    tab-size: 4;
}

.editor-panel textarea::placeholder { color: var(--ink-3); }

/* ============================================================================
 * Status bar
 *
 * Absorbs the editor's own status strip — the parsed type and problem count
 * are facts about the document, not about the editor pane.
 * ==========================================================================*/
.status-bar {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 0 12px;
    background: var(--bg-statusbar);
    border-top: 1px solid var(--line);
    color: var(--ink-3);
    font-size: 11.5px;
}
.status-bar .sb-right {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-left: auto;
}
.status-bar .tb-select {
    height: 22px;
    padding: 0 24px 0 8px;
    border-color: transparent;
    background: transparent;
    font-size: 11.5px;
}
.status-bar .tb-select-wrap::after { right: 7px; width: 11px; height: 11px; }

/* The parsed type is a fact about the document — give it a real badge. */
#editor-type-badge:not(:empty) {
    padding: 1px 7px;
    font-family: var(--font-mono);
    font-size: 10px;
    font-weight: 500;
    letter-spacing: 0.03em;
    text-transform: uppercase;
    color: var(--badge-ink);
    background: var(--badge-bg);
    border-radius: 5px;
}

/* ============================================================================
 * Inspector (legend + problems, one column with tabs)
 *
 * Two panels that each reserved their own width — and left a blank strip when
 * empty — become one column that is either useful or closed.
 * ==========================================================================*/
.inspector {
    display: none;
    flex-direction: column;
    flex-shrink: 0;
    width: var(--w-inspector);
    background: var(--bg-panel);
    border-left: 1px solid var(--line);
}
.inspector.open { display: flex; }

.insp-tabs {
    display: flex;
    gap: 2px;
    flex-shrink: 0;
    padding: 6px 6px 0;
    border-bottom: 1px solid var(--line);
}
.insp-tab {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 7px 11px 8px;
    border: none;
    border-bottom: 2px solid transparent;
    background: transparent;
    color: var(--ink-3);
    font-family: var(--font-ui);
    font-size: 11.5px;
    font-weight: 600;
    letter-spacing: 0.03em;
    cursor: pointer;
    transition: color var(--t-fast), border-color var(--t-fast);
}
.insp-tab:hover { color: var(--ink-2); }
.insp-tab.active { color: var(--ink); border-bottom-color: var(--accent); }

#problems-count:not(:empty) {
    min-width: 16px;
    padding: 0 4px;
    border-radius: 8px;
    background: var(--danger);
    color: #fff;
    font-size: 9.5px;
    font-weight: 600;
    line-height: 15px;
    text-align: center;
}

.insp-body { flex: 1; min-height: 0; overflow-y: auto; }
.insp-pane { display: none; }
.insp-pane.active { display: block; }
.insp-pane.collapsed { display: none; }

/* Nothing to show is a message, not a blank column. */
.insp-empty {
    padding: 26px 16px;
    color: var(--ink-3);
    font-size: 12px;
    line-height: 1.6;
    text-align: center;
}

.elk-legend {
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: 12px;
    background: var(--bg-panel);
    box-sizing: border-box;
}

.elk-legend-heading {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 8px;
    padding: 0 6px;
    font-size: 10.5px;
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--ink-3);
}

.elk-legend-item {
    display: flex;
    align-items: center;
    gap: 9px;
    padding: 5px 6px;
    font-size: 12.5px;
    color: var(--ink-2);
    border-radius: var(--r-sm);
    cursor: pointer;
    transition: opacity var(--t-fast), transform var(--t-fast),
                background var(--t-fast), color var(--t-fast);
    user-select: none;
}
.elk-legend-item:hover {
    background: var(--bg-hover);
    color: var(--ink);
}

.elk-legend-swatch {
    display: inline-block;
    width: 18px;
    height: 3px;
    border-radius: 2px;
    flex-shrink: 0;
}

.elk-legend-text { color: inherit; }

.elk-legend-remove { margin-left: auto; }

/* === Selected Components panel === */
.elk-selected-nodes {
    padding: 12px;
    background: var(--bg-panel);
    border-bottom: 1px solid var(--line);
}

.elk-selected-heading {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 8px;
    padding: 0 6px;
    font-size: 10.5px;
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--ink-3);
}

.elk-selected-clear {
    border: none;
    background: none;
    color: var(--danger);
    font-family: var(--font-ui);
    font-size: 11px;
    font-weight: 500;
    letter-spacing: 0;
    text-transform: none;
    cursor: pointer;
    padding: 2px 8px;
    border-radius: var(--r-sm);
    transition: background var(--t-fast);
}
.elk-selected-clear:hover { background: var(--danger-soft); }

.elk-selected-list {
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.elk-selected-node-item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 4px 6px;
    font-size: 12.5px;
    color: var(--ink-2);
    border-radius: var(--r-sm);
}

.elk-selected-node-name {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    min-width: 0;
}

.elk-selected-remove {
    flex-shrink: 0;
    border: none;
    background: none;
    color: var(--ink-3);
    font-size: 16px;
    line-height: 1;
    cursor: pointer;
    padding: 0 4px;
    border-radius: var(--r-sm);
    transition: color var(--t-fast), background var(--t-fast);
}
.elk-selected-remove:hover {
    color: var(--danger);
    background: var(--danger-soft);
}

/* ============================================================================
 * Problems panel (syntax diagnostics)
 * ==========================================================================*/
/* A pane inside the inspector now; visibility is the tab's business.
   `.collapsed` is still set by ElkProblems when the document is clean. */
#problems-panel { font-size: 12.5px; }

.problems-header {
    padding: 12px 12px 8px;
    font-size: 10.5px;
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--ink-3);
    border-bottom: 1px solid var(--line);
}

.problem-item {
    padding: 8px 12px;
    cursor: pointer;
    border-bottom: 1px solid var(--line);
    transition: background var(--t-fast);
}
.problem-item:hover { background: var(--bg-hover); }

.problem-item .problem-line {
    font-weight: 600;
    color: var(--warn);
}
.problem-item.severity-error .problem-line { color: var(--danger); }

.problem-item .problem-message { color: var(--ink-2); }

.problem-item .problem-text {
    margin-top: 3px;
    font-family: var(--font-mono);
    font-size: 11.5px;
    color: var(--ink-3);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Flash highlight over the editor line a problem points at */
#editor-line-flash {
    position: absolute;
    left: 0;
    right: 0;
    pointer-events: none;
    opacity: 0;
    background: var(--accent-glow);
}
#editor-line-flash.flashing { animation: lineFlash 1.2s ease-out; }
@keyframes lineFlash {
    from { opacity: 1; }
    to { opacity: 0; }
}

/* Spellchecker-style wavy underlines on problem lines (overlay on the
   editor textarea; geometry computed in elk-problems.js) */
#editor-squiggles {
    position: absolute;
    overflow: hidden;
    pointer-events: none;
    z-index: 2;
}
#editor-squiggles-content {
    position: absolute;
    top: 0;
    left: 0;
}
.editor-squiggle {
    position: absolute;
    height: 4px;
    background: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="8" height="4"><path d="M0 3 Q 2 0 4 3 Q 6 6 8 3" stroke="%23dc2626" fill="none" stroke-width="1.2"/></svg>') repeat-x bottom;
}
body.dark .editor-squiggle {
    background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="8" height="4"><path d="M0 3 Q 2 0 4 3 Q 6 6 8 3" stroke="%23f87171" fill="none" stroke-width="1.2"/></svg>');
}

/* ============================================================================
 * Drop overlay
 * ==========================================================================*/
#drop-overlay {
    position: fixed;
    inset: 0;
    background: var(--accent-glow);
    backdrop-filter: blur(2px);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 10000;
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.2s;
}
#drop-overlay.visible {
    opacity: 1;
    pointer-events: auto;
}

.drop-message {
    padding: 36px 56px;
    border: 2px dashed var(--accent);
    border-radius: var(--r-lg);
    background: var(--bg-overlay);
    color: var(--ink);
    font-size: 18px;
    font-weight: 500;
    box-shadow: var(--e-2);
}

/* ============================================================================
 * Edit mode
 * ==========================================================================*/
/* Cursor follows the gesture, not the mode. Where a click edits text the
 * caret is honest; where a click only selects it is a lie, so those get the
 * pointer. On `svg.elk-structural` (types with parser.edit) the first click
 * selects and the second edits — hence pointer, then caret once selected. */
.edit-mode [data-field] { cursor: text !important; }
.edit-mode [data-tooltip] { cursor: text !important; }
.edit-mode .elk-node { cursor: text !important; }
.edit-mode .elk-node * { cursor: text !important; }
.edit-mode .elk-boundary-title { cursor: text !important; }
.edit-mode .elk-boundary-title * { cursor: text !important; }
.edit-mode .elk-edge-label-text[data-field] { cursor: text !important; }
.edit-mode .elk-edge-label-text:not([data-field]) { cursor: not-allowed !important; }

.edit-mode svg.elk-structural .elk-node,
.edit-mode svg.elk-structural .elk-node *,
.edit-mode svg.elk-structural path[data-source][data-target],
.edit-mode svg.elk-structural line[data-source][data-target] { cursor: pointer !important; }
.edit-mode svg.elk-structural .elk-node.elk-selected,
.edit-mode svg.elk-structural .elk-node.elk-selected *,
.edit-mode svg.elk-structural [data-source][data-target].elk-selected { cursor: text !important; }
.edit-mode .elk-node:hover { filter: brightness(1.1); }

.elk-inline-input {
    width: 100%;
    height: 100%;
    box-sizing: border-box;
    padding: 0 4px;
    border: 2px solid var(--accent);
    border-radius: var(--r-sm);
    outline: none;
    color: var(--ink);
    background: var(--bg-overlay);
}

/* ============================================================================
 * Visual builder: undo toast + edit flash
 * ==========================================================================*/
.elk-toast {
    position: fixed;
    bottom: 24px;
    left: 50%;
    transform: translateX(-50%) translateY(8px);
    padding: 9px 18px;
    background: var(--ink);
    color: var(--bg-chrome);
    border-radius: var(--r-md);
    box-shadow: var(--e-2);
    font-size: 12.5px;
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.2s, transform 0.2s;
    z-index: 3000;
}
.elk-toast.visible {
    opacity: 1;
    transform: translateX(-50%) translateY(0);
}

/* Attention flash on the element a visual edit just created/changed
   (the viewport is never recentred — this is what draws the eye). */
@keyframes elkEditFlash {
    0%, 55% { filter: drop-shadow(0 0 6px rgba(91, 91, 214, 0.95)); }
    100%    { filter: none; }
}
.elk-edit-flash { animation: elkEditFlash 1.2s ease-out; }
body.dark .elk-edit-flash { animation-name: elkEditFlashDark; }
@keyframes elkEditFlashDark {
    0%, 55% { filter: drop-shadow(0 0 7px rgba(124, 124, 240, 0.95)); }
    100%    { filter: none; }
}

/* === Selection ring (edit mode) ===========================================
   CSS class rules override SVG presentation attributes, so no !important. */
.edit-mode g.elk-node.elk-selected {
    filter: drop-shadow(0 0 3px var(--accent-glow));
}
.edit-mode g.elk-node.elk-selected > :first-child {
    stroke: var(--accent);
    stroke-width: 2.5px;
}
.edit-mode path[data-source].elk-selected:not(.elk-hit-area),
.edit-mode line[data-source].elk-selected:not(.elk-hit-area) {
    stroke: var(--accent);
    stroke-width: 3.5px;
}
/* Inline arrowheads / cardinality glyphs (custom edge renderers) join the
   selection colour; marker-based arrowheads use the selection markers. */
.edit-mode polygon[data-source].elk-selected {
    fill: var(--accent);
    stroke: var(--accent);
}
.edit-mode circle[data-source].elk-selected {
    stroke: var(--accent);
}
.elk-sel-arrow-head { fill: var(--accent); }
/* Canvas-coloured border inside the selection markers: masks the thicker
   selected line where it would poke past the arrowhead. */
.elk-sel-arrow-mask {
    fill: none;
    stroke: var(--bg-canvas);
}

/* === Shape palette (edit mode, types with addNode capabilities) ============
   The strip floats over the canvas: only the buttons take pointer events, so
   nodes underneath the padding/background stay clickable. */
/* Vertical, hugging the canvas edge — a horizontal bar at top-left sat on
   top of the diagram's own top-left content. */
#elk-shape-palette {
    position: absolute;
    top: 50%;
    left: 14px;
    transform: translateY(-50%);
    display: none;
    flex-direction: column;
    gap: 2px;
    max-height: calc(100% - 28px);
    padding: 5px;
    overflow-y: auto;
    background: var(--bg-overlay);
    border: 1px solid var(--line);
    border-radius: var(--r-lg);
    box-shadow: var(--e-2);
    backdrop-filter: blur(8px);
    z-index: 50;
    pointer-events: none;
}
body.edit-mode #elk-shape-palette.available { display: flex; }

.elk-shape-btn {
    width: 34px;
    height: 26px;
    padding: 2px;
    border: none;
    border-radius: var(--btn-radius);
    background: none;
    color: var(--ink-2);
    font-size: 10px;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    pointer-events: auto;
    transition: background var(--t-fast), color var(--t-fast),
                box-shadow var(--t-fast);
}
.elk-shape-btn svg {
    width: 24px;
    height: 16px;
    stroke: currentColor;
    fill: none;
    stroke-width: 1.5;
}
.elk-shape-btn:hover {
    background: var(--bg-track);
    color: var(--ink);
}
.elk-shape-btn.armed {
    background: var(--accent);
    color: var(--accent-ink);
    box-shadow: 0 2px 8px var(--accent-glow);
}
.elk-shape-btn.current {
    background: var(--accent-soft);
    color: var(--accent);
    cursor: default;
}

body.palette-armed .diagram-viewport { cursor: crosshair; }

/* Retype chooser (floats next to the selected node; shares .elk-shape-btn) */
#elk-retype-chooser {
    position: absolute;
    display: none;
    gap: var(--tb-gap);
    padding: 4px;
    background: var(--bg-overlay);
    border: 1px solid var(--line);
    border-radius: var(--r-lg);
    box-shadow: var(--e-2);
    z-index: 60;
}

/* === Drag-to-connect overlay line + drop-target glow === */
#elk-drag-overlay {
    position: fixed;
    inset: 0;
    width: 100%;
    height: 100%;
    pointer-events: none;
    z-index: 2500;
    display: none;
}
.edit-mode g.elk-node.elk-drop-target {
    filter: drop-shadow(0 0 5px var(--accent-glow));
}
.edit-mode g.elk-node.elk-drop-target > :first-child {
    stroke: var(--accent);
    stroke-width: 2.5px;
}

/* ============================================================================
 * Icon picker (caret-anchored, see elk-icon-picker.js)
 * ==========================================================================*/
#icon-picker {
    position: absolute;
    display: none;
    flex-direction: column;
    z-index: 3;
    width: 320px;
    max-height: 280px;
    background: var(--bg-chrome);
    border: 1px solid var(--line);
    border-radius: var(--r-md);
    box-shadow: var(--e-2);
    font-family: var(--font-mono);
    font-size: 12px;
    color: var(--ink);
}
#icon-picker-search {
    flex-shrink: 0;
    margin: 6px;
    padding: 6px 9px;
    border: 1px solid var(--line);
    border-radius: var(--r-sm);
    background: var(--bg-page);
    color: var(--ink);
    font-family: inherit;
    font-size: 12px;
    outline: none;
    transition: border-color var(--t-fast);
}
#icon-picker-search:focus { border-color: var(--accent); }
#icon-picker-list { overflow-y: auto; padding: 0 4px 4px; }

.icon-picker-item {
    display: flex;
    align-items: center;
    gap: 7px;
    padding: 4px 6px;
    border-radius: var(--r-sm);
    cursor: pointer;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.icon-picker-item img {
    width: 16px;
    height: 16px;
    flex-shrink: 0;
}
.icon-picker-item.selected,
.icon-picker-item:hover {
    background: var(--accent-soft);
    color: var(--accent);
}
.icon-picker-builtin {
    width: 16px;
    text-align: center;
    color: var(--ink-3);
    flex-shrink: 0;
}
.icon-picker-empty {
    padding: 8px 10px;
    color: var(--ink-3);
    font-style: italic;
}

/* ==========================================================================*/
@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        transition-duration: 0.01ms !important;
        animation-duration: 0.01ms !important;
    }
}
