﻿/*
 * DraggableGridComponent (Base.Presentation/Editors/DraggableGrid) has no CSS isolation available —
 * this app's host page (Tevarai.Blazor.Server/Pages/_Host.cshtml) leaves the generated
 * "Tevarai.Blazor.Server.styles.css" bundle link commented out, so no *.razor.css file in this
 * codebase is ever loaded. These rules therefore live here instead, as a plain stylesheet linked
 * directly from _Host.cshtml, matching every other Presentation stylesheet's convention.
 */

/*
 * The editor fills whatever the XAF view item gives it rather than hardcoding a pixel height, so the
 * same grid works full-page and inside a sized DashboardViewItem. Host views can override the
 * --draggable-grid-height custom property to pin a specific height.
 */
.draggable-grid {
	display: flex;
	flex-direction: column;
	height: var(--draggable-grid-height, 100%);
	min-height: var(--draggable-grid-min-height, 20rem);
}

/*
 * The grid/detail-pane split (DraggableGridViewModel.ShowDetailPane): a flex row holding the grid at
 * 3 parts and the inline detail pane at 1 part, so the pane opens beside the rows rather than over
 * them. .draggable-grid__body/.draggable-grid__main are always present; .draggable-grid__detail is
 * only rendered while the pane is open, so .draggable-grid__main naturally reclaims the full row
 * when it closes (flex: 1 1 0 with no sibling to share with).
 */
.draggable-grid .draggable-grid__body {
	display: flex;
	flex-direction: row;
	flex: 1 1 auto;
	min-height: 0;
	gap: 1rem;
}

.draggable-grid .draggable-grid__main {
	display: flex;
	flex-direction: column;
	/* 3:2 growth ratio against .draggable-grid__detail's flex: 2 below = 60%/40% of .__body. */
	flex: 3 1 0;
	min-width: 0;
	min-height: 0;
}

.draggable-grid .draggable-grid__detail {
	/* No max-width cap: a fixed cap would fight the 60/40 split on a wide viewport, leaving the
	   pane stuck narrower than its intended 40% share. */
	flex: 2 1 0;
	min-width: 16rem;
	min-height: 0;
	overflow-y: auto;
	overflow-x: hidden;
	border-left: 1px solid rgba(var(--midgrey), 0.25);
	padding-left: 1rem;
}

.draggable-grid .draggable-grid__grid {
	flex: 1 1 auto;
	min-height: 0;
}

/* Signal that rows are draggable only while reordering is actually enabled. */
.draggable-grid .draggable-grid__grid .dxbl-grid-drag-handle {
	cursor: grab;
}

.draggable-grid .draggable-grid__grid .dxbl-grid-drag-handle:active {
	cursor: grabbing;
}

/*
 * No vertical cell borders in this grid — the column separators (most visibly between the frozen-left
 * checkbox/actions pane and the first data column). Row separators (the horizontal border between rows)
 * are left alone; only the left/right rule is widened here. form-ui.css already zeroes every DxGrid's
 * border-left app-wide; this adds border-right inside .draggable-grid only, so it never touches a
 * standard XAF ListView grid elsewhere.
 */
.draggable-grid .draggable-grid__grid .dxbl-grid-table > thead > tr > th,
.draggable-grid .draggable-grid__grid .dxbl-grid-table > tbody > tr > td,
.draggable-grid .draggable-grid__grid .dxbl-grid-table > tbody > tr > th,
.draggable-grid .draggable-grid__grid .dxbl-grid-table > tfoot > tr > td,
.draggable-grid .draggable-grid__grid .dxbl-grid-table > tfoot > tr > th {
	border-left-width: 0 !important;
	border-right-width: 0 !important;
}

/*
 * The two checkbox columns (DraggableGridComponent.razor's "isEditableBool" branch, and the synthetic
 * mark column behind ShowMarkColumn) are each pinned into their own frozen pane (FixedPosition="Left")
 * to keep them always leftmost and immovable.
 * Its header and data cells are tagged with this class from OnCustomizeElement, since the default
 * header-caption alignment doesn't match the cell alignment for a templated column, and DevExpress
 * draws the frozen pane's boundary line as a border/shadow on the cell itself — not reachable from
 * inside HeaderCaptionTemplate/CellDisplayTemplate.
 */
.draggable-grid .draggable-grid__grid .draggable-grid__selection-cell {
	/* Centred the table-native way rather than with flex. `display: flex` blockifies the cell, which
	   drops it out of table layout: it is then sized by its own content, so `height: 100%` has no
	   definite row height to resolve against and the box sits at the top of any row a neighbouring
	   cell has made taller. `vertical-align: middle` on a real table cell needs no height at all — the
	   row supplies it — so it stays centred however tall the row grows. Zero vertical padding keeps
	   the theme's asymmetric cell padding from biasing the result downward. */
	vertical-align: middle;
	text-align: center;
	padding-top: 0 !important;
	padding-bottom: 0 !important;
	border-right: none !important;
	box-shadow: none !important;
}

/* The checkbox itself: an inline box sitting on the cell's middle baseline, so it centres both ways
   without the cell having to become a flex container. */
.draggable-grid .draggable-grid__grid .draggable-grid__selection-cell > * {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	vertical-align: middle;
}

/*
 * Suppresses the theme's selected-row tint on a grid whose DxGridSelectionColumn is hidden
 * (DraggableGridComponent.razor's "--no-row-highlight" modifier). Those grids express selection
 * through the mark column or a data-bound IsSelected checkbox, never through the row itself, so an
 * accent-coloured row is feedback for a click rather than for any state the user set. Left alone for
 * a grid that does show the selection column, where the tint is the only such feedback there is.
 * (The focused-row highlight is switched off at the source instead — see FocusedRowEnabled.)
 */
.draggable-grid--no-row-highlight .draggable-grid__grid .dxbl-grid-selected-row > td {
	background-color: transparent;
}

/*
 * The grid's own toolbar (ShowToolbar). Only rendered for a host with no XAF action container of its
 * own — a wizard step — so these rules never affect a grid sitting under a framework toolbar.
 * flex-shrink: 0 keeps it at its natural height while the grid below takes the remaining space.
 */
.draggable-grid .draggable-grid__toolbar {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 0.75rem;
	flex: 0 0 auto;
	padding: 0.75rem 0 1rem;
	flex-wrap: wrap;
}

.draggable-grid .draggable-grid__toolbar-search {
	flex: 1 1 14rem;
	max-width: 22rem;
	min-width: 10rem;
}

.draggable-grid .draggable-grid__toolbar-actions {
	display: flex;
	align-items: center;
	gap: 0.5rem;
	flex: 0 0 auto;
}

.draggable-grid .draggable-grid__toolbar-button {
	display: inline-flex;
	align-items: center;
	gap: 0.375rem;
	white-space: nowrap;
}

.draggable-grid .draggable-grid__toolbar-icon {
	width: 1rem;
	height: 1rem;
	flex-shrink: 0;
}

/*
 * The Edit/Delete icon-button cell (DraggableGridViewModel.RowActionsTemplate, rendered beside the
 * checkbox column via RowActionsBesideSelection). Centers the pair so it doesn't hug the cell's left
 * edge the way a plain-text unbound column would.
 */
.draggable-grid .draggable-grid__grid .report-column-row-actions {
	display: flex;
	align-items: center;
	justify-content: center;
	gap: 0.25rem;
	margin: 0 auto;
}

/*
 * Each icon button (ReportColumnRowActions.razor): plain (no fill) at rest, a subtle highlight only
 * while the pointer is actually over it — not a persistent colored button. Targets the rendered
 * <button> directly since DxButton's CssClass lands on that same element.
 *
 * :focus is deliberately not a paint state here — a click leaves the button focused, and tinting it
 * would leave it looking pressed for as long as focus remains, which reads as lingering state rather
 * than a transient press. :focus-visible still paints, so keyboard navigation still shows where you
 * are.
 */
.report-column-row-action-button,
.report-column-row-action-button .dxbl-btn,
.report-column-row-action-button:focus,
.report-column-row-action-button:active,
.report-column-row-action-button .dxbl-btn:focus,
.report-column-row-action-button .dxbl-btn:active {
	background-color: transparent !important;
	border-color: transparent !important;
	box-shadow: none !important;
}

.report-column-row-action-button:hover,
.report-column-row-action-button:focus-visible,
.report-column-row-action-button .dxbl-btn:hover,
.report-column-row-action-button .dxbl-btn:focus-visible {
	background-color: rgba(var(--midgrey), 0.15) !important;
}

/*
 * The calculated-column add/edit pane (CalculatedColumnPane.razor), hosted inside
 * .draggable-grid__detail. A plain flex column so the header/footer stay pinned while the form
 * body scrolls — the pane itself already scrolls (draggable-grid.css's __detail rule), so this is
 * the header/footer sticking within that scroll region.
 */
.calculated-column-panel {
	display: flex;
	flex-direction: column;
	height: 100%;
	min-height: 0;
	min-width: 0;
	width: 100%;
	box-sizing: border-box;
}

/*
 * wizard.css caps every DxFormLayout under .wizard-step-wrapper at a fixed --wizard-step-max-width
 * (480/750px) and centers it with auto margins — the right call for a full-width wizard step, but
 * this pane is only the ~40% .draggable-grid__detail side pane (draggable-grid.css above), so that
 * cap forced the form wider than its own container and produced a horizontal scrollbar. Overridden
 * here with a more specific selector (needed since the original rule is also !important) so the form
 * fills whatever width the pane actually has instead of insisting on the step-wide default.
 *
 * Matched as a descendant, not on the wrapper itself: the form is now emitted by the hosted XAF
 * DetailView (ViewSiteComponent), so .dxbl-fl sits inside .calculated-column-form rather than being
 * that element — the pane no longer authors the DxFormLayout itself.
 */
.wizard-step-wrapper .calculated-column-panel .calculated-column-form .dxbl-fl {
	max-width: 100% !important;
	width: 100% !important;
	margin-left: 0 !important;
	margin-right: 0 !important;
	box-sizing: border-box;
}

/*
 * The hosted view's own root. It has to establish a width-bounded block for the Filter Builder,
 * whose criteria rows are laid out from their content and would otherwise push the pane wider than
 * the 40% split allows.
 */
.calculated-column-panel .calculated-column-form {
	min-width: 0;
	width: 100%;
	box-sizing: border-box;
}

.calculated-column-panel__header {
	display: flex;
	align-items: center;
	flex: 0 0 auto;
	padding-bottom: 0.5rem;
	margin-bottom: 0.5rem;
	border-bottom: 1px solid rgba(var(--midgrey), 0.25);
}

.calculated-column-panel__title {
	margin: 0;
	font-weight: 600;
}

.calculated-column-panel__body {
	flex: 1 1 auto;
	min-height: 0;
	min-width: 0;
	overflow-y: auto;
	overflow-x: hidden;
}

.calculated-column-panel__footer {
	display: flex;
	justify-content: flex-end;
	flex: 0 0 auto;
	padding-top: 0.5rem;
	margin-top: 0.5rem;
	border-top: 1px solid rgba(var(--midgrey), 0.25);
}

/* The live validity lines under the hosted form — one for the picked Field, one for the filter. */
.calculated-column-status {
	display: flex;
	align-items: center;
	gap: 0.375rem;
	font-size: 0.85rem;
	padding: 0.25rem 0;
}

.calculated-column-status__icon {
	width: 1rem;
	height: 1rem;
	flex-shrink: 0;
}

.calculated-column-status--valid {
	color: rgb(var(--success, 40, 167, 69));
}

.calculated-column-status--invalid {
	color: rgb(var(--danger, 220, 53, 69));
}
