/*
    Every colour in this file goes through a token, so the whole application — the site chrome and
    the designer alike — can be re-skinned by redefining this block and nothing else.

    Three states, in this order, and the order matters:

      :root                                     the light palette, always defined
      @media (prefers-color-scheme: dark)       what someone gets before they ever choose
      :root[data-theme="dark"]                  what they get once they have

    The media query is guarded with :not([data-theme="light"]) so that choosing light explicitly
    still wins on a machine set to dark. A colour defined ONLY inside the media query would be
    missing for anyone who picks light on a dark machine, which is why the light palette below is
    complete on its own.
*/
:root {
    /* What palette the browser itself should use for everything this file cannot reach: the inside
       of an open <select>, scrollbars, focus rings, the caret, and the default colours of any
       control left unstyled. Without it all of that is drawn from the light palette however dark
       the tokens below are — a white scrollbar down the side of a dark panel. */
    color-scheme: light;

    /* surfaces */
    --bg: #f6f7f9;
    --panel: #ffffff;
    --canvas: #fbfbfd;
    --surface-alt: #fafbfc;
    --hover: #f0f2f5;
    --strip: #eceef1;
    --strip-hover: #e0e4e9;
    --code-bg: #eef0f4;
    --row-alt: #fcfdff;
    --row-border: #eef0f3;

    /* text */
    --text: #1f2430;
    --muted: #6b7280;
    --disabled: #a8afba;
    --on-accent: #ffffff;

    /* lines */
    --border: #d8dce3;

    /* accent */
    --accent: #2563eb;
    /* The brand colour: the ember at the centre of the mark. Brand only, never a state. */
    --ember: #dd5f1a;
    --accent-soft: #eff4ff;

    /* states */
    --danger: #b42318;
    --danger-soft: #fef3f2;
    --danger-border: #e6b0aa;
    --error-bg: #ffe8e8;
    --ok: #2e7d32;
    --ok-soft: #f1f8f2;
    --ok-border: #a5d6a7;
    --warn-soft: #fffaeb;
    --warn-border: #f5c26b;
    --warn-text: #8a6100;

    /* a new object, before it is kept */
    --new-bg: #fdf1df;
    --new-border: #d98324;
    --new-stroke: #f0a94c;

    /* the diagram */
    --node-table-fill: #e8edf6;
    --node-table-stroke: #aeb8c7;
    --node-view-fill: #dff2e4;
    --node-view-stroke: #8fbf9f;
    --node-proc-fill: #f3e6f8;
    --node-proc-stroke: #bf9fcf;
    --node-fn-fill: #fff3d9;
    --node-fn-stroke: #d9b877;
    --node-rows: #ffffff;
    --node-selected-meta: #dbe6ff;
    --edge: #c3cad4;
    --edge-dim: #dde2e8;
    --arrow: #98a3b3;
    --notation: #7c8798;
    --handle-fill: #ffffff;
    --handle-stroke: #b6bfcc;

    /* overlays */
    --scrim: rgba(20, 24, 33, 0.35);
    --scrim-strong: rgba(20, 24, 33, 0.45);
    --shadow: rgba(20, 24, 33, 0.25);
    --shadow-soft: rgba(0, 0, 0, .18);

    --mono: ui-monospace, "Cascadia Mono", Consolas, monospace;

    /* Border for the tinted callout on the site pages. */
    --accent-soft-border: #cfdcfa;
}

/*
    The dark palette. Node fills are deep and desaturated rather than the light hues darkened:
    a diagram is read by the difference between table, view, procedure and function, so those four
    have to stay clearly distinct from each other at low brightness, not merely dark.
*/
@media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) {
        color-scheme: dark;

        --bg: #14181f;
        --panel: #1b2029;
        --canvas: #11151b;
        --surface-alt: #1f2530;
        --hover: #262d38;
        --strip: #1f2530;
        --strip-hover: #2b323e;
        --code-bg: #242b36;
        --row-alt: #1f2530;
        --row-border: #2b323e;

        --text: #e5e9f0;
        --muted: #9aa4b4;
        --disabled: #5c6572;
        --on-accent: #ffffff;

        --border: #333c49;

        --accent: #5b8def;
        --ember: #f07a35;
        --accent-soft: #1d2942;

        --danger: #ff6b5e;
        --danger-soft: #3a1d1b;
        --danger-border: #7d3a33;
        --error-bg: #3a1d1b;
        --ok: #6cc47a;
        --ok-soft: #17301c;
        --ok-border: #2f5c37;
        --warn-soft: #33280f;
        --warn-border: #7a5f28;
        --warn-text: #e0b458;

        --new-bg: #3a2c16;
        --new-border: #d98324;
        --new-stroke: #f0a94c;

        --node-table-fill: #24334d;
        --node-table-stroke: #4a5b78;
        --node-view-fill: #1d3a2a;
        --node-view-stroke: #43704f;
        --node-proc-fill: #33244a;
        --node-proc-stroke: #6b4f8a;
        --node-fn-fill: #3d3117;
        --node-fn-stroke: #7d6634;
        --node-rows: #1b2029;
        --node-selected-meta: #26375c;
        --edge: #46505f;
        --edge-dim: #2b323e;
        --arrow: #6d7788;
        --notation: #8b96a8;
        --handle-fill: #1b2029;
        --handle-stroke: #4a5464;

        --scrim: rgba(0, 0, 0, 0.55);
        --scrim-strong: rgba(0, 0, 0, 0.7);
        --shadow: rgba(0, 0, 0, 0.6);
        --shadow-soft: rgba(0, 0, 0, 0.5);
        --accent-soft-border: #2f3f63;
    }
}

/* An explicit choice, which must beat the machine's setting in both directions. */
:root[data-theme="dark"] {
    color-scheme: dark;

    --bg: #14181f;
    --panel: #1b2029;
    --canvas: #11151b;
    --surface-alt: #1f2530;
    --hover: #262d38;
    --strip: #1f2530;
    --strip-hover: #2b323e;
    --code-bg: #242b36;
    --row-alt: #1f2530;
    --row-border: #2b323e;

    --text: #e5e9f0;
    --muted: #9aa4b4;
    --disabled: #5c6572;
    --on-accent: #ffffff;

    --border: #333c49;

    --accent: #5b8def;
    --ember: #f07a35;
    --accent-soft: #1d2942;

    --danger: #ff6b5e;
    --danger-soft: #3a1d1b;
    --danger-border: #7d3a33;
    --error-bg: #3a1d1b;
    --ok: #6cc47a;
    --ok-soft: #17301c;
    --ok-border: #2f5c37;
    --warn-soft: #33280f;
    --warn-border: #7a5f28;
    --warn-text: #e0b458;

    --new-bg: #3a2c16;
    --new-border: #d98324;
    --new-stroke: #f0a94c;

    --node-table-fill: #24334d;
    --node-table-stroke: #4a5b78;
    --node-view-fill: #1d3a2a;
    --node-view-stroke: #43704f;
    --node-proc-fill: #33244a;
    --node-proc-stroke: #6b4f8a;
    --node-fn-fill: #3d3117;
    --node-fn-stroke: #7d6634;
    --node-rows: #1b2029;
    --node-selected-meta: #26375c;
    --edge: #46505f;
    --edge-dim: #2b323e;
    --arrow: #6d7788;
    --notation: #8b96a8;
    --handle-fill: #1b2029;
    --handle-stroke: #4a5464;

    --scrim: rgba(0, 0, 0, 0.55);
    --scrim-strong: rgba(0, 0, 0, 0.7);
    --shadow: rgba(0, 0, 0, 0.6);
    --shadow-soft: rgba(0, 0, 0, 0.5);
    --accent-soft-border: #2f3f63;
}

* { box-sizing: border-box; }

html, body {
    margin: 0;
    height: 100%;
    font-family: "Segoe UI", system-ui, sans-serif;
    font-size: 14px;
    color: var(--text);
    background: var(--bg);
}

/* The project menu is a fixed strip above everything; the page fills what is left. */
body { display: flex; flex-direction: column; }

/* A form control does not inherit its colour from the page — a browser paints it from its own
   palette unless told otherwise. Every control here that was given a colour of its own was fine;
   the ones that were not came out in near-black text, which the dark theme's panels swallowed
   whole. The object list was the worst of it: a thousand table names, each an unstyled button.

   Kept as a bare element selector so it is only a floor: every .btn, .tab and .pane-toggle that
   names its own colour still wins on specificity. */
button, input, select, textarea { color: inherit; }

h1 { font-size: 1.6rem; }
h2 { font-size: 1.15rem; }
h3, h4 { font-size: 1rem; }

a { color: var(--accent); }

code { font-family: var(--mono); background: var(--code-bg); padding: 1px 4px; border-radius: 3px; }

.muted { color: var(--muted); }
.small { font-size: 12px; }

/* ---------- buttons ---------- */

.btn {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 6px 12px;
    border: 1px solid var(--border);
    border-radius: 6px;
    background: var(--panel);
    color: var(--text);
    cursor: pointer;
    text-decoration: none;
    font-size: 13px;
}

.btn:hover { background: var(--hover); }
.btn.primary { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
.btn.primary:hover { filter: brightness(1.08); }
.btn.danger { color: var(--danger); border-color: var(--danger-border); background: var(--danger-soft); }
.btn.subtle { border-style: dashed; color: var(--muted); width: 100%; justify-content: center; margin-top: 6px; }
.btn:disabled { opacity: .5; cursor: not-allowed; }

.btn-icon {
    border: 1px solid var(--border);
    background: var(--panel);
    border-radius: 4px;
    cursor: pointer;
    width: 24px;
    height: 24px;
    line-height: 1;
    padding: 0;
}

.btn-icon:hover { background: var(--hover); }
.btn-icon.danger { color: var(--danger); }

.badge {
    background: var(--panel);
    color: var(--accent);
    border-radius: 10px;
    padding: 0 6px;
    font-size: 11px;
    font-weight: 600;
}

/* ---------- landing ---------- */

.landing { max-width: 860px; margin: 0 auto; padding: 48px 24px; }
.landing .lead { color: var(--muted); font-size: 15px; }
.cards { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; margin-top: 24px; }

.card {
    background: var(--panel);
    border: 1px solid var(--border);
    border-radius: 8px;
    padding: 16px;
}

.card h2 { margin-top: 0; }
.card p { color: var(--muted); }
.card.wide { grid-column: 1 / -1; }

.card-actions { display: flex; align-items: center; gap: 12px; margin-top: 10px; }

.conn {
    width: 100%;
    min-height: 68px;
    font-family: var(--mono);
    font-size: 12px;
    padding: 8px;
    border: 1px solid var(--border);
    border-radius: 6px;
    resize: vertical;
}

.conn-form {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    gap: 10px 14px;
}

.conn-form .field input,
.conn-form .field select {
    padding: 6px 8px;
    border: 1px solid var(--border);
    border-radius: 4px;
    width: 100%;
    font-size: 13px;
}

.conn-options {
    display: flex;
    align-items: center;
    gap: 16px;
    flex-wrap: wrap;
    margin-top: 12px;
    font-size: 13px;
}

.btn.link {
    border: none;
    background: none;
    color: var(--accent);
    padding: 0;
    text-decoration: underline;
    font-size: 13px;
}

.btn.link:hover { background: none; filter: brightness(1.2); }

.btn.small { padding: 3px 8px; font-size: 12px; }

.mono { font-family: var(--mono); word-break: break-all; }

.status { margin-top: 20px; }

.error-box {
    margin-top: 20px;
    background: var(--danger-soft);
    border: 1px solid var(--danger-border);
    border-radius: 6px;
    padding: 12px;
}

.error-box pre { white-space: pre-wrap; margin: 8px 0 0; font-family: var(--mono); font-size: 12px; }

.warn-box {
    background: var(--warn-soft);
    border: 1px solid var(--warn-border);
    border-radius: 6px;
    padding: 12px;
    margin-bottom: 16px;
}

/* ---------- workspace shell ---------- */

/* Fills what the project menu leaves, rather than a fixed 100vh that it would push off-screen. */
.workspace { display: flex; flex-direction: column; flex: 1; min-height: 0; }

.topbar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    padding: 10px 16px;
    background: var(--panel);
    border-bottom: 1px solid var(--border);
}

.topbar-actions { display: flex; gap: 8px; }

.workspace-body { display: flex; flex: 1; min-height: 0; }

.sidebar {
    width: 260px;
    flex-shrink: 0;
    border-right: 1px solid var(--border);
    background: var(--panel);
    display: flex;
    flex-direction: column;
    min-height: 0;
}

/* Folded down to a rail wide enough to read its name and click it open again. */
.sidebar.collapsed { width: 30px; }

/* ---------- project menu ---------- */

.project-menu {
    display: flex;
    align-items: center;
    gap: 4px;
    flex-shrink: 0;
    padding: 0 12px;
    background: var(--strip);
    border-bottom: 1px solid var(--border);
}

.project-menu-brand {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    font-weight: 700;
    margin-right: 12px;
}

/* The Growth Rings mark (BrandMark.razor), coloured from the theme so it follows light and dark. */
.brand-mark { flex: none; display: block; }
.brand-mark-ring { fill: none; stroke: var(--text); }
.brand-mark-node { fill: var(--text); }
.brand-mark-ember { fill: var(--ember); }

.menu-item {
    position: relative;
    padding: 9px 12px;
    border: none;
    background: none;
    cursor: pointer;
    font-size: 13px;
    color: var(--text);
}

.menu-item:hover:not(:disabled) { background: var(--strip-hover); }
.menu-item:disabled { color: var(--disabled); cursor: default; }

/* Open is a <label>, so it cannot use :disabled and is marked by class instead. */
.menu-item.disabled { color: var(--disabled); pointer-events: none; }
.menu-item.accent { color: var(--accent); font-weight: 600; }

/* Open is a file picker wearing a menu item's clothes. */
.menu-item input[type="file"] {
    position: absolute;
    inset: 0;
    opacity: 0;
    width: 100%;
    cursor: pointer;
}

/* Absorbs the free space, so everything after it sits at the right-hand end of the strip in the
   order it is written. The alternative — an auto margin on whichever of them happens to come first
   — splits the space between them the moment a second one appears. */
.menu-spacer { margin-left: auto; }

.menu-source { font-size: 12px; color: var(--muted); }
.menu-notice { margin-left: 12px; font-size: 12px; color: var(--accent); }

/* The theme switch, where the project strip is the only chrome there is. Square, so that the sun
   and the moon swapping places cannot shift the strip around them. */
.menu-theme {
    margin-left: 12px;
    width: 34px;
    text-align: center;
    padding: 9px 0;
    font-size: 14px;
    line-height: 1;
    border-radius: 4px;
}

.menu-theme:hover { background: var(--strip-hover); }

/* A change with no statement behind it — visibly not part of the runnable script. */
.grid.changes tr.manual { background: var(--warn-soft); }

.manual-step { margin-top: 8px; }
.manual-step > summary { cursor: pointer; font-weight: 600; }
.manual-step pre { white-space: pre-wrap; margin: 6px 0 0; }

.confirm-delete {
    margin-top: 10px;
    padding: 10px 12px;
    border: 1px solid var(--danger-border);
    border-radius: 6px;
    background: var(--danger-soft);
    color: var(--danger);
    font-size: 13px;
}

.confirm-delete p { margin: 0 0 8px; }
.confirm-delete p:first-child { font-weight: 600; }
.confirm-actions { display: flex; gap: 8px; }

/* The row for a relationship reached by clicking its line on the diagram. */
.grid tr.revealed > td { background: var(--accent-soft); }

/* Asking whether the script is valid T-SQL, and what came back. */
.syntax-check { display: flex; align-items: center; gap: 10px; margin-top: 8px; }
.syntax-check .small { color: var(--muted); }
.syntax-check .small.ok { color: var(--ok); }
.syntax-check .small.bad { color: var(--danger); font-weight: 600; }

/* The outcome of a check, in a box of its own so a clean result is as visible as a failure. */
.check-result {
    display: flex;
    align-items: baseline;
    gap: 10px;
    margin-top: 8px;
    padding: 7px 10px;
    border-radius: 6px;
    font-size: 13px;
}

.check-result.ok { border: 1px solid var(--ok-border); background: var(--ok-soft); color: var(--ok); }
.check-result.bad { border: 1px solid var(--danger-border); background: var(--danger-soft); color: var(--danger); }
.check-result .small { color: var(--muted); font-weight: 400; }

.script-problems {
    margin: 8px 0 0;
    padding: 8px 10px 8px 26px;
    border: 1px solid var(--danger-border);
    border-radius: 6px;
    background: var(--danger-soft);
    color: var(--danger);
    font-size: 13px;
}

.script-problems li { margin: 2px 0; }

/* The state of a module's diagram links against its script. */
.link-state {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
    margin-top: 8px;
    padding: 8px 10px;
    border: 1px solid var(--border);
    border-radius: 6px;
    color: var(--muted);
}

.link-state.stale {
    border-color: var(--warn-border);
    background: var(--warn-soft);
    color: var(--warn-text);
}

/* ---------- editor sections ---------- */

.editor-section { border-bottom: 1px solid var(--border); }
.editor-section:last-child { border-bottom: none; }

.section-toggle {
    display: flex;
    align-items: center;
    gap: 8px;
    width: 100%;
    padding: 9px 4px;
    border: none;
    background: none;
    cursor: pointer;
    font-size: 13px;
    color: var(--text);
    text-align: left;
}

.section-toggle:hover { background: var(--hover); }
.section-toggle .chevron { width: 12px; color: var(--muted); }
.section-toggle .section-title { font-weight: 600; }

/* The count is the point of the header: an empty category is visible without opening it. */
.section-count {
    min-width: 20px;
    padding: 1px 7px;
    border-radius: 10px;
    background: var(--accent-soft);
    color: var(--accent);
    font-size: 11px;
    font-weight: 600;
    text-align: center;
}

.section-count.empty { background: var(--code-bg); color: var(--muted); }

.section-body { padding: 4px 0 14px; }
.section-body > .editor-header { margin-bottom: 0; }

/* The drag handle beside a column. Faint until the row is hovered, so an expanded box is not
   covered in dots. */
.er-link-handle { fill: var(--handle-fill); stroke: var(--handle-stroke); stroke-width: 1.2; opacity: 0; cursor: crosshair; }
.er-row:hover .er-link-handle { opacity: 1; }
.er-link-handle:hover { stroke: var(--accent); fill: var(--accent-soft); }

/* Only on a pinned box, and only worth noticing once the pointer is on that box. */
.er-unpin { font-size: 12px; fill: var(--notation); pointer-events: none; }
.er-unpin-hit { cursor: pointer; opacity: 0; }
.er-node:hover .er-unpin-hit { opacity: 1; }
.er-unpin-hit:hover .er-unpin { fill: var(--danger); }

.er-link-preview { fill: none; stroke: var(--accent); stroke-width: 2; stroke-dasharray: 5 4; }

/* Two outcomes, told apart on sight. A refusal means nothing was created; a "created" notice
   means the key exists but something about it could not be checked. They used to share one
   style, which left no way to know whether the line on the diagram came from the message. */
.er-link-note {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 8px 12px;
    font-size: 13px;
}

.er-link-note.refused {
    border-bottom: 1px solid var(--danger-border);
    background: var(--danger-soft);
    color: var(--danger);
}

.er-link-note.created {
    border-bottom: 1px solid var(--new-border);
    background: var(--new-bg);
    color: var(--warn-text);
}

/* Crow's foot symbols. Stroked, never filled, so the prongs read as lines. */
.er-notation { fill: none; stroke: var(--notation); stroke-width: 1.4; }
.er-notation-open { fill: var(--panel); stroke: var(--notation); stroke-width: 1.4; }

.er-canvas.has-selection .er-edge:not(.highlighted) + .er-notation { opacity: .3; }

/* ---------- foreign key form ---------- */

.fk-form {
    margin-top: 10px;
    padding: 12px;
    border: 1px solid var(--border);
    border-radius: 6px;
    background: var(--surface-alt);
}

.fk-form .field { margin-bottom: 8px; }
.fk-form .field input, .fk-form .field select { padding: 4px 6px; border: 1px solid var(--border); border-radius: 4px; }

.fk-pair { display: flex; align-items: center; gap: 8px; margin-bottom: 6px; }
.fk-pair select { padding: 4px 6px; border: 1px solid var(--border); border-radius: 4px; }

.fk-actions { display: flex; align-items: flex-end; gap: 12px; margin-top: 10px; }

/* The name, its chevron and its delete button share the summary row. */
.trigger { border-bottom: 1px solid var(--border); }
.trigger:last-of-type { border-bottom: none; }

.trigger > summary {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 7px 4px;
    cursor: pointer;
    list-style: none;
}

/* Both are needed: the pseudo-element for WebKit, list-style for everything else. */
.trigger > summary::-webkit-details-marker { display: none; }

.trigger > summary:hover { background: var(--hover); }
.trigger > summary .grow { flex: 1; }
.trigger > summary .chevron { width: 12px; color: var(--muted); transition: transform .12s ease; }
.trigger[open] > summary .chevron { transform: rotate(90deg); }

.fk-form .check { display: inline-flex; align-items: center; gap: 6px; font-size: 13px; }
.fk-form .check input { margin: 0; }

.fk-error { color: var(--danger); font-size: 12px; margin: 8px 0 0; }
.fk-warning { color: var(--warn-text); font-size: 12px; margin: 8px 0 0; }

/* ---------- busy overlay ---------- */

/* Above the modal, because a refresh runs from inside one. */
.busy-overlay {
    position: fixed;
    inset: 0;
    z-index: 60;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--scrim);
    cursor: progress;
}

.busy-card {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 16px 22px;
    border-radius: 8px;
    background: var(--panel);
    box-shadow: 0 12px 40px var(--shadow);
    font-size: 14px;
}

.busy-spinner {
    width: 18px;
    height: 18px;
    flex-shrink: 0;
    border: 2px solid var(--border);
    border-top-color: var(--accent);
    border-radius: 50%;
    animation: busy-spin 0.7s linear infinite;
}

@keyframes busy-spin { to { transform: rotate(360deg); } }

/* A refresh that could not take everything says so until dismissed. */
.conflict-bar {
    flex-shrink: 0;
    padding: 10px 16px;
    border-bottom: 1px solid var(--warn-border);
    background: var(--warn-soft);
    font-size: 13px;
}

.conflict-bar ul { margin: 6px 0; padding-left: 20px; }
.conflict-bar li { margin-bottom: 2px; }

/* ---------- modal ---------- */

.modal-backdrop { position: fixed; inset: 0; background: var(--scrim-strong); z-index: 40; }

.modal {
    position: fixed;
    z-index: 41;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: min(560px, calc(100vw - 32px));
    max-height: calc(100vh - 64px);
    overflow: auto;
    padding: 20px;
    border-radius: 8px;
    background: var(--panel);
    box-shadow: 0 12px 40px var(--shadow);
}

.modal h2 { margin-top: 0; }
.modal .field { margin-bottom: 10px; }
.modal-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 16px; }

.change-list { max-height: 320px; overflow: auto; margin: 0; padding-left: 18px; }
.change-list li { margin-bottom: 4px; }
.change-list li.destructive { color: var(--danger); }

/* ---------- collapsible panels ---------- */

/* Shared by the sidebar and the editor: a grey strip so the control is obvious, and a target
   big enough to hit without aiming. */
/* The editor's header strip: the name, the object's actions, and the chevron. A row rather than
   one button because a button may not contain another, and the action must be its own target. */
.pane-header {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-shrink: 0;
    padding-right: 8px;
    background: var(--strip);
    border-bottom: 1px solid var(--border);
}

.pane-header .pane-toggle { border-bottom: none; }
.pane-header .grow { flex: 1; min-width: 0; justify-content: flex-start; }
.pane-header .chevron-only { width: auto; padding: 11px 4px; }
.pane-header .btn { flex-shrink: 0; }

.pane-toggle {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 8px;
    flex-shrink: 0;
    width: 100%;
    padding: 11px 12px;
    border: none;
    background: var(--strip);
    cursor: pointer;
    font-size: 13px;
    font-weight: 600;
    color: var(--text);
}

.sidebar .pane-toggle { border-bottom: 1px solid var(--border); }
.editor-pane .pane-toggle { border-bottom: 1px solid var(--border); }
.pane-toggle:hover { background: var(--strip-hover); }
.pane-toggle .chevron { font-size: 15px; line-height: 1; color: var(--muted); }

/* The collapsed sidebar: its label turned on its side, so the rail stays narrow. */
.pane-rail {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 10px;
    width: 100%;
    height: 100%;
    padding: 11px 0;
    border: none;
    background: var(--strip);
    cursor: pointer;
    font-size: 13px;
    font-weight: 600;
    color: var(--text);
}

.pane-rail:hover { background: var(--strip-hover); }
.pane-rail .chevron { font-size: 15px; line-height: 1; color: var(--muted); }
.pane-rail .rail-label { writing-mode: vertical-rl; letter-spacing: 0.5px; }

.tabs { display: flex; border-bottom: 1px solid var(--border); }

.tab {
    flex: 1;
    padding: 8px 4px;
    border: none;
    background: none;
    cursor: pointer;
    font-size: 12px;
    color: var(--muted);
    border-bottom: 2px solid transparent;
}

.tab.active { color: var(--accent); border-bottom-color: var(--accent); font-weight: 600; }

.search { margin: 8px; padding: 6px 8px; border: 1px solid var(--border); border-radius: 4px; }

.object-list { overflow-y: auto; padding: 0 8px 8px; min-height: 0; }

/* Outside the scrolling list, so it stays reachable however long the list is. */
.list-actions { flex-shrink: 0; padding: 0 8px 8px; }
.list-actions .btn.subtle { margin-top: 0; }

.item {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 8px;
    width: 100%;
    text-align: left;
    padding: 5px 8px;
    border: none;
    background: none;
    border-radius: 4px;
    cursor: pointer;
    font-size: 13px;
}

.item:hover { background: var(--hover); }

.keep-refused { color: var(--danger); font-size: 12px; align-self: center; }

/* Created here and not yet kept. Marked rather than hidden — hiding them left them unreachable. */
.item.unkept { color: var(--warn-text); }
.unkept-dot { color: var(--warn-border); font-size: 9px; margin-right: 5px; }

.btn.warn { border-color: var(--warn-border); background: var(--warn-soft); color: var(--warn-text); }


.item.active { background: var(--accent-soft); color: var(--accent); font-weight: 600; }

.main { flex: 1; display: flex; flex-direction: column; min-width: 0; min-height: 0; }

.diagram-controls {
    display: flex;
    align-items: center;
    gap: 16px;
    padding: 8px 12px;
    border-bottom: 1px solid var(--border);
    background: var(--panel);
    font-size: 13px;
}

/* Wraps the canvas so a dragged object can be dropped onto it.

   overflow: hidden matters when the editor pane is filling the window: this area is squeezed to
   almost nothing, but its own toolbar cannot shrink, so without clipping it spilled downward and
   painted over the editor's header — covering the very buttons that bring the diagram back. Clipped,
   the squeezed diagram simply disappears and the editor header sits clean. */
.diagram-drop { position: relative; flex: 1; display: flex; flex-direction: column; min-height: 0; overflow: hidden; }
.diagram-drop.over { outline: 2px dashed var(--accent); outline-offset: -4px; }

.drop-hint {
    display: none;
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    padding: 8px 16px;
    border-radius: 6px;
    background: var(--accent);
    color: var(--on-accent);
    font-size: 13px;
    pointer-events: none;
}

.diagram-drop.over .drop-hint { display: block; }

.item[draggable="true"] { cursor: grab; }

/* ---------- diagram ---------- */

.er-diagram-wrapper { flex: 1; display: flex; flex-direction: column; min-height: 0; background: var(--canvas); }

.er-toolbar {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 6px 12px;
    border-bottom: 1px solid var(--border);
}

.er-zoom-label { font-size: 12px; color: var(--muted); width: 44px; }
.er-hint { font-size: 12px; color: var(--muted); margin-left: auto; }

.er-canvas { flex: 1; width: 100%; min-height: 0; cursor: grab; touch-action: none; user-select: none; }
.er-canvas:active { cursor: grabbing; }

.er-node { cursor: move; }
.er-node-body { fill: var(--node-table-fill); stroke: var(--node-table-stroke); stroke-width: 1; }
.er-node.view .er-node-body { fill: var(--node-view-fill); stroke: var(--node-view-stroke); }
.er-node.procedure .er-node-body { fill: var(--node-proc-fill); stroke: var(--node-proc-stroke); }
.er-node.function .er-node-body { fill: var(--node-fn-fill); stroke: var(--node-fn-stroke); }
.er-node.selected .er-node-body { fill: var(--accent); stroke: var(--accent); stroke-width: 2; }
.er-node.selected .er-node-title { fill: var(--on-accent); }

/* Created in the designer and not yet saved.

   A dashed outline rather than a fill, and declared after the selected rules so it survives
   them. A new object is selected the instant it is created — the editor opens on it — so a
   fill-based marker would be painted over by the selection at exactly the moment it is
   needed. */
.er-node.is-new .er-node-body {
    fill: var(--new-bg);
    stroke: var(--new-border);
    stroke-width: 2;
    stroke-dasharray: 5 3;
}

.er-node.is-new.selected .er-node-body {
    fill: var(--accent);
    stroke: var(--new-stroke);
    stroke-width: 2;
    stroke-dasharray: 5 3;
}

.er-empty {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    text-align: center;
    color: var(--muted);
    padding: 24px;
}

.er-legend { display: flex; align-items: center; gap: 6px; font-size: 12px; color: var(--muted); margin-left: 12px; }

/* The key is also the control for what gets drawn. */
.legend-item { display: inline-flex; align-items: center; gap: 4px; cursor: pointer; }
.legend-item input { margin: 0; }
.legend-item.off { opacity: .45; }
.legend-item.static { cursor: default; }
.er-legend .swatch { width: 10px; height: 10px; border-radius: 2px; border: 1px solid var(--border); display: inline-block; }
.er-legend .swatch.table { background: var(--node-table-fill); }
.er-legend .swatch.view { background: var(--node-view-fill); }
.er-legend .swatch.proc { background: var(--node-proc-fill); }
.er-legend .swatch.function { background: var(--node-fn-fill); }
.er-legend .swatch.new { background: var(--new-bg); border-color: var(--new-border); border-style: dashed; }

.level-control { display: flex; align-items: center; gap: 8px; }
.level-control select { padding: 4px 8px; border: 1px solid var(--border); border-radius: 4px; }

.warn-inline {
    background: var(--warn-soft);
    border: 1px solid var(--warn-border);
    border-radius: 4px;
    padding: 3px 8px;
    font-size: 12px;
}

.list-count { padding: 2px 8px 6px; }

.er-node-title { font-size: 12px; font-weight: 600; fill: var(--text); }
.er-node-meta { font-size: 9px; fill: var(--muted); }
.er-node.selected .er-node-meta { fill: var(--node-selected-meta); }
.er-node-rule { stroke: var(--node-table-stroke); stroke-width: 1; }

.er-edge-menu-body {
    fill: var(--panel);
    stroke: var(--border);
    filter: drop-shadow(0 2px 6px var(--shadow-soft));
}

.er-edge-menu-title { font-size: 10px; fill: var(--muted); }
.er-edge-menu-item { cursor: pointer; }
.er-edge-menu-item text { font-size: 11px; fill: var(--danger); }
.er-edge-menu-hit { fill: transparent; }
.er-edge-menu-item:hover .er-edge-menu-hit { fill: var(--danger-soft); }

/* Invisible but painted, so it takes clicks — a drawn relationship is far too thin to hit.
   Wide enough to be forgiving without swallowing clicks meant for a nearby box. */
.er-edge-hit {
    fill: none;
    stroke: transparent;
    stroke-width: 12;
    cursor: pointer;
}

.er-toggle-hit { cursor: pointer; }
.er-toggle-target { fill: transparent; }

/* Transparent rather than absent: a fill of "transparent" is still painted, so it takes pointer
   events, where fill:none would not. Same trick as the toggle target above. */
.er-row-target { fill: transparent; }
.er-node-toggle { font-size: 11px; fill: var(--muted); user-select: none; pointer-events: none; }
.er-toggle-hit:hover .er-node-toggle { fill: var(--accent); }
.er-node.selected .er-node-toggle { fill: var(--node-selected-meta); }

/* Column rows sit on a white panel below the coloured header. */
.er-node-rows { fill: var(--node-rows); stroke: none; }
.er-col-name { font-size: 10.5px; fill: var(--text); }
.er-col-name.pk { font-weight: 700; }
.er-col-key { font-size: 8px; fill: var(--accent); font-weight: 700; }
.er-col-type { font-size: 9px; fill: var(--muted); }

.er-edge-label text {
    font-size: 9px;
    fill: var(--accent);
    paint-order: stroke;
    stroke: var(--node-rows);
    stroke-width: 3px;
    stroke-linejoin: round;
}

.er-edge { stroke: var(--edge); stroke-width: 1.25; fill: none; }
.er-edge.highlighted { stroke: var(--accent); stroke-width: 2; }
.er-arrow-head { fill: var(--arrow); }

/* Fade unrelated links once something is selected, so one table's relationships stand out. */
.er-canvas.has-selection .er-edge { stroke: var(--edge-dim); }
.er-canvas.has-selection .er-edge.highlighted { stroke: var(--accent); }

/* The line that was actually clicked: dark and heavy, so it reads as the one being acted on
   rather than merely related to the selection.

   Both selectors are needed. Clicking a line selects the table that owns it, which puts the
   canvas into .has-selection — and that rule is more specific than a bare .er-edge.selected, so
   it won, and the line being pointed at was repainted the palest grey on the diagram at the exact
   moment it mattered most. Declared last as well, so order cannot undo it either. */
.er-edge.selected,
.er-canvas.has-selection .er-edge.selected {
    stroke: var(--text);
    stroke-width: 3;
}

/* ---------- editors ---------- */

.editor-pane {
    height: 40%;
    min-height: 200px;
    display: flex;
    flex-direction: column;
    overflow: hidden;
    border-top: 1px solid var(--border);
    background: var(--panel);
}

.editor-pane.tall { height: 100%; }

/* Folded away, the pane keeps only its title strip so it can be brought back. */
.editor-pane.collapsed { height: auto; min-height: 0; }

.pane-body { flex: 1; min-height: 0; overflow: auto; padding: 12px; display: flex; flex-direction: column; }

/* The module editor fills the height it is given rather than sitting at its natural size, so that
   making the pane taller actually makes the definition box taller. Without this the pane grew but
   the editor kept its content height and left the new room empty below — expanding bought nothing.
   Scoped to the module editor (`.editor.fill`): the table editor is a stack of grids that should
   keep its natural height and let the pane scroll, not stretch a single field. */
.editor.fill { flex: 1; min-height: 0; display: flex; flex-direction: column; }

.editor-header { display: flex; align-items: flex-end; gap: 12px; margin-bottom: 12px; }
.field { display: flex; flex-direction: column; gap: 3px; }
.field.grow { flex: 1; }
.field label { font-size: 11px; color: var(--muted); text-transform: uppercase; }
.field input { padding: 5px 8px; border: 1px solid var(--border); border-radius: 4px; }

.grid { width: 100%; border-collapse: collapse; font-size: 13px; }
.grid th { text-align: left; font-size: 11px; color: var(--muted); text-transform: uppercase; padding: 4px 6px; border-bottom: 1px solid var(--border); }
.grid td { padding: 3px 6px; border-bottom: 1px solid var(--row-border); vertical-align: top; }
.grid tr.is-fk { background: var(--row-alt); }
.grid tr.destructive { background: var(--danger-soft); }

.w-pk { width: 34px; }
.w-type { width: 130px; }
.w-num { width: 70px; }
.w-flag { width: 40px; }
.w-actions { width: 90px; }
.actions { white-space: nowrap; }

.cell { width: 100%; padding: 3px 5px; border: 1px solid transparent; border-radius: 3px; background: transparent; font-size: 13px; }
.cell:hover { border-color: var(--border); }
.cell:focus { border-color: var(--accent); background: var(--panel); outline: none; }
.cell.num { width: 62px; }

.body-label { display: block; font-size: 11px; color: var(--muted); text-transform: uppercase; margin-bottom: 4px; }

.sql-editor {
    width: 100%;

    /* Grow to fill whatever height the pane has, rather than a fixed box: this is the field the
       "fill the window" toggle is for, so it has to take the room that toggle creates. A floor keeps
       it usable when the pane is only at its half height, below which the editor would be a slit.
       The grow only takes effect inside `.editor.fill` (the module editor), whose flex column gives
       this something to grow within; elsewhere the min-height alone applies. */
    flex: 1;
    min-height: 140px;

    font-family: var(--mono);
    font-size: 13px;
    padding: 10px;
    border: 1px solid var(--border);
    border-radius: 6px;
    resize: vertical;
}

/* ---------- migration ---------- */

/* Fill the host and keep the header still: a long migration used to scroll the whole page, taking
   the Back and Export buttons off the top of the screen. The page is now a column with a fixed
   header and a body that scrolls on its own. */
.migration { flex: 1; min-height: 0; display: flex; flex-direction: column; }
.migration .topbar { flex-shrink: 0; }
.migration-body { flex: 1; min-height: 0; overflow: auto; padding: 16px 16px 40px; }

.sql { font-family: var(--mono); font-size: 12px; margin: 0; white-space: pre-wrap; }

.sql.script {
    background: var(--panel);
    border: 1px solid var(--border);
    border-radius: 6px;
    padding: 12px;
    max-height: 460px;
    overflow: auto;
}

.changes td { vertical-align: middle; }

#blazor-error-ui {
    display: none;
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
    background: var(--error-bg);
    border-top: 1px solid var(--danger);
    padding: 10px 16px;
    z-index: 1000;
}
