/* =========================================================================
 * HS DESIGN SYSTEM — the one stylesheet both apps build on.
 *
 * haramain_store and courier_services_integration are separate Frappe apps that
 * ship pages into the same desk, for the same people, on the same screen. Until
 * now they looked it: haramain had a full design system locked inside its own
 * 9,000-line stylesheet, and the courier app had ninety lines of ad-hoc CSS with
 * its own idea of a card, a tab and a table. Two apps, two visual languages, one
 * user wondering why the parcel page looks like a different product.
 *
 * So the tokens and the primitives live here, and both apps include this file.
 * Everything is `hs-` prefixed and every page-specific rule stays in its own
 * app's stylesheet — this file owns the vocabulary, not the pages.
 *
 * WHAT GOES HERE      tokens, page shell, card, filter bar, tile, table, pill,
 *                     empty state, responsive rules
 * WHAT DOES NOT       anything that names a single page or a single report
 *
 * Colours are Frappe's own custom properties wherever one exists, so dark mode
 * and any deployed theme come free — this file never hardcodes a background or
 * an ink colour that Frappe already re-points.
 *
 * Load order does not matter for the tokens: `var()` resolves at computed-value
 * time, so `:root` here applies wherever this file lands in the bundle.
 * ========================================================================= */


/* ==========================================================================
 * TOKENS
 * ======================================================================= */

:root {
	/* Radius — three steps. Anything rounder is a pill. */
	--hs-r-sm: 8px;
	--hs-r: 12px;
	--hs-r-lg: 16px;
	--hs-pill: 999px;

	/* Elevation — flat, raised, floating. Cards are flat by default; the
	   border does the separating and the shadow only marks what lifts. */
	--hs-e1: 0 1px 2px rgba(16, 24, 40, 0.05);
	--hs-e2: 0 4px 12px rgba(16, 24, 40, 0.08);
	--hs-e3: 0 12px 32px rgba(16, 24, 40, 0.16);

	/* Motion — one duration, one curve. */
	--hs-t: 140ms cubic-bezier(0.4, 0, 0.2, 1);

	/* The accent. Follows the deployed theme, falls back to Frappe's primary. */
	--hs-accent: var(--my-primary-color, var(--primary, #2490ef));

	/* Numeric type: tabular figures, so a column of currency lines up. */
	--hs-nums: tabular-nums;

	/* Tone ramp. Each tone is a Frappe colour plus its paired surface and ink,
	   all four of which Frappe re-points in dark mode. */
	--hs-green: var(--green-600, #16a34a);
	--hs-green-bg: var(--bg-green);
	--hs-green-ink: var(--text-on-green);
	--hs-red: var(--red-600, #dc2626);
	--hs-red-bg: var(--bg-red);
	--hs-red-ink: var(--text-on-red);
	--hs-amber: var(--orange-500, #f59e0b);
	--hs-amber-bg: var(--bg-orange);
	--hs-amber-ink: var(--text-on-orange);
	--hs-yellow: var(--yellow-500, #eab308);
	--hs-yellow-bg: var(--bg-yellow);
	--hs-yellow-ink: var(--text-on-yellow);
	--hs-blue: var(--blue-500, #2490ef);
	--hs-blue-bg: var(--bg-blue);
	--hs-blue-ink: var(--text-on-blue);
	--hs-purple: var(--purple-500, #8b5cf6);
	--hs-purple-bg: var(--bg-purple);
	--hs-purple-ink: var(--text-on-purple);
	--hs-pink: var(--pink-500, #ec4899);
	--hs-pink-bg: var(--bg-pink);
	--hs-pink-ink: var(--text-on-pink);
	--hs-cyan: var(--cyan-500, #06b6d4);
	--hs-cyan-bg: var(--bg-cyan);
	--hs-cyan-ink: var(--text-on-cyan);
	--hs-gray: var(--gray-500, #6b7280);
	--hs-gray-bg: var(--bg-gray);
	--hs-gray-ink: var(--text-on-gray);
}

/* Spacing — one scale, so gaps between cards, inside cards and between fields
   are all multiples of the same number instead of six arbitrary pixel values. */
:root {
	--hs-sp-1: 4px;
	--hs-sp-2: 8px;
	--hs-sp-3: 12px;
	--hs-sp-4: 16px;
	--hs-sp-5: 24px;
	--hs-sp-6: 32px;

	/* The widest a page of text or figures gets. Beyond this a table stops being
	   scannable — the eye loses the row on the way back to the left edge. */
	--hs-measure: 1400px;

	/* The page shell's own gutters. Tokens rather than numbers in the rule,
	   because four different containers across the two apps have to agree on
	   them: `.hs-page` here, each app's page-specific wrapper, the Quick Sales
	   Order two-column shell, and the narrower form measure. They were four
	   hardcoded copies, and they had already drifted — 1400 against 1440, 8px of
	   top gutter against 16px — so switching pages nudged the content. */
	--hs-page-top: 8px;
	--hs-page-bottom: 40px;

	/* The one gap between the blocks of a page — card to card, card to tile row,
	   tab bar to content, and between the cells of a grid of cards. It is owned by
	   the *container*, never by the blocks: every block carrying its own
	   margin-bottom is how a page ends up with 16px in one place, 20px in the next
	   and nothing at all where somebody deleted a wrapper. */
	--hs-gap: var(--hs-sp-4);
}

/* Small screens: redefining the two tokens moves every container at once, so no
   container needs a media query of its own. */
@media (max-width: 768px) {
	:root {
		--hs-page-top: 4px;
		--hs-page-bottom: 28px;
	}
}


/* ==========================================================================
 * PAGE SHELL
 * ======================================================================= */

/* Every custom page in either app sits in one of these: capped measure, centred,
   equal breathing room top and bottom, so switching pages never shifts the
   content sideways. */
.hs-page {
	width: 100%;
	max-width: var(--hs-measure);
	margin: 0 auto;
	padding: var(--hs-page-top) 0 var(--hs-page-bottom);
	display: flex;
	flex-direction: column;
	gap: var(--hs-gap);
}

/* Small screens tighten the rhythm by redefining the token, so containers and
   grids move together instead of each needing its own media query. */
@media (max-width: 768px) {
	:root {
		--hs-gap: var(--hs-sp-3);
	}
}


/* ==========================================================================
 * CARD
 * ======================================================================= */

/* Flat by default. The border does the separating; a shadow is reserved for
   things that genuinely lift off the page (menus, dialogs), so a screen of eight
   cards does not read as eight floating panels. */
.hs-card {
	background: var(--card-bg, var(--fg-color, #fff));
	border: 1px solid var(--border-color);
	border-radius: var(--hs-r);
	padding: var(--hs-sp-4);
}

@media (max-width: 768px) {
	.hs-card {
		padding: var(--hs-sp-3);
		border-radius: var(--hs-r-sm);
	}
}

/* Title on the left, context on the right, wrapping to two lines rather than
   letting a long title crush the hint next to it. */
.hs-card-head {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	gap: var(--hs-sp-3);
	flex-wrap: wrap;
	margin-bottom: var(--hs-sp-3);
	font-weight: 600;
	color: var(--heading-color, var(--text-color));
}

.hs-card-hint {
	color: var(--text-muted);
	font-size: var(--text-xs);
	font-weight: 400;
}


/* ==========================================================================
 * FILTER BAR
 * ======================================================================= */

/* Filters belong in a card of their own. Floating above the content they control
   they read as page furniture; in a card they read as the controls that decide
   what everything below says. */
.hs-filters {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
	gap: var(--hs-sp-3) var(--hs-sp-4);
	align-items: end;
}

.hs-field {
	display: flex;
	flex-direction: column;
	gap: var(--hs-sp-1);
	min-width: 0;
}

.hs-field > label {
	margin: 0;
	font-size: var(--text-xs);
	font-weight: 600;
	color: var(--text-muted);
	text-transform: uppercase;
	letter-spacing: 0.03em;
}

/* The date range decides what a report is about, so it sits above the other
   filters rather than beside them as the last of four. */
.hs-dates {
	display: flex;
	align-items: center;
	gap: var(--hs-sp-2) var(--hs-sp-3);
	flex-wrap: wrap;
	padding-bottom: var(--hs-sp-3);
	margin-bottom: var(--hs-sp-3);
	border-bottom: 1px solid var(--border-color);
}

.hs-range {
	display: flex;
	align-items: center;
	gap: var(--hs-sp-2);
	margin-left: auto;
}

/* Sized to a date, not stretched to the row — an input three times wider than
   the date in it reads as a field waiting for something longer. */
.hs-range .form-control {
	width: auto;
	min-width: 0;
	flex: 0 0 auto;
}

.hs-range-sep {
	flex: 0 0 auto;
	color: var(--text-muted);
	font-size: var(--text-sm);
}

/* The range drops under the presets before the presets themselves wrap, so a
   narrow window never strands a single preset alone on a line. */
@media (max-width: 720px) {
	.hs-range {
		margin-left: 0;
		width: 100%;
	}
}

/* Preset chips — one click for the ranges anyone actually asks for. */
.hs-presets {
	display: flex;
	gap: var(--hs-sp-1);
	flex-wrap: wrap;
}

.hs-preset {
	padding: 3px 11px;
	border: 1px solid var(--border-color);
	border-radius: var(--hs-pill);
	background: transparent;
	color: var(--text-muted);
	font-size: var(--text-xs);
	font-weight: 600;
	line-height: 1.6;
	cursor: pointer;
	transition: background var(--hs-t), color var(--hs-t), border-color var(--hs-t);
}

.hs-preset:hover {
	background: var(--subtle-accent);
	color: var(--text-color);
}

.hs-preset.is-active {
	border-color: var(--text-color);
	background: var(--text-color);
	color: var(--bg-color, #fff);
}


/* ==========================================================================
 * TILES — the figures a page is opened for
 * ======================================================================= */

.hs-tiles {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
	gap: var(--hs-sp-3);
}

.hs-tile {
	padding: var(--hs-sp-3) var(--hs-sp-4);
	border: 1px solid var(--border-color);
	border-radius: var(--hs-r-sm);
	background: var(--card-bg, var(--fg-color, #fff));
	min-width: 0;
}

.hs-tile-label {
	color: var(--text-muted);
	font-size: var(--text-xs);
	font-weight: 600;
	text-transform: uppercase;
	letter-spacing: 0.03em;
	margin-bottom: var(--hs-sp-1);
}

/* Tabular figures, so a column of money lines up digit under digit. */
.hs-tile-value {
	font-size: var(--text-lg);
	font-weight: 700;
	color: var(--text-color);
	font-variant-numeric: var(--hs-nums);
	overflow-wrap: anywhere;
}

.hs-tile-good .hs-tile-value { color: var(--hs-green); }
.hs-tile-warn .hs-tile-value { color: var(--hs-amber); }
.hs-tile-bad  .hs-tile-value { color: var(--hs-red); }


/* ==========================================================================
 * TABLE
 * ======================================================================= */

/* Wide tables scroll inside their own container. The page body must never
   scroll sideways — that moves the filters and the headings off screen too. */
.hs-table-wrap {
	overflow-x: auto;
	-webkit-overflow-scrolling: touch;
}

.hs-table {
	width: 100%;
	margin: 0;
	border-collapse: collapse;
	font-size: var(--text-sm);
}

.hs-table th,
.hs-table td {
	padding: var(--hs-sp-2) var(--hs-sp-3);
	border-bottom: 1px solid var(--border-color);
	text-align: left;
	vertical-align: middle;
}

/* Sticky header: on a report running to hundreds of rows, the column you are
   reading is the one thing you cannot afford to lose halfway down. */
.hs-table thead th {
	position: sticky;
	top: 0;
	z-index: 1;
	background: var(--card-bg, var(--fg-color, #fff));
	font-size: var(--text-xs);
	font-weight: 600;
	color: var(--text-muted);
	text-transform: uppercase;
	letter-spacing: 0.03em;
	white-space: nowrap;
}

.hs-table tbody tr:hover {
	background: var(--subtle-accent);
}

.hs-table tbody tr:last-child td {
	border-bottom: 0;
}

/* Numbers right, and tabular, so magnitudes are comparable down the column. */
.hs-num {
	text-align: right;
	font-variant-numeric: var(--hs-nums);
	white-space: nowrap;
}

.hs-rank {
	width: 1%;
	color: var(--text-muted);
	font-variant-numeric: var(--hs-nums);
}

.hs-strong { font-weight: 600; }
.hs-muted  { color: var(--text-muted); }


/* ==========================================================================
 * PILL — a status, a count, a tag
 * ======================================================================= */

.hs-pill-tag {
	display: inline-block;
	padding: 1px 8px;
	border-radius: var(--hs-pill);
	font-size: var(--text-xs);
	font-weight: 600;
	line-height: 1.7;
	white-space: nowrap;
	background: var(--hs-gray-bg);
	color: var(--hs-gray-ink);
}

.hs-pill-good { background: var(--hs-green-bg); color: var(--hs-green-ink); }
.hs-pill-warn { background: var(--hs-amber-bg); color: var(--hs-amber-ink); }
.hs-pill-bad  { background: var(--hs-red-bg);   color: var(--hs-red-ink); }
.hs-pill-info { background: var(--hs-blue-bg);  color: var(--hs-blue-ink); }


/* ==========================================================================
 * EMPTY / LOADING
 * ======================================================================= */

/* An empty report should say why it is empty. A blank panel reads as a page
   that failed to load, which is the one thing it must not be confused with. */
.hs-empty {
	padding: var(--hs-sp-6) var(--hs-sp-4);
	text-align: center;
	color: var(--text-muted);
	font-size: var(--text-sm);
}

.hs-tabs {
	display: flex;
	gap: var(--hs-sp-1);
	flex-wrap: wrap;
	border-bottom: 1px solid var(--border-color);
	margin-bottom: var(--hs-sp-4);
}

.hs-tab {
	padding: var(--hs-sp-2) var(--hs-sp-4);
	border: 0;
	border-bottom: 2px solid transparent;
	background: transparent;
	color: var(--text-muted);
	font-size: var(--text-sm);
	font-weight: 600;
	cursor: pointer;
	transition: color var(--hs-t), border-color var(--hs-t);
}

.hs-tab:hover { color: var(--text-color); }

.hs-tab.is-active {
	color: var(--hs-accent);
	border-bottom-color: var(--hs-accent);
}


/* ==========================================================================
 * RESPONSIVE — small screens
 * ======================================================================= */

@media (max-width: 576px) {
	/* One column: two 150px tiles side by side on a phone leaves neither
	   readable, and the figure is the entire point of a tile. */
	.hs-tiles {
		grid-template-columns: 1fr;
	}

	.hs-filters {
		grid-template-columns: 1fr;
	}

	.hs-card-head {
		margin-bottom: var(--hs-sp-2);
	}

	/* Sticky headers are dropped on a phone: the viewport is short enough that a
	   pinned header costs more of it than the context is worth. */
	.hs-table thead th {
		position: static;
	}
}

/* Print: the controls are not part of the report. */
@media print {
	.hs-filters,
	.hs-dates,
	.hs-presets,
	.hs-tabs {
		display: none !important;
	}

	.hs-card {
		border: 0;
		padding: 0;
		break-inside: avoid;
	}
}


/* ==========================================================================
 * UTILITIES
 * ======================================================================= */

/* A deliberately short list. A utility earns its place by replacing a pattern
   that repeats across pages — a one-off inline value turned into a single-use
   class is the same declaration with an indirection in front of it, no clearer
   and one more place to look. haramain_store.css carries the older `hs-u-*`
   set; these are the ones the shared file owns because both apps want them. */

.hs-u-m0  { margin: 0; }
.hs-u-pt  { padding-top: var(--hs-sp-2); }
.hs-u-mb-sm { margin-bottom: var(--hs-sp-2); }

/* The two neutral surfaces, named by role rather than by colour so a theme can
   re-point them: `soft` is a tint used to set a block apart from the card it
   sits in, `fill` is the flatter one used behind a table head or a chip. */
.hs-u-tone-soft { background: var(--subtle-accent); }
.hs-u-tone-fill { background: var(--subtle-fg); }

/* A button whose whole job is to confirm something irreversible. Painted from
   JavaScript before this existed — `background-color: '#28a745'` — so it was the
   one button on the desk that ignored the theme and could only be recoloured by
   editing a controller. */
.hs-btn-affirm,
.hs-btn-affirm:hover,
.hs-btn-affirm:focus {
	background: var(--hs-green);
	border-color: var(--hs-green);
	color: var(--white, #fff);
	font-weight: 600;
}

/* A row that needs attention without being an error — "this employee is already on
   a shift". Tinted from the theme's own amber pair, so it stays legible on the
   dark desk; it was painted inline as `#fffbeb` on `#f59e0b`, a light-mode-only
   combination that turned into a near-white bar over unreadable text. */
.hs-row-flagged {
	border-left: 3px solid var(--hs-amber);
	background: var(--hs-amber-bg);
}

/* The warning tone — "this will not do what you might expect". Distinct from
   `bad`, which is a failure; a warning is a consequence worth knowing about
   before you click. Was written inline as `#b45309` in half a dozen dialogs,
   which is amber-700 from a light-mode palette and muddy on the dark desk. */
.hs-u-warn { color: var(--hs-amber-ink, var(--hs-amber)); }
.hs-u-mt-sm { margin-top: var(--hs-sp-2); }
