/*!
 * The admin control panel's visual language, applied to the storefront.
 *
 * admincp was rebuilt on Tabler in 2026-08 and is the most modern surface we
 * own. This file carries its type, control metrics, lines and shadows across
 * to the public site. It is a layer on top of styles.css rather than edits
 * inside it, for two reasons:
 *
 *   1. It comes off in one line. views/header/view_header.php decides whether
 *      to emit the <link>; delete that block and the site is exactly what it
 *      was, because nothing here is depended on by anything there.
 *   2. The two can be compared on the same page. ?ui=classic turns this off
 *      for the rest of the browsing session, ?ui=modern turns it back on.
 *
 * WHAT THIS DOES NOT TOUCH: colour. The palette moved to the brand style
 * guide and admincp's dark surfaces in the commits before this one and is
 * already shared between the two products. The four border and shadow tokens
 * re-pointed below are the exception, and they are re-pointed at admincp's
 * values rather than new ones.
 *
 * ON THE TYPEFACE. docs/brand-style-guide.md says one typeface, Maven Pro,
 * headlines 800 and body 500-600. That guide opens with "How to make an image
 * that belongs to this brand" and every section under it is about marks,
 * wordmarks, ad sets and the generated kit - it governs imagery, and the
 * generated kit still renders in Maven Pro, unchanged. Interface text is a
 * different problem: it is small, it is read at a glance, and it has to
 * rasterise well on a stranger's screen. admincp settles that with the
 * platform's own UI face, which is already hinted for the display it is on,
 * and it costs no webfont request. The storefront gets the same stack here.
 * The wordmark in the header is artwork and is untouched, so the brand face
 * still appears where the guide asks for it.
 *
 * --font-display is left pointing at Maven Pro. Setting --font-body back to
 * var(--font-display) in the block below returns the whole site to it.
 *
 * 2026-09-20 JD
 */

/* ==========================================================================
   Tokens
   ========================================================================== */
:root {
	/* admincp's --admin-font. The platform UI face on each OS, then the
	   historical fallbacks for anything that matches none of them. */
	--font-body: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;

	/* admincp's --admin-shadow / --admin-shadow-lg. */
	--ui-shadow: 0 2px 4px 0 rgba(31, 41, 55, .04);
	--ui-shadow-lg: 0 8px 24px -4px rgba(31, 41, 55, .12);

	/*
	 * The ring a control shows while it has keyboard focus.
	 *
	 * The indicator itself has to clear 3:1 against what is next to it
	 * (WCAG 2.2 SC 2.4.11), which rules out a soft tinted halo on its own -
	 * Sky at 20% over white is about #cfeefc, 1.2:1, and even solid Sky is
	 * only 2.65:1 on white. So the ring proper is Deep Sky, which measures
	 * 4.35:1 on white and 3.34:1 on the navy footer, and the halo outside it
	 * is decoration rather than the indicator.
	 */
	--ui-focus-ring: 0 0 0 2px #0a7fc2, 0 0 0 5px rgba(10, 127, 194, .25);

	/* Section labels - "FILTER BY LEVEL", "PRICE", "SORT". admincp sets
	   these at 11px/600 with .04em of tracking; the storefront was setting
	   them at 14px/500, which is body size, so they competed with the rows
	   underneath instead of introducing them. */
	--ui-label-size: 11px;
	--ui-label-tracking: .04em;
}

/*
 * Two greys were doing the work of admincp's one pair. --primary-border-color
 * was #e1e7ec and --secondary-border-color #d7d7d7, close enough that they
 * read as the same line until they met - and where they met, as under the
 * navbar, the pair looked like one soft line rather than either of them.
 * These are admincp's --admin-border and --admin-border-strong exactly.
 */
.light-theme {
	--primary-border-color: #e5e7eb;
	--secondary-border-color: #d1d5db;
	--form-border-color: #d1d5db;

	/*
	 * admincp's --admin-text-muted. The storefront's own --text-muted-color is
	 * #9da9b9, which is 2.38:1 on white - under AA, and a label set in it at
	 * 11px would be worse than the 14px one it replaces. This is 4.83:1.
	 *
	 * It is a separate token rather than a correction to --text-muted-color
	 * because that one is also used on the navy footer, where a darker grey
	 * would fail in the other direction. Muted body text is a job for the
	 * pass that goes through the footer with it.
	 */
	--ui-label-color: #6b7280;
}

/*
 * The dark theme has to restate the three border tokens even though it is not
 * changing two of them, and the reason is worth writing down. The body element
 * carries BOTH classes - view_header.php:364 renders class="light-theme
 * dark-theme" when dark is on - so which one wins is decided by document order,
 * not by the element. styles.css puts .dark-theme after .light-theme and gets
 * the right answer. This file is loaded after styles.css, so a .light-theme
 * block here outranks the .dark-theme block there, and a dark page would have
 * taken the light greys above.
 *
 * --secondary-border-color moves off #2e3c51 to #3b4a61 to mirror the
 * weak/strong pair the light theme now has; both are admincp's.
 * --form-border-color keeps #64748b, which is what gets an unfocused input a
 * 3:1 edge against the #111827 page rather than against the card it sits on.
 */
.dark-theme {
	--primary-border-color: #2e3c51;
	--secondary-border-color: #3b4a61;
	--form-border-color: #64748b;

	/* admincp's dark --admin-text-muted: 6.4:1 on the #111827 page. */
	--ui-label-color: rgba(229, 231, 235, .6);

	/* A shadow tuned for a white page disappears on a #111827 one. */

	--ui-shadow: 0 2px 4px 0 rgba(0, 0, 0, .3);
	--ui-shadow-lg: 0 8px 24px -4px rgba(0, 0, 0, .5);
	/* Sky on dark: 6.7:1 on the #111827 page, 5.6:1 on a #1f2937 card. */
	--ui-focus-ring: 0 0 0 2px #0da9ef, 0 0 0 5px rgba(13, 169, 239, .3);
}

/* ==========================================================================
   Base text

   The site set body text in Maven Pro at weight 400. Maven Pro is a geometric
   face with a low x-height and even, thin strokes; at 14px on a light grey it
   has very little on the page to hold on to, which is most of why the site
   read as faint. The stack above lands on a face built for this size, so 400
   is a normal weight again rather than a thin one.

   -webkit-font-smoothing: antialiased was thinning glyphs further on the
   platforms where it applies. It goes back to the platform default.
   ========================================================================== */
body {
	font-family: var(--font-body);
	font-weight: 400;
	-webkit-font-smoothing: auto;
	-moz-osx-font-smoothing: auto;
	text-rendering: optimizeSpeed;
}

/*
 * Headings.
 *
 * Two problems, not one. They were all set at weight 500 - a heading that
 * weighs barely more than the paragraph under it is not doing its job - and
 * the scale ran 36/30/24/20/18/16, which is a print scale. On a screen that
 * makes an h1 a banner and leaves h5 and h6 indistinguishable from body text.
 * This is the same six steps at about 82% and with real weight behind them.
 */
h1, .h1,
h2, .h2,
h3, .h3,
h4, .h4,
h5, .h5,
h6, .h6 {
	font-weight: 600;
	letter-spacing: -.011em;
}

h1, .h1,
h2, .h2 {
	font-weight: 700;
}

h1, .h1 { font-size: 30px; line-height: 1.2; }
h2, .h2 { font-size: 25px; line-height: 1.24; }
h3, .h3 { font-size: 21px; line-height: 1.3; }
h4, .h4 { font-size: 18px; line-height: 1.35; }
h5, .h5 { font-size: 16px; line-height: 1.4; }
h6, .h6 { font-size: 14px; line-height: 1.45; }

@media (max-width: 767.98px) {
	h1, .h1 { font-size: 26px; }
	h2, .h2 { font-size: 22px; }
	h3, .h3 { font-size: 19px; }
}

/*
 * The band at the top of a content page sets its own heading at 24px and
 * font-weight: normal (styles.css:9088), which is more specific than the
 * element rules above, so those pages would have kept a heading that weighs
 * the same as the paragraph under it. This is the h2 step, which is what a
 * page title is.
 */
.page-title h1,
.page-title h2,
.page-title h3 {
	font-size: 25px;
	font-weight: 700;
	letter-spacing: -.011em;
}

@media (max-width: 767.98px) {
	.page-title h1,
	.page-title h2,
	.page-title h3 {
		font-size: 22px;
	}
}

/*
 * Muted text was being set at weight 300 with a line-height equal to its own
 * font-size. No 300 face was ever loaded, so the weight did nothing but leave
 * the intent on record; the leading was the visible half of it, and it packed
 * descenders into the line below. Both revert to the body's.
 */
.text-muted,
.text-muted-less {
	font-weight: inherit;
	line-height: 1.5;
}

/* ==========================================================================
   Section labels

   admincp's pattern: small, semibold, tracked out, muted, and clearly a label
   rather than a heading.
   ========================================================================== */
.widget-title {
	margin-bottom: 12px;
	padding-bottom: 8px;
	color: var(--ui-label-color);
	font-size: var(--ui-label-size);
	font-weight: 600;
	letter-spacing: var(--ui-label-tracking);
	line-height: 16px;
	border-bottom: 1px solid var(--primary-border-color);
}

/* ==========================================================================
   Buttons

   Four changes, and the first is the one that matters.

   ALL CAPS. Every button on the site was uppercased in CSS with .07em of
   tracking on top. The style guide is explicit - "CTA button: Sentence case,
   never ALL CAPS" - and the markup was sentence case all along ("Order Now",
   "Sign In", "Join"), so this is text-transform doing it, and turning it off
   is the whole fix. Caps at 12px also cost the reader the word shape they
   normally recognise a label by.

   transform: translateZ(0). Promotes every button to its own compositor
   layer. A composited layer whose position lands on a fractional device pixel
   rasterises its text off the pixel grid, which is a soft-edged label on any
   display that is not exactly 1x - and a layer per button, on a page with
   forty of them, for no drawing that needs one.

   transition: all 0.4s. Four hundred milliseconds on every animatable
   property, so a hover took most of half a second to arrive and dragged
   layout properties through the compositor on the way. admincp transitions
   the two things that actually change, over 0.12s.

   Focus. There was no focus style beyond the browser's, and .btn:focus was
   caught up in a malformed selector further up styles.css, so keyboard users
   had nothing. :focus-visible means the ring appears for the keyboard and
   not for the mouse.
   ========================================================================== */
.btn {
	font-family: var(--font-body);
	font-weight: 500;
	text-transform: none;
	letter-spacing: 0;
	-webkit-transform: none;
	transform: none;
	transition: background-color .12s ease, border-color .12s ease, color .12s ease, box-shadow .12s ease;
}

.btn-sm {
	font-size: 13px;
}

.btn:focus-visible,
.btn:focus-visible:active {
	outline: none;
	box-shadow: var(--ui-focus-ring);
}

/*
 * Three things that look like buttons without carrying .btn: the two disabled
 * variants (the rating and helpful controls) and iziToast's action buttons.
 * Each is its own copy of the .btn declaration block, caps, tracking, layer
 * promotion and all, so leaving them out would have put two button styles on
 * the same page.
 */
.btn-link-primary-disabled,
.btn-success-disabled,
.iziToast > .iziToast-body .iziToast-buttons > button {
	text-transform: none;
	letter-spacing: 0;
	-webkit-transform: none;
	transform: none;
}

/* ==========================================================================
   Form controls

   The height stays at 44px. It is generous for a desktop form but it is also
   a comfortable touch target, and the mobile pass that follows this one wants
   every target at 44px or more, so shrinking it here would be work to undo.
   What changes is the inside: the text was sitting on a 3px bottom pad that
   pushed it off centre, and there was no focus ring.
   ========================================================================== */
.form-control {
	font-family: var(--font-body);
	padding: 0 12px;
}

textarea.form-control {
	padding: 10px 12px;
}

/* styles.css:2181 sets box-shadow: none !important on this same selector, so
   the ring has to carry !important to reach the control at all. */
.form-control:focus {
	border-color: var(--primary-color);
	box-shadow: var(--ui-focus-ring) !important;
}

label,
.form-label {
	font-weight: 500;
}

/* ==========================================================================
   Surfaces

   admincp draws a card as a flat panel: one hairline border, a 6px radius and
   a shadow you notice only when it is missing. The storefront was drawing
   .card with a 12px-blur shadow at 0.75rem offset, which is a drop shadow
   from a different decade, and no border at all on the light theme.
   ========================================================================== */
.card {
	border: 1px solid var(--primary-border-color);
	box-shadow: var(--ui-shadow);
}

.card:hover {
	box-shadow: var(--ui-shadow-lg);
}

.dropdown-menu,
.toolbar-dropdown {
	border: 1px solid var(--primary-border-color);
	border-radius: var(--radius);
	box-shadow: var(--ui-shadow-lg);
}

/* ==========================================================================
   Navigation

   The main nav was uppercased and tracked the same way the buttons were, and
   for the same reason it reads better as written. The markup is "Home",
   "Community", "Sell A Service".
   ========================================================================== */
.site-menu > ul > li > a {
	font-weight: 500;
	text-transform: none;
	letter-spacing: 0;
}

/*
 * And the same labels in the mobile drawer, which keeps its own copy at
 * styles.css:253 with .05em of tracking. Without this, Home and Community
 * are sentence case on a desktop and caps on a phone. A media query adds no
 * specificity, so this reaches inside the one that rule lives in.
 */
.offcanvas-menu ul li a {
	text-transform: none;
	letter-spacing: 0;
}

/*
 * The category strip.
 *
 * It was laid out as a table: .sub-nav display:table with each item a
 * table-cell. A table row gives every cell the same width regardless of what
 * is in it, so "Programming" got as much room as "Onsite SEO & Research" and
 * the gaps between labels came out different every time - the strip looked
 * unevenly spaced because it was. Flex lays them out at the width of their
 * own text with one gap between.
 *
 * The labels were also set at weight 200. No 200 face was ever loaded, so
 * they rendered at 400, the lightest weight there was - the strip was asking
 * to be the faintest thing on the page and getting most of its wish.
 *
 * This also clears the way for the popout menu: a table-cell cannot be a
 * positioning context for a submenu, and display:block li can.
 */
.sub-menu-nav {
	display: flex;
	align-items: center;
}

.sub-nav {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 4px;
	height: auto;
	min-height: 0;
	margin-top: 0 !important;
	padding: 0 4px;
}

.sub-nav li {
	display: block;
	position: relative;

	/* A flex item will not shrink below its content by default, so eight
	   labels long enough to exceed the row would push it past the viewport
	   instead of giving way. They fit today at 1071px with about 60px to
	   spare, but the labels are the eight busiest categories and come out of
	   the database, so that is a fact about this week's data rather than
	   about the layout. This and the ellipsis below make it a property of
	   the layout. */
	min-width: 0;
}

/*
 * .site-menu ul > li > a is (0,1,3) and would otherwise keep its 15px of
 * padding and its 300ms transition here, because the strip renders inside
 * .site-menu. Naming .sub-nav makes this (0,2,2), which wins on class count.
 */
.site-menu .sub-nav li a {
	display: block;
	padding: 4px 10px;
	line-height: 20px;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
	transition: color .12s ease;
}

/* ==========================================================================
   Tables
   ========================================================================== */
.table th {
	font-size: 12px;
	font-weight: 600;
	letter-spacing: var(--ui-label-tracking);
	text-transform: uppercase;
	color: var(--ui-label-color);
}

/* ==========================================================================
   Alerts

   Kept at their own colours; what changes is that they stop being shouty
   blocks with a heavy radius and become the flat, bordered notices admincp
   uses.
   ========================================================================== */
.alert {
	border-radius: var(--radius);
	font-size: 14px;
	box-shadow: none;
}

.alert strong,
.alert .alert-heading {
	font-weight: 600;
}
