/* =========================================================================
   VEIL COMPONENTS — approved component library (System §6)
   CSS ported from the live approved builds (sv-/st-/kb- prefixed page code).
   Do NOT restyle these per page; page css may only compose/position them.
   ========================================================================= */

/* ----- Chips (pills) ----- */
.veil-chips { display: flex; flex-wrap: wrap; gap: 7px; }
.veil-chip {
	display: inline-block;
	background: var(--veil-sage);
	border: 1px solid var(--veil-chip-border);
	color: var(--veil-chip-text);
	border-radius: 999px;
	font-weight: 700;
	font-size: 11px;
	letter-spacing: .6px;
	padding: 5px 11px;
	text-transform: uppercase;
}
.veil-on-dark .veil-chip {
	background: transparent;
	border: 1.3px solid rgba(127, 201, 162, .40);
	color: #d7f2e2;
	padding: 6px 12px;
}

/* ----- Veil light-line (brand detail; max ONE per surface) ----- */
.veil-line {
	position: absolute;
	top: 0; bottom: 0;
	width: 1px;
	background: linear-gradient(rgba(127,201,162,0), rgba(127,201,162,.4), rgba(127,201,162,0));
	pointer-events: none;
}

/* ----- Ghost numeral / letter (one per page max; hidden ≤960px) ----- */
.veil-ghost {
	position: absolute;
	font-family: var(--veil-font-display);
	font-weight: 800;
	line-height: 1;
	pointer-events: none;
	user-select: none;
}
.veil-ghost--light { color: rgba(8, 64, 38, .045); }   /* on cream (Services "06") */
.veil-ghost--dark  { color: rgba(127, 201, 162, .06); } /* on dark (Story "V") */
@media (max-width: 960px) { .veil-ghost { display: none; } }

/* ----- Stat card (white card, accent left edge, Source Serif 4 number) ----- */
.veil-stat {
	background: var(--veil-white);
	border: 1px solid var(--veil-hairline);
	border-radius: var(--veil-radius-card);
	padding: 24px 26px;
	position: relative;
	overflow: hidden;
}
.veil-stat::before {
	content: "";
	position: absolute; top: 0; left: 0; bottom: 0;
	width: 4px; background: var(--veil-accent);
}
.veil-stat .n {
	font-family: var(--veil-font-display);
	font-weight: 700; font-size: 40px;
	color: var(--veil-accent-deep); line-height: 1.1;
}
.veil-stat p { font-size: var(--veil-small); color: var(--veil-muted); line-height: 1.5; margin: 4px 0 0; }

/* ----- Proof band (full-width dark strip of 3–4 cells) ----- */
.veil-proof { background: var(--veil-black-green); color: #fff; display: grid; grid-template-columns: repeat(4, 1fr); }
.veil-proof .cell { padding: 30px 40px; border-right: 1px solid rgba(127, 201, 162, .16); }
.veil-proof .cell:last-child { border-right: none; }
.veil-proof .n { font-family: var(--veil-font-display); font-weight: 600; font-size: 40px; color: var(--veil-accent); line-height: 1; }
.veil-proof .l { font-size: 12.5px; color: #aecdbb; margin-top: 8px; line-height: 1.45; font-weight: 600; }
@media (max-width: 1000px) {
	.veil-proof { grid-template-columns: 1fr 1fr; }
	.veil-proof .cell { border-bottom: 1px solid rgba(127, 201, 162, .16); }
}
@media (max-width: 760px) { .veil-proof { grid-template-columns: 1fr; } }

/* ----- Pull quote ----- */
.veil-pullquote {
	font-family: var(--veil-font-display);
	font-style: normal;
	font-weight: 400;
	font-size: 21px;
	color: var(--veil-accent-deep);
	line-height: 1.65;
	border-left: 3px solid var(--veil-accent);
	padding-left: 18px;
	margin: 0;
}
.veil-on-dark .veil-pullquote { color: #eafff4; }

/* ----- Drop cap lead paragraph ----- */
.veil-lead:first-letter {
	font-family: var(--veil-font-display);
	font-size: 64px; font-weight: 700;
	float: left; line-height: .84;
	padding-right: 12px;
	color: var(--veil-accent-deep);
}

/* ----- Creed band (dark rounded panel, 3-col numbered list) ----- */
.veil-creed {
	background: var(--veil-dark-card);
	border-radius: 20px;
	color: #fff;
	padding: 52px 54px;
	position: relative;
	overflow: hidden;
}
.veil-creed .grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 36px; }
.veil-creed .item { border-top: 2px solid rgba(127, 201, 162, .35); padding-top: 14px; }
.veil-creed .item .k { font-family: var(--veil-font-display); font-weight: 700; color: var(--veil-accent); font-size: 17px; margin-right: 8px; }
.veil-creed .item b { font-size: 15.5px; color: #fff; }
.veil-creed .item p { color: var(--veil-dark-body-2); font-size: var(--veil-small); line-height: 1.55; margin: 6px 0 0; }
@media (max-width: 960px) { .veil-creed { padding: 38px 28px; } .veil-creed .grid { grid-template-columns: 1fr; gap: 24px; } }

/* ----- Vertical timeline (Bio signature — do not reuse elsewhere, System §7) ----- */
.veil-vtl { position: relative; }
.veil-vtl::before {
	content: "";
	position: absolute; left: calc(50% - 1px); top: 6px; bottom: 6px;
	width: 2px;
	background: linear-gradient(var(--veil-accent), rgba(52, 166, 95, .18));
}
.veil-vtl .entry { position: relative; display: grid; grid-template-columns: 1fr 1fr; margin-bottom: 26px; }
.veil-vtl .card {
	background: var(--veil-white);
	border: 1px solid var(--veil-hairline);
	border-radius: 14px;
	padding: 20px 22px;
	box-shadow: 0 14px 30px rgba(7, 23, 18, .07);
	max-width: 370px;
}
.veil-vtl .era { font-weight: 800; font-size: 11px; letter-spacing: 1.6px; color: var(--veil-accent-deep); text-transform: uppercase; margin-bottom: 6px; }
.veil-vtl .card p { font-size: 14px; line-height: 1.6; color: var(--veil-muted); margin: 0; }
.veil-vtl .node {
	position: absolute; left: calc(50% - 11px); top: 24px;
	width: 22px; height: 22px; border-radius: 50%;
	background: var(--veil-accent);
	border: 4px solid var(--veil-cream);
	box-shadow: 0 0 0 2px var(--veil-accent);
}
.veil-vtl .entry.l .card { justify-self: end; margin-right: 44px; text-align: right; }
.veil-vtl .entry.r .card { grid-column: 2; justify-self: start; margin-left: 44px; }
.veil-vtl .entry.dark .card { background: var(--veil-dark-card); border: none; color: #fff; }
.veil-vtl .entry.dark h3 { color: #fff; }
.veil-vtl .entry.dark .card p { color: var(--veil-dark-body); }
.veil-vtl .entry.dark .era { color: var(--veil-mist); }
@media (max-width: 760px) {
	.veil-vtl::before { left: 10px; }
	.veil-vtl .entry { grid-template-columns: 1fr; }
	.veil-vtl .node { left: 0; }
	.veil-vtl .entry.l .card, .veil-vtl .entry.r .card { grid-column: 1; justify-self: stretch; margin: 0 0 0 36px; text-align: left; max-width: none; }
}

/* ----- Horizontal path timeline (Story signature) ----- */
.veil-path { position: relative; display: grid; grid-template-columns: repeat(4, 1fr); gap: 30px; }
.veil-path::before {
	content: "";
	position: absolute; top: 9px; left: 4%; right: 4%;
	height: 2px;
	background: linear-gradient(90deg, var(--veil-accent), rgba(52, 166, 95, .12));
}
.veil-path .stop { position: relative; padding-top: 30px; }
.veil-path .stop::after {
	content: "";
	position: absolute; top: 2px; left: 0;
	width: 16px; height: 16px; border-radius: 50%;
	background: var(--veil-cream);
	border: 3px solid var(--veil-accent);
}
.veil-path .yr { font-family: var(--veil-font-display); font-weight: 700; font-size: 30px; color: var(--veil-accent-deep); }
.veil-path .stop p { font-size: var(--veil-small); line-height: 1.55; color: var(--veil-muted); margin: 6px 0 0; }
@media (max-width: 960px) { .veil-path { grid-template-columns: 1fr; gap: 34px; } .veil-path::before { display: none; } }

/* ----- Portrait card (Story signature: white frame, caption, badges) ----- */
.veil-portrait {
	background: var(--veil-white);
	border-radius: var(--veil-radius-surface);
	padding: 14px;
	box-shadow: var(--veil-shadow-feature);
	border: 1px solid var(--veil-hairline);
}
.veil-portrait img { display: block; width: 100%; height: 470px; object-fit: cover; object-position: center top; border-radius: 12px; }
.veil-portrait .cap { padding: 16px 12px 8px; font-size: 13px; color: var(--veil-muted); line-height: 1.5; }
.veil-portrait .cap b { color: var(--veil-ink); display: block; font-size: 14.5px; margin-bottom: 3px; }
.veil-portrait .badges { padding: 4px 12px 10px; }

/* ----- FAQ accordion (native details/summary; h3 inside summary for SEO) ----- */
.veil-faq details { border: 1px solid var(--veil-hairline); border-radius: 12px; background: var(--veil-white); margin-bottom: 12px; }
.veil-faq summary { cursor: pointer; padding: 18px 22px; list-style: none; }
.veil-faq summary::-webkit-details-marker { display: none; }
.veil-faq summary h3 {
	display: flex; justify-content: space-between; align-items: center; width: 100%;
	font-size: 17px; font-weight: 700; margin: 0;
}
/* B-10/B-35 — ONE FAQ markup dialect, ONE indicator, owned by the markup.
 *
 * History, kept because it bit twice: the component used to draw the
 * indicator as a ::after pseudo-element while the six shipped FAQ patterns
 * carried their own <span class="veil-ic">+</span> — so shipped pages showed
 * two indicators and pages/dossier.css grew an override to blank the extra
 * one, which itself shipped incomplete (one "+" closed, two "×" open, all six
 * pages, found 2026-08-14 by the owner's team and a mobile audit
 * independently). The interim fix guarded the ::after with :not(:has(...)).
 * B-35 (2026-08-16) removed the need: patterns/faq-accordion.php — the only
 * markup that lacked its own indicator, registered but on zero live pages —
 * was rewritten onto the shipped dialect. With every .veil-faq item carrying
 * its own .veil-ic, the ::after rules and their :has() dependency are gone.
 * If a NEW FAQ pattern is ever written, it must include the .veil-ic span;
 * nothing will draw an indicator for it otherwise.
 *
 * The .veil-ic rules make the component complete on its own. Today .veil-faq
 * only renders on the six pages that also load dossier.css, whose identical
 * selectors (same specificity, later in the cascade) keep winning — measured
 * inert, 0px change on all six. Without this, a .veil-faq placed outside the
 * dossier enqueue list gets an unstyled "+" with no rotate (measured on
 * /services/: rgb(8,64,38), transform none).
 * #2f9e44 is kept as a literal rather than mapped to --veil-accent (#34a65f)
 * so such a page renders the same green as the six approved ones; dossier.css
 * keeps the literal for the same verbatim-port reason. */
.veil-faq .veil-ic { color: #2f9e44; font-size: 26px; line-height: 1; transition: transform .25s; flex: none; }
.veil-faq details[open] .veil-ic { transform: rotate(45deg); }
/* .veil-a joined this rule with B-35: the scaffold's answers now use the
 * shipped class, and outside the dossier pages nothing else would pad them.
 * On dossier pages the page file's own .veil-a rules still win on order. */
.veil-faq .a, .veil-faq .veil-a { padding: 0 22px 18px; color: var(--veil-muted); font-size: 15px; line-height: 1.65; }

/* ----- Glass caption plate (over photos) ----- */
.veil-plate {
	background: rgba(5, 15, 10, .55);
	border: 1px solid rgba(127, 201, 162, .28);
	border-radius: 12px;
	padding: 14px 18px;
	backdrop-filter: blur(3px);
}
.veil-plate b { color: #fff; font-family: var(--veil-font-display); font-weight: 700; font-size: 16px; display: block; }
.veil-plate span { color: var(--veil-mist); font-size: 12px; font-weight: 700; }

/* ----- Dark dossier card (Bio right rail) ----- */
.veil-dossier-card {
	background: radial-gradient(520px 340px at 110% -10%, rgba(52,178,102,.16), transparent 55%), linear-gradient(155deg, var(--veil-deep-forest), var(--veil-black-green));
	border-radius: var(--veil-radius-surface);
	padding: 30px 30px 28px;
	color: #fff;
	box-shadow: var(--veil-shadow-dark-card);
	overflow: hidden;
}
.veil-dossier-card .lab {
	font-weight: 800; font-size: 10.5px; letter-spacing: 1.8px;
	color: var(--veil-mist); text-transform: uppercase; margin: 0 0 12px;
}
.veil-dossier-card .fact {
	display: flex; justify-content: space-between;
	font-size: var(--veil-small); padding: 9px 0;
	border-bottom: 1px solid rgba(127, 201, 162, .14);
	color: var(--veil-dark-body-2);
}
.veil-dossier-card .fact b { color: #fff; }

/* -------------------------------------------------------------------------
   CLOSING CTA BAND (.brf-cta) + its wrap (.brf-wrap) — SHARED COMPONENT.
   Promoted here verbatim from pages/briefing.css (THEME-22, the approved
   original) during the pre-deploy hygiene pass. Identical copies previously
   also lived in pages/remaining.css and pages/story.css (THEME-42) and have
   been deleted from all three page stylesheets; components.css is enqueued
   globally (inc/veil-design-system.php: veil-components, before veil-heroes
   and every pages/*.css), so every consumer still receives these rules with
   the same specificity (0,1,0) and no conflicting selector exists later in
   the cascade. Declarations are byte-identical to the approved original —
   zero visual change intended. Consumers: the four briefing slugs, the About
   hub, the Industries hub and Our Story.
   ---------------------------------------------------------------------- */
.brf-wrap{max-width:1180px;margin:0 auto;padding:0 40px}
.brf-cta{position:relative;width:100vw;margin-left:calc(50% - 50vw);background:var(--veil-dark-surface);padding:62px 0;text-align:center;color:var(--veil-cream);overflow:hidden}
.brf-cta h2{font-family:var(--veil-font-display);font-weight:600;font-size:30px;margin:0 0 8px;color:var(--veil-cream)}
.brf-cta p{color:var(--veil-dark-body);max-width:560px;margin:0 auto 20px;font-size:16px}
.brf-cta a{display:inline-block;background:var(--veil-accent);color:var(--veil-on-accent);font-family:var(--veil-font-body);font-weight:800;font-size:15px;padding:15px 28px;border-radius:10px;text-decoration:none}
@media(max-width:820px){
	.brf-wrap{padding:0 22px}
}

/* =========================================================================
   WCAG-05 · SC 1.4.11 (Non-text Contrast, AA) — BACK-TO-TOP CONTROL
   -------------------------------------------------------------------------
   WCAG-04 §7c flagged that the Blocksy Customizer palette still holds
   #39A751 as palette colour 1 and that it "still feeds button fills, the
   back-to-top control and the form-field focus border". Measured at rendered
   pixels, ONE of those three is real and it is this control:

     .ct-back-to-top computes  background: rgb(57,167,81)  (= palette 1, via
     --top-button-background-color) and, because it is position:fixed, it
     floats over whatever happens to be behind it. Sampled at six scroll
     positions on all 25 published URLs (133 painted samples):

       #39a751 on cream #fffaf1 ....  2.96:1   FAIL   68 samples
       #39a751 on the dark bands ...  3.85 - 6.25:1   pass  65 samples

   The control is `display:none` until the page is scrolled, which is why a
   rest-state probe reports zero palette-green consumers. That false absence
   was caught by re-probing in the scrolled state.

   Because the control is fixed, a conforming fill must clear 3:1 against BOTH
   extremes it can overlap — the cream canvas AND the near-black dark bands.
   Solving the two constraints gives a relative-luminance window of
   0.1213 <= L <= 0.2856. Of the existing Veil tokens only ONE lands in it:

     --veil-accent-em  #2f9d59  L = 0.2541   ->  3.31:1 cream / 3.45:1 white
                                                 3.06:1 sage  / 3.43:1 ink
                                                 5.33:1 on #071712
     --veil-accent      #34a65f  L = 0.2883  ->  2.98:1 cream   (out of window)
     --veil-accent-deep #0a5c36  L = 0.0799  ->  2.27:1 on dark (out of window)

   So --veil-accent-em it is. NO NEW BRAND COLOUR is introduced, and the
   change is a slight deepening of an almost identical green.

   THE :hover STATE IS DELIBERATELY NOT TOUCHED, and the reason is a false
   finding this task caught in itself. Reading Blocksy's stylesheet alone says
     .ct-back-to-top:hover { background: var(--top-button-background-hover-color,
                                          var(--theme-palette-color-4)) }
   and palette colour 4 is #fff — which would be a white button on the cream
   canvas at 1.04:1, a total loss of boundary. That is a SOURCE-DERIVED claim
   and MEASUREMENT REFUTES IT: Blocksy's own global.css sets the hover variable
   to palette colour 2, so the hovered control actually paints
       #2f9946 on cream #fffaf1 .... 3.50:1   pass   (68 samples)
       #2f9946 on the dark bands ... 4.73 - 5.28:1   pass
   It conforms, so per the order it is left alone. Only the resting fill was
   failing and only the resting fill is changed.

   The chevron glyph is white and is the only thing identifying the control's
   purpose, so it is a meaningful graphic under SC 1.4.11:
     #fff on #39a751 .... 3.08:1  (was, marginal)
     #fff on #2f9d59 .... 3.45:1  (now — improved as a side effect)

   NO border, ring or shadow is added. The resting fill alone clears 3:1
   against every surface the control can float over, so a hairline would be an
   unrequested visual change to an approved composition.

   CASCADE NOTE — why this sets Blocksy's VARIABLES rather than `background`.
   Blocksy's own `back-to-top.min.css` is enqueued AFTER the child theme's
   components.css, and it declares
       .ct-back-to-top { background: var(--top-button-background-color, …) }
   at specificity (0,1,0). A plain `.ct-back-to-top { background: … }` here is
   therefore LOST to source order — verified at runtime, the control still
   computed rgb(57,167,81) with that rule in place. Overriding the variable at
   (0,1,1) instead means Blocksy's own declaration consumes the Veil value, so
   nothing has to out-specify the parent theme's shorthand.
   ------------------------------------------------------------------------- */
body .ct-back-to-top {
	--top-button-background-color: var(--veil-accent-em);
}

/* ----- Content row (1200/32 measure) — B-11 -------------------------------
 * Promoted verbatim out of pages/dossier.css (THEME-12 addition #2), where it
 * was added ad hoc because "no CSS existed for this". A generic row container
 * is a component, not a page concern, and a page file must not be the only
 * place a shared measure is defined.
 * NOT folded into .veil-wrap: that is --veil-max/--veil-gutter = 1280px/40px.
 * This is the 1200px/32px dossier measure (.veil-lc .in, .veil-fw .in, and the
 * THEME-36 restoration in base.css) and folding would change the metrics.
 * Measured on production 2026-08-14: .veil-content-row matches ZERO elements on
 * all 22 sitemap pages (probe positive-controlled by injecting one). It now
 * survives only in archive/{backup-drafts,revisions}-2026-08-04 — the pre-v2
 * post_content THEME-14 replaced. Kept rather than deleted so a restored
 * revision still lays out; deletion is an owner call, not a refactor. */
.veil-content-row { max-width: 1200px; margin: 0 auto; padding: 0 32px 30px; }
.veil-content-row:last-child { padding-bottom: 0; }

/* =========================================================================
   THEME-45 (2026-08-17) — CRAFT POLISH, component half (see base.css)
   ========================================================================= */

/* --- A3. FAQ summary hover. 39 <summary> controls carried cursor:pointer
   with no visual response at all — the pointer promised something the
   design never delivered. --- */
.veil-faq details { transition: border-color var(--veil-ease), box-shadow var(--veil-ease); }
.veil-faq summary { transition: background var(--veil-ease); }
.veil-faq summary:hover { background: var(--veil-sage); }
.veil-faq details:hover { border-color: var(--veil-chip-border); }
.veil-faq summary:hover .veil-ic { color: var(--veil-accent-deep); }

/* --- A4. Card-level hover. bio.css, briefing.css, remaining.css and
   story.css had zero hover rules between them; only the inner <a> faded via
   THEME-42, so the card itself was inert under the cursor. components.css is
   loaded globally, so one block covers all four page families.
   Class list measured against the live DOM on 6 pages (2026-08-17) rather
   than taken from the stylesheets: .brf-card and .dv2-card render zero times
   anywhere and are omitted. The card classes that actually exist and lacked a
   hover are .vw-card (home) and .fsx-stats (finserv); .sv5-card (services)
   and .hubcard (about) are real and included. .vb-tile and .veil-rcard
   already have bespoke hovers (home.css:143, dossier.css:26) and are
   deliberately left alone so this block cannot flatten them.
   Classes are DOUBLED (.x.x) to reach (0,3,0): pages/services.css:57
   declares .sv5-card.white{box-shadow:...} at (0,2,0), which ties the
   undoubled :hover selector and wins on source order because pages/*.css
   is enqueued after components.css. Measured: the lift applied but the
   layered shadow did not. Same escape THEME-41 uses for the bleed. --- */
.fsx-stats, .sv5-card, .hubcard {
	transition: border-color var(--veil-ease), box-shadow var(--veil-ease), transform var(--veil-ease);
}
.fsx-stats.fsx-stats:hover,
.sv5-card.sv5-card:hover, .hubcard.hubcard:hover {
	border-color: var(--veil-chip-border);
	box-shadow: var(--veil-shadow-card);
	transform: translateY(-2px);
}
@media (prefers-reduced-motion: reduce) {
	.fsx-stats:hover,
	.sv5-card:hover, .hubcard:hover { transform: none; }
}

/* --- THEME-45 A9. Branded 404 (inc/veil-404.php). Composes existing
   components — .veil-eyebrow, .veil-rule, .veil-btn — and adds only the
   layout the stock Blocksy 404 never had. The anchors carry an explicit
   .veil-404-link class so base.css's `.veil-scope a:not([class])` underline
   rule (0,2,1) stops matching them — measured: without it the links render
   underlined in --veil-link, which is wrong for a card-style nav list. --- */
.veil-404 { padding: clamp(56px, 8vw, 120px) var(--veil-gutter); background: var(--veil-cream); }
.veil-404-in { max-width: 720px; margin-inline: auto; }
.veil-404 h1 { font-size: clamp(34px, 4.2vw, 48px); line-height: 1.1; margin: 0 0 22px; }
.veil-404-lead { color: var(--veil-muted); max-width: 52ch; margin: 0 0 40px; }
.veil-404-list { list-style: none; margin: 0 0 40px; padding: 0; border-top: 1px solid var(--veil-hairline); }
.veil-404-list li { border-bottom: 1px solid var(--veil-hairline); }
.veil-404-list a.veil-404-link {
	display: block;
	padding: 20px 0;
	text-decoration: none;
	transition: background var(--veil-ease), padding-inline-start var(--veil-ease);
}
.veil-404-list a.veil-404-link:hover { background: var(--veil-sage); padding-inline-start: 12px; }
.veil-404-label { display: block; font-weight: 700; color: var(--veil-ink); margin-bottom: 4px; }
.veil-404-desc { display: block; font-size: 15px; color: var(--veil-muted); }
@media (prefers-reduced-motion: reduce) {
	.veil-404-list a.veil-404-link:hover { padding-inline-start: 0; }
}

/* =========================================================================
   THEME-46 (2026-08-17) — MOBILE CORRECTNESS (Bucket B, B7 mechanical half)
   Three measured defects at 390px, confirmed on production before changing
   anything. Selectors are DOUBLED (.x.x) because pages/*.css and footer.css
   are enqueued after components.css and would otherwise win the tie.
   Scoped to <=600px (cards/stats) and <=760px (footer) so no desktop or
   tablet rendering is touched.
   ========================================================================= */

@media (max-width: 600px) {
	/* B7-a. Home stat rail. pages/home.css turns .vh-rail into a 3-across
	   flex at <=900px and never revisits it, so at 390px each stat gets
	   ~78px — a measured 11.9ch measure, the narrowest text on the site.
	   Stacking restores a full-width line per stat. */
	.vh-rail.vh-rail {
		flex-direction: column;
		gap: 20px;
	}

	/* B7-b. Services cards keep their desktop padding (44px 40px 38px) at
	   every width. Inside an already-inset card at 390px that leaves ~159px
	   of text — a measured 20.6ch. Trimming the inline padding returns
	   roughly 32px of measure per side. */
	.sv5-card.sv5-card {
		padding: 30px 24px 26px;
		min-height: 0;
	}
}

@media (max-width: 760px) {
	/* B7-c. Footer tap targets. Measured: all 20 footer links on every page
	   render 19-24px tall, against the 44px touch floor (WCAG 2.5.8 asks 24;
	   44 is the usability target). Padding the anchors to a block box lifts
	   every one without changing type size or colour. 13px (not 11) because
	   measured at 11px the legal row landed at 41px and the email at 43px —
	   past the SC 2.5.8 floor but short of the 44px target. The logo anchor
	   is excluded: it wraps an SVG mark, not a text link. */
	.veil-footer__nav-col.veil-footer__nav-col a,
	.veil-footer__legal-text.veil-footer__legal-text a,
	.veil-footer__contact-text.veil-footer__contact-text a {
		display: inline-block;
		padding-block: 13px;
	}
}

/* =========================================================================
   THEME-48 (2026-08-17) — ONE MOBILE GUTTER (Bucket B, mechanical)
   Measured at 390px across 6 pages: top-level page wrappers carried FIVE
   different side paddings — 0px (fsx-pg), 22px (hub-wrap, brf-wrap), 32px
   (vh-in, vb-sec, vw, and .in on home/compliance), 40px (sv5-wrap, and .in
   on data-mining). Result was 2-9 distinct left rails per page and a text
   edge that jumped page to page during navigation, which reads as
   inconsistency even when no single page looks wrong.

   This sets ONE wrapper gutter below 600px. Nested card padding is
   deliberately NOT touched: .vb-tile 26, .sv5-card 24, .card 24, .fsx-row 26
   and .hubcard 32 are intentional insets INSIDE a wrapper, and flattening
   them would remove the card inset entirely.

   20px chosen over the existing 32/40: at 390px a 40px wrapper leaves 310px
   of content, 20px leaves 350px — ~13% more measure on the narrowest screens,
   where the measured worst case was already 11.9ch before THEME-46.
   Doubled classes because the page files load after this one.
   ========================================================================= */
@media (max-width: 600px) {
	.vh-in.vh-in, .vb-sec.vb-sec, .vw.vw,
	.sv5-wrap.sv5-wrap, .hub-wrap.hub-wrap, .brf-wrap.brf-wrap,
	.fsx-pg.fsx-pg, .dv2-cap.dv2-cap, .dv2-cap.dv2-cap > .in, .veil-lc.veil-lc > .in,
	.dv2-proc.dv2-proc > .in, .dv2-prob.dv2-prob > .in,
	.dv2-cta.dv2-cta > .in, .ct.ct > .in,
	.vq.vq > .in, .vc.vc > .in, .veil-eng.veil-eng > .in,
	.veil-wv.veil-wv > .in, .veil-ind.veil-ind > .in,
	.veil-fw.veil-fw > .in, .dv2-ben.dv2-ben > .in {
		padding-left: 20px;
		padding-right: 20px;
	}
}

/* =========================================================================
   THEME-49 (2026-08-17) — B5 nav active state + B9 founder portrait
   Both approved from rendered mockups 2026-08-17. B2 (radial glow) was
   proposed alongside these and the owner declined it — do not reintroduce.
   ========================================================================= */

/* --- B5. Active nav item. Measured: the current item's anchor carries
   background rgba(8,64,38,.2) at 6px radius, which over cream renders as a
   grey-green chip — an unstyled parent-theme default, and the only rounded
   fill anywhere in the header. Replaced with a 2px accent underline, which
   is how the rest of the site marks emphasis.
   KNOWN GAP (not caused here): WordPress only stamps current-menu-item on
   post_type menu items, so the two custom-link top-levels (Industries
   Served, About) never receive it. Tracked separately as D-7. --- */
.ct-menu-link.ct-menu-link,
li.current-menu-item > .ct-menu-link.ct-menu-link,
li.current_page_item > .ct-menu-link.ct-menu-link {
	border-radius: 0;
}
li.current-menu-item > .ct-menu-link.ct-menu-link,
li.current_page_item > .ct-menu-link.ct-menu-link,
li.current-menu-ancestor > .ct-menu-link.ct-menu-link {
	background-color: transparent;
	box-shadow: inset 0 -2px 0 var(--veil-accent);
}

/* --- B9. Founder portrait. The photo is genuine (owner confirmed
   2026-08-17), but two independent audits read it as stock. Cause is the
   framing, not the image: an 18px-radius white card with a drop shadow
   presents a person as a UI widget. Card chrome removed, square corners,
   4:5 editorial crop, mild desaturation; caption sits on the cream ground
   below. .vw-card is also removed from the THEME-45 card-hover list above,
   since it is no longer a card. --- */
.vw-card.vw-card {
	background: transparent;
	border: 0;
	box-shadow: none;
	border-radius: 0;
	padding: 0;
	overflow: visible;
}
.vw-card.vw-card img {
	display: block;
	width: 100%;
	border-radius: 0;
	aspect-ratio: 4 / 5;
	object-fit: cover;
	filter: grayscale(.35) contrast(1.06);
}

/* =========================================================================
   THEME-50 (2026-08-17) — ONE CARD RADIUS (Bucket B, B3 — narrowed)
   The audit proposed replacing three "card systems" wholesale: promoting the
   Services staggered card sitewide, removing drop shadows, and fixing
   "clipped text" on the compliance related-services row. MEASURED FIRST, and
   most of that premise did not hold:
     - home .vb-tile is a bento (459px and 340px tiles), not the "3x2 grid of
       six identically sized boxes" described, and carries NO shadow
     - zero clipped text anywhere: all 5 compliance cards are 216x181,
       height spread 0; all 6 services cards 524x290, spread 0
     - the 5-up related grid is a deliberate prior fix (QA-05 M-3) for an
       orphaned fifth card and must not be "corrected"
   What DID hold, measured across 6 live pages: three different corner radii
   on card components — 14px, 16px, 18px. That is the real inconsistency and
   it is all this block changes. Restructuring the layouts is not done here.
   ========================================================================= */
.sv5-card.sv5-card, .hubcard.hubcard, .vb-tile.vb-tile, .sv-sit.sv-sit,
.veil-rcard.veil-rcard, .dv2-stat.dv2-stat, .fsx-mx.fsx-mx {
	border-radius: var(--veil-radius-card);
}

/* -------------------------------------------------------------------------
 * Form consent notice (Terms of Use work order §23).
 *
 * `color: inherit` is load-bearing, not laziness. This notice renders inside
 * BOTH the light contact-page form and the dark hero form; a fixed token would
 * be invisible in one of them. Inheriting the surrounding text colour keeps it
 * legible in both, and both contexts were contrast-measured.
 *
 * Font size is 0.875rem and NOT smaller: §23 explicitly forbids hiding this in
 * small grey text, so it does not get a muted colour token either.
 * ---------------------------------------------------------------------- */
.veil-form-consent {
	margin: .75rem 0 0;
	font-size: .875rem;
	line-height: 1.5;
	color: inherit;
}

.veil-form-consent a {
	color: inherit;
	text-decoration: underline;
}

/* -------------------------------------------------------------------------
   A11Y-04 — HTML sitemap link target size (WCAG 2.5.8 Target Size (Minimum), AA)

   MEASURED at 375x812 on /sitemap/: `li.page_item > a` rendered 44.5 x 22 px
   across all 21 entries — 2px under the minimum. These are stacked list links,
   so unlike the footer legal row there is no neighbour to steal clicks from and
   line-height is the honest fix: it grows the target AND the visual row, which
   is what a dense link list wants anyway.

   Scoped to the list item so it cannot reach prose links elsewhere; prose links
   are exempt from 2.5.8 under the inline exception and must not be touched.

   NAV-02 (2026-09-07): WordPress also stamps `page_item page-item-2
   current_page_item` on the Home entry of the header menu when the front
   page is showing, so this rule reached the Home link, turned Blocksy's
   flex link into inline-block, and lifted the label about 9px above its
   neighbours (measured on veilgrp.com: Home text top 42.4px, Services
   51.9px). Header links carry .ct-menu-link; excluding them keeps the
   sitemap fix and leaves the menu alone.
   ---------------------------------------------------------------------- */
li.page_item > a:not(.ct-menu-link) {
	display: inline-block;
	min-height: 24px;
	line-height: 24px;
}
