/* RTOS - the public face of Royco Ports Services Ltd.
   Light Frappe "Espresso" styling for www/rtos.html. Extracted from the
   page's inline <style> so it is served as a cacheable asset rather than
   re-downloaded on every visit. Edit here, not in the HTML. */

/* ══ DESIGN TOKENS ═══════════════════════════════════

   The palette is not invented here. It is lifted from the app's own
   login page, which in a comment calls itself "industrial square-
   corner language used across the React tally pages". That is this
   company's house style, so the public site now reads as the same
   product as the login and tally screens instead of as a separate
   marketing template bolted to the side of them.

   The values themselves now live in ONE place,
   public/css/brand-tokens.css, linked ahead of this file by
   www/rtos.html. Everything below that has a brand counterpart is an
   alias onto a --wm-* token rather than a second copy of the hex, so
   a palette change is made once. The local names (--surface,
   --primary, --radius...) are kept because 150-odd rules further
   down already consume them; only the source of the colour changed.

   Type and spacing follow Frappe Desk: the scale lifted out of
   frappe/public/dist/css/desk.bundle.css (--text-tiny 11px up to
   --text-7xl 40px), the Inter stack Desk itself uses, and its
   1px --outline-gray borders. Frappe's own greys and blue are
   deliberately NOT used for the brand surfaces - Desk's grey has
   no place on a page whose logo is gold on navy. */
:root {
	/* Surfaces & lines. White and the pale greys are Frappe's, not the
	   brand's, so they stay literal here; paper and line are shared. */
	--surface: #ffffff;
	--surface-2: var(--wm-paper);
	--surface-3: #f1f5f9;
	--line: var(--wm-line);
	--line-soft: #edf2f7;

	/* Ink. The two brand steps both clear AA on white and on
	   --surface-2; Desk's own gray-800 (#383838) does not get close on
	   the navy panels. */
	--ink: var(--wm-navy);
	--body: var(--wm-ink);
	--muted: var(--wm-muted);

	/* Interactive. Cyan is the focus/active accent from login.css;
	   the darker step is what carries white button text. */
	--primary: var(--wm-navy);
	--primary-hover: var(--wm-navy-2);
	--primary-tint: #f2fdfb;
	--primary-line: #99f6e4;

	/* Brand gold. Gold is a heading and rule colour, never a text
	   colour on white: --wm-gold is 2.1:1 there. --wm-gold-2 is the
	   readable step. */
	--gold: var(--wm-gold);
	--accent: var(--wm-gold-2);
	--accent-tint: #fdfaed;
	--accent-line: #f1e2b0;

	--navy: var(--wm-navy);
	/* Caption text on a navy scrim over a photo. */
	--sky-soft: #a5d8d3;

	/* Square. The React tally pages and the login page are all
	   square-cornered, and a rounded one is the loudest signal that
	   a page came from a generator rather than from this codebase. */
	--radius-sm: var(--wm-radius);
	--radius: var(--wm-radius);
	--radius-md: var(--wm-radius);
	--radius-lg: var(--wm-radius);
	--radius-full: var(--wm-radius);

	/* Flat. login.css leans on a 1px border and almost no shadow;
	   the heavy drop shadows here were the second giveaway. */
	--shadow-sm: 0 1px 2px rgba(15, 23, 42, .05);
	--shadow: 0 1px 2px rgba(15, 23, 42, .04), 0 8px 24px -16px rgba(15, 23, 42, .18);

	/* Tall enough to hold the logo at its original 100px. On the
	   old site a 100px logo hung 20px out of an 80px header and
	   over a dark hero, so the bleed read as deliberate; over a
	   white header it would just overlap whatever scrolled
	   underneath, so the bar is sized to contain it instead. */
	--header-h: 112px;
}

/* ══ BASE ════════════════════════════════════════════ */
html {
	scroll-behavior: smooth;
	/* Anchors land clear of the fixed header. */
	scroll-padding-top: calc(var(--header-h) + 16px);
}

/* ── Reduced motion ─────────────────────────────────
   AOS is switched off at runtime by the `disable` callback in its
   init (which strips the data-aos attributes outright), so these
   rules only have to cover the CSS-driven motion: smooth scrolling
   and the header condensing. */
@media (prefers-reduced-motion: reduce) {

	html {
		scroll-behavior: auto;
	}

	*,
	*::before,
	*::after {
		animation-duration: .01ms !important;
		animation-iteration-count: 1 !important;
		transition-duration: .01ms !important;
		scroll-behavior: auto !important;
	}
}

body {
	font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
		"Helvetica Neue", Arial, sans-serif;
	background: var(--surface);
	color: var(--body);
	font-size: 16px;
	line-height: 1.6;
	-webkit-font-smoothing: antialiased;
	/* AOS parks every below-the-fold [data-aos] element at its animation
	   start state - a 100px translate - until it scrolls into view. Those
	   transforms counted toward the document's scroll width, so the page
	   grew a horizontal scrollbar that vanished again once you scrolled.

	   `clip` rather than `hidden`: hidden would make body a scroll
	   container, which breaks smooth scrolling and scroll anchoring.
	   `clip` does not create one, and the fixed header is unaffected. */
	overflow-x: clip;
}

section {
	padding: 88px 0;
	position: relative;
}

h1,
h2,
h3,
h4,
h5,
h6 {
	font-family: inherit;
	color: var(--ink);
	letter-spacing: -.02em;
	font-weight: 700;
}

a {
	color: var(--primary-hover);
}

/* Content is hidden until AOS animates it (aos.css forces
   opacity:0). If the script never runs, the page would come up
   blank - the .aos-off escape hatch in the init script below
   reveals everything instead. */
.aos-off [data-aos] {
	opacity: 1 !important;
	transform: none !important;
}

/* ══ SHARED BITS ═════════════════════════════════════ */

/* Left-aligned, not centred, and headed by a square gold rule rather than
   a centred gradient pill. The centred-heading-plus-gradient-divider under
   every section is the single most recognisable thing about a generated
   landing page; login.css leads with a flush-left gold rule instead. */
.section-title {
	text-align: left;
	margin-bottom: 2.5rem;
	max-width: 46rem;
}

.section-tag {
	display: inline-block;
	font-size: 11px;
	font-weight: 600;
	letter-spacing: .08em;
	text-transform: uppercase;
	color: var(--accent);
	border: 1px solid var(--accent-line);
	background: var(--accent-tint);
	padding: .3rem .6rem;
	margin-bottom: .9rem;
}

.section-title h2 {
	font-size: 30px;
	line-height: 1.2;
	font-weight: 700;
	color: var(--ink);
	margin-bottom: .7rem;
	letter-spacing: -.015em;
}

.section-title p {
	color: var(--muted);
	max-width: 42rem;
	margin: 0;
	font-size: 15px;
	line-height: 1.6;
}

.divider {
	width: 46px;
	height: 2px;
	background: var(--gold);
	margin: 0 0 1.15rem;
}

/* ── Buttons ─────────────────────────────────────── */

/* Square, flat, and they do not lift on hover. The translateY(-1px) plus
   a coloured glow was decoration; Frappe's own buttons are a solid fill
   that darkens, and login.css does the same. */
.btn-primary-app,
.btn-outline-app {
	display: inline-flex;
	align-items: center;
	gap: .5rem;
	font-size: 14px;
	font-weight: 600;
	padding: .6rem 1.1rem;
	border-radius: var(--radius);
	text-decoration: none;
	border: 1px solid transparent;
	cursor: pointer;
	transition: background-color .16s ease, border-color .16s ease, color .16s ease;
}

.btn-primary-app {
	background: var(--primary);
	color: #fff;
	border-color: var(--primary);
}

.btn-primary-app:hover {
	background: var(--primary-hover);
	border-color: var(--primary-hover);
	color: #fff;
}

.btn-outline-app {
	background: var(--surface);
	border-color: var(--line);
	color: var(--ink);
}

.btn-outline-app:hover {
	border-color: var(--ink);
	color: var(--ink);
	background: var(--surface-3);
}

/* ── Header ──────────────────────────────────────── */
#header {
	position: fixed;
	top: 0;
	left: 0;
	right: 0;
	height: var(--header-h);
	z-index: 900;
	background: rgba(255, 255, 255, .88);
	backdrop-filter: saturate(180%) blur(12px);
	-webkit-backdrop-filter: saturate(180%) blur(12px);
	border-bottom: 1px solid var(--line-soft);
	transition: box-shadow .2s, background-color .2s, height .25s ease;
}

/* A 112px bar costs a laptop viewport 12% of its height, permanently.
   Once the reader is past the hero the mark condenses to 56px, and comes
   straight back on the way up so the nav is reachable. At rest - top of
   page - the mark is still the 100px it has always been. */
#header.condensed {
	--header-h: 68px;
}

@media (max-width: 768px) {

	#header.condensed {
		--header-h: 62px;
	}
}

#header.scrolled {
	box-shadow: var(--shadow-sm);
	background: rgba(255, 255, 255, .96);
}

#header .container-fluid {
	height: 100%;
}

/* The mark keeps the 100px it has always had. The navy plate that
   used to carry it is gone - the gold sits straight on the bar. */
.brand {
	display: inline-flex;
	align-items: center;
	text-decoration: none;
}

.brand img {
	height: 100px;
	width: auto;
	display: block;
	/* Never let the bar squeeze it - a squashed mark reads as a
	   rendering fault rather than a layout one. */
	flex: none;
	transition: height .25s ease;
}

#header.condensed .brand img {
	height: 56px;
}

.navmenu ul {
	list-style: none;
	padding: 0;
	margin: 0;
	display: flex;
	align-items: center;
	gap: .35rem;
}

.navmenu ul li a {
	font-size: .925rem;
	font-weight: 500;
	color: var(--body) !important;
	text-decoration: none;
	padding: .5rem .8rem;
	border-radius: var(--radius-sm);
	transition: background-color .15s, color .15s;
}

.navmenu ul li a:hover,
.navmenu ul li a.active {
	color: var(--primary-hover) !important;
	background: var(--primary-tint);
}

.navmenu ul li .btn {
	background: var(--surface);
	border: 1px solid var(--line);
	color: var(--body) !important;
	padding: .42rem .9rem;
	border-radius: var(--radius-sm);
	font-size: .9rem;
	font-weight: 500;
	margin-left: .25rem;
}

.navmenu ul li .btn:hover {
	background: var(--surface-3);
	border-color: var(--line);
	color: var(--ink) !important;
}

.btn-login {
	display: inline-flex;
	align-items: center;
	gap: .4rem;
	background: var(--ink) !important;
	color: #fff !important;
	font-weight: 600;
	font-size: .9rem;
	padding: .5rem 1.1rem;
	border-radius: var(--radius);
	text-decoration: none;
	transition: background-color .18s, transform .15s;
}

.btn-login:hover {
	background: #000 !important;
	color: #fff !important;
	transform: translateY(-1px);
}

.mobile-nav-toggle {
	font-size: 1.5rem;
	color: var(--body);
	cursor: pointer;
	user-select: none;
	padding: .25rem;
}

/* ── Mobile nav ──────────────────────────────────── */
@media (max-width: 1199.98px) {
	.navmenu {
		position: fixed;
		top: var(--header-h);
		left: 0;
		right: 0;
		background: var(--surface);
		border-bottom: 1px solid var(--line);
		box-shadow: var(--shadow);
		padding: .75rem 1.25rem 1.25rem;
		display: none;
	}

	body.mobile-nav-active .navmenu {
		display: block;
	}

	.navmenu ul {
		flex-direction: column;
		align-items: stretch;
		gap: .15rem;
	}

	.navmenu ul li a {
		display: block;
		padding: .7rem .8rem;
		font-size: 1rem;
	}

	.navmenu ul li .btn {
		display: block;
		text-align: center;
		margin: .35rem 0 0;
		padding: .7rem .8rem;
		font-size: 1rem;
	}
}

/* ── Hero ────────────────────────────────────────── */
.hero {
	position: relative;
	min-height: 100vh;
	display: flex;
	align-items: center;
	overflow: hidden;
	padding: calc(var(--header-h) + 60px) 0 72px;
}

.hero img {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
	object-position: center;
	z-index: 0;
}

/* White scrim, heaviest behind the text column and clearing
   towards the right so the photograph still reads. */
.hero::after {
	content: '';
	position: absolute;
	inset: 0;
	z-index: 1;
	background:
		linear-gradient(90deg, rgba(255, 255, 255, .97) 0%, rgba(255, 255, 255, .93) 34%, rgba(255, 255, 255, .6) 62%, rgba(255, 255, 255, .12) 100%),
		linear-gradient(0deg, rgba(255, 255, 255, .8) 0%, transparent 45%);
}

.hero::before {
	content: '';
	position: absolute;
	bottom: 0;
	left: 0;
	width: 100%;
	height: 4px;
	background: var(--gold);
	z-index: 3;
}

.hero .container {
	position: relative;
	z-index: 2;
}

.hero-eyebrow {
	display: inline-flex;
	align-items: center;
	gap: .6rem;
	font-size: .8rem;
	font-weight: 700;
	letter-spacing: .14em;
	text-transform: uppercase;
	color: var(--accent);
	background: var(--accent-tint);
	border: 1px solid var(--accent-line);
	padding: .35rem .9rem;
	border-radius: var(--radius-full);
	margin-bottom: 1.4rem;
}

.hero-eyebrow::before {
	content: '';
	display: block;
	width: 20px;
	height: 2px;
	background: var(--accent);
}

.hero h2 {
	font-size: clamp(2.5rem, 5.6vw, 4.25rem);
	font-weight: 800;
	line-height: 1.05;
	letter-spacing: -.03em;
	color: var(--navy);
	margin-bottom: 1.4rem;
}

.hero h2 span {
	color: var(--accent);
}

.hero p {
	font-size: 1.1rem;
	color: var(--body);
	max-width: 520px;
	line-height: 1.75;
	margin-bottom: 2.25rem;
}

.hero-btns {
	display: flex;
	gap: .85rem;
	flex-wrap: wrap;
}

/* ── Stats bar ───────────────────────────────────── */
.stats-bar {
	background: var(--surface-2);
	border-top: 1px solid var(--line-soft);
	border-bottom: 1px solid var(--line-soft);
}

.stat-item {
	text-align: center;
	padding: 2.1rem 1.25rem;
	border-right: 1px solid var(--line);
}

.stat-item:last-child {
	border-right: none;
}

.stat-number {
	font-size: 2.35rem;
	font-weight: 800;
	letter-spacing: -.03em;
	color: var(--navy);
	line-height: 1;
	margin-bottom: .45rem;
}

.stat-label {
	font-size: .75rem;
	font-weight: 600;
	letter-spacing: .1em;
	text-transform: uppercase;
	color: var(--muted);
}

/* ── About ───────────────────────────────────────── */
#about {
	background: var(--surface);
}

.about-text p {
	font-size: 1rem;
	color: var(--body);
	line-height: 1.8;
	margin-bottom: 1.1rem;
}

.about-highlight {
	background: var(--accent-tint);
	border: 1px solid var(--accent-line);
	border-left: 3px solid var(--gold);
	border-radius: var(--radius);
	padding: 1.35rem 1.6rem;
	margin-top: 1.75rem;
}

.about-highlight p {
	font-style: italic;
	color: var(--accent);
	font-size: 1.02rem;
	margin: 0;
}

/* ── Services ────────────────────────────────────── */
#services {
	background: var(--surface-2);
	border-top: 1px solid var(--line-soft);
	border-bottom: 1px solid var(--line-soft);
}

.service-card {
	background: var(--surface);
	border: 1px solid var(--line);
	border-radius: var(--radius-lg);
	padding: 1.9rem;
	height: 100%;
	position: relative;
	overflow: hidden;
	transition: transform .2s, border-color .2s, box-shadow .2s;
}

.service-card::before {
	content: '';
	position: absolute;
	top: 0;
	left: 0;
	right: 0;
	height: 3px;
	background: var(--gold);
	transform: scaleX(0);
	transform-origin: left;
	transition: transform .28s;
}

.service-card:hover {
	border-color: var(--gold);
	box-shadow: var(--shadow);
}

.service-card:hover::before {
	transform: scaleX(1);
}

.service-icon {
	width: 48px;
	height: 48px;
	background: var(--primary-tint);
	border: 1px solid var(--primary-line);
	border-radius: var(--radius);
	display: flex;
	align-items: center;
	justify-content: center;
	font-size: 1.3rem;
	color: var(--primary-hover);
	margin-bottom: 1.15rem;
	transition: background-color .2s;
}

.service-card:hover .service-icon {
	background: #e4f2ff;
}

.service-card h4 {
	font-size: 1.1rem;
	font-weight: 700;
	color: var(--ink);
	margin-bottom: .6rem;
}

.service-card p {
	font-size: .9rem;
	color: var(--muted);
	line-height: 1.7;
	margin: 0;
}

/* ── About mosaic ────────────────────────────────── */
.about-mosaic {
	display: grid;
	grid-template-columns: 1fr 1fr;
	gap: .75rem;
	height: 420px;
}

.mosaic-main {
	position: relative;
	border-radius: var(--radius-lg);
	overflow: hidden;
	grid-row: span 2;
}

.mosaic-main img,
.mosaic-thumb img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
	transition: transform .5s ease;
}

.mosaic-main:hover img {
	transform: scale(1.04);
}

.mosaic-badge {
	position: absolute;
	bottom: 1rem;
	left: 1rem;
	right: 1rem;
	background: rgba(255, 255, 255, .94);
	backdrop-filter: blur(8px);
	-webkit-backdrop-filter: blur(8px);
	border: 1px solid var(--line);
	border-radius: var(--radius-sm);
	padding: .55rem .9rem;
	font-size: .85rem;
	font-weight: 600;
	color: var(--accent);
	display: flex;
	align-items: center;
	gap: .5rem;
}

.mosaic-side {
	display: flex;
	flex-direction: column;
	gap: .75rem;
}

.mosaic-thumb {
	position: relative;
	border-radius: var(--radius-lg);
	overflow: hidden;
	flex: 1;
}

.mosaic-thumb:hover img {
	transform: scale(1.06);
}

.mosaic-overlay {
	position: absolute;
	inset: 0;
	background: linear-gradient(0deg, rgba(14, 37, 58, .78) 0%, transparent 60%);
	display: flex;
	align-items: flex-end;
	padding: .8rem;
}

.mosaic-overlay span {
	font-size: .85rem;
	font-weight: 600;
	letter-spacing: .05em;
	text-transform: uppercase;
	color: #fff;
}

.mosaic-stat-card {
	background: linear-gradient(135deg, var(--navy) 0%, #16324f 100%);
	border-radius: var(--radius-lg);
	padding: 1.15rem;
	text-align: center;
	flex-shrink: 0;
}

.mscard-val {
	font-size: 2rem;
	font-weight: 800;
	letter-spacing: -.03em;
	color: var(--gold);
	line-height: 1;
	margin-bottom: .25rem;
}

.mscard-label {
	font-size: .72rem;
	font-weight: 600;
	letter-spacing: .08em;
	text-transform: uppercase;
	color: rgba(255, 255, 255, .75);
}

/* ── Photo gallery strip ─────────────────────────── */
.gallery-strip {
	padding: 0;
	overflow: hidden;
}

.gallery-strip-inner {
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	height: 320px;
}

.gallery-strip-item {
	position: relative;
	overflow: hidden;
}

.gallery-strip-item img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
	transition: transform .5s ease, filter .3s;
	filter: saturate(.95);
}

.gallery-strip-item:hover img {
	transform: scale(1.06);
	filter: saturate(1.05);
}

.gallery-strip-item .strip-caption {
	position: absolute;
	bottom: 0;
	left: 0;
	right: 0;
	padding: 1rem 1.25rem;
	background: linear-gradient(0deg, rgba(14, 37, 58, .88) 0%, transparent 100%);
	font-size: .9rem;
	font-weight: 600;
	letter-spacing: .06em;
	text-transform: uppercase;
	color: #fff;
	transform: translateY(4px);
	transition: transform .3s;
}

.gallery-strip-item:hover .strip-caption {
	transform: translateY(0);
}

.gallery-strip-item .strip-caption span {
	display: block;
	font-size: .75rem;
	font-weight: 400;
	color: var(--sky-soft);
	letter-spacing: .03em;
	text-transform: none;
	margin-top: .1rem;
}

/* ── News / case study ───────────────────────────── */
#casestudy {
	background: var(--surface);
	overflow: hidden;
}

.bg-text {
	position: absolute;
	top: 50%;
	left: 50%;
	transform: translate(-50%, -50%);
	font-size: clamp(6rem, 18vw, 15rem);
	font-weight: 800;
	letter-spacing: -.04em;
	/* Was rgba(2, 137, 247, .05) - the old blue. This is the giant
	   watermark word behind the mosaic, so it only has to read as a
	   tint; navy at 4% does that without dragging a second brand
	   colour onto the page. */
	color: rgba(11, 37, 64, .04);
	white-space: nowrap;
	pointer-events: none;
	user-select: none;
	z-index: 0;
}

#casestudy .container {
	position: relative;
	z-index: 1;
}

.story {
	padding-bottom: 3.25rem;
	margin-bottom: 3.25rem;
	border-bottom: 1px solid var(--line-soft);
}

.story:last-child {
	padding-bottom: 0;
	margin-bottom: 0;
	border-bottom: none;
}

.case-badge {
	display: inline-flex;
	align-items: center;
	gap: .45rem;
	background: var(--accent-tint);
	border: 1px solid var(--accent-line);
	color: var(--accent);
	font-size: .76rem;
	font-weight: 700;
	letter-spacing: .08em;
	text-transform: uppercase;
	padding: .3rem .8rem;
	border-radius: var(--radius-full);
	margin-bottom: 1.15rem;
}

.case-badge.is-blue {
	background: var(--primary-tint);
	border-color: var(--primary-line);
	color: var(--primary-hover);
}

.case-headline {
	font-size: clamp(1.65rem, 3.4vw, 2.4rem);
	font-weight: 800;
	letter-spacing: -.025em;
	color: var(--ink);
	line-height: 1.15;
	margin-bottom: 1rem;
}

.case-headline span {
	color: var(--accent);
}

.case-headline .blue {
	color: var(--primary-hover);
}

.case-body {
	font-size: 1rem;
	color: var(--body);
	line-height: 1.8;
	margin-bottom: 1.25rem;
}

/* ── Live throughput ────────────────────────────────
   Shaped like a Frappe list view rather than a marketing
   chart: a hairline-framed table, muted uppercase column
   heads, right-aligned tabular figures, and a scaled bar
   in the row header. It is a real <table>, so the numbers
   are readable and selectable without JavaScript - the bar
   is decoration on top, not the only representation. */

.sr-only {
	position: absolute;
	width: 1px;
	height: 1px;
	padding: 0;
	margin: -1px;
	overflow: hidden;
	clip: rect(0, 0, 0, 0);
	white-space: nowrap;
	border: 0;
}

.throughput {
	background: var(--surface-2);
	border-top: 1px solid var(--line);
	border-bottom: 1px solid var(--line);
}

.throughput .section-title {
	margin-bottom: 2rem;
}

/* The five monthly figures. Square, 1px border, no shadow: the
   same tile Frappe uses for a stat in a dashboard card. */
.total-grid {
	display: grid;
	grid-template-columns: repeat(5, 1fr);
	gap: 1px;
	background: var(--line);
	border: 1px solid var(--line);
	list-style: none;
	padding: 0;
	margin: 0 0 2.25rem;
}

.total-tile {
	background: var(--surface);
	padding: 1.15rem 1.1rem;
}

.total-value {
	display: block;
	font-size: 26px;
	line-height: 1.1;
	font-weight: 700;
	color: var(--ink);
	letter-spacing: -.02em;
	font-variant-numeric: tabular-nums;
}

/* Turnaround is a duration, so it carries a unit while the other four
   tiles are bare counts. Set at the value's size so the baseline and the
   optical weight match - a small "min" reads as an afterthought, and a
   full-size one would shout over the number it belongs to. */
.total-value-time .unit {
	font-size: .58em;
	font-weight: 600;
	letter-spacing: .01em;
	margin-left: .18em;
	color: var(--muted);
}

.total-label {
	display: block;
	margin-top: .35rem;
	font-size: 11px;
	font-weight: 600;
	letter-spacing: .06em;
	text-transform: uppercase;
	color: var(--muted);
}

.throughput-note {
	margin: 1rem 0 0;
	font-size: 12px;
	color: var(--muted);
	max-width: 46rem;
}

@media (max-width: 991px) {
	.total-grid {
		grid-template-columns: repeat(3, 1fr);
	}
}

@media (max-width: 575px) {
	.total-grid {
		grid-template-columns: repeat(2, 1fr);
	}

	.total-value {
		font-size: 22px;
	}
}

/* ── Metric pills ────────────────────────────────── */
.metric-row {
	display: flex;
	flex-wrap: wrap;
	gap: .7rem;
	margin-bottom: 2rem;
}

.metric-pill {
	background: var(--surface-2);
	border: 1px solid var(--line);
	border-radius: var(--radius-full);
	padding: .5rem 1.2rem;
	text-align: center;
}

.metric-pill strong {
	display: block;
	font-size: 1.35rem;
	font-weight: 800;
	letter-spacing: -.02em;
	color: var(--accent);
	line-height: 1.15;
}

.metric-pill span {
	font-size: .7rem;
	color: var(--muted);
	font-weight: 500;
}

/* ── Outcome cards ───────────────────────────────── */
.outcome-grid {
	display: grid;
	grid-template-columns: repeat(2, 1fr);
	gap: .9rem;
	margin-bottom: 2rem;
}

@media (max-width: 575.98px) {
	.outcome-grid {
		grid-template-columns: 1fr;
	}
}

.outcome-card {
	background: var(--surface);
	border: 1px solid var(--line);
	border-radius: var(--radius);
	padding: 1.05rem 1.15rem;
	display: flex;
	align-items: flex-start;
	gap: .85rem;
	transition: border-color .2s, box-shadow .2s;
}

.outcome-card:hover {
	border-color: var(--primary-line);
	box-shadow: var(--shadow-sm);
}

.outcome-icon {
	width: 34px;
	height: 34px;
	flex-shrink: 0;
	display: flex;
	align-items: center;
	justify-content: center;
	border-radius: var(--radius-sm);
	background: var(--primary-tint);
	color: var(--primary-hover);
	font-size: 1rem;
}

.outcome-card h6 {
	font-size: .9rem;
	font-weight: 700;
	color: var(--ink);
	margin-bottom: .2rem;
}

.outcome-card p {
	font-size: .82rem;
	color: var(--muted);
	margin: 0;
	line-height: 1.55;
}

/* ── Quotes ──────────────────────────────────────── */
.quote-block {
	background: var(--surface-2);
	border: 1px solid var(--line-soft);
	border-left: 3px solid var(--primary);
	border-radius: var(--radius);
	padding: 1.3rem 1.5rem;
	margin-bottom: .85rem;
}

.quote-block blockquote {
	font-style: italic;
	color: var(--body);
	font-size: .93rem;
	line-height: 1.7;
	margin: 0 0 .5rem;
}

.quote-block cite {
	font-size: .78rem;
	color: var(--muted);
	font-style: normal;
	font-weight: 600;
}

/* ── Timeline ────────────────────────────────────── */
.panel {
	background: var(--surface);
	border: 1px solid var(--line);
	border-radius: var(--radius-lg);
	padding: 1.6rem;
	box-shadow: var(--shadow-sm);
}

.panel-title {
	font-size: .76rem;
	font-weight: 700;
	letter-spacing: .1em;
	text-transform: uppercase;
	color: var(--primary-hover);
	margin-bottom: 1.15rem;
}

.timeline {
	position: relative;
	padding-left: 1.75rem;
}

.timeline::before {
	content: '';
	position: absolute;
	left: 5px;
	top: 6px;
	bottom: 6px;
	width: 2px;
	background: var(--line);
}

.timeline-item {
	position: relative;
	margin-bottom: 1.3rem;
}

.timeline-item:last-child {
	margin-bottom: 0;
}

.timeline-item::before {
	content: '';
	position: absolute;
	left: -1.75rem;
	top: .28rem;
	width: 12px;
	height: 12px;
	border-radius: 50%;
	background: var(--primary);
	border: 2px solid var(--surface);
}

.timeline-year {
	font-size: .8rem;
	font-weight: 700;
	letter-spacing: .06em;
	text-transform: uppercase;
	color: var(--accent);
	margin-bottom: .2rem;
}

.timeline-item p {
	font-size: .85rem;
	color: var(--muted);
	margin: 0;
	line-height: 1.6;
}

/* ── Figure / media blocks ────────────────────────── */
.figure {
	background: var(--surface);
	border: 1px solid var(--line);
	border-radius: var(--radius-lg);
	padding: .6rem;
	box-shadow: var(--shadow-sm);
}

.figure img {
	width: 100%;
	display: block;
	border-radius: var(--radius-md);
}

.figure-caption {
	font-size: .74rem;
	font-weight: 600;
	letter-spacing: .07em;
	text-transform: uppercase;
	color: var(--muted);
	text-align: center;
	padding: .7rem .25rem .25rem;
}

/* ── QR panel ────────────────────────────────────── */
.qr-panel {
	background: var(--surface-2);
	border: 1px solid var(--line);
	border-radius: var(--radius-lg);
	padding: 1.5rem;
	margin-top: 1.25rem;
	text-align: center;
}

.qr-panel .panel-title {
	margin-bottom: 1rem;
}

.qr-frame {
	background: #fff;
	border: 1px solid var(--line);
	border-radius: var(--radius-md);
	padding: .85rem;
	display: inline-block;
	line-height: 0;
}

.qr-frame svg {
	display: block;
}

/* ── Partner badges ──────────────────────────────── */
.partner-badge {
	background: var(--surface-2);
	border: 1px solid var(--line);
	border-radius: var(--radius-sm);
	padding: .3rem .7rem;
	font-size: .68rem;
	font-weight: 700;
	letter-spacing: .08em;
	text-transform: uppercase;
	color: var(--muted);
}

/* ── Contact ─────────────────────────────────────── */
#contact {
	background: var(--surface-2);
	border-top: 1px solid var(--line-soft);
}

.info-item {
	background: var(--surface);
	border: 1px solid var(--line);
	border-radius: var(--radius-lg);
	padding: 1.6rem;
	text-align: center;
	height: 100%;
	transition: border-color .2s, transform .2s, box-shadow .2s;
}

.info-item:hover {
	border-color: var(--primary-line);
	transform: translateY(-3px);
	box-shadow: var(--shadow-sm);
}

.info-item i {
	width: 46px;
	height: 46px;
	margin: 0 auto .85rem;
	display: flex;
	align-items: center;
	justify-content: center;
	font-size: 1.2rem;
	background: var(--accent-tint);
	border: 1px solid var(--accent-line);
	border-radius: var(--radius);
	color: var(--accent);
}

.info-item h3 {
	font-size: .8rem;
	font-weight: 700;
	letter-spacing: .09em;
	text-transform: uppercase;
	color: var(--ink);
	margin-bottom: .45rem;
}

.info-item p {
	font-size: .875rem;
	color: var(--muted);
	margin: 0;
	line-height: 1.7;
}

.contact-form-wrapper {
	background: var(--surface);
	border: 1px solid var(--line);
	border-radius: var(--radius-lg);
	padding: 2.25rem;
	height: 100%;
}

.contact-form .form-control {
	background: var(--surface);
	border: 1px solid var(--line);
	color: var(--ink);
	border-radius: var(--radius);
	padding: .7rem .9rem;
	font-size: .9rem;
	transition: border-color .18s, box-shadow .18s;
}

.contact-form .form-control:focus {
	border-color: var(--primary);
	background: var(--surface);
	color: var(--ink);
	/* Was rgba(2, 137, 247, .14) - a blue left over from the old
	   palette, now invisible against the navy brand. A solid 2px
	   ring reads more clearly than a soft glow anyway, and the
	   border-colour change above is the primary focus signal. */
	box-shadow: 0 0 0 2px var(--primary-tint), 0 0 0 4px var(--primary-line);
	outline: none;
}

.contact-form .form-control::placeholder {
	color: var(--muted);
	opacity: 1;
}

.contact-form button[type=submit] {
	background: var(--primary);
	color: #fff;
	border: none;
	border-radius: var(--radius);
	padding: .75rem 2.25rem;
	font-size: .95rem;
	font-weight: 600;
	cursor: pointer;
	transition: background-color .18s, transform .15s;
}

.contact-form button[type=submit]:hover {
	background: var(--primary-hover);
	transform: translateY(-1px);
}

/* The form status line. Hidden until the submit handler says otherwise, and
   driven by an .is-shown class rather than the bootstrap d-block the old
   validate.js used, so the page no longer depends on that script. */
.contact-form .form-status {
	display: none;
	border-radius: var(--radius);
	padding: .8rem 1rem;
	margin-bottom: 1.25rem;
	font-size: .875rem;
	font-weight: 500;
}

.contact-form .form-status.is-shown {
	display: block;
}

.contact-form .loading {
	background: var(--surface-3);
	color: var(--muted);
	text-align: center;
}

.contact-form .error-message {
	background: #fef2f2;
	border: 1px solid #fecaca;
	color: #b42318;
	text-align: left;
}

.contact-form .sent-message {
	background: #ecfdf3;
	border: 1px solid #abefc6;
	color: #067647;
}

/* Honeypot: off-screen rather than display:none, so a bot reading the DOM
   still finds an input worth filling but nobody can see or tab to it. */
.hp-field {
	position: absolute;
	width: 1px;
	height: 1px;
	padding: 0;
	margin: -1px;
	overflow: hidden;
	clip: rect(0 0 0 0);
	white-space: nowrap;
	border: 0;
}

.contact-form .loading {
	background: var(--surface-3);
	color: var(--muted);
	text-align: center;
}

.contact-form .error-message {
	background: #fef2f2;
	border: 1px solid #fecaca;
	color: #b42318;
}

.contact-form .sent-message {
	background: #ecfdf3;
	border: 1px solid #abefc6;
	color: #067647;
}

/* ── Footer ──────────────────────────────────────── */
#footer {
	background: var(--surface-3);
	border-top: 1px solid var(--line);
	padding-top: 3.25rem;
}

.footer-brand {
	font-size: 1.3rem;
	font-weight: 800;
	letter-spacing: -.02em;
	color: var(--ink);
	margin-bottom: .75rem;
}

.footer-brand span {
	color: var(--accent);
}

#footer p,
#footer address {
	font-size: .875rem;
	color: var(--muted);
	line-height: 1.8;
}

.footer-links h4,
.footer-contact h4 {
	font-size: .8rem;
	font-weight: 700;
	letter-spacing: .1em;
	text-transform: uppercase;
	color: var(--ink);
	margin-bottom: .9rem;
}

.footer-links ul {
	list-style: none;
	padding: 0;
	margin: 0;
}

.footer-links ul li {
	margin-bottom: .4rem;
}

.footer-links ul li a {
	font-size: .875rem;
	color: var(--muted);
	text-decoration: none;
	transition: color .15s;
}

.footer-links ul li a:hover {
	color: var(--primary-hover);
}

.footer-bottom {
	border-top: 1px solid var(--line);
	padding: 1.25rem 0;
	margin-top: 2.25rem;
	font-size: .8rem;
	color: var(--muted);
}

.footer-bottom a {
	color: var(--primary-hover);
	text-decoration: none;
}

.footer-bottom a:hover {
	text-decoration: underline;
}

/* ── Scroll top ──────────────────────────────────── */
#scroll-top {
	position: fixed;
	visibility: hidden;
	opacity: 0;
	right: 20px;
	bottom: 20px;
	z-index: 9999;
	width: 42px;
	height: 42px;
	border-radius: 50%;
	background: var(--primary);
	color: #fff;
	text-decoration: none;
	align-items: center;
	justify-content: center;
	transition: opacity .25s, visibility .25s, background-color .2s, transform .15s;
}

#scroll-top i {
	font-size: 1.2rem;
	line-height: 0;
}

#scroll-top:hover {
	background: var(--primary-hover);
	transform: translateY(-2px);
}

#scroll-top.active {
	visibility: visible;
	opacity: 1;
}

/* ── Preloader ───────────────────────────────────── */
#preloader {
	position: fixed;
	inset: 0;
	z-index: 9998;
	overflow: hidden;
	background: var(--surface);
}

/* This is an opaque full-viewport panel that script removes on load. Left
   unguarded, a visitor with scripting off gets a blank white screen and no
   way out - the same failure the .no-js class exists to prevent, so the
   spinner only ever appears where script is running to take it away. */
html.no-js #preloader {
	display: none;
}

#preloader div {
	width: 13px;
	height: 13px;
	background: var(--primary);
	border-radius: 50%;
	animation-timing-function: cubic-bezier(0, 1, 1, 0);
	position: absolute;
	top: calc(50% - 6px);
}

#preloader div:nth-child(1) {
	left: calc(50% + 8px);
	animation: preloader-1 .6s infinite;
}

#preloader div:nth-child(2) {
	left: calc(50% + 8px);
	animation: preloader-2 .6s infinite;
}

#preloader div:nth-child(3) {
	left: calc(50% + 32px);
	animation: preloader-2 .6s infinite;
}

#preloader div:nth-child(4) {
	left: calc(50% + 56px);
	animation: preloader-3 .6s infinite;
}

@keyframes preloader-1 {
	0% {
		transform: scale(0);
	}

	100% {
		transform: scale(1);
	}
}

@keyframes preloader-2 {
	0% {
		transform: translate(0, 0);
	}

	100% {
		transform: translate(24px, 0);
	}
}

@keyframes preloader-3 {
	0% {
		transform: scale(1);
	}

	100% {
		transform: scale(0);
	}
}

/* ── Responsive ──────────────────────────────────── */
@media (max-width: 991.98px) {
	section {
		padding: 64px 0;
	}

	/* The hero scrim runs left-to-right, which reads as a hard
	   vertical edge once the column is full width. */
	.hero::after {
		background: linear-gradient(180deg, rgba(255, 255, 255, .93) 0%, rgba(255, 255, 255, .88) 55%, rgba(255, 255, 255, .7) 100%);
	}

	.hero p {
		max-width: 100%;
	}
}

@media (max-width: 768px) {
	/* At 100px the mark is 260px wide, which will not sit beside
	   the Login button on a phone - it collides, and a squeezed
	   flex item distorts the mark. Scale it with the bar instead;
	   100px is kept at every width above this. */
	:root {
		--header-h: 78px;
	}

	.brand img {
		height: 66px;
	}

	/* Follows the bar down from 78px to 62px, same idea as desktop. */
	#header.condensed .brand img {
		height: 50px;
	}

	.about-mosaic {
		height: 280px;
	}

	.gallery-strip-inner {
		grid-template-columns: 1fr;
		height: auto;
	}

	.gallery-strip-item {
		height: 220px;
	}

	.stat-item {
		padding: 1.25rem .75rem;
		border-right: none;
		border-bottom: 1px solid var(--line);
	}

	.stat-item:nth-last-child(-n+2) {
		border-bottom: none;
	}

	.stat-number {
		font-size: 1.9rem;
	}

	.contact-form-wrapper {
		padding: 1.5rem;
	}
}