
/* ==========================================================================
   1. Bootstrap design tokens — :root / [data-bs-theme=light] / [data-bs-theme=dark]
   Bootstrap 5.3 defines most of these twice (once in the bare :root block,
   once again inside [data-bs-theme=light]) and a third time inside
   [data-bs-theme=dark]; we override all three so the brand color is correct
   regardless of which block ends up governing at runtime / if the user
   toggles theme mode.
   ========================================================================== */
:root,
[data-bs-theme="light"] {
	/* roundedness */
	--bs-border-radius: 0.85rem;
	--bs-border-radius-sm: 0.5rem;
	--bs-border-radius-lg: 1rem;
	--bs-border-radius-xl: 1.25rem;

	/* brand primary — purple, tuned for contrast on light/white surfaces */
	--bs-primary: #6D3BC4;
	--bs-primary-rgb: 109, 59, 196;
	--bs-primary-text-emphasis: #3F2170;
	--bs-primary-bg-subtle: #F1EAFC;
	--bs-primary-border-subtle: #C9AEF0;

	/* Metronic-specific primary tokens (drive .bg-light-primary, .badge-light-primary,
	   .btn-light-primary, .text-light-primary, menu-*-bg-light-primary, etc.) */
	--bs-primary-light: #F1EAFC;
	--bs-primary-active: #5A2FA6;
	--bs-primary-clarity: rgba(109, 59, 196, 0.2);
	--bs-text-primary: #6D3BC4;

	/* links + focus ring (literal in the compiled bundle, not var-derived) */
	--bs-link-color: #6D3BC4;
	--bs-link-color-rgb: 109, 59, 196;
	--bs-link-hover-color: #5A2FA6;
	--bs-link-hover-color-rgb: 90, 47, 166;
	--bs-focus-ring-color: rgba(109, 59, 196, 0.25);

	/* ------------------------------------------------------------------
	   White + purple surfaces. LIGHT IS THE APP DEFAULT (see
	   defaultThemeMode in layouts/panel.blade.php and layouts/auth.blade.php).

	   THE PAGE IS NOT PURE WHITE, and that is the whole point of these three
	   values. A full-screen #FFFFFF field is the most glaring thing a monitor
	   can show; a barely-tinted off-white costs nothing in brightness and is
	   measurably easier to sit in front of. Cards then stay pure white, so
	   they LIFT off the page instead of dissolving into it — on a pure-white
	   page every card needs a border to exist at all, and the screen fills up
	   with lines.

	   Body text is a dark slate-purple rather than #000. Pure black on
	   near-white is the highest contrast a screen can produce and reads as
	   harsh over long sessions; this sits around 13:1, comfortably past WCAG
	   AAA while losing the glare.
	   ------------------------------------------------------------------ */
	--bs-page-bg: #F6F4FB;
	--bs-body-bg: #F6F4FB;
	--bs-app-bg: #F6F4FB;
	--bs-app-blank-bg: #F6F4FB;

	--bs-body-color: #2B2536;
	--bs-body-color-rgb: 43, 37, 54;
	--bs-heading-color: #1F1A2B;
	--bs-secondary-color: #6E667F;
	--bs-tertiary-color: #8C8499;

	/* Hairlines with a purple cast, so borders belong to the scheme rather
	   than looking like leftover grey. */
	--bs-border-color: #E7E1F3;
	--bs-border-color-translucent: rgba(109, 59, 196, 0.12);

	--bs-gray-100: #F6F4FB;
	--bs-gray-200: #EDE9F6;
	--bs-gray-300: #E7E1F3;

	/* Metronic's "light-*" fills, retinted from grey to a lavender wash. */
	--bs-light: #F3F0FA;
	--bs-light-rgb: 243, 240, 250;
	--bs-secondary: #EDE9F6;

	/* Success/danger tuned for contrast on white rather than Bootstrap's
	   defaults, which are set for large text. Both pass AA at normal size. */
	--bs-success: #14724D;
	--bs-success-rgb: 20, 114, 77;
	--bs-danger: #B3261E;
	--bs-danger-rgb: 179, 38, 30;
}

/* Cards, modals and every raised surface stay pure white against the tinted
   page. This is the contrast that replaces heavy borders. */
[data-bs-theme="light"] .card,
[data-bs-theme="light"] .modal-content,
[data-bs-theme="light"] .dropdown-menu,
[data-bs-theme="light"] .offcanvas {
	background-color: #FFFFFF;
	border: 1px solid var(--bs-border-color);
}

/* Metronic ships a fairly heavy default card shadow. On a light page a soft,
   purple-tinted lift reads cleaner than a grey drop shadow. */
[data-bs-theme="light"] .card {
	box-shadow: 0 1px 2px rgba(31, 26, 43, 0.04), 0 8px 24px rgba(109, 59, 196, 0.06);
}

[data-bs-theme="light"] .table {
	--bs-table-color: var(--bs-body-color);
	--bs-table-border-color: var(--bs-border-color);
	--bs-table-striped-bg: #FAF8FE;
	--bs-table-hover-bg: #F3F0FA;
}

[data-bs-theme="light"] .form-control,
[data-bs-theme="light"] .form-select {
	background-color: #FFFFFF;
	border-color: var(--bs-border-color);
	color: var(--bs-body-color);
}

[data-bs-theme="light"] .form-control:focus,
[data-bs-theme="light"] .form-select:focus {
	border-color: var(--bs-primary);
	box-shadow: 0 0 0 3px rgba(109, 59, 196, 0.14);
}

/* The top bar sits against the purple sidebar and the white content; a plain
   white bar with one hairline keeps that junction clean. */
[data-bs-theme="light"] .header {
	background-color: #FFFFFF;
	border-bottom: 1px solid var(--bs-border-color);
}

[data-bs-theme="dark"] {
	/* Near-black purple-tinted surfaces (cashier-terminal mockup), not
	   Metronic's stock neutral-gray dark mode. */
	--bs-body-bg: #170B2C;
	--bs-body-color: #F1ECFA;
	--bs-secondary-bg: #1F1038;
	--bs-tertiary-bg: #241640;
	--bs-border-color: #4A3270;
	--bs-border-color-translucent: rgba(74, 50, 112, 0.6);

	/* brand primary — lighter purple, tuned for contrast on near-black surfaces */
	--bs-primary: #9D6FE0;
	--bs-primary-rgb: 157, 111, 224;
	--bs-primary-text-emphasis: #D8C4F0;
	--bs-primary-bg-subtle: #33235C;
	--bs-primary-border-subtle: #5B3F92;

	--bs-primary-light: #33235C;
	--bs-primary-active: #6D3BC4;
	--bs-primary-clarity: rgba(157, 111, 224, 0.25);
	--bs-text-primary: #9D6FE0;

	--bs-link-color: #9D6FE0;
	--bs-link-color-rgb: 157, 111, 224;
	--bs-link-hover-color: #D8C4F0;
	--bs-link-hover-color-rgb: 245, 217, 138;
	--bs-focus-ring-color: rgba(157, 111, 224, 0.3);

	--bs-scrolltop-bg-color: #9D6FE0;
	--bs-scrolltop-bg-color-hover: #6D3BC4;
}

/* Card/content surfaces in dark mode — Metronic's compiled .card doesn't
   fully key off --bs-body-bg/--bs-tertiary-bg for its own background, so it
   needs a direct (still dark-scoped, not unconditional) override here. */
[data-bs-theme="dark"] .card,
[data-bs-theme="dark"] .modal-content {
	background-color: #241640;
	border-color: #4A3270;
	color: #F1ECFA;
}

[data-bs-theme="dark"] .table {
	--bs-table-bg: transparent;
	--bs-table-color: #F1ECFA;
	--bs-table-border-color: #4A3270;
}

[data-bs-theme="dark"] .form-control,
[data-bs-theme="dark"] .form-select {
	background-color: #1F1038;
	border-color: #4A3270;
	color: #F1ECFA;
}

[data-bs-theme="dark"] .form-control:focus,
[data-bs-theme="dark"] .form-select:focus {
	background-color: #1F1038;
	color: #F1ECFA;
}

/* ==========================================================================
   2. Per-component literal hex overrides
   Bootstrap 5.3's compiled CSS bakes literal hex values into a handful of
   per-component custom properties instead of consuming --bs-primary. Each
   selector below was confirmed present in style.bundle.css with a hardcoded
   value; restated here with the purple brand color. Uses one mid purple
   unconditionally, since it reads acceptably on both light
   and dark surfaces and these components appear in both modes.
   ========================================================================== */
.btn-primary {
	/* Purple is dark enough that white ink is the correct choice across
	   every state. */
	--bs-btn-color: #ffffff;
	--bs-btn-bg: #6D3BC4;
	--bs-btn-border-color: #6D3BC4;
	--bs-btn-hover-color: #ffffff;
	--bs-btn-hover-bg: #5A2FA6;
	--bs-btn-hover-border-color: #5A2FA6;
	--bs-btn-focus-shadow-rgb: 109, 59, 196;
	--bs-btn-active-color: #ffffff;
	--bs-btn-active-bg: #4B2E82;
	--bs-btn-active-border-color: #4B2E82;
	--bs-btn-active-shadow: none;
	--bs-btn-disabled-color: #ffffff;
	--bs-btn-disabled-bg: #6D3BC4;
	--bs-btn-disabled-border-color: #6D3BC4;
}

.btn-outline-primary {
	--bs-btn-color: #6D3BC4;
	--bs-btn-border-color: #6D3BC4;
	--bs-btn-hover-color: #ffffff;
	--bs-btn-hover-bg: #6D3BC4;
	--bs-btn-hover-border-color: #6D3BC4;
	--bs-btn-focus-shadow-rgb: 109, 59, 196;
	--bs-btn-active-color: #ffffff;
	--bs-btn-active-bg: #4B2E82;
	--bs-btn-active-border-color: #4B2E82;
	--bs-btn-active-shadow: none;
	--bs-btn-disabled-color: #6D3BC4;
	--bs-btn-disabled-bg: transparent;
	--bs-btn-disabled-border-color: #6D3BC4;
	--bs-gradient: none;
}

.nav-pills .nav-link.active,
.nav-pills .show>.nav-link {
	background-color: #6D3BC4;
	--bs-nav-pills-link-active-color: #ffffff;
}

.progress,
.progress-stacked {
	--bs-progress-bar-bg: #6D3BC4;
}

.accordion-button {
	--bs-accordion-btn-active-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%236D3BC4'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
}

.form-check-input:checked {
	background-color: #6D3BC4;
	border-color: #6D3BC4;
}

.form-check-input[type="checkbox"]:indeterminate {
	background-color: #6D3BC4;
	border-color: #6D3BC4;
}

.form-check.form-check-solid .form-check-input[type="checkbox"]:indeterminate {
	background-color: #6D3BC4;
}

.form-range::-webkit-slider-thumb {
	background-color: #6D3BC4;
}

.form-range::-moz-range-thumb {
	background-color: #6D3BC4;
}

.separator.separator-content.border-primary::after,
.separator.separator-content.border-primary::before {
	border-color: #6D3BC4 !important;
}

/* ==========================================================================
   3. Dark sidebar — deep purple identity (distinct from the near-black
   content area for visual hierarchy), active item now gold to match the
   app-wide "selected/active" accent.
   ========================================================================== */
.aside {
	background-color: #1B1430;
}

.aside .aside-logo {
	background-color: #120D22;
}

.aside-menu .menu-item.hover:not(.here)>.menu-link:not(.disabled):not(.active):not(.here),
.aside-menu .menu-item:not(.here)>.menu-link:hover:not(.disabled):not(.active) {
	background-color: #2C2148;
	color: #fff;
}

.aside-menu .menu-item.here>.menu-link {
	background-color: #2C2148;
	color: #fff;
}

.aside-menu .menu-item.show>.menu-link {
	background-color: #2C2148;
	color: #fff;
}

/* current-page highlight pill: gold gradient (dark ink for contrast — gold
   is too light for white text). */
.aside-menu .menu-item .menu-link.active {
	background: linear-gradient(135deg, #9D6FE0, #6D3BC4);
	color: #241640;
}

.aside-menu .menu-item .menu-link.active .menu-icon,
.aside-menu .menu-item .menu-link.active .menu-icon .svg-icon,
.aside-menu .menu-item .menu-link.active .menu-icon i,
.aside-menu .menu-item .menu-link.active .menu-bullet .bullet {
	color: #ffffff;
}

.aside-menu .menu-item .menu-link .menu-bullet .bullet {
	background-color: #8B7FAE;
}

.aside-menu .menu-item .menu-link .menu-icon,
.aside-menu .menu-item .menu-link .menu-icon .svg-icon,
.aside-menu .menu-item .menu-link .menu-icon i {
	color: #8B7FAE;
}

.aside-menu .menu-item .menu-link .menu-arrow:after {
	background-color: #8B7FAE;
}

/* ==========================================================================
   4. Soft / jolly polish — roundedness + gold-tinted shadows
   .btn and .card hardcode --bs-btn-border-radius / --bs-card-border-radius
   to 0rem in the compiled bundle rather than consuming --bs-border-radius,
   so the root-level token redefinition above does not reach them; set the
   literal property directly here instead.
   ========================================================================== */
.btn,
.btn-lg,
.btn-sm {
	border-radius: 0.65rem;
}

.card {
	border-radius: 1rem;
	box-shadow: 0 0.5rem 1.5rem rgba(109, 59, 196, 0.1);
}

[data-bs-theme="dark"] .card {
	box-shadow: 0 0.5rem 1.5rem rgba(0, 0, 0, 0.35);
}

/* Clickable dashboard summary/link cards only (panels/production/dashboard.blade.php,
   panels/auditor/dashboard.blade.php) — not applied globally to table/form cards. */
.hover-lift {
	transition: transform 0.15s ease, box-shadow 0.15s ease;
}

.hover-lift:hover {
	transform: translateY(-3px);
	box-shadow: 0 0.75rem 2rem rgba(109, 59, 196, 0.2);
}

/* ==========================================================================
   5. Login page — soft card + gradient background
   ========================================================================== */
.auth-bg {
	/* background-image only (not the `background` shorthand): the shorthand
	   would implicitly reset background-repeat to its initial value (repeat),
	   tiling this gradient into a striped pattern instead of one smooth
	   sweep, and would fight the body's existing bgi-size-cover /
	   bgi-position-center / bgi-no-repeat / bgi-attachment-fixed utility
	   classes that already set those sub-properties correctly. */
	background-image: linear-gradient(135deg, #F7F2FC 0%, #ECE0F9 50%, #E4D4F7 100%) !important;
}

[data-bs-theme="dark"] .auth-bg {
	background-image: linear-gradient(135deg, #170B2C 0%, #241640 50%, #3A2E5A 100%) !important;
}

.login-card {
	border-radius: 1.25rem;
	box-shadow: 0 1rem 3rem rgba(109, 59, 196, 0.18);
	border: 1px solid #C9AEF0;
}

[data-bs-theme="dark"] .login-card {
	border-color: #4A3270;
	box-shadow: 0 1rem 3rem rgba(0, 0, 0, 0.45);
}

/* Decorative cake illustrations on the login page's left brand panel.
   Purely visual: absolutely positioned, pointer-events:none so they can
   never intercept a click, and hidden below the lg breakpoint where the
   brand panel itself stacks above the form (avoids clutter on mobile). */
.login-illustration-panel {
	position: relative;
}

.login-illustration-panel>.position-relative {
	z-index: 1;
}

.login-decor {
	position: absolute;
	pointer-events: none;
	z-index: 0;
	filter: drop-shadow(0 6px 14px rgba(109, 59, 196, 0.18));
}

.login-decor-cupcake {
	width: 110px;
	height: auto;
	top: 6%;
	right: 4%;
	animation: login-decor-float 5s ease-in-out infinite;
}

.login-decor-slice {
	width: 130px;
	height: auto;
	bottom: 8%;
	left: 2%;
	animation: login-decor-float 6s ease-in-out infinite;
	animation-delay: 0.5s;
}

.login-decor-sprinkle {
	width: 22px;
	height: 22px;
	opacity: 0.55;
	animation: login-decor-float 4s ease-in-out infinite;
}

.login-decor-sprinkle-1 {
	top: 18%;
	left: 12%;
	animation-delay: 0.2s;
}

.login-decor-sprinkle-2 {
	top: 52%;
	right: 16%;
	animation-delay: 1.1s;
}

.login-decor-sprinkle-3 {
	bottom: 18%;
	left: 28%;
	animation-delay: 1.8s;
}

.login-decor-sprinkle-4 {
	top: 32%;
	right: 8%;
	animation-delay: 0.7s;
}

@keyframes login-decor-float {

	0%,
	100% {
		transform: translateY(0);
	}

	50% {
		transform: translateY(-8px);
	}
}

@media (max-width: 991.98px) {
	.login-decor {
		display: none;
	}
}

/* ==========================================================================
   6. Error pages (403 / 404 / 500) — soft card chrome
   ========================================================================== */
.error-card {
	border-radius: 1.25rem;
	box-shadow: 0 1rem 3rem rgba(109, 59, 196, 0.18);
	border: 1px solid #C9AEF0;
}

[data-bs-theme="dark"] .error-card {
	border-color: #4A3270;
	box-shadow: 0 1rem 3rem rgba(0, 0, 0, 0.45);
}

.error-glyph {
	color: #6D3BC4;
}


/* --------------------------------------------------------------------------
   POS palette. Written for a LIGHT page background first, because that is
   what the terminal actually renders as unless the user has switched theme —
   the previous revision assumed dark and produced pale-on-white text that was
   effectively invisible (stock badges, discount/payment pills, tender pad).
   Every pair below is a solid fill or a tinted fill with dark ink, never
   light-on-light. Dark-mode variants follow at the end of this block.
   Purple is the accent throughout (Purple Yam); orange stays reserved for the
   single checkout CTA so it remains the most prominent control on screen.
   -------------------------------------------------------------------------- */


/* Prices and money figures. */


/* Stock pill — tinted fill with DARK ink so the number is always readable.
   The previous light-lavender-on-translucent version disappeared entirely on
   a white card. */


@keyframes pos-live-pulse {

	0%,
	100% {
		opacity: 1;
		box-shadow: 0 0 0 0 rgba(30, 158, 90, 0.6);
	}

	50% {
		opacity: 0.6;
		box-shadow: 0 0 0 4px rgba(30, 158, 90, 0);
	}
}


/* Discount + payment pills share one visual language: tinted when idle,
   SOLID PURPLE when selected. One consistent "selected = purple" signal is
   easier to read at a glance than two different active colours. */


/* Cart line delete button — the duotone icon inherits currentColor, so the
   colour has to be set on the button for the glyph to show at all. */


/* Quantity steppers. */


/* Primary checkout CTA — orange, deliberately the ONLY orange on the screen
   so it reads as "the one button that finishes the sale". */


/* -------------------------------------------------------------------------
   Dark-mode variants. Same roles, inverted: tinted fills become deep purples
   and the ink becomes light, so contrast is preserved either way.
   ------------------------------------------------------------------------- */


/* ==========================================================================
   Offline-first POS: status strip + non-blocking notice stack
   Appended section — nothing above this line was modified.
   ========================================================================== */

.pos-status-strip {
	position: fixed;
	left: 1rem;
	bottom: 1rem;
	z-index: 1070;
	display: inline-flex;
	align-items: center;
	gap: .5rem;
	padding: .5rem .9rem;
	border-radius: 999px;
	border: 1px solid #4A3270;
	background-color: #241640;
	color: #E9E2F5;
	font-size: .8125rem;
	font-weight: 600;
	box-shadow: 0 .25rem .75rem rgba(0, 0, 0, .35);
}

.pos-status-strip .pos-status-dot {
	width: .55rem;
	height: .55rem;
	border-radius: 50%;
	background-color: #6c757d;
	flex: 0 0 auto;
}

.pos-status-strip.is-online {
	border-color: #2E7D4F;
}

.pos-status-strip.is-online .pos-status-dot {
	background-color: #3DD68C;
	box-shadow: 0 0 0 .2rem rgba(61, 214, 140, .18);
}

.pos-status-strip.is-warn {
	border-color: #8a5615;
}

.pos-status-strip.is-warn .pos-status-dot {
	background-color: #E7B84B;
	box-shadow: 0 0 0 .2rem rgba(231, 184, 75, .18);
}

.pos-status-strip.is-offline {
	border-color: #A33A3A;
}

.pos-status-strip.is-offline .pos-status-dot {
	background-color: #F1585B;
	box-shadow: 0 0 0 .2rem rgba(241, 88, 91, .18);
}

.pos-status-strip .pos-status-pending {
	padding: .1rem .5rem;
	border-radius: 999px;
	background-color: #E7B84B;
	color: #241640;
	font-size: .75rem;
	font-weight: 700;
}

.pos-notice-stack {
	position: fixed;
	right: 1rem;
	/* TOP right, matching #app_toast_container — the rest of the app puts its
	   toasts there, and a cashier who learns to look in one corner should not
	   have to learn a second one for the till. */
	top: 1rem;
	z-index: 1075;
	width: 22rem;
	max-width: calc(100vw - 2rem);
	display: flex;
	flex-direction: column;
	gap: .5rem;
	pointer-events: none;
}

/* Pushed clear of a modal header while one is open.
   The stack sits ABOVE the modal layer (1075 vs 1055) and every notice takes
   pointer events, so at top:1rem a notice lands squarely on the till's
   "Close Terminal" button and swallows the click — the cashier taps to leave
   and nothing happens. 4.75rem clears the 62px header (and the 52px one on a
   short landscape screen). */
body.modal-open .pos-notice-stack {
	top: 4.75rem;
}

.pos-notice {
	position: relative;
	pointer-events: auto;
	padding: .7rem 2rem .7rem .9rem;
	border-radius: .5rem;
	border-left: .25rem solid #8E5CD9;
	background-color: #2C1B4D;
	color: #E9E2F5;
	font-size: .8125rem;
	font-weight: 500;
	line-height: 1.35;
	box-shadow: 0 .35rem .9rem rgba(0, 0, 0, .4);
	white-space: pre-line;
	word-break: break-word;
}

.pos-notice-success {
	border-left-color: #3DD68C;
}

.pos-notice-warn {
	border-left-color: #E7B84B;
}

.pos-notice-close {
	position: absolute;
	top: .25rem;
	right: .4rem;
	border: 0;
	background: transparent;
	color: inherit;
	opacity: .6;
	font-size: 1.05rem;
	line-height: 1;
	padding: .15rem .3rem;
	cursor: pointer;
}

.pos-notice-close:hover {
	opacity: 1;
}

/* ==========================================================================
   9. POS quick-tender pad
   Denomination shortcuts under Cash Tendered. Sized for finger targets on a
   tablet (44px min) rather than mouse precision, since this is the control
   the cashier hits most under time pressure. Uses the same purple language as
   the rest of the screen; all fills are solid or tinted-with-dark-ink so the
   numbers stay legible on a white card.
   ========================================================================== */


/* Denominations — tinted purple with deep purple ink. */


/* Exact — solid purple, the "primary" action of this pad. */


/* ==========================================================================
   10. Receipt modal + thermal print
   The preview is monospaced at a fixed 32-column measure so what the cashier
   sees on screen is column-for-column what the 58mm printer emits.
   ========================================================================== */
.pos-receipt-preview {
	font-family: "Courier New", Courier, monospace;
	font-size: 12px;
	line-height: 1.35;
	white-space: pre;
	background: #ffffff;
	color: #111111;
	border: 1px solid var(--pos-purple-border, #C9AEF0);
	border-radius: 0.5rem;
	padding: 0.75rem 0.5rem;
	max-height: 60vh;
	overflow-y: auto;
}

/* Preview stays a white paper slip even in dark mode — it represents
   physical receipt paper, not app chrome. */
[data-bs-theme="dark"] .pos-receipt-preview {
	background: #ffffff;
	color: #111111;
}

.pos-receipt-line {
	white-space: pre;
}

.pos-receipt-big {
	font-size: 18px;
	letter-spacing: 0.05em;
}

/* Hidden until print_fallback() fills it. */
.pos-receipt-print-area {
	display: none;
}

@media print {

	/* Receipt isolation.
	   `display: none` — NOT `visibility: hidden` — because a hidden element
	   still occupies layout, so the browser paginates all that empty space
	   and emits pages of blank paper after the receipt. Removing the nodes
	   from flow entirely is what makes the output exactly one slip.
	   print_fallback() relocates #pos_receipt_print_area to be a direct child
	   of <body> before printing, which is what lets `body > *` target
	   everything else. */
	@page {
		margin: 0;
	}

	html,
	body {
		margin: 0 !important;
		padding: 0 !important;
		height: auto !important;
		background: #ffffff !important;
		overflow: visible !important;
	}

	html.pos-printing body>*:not(#pos_receipt_print_area) {
		display: none !important;
	}

	/* Bootstrap appends the backdrop to <body>; the modal itself may sit
	   deeper in the tree, so both are named explicitly. */
	.modal,
	.modal-backdrop,
	.pos-status-strip,
	.pos-notice-stack {
		display: none !important;
	}

	#pos_receipt_print_area {
		display: block !important;
		position: static !important;
		width: 58mm;
		margin: 0;
		padding: 2mm;
		font-family: "Courier New", Courier, monospace;
		font-size: 11px;
		line-height: 1.3;
		color: #000000;
		background: #ffffff;
		white-space: pre;
	}

	#pos_receipt_print_area .pos-receipt-line {
		white-space: pre;
		page-break-inside: avoid;
	}

	#pos_receipt_print_area .pos-receipt-big {
		font-size: 15px;
		font-weight: 700;
	}
}

/* ==========================================================================
   11. POS blocking error dialog
   Red header so it is unmistakably an error, not another confirmation the
   cashier can tap through on autopilot.
   ========================================================================== */
.pos-error-header {
	background-color: #B32318;
	color: #ffffff;
	border-bottom: 0;
}

.pos-error-header .modal-title {
	color: #ffffff;
}

#pos_error_modal .modal-body .fs-1 {
	color: #B32318;
	line-height: 1;
}
/* ==========================================================================
   Icon buttons
   ==========================================================================
   Most actions in this app are icon-only, which buys back a lot of horizontal
   room in the data tables — but only if the buttons are actually square and
   sit on a predictable grid. Metronic ships .btn-icon; these rules pin the
   sizing so a row of actions lines up whether it holds two buttons or five,
   and whether a button is an <a>, a <button>, or a <button> wrapped in the
   inline <form> that a DELETE action needs.
   ========================================================================== */

/* Square, fixed footprint. Without an explicit width an icon-only <a> collapses
   to the glyph's advance width and the column jitters between rows. */
.btn.btn-icon.btn-sm {
    width: 2.25rem;
    height: 2.25rem;
    padding: 0;
    flex: 0 0 auto;
}

.btn.btn-icon.btn-sm > i {
    font-size: 1.05rem;
    line-height: 1;
}

/* Action cluster in a table cell.
   inline-flex + gap replaces the me-1 margins that used to be hand-applied to
   every button (and forgotten on the last one). align-items keeps a form-wrapped
   button level with its plain siblings. */
.action-buttons {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    white-space: nowrap;
}

/* A DELETE action is a <form> so it can carry the CSRF token and method
   spoofing. Strip the block-level behaviour so it sits in the row like a
   button rather than breaking the line. */
.action-buttons form {
    display: inline-flex;
    margin: 0;
}

/* Toolbar buttons keep their label, so they need breathing room between the
   glyph and the text. Applied via the utility class rather than a global
   .btn > i rule, which would also hit icon-only buttons and offset the glyph
   inside its square. */
.btn-labeled > i {
    margin-right: 0.4rem;
    font-size: 1rem;
    line-height: 1;
}

/* Card toolbars hold several labelled buttons; gap keeps them apart without
   per-button margin classes. */
.card-toolbar {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    flex-wrap: wrap;
}

/* Destructive actions read as red on hover even in the light-tinted variant,
   so a mis-aimed click is visibly different from Edit right before it lands. */
.btn.btn-icon.btn-light-danger:hover,
.btn.btn-icon.btn-light-danger:focus {
    background-color: var(--bs-danger);
    color: #fff;
}

/* Tooltips are the only on-screen label an icon-only button has, so make them
   legible rather than the default washed-out grey. */
.tooltip-inner {
    font-weight: 500;
    letter-spacing: 0.01em;
}

/* ==========================================================================
   Daily Expenses Report — sheet layout + print
   ==========================================================================
   The branches fill in a printed five-column form. The digital page is laid out
   the same way so a manager can hold the two side by side and check the column
   totals against each other; the print rules then produce a filed copy that
   looks like the document they already keep.
   ========================================================================== */

/* Each column is a stack of entries, not a row per entry — the paper form has
   one tall box per column and staff write down it. Matching that keeps the
   columns independent, so a busy Direct column does not push blank rows into
   Salaries. */
.daily-sheet > tbody > tr > td {
    vertical-align: top;
}

/* A rule between entries, standing in for the ruled lines on the paper. */
.daily-sheet .sheet-line + .sheet-line {
    border-top: 1px dashed var(--bs-border-color);
}

.daily-sheet thead th {
    vertical-align: top;
}

/* Minimum height so an empty column still reads as a column rather than
   collapsing to nothing beside a full one. */
.daily-sheet > tbody > tr:first-child > td {
    height: 180px;
}

@media print {
    /* App chrome never belongs on paper, on any page. The POS receipt is not
       affected: it isolates itself far more aggressively via the
       html.pos-printing rules above, which hide every body child except the
       receipt node. */
    .aside,
    .header,
    .footer,
    .toolbar,
    #kt_aside,
    #kt_header,
    #kt_footer,
    .d-print-none {
        display: none !important;
    }

    .wrapper,
    .content,
    .container-xxl,
    .post {
        padding: 0 !important;
        margin: 0 !important;
    }

    /* .report-sheet is carried by every printable sheet (the daily cost form,
       the monthly DSR/DER grid, the monthly expense ledger). #daily_sheet is
       kept alongside it so the daily sheet keeps printing correctly for anyone
       whose cached markup predates the class. */
    #daily_sheet,
    .report-sheet {
        box-shadow: none !important;
        border: 0 !important;
    }

    /* Force the ruled grid to survive the browser's "don't print background
       graphics" default — without this the sheet prints as unaligned text. */
    #daily_sheet .table,
    #daily_sheet .table th,
    #daily_sheet .table td,
    .report-sheet .table,
    .report-sheet .table th,
    .report-sheet .table td {
        border-color: #000 !important;
    }

    /* Badges are colour-coded on screen; on paper they need an outline to read
       at all once the fill is dropped. */
    #daily_sheet .badge,
    .report-sheet .badge {
        border: 1px solid #666;
        color: #000 !important;
        background: transparent !important;
    }

    /* A month is long. Let the browser break the grid across sheets, but never
       mid-row — half a day's figures at the foot of one page and half at the
       head of the next is how a total gets read twice. */
    .report-sheet tr {
        page-break-inside: avoid;
    }

    /* Repeat the two header rows on every printed page, otherwise page 2 of the
       ledger is twelve unlabelled columns of numbers. */
    .report-sheet thead {
        display: table-header-group;
    }

    /* A NAMED page, not a bare @page.
       @page cannot be scoped by selector, so a plain
       `@page { size: A4 landscape }` here would also apply to the POS receipt —
       which sets `@page { margin: 0 }` above for a 58mm slip and would start
       emitting landscape A4 sheets instead. Naming the page and pointing only
       this element at it keeps the two apart. Browsers without named-page
       support simply fall back to the default size; the sheet still prints. */
    @page daily_expenses_sheet {
        size: A4 landscape;
        margin: 12mm;
    }

    #daily_sheet,
    .report-sheet {
        page: daily_expenses_sheet;
    }
}

/* ==========================================================================
   Monthly workbook sheets — DSR/DER grid and the MSE expense ledger
   ==========================================================================
   These two reproduce the Excel file the branches keep, one tab each. Both are
   wide: the grid is 9 columns, the ledger 14. The rules below are about keeping
   that width readable on screen without shrinking the figures to nothing.
   ========================================================================== */

/* Tight cells. At 31 rows x 9 columns the theme's default padding pushes the
   month off the bottom of the screen, and the point of a one-page-per-month
   sheet is that it fits on one page. */
.monthly-grid > tbody > tr > td,
.monthly-grid > thead > tr > th {
    padding: 0.45rem 0.5rem;
}

.monthly-ledger > tbody > tr > td,
.monthly-ledger > thead > tr > th {
    padding: 0.35rem 0.4rem;
}

/* A merged date or block-total cell sits top-aligned against its own lines,
   the way the spreadsheet's merged cells do. Everything else centres on its
   row. */
.monthly-ledger > tbody > tr > td.align-top {
    vertical-align: top;
}

/* The five kind groups need to be separable at a glance — without a rule
   between them, 14 equally-spaced columns read as one undifferentiated block
   and it is genuinely hard to tell which AMOUNT belongs to which heading. The
   view marks the first cell of each group with .group-start rather than this
   stylesheet counting columns with nth-child: the column count depends on how
   many kinds there are, and a positional rule would silently point at the wrong
   column the day a sixth kind is added. */
.monthly-ledger th.group-start,
.monthly-ledger td.group-start {
    border-left-width: 2px;
}

/* Sticky headers while scrolling a long month. Two header rows, so the second
   is offset by the height of the first. */
.monthly-grid > thead > tr > th,
.monthly-ledger > thead > tr > th {
    position: sticky;
    top: 0;
    z-index: 2;
    background-color: var(--bs-light);
}

.monthly-grid > thead > tr:nth-child(2) > th,
.monthly-ledger > thead > tr:nth-child(2) > th {
    top: 2.6rem;
}

@media print {
    /* Sticky positioning and printing do not mix — a sticky header can repeat
       itself over the body text on paper. The thead display rule above is what
       repeats the header per page instead. */
    .monthly-grid > thead > tr > th,
    .monthly-ledger > thead > tr > th {
        position: static;
    }

    /* The ledger is 14 columns; at screen size it will not fit even landscape
       A4. Shrinking the type is the only way to print it whole, and it is still
       legible at this size because the cells are mostly figures. */
    .monthly-ledger {
        font-size: 7.5pt;
    }

    .monthly-grid {
        font-size: 9pt;
    }

    /* .table-responsive clips overflow on screen; on paper that clip would cut
       the last columns off entirely rather than wrapping them. */
    .report-sheet .table-responsive {
        overflow: visible !important;
    }
}


/* ==========================================================================
   12. POS notices that need an ANSWER
   --------------------------------------------------------------------------
   Two states a cashier cannot resolve by reading: signed out with completed
   sales still queued, and a new version of the till waiting to be applied.
   Both carry a button, so they are laid out rather than being a line of text
   with a close box.
   ========================================================================== */

/* Red, and distinct from .pos-notice-warn. Amber on this screen means
   "something to know"; this means "money is not moving until you act". */
.pos-notice-error {
	border-left-color: #E5484D;
	background-color: #3A1620;
}

.pos-notice-action {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: .55rem;
	padding-right: 2rem;
}

.pos-notice-action .pos-notice-text {
	white-space: pre-line;
}

.pos-notice-btn {
	align-self: stretch;
	/* A real touch target. This is the control that gets a shift's takings
	   onto the server; it does not get to be a 20px link. */
	min-height: 40px;
	padding: 0 1rem;
	border: 0;
	border-radius: .4rem;
	background: #8E5CD9;
	color: #FFFFFF;
	font-size: .8125rem;
	font-weight: 700;
	cursor: pointer;
}

.pos-notice-btn:hover:not(:disabled) { background: #7B48C9; }
.pos-notice-btn:disabled { opacity: .6; cursor: default; }

.pos-notice-error .pos-notice-btn { background: #E5484D; }
.pos-notice-error .pos-notice-btn:hover:not(:disabled) { background: #CE3A3F; }

/* viewport-fit=cover lets the page paint under a tablet's rounded corners;
   the toast stack has to pad itself back out or it sits under them. */
.pos-notice-stack {
	right: calc(1rem + env(safe-area-inset-right));
	top: calc(1rem + env(safe-area-inset-top));
}

body.modal-open .pos-notice-stack {
	top: calc(4.75rem + env(safe-area-inset-top));
}

/* ==========================================================================
   13. Installed-app (standalone) chrome
   --------------------------------------------------------------------------
   Launched from the home screen there is no browser UI, so every pixel the
   app spends on its own furniture is one the till does not get. On a 768px-
   tall landscape tablet the footer alone is about 56px of copyright line.

   Scoped to display-mode: standalone so the browser tab is untouched — an
   admin on a laptop still sees the normal page.
   ========================================================================== */
@media (display-mode: standalone) {
	#kt_footer {
		display: none !important;
	}

	/* Pull-to-refresh reloads the page. The open cart survives it (it is
	   persisted on every mutation) but the reload itself, mid-order, with a
	   customer waiting, is not something a stray downward swipe should be
	   able to cause. */
	html, body {
		overscroll-behavior-y: contain;
	}
}

/* ==========================================================================
   BADGES — light, readable

   Two opposite failures were happening at once.

   Metronic's solid badges (`badge bg-success`, `badge bg-danger`) rendered as
   a mid-dark fill with a darker text colour on top of it — the pair was never
   meant to be used together, and the result was close to unreadable at badge
   size. Its light badges (`badge-light-warning`) went the other way:
   saturated text on a near-white tint that all but disappeared.

   Every badge variant is replaced with one honest pattern: a light tinted
   background, a dark saturated text colour, and a 1px border of the same hue
   so the badge still has an edge against a white card. Each pair below was
   measured in a browser and clears WCAG AA (4.5:1) for text on its own
   background — lowest is success at 5.89:1, highest is dark at 13.85:1.

   Three scoping decisions, each of which was a bug the first time round:

   1. Every rule is anchored on `.badge`. `bg-light-primary` and friends are
      also used on cards, icon tiles and buttons, where changing the
      background would be wrong. Nothing outside a badge moves.

   2. The base rule excludes the till's own two badges. `pos-count-badge` is
      a solid accent pill with white text and `pos-stock-badge` goes solid red
      when a tile is sold out; both carry the `badge` class, and both are
      styled in pos-terminal.css without `!important`. An `!important` here
      would silently bleach them, and the sold-out state is the one badge in
      the system that MUST stay loud.

   3. `!important` on the variant rules is not decoration: Bootstrap's `.bg-*`
      utilities carry it, so an override without it loses whatever its
      specificity. The base rule deliberately does NOT use it, so that
      pos-terminal.css — which loads after this file — can still win.
   ========================================================================== */

/* The defaults live on their own low-specificity rule. They cannot sit in
   the block below: that selector scores 0-3-0, which would beat every
   `.badge.bg-*` variant at 0-2-0 and leave the whole system one flat grey. */
.badge {
	--py-badge-bg: #F6F4FB;
	--py-badge-fg: #474154;
	--py-badge-border: #E2DCEF;
}

.badge:not(.pos-count-badge):not(.pos-stock-badge) {
	display: inline-flex;
	align-items: center;
	gap: 0.35em;
	padding: 0.45em 0.75em;
	border: 1px solid var(--py-badge-border);
	border-radius: 0.6rem;
	background-color: var(--py-badge-bg);
	color: var(--py-badge-fg);
	font-size: 0.8125rem;
	font-weight: 600;
	line-height: 1.1;
	letter-spacing: 0.01em;
	white-space: nowrap;
	vertical-align: middle;
}

/* Primary ------------------------------------------------------------- */
.badge.bg-primary,
.badge.bg-light-primary,
.badge.badge-primary,
.badge.badge-light-primary {
	--py-badge-bg: #F1E9FD;
	--py-badge-fg: #4B2191;
	--py-badge-border: #D6C2F5;
}

/* Success ------------------------------------------------------------- */
.badge.bg-success,
.badge.bg-light-success,
.badge.badge-success,
.badge.badge-light-success {
	--py-badge-bg: #E6F6EC;
	--py-badge-fg: #0E6B3C;
	--py-badge-border: #BFE7D0;
}

/* Danger -------------------------------------------------------------- */
.badge.bg-danger,
.badge.bg-light-danger,
.badge.badge-danger,
.badge.badge-light-danger {
	--py-badge-bg: #FDECEF;
	--py-badge-fg: #9E1B37;
	--py-badge-border: #F6C8D2;
}

/* Warning ------------------------------------------------------------- */
.badge.bg-warning,
.badge.bg-light-warning,
.badge.badge-warning,
.badge.badge-light-warning {
	--py-badge-bg: #FDF4E3;
	--py-badge-fg: #7A4E00;
	--py-badge-border: #F2DDB2;
}

/* Info ---------------------------------------------------------------- */
.badge.bg-info,
.badge.bg-light-info,
.badge.badge-info,
.badge.badge-light-info {
	--py-badge-bg: #E8F1FD;
	--py-badge-fg: #17497F;
	--py-badge-border: #C4DCF7;
}

/* Secondary ----------------------------------------------------------- */
.badge.bg-secondary,
.badge.bg-light-secondary,
.badge.badge-secondary,
.badge.badge-light-secondary {
	--py-badge-bg: #F0EEF6;
	--py-badge-fg: #474154;
	--py-badge-border: #DCD7E7;
}

/* Dark ---------------------------------------------------------------- */
.badge.bg-dark,
.badge.bg-light-dark,
.badge.badge-dark,
.badge.badge-light-dark {
	--py-badge-bg: #E9E6F0;
	--py-badge-fg: #241533;
	--py-badge-border: #D2CCDF;
}

/* Light / neutral ------------------------------------------------------ */
.badge.bg-light,
.badge.badge-light {
	--py-badge-bg: #F6F4FB;
	--py-badge-fg: #474154;
	--py-badge-border: #E2DCEF;
}

/* Beat the Bootstrap `.bg-*` utilities, which carry `!important`. The
   attribute selectors also catch a `badge-light-` built in Blade from a
   value that turned out empty, which would otherwise fall through to
   Bootstrap's transparent default and print dark text on nothing. */
.badge[class*="bg-"]:not(.pos-count-badge):not(.pos-stock-badge),
.badge[class*="badge-light"]:not(.pos-count-badge):not(.pos-stock-badge) {
	background-color: var(--py-badge-bg) !important;
	color: var(--py-badge-fg) !important;
	border-color: var(--py-badge-border) !important;
}

/* Circle badges are a count or a status dot, not a label. Metronic already
   sizes and rounds them; all that is needed here is to undo the padding and
   the gap the base rule above introduced, so a `w-10px h-10px` status dot
   stays a dot instead of stretching into a lozenge.

   The `:not()` pair is carried over from the base rule purely for weight:
   without it this selector scores 0-2-0 against the base rule's 0-3-0, the
   base padding survives, and a flex item's automatic minimum size then
   stretches the 10px dot to 18px wide. */
.badge.badge-circle:not(.pos-count-badge):not(.pos-stock-badge) {
	padding: 0;
	gap: 0;
	justify-content: center;
	border-radius: 50%;
}

/* Printing. A tinted background is dropped by most print settings, which
   would leave a bordered box with no fill — so print the text darker and
   keep the border, which does survive. */
@media print {
	.badge {
		color: #1F1A2E !important;
		background-color: #FFFFFF !important;
		border-color: #9A93AC !important;
	}
}
