/* Estimate graph editor (Components/Estimation/GraphEditor.razor). Global rather than scoped because
   the canvas is drawn partly by child components (SvgText, PortGlyph), which a parent's scoped CSS does
   not reach. Every colour is a theme variable (--mud-palette-* or --pk-*), so dark mode needs no rule
   of its own here. */

.ge-root {
    display: grid;
    grid-template-columns: 240px minmax(0, 1fr) 320px;
    gap: 0;
    border: 1px solid var(--pk-line);
    border-radius: 8px;
    background: var(--mud-palette-surface);
    min-height: 520px;
}

.ge-root.ge-readonly {
    grid-template-columns: minmax(0, 1fr) 320px;
}

@media (max-width: 1280px) {
    .ge-root, .ge-root.ge-readonly { grid-template-columns: minmax(0, 1fr); }
    .ge-palette, .ge-inspector { border: 0 !important; border-top: 1px solid var(--pk-line) !important; max-height: none !important; }
    .ge-palette { order: 2; }
    .ge-inspector { order: 3; }
}

.ge-palette {
    padding: 12px;
    border-right: 1px solid var(--pk-line);
    overflow-y: auto;
    max-height: 760px;
}

.ge-palette-heading {
    margin: 14px 0 6px;
    font-size: 11px;
    font-weight: 600;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--mud-palette-text-secondary);
}

.ge-palette-list, .ge-legend, .ge-task-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.ge-palette-item {
    width: 100%;
    min-height: 36px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    padding: 0 10px;
    border: 1px solid var(--pk-line-control);
    border-radius: 6px;
    background: var(--mud-palette-surface);
    color: var(--mud-palette-text-primary);
    font: inherit;
    font-size: 13px;
    text-align: left;
    cursor: pointer;
}

.ge-palette-item:hover:not(:disabled) { background: var(--pk-gold-tint); border-color: var(--pk-gold-tint-border); }
.ge-palette-item:disabled { cursor: not-allowed; opacity: .55; }
.ge-palette-item:focus-visible, .ge-link:focus-visible { outline: 3px solid var(--pk-accent-text); outline-offset: 2px; }

.ge-mono { font-family: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 10px; color: var(--mud-palette-text-secondary); }
.ge-note { margin: 10px 0 0; font-size: 12px; color: var(--mud-palette-text-secondary); }

.ge-legend li { display: flex; align-items: center; gap: 8px; font-size: 11px; color: var(--mud-palette-text-secondary); }

.ge-main { min-width: 0; display: flex; flex-direction: column; }

.ge-toolbar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
    min-height: 44px;
    padding: 6px 12px;
    border-bottom: 1px solid var(--pk-line);
    font-size: 13px;
    color: var(--mud-palette-text-secondary);
}

/* The camera (pan, zoom) is the SVG's viewBox, set by estimate-graph.js, so the canvas never scrolls. */
.ge-canvas {
    overflow: hidden;
    background: var(--pk-graph-canvas);
}

.ge-svg { display: block; width: 100%; height: clamp(360px, 64vh, 640px); user-select: none; -webkit-user-select: none; touch-action: none; }
.ge-background { cursor: grab; }
.ge-svg.ge-dragging, .ge-svg.ge-dragging * { cursor: grabbing !important; }

/* Full screen: the editor covers the window, above the app bar and drawer (MudBlazor 1300) and below
   dialogs (1400). MudBlazor places a popover one above its nearest positioned ancestor, so the
   inspector's dropdowns open above this layer. The canvas takes every row the toolbar leaves. */
.ge-root.ge-fullscreen {
    position: fixed;
    inset: 0;
    z-index: 1350;
    border-radius: 0;
    border: 0;
    min-height: 0;
    height: 100dvh;
    grid-template-rows: minmax(0, 1fr);
}
.ge-fullscreen .ge-palette, .ge-fullscreen .ge-inspector { max-height: none; overflow-y: auto; }
.ge-fullscreen .ge-main { min-height: 0; }
.ge-fullscreen .ge-canvas { flex: 1 1 auto; min-height: 0; position: relative; }
.ge-fullscreen .ge-svg { position: absolute; inset: 0; height: 100%; }
.ge-fullscreen .ge-issues { max-height: 25dvh; overflow-y: auto; }
@media (max-width: 1280px) {
    .ge-root.ge-fullscreen { grid-template-rows: minmax(0, 1fr) auto auto; overflow-y: auto; }
    .ge-fullscreen .ge-main { height: 100dvh; }
}
html.ge-fullscreen-open, html.ge-fullscreen-open body { overflow: hidden; }

.ge-camera { display: inline-flex; align-items: center; gap: 4px; margin-left: auto; }
.ge-camera-hint { font-size: 12px; margin-right: 4px; }
.ge-zoom { min-width: 4ch; text-align: center; font-size: 11px; }
@media (max-width: 720px) { .ge-camera-hint { display: none; } }
.ge-dot { fill: var(--pk-graph-dot); }

/* Wires: a visible 2px stroke and a wide invisible one that takes the click. */
.ge-wire { fill: none; stroke: var(--pk-graph-wire); stroke-width: 2; pointer-events: none; }
.ge-wire-selected { stroke: var(--pk-accent-text); stroke-width: 3; }
.ge-wire-draft { stroke: var(--pk-accent-text); stroke-dasharray: 6 4; }
.ge-wire-hit { fill: none; stroke: transparent; stroke-width: 12; cursor: pointer; }
.ge-readonly .ge-wire-hit { cursor: default; }

/* Nodes */
.ge-node { cursor: default; outline: none; }
/* A node's tone class (ge-tone-*) sets these four; the rules below only read them. */
.ge-tone-calculation { --ge-head: var(--pk-tone-calculation-head); --ge-title: var(--pk-tone-calculation-title); --ge-tag: var(--pk-tone-calculation-tag); --ge-wash: var(--pk-tone-calculation-body); }
.ge-tone-input { --ge-head: var(--pk-tone-input-head); --ge-title: var(--pk-tone-input-title); --ge-tag: var(--pk-tone-input-tag); --ge-wash: var(--pk-tone-input-body); }
.ge-tone-data { --ge-head: var(--pk-tone-data-head); --ge-title: var(--pk-tone-data-title); --ge-tag: var(--pk-tone-data-tag); --ge-wash: var(--pk-tone-data-body); }
.ge-tone-module { --ge-head: var(--pk-tone-module-head); --ge-title: var(--pk-tone-module-title); --ge-tag: var(--pk-tone-module-tag); --ge-wash: var(--pk-tone-module-body); }
.ge-tone-output { --ge-head: var(--pk-tone-output-head); --ge-title: var(--pk-tone-output-title); --ge-tag: var(--pk-tone-output-tag); --ge-wash: var(--pk-tone-output-body); }

.ge-body { fill: var(--ge-wash, var(--mud-palette-surface)); stroke: var(--mud-palette-text-primary); stroke-width: 1; }
/* The header's outline is the divider a white Calculation header needs against its white body. */
.ge-header { fill: var(--ge-head, var(--pk-ink-fill)); stroke: var(--mud-palette-text-primary); stroke-width: 1; }
.ge-svg [data-drag-handle] { cursor: grab; }
.ge-title { fill: var(--ge-title, var(--pk-on-ink)); font-size: 12px; font-weight: 600; }
.ge-kind { fill: var(--ge-tag, var(--pk-graph-kind)); font-family: 'JetBrains Mono', ui-monospace, monospace; font-size: 10px; }

/* Legend swatches and the node library's per-entry mark. */
.ge-swatch { fill: var(--ge-head); stroke: var(--mud-palette-text-primary); stroke-width: 1; }
.ge-palette-item[class*="ge-tone-"] > span:first-child::before {
    content: "";
    display: inline-block;
    width: 10px;
    height: 10px;
    margin-right: 8px;
    border: 1px solid var(--mud-palette-text-primary);
    border-radius: 2px;
    background: var(--ge-head);
    vertical-align: -1px;
}
.ge-legend-inline { flex-direction: row; flex-wrap: wrap; gap: 6px 16px; }
.ge-tone-strip { padding: 8px 12px; border-top: 1px solid var(--pk-line); }
.ge-label { fill: var(--mud-palette-text-primary); font-size: 12px; }
.ge-label-add { fill: var(--pk-accent-text); font-weight: 600; }
.ge-unit { fill: var(--mud-palette-text-secondary); font-family: 'JetBrains Mono', ui-monospace, monospace; font-size: 10px; }
.ge-meta { fill: var(--mud-palette-text-secondary); font-size: 11px; }
.ge-trace { fill: var(--pk-success-text); font-size: 11px; font-weight: 600; }

.ge-node-selected .ge-body { stroke: var(--pk-accent-text); stroke-width: 3; }
.ge-node:focus-visible .ge-body { stroke: var(--pk-accent-text); stroke-width: 3; stroke-dasharray: 5 3; }
.ge-node-error .ge-body { stroke: var(--pk-danger-text); stroke-width: 2; }
.ge-node-warning .ge-body { stroke: var(--pk-status-warn-text); stroke-width: 2; }

.ge-badge circle { fill: var(--pk-danger-fill); }
.ge-node-warning .ge-badge circle { fill: var(--pk-gold); }
.ge-badge text { fill: var(--pk-on-danger); font-size: 11px; font-weight: 700; }
.ge-node-warning .ge-badge text { fill: var(--pk-on-gold); }

/* Ports */
.ge-port { cursor: pointer; }
.ge-readonly .ge-port { cursor: default; }
.ge-port-hit { fill: transparent; }
.ge-svg[data-editable="true"] .ge-port-out { touch-action: none; }
.ge-port-glyph { stroke: var(--mud-palette-text-primary); stroke-width: 2; }
.ge-port-fill-gold { fill: var(--pk-gold); stroke: var(--mud-palette-text-primary); stroke-width: 2; }
.ge-port-fill-ink { fill: var(--pk-ink-fill); stroke: var(--mud-palette-text-primary); stroke-width: 2; }
.ge-port-fill-paper { fill: var(--mud-palette-surface); stroke: var(--mud-palette-text-primary); stroke-width: 2; }
.ge-port-open { fill: var(--mud-palette-surface) !important; }
.ge-port-accepts .ge-port-hit { fill: var(--pk-gold-tint); }
.ge-port-accepts .ge-port-glyph { stroke: var(--pk-accent-text); stroke-width: 3; }
.ge-port-pending .ge-port-glyph { stroke: var(--pk-accent-text); stroke-width: 3; }
.ge-port:hover .ge-port-hit { fill: var(--pk-row-tint); }

/* Inspector and issue list */
.ge-inspector {
    padding: 12px;
    border-left: 1px solid var(--pk-line);
    overflow-y: auto;
    max-height: 760px;
}

.ge-fieldset {
    border: 1px solid var(--pk-line);
    border-radius: 6px;
    padding: 8px 10px 10px;
    margin: 0;
    min-width: 0;
}

.ge-fieldset legend { padding: 0 4px; font-size: 12px; font-weight: 600; color: var(--mud-palette-text-secondary); }
.ge-panel { border: 1px solid var(--pk-line); border-radius: 6px; padding: 8px 10px; }
.ge-task-list li { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.ge-share-row { display: flex; align-items: flex-start; gap: 6px; }
.ge-days { display: flex; flex-wrap: wrap; }

.ge-issues { padding: 8px 12px; border-top: 1px solid var(--pk-line); font-size: 13px; }
.ge-issues ul { margin: 4px 0 0; padding-left: 0; list-style: none; display: flex; flex-direction: column; gap: 4px; }
.ge-issues li { display: flex; gap: 6px; flex-wrap: wrap; align-items: baseline; }
.ge-issue-error .ge-mono { color: var(--pk-danger-text); font-weight: 700; }
.ge-issue-warning .ge-mono { color: var(--pk-status-warn-text); font-weight: 700; }

.ge-link {
    border: 0;
    padding: 0;
    background: none;
    color: var(--pk-accent-text);
    text-decoration: underline;
    cursor: pointer;
    font: inherit;
}

/* Estimate page panels (Pages/Estimates, Components/Estimation) */
.pk-est-panel {
    border: 1px solid var(--pk-line);
    border-radius: 8px;
    background: var(--mud-palette-surface);
    padding: 16px;
    min-width: 0;
}

.pk-est-grid {
    display: grid;
    grid-template-columns: minmax(0, 2fr) minmax(280px, 1fr);
    gap: 16px;
    align-items: start;
}

@media (max-width: 960px) {
    .pk-est-grid { grid-template-columns: minmax(0, 1fr); }
}

/* Side-by-side: the side panel is exactly as tall as the main one and scrolls inside. Its content is taken out
   of the row's height (absolute), so only the main panel sizes the row; a floor keeps a short main panel usable.
   Stacked (narrow), the side panel is its natural height. */
@media (min-width: 961px) {
    .pk-est-grid-match { align-items: stretch; }
    .pk-est-side-scroll { position: relative; min-height: 360px; padding: 0; }
    .pk-est-side-scroll-body { position: absolute; inset: 0; overflow-y: auto; padding: 16px; }
}
.pk-est-side-scroll:focus-visible { outline: 3px solid var(--pk-accent-text); outline-offset: 2px; }

.pk-est-workers { width: 100%; border-collapse: collapse; font-size: 13px; }
.pk-est-workers th, .pk-est-workers td { padding: 4px 8px; border-bottom: 1px solid var(--pk-line-soft); text-align: left; font-weight: 400; }
.pk-est-workers thead th { font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: .04em; color: var(--mud-palette-text-secondary); }
.pk-est-issues { list-style: none; margin: 4px 0 0; padding: 0; display: flex; flex-direction: column; gap: 4px; font-size: 13px; }
.pk-est-line-selected { background: var(--pk-gold-tint); }
.pk-est-header-meta { display: flex; flex-wrap: wrap; gap: 6px 16px; font-size: 13px; color: var(--mud-palette-text-secondary); }

/* Table node column editor (TableColumnsEditor.razor). */
.ge-columns { list-style: none; margin: 8px 0 0; padding: 0; display: flex; flex-direction: column; gap: 10px; }
.ge-column { display: flex; flex-direction: column; gap: 6px; padding: 8px; border: 1px solid var(--pk-line); border-radius: 6px; }
.ge-column-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.ge-column-head h4 { margin: 0; }
.ge-mono-input input { font-family: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; }

/* Line tables in the breakdown (Table nodes). */
.pk-est-report { margin-top: 8px; }
.pk-est-report caption { caption-side: top; text-align: left; font-weight: 600; font-size: 13px; padding: 4px 0; }
.pk-est-report tfoot td { font-weight: 700; border-top: 1px solid var(--pk-line); }
.pk-est-cell-number { text-align: right; font-variant-numeric: tabular-nums; }
.pk-est-cell-error { color: var(--pk-danger-text); font-family: 'JetBrains Mono', ui-monospace, monospace; font-size: 12px; }

/* Canvas context menu (GraphEditor.razor, opened by estimate-graph.js). */
.ge-canvas { position: relative; }
.ge-menu {
    position: absolute;
    z-index: 5;
    min-width: 200px;
    max-width: 280px;
    padding: 4px;
    border: 1px solid var(--pk-line-control);
    border-radius: 6px;
    background: var(--mud-palette-surface);
    box-shadow: 0 6px 18px rgba(0, 0, 0, .18);
    display: flex;
    flex-direction: column;
}
.ge-menu-item {
    display: flex;
    align-items: center;
    gap: 8px;
    min-height: 32px;
    padding: 4px 10px;
    border: 0;
    border-radius: 4px;
    background: none;
    color: var(--mud-palette-text-primary);
    font: inherit;
    font-size: 13px;
    text-align: left;
    text-decoration: none;
    cursor: pointer;
}
.ge-menu-item:hover, .ge-menu-item:focus-visible { background: var(--pk-gold-tint); outline: none; }
.ge-menu-item:focus-visible { box-shadow: inset 0 0 0 2px var(--pk-accent-text); }
.ge-menu-danger { color: var(--pk-danger-text); }
.ge-menu-hint { color: var(--mud-palette-text-secondary); font-size: 11px; margin-left: 4px; }
