/* ==========================================================================
   Valentino Box & Packaging Industry LLC
   Design system + components. Hand written, no framework, mobile first.
   Palette: ink navy / press blue / process cyan on paper white.
   ========================================================================== */

/* --------------------------------------------------------------- Fonts -- */
@font-face {
	font-family: 'Inter';
	font-style: normal;
	font-weight: 400 700;
	font-display: swap;
	src: url('../fonts/inter-normal-latin.woff2') format('woff2');
	unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
	font-family: 'Lora';
	font-style: normal;
	font-weight: 400 700;
	font-display: swap;
	src: url('../fonts/lora-normal-latin.woff2') format('woff2');
	unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
	font-family: 'Lora';
	font-style: italic;
	font-weight: 400 600;
	font-display: swap;
	src: url('../fonts/lora-italic-latin.woff2') format('woff2');
	unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* -------------------------------------------------------------- Tokens -- */
:root {
	/* ============================================================ PRINT-IN-MOTION
	   The site is built on paper and ink: a warm paper ground, a deep ink navy,
	   and the four process colours used the way a press uses them — sparingly,
	   and never all at once. */
	--ink-navy:        #071A2F;
	--ink-navy-2:      #0B2440;
	--charcoal:        #171B22;

	--paper:           #F7F3EA;
	--paper-white:     #FFFDF8;
	--paper-grey:      #E9E7E1;

	--process-blue:    #1463FF;
	--process-cyan:    #00B8D9;
	--process-magenta: #E73C87;
	--process-yellow:  #F4C542;
	--process-orange:  #FF6433;

	--border-dark:     rgba(7, 26, 47, .14);
	--border-light:    rgba(255, 255, 255, .18);

	/* Text-weight variants. The raw process colours are display colours; these
	   are the ones allowed to carry text on paper, measured against paper-white. */
	--blue-text:       #0B4FD8;
	--cyan-text:       #056B80;
	--magenta-text:    #C01E68;
	--orange-text:     #C2400F;
	--yellow-text:     #7A5B00;

	--vp-whatsapp:     #25D366;   /* WhatsApp controls ONLY */

	/* ---- semantic mapping — every legacy component reads through these ---- */
	--vp-ink:       var(--ink-navy);
	--vp-blue:      var(--process-blue);
	--vp-cyan:      var(--process-cyan);
	--vp-blue-soft: #EDEAE0;
	--vp-paper:     var(--paper);
	--vp-white:     var(--paper-white);
	--vp-text:      var(--charcoal);
	--vp-muted:     #5A6472;
	--vp-border:    #DFDACD;

	--v-ink:        var(--ink-navy);
	--v-ink-2:      var(--ink-navy-2);
	--v-ink-3:      #12365C;
	--v-paper:      var(--paper);
	--v-paper-2:    #EFEBE0;
	--v-paper-3:    var(--paper-grey);
	--v-line:       var(--border-dark);
	--v-line-ui:    #8A8578;
	--v-line-dark:  var(--border-light);
	--v-body:       #1B2230;
	--v-muted:      #565F6D;
	--v-accent:     var(--blue-text);
	--v-accent-dim: #63D7EC;
	--v-white:      var(--paper-white);
	--v-error:      #B3261E;
	--v-success:    #15803D;

	/* Type — two families, both already self-hosted by the theme. */
	--v-serif: 'Lora', 'Iowan Old Style', 'Palatino Linotype', Palatino, Georgia, serif;
	--v-sans:  'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;

	--v-fs-eyebrow:  .78rem;
	--v-fs-small:    .9rem;
	--v-fs-body:     clamp(1.0625rem, 1.02rem + .16vw, 1.1875rem);
	--v-fs-lead:     clamp(1.15rem, 1.06rem + .45vw, 1.4rem);
	--v-fs-h4:       clamp(1.1rem, 1.03rem + .34vw, 1.3rem);
	--v-fs-h3:       clamp(1.3rem, 1.15rem + .75vw, 2rem);
	--v-fs-h2:       clamp(2rem, 1.45rem + 2.1vw, 4rem);
	--v-fs-h1:       clamp(2.8rem, 2rem + 3.1vw, 6rem);
	--v-fs-display:  clamp(3.2rem, 2.1rem + 4.2vw, 7.5rem);

	/* Space scale */
	--space-1: clamp(.35rem, .3rem + .2vw, .5rem);
	--space-2: clamp(.65rem, .55rem + .4vw, 1rem);
	--space-3: clamp(1rem, .85rem + .7vw, 1.6rem);
	--space-4: clamp(1.5rem, 1.2rem + 1.3vw, 2.6rem);
	--space-5: clamp(2.2rem, 1.7rem + 2.2vw, 4rem);
	--space-6: clamp(3.2rem, 2.4rem + 3.4vw, 6rem);
	--space-section: clamp(4rem, 2.8rem + 5.2vw, 8.5rem);

	--v-gutter:  clamp(1.25rem, .9rem + 1.6vw, 2.5rem);
	--v-section: var(--space-section);

	/* Containers */
	--container:       1300px;
	--container-wide:  1480px;
	--container-read:  780px;
	--v-max:           var(--container);
	--v-max-text:      68ch;

	/* Rounding */
	--radius-sm:      10px;
	--radius-md:      16px;
	--radius-lg:      24px;
	--radius-feature: 32px;
	--v-radius-sm:   var(--radius-sm);
	--v-radius-md:   var(--radius-md);
	--v-radius-lg:   var(--radius-lg);
	--v-radius-card: var(--radius-lg);
	--v-radius:      var(--radius-sm);
	--v-radius-pill: 999px;

	--v-shadow:    0 1px 2px rgba(7, 26, 47, .05), 0 8px 24px -12px rgba(7, 26, 47, .18);
	--v-shadow-lg: 0 2px 4px rgba(7, 26, 47, .06), 0 28px 60px -26px rgba(7, 26, 47, .32);

	--v-topbar-h: 40px;
	--v-header-h: 76px;

	--ease-print: cubic-bezier(.22, .61, .36, 1);
}

/* --------------------------------------------------------------- Reset -- */
*, *::before, *::after { box-sizing: border-box; }

html {
	-webkit-text-size-adjust: 100%;
	scroll-behavior: smooth;
	scroll-padding-top: calc(var(--v-header-h) + 1rem);
}

@media (prefers-reduced-motion: reduce) {
	html { scroll-behavior: auto; }
	*, *::before, *::after {
		animation-duration: .01ms !important;
		animation-iteration-count: 1 !important;
		transition-duration: .01ms !important;
	}
}

body {
	margin: 0;
	background: var(--v-paper);
	color: var(--v-body);
	font-family: var(--v-sans);
	font-size: var(--v-fs-body);
	line-height: 1.65;
	-webkit-font-smoothing: antialiased;
	text-rendering: optimizeLegibility;
	overflow-x: hidden;
	overflow-wrap: break-word;
}

/* Grid and flex children default to min-width:auto, which lets long content
   push a track wider than the viewport. */
.v-grid > *, .v-specs > *, .v-process > *, .v-split > *, .v-product > * { min-width: 0; }

img, svg, video, iframe { max-width: 100%; height: auto; display: block; }
img { background: var(--v-paper-2); }

h1, h2, h3, h4, h5, h6 {
	font-family: var(--v-serif);
	color: var(--v-ink);
	font-weight: 600;
	line-height: 1.15;
	letter-spacing: -.012em;
	margin: 0 0 .6em;
	text-wrap: balance;
}

h1 { font-size: var(--v-fs-h1); }
h2 { font-size: var(--v-fs-h2); }
h3 { font-size: var(--v-fs-h3); }
h4 { font-size: var(--v-fs-h4); }

p { margin: 0 0 1.15em; }
p:last-child { margin-bottom: 0; }

a { color: var(--v-ink); text-underline-offset: .18em; text-decoration-thickness: 1px; }
a:hover { color: var(--v-accent); }

ul, ol { margin: 0 0 1.15em; padding-left: 1.25em; }
li { margin-bottom: .35em; }

strong, b { font-weight: 600; color: var(--v-ink); }
small { font-size: var(--v-fs-small); }
hr { border: 0; border-top: 1px solid var(--v-line); margin: var(--v-gutter) 0; }

/* Keyboard focus: ink line inside a cyan halo — visible on any ground. */
:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
	outline: 2px solid var(--vp-ink);
	outline-offset: 2px;
	box-shadow: 0 0 0 6px rgba(0, 166, 214, .4);
	border-radius: 4px;
}

::selection { background: var(--vp-blue); color: var(--vp-white); }

/* ------------------------------------------------------------ Utilities -- */
.v-container {
	width: 100%;
	max-width: var(--v-max);
	margin-inline: auto;
	padding-inline: var(--v-gutter);
}

.v-container--narrow { max-width: 860px; }

.screen-reader-text {
	position: absolute !important;
	width: 1px; height: 1px;
	padding: 0; margin: -1px;
	overflow: hidden; clip-path: inset(50%);
	white-space: nowrap; border: 0;
}

.v-skip-link {
	position: absolute;
	left: 50%;
	top: 0;
	transform: translate(-50%, -120%);
	z-index: 999;
	background: var(--v-ink);
	color: var(--v-white);
	padding: .8rem 1.4rem;
	font-size: var(--v-fs-small);
	font-weight: 600;
	text-decoration: none;
	border-radius: 0 0 var(--v-radius-sm) var(--v-radius-sm);
	transition: transform .18s ease;
}
.v-skip-link:focus { transform: translate(-50%, 0); color: var(--v-white); }

.v-eyebrow {
	display: block;
	font-family: var(--v-sans);
	font-size: var(--v-fs-eyebrow);
	font-weight: 600;
	letter-spacing: .16em;
	text-transform: uppercase;
	color: var(--v-accent);
	margin: 0 0 1rem;
}
/* Every ink ground takes the dark-surface accent. Press Blue on Ink Navy
   measures 2.7:1 and fails AA at eyebrow size; Process Cyan gives 5.49:1. */
.v-section--ink .v-eyebrow,
.v-page-hero .v-eyebrow,
.v-hero .v-eyebrow,
.v-cta .v-eyebrow,
.v-proof .v-eyebrow { color: var(--v-accent-dim); }

.v-lead {
	font-size: var(--v-fs-lead);
	line-height: 1.6;
	color: var(--v-body);
	max-width: var(--v-max-text);
}

.v-grid { display: grid; gap: clamp(1.25rem, 2.4vw, 2rem); }
.v-grid--2 { grid-template-columns: 1fr; }
.v-grid--3 { grid-template-columns: 1fr; }
.v-grid--4 { grid-template-columns: 1fr; }

@media (min-width: 600px) {
	.v-grid--2 { grid-template-columns: repeat(2, 1fr); }
	.v-grid--3 { grid-template-columns: repeat(2, 1fr); }
	.v-grid--4 { grid-template-columns: repeat(2, 1fr); }
}
@media (min-width: 900px) {
	.v-grid--3 { grid-template-columns: repeat(3, 1fr); }
	.v-grid--4 { grid-template-columns: repeat(4, 1fr); }
}

/* -------------------------------------------------------------- Buttons -- */
.v-btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: .55em;
	min-height: 48px;
	padding: .8rem 1.7rem;
	font-family: var(--v-sans);
	font-size: var(--v-fs-small);
	font-weight: 600;
	letter-spacing: .06em;
	text-transform: uppercase;
	text-decoration: none;
	text-align: center;
	border: 1px solid transparent;
	border-radius: var(--v-radius-pill);
	cursor: pointer;
	transition: background-color .18s ease, color .18s ease, border-color .18s ease, transform .18s ease;
}

.v-btn:hover { transform: translateY(-1px); }
.v-btn:active { transform: translateY(0); }

/* Primary — Press Blue ground, white type; Ink Navy on hover. */
.v-btn--primary { background: var(--vp-blue); color: var(--vp-white); border-color: var(--vp-blue); }
.v-btn--primary:hover { background: var(--vp-ink); border-color: var(--vp-ink); color: var(--vp-white); }

.v-btn--secondary { background: var(--vp-white); color: var(--v-ink); border-color: var(--v-ink); }
.v-btn--secondary:hover { background: var(--v-ink); color: var(--v-white); }

.v-btn--dark { background: var(--vp-ink); color: var(--vp-white); border-color: var(--vp-ink); }
.v-btn--dark:hover { background: var(--vp-blue); color: var(--vp-white); border-color: var(--vp-blue); }

.v-btn--ghost { background: transparent; color: var(--v-white); border-color: rgba(255, 255, 255, .55); }
.v-btn--ghost:hover { background: var(--v-white); color: var(--v-ink); border-color: var(--v-white); }

/* WhatsApp always wears its own green, with ink type for contrast. */
.v-btn--wa { background: var(--vp-whatsapp); color: var(--vp-ink); border-color: var(--vp-whatsapp); }
.v-btn--wa:hover { background: var(--vp-ink); color: var(--vp-white); border-color: var(--vp-ink); }
.v-btn--wa svg { width: 18px; height: 18px; flex: none; }

/* Elementor's kit paints global button styles (.elementor-kit-N button) that
   would repaint the theme's own <button> controls. Shield them — the body
   prefix out-ranks the kit selector without resorting to !important. */
body button.v-nav__link { background: none; color: var(--v-ink); padding: .7rem .8rem; }
body button.v-nav__link:hover { background: none; color: var(--v-accent); }
body button.v-gallery__thumb { background: var(--v-paper-2); padding: 0; border-radius: var(--v-radius-sm); }
body button.v-mobile__toggle { background: none; color: var(--v-ink); padding: .9rem 0; border-radius: 0; }
body button.v-step__head { background: none; color: inherit; text-transform: none; letter-spacing: normal; padding: 1.05rem 1.25rem; border-radius: 0; }
body button.v-search-toggle { background: none; color: var(--v-ink); padding: 0; }
body button.v-search-toggle[aria-expanded="true"] { background: var(--v-ink); color: var(--v-white); }
body button.v-search__clear { background: none; color: var(--v-muted); padding: 0; }
body button.v-search__submit { background: var(--vp-blue); color: var(--vp-white); padding: 0; }
body button.v-search__submit:hover { background: var(--vp-ink); }

/* The kit's global link colour (.elementor-kit-N a) also out-ranks the theme's
   single-class rules on builder pages, which would paint navy links onto the
   navy utility bar, footer and dark sections. Same shield, same reasoning. */
body .v-topbar a { color: rgba(255, 255, 255, .82); }
body .v-topbar a:hover { color: var(--vp-cyan); }
body .v-topbar a.v-topbar__wa:hover { color: var(--vp-whatsapp); }
body a.v-skip-link { color: var(--v-white); }
body .v-mobile__contact a { color: var(--v-body); }
body .v-mobile__contact a:hover { color: var(--v-accent); }

/* Elementor's kit paints a global link colour (.elementor-kit-N a) that would
   out-rank the single-class variants above on builder pages. Re-assert the
   text colours at higher specificity — no !important needed. */
a.v-btn.v-btn--primary { color: var(--vp-white); }
a.v-btn.v-btn--primary:hover { color: var(--vp-white); }
a.v-btn.v-btn--secondary { color: var(--v-ink); }
a.v-btn.v-btn--secondary:hover { color: var(--v-white); }
a.v-btn.v-btn--dark { color: var(--vp-white); }
a.v-btn.v-btn--dark:hover { color: var(--vp-white); }
a.v-btn.v-btn--ghost { color: var(--v-white); }
a.v-btn.v-btn--ghost:hover { color: var(--v-ink); }
a.v-btn.v-btn--wa { color: var(--vp-ink); }
a.v-btn.v-btn--wa:hover { color: var(--vp-white); }

.v-btn--full { width: 100%; }
.v-btn--sm { min-height: 44px; padding: .6rem 1.25rem; font-size: .8125rem; }

.v-btn-row { display: flex; flex-wrap: wrap; gap: .75rem; }
.v-btn-row .v-btn { flex: 1 1 auto; min-width: 200px; }

/* ----------------------------------------------------------- Utility bar -- */
/* Slim Ink Navy strip above the main header: email, WhatsApp, factory
   location and Instagram. Scrolls away; the main header alone stays sticky. */
.v-topbar {
	background: var(--vp-ink);
	color: rgba(255, 255, 255, .82);
	font-size: .8125rem;
}
.v-topbar__inner {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 1rem;
	min-height: var(--v-topbar-h);
}
.v-topbar__group { display: flex; align-items: center; gap: .25rem 1.4rem; flex-wrap: wrap; }
.v-topbar a {
	display: inline-flex;
	align-items: center;
	gap: .45em;
	color: rgba(255, 255, 255, .82);
	text-decoration: none;
	padding: .35rem 0;
	white-space: nowrap;
}
.v-topbar a:hover { color: var(--vp-cyan); }
.v-topbar svg { width: 15px; height: 15px; flex: none; opacity: .85; }
.v-topbar__wa:hover { color: var(--vp-whatsapp); }

/* ------------------------------------------------- icon-only links ------ */
/* One treatment shared by the utility strip, Contact and the footer, so the
   same glyph never appears in three slightly different sizes. The hit area is
   deliberately larger than the glyph: 17px of artwork inside a 38px target. */
.v-icon-link {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 38px;
	height: 38px;
	border-radius: var(--v-radius-sm);
	color: inherit;
	text-decoration: none;
	transition: color .15s ease, background-color .15s ease;
}
.v-icon-link svg { width: 17px; height: 17px; flex: none; opacity: 1; }

.v-topbar__icons { gap: .1rem; }
.v-topbar .v-icon-link { color: rgba(255, 255, 255, .82); }
body .v-topbar .v-icon-link:hover,
body .v-topbar .v-icon-link:focus-visible { color: var(--vp-cyan); background: rgba(255, 255, 255, .08); }
/* WhatsApp keeps its brand colour on hover only, so the strip is not
   dominated by a green glyph at rest. */
body .v-topbar .v-icon-link--wa:hover,
body .v-topbar .v-icon-link--wa:focus-visible { color: var(--vp-whatsapp); }

/* Contact and footer sit on light and dark grounds respectively. */
.v-info-list__value--icon .v-icon-link { margin-left: -9px; color: var(--v-accent); }
body .v-info-list__value--icon .v-icon-link:hover,
body .v-info-list__value--icon .v-icon-link:focus-visible { color: var(--v-ink); background: var(--vp-blue-soft); }

.v-footer__ig .v-icon-link { margin-left: -9px; color: rgba(255, 255, 255, .78); }
.v-footer__ig .v-icon-link:hover,
.v-footer__ig .v-icon-link:focus-visible { color: var(--vp-cyan); background: rgba(255, 255, 255, .08); }

/* ------------------------------------------- address as the map link ---- */
/* The address carries the Google Maps destination, so it must read as contact
   information first and as a link second: body colour, a hairline underline
   that firms up on hover, and a small pin to signal what it does. */
.v-address-link {
	display: inline-flex;
	align-items: flex-start;
	gap: .5em;
	color: inherit;
	text-decoration: none;
	border-bottom: 0;
}
.v-address-link > svg {
	width: 15px;
	height: 15px;
	flex: none;
	margin-top: .28em;
	color: var(--v-accent);
	opacity: .95;
}
.v-info-list__value--address .v-address-link {
	text-decoration: underline;
	text-decoration-color: var(--v-line);
	text-underline-offset: 3px;
	text-decoration-thickness: 1px;
}
body .v-info-list__value--address .v-address-link { color: var(--v-ink); }
body .v-info-list__value--address .v-address-link:hover,
body .v-info-list__value--address .v-address-link:focus-visible {
	color: var(--v-accent);
	text-decoration-color: currentColor;
}
.v-footer__list--factory .v-address-link {
	text-decoration: underline;
	text-decoration-color: rgba(255, 255, 255, .28);
	text-underline-offset: 3px;
	text-decoration-thickness: 1px;
	line-height: 1.55;
}
.v-footer__list--factory .v-address-link > svg { color: var(--vp-cyan); }
.v-footer__list--factory .v-address-link:hover,
.v-footer__list--factory .v-address-link:focus-visible { text-decoration-color: currentColor; }
/* The address is a multi-line block; the flex row default would stretch it. */
.v-footer__list--factory > li { display: block; }
.v-footer__list--factory > li:first-child { margin-bottom: .9rem; }

/* Progressive disclosure: the strip is a desktop element. The location glyph
   no longer needs hiding on narrower desktops — three icons cost far less
   width than the labels they replaced. */
.v-topbar { display: none; }
@media (min-width: 900px) { .v-topbar { display: block; } }

.v-header__bar {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 1rem;
	min-height: var(--v-header-h);
}

.v-brand { display: flex; align-items: center; gap: .7rem; text-decoration: none; flex: none; }
.v-brand img { max-height: 46px; width: auto; background: none; }
.v-brand__text {
	font-family: var(--v-serif);
	font-style: italic;
	font-weight: 600;
	font-size: 1.4rem;
	line-height: 1;
	color: var(--v-ink);
	letter-spacing: -.01em;
}
.v-brand__sub {
	display: block;
	font-family: var(--v-sans);
	font-style: normal;
	font-size: .58rem;
	font-weight: 600;
	letter-spacing: .19em;
	text-transform: uppercase;
	color: var(--v-muted);
	margin-top: .3rem;
}
.v-header__actions { display: flex; align-items: center; gap: .5rem; }

@media (min-width: 1080px) {
	.v-nav__list { display: flex; align-items: center; gap: .1rem; list-style: none; margin: 0; padding: 0; }
	.v-nav__list > li { margin: 0; position: static; }

	.v-nav__link {
		display: inline-flex;
		align-items: center;
		gap: .35em;
		padding: .7rem .8rem;
		font-size: .8125rem;
		font-weight: 600;
		letter-spacing: .08em;
		text-transform: uppercase;
		text-decoration: none;
		color: var(--v-ink);
		border-radius: var(--v-radius-pill);
		background: none;
		border: 0;
		font-family: var(--v-sans);
		cursor: pointer;
		white-space: nowrap;
	}
	.v-nav__link:hover,
	.v-nav__item--active > .v-nav__link { color: var(--v-accent); }

	.v-nav__item--active > .v-nav__link { position: relative; }
	.v-nav__item--active > .v-nav__link::before {
		content: '';
		position: absolute;
		left: .8rem; right: .8rem; bottom: .2rem;
		height: 2px;
		border-radius: 2px;
		background: var(--vp-cyan);
	}

	.v-nav__link[aria-expanded]::after {
		content: '';
		width: 6px; height: 6px;
		border-right: 1.5px solid currentColor;
		border-bottom: 1.5px solid currentColor;
		transform: rotate(45deg) translate(-2px, -2px);
		transition: transform .2s ease;
	}
	.v-nav__link[aria-expanded="true"]::after { transform: rotate(-135deg) translate(-2px, -2px); }
}

/* At the widths where the full nav fits but space is tight, tighten padding
   before anything can wrap. No nav item may ever break onto two lines. */
@media (min-width: 1080px) and (max-width: 1219px) {
	.v-nav__link { padding-inline: .55rem; letter-spacing: .05em; }
}
/* Only the three visual bars — the button also holds a screen-reader label,
   which must keep its collapsed 1px box or it widens the page's scroll area. */
.v-burger span:not(.screen-reader-text) {
	display: block; height: 1.5px; width: 100%;
	background: var(--v-ink);
	transition: transform .22s ease, opacity .22s ease;
}


.v-header__quote { display: none; }
@media (min-width: 560px) { .v-header__quote { display: inline-flex; } }

/* ---------------------------------------------------------------- Search -- */
/* One control, two surfaces: a header toggle button opens a full-width
   rounded panel under the header holding the input and live suggestions.
   The same panel serves desktop and mobile, so behaviour never forks. */
.v-search-toggle {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 48px; height: 48px;
	border: 1px solid transparent;
	border-radius: var(--v-radius-pill);
	background: none;
	color: var(--v-ink);
	cursor: pointer;
	transition: background-color .18s ease, color .18s ease;
}
.v-search-toggle:hover { background: var(--v-paper-2); color: var(--v-accent); }
.v-search-toggle[aria-expanded="true"] { background: var(--v-ink); color: var(--v-white); }
.v-search-toggle svg { width: 20px; height: 20px; }

.v-search-panel {
	position: absolute;
	left: 0; right: 0;
	top: 100%;
	display: none;
	background: var(--v-white);
	border-bottom: 1px solid var(--v-line);
	box-shadow: var(--v-shadow-lg);
	padding: 1.1rem 0 1.25rem;
}
.v-search-panel[data-open="true"] { display: block; }

.v-search { position: relative; max-width: 720px; margin-inline: auto; }
.v-search__box { position: relative; display: flex; align-items: center; }
.v-search__box > svg {
	position: absolute;
	left: 1.05rem;
	width: 18px; height: 18px;
	color: var(--v-muted);
	pointer-events: none;
}
.v-search__input {
	width: 100%;
	min-height: 52px;
	padding: .75rem 6.5rem .75rem 2.9rem;
	font-family: var(--v-sans);
	font-size: 1rem;
	color: var(--v-ink);
	background: var(--v-paper);
	border: 1px solid var(--v-line-ui);
	border-radius: var(--v-radius-pill);
	transition: border-color .16s ease, box-shadow .16s ease, background-color .16s ease;
	appearance: none;
}
.v-search__input:focus {
	outline: none;
	background: var(--v-white);
	border-color: var(--vp-blue);
	box-shadow: 0 0 0 4px rgba(0, 166, 214, .25);
}
.v-search__input::placeholder { color: var(--v-muted); opacity: 1; }
/* The browser's own clear control would double the custom one. */
.v-search__input::-webkit-search-cancel-button { -webkit-appearance: none; appearance: none; }

.v-search__clear,
.v-search__submit {
	position: absolute;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	border: 0;
	cursor: pointer;
	border-radius: var(--v-radius-pill);
}
.v-search__clear {
	right: 3.4rem;
	width: 40px; height: 40px;
	background: none;
	color: var(--v-muted);
}
.v-search__clear:hover { color: var(--v-ink); }
.v-search__clear[hidden] { display: none; }
.v-search__clear svg { width: 14px; height: 14px; }
.v-search__submit {
	right: .45rem;
	width: 44px; height: 44px;
	background: var(--vp-blue);
	color: var(--vp-white);
	transition: background-color .18s ease;
}
.v-search__submit:hover { background: var(--vp-ink); }
.v-search__submit svg { width: 18px; height: 18px; }

.v-search__results {
	list-style: none;
	margin: .7rem 0 0;
	padding: .4rem;
	background: var(--v-white);
	border: 1px solid var(--v-line);
	border-radius: var(--v-radius-md);
	box-shadow: var(--v-shadow);
	max-height: min(52vh, 26rem);
	overflow-y: auto;
}
.v-search__results:empty, .v-search__results[hidden] { display: none; }
.v-search__results li { margin: 0; }
.v-search__hit {
	display: flex;
	align-items: center;
	gap: .85rem;
	padding: .55rem .7rem;
	border-radius: var(--v-radius-sm);
	text-decoration: none;
	color: var(--v-ink);
}
.v-search__hit:hover, .v-search__hit[aria-selected="true"] { background: var(--v-paper-2); color: var(--v-ink); }
.v-search__thumb {
	flex: none;
	width: 52px; height: 52px;
	border-radius: var(--v-radius-sm);
	overflow: hidden;
	background: var(--v-paper-2);
	border: 1px solid var(--v-line);
}
.v-search__thumb img { width: 100%; height: 100%; object-fit: cover; }
.v-search__thumb--mark { display: grid; place-items: center; color: var(--v-line-ui); }
.v-search__thumb--mark svg { width: 22px; height: 22px; }
.v-search__meta { min-width: 0; }
.v-search__title { display: block; font-weight: 600; font-size: .9375rem; line-height: 1.3; }
.v-search__type {
	display: block;
	font-size: .71875rem;
	font-weight: 600;
	letter-spacing: .1em;
	text-transform: uppercase;
	color: var(--v-muted);
	margin-top: .15rem;
}
.v-search__status {
	padding: .8rem .7rem;
	font-size: .875rem;
	color: var(--v-muted);
}
.v-search__all { border-top: 1px solid var(--v-line); margin-top: .3rem; padding-top: .3rem; }
.v-search__all .v-search__hit { font-size: .8125rem; font-weight: 600; letter-spacing: .05em; text-transform: uppercase; color: var(--v-accent); }

.v-mega__inner {
	display: grid;
	gap: clamp(1.5rem, 3vw, 2.5rem);
	grid-template-columns: 1fr;
}
@media (min-width: 1080px) { .v-mega__inner { grid-template-columns: 2.4fr 1fr; } }

.v-mega__grid { display: grid; gap: 1rem 1.75rem; grid-template-columns: repeat(3, 1fr); }

.v-mega__cat { text-decoration: none; display: block; padding: .55rem 0; }
.v-mega__cat-name {
	font-family: var(--v-serif);
	font-size: 1.0625rem;
	font-weight: 600;
	color: var(--v-ink);
	margin-bottom: .2rem;
}
.v-mega__cat:hover .v-mega__cat-name { color: var(--v-accent); }
.v-mega__cat-desc { font-size: .8125rem; color: var(--v-muted); line-height: 1.5; }

/* A small registration mark before each family name — one colour, print-like. */
.v-mega__cat .v-mega__cat-name::before {
	content: '';
	display: inline-block;
	width: 7px; height: 7px;
	border: 1.5px solid var(--vp-cyan);
	border-radius: 50%;
	margin-right: .55rem;
	vertical-align: .07em;
}

.v-mega__list { list-style: none; margin: .4rem 0 0; padding: 0; }
.v-mega__list li { margin: 0; }
.v-mega__list a {
	display: block;
	padding: .2rem 0;
	font-size: .8125rem;
	color: var(--v-body);
	text-decoration: none;
}
.v-mega__list a:hover { color: var(--v-accent); }

.v-mega__aside {
	background: var(--v-paper-2);
	padding: clamp(1.25rem, 2.4vw, 1.75rem);
	border-radius: var(--v-radius-lg);
	align-self: start;
}
.v-mega__aside h3, .v-mega__aside-title { font-family: var(--v-serif); font-weight: 600; color: var(--v-ink); font-size: 1.125rem; line-height: 1.2; margin: 0 0 .5rem; }
.v-mega__aside p { font-size: .875rem; color: var(--v-muted); margin-bottom: 1.1rem; }

body.v-menu-open { overflow: hidden; }

.v-mobile__list { list-style: none; margin: 0; padding: 0; }
.v-mobile__list > li { border-bottom: 1px solid var(--v-line); }

.v-mobile__link,
.v-mobile__toggle {
	display: flex;
	align-items: center;
	justify-content: space-between;
	width: 100%;
	gap: 1rem;
	min-height: 56px;
	padding: .9rem 0;
	font-family: var(--v-sans);
	font-size: 1rem;
	font-weight: 600;
	letter-spacing: .06em;
	text-transform: uppercase;
	color: var(--v-ink);
	text-decoration: none;
	background: none;
	border: 0;
	text-align: left;
	cursor: pointer;
}

.v-mobile__toggle::after {
	content: '';
	flex: none;
	width: 9px; height: 9px;
	border-right: 1.5px solid currentColor;
	border-bottom: 1.5px solid currentColor;
	transform: rotate(45deg) translate(-2px, -2px);
	transition: transform .2s ease;
}
.v-mobile__toggle[aria-expanded="true"]::after { transform: rotate(-135deg) translate(-3px, -3px); }

.v-mobile__panel { display: none; padding: 0 0 1.1rem; }
.v-mobile__panel[data-open="true"] { display: block; }
.v-mobile__panel ul { list-style: none; margin: 0; padding: 0; }
.v-mobile__panel > ul > li { margin-bottom: 1rem; }

.v-mobile__cat {
	display: block;
	font-family: var(--v-serif);
	font-size: 1.0625rem;
	font-weight: 600;
	color: var(--v-ink);
	text-decoration: none;
	padding: .4rem 0;
}
.v-mobile__sub { padding-left: .9rem; border-left: 1px solid var(--v-line); }
.v-mobile__sub a {
	display: flex;
	align-items: center;
	min-height: 44px;
	font-size: .9375rem;
	color: var(--v-body);
	text-decoration: none;
}

.v-mobile__cta { margin-top: 1.75rem; display: grid; gap: .75rem; }

/* Business links repeated inside the drawer, where the utility bar is hidden. */
.v-mobile__contact { margin-top: 1.75rem; display: grid; gap: .1rem; }
.v-mobile__contact a {
	display: inline-flex;
	align-items: center;
	gap: .6rem;
	min-height: 44px;
	font-size: .9375rem;
	color: var(--v-body);
	text-decoration: none;
}
.v-mobile__contact a:hover { color: var(--v-accent); }
.v-mobile__contact svg { width: 16px; height: 16px; flex: none; color: var(--v-muted); }
.v-hero__media { position: absolute; inset: 0; }
.v-hero__media img { width: 100%; height: 100%; object-fit: cover; opacity: .38; }
.v-hero__media::after {
	content: '';
	position: absolute; inset: 0;
	background: linear-gradient(105deg, rgba(10, 37, 64, .94) 0%, rgba(10, 37, 64, .78) 46%, rgba(10, 37, 64, .5) 100%);
}
.v-hero__inner { position: relative; padding-block: clamp(4rem, 9vw, 8.5rem); max-width: 42rem; }
.v-hero__title { font-size: var(--v-fs-display); color: var(--v-white); margin-bottom: 1.1rem; }
.v-hero__title em { font-style: italic; color: var(--v-accent-dim); }

.v-hero__meta {
	display: flex; flex-wrap: wrap; gap: .5rem 1.75rem;
	margin-top: 2.5rem;
	padding-top: 1.75rem;
	border-top: 1px solid var(--v-line-dark);
	font-size: .8125rem;
	letter-spacing: .04em;
	color: rgba(255, 255, 255, .62);
}
.v-hero__meta span { display: inline-flex; align-items: center; gap: .45rem; }
.v-hero__meta span::before { content: ''; width: 5px; height: 5px; background: var(--vp-cyan); border-radius: 50%; flex: none; }
.v-page-hero__media { position: absolute; inset: 0; }
.v-page-hero__media img { width: 100%; height: 100%; object-fit: cover; opacity: .3; }
.v-page-hero__media::after { content: ''; position: absolute; inset: 0; background: linear-gradient(100deg, rgba(10,37,64,.93), rgba(10,37,64,.64)); }
.v-page-hero__inner { position: relative; padding-block: clamp(2.75rem, 6vw, 5rem); max-width: 46rem; }

.v-card__media { position: relative; aspect-ratio: 4 / 3; background: var(--v-paper-2); overflow: hidden; }
.v-card__media img { width: 100%; height: 100%; object-fit: cover; transition: transform .5s ease; }

.v-card__body { padding: clamp(1.1rem, 2vw, 1.5rem); display: flex; flex-direction: column; flex: 1; }
.v-card__title { font-size: var(--v-fs-h4); margin-bottom: .4rem; }
.v-card__title a { text-decoration: none; }
.v-card__title a::after { content: ''; position: absolute; inset: 0; }
.v-card__desc { font-size: .875rem; color: var(--v-muted); margin-bottom: 1rem; }
.v-card__foot { margin-top: auto; padding-top: .4rem; }
.v-card__count { font-size: .75rem; letter-spacing: .1em; text-transform: uppercase; color: var(--v-muted); }

/* Category card (larger, editorial) */
.v-cat-card .v-card__media { aspect-ratio: 3 / 2; }
.v-process__n {
	display: block;
	font-family: var(--v-sans);
	font-size: .6875rem;
	font-weight: 700;
	letter-spacing: .16em;
	color: var(--v-accent);
	margin-bottom: .6rem;
}

.v-spec { background: var(--v-white); padding: clamp(1.1rem, 2vw, 1.5rem); }
.v-spec__label {
	display: block;
	font-size: .6875rem;
	font-weight: 700;
	letter-spacing: .14em;
	text-transform: uppercase;
	color: var(--v-muted);
	margin-bottom: .55rem;
}
.v-spec ul { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: .4rem; }
.v-spec li { margin: 0; }
.v-tag {
	display: inline-block;
	padding: .3rem .7rem;
	font-size: .8125rem;
	color: var(--v-ink);
	background: var(--v-paper-2);
	border-radius: var(--v-radius-pill);
	border: 1px solid var(--v-line);
}
.v-spec p { font-size: .9375rem; color: var(--v-body); margin: 0; }

.v-gallery__main {
	position: relative;
	aspect-ratio: 4 / 3;
	background: var(--v-paper-2);
	border: 1px solid var(--v-line);
	border-radius: var(--v-radius-lg);
	overflow: hidden;
}
.v-gallery__main img { width: 100%; height: 100%; object-fit: cover; }

.v-gallery__thumbs { display: flex; flex-wrap: wrap; gap: .6rem; margin-top: .75rem; padding: 0; list-style: none; }
.v-gallery__thumbs li { margin: 0; }
.v-gallery__thumb {
	width: 72px; height: 72px;
	padding: 0;
	border: 1px solid var(--v-line-ui);
	border-radius: var(--v-radius-sm);
	overflow: hidden;
	background: var(--v-paper-2);
	cursor: pointer;
}
.v-gallery__thumb img { width: 100%; height: 100%; object-fit: cover; }
.v-gallery__thumb[aria-current="true"] { border-color: var(--vp-blue); border-width: 2px; }

.v-product__title { margin-bottom: .5rem; }
.v-product__cat { font-size: .75rem; letter-spacing: .14em; text-transform: uppercase; color: var(--v-accent); margin-bottom: .9rem; display: block; }
.v-product__tagline { font-size: var(--v-fs-lead); color: var(--v-body); margin-bottom: 1.5rem; }
.v-product__cta { margin-top: 1.75rem; display: grid; gap: .7rem; }
@media (min-width: 480px) { .v-product__cta { grid-template-columns: 1fr 1fr; } }
.v-product__note { font-size: .8125rem; color: var(--v-muted); margin-top: 1rem; }

/* ------------------------------------------------------------------ FAQ -- */
.v-faq { border-top: 1px solid var(--v-line); }
.v-faq details { border-bottom: 1px solid var(--v-line); }
.v-faq summary {
	display: flex;
	align-items: flex-start;
	justify-content: space-between;
	gap: 1rem;
	padding: 1.15rem 0;
	cursor: pointer;
	list-style: none;
	font-family: var(--v-serif);
	font-size: var(--v-fs-h4);
	font-weight: 600;
	color: var(--v-ink);
	min-height: 48px;
}
.v-faq summary::-webkit-details-marker { display: none; }
.v-faq summary::before {
	content: 'Q';
	flex: none;
	font-family: var(--v-serif);
	font-style: italic;
	font-size: 1rem;
	color: var(--v-accent);
	padding-top: .2em;
}
.v-faq summary::after {
	content: '';
	flex: none;
	margin-top: .45em;
	width: 10px; height: 10px;
	border-right: 1.5px solid var(--v-accent);
	border-bottom: 1.5px solid var(--v-accent);
	transform: rotate(45deg);
	transition: transform .2s ease;
}
.v-faq details[open] summary::after { transform: rotate(-135deg); }
.v-faq__body { padding: 0 0 1.4rem; max-width: var(--v-max-text); }
.v-faq__body p:last-child { margin-bottom: 0; }

/* ----------------------------------------------------------------- Prose -- */
.v-prose { max-width: var(--v-max-text); }
.v-prose h2 { margin-top: 2.25em; }
.v-prose h3 { margin-top: 1.9em; }
.v-prose > :first-child { margin-top: 0; }
.v-prose img { border-radius: var(--v-radius-md); margin-block: 1.75rem; }
.v-prose blockquote {
	margin: 1.75rem 0;
	padding-left: 1.5rem;
	border-left: 2px solid var(--v-accent);
	font-family: var(--v-serif);
	font-style: italic;
	font-size: var(--v-fs-lead);
	color: var(--v-ink);
}
.v-prose ul li::marker { color: var(--v-accent); }
.v-prose table { width: 100%; border-collapse: collapse; margin: 1.5rem 0; font-size: .9375rem; }
.v-prose th, .v-prose td { text-align: left; padding: .7rem .9rem; border-bottom: 1px solid var(--v-line); }
.v-prose th { font-weight: 600; color: var(--v-ink); }

.v-table-wrap { overflow-x: auto; }

/* ----------------------------------------------------------------- Forms -- */
.v-form { display: grid; gap: 1.5rem; }
.v-fieldset { border: 0; margin: 0; padding: 0; }
.v-fieldset legend {
	padding: 0;
	font-family: var(--v-sans);
	font-size: .6875rem;
	font-weight: 700;
	letter-spacing: .14em;
	text-transform: uppercase;
	color: var(--v-accent);
	margin-bottom: 1.1rem;
}
.v-field__req { color: var(--v-error); }
.v-field__hint { font-size: .75rem; color: var(--v-muted); }

.v-input, .v-select, .v-textarea, .v-file {
	width: 100%;
	min-height: 48px;
	padding: .7rem .95rem;
	font-family: var(--v-sans);
	font-size: 1rem;
	color: var(--v-ink);
	background: var(--v-white);
	border: 1px solid var(--v-line-ui);
	border-radius: var(--v-radius-sm);
	transition: border-color .16s ease, box-shadow .16s ease;
}
.v-textarea { min-height: 130px; resize: vertical; line-height: 1.6; }
.v-input:hover, .v-select:hover, .v-textarea:hover { border-color: var(--vp-blue); }
.v-input:focus, .v-select:focus, .v-textarea:focus, .v-file:focus {
	border-color: var(--vp-blue);
	box-shadow: 0 0 0 4px rgba(0, 166, 214, .25);
	outline: none;
}
.v-input[aria-invalid="true"], .v-select[aria-invalid="true"], .v-textarea[aria-invalid="true"] { border-color: var(--v-error); }
.v-input::placeholder, .v-textarea::placeholder { color: var(--v-muted); opacity: 1; }

.v-checks { display: grid; gap: .5rem; }
@media (min-width: 620px) { .v-checks--2 { grid-template-columns: repeat(2, 1fr); } }

.v-error-text { font-size: .8125rem; color: var(--v-error); font-weight: 500; }

.v-notice { padding: 1.1rem 1.25rem; border-radius: var(--v-radius-sm); border: 1px solid; font-size: .9375rem; margin-bottom: 1.5rem; }
.v-notice--error { background: #FBEDEC; border-color: #E7B4B0; color: var(--v-error); }
.v-notice--success { background: #E9F6EE; border-color: #B2DEC4; color: var(--v-success); }
.v-notice strong { color: inherit; }

.v-honeypot { position: absolute !important; left: -9999px !important; width: 1px; height: 1px; overflow: hidden; }

.v-footer__grid { display: grid; gap: 2.25rem; }
@media (min-width: 700px) { .v-footer__grid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1000px) { .v-footer__grid { grid-template-columns: 1.6fr 1fr 1fr 1.2fr; } }

.v-footer__title {
	font-family: var(--v-sans);
	font-size: .6875rem;
	font-weight: 700;
	letter-spacing: .16em;
	text-transform: uppercase;
	color: rgba(255, 255, 255, .5);
	margin-bottom: 1.1rem;
	position: relative;
	padding-bottom: .55rem;
}
.v-footer__title::after {
	content: '';
	position: absolute;
	left: 0; bottom: 0;
	width: 2rem; height: 2px;
	border-radius: 2px;
	background: var(--vp-cyan);
}
.v-footer__list { list-style: none; margin: 0; padding: 0; }
.v-footer__list li { margin-bottom: .55rem; }
.v-footer__list a { display: inline-flex; align-items: center; min-height: 32px; }

.v-footer__brand .v-brand__text { color: var(--v-white); font-size: 1.5rem; }
.v-footer__brand .v-brand__sub { color: rgba(255, 255, 255, .5); }
/* The logo artwork is ink-dark, so on the navy footer it sits on a paper chip. */
.v-footer__blurb { margin-top: 1.1rem; max-width: 32ch; font-size: .9375rem; }

.v-footer__bottom {
	margin-top: 3rem;
	padding-top: 1.5rem;
	border-top: 1px solid var(--v-line-dark);
	display: flex;
	flex-wrap: wrap;
	gap: .75rem 1.5rem;
	justify-content: space-between;
	font-size: .8125rem;
	color: rgba(255, 255, 255, .5);
}

.v-footer__social {
	display: flex;
	flex-wrap: wrap;
	gap: .5rem 1.5rem;
	margin-top: 2.5rem;
	padding-top: 1.5rem;
	border-top: 1px solid var(--v-line-dark);
	font-size: .8125rem;
	letter-spacing: .04em;
}
.v-footer__social a { display: inline-flex; align-items: center; min-height: 44px; }
.v-footer__social + .v-footer__bottom { margin-top: 1.5rem; padding-top: 1.5rem; }

/* Legal links share the copyright row rather than taking a column of their own.
   Inheriting the row's type and colour keeps them utility links, not navigation. */
.v-footer__legal { display: flex; flex-wrap: wrap; gap: .4rem 1.25rem; }
.v-footer__legal a { color: inherit; text-decoration: none; border-bottom: 1px solid rgba(255, 255, 255, .25); }
.v-footer__legal a:hover, .v-footer__legal a:focus-visible { color: var(--vp-cyan); border-bottom-color: currentColor; }

/* The footer's preference control is a button, so it has to be talked back into
   looking like the two links beside it. */
.v-footer__legal button {
	font: inherit;
	color: inherit;
	background: none;
	border: 0;
	border-bottom: 1px solid rgba(255, 255, 255, .25);
	padding: 0;
	cursor: pointer;
}
.v-footer__legal button:hover, .v-footer__legal button:focus-visible { color: var(--vp-cyan); border-bottom-color: currentColor; }

/* ==========================================================================
   ANALYTICS PREFERENCES
   A bar at the foot of the viewport, not a modal: the page stays readable and
   usable behind it, so a visitor is never forced to decide before continuing.
   Both answers are the same size and sit side by side — the only difference is
   that one is filled and one is outlined.
   ========================================================================== */

.v-consent {
	position: fixed;
	inset: auto 0 0 0;
	z-index: 60;
	background: var(--v-white);
	border-top: 1px solid var(--v-line);
	box-shadow: 0 -8px 30px rgba(10, 37, 64, .1);
	padding: 1rem clamp(1rem, 4vw, 2rem);
}
.v-consent[hidden] { display: none; }

.v-consent__inner {
	max-width: var(--v-max);
	margin-inline: auto;
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: .85rem 1.75rem;
}

.v-consent__text {
	margin: 0;
	flex: 1 1 30ch;
	font-size: .875rem;
	line-height: 1.55;
	color: var(--v-body);
}
.v-consent__text a { color: var(--vp-blue); }

.v-consent__actions { display: flex; flex-wrap: wrap; gap: .6rem; }
.v-consent__actions .v-btn { flex: 0 0 auto; }

/* Hold the bar clear of the last of the page so it never sits on top of a
   submit button or the end of a form. */
body.has-consent-panel { padding-bottom: var(--v-consent-h, 0px); }

@media (max-width: 640px) {
	.v-consent__inner { justify-content: stretch; }
	.v-consent__actions { width: 100%; }
	.v-consent__actions .v-btn { flex: 1 1 auto; }
}

/* -------------------------------------------------------------- Contact -- */
.v-contact-grid { display: grid; gap: clamp(2rem, 4vw, 3.5rem); align-items: start; }
@media (min-width: 900px) { .v-contact-grid { grid-template-columns: 1.15fr .85fr; } }

.v-info-list { list-style: none; margin: 0; padding: 0; }
.v-info-list li { margin-bottom: 1.4rem; }
.v-info-list__label {
	display: block;
	font-size: .6875rem;
	font-weight: 700;
	letter-spacing: .14em;
	text-transform: uppercase;
	color: var(--v-muted);
	margin-bottom: .3rem;
}
.v-info-list__value { color: var(--v-ink); font-size: 1rem; }
.v-info-list__value a { text-decoration: none; display: inline-flex; align-items: center; min-height: 32px; }
.v-info-list__value a:hover { color: var(--v-accent); }

.v-panel {
	background: var(--v-white);
	border: 1px solid var(--v-line);
	border-radius: var(--v-radius-lg);
	padding: clamp(1.5rem, 3vw, 2.25rem);
}

/* -------------------------------------------------------------- Content -- */
.v-flag {
	display: inline-block;
	font-size: .6875rem;
	font-weight: 700;
	letter-spacing: .1em;
	text-transform: uppercase;
	color: var(--v-muted);
	background: var(--v-paper-3);
	border: 1px dashed var(--v-line);
	border-radius: var(--v-radius-sm);
	padding: .3rem .6rem;
}

/* ---------------------------------------------------------- Split media -- */
.v-split { display: grid; gap: clamp(2rem, 4vw, 4rem); align-items: center; }
@media (min-width: 900px) { .v-split { grid-template-columns: repeat(2, 1fr); } }
.v-split--reverse > :first-child { order: 0; }
@media (min-width: 900px) { .v-split--reverse > :first-child { order: 1; } }

.v-media-frame {
	position: relative;
	aspect-ratio: 4 / 3;
	border-radius: var(--v-radius-md);
	overflow: hidden;
	background: var(--v-paper-2);
	border: 1px solid var(--v-line);
}
.v-media-frame img { width: 100%; height: 100%; object-fit: cover; }

/* --------------------------------------------------------- Stat / proof -- */
.v-proof { display: grid; gap: 1px; background: var(--v-line-dark); }
@media (min-width: 600px) { .v-proof { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1000px) { .v-proof { grid-template-columns: repeat(4, 1fr); } }
.v-proof__item { background: var(--v-ink); padding: clamp(1.25rem, 2.5vw, 2rem); }
.v-proof__item h3 { font-size: 1.0625rem; color: var(--v-white); margin-bottom: .4rem; }
.v-proof__item p { font-size: .875rem; color: rgba(255, 255, 255, .62); margin: 0; }

/* ------------------------------------------------------------- CTA band -- */
.v-cta {
	background: var(--v-ink);
	color: rgba(255, 255, 255, .8);
	border-radius: var(--v-radius-lg);
	padding: clamp(2rem, 5vw, 3.75rem);
	text-align: center;
}
.v-cta h2 { color: var(--v-white); max-width: 22ch; margin-inline: auto; }
.v-cta p { max-width: 48ch; margin-inline: auto; color: rgba(255, 255, 255, .75); }
.v-cta .v-btn-row { justify-content: center; margin-top: 2rem; }
.v-cta .v-btn-row .v-btn { flex: 0 1 auto; min-width: 200px; }
/* On the dark CTA band the primary flips to white so it cannot vanish. */
.v-cta .v-btn--primary:hover { background: var(--v-white); color: var(--v-ink); border-color: var(--v-white); }
.v-cta a.v-btn.v-btn--primary:hover { color: var(--v-ink); }
.v-cta .v-btn--wa:hover { background: var(--v-white); color: var(--v-ink); border-color: var(--v-white); }
.v-cta a.v-btn.v-btn--wa:hover { color: var(--v-ink); }

/* --------------------------------------------------------- Post listing -- */
.v-post-card__meta { font-size: .75rem; letter-spacing: .1em; text-transform: uppercase; color: var(--v-muted); margin-bottom: .5rem; }

/* ------------------------------------------------------------------ 404 -- */
.v-404 { text-align: center; padding-block: clamp(4rem, 10vw, 8rem); }
.v-404 h1 { font-size: var(--v-fs-display); }

/* --------------------------------------------------- Print (quotations) -- */
@media print {
	.v-header, .v-topbar, .v-footer, .v-breadcrumbs, .v-cta, .v-sticky-cta, .v-search-panel { display: none !important; }
	body { background: #fff; color: #000; }
}

/* ---------------------------------------------------------- Editorial block -- */
.v-block {
	background: var(--v-white);
	border: 1px solid var(--v-line);
	border-radius: var(--v-radius-lg);
	padding: clamp(1.1rem, 2vw, 1.5rem);
}
.v-block h3 { font-size: var(--v-fs-h4); margin-bottom: .5rem; }
.v-block p { font-size: .9375rem; color: var(--v-muted); margin: 0; }

/* ==========================================================================
   IMAGE PLACEHOLDER
   One reusable neutral visual for slots that will receive real photography
   later. Pale paper-blue ground, hairline ink border, crop marks in the
   corners and a cyan registration circle — the visual language of a press
   sheet, never fake photography. Replacing it is just placing a real image
   in the same container.
   ========================================================================== */
.v-ph {
	position: relative;
	background-color: var(--vp-blue-soft);
	background-image:
		/* registration circle */
		url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 48 48' fill='none'%3E%3Ccircle cx='24' cy='24' r='12' stroke='%2300A6D6' stroke-width='1.4' opacity='.55'/%3E%3Cpath d='M24 6v10M24 32v10M6 24h10M32 24h10' stroke='%2300A6D6' stroke-width='1.4' opacity='.55'/%3E%3C/svg%3E"),
		/* fine grid */
		linear-gradient(rgba(10, 37, 64, .045) 1px, transparent 1px),
		linear-gradient(90deg, rgba(10, 37, 64, .045) 1px, transparent 1px);
	background-repeat: no-repeat, repeat, repeat;
	background-position: center, 0 0, 0 0;
	background-size: 48px 48px, 24px 24px, 24px 24px;
	border: 1px solid var(--v-paper-3);
	border-radius: var(--v-radius-md);
	overflow: hidden;
	aspect-ratio: 4 / 3;
}
/* Crop marks in the four corners. */
.v-ph::before, .v-ph::after {
	content: '';
	position: absolute;
	width: 14px; height: 14px;
	border: 0 solid rgba(10, 37, 64, .35);
}
.v-ph::before { top: 10px; left: 10px; border-top-width: 1.5px; border-left-width: 1.5px; }
.v-ph::after { bottom: 10px; right: 10px; border-bottom-width: 1.5px; border-right-width: 1.5px; }

/* Inside an already-framed container the frame styling steps back. */
.v-card__media.v-ph, .v-media-frame.v-ph, .v-gallery__main .v-ph { border: 0; border-radius: 0; aspect-ratio: auto; position: absolute; inset: 0; }
.v-card__media.v-ph { position: relative; aspect-ratio: 4 / 3; }
.v-media-frame.v-ph { position: relative; aspect-ratio: 4 / 3; }

/* On the navy ground the placeholder keeps its paper tone but dims slightly,
   reading as a press sheet laid on the dark table. */
.v-section--ink .v-ph, .val-bg-ink .v-ph { opacity: .92; }

/* Elementor containers marked v-media-art are exactly these future-photo
   slots, so they wear the same placeholder. */
.v-media-art { aspect-ratio: 4 / 3; }
.v-media-frame.v-media-art {
	background-color: var(--vp-blue-soft);
	background-image:
		url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 48 48' fill='none'%3E%3Ccircle cx='24' cy='24' r='12' stroke='%2300A6D6' stroke-width='1.4' opacity='.55'/%3E%3Cpath d='M24 6v10M24 32v10M6 24h10M32 24h10' stroke='%2300A6D6' stroke-width='1.4' opacity='.55'/%3E%3C/svg%3E"),
		linear-gradient(rgba(10, 37, 64, .045) 1px, transparent 1px),
		linear-gradient(90deg, rgba(10, 37, 64, .045) 1px, transparent 1px);
	background-repeat: no-repeat, repeat, repeat;
	background-position: center, 0 0, 0 0;
	background-size: 48px 48px, 24px 24px, 24px 24px;
	border-color: var(--v-paper-3);
}

/* ==========================================================================
   ELEMENTOR LAYER
   Elementor is an editing surface over this design system, not a second one.
   Everything below is single-class specificity on purpose, so any value the
   owner sets in Elementor overrides it cleanly — no !important anywhere.
   ========================================================================== */

/* ------------------------------------------- design tokens, republished -- */
/* Aliases only. The values live once, above, in the --v-* set. */
:root {
	--val-color-primary:    var(--v-ink);
	--val-color-secondary:  var(--v-ink-2);
	--val-color-text:       var(--v-body);
	--val-color-muted:      var(--v-muted);
	--val-color-accent:     var(--v-accent);
	--val-color-accent-dim: var(--v-accent-dim);
	--val-color-background: var(--v-paper);
	--val-color-surface:    var(--v-white);
	--val-color-surface-alt:var(--v-paper-2);
	--val-color-border:     var(--v-line);
	--val-color-border-ui:  var(--v-line-ui);

	--val-container-width:  var(--v-max);
	--val-gutter:           var(--v-gutter);
	--val-radius:           var(--v-radius-lg);

	/* Section rhythm. Four steps, used by the val-section-* classes. */
	--val-space-xl: var(--v-section);
	--val-space-lg: calc(var(--v-section) * .78);
	--val-space-md: calc(var(--v-section) * .55);
	--val-space-sm: calc(var(--v-section) * .34);

	/* Gaps between items inside a container. */
	--val-gap-lg: clamp(1.5rem, 1.1rem + 1.6vw, 2.5rem);
	--val-gap-md: clamp(1.1rem, .9rem + .9vw, 1.75rem);
	--val-gap-sm: clamp(.65rem, .55rem + .4vw, 1rem);
}

.val-gap-lg { gap: var(--val-gap-lg); }
.val-gap-md { gap: var(--val-gap-md); }
.val-gap-sm { gap: var(--val-gap-sm); }

/* ------------------------------------------------------ content width -- */
.val-measure { max-width: var(--v-max-text); }
.val-measure-center { max-width: var(--v-max-text); margin-inline: auto; }
.val-center { text-align: center; }
.val-center .v-btn-row, .val-center .elementor-button-wrapper { justify-content: center; }

/* ------------------------------------------------ Elementor harmony ---- */
/* Elementor's own reset adds vertical rhythm we already control. */
.elementor-widget:not(:last-child) { margin-block-end: 0; }
.elementor-widget-container > :last-child { margin-bottom: 0; }

/* Keep builder containers on the same gutter as hand-coded sections. */
.elementor-section-boxed > .elementor-container,
.e-con.e-con-boxed > .e-con-inner { padding-inline: var(--v-gutter); }

/* Buttons placed from the Elementor panel inherit the Valentino button shape.
   The kit supplies colour and type; this supplies size and behaviour. */
.elementor-button {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: .55em;
	min-height: 48px;
	border-radius: var(--v-radius-pill);
	transition: background-color .18s ease, color .18s ease, border-color .18s ease, transform .18s ease;
}
.elementor-button:hover { transform: translateY(-1px); }

/* Valentino components dropped into a builder page should not inherit
   Elementor's text alignment for their internal grids. */
.elementor-widget-shortcode .v-grid,
[class*="elementor-widget-valentino-"] .v-grid { text-align: initial; }

/* The editor canvas has no theme header, so give it breathing room. */
.elementor-editor-active .v-main { padding-top: 0; }

/* Elementor image widgets keep the rounded frame treatment. */
.elementor-widget-image img { border-radius: var(--v-radius-md); }
/* .v-spec__label lands on the Elementor widget WRAPPER, and only inherited
   properties reach the <h3> inside it. text-transform inherits; font-family,
   font-size, font-weight and letter-spacing do not — they are re-declared by
   the theme's bare `h3` rules. So the label kept its uppercase while
   rendering at 26px in Lora: giant serif capitals.

   Those bare element selectors are specificity 0,0,1, so naming the inner
   element is enough to win. No !important is needed anywhere here.

   The treatment matches .v-cap__title on the homepage, so a quality point
   reads as the same kind of object as a capability card. The words are
   stored in sentence case, so removing the uppercase renders them as written
   rather than altering any content. */
.v-specs-flex .v-spec__label,
.v-specs-flex .v-spec__label .elementor-heading-title {
	font-family: var(--v-sans);
	font-size: 1.0625rem;
	font-weight: 650;
	line-height: 1.3;
	letter-spacing: -.005em;
	text-transform: none;
	color: var(--v-ink);
}
/* Elementor's own .e-con padding rule is a single class and loads after the
   theme, so a bare `.v-specs-flex > *` ties on specificity and loses on
   source order — the cells kept Elementor's default 10px. The body prefix is
   the same shield the rest of this file uses against the builder. Before this
   the cells also had padding-inline stripped to 0 and the copy ran into the
   dividers: the exclusion list above named [class*="v-specs"], which matches
   the wrapper but not the .v-spec cells inside it. */
body .v-specs-flex > * { padding: clamp(1.35rem, 1.1rem + .6vw, 1.65rem); }

/* Panel headings placed as Elementor heading widgets. */
.v-panel-title    { font-size: var(--v-fs-h3); }
.v-panel-title-sm { font-size: var(--v-fs-h4); }

/* Hero inner column keeps its editorial measure. */
.val-hero-inner { max-width: 46rem; }

/* Factory photo strip: four across on desktop, two on tablet, one on mobile. */
.val-photo-row > * { flex: 1 1 clamp(200px, 22%, 320px); }

/* ==========================================================================
   UI COMPONENTS LAYER
   Split hero, editorial process, chips, stepped quote form, sticky CTA.
   ========================================================================== */

/* ------------------------------------------------------ split hero ------ */
.v-hero--split .v-hero__grid {
	display: grid;
	gap: clamp(2rem, 4vw, 4rem);
	align-items: center;
}
.v-hero__art {
	aspect-ratio: 4 / 3;
	border: 1px solid var(--v-line-dark);
	border-radius: var(--v-radius-lg);
	background-color: transparent;
	background-size: 80% auto;
}

/* The homepage hero panel: real catalogue photography in a framed panel. */
.v-hero__photo {
	aspect-ratio: 4 / 3;
	border-radius: clamp(18px, 2vw, 26px);
	border: 1px solid var(--v-line-dark);
	background-size: cover;
	background-position: center;
	overflow: hidden;
	position: relative;
}
.v-hero__photo::after {
	content: '';
	position: absolute;
	inset: auto 0 0 0;
	height: 4px;
	background: linear-gradient(90deg, var(--vp-blue), var(--vp-cyan));
}

/* --------------------------------------------- editorial process list --- */
/* Applied via a wrapper class on the Elementor container, so the same
   template part serves both treatments. */
.val-process-editorial .v-process {
	display: grid;
	gap: 0 clamp(2rem, 4vw, 4rem);
	background: none;
	border: 0;
	border-radius: 0;
	overflow: visible;
}
.val-process-editorial .v-process__n {
	font-family: var(--v-serif);
	font-size: 1.55rem;
	font-weight: 500;
	color: var(--v-accent-dim);
	letter-spacing: 0;
	margin: 0;
	line-height: 1.1;
}

/* The boxed process grid keeps white cells even inside a dark section, so its
   text must keep the light-surface colours there. The editorial variant sets
   its own transparent cells and white type, and is excluded. */
.val-bg-ink:not(.val-process-editorial) .v-process h3 { color: var(--v-ink); }
.v-svc__n {
	font-family: var(--v-serif);
	font-size: 1.5rem;
	color: var(--v-accent);
	line-height: 1;
	margin-bottom: 1rem;
}
.v-svc__title {
	font-family: var(--v-sans);
	font-size: .8125rem;
	font-weight: 700;
	letter-spacing: .12em;
	text-transform: uppercase;
	color: var(--v-ink);
	margin: 0 0 .6rem;
}
.v-svc__title a { text-decoration: none; color: inherit; }
.v-svc__title a::after { content: ''; position: absolute; inset: 0; }

/* -------------------------------------------------- stepped quote form -- */
.v-steps { counter-reset: vstep; }
.v-step__head {
	display: flex;
	align-items: center;
	gap: .9rem;
	width: 100%;
	padding: 1.05rem 1.25rem;
	background: none;
	border: 0;
	font-family: var(--v-sans);
	text-align: left;
	cursor: pointer;
}
.v-step__n {
	counter-increment: vstep;
	flex: none;
	display: grid;
	place-items: center;
	width: 2rem; height: 2rem;
	border: 1px solid var(--v-line-ui);
	border-radius: 50%;
	font-size: .8125rem;
	font-weight: 600;
	color: var(--v-ink);
	font-variant-numeric: tabular-nums;
}
.v-step__n::before { content: counter(vstep); }
.v-step__label { font-size: .9375rem; font-weight: 600; color: var(--v-ink); }
.v-step__hint { font-size: .8125rem; color: var(--v-muted); margin-left: auto; }
.v-step__body { padding: 0 1.25rem 1.4rem; }
.v-step__nav { display: flex; justify-content: space-between; gap: .75rem; margin-top: 1.4rem; }

/* JS-enhanced state: collapse inactive steps. Without JS all steps stay open. */
.v-steps--js .v-step__body[hidden] { display: none; }
.v-steps__progress {
	font-size: .8125rem;
	font-weight: 600;
	color: var(--v-accent);
	font-variant-numeric: tabular-nums;
	margin-bottom: 1rem;
}

/* ------------------------------------------- sticky product CTA (mobile) - */
.v-sticky-cta {
	position: fixed;
	left: 0; right: 0; bottom: 0;
	z-index: 95;
	display: flex;
	gap: .6rem;
	padding: .65rem max(1rem, env(safe-area-inset-right)) calc(.65rem + env(safe-area-inset-bottom)) max(1rem, env(safe-area-inset-left));
	background: rgba(255, 255, 255, .96);
	-webkit-backdrop-filter: blur(10px);
	backdrop-filter: blur(10px);
	border-top: 1px solid var(--v-line);
}
.v-sticky-cta .v-btn { flex: 1; min-height: 46px; min-width: 0; padding-inline: 1rem; }
@media (min-width: 900px) { .v-sticky-cta { display: none; } }
body.v-has-sticky-cta { padding-bottom: 76px; }
@media (min-width: 900px) { body.v-has-sticky-cta { padding-bottom: 0; } }

/* ----------------------------------------- editorial two-column section -- */
.v-editorial { display: grid; gap: clamp(1.75rem, 3.5vw, 3.5rem); align-items: start; }
@media (min-width: 900px) { .v-editorial { grid-template-columns: minmax(0, .9fr) minmax(0, 1.1fr); } }
.v-editorial__topics { display: grid; gap: 1rem; }
.v-topic { background: var(--v-white); border: 1px solid var(--v-line); border-radius: var(--v-radius-lg); padding: clamp(1.1rem, 2vw, 1.5rem); }
.v-topic h3 { font-size: 1.05rem; margin: 0 0 .4rem; }
.v-topic p { font-size: .9375rem; color: var(--v-body); margin: 0; }

/* Mobile drawer: the view-all row reads as the action, not another category. */
.v-mobile__cat--all { color: var(--v-accent); font-family: var(--v-sans); font-size: .9375rem; font-weight: 600; letter-spacing: .04em; text-transform: uppercase; }

/* ------------------------------------------------------ resource kicker -- */
.v-resource-kicker {
	display: inline-block;
	font-size: .6875rem;
	font-weight: 700;
	letter-spacing: .14em;
	text-transform: uppercase;
	color: var(--v-muted);
	margin-bottom: .5rem;
}

/* ==========================================================================
   FRONTEND POLISH LAYER
   Presentation-only corrections found during rendered visual QA. No new
   palette, no new dependencies — the approved Ink/Press Blue system and the
   existing radius tokens are the only inputs.
   ========================================================================== */

/* ------------------------------------------------- builder alignment ----- */
/* Elementor ships every container with 10px padding. On a nested container
   that pushes its content 10px inside the boxed gutter, so builder text sat
   10px right of the header, footer and every hand-coded section. Nested
   containers inherit the parent's gutter instead. */
/* Plain layout children only — a child container that also carries a visual
   component class (a panel, a spec block) owns its own padding and must keep
   it, or the component collapses against its own border. */
.e-con.e-child:not([class*="v-panel"]):not([class*="v-spec"]):not([class*="v-topic"]):not([class*="v-card"]):not([class*="v-svc"]):not(.v-cap):not(.v-qp):not(.v-qp__row) { padding-inline: 0; }

/* A panel built as an Elementor container still reads as the theme's panel:
   its own padding and the shared card radius, which Elementor's container
   defaults were flattening to square. */
.e-con.v-panel {
	padding: clamp(1.5rem, 3vw, 2.25rem);
	border-radius: var(--v-radius-lg);
}

/* ------------------------------------------------ builder prose links ---- */
/* The Elementor kit strips text-decoration from every anchor. That is right
   for the buttons and for the .v-link-arrow links, which carry their own
   treatment — but it leaves an ordinary inline link inside body copy looking
   exactly like the sentence around it. The theme's own prose links are
   underlined (see any article), so this restores that one property for
   builder text widgets and nothing else; offset, thickness and hover colour
   already come from the base `a` rule. */
body .elementor-widget-text-editor a:not(.v-link-arrow):not([class*="v-btn"]) {
	text-decoration: underline;
}

/* --------------------------------------------- builder call to action ---- */
/* _css_classes lands on the widget WRAPPER, never on the <a>. Styling the
   wrapper as a button drew a second pill around the real one, so the wrapper
   only ever positions, and the button inside carries the treatment. */
.val-cta { display: inline-flex; background: none; border: 0; padding: 0; }
/* The Elementor kit paints .elementor-kit-N .elementor-button at the same
   specificity and loads later, so these carry the body prefix the rest of the
   theme already uses to shield its own controls from the kit. */
body .val-cta-primary .elementor-button {
	background: var(--vp-blue);
	color: var(--vp-white);
	border-color: var(--vp-blue);
}

/* --------------------------------------------------- panel headings ----- */
/* A heading widget inside a side panel inherited the full H2 display size and
   rendered around 40–44px, overpowering the panel it labels. */
.v-panel h2,
.v-panel .elementor-heading-title,
.v-panel h2.elementor-heading-title { font-size: var(--v-fs-h3); margin-bottom: .75rem; }
.v-panel .v-info-list { margin-top: .25rem; }

/* ------------------------------------------------- reading measure ------ */
/* A prose-only section left its measure hard against the left gutter, leaving
   the right half of a 1280px container empty — it read as unfinished rather
   than as a deliberate column. Centring the measure closes the void without
   touching the line length that makes it readable. */
.v-section--reading .v-container > .v-section-head,
.v-section--reading .v-container > .v-prose { margin-inline: auto; }

/* --------------------------------------------- WhatsApp, secondary ------ */
/* Beside Get a Quote the solid green read as loud as the primary. On light
   grounds it keeps the WhatsApp colour but steps back to an outline so the
   quotation stays the dominant action. */
.v-btn--wa-soft {
	background: var(--vp-white);
	color: #0F7A38;
	border-color: #7BE0A5;
}
.v-btn--wa-soft:hover { background: var(--vp-whatsapp); color: var(--vp-ink); border-color: var(--vp-whatsapp); }
a.v-btn.v-btn--wa-soft { color: #0F7A38; }
a.v-btn.v-btn--wa-soft:hover { color: var(--vp-ink); }
.v-btn--wa-soft svg { width: 18px; height: 18px; flex: none; }

/* Equal columns: the colour treatment already carries the hierarchy, and an
   uneven split wrapped the WhatsApp label onto two lines. */
.v-product__cta .v-btn { white-space: nowrap; padding-inline: 1.25rem; }

/* ------------------------------------------------- button consistency --- */
/* Buttons measured 48px in most places and 51px inside grids, because the
   uppercase label's line box grew the box. A fixed line-height settles them. */
.v-btn { line-height: 1.2; }
.v-btn--sm { line-height: 1.2; }

/* ---------------------------------------------------- empty states ------ */
/* Portfolio and Blog are intentionally without content. They should read as
   deliberate and composed, not as a page that failed to load — achieved with
   rhythm and type alone, never with filler imagery or cards. */
.v-empty-state {
	max-width: 34rem;
	padding-block: clamp(2.5rem, 6vw, 4.5rem);
}

/* ------------------------------------------------------ type polish ----- */
/* Headings sat one word wide on the last line at some widths. */
h1, h2, h3 { text-wrap: balance; }
.v-lead, .v-card__desc, .v-prose p { text-wrap: pretty; }

/* The page hero on interior templates sits below the homepage in the
   hierarchy, so its display size steps down accordingly. */
.v-page-hero h1 { font-size: clamp(2rem, 1.5rem + 1.9vw, 3.25rem); }

/* ------------------------------------------------------ card elevation -- */
/* One elevation step across every card so hover reads as a state change
   rather than as a different component. */
.v-card:hover, .v-svc:hover, .v-topic:hover { box-shadow: 0 1px 2px rgba(10, 37, 64, .04), 0 12px 28px -18px rgba(10, 37, 64, .22); }

/* ------------------------------------------------- contact affordance --- */
/* Email, map and social values are actions, so they read as links rather than
   as the same dark text as the address beside them. */
.v-info-list__value a {
	color: var(--v-accent);
	text-decoration: underline;
	text-decoration-color: color-mix(in srgb, var(--vp-blue) 35%, transparent);
	text-underline-offset: .22em;
	text-decoration-thickness: 1px;
}
.v-info-list__value a:hover {
	color: var(--v-ink);
	text-decoration-color: currentColor;
}
body .v-info-list__value a { color: var(--v-accent); }
body .v-info-list__value a:hover { color: var(--v-ink); }

/* --------------------------------------- the address is the map link ---- */
/* The address row is the one .v-info-list value that is not a short inline
   action, so it opts out of the shared link treatment above: it keeps body
   colour (a three-line address set in link blue reads as an error, not as
   contact information) and the pin aligns to the first line rather than to
   the middle of the block. The generic rules win on specificity, so these
   restate the two properties that matter. */
.v-info-list__value--address .v-address-link,
.v-footer__list--factory .v-address-link {
	align-items: flex-start;
	min-height: 0;
}
/* Visible enough to read as clickable, quiet enough to stay contact info. */
.v-info-list__value--address .v-address-link {
	text-decoration-color: color-mix(in srgb, var(--v-ink) 30%, transparent);
	text-underline-offset: .22em;
}
body .v-info-list__value--address .v-address-link:hover,
body .v-info-list__value--address .v-address-link:focus-visible {
	color: var(--v-accent);
	text-decoration-color: currentColor;
}

/* ==========================================================================
   PHOTOGRAPHY SLOTS
   Ten reserved positions across About, the five service pages and the
   homepage, waiting for real Valentino photography. One component serves all
   of them so a photograph behaves identically wherever it lands.

   The empty state is CSS only — no file, no request, nothing in the media
   library to tidy up later. It extends the .v-ph press sheet with one motif
   per subject so a reader understands what the position is for without the
   page having to say "photo goes here", and without any of it resembling
   evidence of a factory nobody has photographed yet.
   ========================================================================== */

.v-photo{
	position:relative;
	width:100%;
	margin:0;
	overflow:hidden;
	border-radius:var(--v-radius-card);
	background:var(--v-paper-2);
}
.v-photo--16-9{aspect-ratio:16/9}
.v-photo--16-10{aspect-ratio:16/10}
.v-photo--4-3{aspect-ratio:4/3}
.v-photo--4-5{aspect-ratio:4/5}
.v-photo--1-1{aspect-ratio:1/1}
.v-photo img,
/* Elementor ships `.elementor img{height:auto}` in frontend.min.css. It has the
   same specificity as `.v-photo img` and loads after this file, so it won the
   height declaration on every slot Elementor renders — the image kept its own
   intrinsic height and the frame just clipped the top of it. Naming .elementor
   here outranks it without touching Elementor's stylesheet. */
.elementor .v-photo img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;object-position:center;display:block}
/* The image is taken out of flow so it fills the ratio box exactly. With it in
   flow, height:100% resolved against an auto-height parent (the ratio box, and
   on wide screens a max-height-clamped one) and fell back to auto, so the photo
   laid out at its own intrinsic height and the frame simply clipped the top of
   it. object-fit never got to run, which is what turned an intended centre crop
   into a top crop. */
/* The placeholder carries a hairline so an empty slot reads as a reserved
   frame rather than as a block of flat colour that failed to load. */
.v-photo--empty{border:1px solid var(--v-paper-3)}

/* A wide band inside a full-width section would otherwise stand 720px tall at
   1280px and dominate the page it is meant to support. Elementor puts a
   widget's custom class on the wrapper, so the cap is applied from there. */
.val-photo-band .v-photo,
.v-photo--band{max-height:320px}
/* A band is four times wider than a column slot, so the motif is scaled with
   it — at the base size it read as a speck floating in an empty field. */
.val-photo-band .v-photo--empty{background-size:210px 158px,24px 24px,24px 24px}

/* The lead image on a service page. 16:10 governs on phones and tablets; on a
   1280px container that ratio would stand 750px tall directly under the hero
   and push the whole article below the fold, so on wide screens it crops to a
   band instead. Every service page therefore opens the same height. */
.val-photo-lead .v-photo{max-height:380px}
.val-photo-lead .v-photo--empty{background-size:210px 158px,24px 24px,24px 24px}

/* ---- contextual placeholder motifs ------------------------------------- */
/* Each variant swaps the base registration mark for one line drawing of the
   process the eventual photograph will show. Grid and ground are inherited. */
.v-ph--factory,.v-ph--printing,.v-ph--finishing,.v-ph--assembly,
.v-ph--design,.v-ph--sampling,.v-ph--consultation{
	background-repeat:no-repeat,repeat,repeat;
	background-position:center,0 0,0 0;
	background-size:132px 99px,24px 24px,24px 24px;
}
.v-ph--factory{
	background-image:
		url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 132 99' fill='none' stroke='%230A2540' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' opacity='.5'%3E%3Cpath d='M14 76h104'/%3E%3Cpath d='M24 76V44l22 13V44l22 13V30l18 9v37'/%3E%3Cpath d='M86 76V39l22-9v46'/%3E%3Cpath d='M34 64h6M56 64h6M78 64h6M96 62h6' stroke='%2300A6D6'/%3E%3C/svg%3E"),
		linear-gradient(rgba(10,37,64,.045) 1px,transparent 1px),
		linear-gradient(90deg,rgba(10,37,64,.045) 1px,transparent 1px);
}

/* People slots are portrait, so the motif is too: an empty frame with
   registration marks rather than anything resembling a face. A silhouette
   would be read as a likeness of whoever eventually appears here. */
.v-ph--person{
	background-image:
		url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 99 132' fill='none' stroke='%230A2540' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' opacity='.45'%3E%3Crect x='22' y='26' width='55' height='68' rx='3'/%3E%3Cg stroke='%2300A6D6'%3E%3Cpath d='M16 20v8M16 20h8M83 20h-8M83 20v8M16 100v-8M16 100h8M83 100h-8M83 100v-8'/%3E%3C/g%3E%3Cpath d='M34 108h31' stroke='%2300A6D6'/%3E%3Cpath d='M40 116h19'/%3E%3C/svg%3E"),
		linear-gradient(rgba(10,37,64,.045) 1px,transparent 1px),
		linear-gradient(90deg,rgba(10,37,64,.045) 1px,transparent 1px);
	background-repeat:no-repeat,repeat,repeat;
	background-position:center,0 0,0 0;
	background-size:99px 132px,24px 24px,24px 24px;
}

/* ==========================================================================
   LEADERSHIP & TEAM
   People, not product. The chairman reads as one profile rather than a card in
   a grid; the team below is a grid because those entries are peers.
   ========================================================================== */

.v-chair{
	background: var(--v-white);
	border: 1px solid var(--v-line);
	border-radius: 24px;
	padding: clamp(1.5rem, 1rem + 2.2vw, 3rem);
}
.v-chair .v-photo{ border-radius: 18px; overflow: hidden; }

/* Elementor owns --flex-* and --width on its containers and its stylesheet
   loads after this one, so percentage widths set in the builder are what
   actually apply — and 38% + 62% plus a gap overflows the row and wraps the
   two columns into one. Driving its variables instead lets the portrait keep a
   fixed share and the text take whatever is left, at any width. */
body .v-chair > .e-con:first-child{
	--flex-grow: 0; --flex-shrink: 0; --flex-basis: 36%; --width: auto;
	/* Block, not flex. The portrait sizes itself from aspect-ratio, and as a
	   flex item on a wrapped line it was collapsing to a 23px column that the
	   text then sat on top of. As a block child it simply takes its own
	   height, at every width. */
	display: block;
	align-self: flex-start;
}
body .v-chair > .e-con:last-child{
	--flex-grow: 1; --flex-shrink: 1; --flex-basis: 0%; --width: auto;
	min-width: 0;
	/* Centred against the portrait. A short placeholder biography top-aligned
	   beside a tall portrait leaves an obvious void; real copy will simply
	   fill downwards from the middle. */
	justify-content: center;
}

/* The portrait is a supporting element, not the subject of the page. Capped so
   it stays a profile photograph rather than a poster. */
.v-chair > .e-con:first-child .v-photo{ max-width: 340px; }

@media (max-width: 860px){
	/* Stacked, and the portrait is capped: at full width it became a screen of
	   placeholder before any of the text. */
	body .v-chair > .e-con:first-child,
	body .v-chair > .e-con:last-child{ --flex-basis: 100%; }
	.v-chair > .e-con:first-child .v-photo{ max-width: 300px; }
	/* Centring only makes sense beside the portrait, not beneath it. */
	body .v-chair > .e-con:last-child{ justify-content: flex-start; }
}

.v-chair__role{
	font-family: var(--v-sans);
	font-size: .8125rem;
	letter-spacing: .08em;
	text-transform: uppercase;
	color: var(--v-muted);
	font-weight: 600;
}

/* The message is set apart with a rule rather than quotation marks, which at
   this size read as decoration. */
.v-chair__message{
	border-left: 2px solid var(--vp-cyan);
	padding-left: 1.15rem;
	color: var(--v-body);
}
.v-chair__message p{ margin: 0; }

.v-team__card{
	background: var(--v-white);
	border: 1px solid var(--v-line);
	border-radius: 22px;
	overflow: hidden;
}
.v-team__card .v-photo{ border-radius: 0; border-left: 0; border-right: 0; border-top: 0; }
.v-team__body{ padding: 1.15rem 1.25rem 1.35rem; }
.v-team__name{ font-size: 1.0625rem; margin: 0 0 .35rem; }
.v-team__body p{ margin: 0; font-size: .9375rem; color: var(--v-muted); }

.v-ph--printing{
	background-image:
		url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 132 99' fill='none' stroke='%230A2540' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' opacity='.5'%3E%3Cpath d='M30 26h72v52H30z'/%3E%3Cg stroke='%2300A6D6'%3E%3Cpath d='M24 20v8M24 20h8M108 20h-8M108 20v8M24 84v-8M24 84h8M108 84h-8M108 84v-8'/%3E%3C/g%3E%3Cg fill='%230A2540' stroke='none' opacity='.85'%3E%3Ccircle cx='44' cy='58' r='2'/%3E%3Ccircle cx='56' cy='58' r='3'/%3E%3Ccircle cx='68' cy='58' r='4'/%3E%3Ccircle cx='80' cy='58' r='3'/%3E%3Ccircle cx='92' cy='58' r='2'/%3E%3C/g%3E%3Cg stroke='%2300A6D6'%3E%3Ccircle cx='66' cy='40' r='5'/%3E%3Cpath d='M66 32v16M58 40h16'/%3E%3C/g%3E%3C/svg%3E"),
		linear-gradient(rgba(10,37,64,.045) 1px,transparent 1px),
		linear-gradient(90deg,rgba(10,37,64,.045) 1px,transparent 1px);
}
.v-ph--finishing{
	background-image:
		url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 132 99' fill='none' stroke='%230A2540' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' opacity='.5'%3E%3Cpath d='M66 22 26 40l40 18 40-18-40-18Z'/%3E%3Cpath d='m26 56 40 18 40-18'/%3E%3Cpath d='m26 70 40 18 40-18' stroke='%2300A6D6'/%3E%3C/svg%3E"),
		linear-gradient(rgba(10,37,64,.045) 1px,transparent 1px),
		linear-gradient(90deg,rgba(10,37,64,.045) 1px,transparent 1px);
}
.v-ph--assembly{
	background-image:
		url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 132 99' fill='none' stroke='%230A2540' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' opacity='.5'%3E%3Cpath d='M60 26 32 40l28 14 28-14-28-14Z'/%3E%3Cpath d='M32 40v26l28 14V54'/%3E%3Cpath d='M88 40v26L60 80'/%3E%3Cg stroke='%2300A6D6'%3E%3Ccircle cx='98' cy='68' r='12'/%3E%3Cpath d='m92 68 4.5 5 8-9.5'/%3E%3C/g%3E%3C/svg%3E"),
		linear-gradient(rgba(10,37,64,.045) 1px,transparent 1px),
		linear-gradient(90deg,rgba(10,37,64,.045) 1px,transparent 1px);
}
.v-ph--design{
	background-image:
		url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 132 99' fill='none' stroke='%230A2540' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' opacity='.5'%3E%3Cpath d='M22 30h88v40H22z'/%3E%3Cpath d='M44 30v40M88 30v40' stroke-dasharray='5 5' stroke='%2300A6D6'/%3E%3Cpath d='M22 44h88' stroke-dasharray='5 5' stroke='%2300A6D6'/%3E%3Cpath d='M22 78h88M26 74v8M110 74v8'/%3E%3C/svg%3E"),
		linear-gradient(rgba(10,37,64,.045) 1px,transparent 1px),
		linear-gradient(90deg,rgba(10,37,64,.045) 1px,transparent 1px);
}
.v-ph--sampling{
	background-image:
		url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 132 99' fill='none' stroke='%230A2540' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' opacity='.5'%3E%3Cpath d='M46 34h40v34H46z'/%3E%3Cpath d='m46 34-18 8v34l18-8M86 34l18 8v34l-18-8'/%3E%3Cpath d='M46 68h40' stroke='%2300A6D6'/%3E%3Cpath d='M28 42h18M86 42h18' stroke-dasharray='4 4' stroke='%2300A6D6'/%3E%3C/svg%3E"),
		linear-gradient(rgba(10,37,64,.045) 1px,transparent 1px),
		linear-gradient(90deg,rgba(10,37,64,.045) 1px,transparent 1px);
}
.v-ph--consultation{
	background-image:
		url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 132 99' fill='none' stroke='%230A2540' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' opacity='.5'%3E%3Crect x='22' y='30' width='30' height='40' rx='2'/%3E%3Crect x='56' y='30' width='30' height='40' rx='2'/%3E%3Crect x='90' y='30' width='20' height='40' rx='2' stroke='%2300A6D6'/%3E%3Cpath d='M22 58h30M56 58h30' stroke='%2300A6D6'/%3E%3C/svg%3E"),
		linear-gradient(rgba(10,37,64,.045) 1px,transparent 1px),
		linear-gradient(90deg,rgba(10,37,64,.045) 1px,transparent 1px);
}

/* ==========================================================================
   ARTICLES
   A reading measure, a label chip, and comparison tables that survive a
   360px phone without shrinking the type to nothing.
   ========================================================================== */

/* The shell is 840px; the gutter takes it to roughly a 765px measure, which is
   the reading width this template is specified at and a little tighter than
   the generic 860px container. */
.v-container--article { max-width: 840px; }

.v-post-card__meta { display: flex; align-items: center; flex-wrap: wrap; gap: .55rem; }
.v-post-card__label {
	display: inline-block;
	padding: .26rem .62rem;
	font-size: .6875rem;
	font-weight: 700;
	letter-spacing: .1em;
	text-transform: uppercase;
	color: var(--v-ink);
	background: var(--vp-blue-soft);
	border-radius: var(--v-radius-pill);
	letter-spacing: .09em;
}
/* The headline is the card's main voice; it should not be set at the same
   size as a product card title. */
.v-post-card__title { font-size: 1.125rem; line-height: 1.32; }
.v-post-card__title a { text-decoration: none; }

/* .v-prose caps itself at 68ch, which lands around 686px here — narrower than
   the article shell and narrow enough that the wider comparison tables start
   scrolling on a desktop that has room for them. The article body takes the
   container's measure instead. */
.v-article { max-width: none; }
.v-article h2 { margin-top: 2.4em; }
.v-article h3 { margin-top: 1.8em; }
.v-article ul, .v-article ol { margin-block: 1.1rem; padding-left: 1.35rem; }
.v-article li { margin-bottom: .5rem; }
.v-article li::marker { color: var(--v-accent); }

/* ---------------------------------------------------- comparison tables -- */
/* A three-column comparison cannot be made to fit a 360px screen honestly, so
   it scrolls inside its own region rather than being shrunk to unreadable
   type. The wrapper is focusable and labelled, so the scroll is reachable by
   keyboard and announced rather than being a mouse-only affordance. */
.v-table-scroll {
	overflow-x: auto;
	-webkit-overflow-scrolling: touch;
	margin: 1.6rem 0;
	border: 1px solid var(--v-line);
	border-radius: var(--v-radius-md);
	background: var(--v-white);
}
.v-table-scroll:focus-visible { outline: 2px solid var(--vp-cyan); outline-offset: 2px; }
.v-table-scroll table { margin: 0; min-width: 34rem; border-collapse: collapse; width: 100%; }
.v-prose .v-table-scroll th,
.v-prose .v-table-scroll td {
	padding: .78rem 1rem;
	border-bottom: 1px solid var(--v-line);
	vertical-align: top;
	font-size: .9375rem;
}
.v-prose .v-table-scroll thead th {
	background: var(--vp-blue-soft);
	color: var(--v-ink);
	font-weight: 700;
	white-space: nowrap;
}
.v-prose .v-table-scroll tbody th[scope="row"] {
	font-weight: 600;
	color: var(--v-ink);
	background: var(--v-paper);
	white-space: nowrap;
}
.v-prose .v-table-scroll tr:last-child th,
.v-prose .v-table-scroll tr:last-child td { border-bottom: 0; }

/* ==========================================================================
   DEMONSTRATION CONTENT MARKERS
   One sample project exists so the owner can see and edit the portfolio
   layout before real work is published. It must never be mistakable for
   client work, so it is marked on the card and again on the page — cyan
   rather than the muted grey of a normal .v-flag, because this label is
   information the reader actually needs.
   ========================================================================== */

.v-flag--demo {
	color: var(--v-ink);
	background: var(--vp-blue-soft);
	border: 1px solid var(--vp-cyan);
	margin-bottom: .7rem;
}
.v-demo-note {
	margin: 1.5rem 0 0;
	padding: .95rem 1.15rem;
	background: var(--vp-blue-soft);
	border: 1px solid var(--vp-cyan);
	border-radius: var(--v-radius-md);
	font-size: .9375rem;
	line-height: 1.55;
	color: var(--v-ink);
	max-width: var(--v-max-text);
}

/* ==========================================================================
   SERVICE CARD IMAGE REGION
   The service cards were clean but entirely typographic. Each now opens with
   a 16:10 image region, sized identically across the grid so a row of cards
   never steps. .v-card already clips to the card radius, so the image meets
   the body with no seam and no separate top-radius rule is needed.

   The slot is filled by the service's Featured Image; with none set it wears
   the shared .v-ph press-sheet placeholder, which is deliberately not a
   photograph. Nothing here hard-codes a per-card image URL.
   ========================================================================== */

/* 8:5 — the same ratio the service Featured Images are produced at, so the card
   shows the photographer's framing rather than a crop of a crop. The earlier
   version capped this slot at 230px; because the cap made the frame's height
   indefinite, the child image's height:100% fell back to auto and the photo
   overflowed to its own intrinsic height, leaving the frame showing only the
   top of it. The image is now positioned to fill the frame, so the ratio alone
   governs and every card in a row is exactly the same height. */
.v-svc-card__media { aspect-ratio: 8 / 5; overflow: hidden; }
/* Inside the card the placeholder drops its own frame, as the other media
   slots already do, so the card border stays the only edge. */
.v-card__media.v-svc-card__media.v-ph { aspect-ratio: 8 / 5; }

/* ==========================================================================
   PACKAGING INTRO CALLOUT
   The intro used to be one narrow paragraph on a 1280px row, so two thirds of
   the section was empty and the genuinely useful line — what to send when you
   do not know which construction you need — was buried at the end of it. That
   line is now a callout occupying the space the paragraph was leaving blank.
   It reuses .v-panel rather than inventing a second panel treatment.
   ========================================================================== */

body .e-con.v-help {
	--width: auto;
	--border-radius: var(--v-radius-lg);
	align-self: start;
}
.v-help .v-help__title,
.v-help .v-help__title .elementor-heading-title {
	font-family: var(--v-serif);
	font-size: var(--v-fs-h4);
	line-height: 1.3;
	color: var(--v-ink);
	margin: 0;
}
.v-help p { font-size: .9375rem; line-height: 1.6; color: var(--v-body); margin: 0; }

/* The grid below is introduced by the section above it, so it opens with the
   cards rather than repeating a heading that has just been read. */
.v-cat-grid-section { padding-top: 0; }

/* ==========================================================================
   CAPABILITY CARDS  —  "Manufacturing under one roof"
   The four claims used to sit in a 2x2 hairline table that read as a
   specification sheet rather than as a manufacturer's capabilities. They are
   now four cards: a quiet ordinal, a line icon, a restrained heading and one
   sentence.

   The ordinals and icons are drawn in CSS, not in the markup, for one
   practical reason: everything inside a card is an Elementor heading and an
   Elementor text widget the owner edits directly, and decoration living in
   the stylesheet cannot be deleted by accident while editing copy. The icons
   are custom single-path SVGs carried as data URIs and painted through a
   mask, so they take the palette from CSS, cost no request, and add nothing
   to the accessibility tree — they are decorative and must stay silent.
   ========================================================================== */

.v-cap-grid { counter-reset: v-cap; align-items: stretch; }

.e-con.v-cap > .e-con-inner,
.v-cap {
	background: var(--v-white);
	border: 1px solid var(--v-line);
	border-radius: var(--v-radius-card);
	box-shadow: 0 1px 2px rgba(10, 37, 64, .04);
	transition: box-shadow .18s ease, border-color .18s ease, transform .18s ease;
}
.e-con.v-cap,
.v-cap {
	counter-increment: v-cap;
	position: relative;
	min-width: 0;
	padding: clamp(1.5rem, 1.2rem + .6vw, 1.875rem);
	overflow: hidden;
}
/* Elementor sizes its containers through --flex-* and --border-radius, and
   its .e-con.e-flex rule matches at the same specificity as a two-class
   theme selector while loading later — so a plain `flex:` declaration here
   loses on source order. Setting its variables instead, behind the body
   prefix the rest of this file already uses against the kit, makes the
   builder do the sizing rather than working around it. */
body .e-con.v-cap {
	--flex-grow: 1;
	--flex-shrink: 1;
	--flex-basis: calc(25% - 15px);
	--width: auto;
	--border-radius: var(--v-radius-card);
}

/* Ordinal and icon share the top row of the card.

   The ordinal has to out-specify Elementor. A container's ::before is where
   Elementor paints its background overlay, via `content: var(--background-overlay)`
   — and with no overlay set that variable is undefined, which makes the whole
   declaration invalid at computed-value time. That does not fall back to an
   earlier `content`; it resets the property to its initial value, so a
   same-specificity rule here silently produces no ordinal at all. The body
   prefix is the same shield this file already uses against the kit. These
   cards never carry an Elementor overlay, so nothing is lost by claiming the
   pseudo-element outright. */
.v-cap::after { content: ""; position: absolute; top: clamp(1.5rem, 1.2rem + .6vw, 1.875rem); }
.v-cap::before,
body .e-con.v-cap::before {
	content: counter(v-cap, decimal-leading-zero);
	/* Where the alt-text form is understood the ordinal stays out of the
	   accessibility tree; where it is not, the line above still renders it. */
	content: counter(v-cap, decimal-leading-zero) / "";
	position: absolute;
	top: clamp(1.5rem, 1.2rem + .6vw, 1.875rem);
	left: clamp(1.5rem, 1.2rem + .6vw, 1.875rem);
	font-family: var(--v-sans);
	font-size: .6875rem;
	font-weight: 700;
	letter-spacing: .14em;
	color: var(--v-muted);
	line-height: 1;
}
.v-cap::after {
	right: clamp(1.5rem, 1.2rem + .6vw, 1.875rem);
	width: 22px;
	height: 22px;
	background: none;
}
/* Only paint the glyph where masking is understood; a solid square would be
   worse than no icon at all. */
@supports ((-webkit-mask-image: url("i.svg")) or (mask-image: url("i.svg"))) {
	.v-cap::after {
		background-color: var(--vp-cyan);
		-webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
		-webkit-mask-position: center; mask-position: center;
		-webkit-mask-size: contain; mask-size: contain;
	}
	/* 01 — the facility */
	.v-cap:nth-child(4n+1)::after {
		--v-cap-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M2.5 21h19'/%3E%3Cpath d='M4 21V11l5.5 3.5V11L15 14.5V7.5l4.5 2.2V21'/%3E%3Cpath d='M7 17.5h1.5M12.5 17.5H14'/%3E%3C/svg%3E");
	}
	/* 02 — printing and finishing, as stacked sheets */
	.v-cap:nth-child(4n+2)::after {
		--v-cap-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 3 2.5 7.8 12 12.6l9.5-4.8L12 3Z'/%3E%3Cpath d='m2.5 12.6 9.5 4.8 9.5-4.8'/%3E%3Cpath d='m2.5 17.2 9.5 4.8 9.5-4.8'/%3E%3C/svg%3E");
	}
	/* 03 — specification, as a rule */
	.v-cap:nth-child(4n+3)::after {
		--v-cap-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='2' y='8' width='20' height='8' rx='1.8'/%3E%3Cpath d='M7 8v3.2M12 8v4.4M17 8v3.2'/%3E%3C/svg%3E");
	}
	/* 04 — one process, as a joined workflow */
	.v-cap:nth-child(4n+4)::after {
		--v-cap-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='5' cy='12' r='2.6'/%3E%3Ccircle cx='19' cy='5.8' r='2.6'/%3E%3Ccircle cx='19' cy='18.2' r='2.6'/%3E%3Cpath d='m7.4 10.9 9.2-4.1M7.4 13.1l9.2 4.1'/%3E%3C/svg%3E");
	}
	.v-cap::after {
		-webkit-mask-image: var(--v-cap-icon); mask-image: var(--v-cap-icon);
	}
}

/* The heading is an Elementor heading widget, so the inner title carries the
   type — styling only the wrapper left an h3 at full display size, which is
   how the old table ended up shouting in serif capitals. */
.v-cap .v-cap__title,
.v-cap .v-cap__title .elementor-heading-title {
	font-family: var(--v-sans);
	font-size: 1.0625rem;
	font-weight: 650;
	line-height: 1.3;
	letter-spacing: -.005em;
	color: var(--v-ink);
	text-transform: none;
	margin: 0;
}
.v-cap .v-cap__title { margin-top: 2.35rem; }
.v-cap p {
	font-size: .9375rem;
	line-height: 1.62;
	color: var(--v-body);
	margin: .55rem 0 0;
}

@media (hover: hover) {
	.v-cap:hover {
		border-color: var(--v-line-ui);
		box-shadow: var(--v-shadow);
		transform: translateY(-2px);
	}
}

@media (max-width: 1024px) { body .e-con.v-cap, .v-cap { --flex-basis: calc(50% - 10px); } }
@media (max-width: 600px)  { body .e-con.v-cap, .v-cap { --flex-basis: 100%; } }

/* Outside the builder the grid is a plain element, so it needs the flex box
   and the sizing that Elementor's container variables supply above. This is
   the path the theme falls back to if Elementor is ever deactivated. */
.v-cap-grid:not(.e-con) { display: flex; flex-wrap: wrap; gap: 20px; }
.v-cap-grid:not(.e-con) > .v-cap { flex: 1 1 calc(25% - 15px); }
@media (max-width: 1024px) { .v-cap-grid:not(.e-con) > .v-cap { flex-basis: calc(50% - 10px); } }
@media (max-width: 600px)  { .v-cap-grid:not(.e-con) > .v-cap { flex-basis: 100%; } }

/* ==========================================================================
   QUOTE INFORMATION PANEL
   Three unrelated documentation cards became one panel with a single job:
   tell a visitor what to send. Ink Navy, because the four capability cards
   directly above are pale — a fourth pale card here would have flattened the
   page into one undifferentiated field of boxes.
   ========================================================================== */

body .e-con.v-qp { --border-radius: var(--v-radius-lg); --width: auto; }
body .e-con.v-qp__row { --width: auto; }
.e-con.v-qp,
.v-qp {
	background: var(--v-ink);
	color: rgba(255, 255, 255, .84);
	border-radius: var(--v-radius-lg);
	padding: clamp(1.75rem, 1.2rem + 1.6vw, 2.5rem);
	counter-reset: v-qp;
}
.v-qp .v-qp__title,
.v-qp .v-qp__title .elementor-heading-title {
	font-family: var(--v-serif);
	font-size: var(--v-fs-h3);
	line-height: 1.25;
	color: var(--v-white);
	margin: 0 0 .35rem;
}
.v-qp__rows { width: 100%; }

.e-con.v-qp__row,
.v-qp__row {
	counter-increment: v-qp;
	position: relative;
	padding: 1.15rem 0 1.15rem 2.6rem;
	border-top: 1px solid rgba(255, 255, 255, .14);
}
.v-qp__row:first-child { border-top: 0; }
/* Same Elementor ::before contest as the capability cards above. */
.v-qp__row::before,
body .e-con.v-qp__row::before {
	content: counter(v-qp, decimal-leading-zero);
	content: counter(v-qp, decimal-leading-zero) / "";
	position: absolute;
	left: 0;
	top: 1.35rem;
	font-family: var(--v-sans);
	font-size: .6875rem;
	font-weight: 700;
	letter-spacing: .12em;
	color: var(--vp-cyan);
	line-height: 1;
}
.v-qp .v-qp__row-title,
.v-qp .v-qp__row-title .elementor-heading-title {
	font-family: var(--v-sans);
	font-size: .75rem;
	font-weight: 700;
	letter-spacing: .12em;
	text-transform: uppercase;
	color: var(--v-white);
	margin: 0;
}
.v-qp .v-qp__row p {
	font-size: .9375rem;
	line-height: 1.6;
	color: rgba(255, 255, 255, .8);
	margin: .4rem 0 0;
}
.v-qp .v-qp__foot {
	margin-top: 1.25rem;
	padding-top: 1.15rem;
	border-top: 1px solid rgba(255, 255, 255, .14);
}
.v-qp .v-qp__foot p {
	font-family: var(--v-sans);
	font-size: .8125rem;
	font-weight: 600;
	letter-spacing: .02em;
	color: var(--vp-cyan);
	margin: 0;
}

/* ==========================================================================
   ART DIRECTION LAYER
   Hero presentation and page rhythm. Palette unchanged.
   ========================================================================== */

/* The hero photograph is painted as an Elementor container background, and
   Elementor's container defaults were flattening the panel to square corners
   — the one image on the site that was escaping the rounding system. */
.e-con.v-hero__photo,
.v-hero__photo {
	border-radius: clamp(18px, 2vw, 26px);
	overflow: hidden;
}

