/* PositionsGrid. Irregular rows by design: every row is its own grid but they
 * all share one track template through --pg-cols (the longest row), so a
 * two-cell row occupies exactly half the width of a four-cell one, cells stay
 * left aligned and identical in width across rows, and nothing is padded out
 * to a rectangle.
 *
 * Its own file, not one of the theme stylesheets: base.html loads a swappable
 * theme (custom.css / modern.css / modern_black_white.css /
 * style_black_and_white.css) and anything put in one only works there. Same
 * reasoning as maps.css. Colours come from the --bs-* custom properties, so
 * all four themes work untouched.
 */
.pg {
	--pg-cols: 1;
	--pg-cell-min: 9rem;
	--pg-gutter: 2.75rem;
	--pg-gap: .5rem;
	--pg-touch: 44px;                       /* WCAG 2.2 SC 2.5.8 target size */
	--pg-cell-bg: var(--bs-body-bg, #fff);
	--pg-cell-border: var(--bs-border-color, #dee2e6);
	--pg-accent: var(--bs-primary, #0d6efd);
	--pg-muted: var(--bs-secondary-color, #6c757d);
}

.pg-toolbar {
	display: flex;
	gap: 1.5rem;
	margin-bottom: .5rem;
	flex-wrap: wrap;
	align-items: flex-start;
}

.pg-toolbar-group {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: .25rem;
}

.pg-toolbar-title {
	margin: 0;
	font-size: 1rem;
}

/* The horizontal scroll lives here and nowhere else. overscroll-behavior stops
 * the chain: without it, scrolling past the last column scrolls the page and,
 * on iOS and Android, triggers the browser's back gesture. */
.pg-scroll {
	overflow-x: auto;
	overflow-y: hidden;
	overscroll-behavior-x: contain;
	-webkit-overflow-scrolling: touch;
	padding-bottom: .25rem;

	/* Without snapping, a wheel or trackpad scroll can stop with a column
	 * half off the edge -- its remove button half-cut and unclickable,
	 * looking like the grid overflowed rather than like there is one more
	 * column to reach. Snapping always settles on a whole column. */
	scroll-snap-type: x mandatory;

	/* A thin auto-hiding scrollbar at the bottom of the whole grid gives no
	 * hint that off-screen columns exist while looking at row 1 -- there is
	 * nothing to see or hover near the top. Always-on and coloured, it reads
	 * as "there is more, drag me" instead of looking like the far columns
	 * were simply cut off. */
	scrollbar-width: thin;
	scrollbar-color: var(--pg-accent) var(--pg-cell-border);
}

.pg-scroll::-webkit-scrollbar {
	height: 10px;
}

.pg-scroll::-webkit-scrollbar-track {
	background: var(--pg-cell-border);
	border-radius: 6px;
}

.pg-scroll::-webkit-scrollbar-thumb {
	background: var(--pg-accent);
	border-radius: 6px;
}

/* The scroll content: never narrower than the widest row needs, so the
 * scrollbar appears exactly when a cell would go below --pg-cell-min. */
.pg-rows {
	min-width: calc(var(--pg-gutter) + var(--pg-cols) * var(--pg-cell-min)
	                + var(--pg-cols) * var(--pg-gap));
}

.pg-row {
	display: grid;
	grid-template-columns: var(--pg-gutter)
	                       repeat(var(--pg-cols), minmax(var(--pg-cell-min), 1fr));
	gap: var(--pg-gap);
	margin-bottom: var(--pg-gap);
	align-items: stretch;
}

.pg-head {
	margin-bottom: .25rem;
}

.pg-head-cell {
	display: flex;
	justify-content: center;
	scroll-snap-align: start;
}

.pg-gutter {
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: flex-start;
	gap: .25rem;
	color: var(--pg-muted);
	scroll-snap-align: start;
}

.pg-rownum {
	font-size: .75rem;
	line-height: 1.6;
}

.pg-cell {
	display: flex;
	flex-direction: column;
	gap: .25rem;
	min-height: calc(var(--pg-touch) + .5rem);
	padding: .25rem;
	background: var(--pg-cell-bg);
	border: 1px solid var(--pg-cell-border);
	border-radius: var(--bs-border-radius, .375rem);
	scroll-snap-align: start;
}

.pg-cell-items {
	display: flex;
	flex-direction: column;
	gap: .25rem;
	flex: 1 1 auto;
}

/* create-item is full width on purpose -- no override needed: .pg-cell is a
 * column flex container and stretch is its own default align-items. */

.pg-item {
	position: relative;
	min-height: var(--pg-touch);
	cursor: pointer;
	border-radius: var(--bs-border-radius-sm, .25rem);
}

.pg-item-default {
	display: block;
	padding: .5rem;
}

/* Every interactive target is at least 44x44 -- the buttons in the gutter and
 * in the column head included, since those are the ones a thumb misses. */
.pg [data-pg-action] {
	min-width: var(--pg-touch);
	min-height: var(--pg-touch);
	display: inline-flex;
	align-items: center;
	justify-content: center;
}

/* Remove row/column stand right next to the row numbers and column heads,
 * both small chrome of their own -- at 44x44 they read as the loudest thing
 * in the gutter/head row instead of a secondary action. Still a real click
 * target, just not a WCAG-sized touch one: a deliberate exception, same
 * trade-off as remove-item below. create-item is the one that stays full
 * size -- it is the primary action of an empty cell, not a secondary one. */
.pg-gutter [data-pg-action],
.pg-head-cell [data-pg-action] {
	min-width: 28px;
	min-height: 28px;
	font-size: .75rem;
}

/* Just the icon: no btn-outline-danger border/background, which read as
 * heavier chrome than this secondary action calls for next to the plain row
 * number/column head it sits beside. */
.pg-icon-remove {
	background: none;
	border: none;
	padding: 0;
	color: var(--bs-danger, #dc3545);
}

/* Sits in the corner of the item it removes, so it never touches renderItem's
 * own layout underneath. Smaller than a touch target on purpose -- see the
 * comment on the gutter/head remove buttons above, same trade-off.
 *
 * Selector is `.pg .pg-item-remove`, not the plain class: `.pg [data-pg-action]`
 * above is two compound selectors (0,2,0) and a bare `.pg-item-remove` (0,1,0)
 * loses to it on specificity regardless of which rule comes later in the
 * file -- the 44px touch-target min-width/height wins and the button renders
 * full size no matter what this rule says. Matching that specificity here is
 * what makes the override actually take. */
.pg .pg-item-remove {
	position: absolute;
	/* The theme's global `button { margin-right: 5px; margin-bottom: 5px }`
	 * (custom.css) applies to every plain <button>, this one included, and
	 * this rule never reset it -- an absolutely positioned box's margin still
	 * counts on the side across from the offset it did not set (`left` was
	 * auto here), so `right: 2px` rendered as 2px + that 5px margin, 7px in
	 * total, while `top` -- set directly, with `bottom` auto -- was never
	 * affected. That mismatch, not the 2px/2px values, was the uneven gap. */
	margin: 0;
	top: 4px;
	right: 4px;
	min-width: 16px;
	min-height: 16px;
	padding: 0;
	font-size: .6rem;
	line-height: 1;
	background: var(--pg-cell-bg);
	border: 1px solid var(--pg-cell-border);
	border-radius: var(--bs-border-radius-sm, .25rem);
	color: var(--bs-danger, #dc3545);
}

.pg-cell:focus-visible,
.pg-item:focus-visible,
.pg [data-pg-action]:focus-visible {
	outline: 2px solid var(--pg-accent);
	outline-offset: 2px;
}

/* Move by touch: while something is picked, every cell reads as a destination. */
.pg-selecting .pg-cell {
	cursor: copy;
	box-shadow: inset 0 0 0 1px var(--pg-accent);
}

.pg-item.pg-selected {
	outline: 2px dashed var(--pg-accent);
	outline-offset: 2px;
}

/* A mutation is in flight: the grid still shows the confirmed state, it just
 * refuses a second one. */
.pg-busy {
	opacity: .6;
	pointer-events: none;
	cursor: progress;
}

.pg-highlight {
	animation: pg-flash 1.2s ease-out 2;
}

@keyframes pg-flash {
	0%, 100% { box-shadow: none; }
	50% { box-shadow: 0 0 0 3px var(--pg-accent); }
}

@media (prefers-reduced-motion: reduce) {
	.pg-highlight {
		animation: none;
		box-shadow: 0 0 0 3px var(--pg-accent);
	}
}

@media (max-width: 575.98px) {
	.pg {
		--pg-cell-min: 7.5rem;
		--pg-gutter: 2.25rem;
		--pg-gap: .375rem;
	}
}
