/* -----------------------------------------------------------------------------
 * PeptPro Preview3 — Round 5, lane A. Loaded on every route.
 *
 *   R1 — header wordmark: visibly larger, "Pro" in the turquoise brand accent.
 *   R2 — Lab Reports product selector: engraved well, designed disclosure,
 *        brand focus ring, honest availability grouping.
 *
 * R2 lives in this sheet rather than a sheet of its own because this is the one
 * Round 5 file that functions.php enqueues unconditionally, and the Lab Reports
 * route has no Round 5 sheet of its own. Every R2 rule is scoped under
 * .reports-page, so nothing here can reach another route.
 *
 * House rules honoured here:
 *   - only existing tokens and radii (--accent, --accent-bright, --line-strong,
 *     --r-sm/--r-md, --s1..--s7); no new radius, no second accent;
 *   - this theme is DARK ONLY. It ships <meta name="color-scheme" content="dark">
 *     and carries no OS colour-preference media query anywhere. None is added
 *     here: a partial light branch would activate on a light-preferring OS and
 *     break the design, because the meta tag does not stop such a query matching;
 *   - motion is transform/opacity or a short colour settle, 150-260ms, and always
 *     inside a `prefers-reduced-motion: no-preference` guard;
 *   - this sheet loads after style.css and every Round 2-4 sheet, so it wins on
 *     order alone. No !important anywhere below.
 * -------------------------------------------------------------------------- */


/* R1 · Header wordmark ---------------------------------------------------- */
/* Naem: "make the top-right logo/wordmark visibly larger without breaking 375px
   navigation" and "render PeptPro with Pro in the PeptPro turquoise".

   Measured Round 4 baseline on the live site (evidence/header-labreports/
   before-measurements.json): 132.28x40 at 1440/768, and at 375/390 the word was
   not rendered AT ALL — mobile.css collapsed .wordmark to a 48x48 tile and set
   the text span to display:none, so the brand read as a bare glyph on the two
   narrowest breakpoints. Every size below is a strict increase on that baseline,
   and the word is restored at 375/390 because the header has the room: at 375 the
   bar carries 15px gutters, a 48px search button, a 48px cart button and a 48px
   nav toggle, which leaves 201px of free track for a wordmark that measures ~124.
   The measured after-numbers are in after-measurements.json beside the baseline. */

.site-header .wordmark {
	gap: 10px;
	font-size: 29px;
	line-height: 1.25;
	letter-spacing: -.035em;
}

.site-header .wordmark .mark {
	width: 46px;
	height: 46px;
}

/* The brand node is pulled 4px back into the word by style.css. That was right
   while the whole word was one ink; now that "Pro" is itself turquoise, a node
   4px away reads as a bullet stuck to the end of the word. Releasing the negative
   margin lets the flex gap separate it, so it reads as the status node it is. */
.site-header .wordmark .node {
	width: 8px;
	height: 8px;
	margin-left: 0;
}

/* The accent half. Scoped to the class, not to the header, so the same two-tone
   rule is already correct if the footer wordmark is ever given the same markup.
   --accent-bright reads at ~13:1 on the obsidian page, comfortably past AAA. */
.wordmark-pro {
	color: var(--accent-bright);
}

/* One inline run, no wrapping, no shrink surprise: the two tone spans are
   adjacent text nodes so the word is announced once, and the head half must never
   break between "Pept" and "Pro". */
.site-header .wordmark .wordmark-text {
	min-width: 0;
	white-space: nowrap;
}

/* Tablet: the nav is still the drawer here, so the bar is as roomy as desktop
   minus the centred menu. One step down keeps the mark inside the 68px bar. */
@media (max-width: 900px) {
	.site-header .wordmark {
		font-size: 27px;
	}

	.site-header .wordmark .mark {
		width: 44px;
		height: 44px;
	}
}

/* Phone. mobile.css (<=680px) drops the mark to 28px and the type to 17px, and
   round2.css to 34px/18px; both are re-raised here. Sized so the wordmark plus
   the three 48px controls plus the gutters still fit inside 320px, which is
   narrower than any width in the review matrix. */
@media (max-width: 680px) {
	.site-header .wordmark {
		gap: 8px;
		font-size: 22px;
	}

	.site-header .wordmark .mark {
		width: 36px;
		height: 36px;
	}

	.site-header .wordmark .node {
		width: 7px;
		height: 7px;
	}
}

/* <=390px. mobile.css pins .wordmark to a 48x48 tile and hides the text span;
   both are released here so the brand actually reads on an iPhone-class screen.
   `flex: 0 1 auto` plus `min-width: 0` plus the clip below is the belt-and-braces
   guarantee that a longer site title can only ellipsis, never push the nav
   toggle off-screen. The selector outranks mobile.css's
   `.site-header .wordmark > span:not(.node)` on specificity (0,3,2 vs 0,3,1) and
   on order, so no !important is needed. */
@media (max-width: 390px) {
	.site-header a.wordmark {
		flex: 0 1 auto;
		width: auto;
		min-width: 0;
		height: auto;
	}

	.site-header a.wordmark > span.wordmark-text {
		display: block;
		overflow: hidden;
		text-overflow: ellipsis;
	}

	.site-header .wordmark {
		font-size: 21px;
	}

	.site-header .wordmark .mark {
		width: 34px;
		height: 34px;
	}
}

/* A custom logo still wins outright — R1 only re-sizes the fallback wordmark —
   but it is given the same optical presence so an admin upload is not suddenly
   the smallest thing in the bar. */
.site-header .wordmark .custom-logo {
	height: 42px;
	max-width: 190px;
}

@media (max-width: 680px) {
	.site-header .wordmark .custom-logo {
		height: 34px;
		max-width: 132px;
	}
}


/* R2 · Lab Reports product selector --------------------------------------- */
/* Naem: "restyle the product-selection lettering/list to match the professional
   PeptPro design system", preserving keyboard navigation, focus states, mobile
   usability and honest report availability.

   The control stays a native <select>. That is the accessible and mobile-correct
   answer here — it inherits the platform picker, arrow-key and type-ahead
   navigation, and VoiceOver's list semantics for free — so this is a skin, not a
   replacement. Availability honesty is carried by the <optgroup> split in
   lab-reports.php, not by colour: a pending row is never dressed to read as an
   available one. */

.reports-page .reports-filter {
	position: relative;
	border-radius: var(--r-lg);
}

/* Engraved-panel highlight along the top edge. Drawn outside the padding box on
   purpose — no overflow:hidden anywhere in this block, because clipping the
   container would eat the 3px-offset native focus outline of the fields inside. */
.reports-page .reports-filter::before {
	content: "";
	position: absolute;
	top: -1px;
	left: var(--s5);
	right: var(--s5);
	height: 1px;
	pointer-events: none;
	background: linear-gradient(90deg, transparent, var(--accent) 30%, transparent 82%);
	opacity: .45;
}

/* Two equal fields that collapse to one column on their own. `align-items:start`
   keeps both wells on the same baseline even though their hint lines differ in
   length. */
.reports-page .reports-filter-row {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(258px, 1fr));
	align-items: start;
	gap: var(--s4) var(--s5);
}

.reports-page .reports-filter .reports-field {
	display: grid;
	gap: 7px;
	min-width: 0;
	text-transform: none;
	letter-spacing: 0;
}

/* The caption is a real <label for>, and the hint sits OUTSIDE it and is wired
   with aria-describedby instead. Wrapping the hint in the label would fold it
   into the control's accessible name, so the select would announce as
   "Select a product Filters the ledger below. No report file has been uploaded
   yet." — a caption is a name, a hint is a description, and they are separate
   elements here for that reason. `display: block` undoes the `display: grid`
   that pharma-pass.css puts on every label inside .reports-filter. */
.reports-page .reports-filter .reports-field-label {
	display: block;
	color: var(--quiet);
	font: 600 11px/1.4 "Inter Tight", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
	letter-spacing: .09em;
	text-transform: uppercase;
}

.reports-page .reports-filter .reports-field-hint {
	display: block;
	color: var(--muted);
	font: 400 12px/1.45 "Inter Tight", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
	letter-spacing: 0;
	text-transform: none;
}

/* The well: darker than the panel it sits in, with the light catching the top
   inner edge — the same engraved language the rest of the catalogue uses for an
   input surface. */
.reports-page .reports-well {
	position: relative;
	display: block;
	min-width: 0;
	border: 1px solid var(--line-strong);
	border-radius: var(--r-md);
	background: color-mix(in srgb, var(--void) 76%, var(--panel));
	box-shadow: inset 0 1px 2px rgba(0, 0, 0, .55), inset 0 1px 0 rgba(235, 235, 236, .04);
}

.reports-page .reports-well:hover {
	border-color: color-mix(in srgb, var(--accent) 42%, var(--line-strong));
}

/* Focus is carried by the native outline that style.css already draws on the
   control; the well only echoes it on its own edge, so there is exactly one
   focus ring and it is never weaker than Round 4's. :has() is progressive — if a
   browser ignores it the native outline is still the indicator. */
.reports-page .reports-well:has(select:focus-visible),
.reports-page .reports-well:has(input:focus-visible) {
	border-color: var(--accent);
}

.reports-page .reports-filter .reports-well select,
.reports-page .reports-filter .reports-well input[type="search"] {
	width: 100%;
	min-width: 0;
	min-height: 52px;
	margin: 0;
	padding: 0 46px 0 15px;
	-webkit-appearance: none;
	appearance: none;
	border: 0;
	border-radius: var(--r-md);
	background: transparent;
	color: var(--text);
	font-size: 15px;
	font-weight: 500;
	letter-spacing: 0;
	text-transform: none;
}

/* The search glyph leads, the disclosure caret trails — the conventional reading
   for each control, and it keeps the caret clear of Safari's native clear button. */
.reports-page .reports-filter .reports-well-search input[type="search"] {
	padding: 0 15px 0 46px;
}

.reports-page .reports-well select::-ms-expand {
	display: none;
}

/* Platform pickers ignore most option styling on macOS, but Windows and Firefox
   honour it, and an unstyled option list on a dark page is a white flash. */
.reports-page .reports-well select option {
	background: var(--panel);
	color: var(--text);
}

.reports-page .reports-well select optgroup {
	background: var(--panel);
	color: var(--quiet);
	font-weight: 600;
}

.reports-page .reports-well-caret {
	position: absolute;
	top: 50%;
	right: 15px;
	display: grid;
	place-items: center;
	width: 18px;
	height: 18px;
	transform: translateY(-50%);
	pointer-events: none;
	color: var(--accent);
}

.reports-page .reports-well-search .reports-well-caret {
	right: auto;
	left: 15px;
	color: var(--quiet);
}

.reports-page .reports-well-caret svg {
	display: block;
	width: 18px;
	height: 18px;
}

@media (prefers-reduced-motion: no-preference) {
	.reports-page .reports-well {
		transition: border-color 180ms var(--ease);
	}
}

/* The toggle row belongs to the same control block, so it is brought up to the
   same standard here. Round 4 left its checkbox orphaned on the line ABOVE its
   own caption: pharma-pass.css sets `flex-direction: row` on a label that
   `.reports-filter label` had already made a grid, so the declaration was inert
   and the control stacked over its text. Restoring the row is what that rule
   always intended, and it puts the caption back beside the box it labels. */
.reports-page .reports-filter-toggles {
	align-items: center;
	justify-content: space-between;
	gap: var(--s3) var(--s5);
	padding-top: var(--s3);
	border-top: 1px solid var(--line);
}

.reports-page .reports-filter-toggles label {
	display: flex;
	align-items: center;
	gap: 10px;
	min-height: 48px;
	color: var(--muted);
	font: 500 14px/1.4 "Inter Tight", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
	letter-spacing: 0;
	text-transform: none;
	cursor: pointer;
}

/* accent-color keeps the box a native checkbox — native focus, native keyboard,
   native VoiceOver — while tinting it into the brand. */
.reports-page .reports-filter-toggles input[type="checkbox"] {
	flex: 0 0 auto;
	width: 20px;
	height: 20px;
	margin: 0;
	accent-color: var(--accent);
	cursor: pointer;
}

.reports-page .reports-count {
	margin: 0;
	color: var(--muted);
	font-size: 13px;
	font-variant-numeric: tabular-nums;
}

/* Phone: one column, and the well keeps its 52px height so the tap target stays
   past the 48px floor. pharma-pass.css already releases the 240px min-width
   below 680px; the grid track above does the same job at every width. */
@media (max-width: 680px) {
	.reports-page .reports-filter-row {
		grid-template-columns: minmax(0, 1fr);
	}

	.reports-page .reports-filter .reports-well select,
	.reports-page .reports-filter .reports-well input[type="search"] {
		font-size: 16px;
	}
}


/* ===========================================================================
   Round 5 fix pass — anti-slop findings B8 and B9.

   Both corrections live in this sheet because it is the one Round 5 file that
   functions.php enqueues UNCONDITIONALLY, and the control they correct is site
   chrome that renders on every route. Nothing below is scoped to a route.
   ========================================================================= */


/* B8 · the fixed support control must never read as an open live chat ------ */
/* pharma-pass.css (the `@media (max-width: 380px)` block) hides
   `.tg-support-text` and squares the pill down to a `var(--tg-size)` circle.
   What survived at 375 was a bare 52x52 circle carrying a paper-plane glyph and
   `cursor: pointer` — the universal signifier of an OPEN live chat — while the
   one thing on screen that said the channel is NOT open, the "TELEGRAM · SOON"
   label, was exactly what that rule removed. The only disclosure left arrived
   AFTER the tap, as a toast. So the label is the fix, and it is restored at
   every width: this is a pill, never a bare circle.

   Nothing here touches behaviour. It stays a real <button> with its accessible
   name and its explanatory toast, and no `disabled`/`aria-disabled` is added —
   the control still needs to be focusable and to explain itself.
   PEPTPRO_TELEGRAM_HANDLE is still '' and the button still links nowhere; only
   its self-evidence changed.

   WHY THE PILL AND NOT THE "DROP THE FAB BELOW 380" ALTERNATIVE. Measured on
   the live page at 375 with these rules injected: the pill renders 164.3x52 at
   left 196.7 / right 361, leaving 196.7px — 52.5% of the viewport — of free
   horizontal track and 746px of free vertical track. That is the SAME 164.3px
   footprint and the same "Support / TELEGRAM · SOON" content the site already
   ships at 390, so this extends an accepted rendering down two breakpoints
   rather than introducing a new one. Dropping the FAB instead would have left
   every route except the front page with no support affordance at all below
   380, because the inline control that carries the explanatory copy exists only
   in the homepage FAQ card. Occlusion cost, measured by hit-testing the pill's
   footprint at 100px scroll steps down the whole document: on /prepared-
   checkout/ — the only route with form fields — the pill covers ZERO inputs,
   links or buttons at any scroll position, identical to the circle; on the home
   page it transiently crosses two links while scrolling, which is already true
   of the 390 rendering. */

@media (max-width: 380px) {
	.tg-support .tg-support-text {
		display: grid;
	}

	.tg-support {
		width: auto;
		padding: 0 14px 0 12px;
		justify-content: flex-start;
	}
}

/* Safe-area inset. The bottom edge already added env(safe-area-inset-bottom);
   the right edge did not, so on a notched handset held in landscape the pill
   could sit under the rounded corner or the sensor housing and land on whatever
   is beneath it. max() keeps the existing clamp as the floor, so nothing moves
   on a device that reports no inset. */
.tg-support {
	right: max(clamp(14px, 2.4vw, 26px), env(safe-area-inset-right, 0px));
}


/* B9 · TELEGRAM · SOON is metal in BOTH places ---------------------------- */
/* The same `.tg-support-note` rendered in two colours on one page: the fixed
   pill painted it #A7B0BC metal (pharma-pass.css), while the homepage FAQ echo
   painted it #00D4C8 turquoise, because `.r5-tg-pending .tg-support-note` in
   round5-home.css maps it to --accent-text. DESIGN.md's own Round 5 section
   states that turquoise on a commerce surface means "this is real and it is
   yours", which is why a not-yet-live badge is deliberately metal — so the echo
   was contradicting the grammar the round wrote.

   This rule DELIBERATELY OVERRIDES round5-home.css. That sheet is owned by
   another lane and loads AFTER this one, so order cannot carry the correction;
   specificity does. `.r5-tg-slot .r5-tg-pending .tg-support-note` is (0,3,0)
   against that sheet's (0,2,0), and the wrapper is emitted unconditionally by
   peptpro_r5_telegram_cta(). No !important is used or needed. The value is
   --muted, which is what the base .tg-support-note rule already resolves to, so
   this restores the site default rather than inventing a third colour.

   The second selector mirrors the safety net already in round5-home.css: if
   peptpro_telegram_support_button() is ever rewritten so the class rename stops
   matching, the pending note in the slot still resolves to metal. */
.r5-tg-slot .r5-tg-pending .tg-support-note,
.r5-tg-slot .tg-support-pending .tg-support-note {
	color: var(--muted);
}

/* B8 follow-up · superseded, kept as the record of why the control moved -----
   The fixed pill covered the product name at rest on 375/390/430, and the
   routing work below showed `.is-front` could not be trusted to mean "the home
   page" until peptpro_is_real_front() landed. Both are moot now: the control is
   no longer position:fixed and no longer emitted on the front page at all
   (footer.php renders it only when peptpro_is_real_front() is false, because the
   homepage carries the inline .r5-tg instead). No display rule is needed here. */



/* =========================================================================
   BL-1 / B8 second clause · the support control stops floating over content
   ========================================================================= */
/* The independent verifier measured, at scrollY=0 with no scrolling involved:
   /shop/@390 the pill covers 86% of a wishlist button and 37% of a product
   link; /faq/@390 35% of an FAQ summary; /lab-reports/@375 33% of the search
   input. And it is a regression in DEGREE caused by this round: the old 52px
   circle covered ~925px2 (6%) of that input, the honest 164px pill covers
   5071px2 (33%). Making the control truthful made it cover 5.5x more of a form
   field.

   No offset fixes this. The pill is position:fixed at the viewport's bottom
   right, so on any content-dense page it lands on whatever happens to be in
   that corner at rest — a product grid, a search field, an FAQ row. A larger
   `bottom` merely picks a different victim, and the earlier POST-DEPLOY check
   only re-measured the HOMEPAGE hero, which is why the tripled footprint went
   unnoticed on the routes that still carry it.

   So the control stops floating. It is already rendered in the footer markup;
   it now sits in that flow as a deliberate end-of-page support row. That also
   finishes what B8 was actually about — a floating circular widget pinned to
   the corner is the universal signifier of an OPEN live chat, and this channel
   is not open. A labelled row in the footer cannot be mistaken for one, cannot
   cover anything, and needs no safe-area arithmetic.

   Kept: the >=48px target, the full "Support / TELEGRAM · SOON" label at every
   width, the real <button> with its accessible name and explanatory toast, and
   PEPTPRO_TELEGRAM_HANDLE still ''. Only the positioning changed. */
.tg-support {
	position: static;
	display: inline-flex;
	box-shadow: none;
}

/* In the footer's Information column it is a support ENTRY, not a floating
   button that happened to land there. The capsule chrome was the FAB's, and
   keeping it made the control the only pill in a three-column type layout —
   it read as orphaned. Here it aligns to its column, sits on the footer's own
   link rhythm, and keeps a 48px target and the full label. */
.site-footer .tg-support {
	margin-top: var(--s4, 16px);
	padding: 0;
	gap: 8px;
	min-height: 48px;
	border: 0;
	border-radius: 0;
	background: none;
	-webkit-backdrop-filter: none;
	backdrop-filter: none;
	color: #a7b0bc;
	font-size: 13px;
	text-align: left;
}
.site-footer .tg-support svg { width: 18px; height: 18px; }
.site-footer .tg-support:hover { border-color: transparent; transform: none; color: #ebebec; }
.site-footer .tg-support .tg-support-text { display: grid; gap: 1px; }
.site-footer .tg-support-note { font-size: 11px; }
.site-footer .tg-support:focus-visible { outline: 2px solid var(--accent-bright); outline-offset: 3px; }


/* B7 second clause · the lab-reports filter checkbox -----------------------
   B7 was executed as scoped and closed the prepared checkout's four controls,
   but /lab-reports/ carries a fifth: #reportOnlyFiles is still appearance:auto
   with border-width 0 and border-radius 0, so Chromium paints it as a solid
   grey filled square — which reads as ALREADY CHECKED while the ledger below
   it shows all 28 records unfiltered. Same treatment as the checkout's. */
#reportOnlyFiles {
	appearance: none;
	-webkit-appearance: none;
	width: 20px;
	height: 20px;
	margin: 0 10px 0 0;
	flex: 0 0 auto;
	/* #59677C is the boundary the checkout's controls already use and measures
	   3.18:1 on this fill; --line-strong measured 1.67:1, under the 3:1 WCAG
	   1.4.11 asks of a control boundary. */
	border: 1px solid #59677C;
	border-radius: var(--r-sm);
	background: var(--surface);
	display: inline-grid;
	place-content: center;
	cursor: pointer;
}
#reportOnlyFiles::before {
	content: "";
	width: 10px;
	height: 10px;
	transform: scale(0);
	background: var(--accent-bright);
	clip-path: polygon(14% 44%, 0 60%, 40% 100%, 100% 18%, 84% 2%, 38% 68%);
}
#reportOnlyFiles:checked { border-color: var(--accent); }
#reportOnlyFiles:checked::before { transform: scale(1); }
#reportOnlyFiles:focus-visible { outline: 2px solid var(--accent-bright); outline-offset: 3px; }
label[for="reportOnlyFiles"] { display: inline-flex; align-items: center; min-height: 48px; cursor: pointer; }


/* Sticky header · legible where backdrop-filter never composites -----------
   style.css:207 gives .site-header.stuck a 92%-of-page background and leans on
   blur(18px) for the rest. Where the blur is declared but not composited, the
   hero trust-strip text reads THROUGH the nav at 375 and collides with the
   search and cart icons. @supports cannot detect a property that lies, so the
   base background simply carries itself and the blur stays enhancement. */
.site-header.stuck {
	background: color-mix(in srgb, var(--page) 98%, transparent);
}
