/**
 * base.css
 *
 * Design tokens (CSS custom properties) and global element resets shared
 * by every other stylesheet in the theme. Loaded first — every other CSS
 * file in assets/css/ depends on the variables defined here.
 *
 * --ink/--bg default to the brand palette (docs/brand-identity.md,
 * 2026-09-28) and are overridden live by includes/class-brand-output.php
 * (Appearance > Customize > Brand — Colors & Type) — that file prints an
 * inline <style> block right after this one loads, so a Customizer
 * change takes effect with no build step. --ink-soft/--line/--bg-soft/
 * --bg-bright are NOT Customizer-editable — fixed values derived from
 * the two editable colors (brand-identity.md's own "derived, not
 * sampled" note), kept as separate variables so rules below don't need
 * to compute a tint every time they're used. (--bg-soft has no brand-doc
 * equivalent — it's this file's own slightly-deeper tint of --bg, picked
 * to stay visually close while still reading as distinct, for notice/
 * badge backgrounds.)
 *
 * The --wt-* variables mirror docs/brand-tokens.css's reference names
 * exactly (as aliases of the ones above), so that file's utility classes
 * (.wt-divider/.wt-badge/.wt-stripe-texture/.wt-image-mat, reproduced
 * near the bottom of this file) work as-is anywhere in the theme, fully
 * wired to the same live, admin-editable values.
 *
 * Scope note (2026-09-28): only this file's own rules and the new
 * utility classes read these variables so far. The other stylesheets in
 * this folder (header.css, footer.css, shop.css, etc.) still use their
 * own hardcoded grayscale values from before this phase — see
 * roadmap.md Phase 3 for why that migration is flagged as follow-up
 * rather than done here.
 */

:root {
	/* Customizer-editable (includes/admin/class-brand-customizer.php). */
	--ink: #1c1c1c;
	--bg: #f4f3ee;

	/* Fixed, derived from the brand palette — not editable. */
	--ink-soft: #5a5a5a;
	--line: #d9d6cd;
	--bg-soft: #e7e6e1;
	--bg-bright: #ffffff;

	/* Aliases matching docs/brand-tokens.css's own names 1:1. */
	--wt-color-ink: var(--ink);
	--wt-color-ink-muted: var(--ink-soft);
	--wt-color-paper: var(--bg);
	--wt-color-paper-bright: var(--bg-bright);
	--wt-color-cream: var(--bg);
	--wt-color-line: var(--line);
	--wt-color-line-on-dark: #3a3a3a;
	--wt-tracking-headline: -0.015em;
	--wt-tracking-eyebrow: 0.05em;
	--wt-stripe-size: 10px;

	/* Font pairing — set live by includes/class-brand-output.php; these
	   are just the brand-default fallback for the rare case that file
	   hasn't run (e.g. a raw CSS preview outside WordPress). */
	--wt-font-display: 'Archivo', system-ui, sans-serif;
	--wt-font-body: 'Inter', system-ui, sans-serif;
}

* {
	box-sizing: border-box;
}

body {
	margin: 0;
	font-family: var(--wt-font-body);
	color: var(--ink);
	background: var(--bg);
	line-height: 1.55;
}
a {
	color: var(--ink);
	text-decoration: none;
}
img {
	max-width: 100%;
	display: block;
}
h1,
h2,
h3,
h4 {
	margin: 0 0 0.4em;
	letter-spacing: -0.01em;
	font-family: var(--wt-font-display);
}
button {
	font: inherit;
	cursor: pointer;
}

.wrap {
	max-width: 1240px;
	margin: 0 auto;
	padding: 0 24px;
}

/*
 * Static Page content (page.php's own .entry-content wrapper — Contact
 * Us, Partner With Us, Terms & Conditions, Customization Policy, Privacy
 * Policy, Cookies Policy, and any other plain admin-authored Page) —
 * mobile-audit "Contact Us" pass, 2026-09-15.
 *
 * This is free-form admin-authored prose (the_content()) with no guard
 * against a single long, unbreakable token. Found via Playwright: a
 * realistic admin_email value in Contact Us's mailto: link (e.g.
 * "orders@acmepromotionalproductsandapparelsupply.com") overflowed the
 * page at 320/375px — default text wrapping only breaks at
 * spaces/hyphens, and an email address's local/domain parts typically
 * have neither. Scoped to .entry-content generally, not just that one
 * link, since any of these pages could just as easily contain a long
 * URL instead. `overflow-wrap: anywhere` (stronger than `break-word`)
 * forces a break even with no better hyphenation point available, so
 * this can't blow out .wrap's width regardless of what an admin types
 * into any of these pages in the future.
 *
 * Mobile-audit "index.php" pass (2026-09-15) extends this same
 * protection to .entry-summary — index.php's the_excerpt() output on
 * the blog listing/search-results view (index.php only reaches
 * .entry-content for a rare singular post with no excerpt; the normal
 * multi-post listing case uses .entry-summary instead). Same risk,
 * same fix: confirmed via Playwright with a stress-test excerpt
 * containing a long email — .entry-summary alone scrolled to 486px in
 * a 375px viewport without this.
 */
.entry-content,
.entry-summary {
	overflow-wrap: anywhere;
}

/*
 * index.php's search-results heading — mobile-audit "index.php" pass
 * (2026-09-15), real confirmed bug. get_search_query() is raw
 * visitor-typed input with no guaranteed spaces/hyphens (a long
 * single "word" search, or a pasted URL) rendered directly into this
 * <h1> with no wrapping protection at all — confirmed via Playwright:
 * a realistic long, space-free query alone scrolled this heading to
 * 903px in a 375px viewport, well past .entry-content/.entry-summary's
 * already-protected risk class. Page-specific class (index.php) rather
 * than a bare `.wrap h1` rule, since .wrap wraps headings sitewide that
 * don't need this.
 */
.search-results-heading {
	overflow-wrap: anywhere;
}

/*
 * Breadcrumbs — used on every page that renders woocommerce_breadcrumb()
 * (shop/category archives, single product, cart, checkout, account),
 * so this belongs in base.css (loaded on every page) rather than a
 * page-specific stylesheet. Moved here after finding it duplicated
 * identically in both shop.css and account.css, and missing entirely
 * everywhere else (single-product.css, cart.css, checkout.css) — since
 * shop.css only loads on shop/category/taxonomy/search pages and
 * account.css only on account pages, single product/cart/checkout
 * breadcrumbs had no custom styling at all and fell back to the bare
 * browser default. That's what actually caused the font/padding/margin
 * mismatch reported against the single product page specifically, but
 * it affected cart and checkout too. One canonical copy here fixes all
 * of them and prevents the same gap on any future page.
 */
.breadcrumbs {
	font-size: 12.5px;
	color: var(--ink-soft);
	padding: 16px 0 0;
}
.breadcrumbs a {
	color: var(--ink-soft);
	text-decoration: underline;
}

/* Shared button styles used across multiple components (cart, checkout,
 * account, product page) — see docs/spec-review.md for each usage. */
.btn {
	display: inline-block;
	text-align: center;
	background: var(--ink);
	color: var(--bg);
	border: 1px solid var(--ink);
	padding: 12px 20px;
	font-size: 12.5px;
	text-transform: uppercase;
	letter-spacing: 0.03em;
	font-weight: 700;
	font-family: var(--wt-font-display);
}
.btn:hover {
	background: var(--bg);
	color: var(--ink);
}
.btn-outline {
	background: var(--bg);
	color: var(--ink);
}
.btn-outline:hover {
	background: var(--ink);
	color: var(--bg);
}
/*
 * Moved here from account.css (2026-09-07) — .btn defaults to
 * content-width (sized to its own text, see the comment above), and
 * .btn-block is the sitewide override used wherever a button should
 * instead match its container's full width (Wholesale Application,
 * per-product/general Get Custom Quote, Account Sign Up/Login). It was
 * only ever defined in account.css, which only loads on My Account
 * pages (is_account_page()) — every other page using it was relying on
 * a rule that was never actually present in its own stylesheet, so the
 * class silently did nothing there. Confirmed as the root cause of the
 * Get Quote page's "Get My Personalized Quote" button rendering
 * content-width instead of matching its .summary-box, same as
 * Checkout's Place Order button right next to it — belongs in base.css
 * since it's a shared, sitewide utility, not account-specific.
 */
.btn-block {
	display: block;
	width: 100%;
	text-align: center;
}

/*
 * Shared modal pattern — used by the single product page's Size Chart
 * modal (single-product.css) and the cart page's Save/Share Cart
 * modals (cart.css). Common overlay/box/close-button/heading styling
 * lives here so it's not duplicated per page; each consumer sets its
 * own .modal-box max-width (and max-height/overflow, if its content
 * needs scrolling) since the two contexts want genuinely different
 * sizes — a compact form vs. a large size-chart table.
 */
.modal-overlay {
	display: none;
	position: fixed;
	inset: 0;
	background: rgba(0, 0, 0, 0.5);
	z-index: 100;
	align-items: center;
	justify-content: center;
	padding: 20px;
}
.modal-overlay.open {
	display: flex;
}
.modal-box {
	background: var(--bg);
	width: 100%;
	border: 1px solid var(--ink);
	padding: 26px;
	position: relative;
}
.modal-close {
	position: absolute;
	top: 14px;
	right: 16px;
	background: none;
	border: 0;
	font-size: 20px;
	cursor: pointer;
}
.modal-box h3 {
	text-transform: uppercase;
	letter-spacing: 0.03em;
	border-bottom: 2px solid var(--ink);
	padding-bottom: 10px;
	margin-bottom: 16px;
}

/*
 * v88 (2026-09-05, user-reported bug): a modal form's own error (e.g.
 * Save Cart/Save Quote's "you already have a saved cart/quote named X")
 * was falling back to the browser's native window.alert() — an ugly,
 * unstyled system dialog, and the exact class of thing this theme
 * already replaced elsewhere (My Account's delete-confirm modal
 * replaced window.confirm(), see saved-carts.js's own docblock; Save/
 * Share Cart's naming step already replaced window.prompt()/alert()
 * with these same modals). Same shape as single-product.css's
 * .b2b-add-to-cart-message.is-error/.is-success — grayscale only, no
 * color-coding by type, message text carries the meaning.
 */
.b2b-modal-message {
	font-size: 13px;
	margin: 10px 0 0;
	padding: 8px 12px;
	border: 1px solid var(--line);
}
.b2b-modal-message.is-error,
.b2b-modal-message.is-success {
	border-color: var(--ink);
	color: var(--ink);
}

/* ---------------- WooCommerce's own notice classes (success/error/info)
   — these render wherever wc_print_notices()/wc_print_notice() fire
   (cart, checkout, account, single-product "added to cart", etc.), so
   this lives in base.css rather than any one page's stylesheet.
   WooCommerce's own bundled default styles (still loaded — this theme
   has never dequeued them) give these a colored border and icon; this
   overrides that to match the monochrome black/white/grey convention
   used everywhere else in this theme (same treatment as .verify-banner
   in account.css: bordered box, no icon, no color-coding by type). ---- */
.woocommerce-message,
.woocommerce-error,
.woocommerce-info {
	list-style: none;
	/* 2026-09-23 (user request): equal 16px above and below every notice —
	   applied sitewide, not just the "prices changed" notice. A notice that
	   sits right above a .page-header gets that header's own 10px top
	   padding cancelled by the sibling rule after this block, so the
	   visible gap is 16px, not 26px. */
	margin: 16px 0;
	padding: 14px 18px;
	border: 1px solid var(--ink);
	background: var(--bg-soft);
	font-size: 13px;
}
.woocommerce-message li,
.woocommerce-error li,
.woocommerce-info li {
	list-style: none;
	margin: 0;
	padding: 0;
}
.woocommerce-message::before,
.woocommerce-error::before,
.woocommerce-info::before {
	content: none !important;
}
/*
 * v82 (2026-09-04) reported a Saved Carts notice ("Saved cart deleted.")
 * showing a thick BLUE border instead of the intended black one. Fixed
 * in v82 with an explicit black :focus/:focus-visible outline, on the
 * working theory that some element was genuinely receiving browser
 * focus (this theme never defined any :focus style anywhere) and
 * falling through to the browser's native blue ring. CONFIRMED correct
 * by the user's own screenshot after deploying: the border showed
 * black, not blue — but as two visible black lines (the box's own
 * border plus the outline sitting just outside it), not one clean
 * line, and the SAME double-line effect turned out to show on every
 * notice/alert sitewide (e.g. "Last name is a required field."), not
 * just Saved Carts — this rule was never Saved-Carts-specific, it
 * covers every .woocommerce-message/-error/-info on the site.
 *
 * Fix (v83, 2026-09-04, user request): drop the outline entirely and
 * let the existing 2px solid border (set earlier in this same rule
 * block, above) be the only visible line again. Safe to do without
 * losing the screen-reader benefit the focus-move itself provides:
 * these notices are only ever focused PROGRAMMATICALLY (for an
 * assistive-tech announcement) via a tabindex="-1"-style pattern, never
 * reachable by a sighted keyboard user actually pressing Tab — WCAG's
 * focus-visible requirement only applies to elements in the real Tab
 * sequence, so removing the ring here has no accessibility downside,
 * only removes the double-line cosmetic issue.
 */
.woocommerce-message:focus,
.woocommerce-error:focus,
.woocommerce-info:focus,
.woocommerce-message:focus-visible,
.woocommerce-error:focus-visible,
.woocommerce-info:focus-visible {
	outline: none;
}

/* Notice directly above the page title: drop the page header's own 10px top
   padding so the gap to the title equals the 16px gap above the notice. */
.woocommerce-message + .page-header,
.woocommerce-error + .page-header,
.woocommerce-info + .page-header {
	padding-top: 0;
}

/* "Prices changed" notice (2026-09-23) — reuses .woocommerce-info above for
   the box itself; these rules only lay out its heading + per-line list
   (wholesaletheme_print_price_change_notice(), includes/helpers.php). */
/* Border (1px) and 16px spacing come from the shared notice rule above. */
.b2b-price-change-notice ul {
	margin: 8px 0 0;
	padding: 0;
	list-style: none;
}
.b2b-price-change-notice li {
	margin: 0 0 4px;
	padding: 0;
}
.b2b-price-change-notice li:last-child {
	margin-bottom: 0;
}

/* ---------------- Active saved list badge ----------------
   "YOUR QUOTE — [quote name]" / "YOUR CART — [cart name]" style label
   (v80, 2026-09-04, user request) — shown next to the page H1 on View
   Quote and Cart when the visitor is currently working from a saved
   quote/cart (WholesaleTheme_Quote_Cart::get_active_quote_id() /
   WholesaleTheme_Saved_Carts::get_active_cart_id()). Lives in base.css
   since both pages use it. Reset text-transform explicitly since it
   sits inside an uppercase <h1>. */
.active-list-badge {
	display: inline-block;
	vertical-align: middle;
	margin-left: 12px;
	padding: 4px 10px;
	font-size: 11px;
	font-weight: 500;
	letter-spacing: normal;
	text-transform: none;
	color: var(--ink-soft);
	background: var(--bg-soft);
	border: 1px solid var(--line);
	border-radius: 3px;
}

/* ---------------- Cloudflare Turnstile widget spacing ----------------
   Lives in base.css since it appears across several stylesheets' forms
   (Get Custom Quote, My Account login/register) — see
   wholesaletheme_render_turnstile_widget() (includes/helpers.php). The
   widget itself is sized via its own data-size="flexible" attribute
   (fills 100% of this wrapper's width, 300px minimum) — this rule only
   adds the same vertical spacing every other form field on these pages
   already gets before the next element, so it doesn't look bolted on. */
.b2b-turnstile-widget {
	margin: 4px 0 18px;
}

/* ---------------- Brand utility classes ----------------
   Reproduced from docs/brand-tokens.css (2026-09-28) so the documented
   brand motifs are real, usable classes, not just a reference file.
   These read the --wt-* aliases defined in the :root block above, so
   they stay wired to the same Customizer-editable ink/paper colors as
   everything else in this file. Not yet applied anywhere in the theme's
   own markup — available for any template/admin screen that wants
   them. */
.wt-divider {
	border: none;
	border-top: 1px solid var(--wt-color-line);
	margin: 0;
}

.wt-badge {
	display: inline-flex;
	align-items: center;
	gap: 0.5em;
	border: 1px solid var(--wt-color-ink);
	padding: 0.35em 0.75em;
	font-family: var(--wt-font-display);
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: var(--wt-tracking-eyebrow);
	font-size: 0.75rem;
	color: var(--wt-color-ink);
	background: var(--wt-color-paper);
}
.wt-badge--divided {
	padding-left: 0;
}
.wt-badge--divided > .wt-badge__icon {
	padding: 0.35em 0.75em;
	border-right: 1px solid var(--wt-color-ink);
}

.wt-stripe-texture {
	background-image: repeating-linear-gradient(
		115deg,
		var(--wt-color-line) 0,
		var(--wt-color-line) 2px,
		transparent 2px,
		transparent var(--wt-stripe-size)
	);
}
.wt-stripe-texture--on-dark {
	background-image: repeating-linear-gradient(
		115deg,
		var(--wt-color-line-on-dark) 0,
		var(--wt-color-line-on-dark) 2px,
		transparent 2px,
		transparent var(--wt-stripe-size)
	);
}

.wt-image-mat {
	background: var(--wt-color-paper-bright);
}
