/* Copyright (C) 2026 Island Treasures Ltd <admin@itltz.com>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
 */

/**
 * ITOS UI — resizable list columns.
 *
 * EVERY RULE IN HERE IS SCOPED.
 *
 * This stylesheet is injected into every page of the ERP by `module_parts['css']`, so a
 * single unscoped selector would be an ERP-wide layout change. There are therefore no
 * element selectors, no utility classes and no resets: every rule is anchored to
 * `.itosui-*` (something this module created) or to `table.liste.itosui-on` (a table
 * this user has explicitly resized). A user who never drags a column edge is served this
 * file and it changes nothing on any page.
 *
 * Colours come from Dolibarr's own CSS custom properties, with literal fallbacks, so the
 * handles follow the active theme instead of fighting it.
 */

/* ---------------------------------------------------------------------------
 * The drag handle.
 *
 * Sits on the right edge of a resizable header cell. It is positioned against the
 * header cell, which the SCRIPT makes `position: relative` only when the cell is
 * `static`. That is deliberate and it is not something this file should do: Dolibarr
 * gives sticky list headers `position: sticky` (`.liste_titre.sticky`), and a blanket
 * `position: relative` here would silently override it and un-stick every sticky header
 * in the ERP.
 * ------------------------------------------------------------------------- */
.itosui-handle {
	position: absolute;
	top: 0;
	right: 0;
	width: 9px;
	height: 100%;

	cursor: col-resize;
	user-select: none;
	-webkit-user-select: none;

	/* The handle overlays the column's sort link. Without this the browser may start a
	   touch scroll or a text selection instead of giving us the pointer events. */
	touch-action: none;

	/* Above the sort <a>, so that a grab on the edge is a resize and never a sort. */
	z-index: 3;

	background: transparent;
	opacity: 0;
	transition: opacity 0.12s ease-in-out;
}

/* Reveal the grip when the user is anywhere near the header row, not only exactly on the
   6px target — otherwise the feature is undiscoverable. */
tr.liste_titre:hover .itosui-handle,
.itosui-handle:hover,
.itosui-handle:focus,
.itosui-handle-active {
	opacity: 1;
}

.itosui-handle::after {
	content: "";
	position: absolute;
	top: 15%;
	right: 3px;
	width: 2px;
	height: 70%;
	border-radius: 1px;
	background: var(--colortexttitle, #6c7c8c);
}

.itosui-handle:hover::after,
.itosui-handle-active::after {
	background: var(--colorbackhmenu1, #263c5c);
	width: 3px;
	right: 3px;
}

/* Keyboard users must be able to see which handle they are on. */
.itosui-handle:focus-visible {
	outline: 2px solid var(--colorbackhmenu1, #263c5c);
	outline-offset: -1px;
	opacity: 1;
}

/* ---------------------------------------------------------------------------
 * While dragging.
 *
 * The cursor is forced globally so it does not flicker back to a text caret when the
 * pointer strays off the 9px handle mid-drag, and selection is killed so the drag does
 * not paint the whole header row blue.
 * ------------------------------------------------------------------------- */
body.itosui-dragging,
body.itosui-dragging * {
	cursor: col-resize !important;
	user-select: none !important;
	-webkit-user-select: none !important;
}

/* ---------------------------------------------------------------------------
 * A table that this user has actually resized.
 *
 * `table-layout: fixed` and the column widths themselves are set inline by the script.
 * This block only handles what happens to the CONTENT once a column can be narrower than
 * its text.
 *
 * The two cases are treated differently on purpose:
 *
 *  - Cells that Dolibarr already wraps: let them keep wrapping. `overflow-wrap` is added
 *    so a single long unbroken token (a 40-character product ref, a URL) breaks instead
 *    of spilling into the next column. Nothing is hidden; the row just gets taller.
 *
 *  - Cells Dolibarr deliberately keeps on one line (`.nowrap`, `.nowraponall` — dates,
 *    amounts, refs): these cannot wrap by design, so if the user narrows the column the
 *    text has to go somewhere. Clipping it with a visible ellipsis is the honest answer;
 *    letting it overflow would have it silently overlap the neighbouring column's value,
 *    and on a money column that is genuinely dangerous — you could read a total that is
 *    half of one figure and half of another.
 *
 * So: nothing is hidden that was not already single-line, the truncation is always
 * visible as an ellipsis rather than silent, and it is undone by a double-click on the
 * handle (auto-fit) or by Reset.
 * ------------------------------------------------------------------------- */
table.liste.itosui-on th,
table.liste.itosui-on td {
	overflow-wrap: break-word;
	word-break: break-word;
	overflow: hidden;
}

table.liste.itosui-on td.nowrap,
table.liste.itosui-on th.nowrap,
table.liste.itosui-on td.nowraponall,
table.liste.itosui-on th.nowraponall,
table.liste.itosui-on td.nowrapfordate,
table.liste.itosui-on th.nowrapfordate {
	text-overflow: ellipsis;
}

/* The action column must never be clipped: its row menu pops OUT of the cell, and
   `overflow: hidden` above would cut it off. It is also the trailing auto-width column, so
   it is never narrow enough to need clipping in the first place. */
table.liste.itosui-on th:last-child,
table.liste.itosui-on td:last-child,
table.liste.itosui-on th.maxwidthsearch,
table.liste.itosui-on td.maxwidthsearch {
	overflow: visible;
}

/* The filter row.
 *
 * Dolibarr's search inputs carry their own minimum widths (`maxwidth75imp`, `minwidth100`
 * and friends). Under a fixed layout those minimums win, so a narrowed column's search box
 * keeps its size and pokes out over the next column — the ONE case where narrowing a column
 * used to spill visible content sideways, and it was in the filter row rather than the data.
 * Constrain the controls to their column and the filters keep working at any width. */
table.liste.itosui-on tr.liste_titre_filter input,
table.liste.itosui-on tr.liste_titre_filter select,
table.liste.itosui-on tr.liste_titre_filter .select2,
table.liste.itosui-on tr.liste_titre_filter .select2-container {
	max-width: 100%;
	box-sizing: border-box;
}

/* ---------------------------------------------------------------------------
 * The reset control.
 *
 * Created by the script ONLY while the table has stored widths, and removed the instant
 * it does not. A user who has never resized a column never sees this on any page.
 * ------------------------------------------------------------------------- */
.itosui-reset {
	display: inline-block;
	margin: 0 0 4px 0;
	padding: 2px 8px;

	font-size: 0.85em;
	line-height: 1.6;

	color: var(--colortexttitle, #6c7c8c);
	background: transparent;
	border: 1px solid var(--colorboxstatsborder, #ced4da);
	border-radius: 3px;
	cursor: pointer;
}

.itosui-reset:hover,
.itosui-reset:focus-visible {
	color: var(--colorbackhmenu1, #263c5c);
	border-color: var(--colorbackhmenu1, #263c5c);
}

/* ---------------------------------------------------------------------------
 * Print.
 *
 * Printed output must be exactly what Dolibarr prints today. The handles and the reset
 * button are removed, and the fixed layout is unwound, so a user's screen widths cannot
 * leak onto paper and clip a figure.
 *
 * (Dolibarr's PDFs — invoices, proposals, orders — are generated server-side by TCPDF and
 * never load this stylesheet at all, so they are structurally untouchable from here. This
 * block is about the browser's own Print, which does use it.)
 * ------------------------------------------------------------------------- */
@media print {
	.itosui-handle,
	.itosui-reset {
		display: none !important;
	}

	table.liste.itosui-on {
		table-layout: auto !important;
		min-width: 0 !important;
		width: 100% !important;
	}

	table.liste.itosui-on td,
	table.liste.itosui-on th {
		overflow: visible !important;
		text-overflow: clip !important;
	}
}

/* ---------------------------------------------------------------------------
 * Touch and narrow screens.
 *
 * The script already refuses to attach handles on a coarse pointer or below 768px, so
 * this is belt-and-braces for the case where a desktop window is resized down AFTER the
 * handles were attached: the handles disappear and normal horizontal scrolling of the
 * list is preserved. Row taps and links are never intercepted.
 * ------------------------------------------------------------------------- */
@media (max-width: 767px), (pointer: coarse) {
	.itosui-handle {
		display: none !important;
	}
}
