@charset "UTF-8";

/* MATERIAL SYMBOLS — base rule
   The <link> in <head> only registers the "Material Symbols Outlined"
   web font itself; it doesn't style anything. Every place in this file
   that uses an icon (.chip-icon, .btn-secondary-icon,
   .nav-pill-icon, and the homepage's .card-icon) only sets SIZE on
   .material-symbols-outlined — without this base rule the font is never
   actually applied, so the icon span just renders its ligature text
   ("mail", "design_services", etc.) instead of the glyph. */
.material-symbols-outlined {
	font-family: 'Material Symbols Outlined';
	/* Weight 200: the <link> asks Google Fonts for the 200 instance (about a
	   1px stroke at 24px), to match the 1px UI strokes. */
	font-weight: 200;
	font-style: normal;
	line-height: 1;
	letter-spacing: normal;
	text-transform: none;
	display: inline-block;
	white-space: nowrap;
	word-wrap: normal;
	direction: ltr;
	-webkit-font-feature-settings: 'liga';
	-webkit-font-smoothing: antialiased;
}

/* CHIPS */

.chip {
	position: relative;
	/* Stacks above .chip-scroll-line (see component-layout.css), which is
	   deliberately positioned to start 1px underneath the chip's right
	   edge rather than flush against it — on some browsers/displays the
	   line (its own GPU compositor layer, via `transform`) and the chip
	   (plain painted content) can snap to slightly different sub-pixel
	   grids, leaving a hairline gap between them. The 1px overlap plus
	   this z-index hides that seam under the chip's own border, whichever
	   way it rounds, rather than relying on both layers lining up
	   perfectly. */
	z-index: 1;
	display: inline-flex;
	align-items: center;
	font-family: "Open Sans", sans-serif;
	font-weight: 300;
	font-size: clamp(0.875rem, calc(0.42 * var(--vw)) + 0.792rem, 1.125rem);
	line-height: 140%;
	color: var(--color-text-primary);
	padding: 0.444em 0.889em;
	border: 1px solid var(--color-border-strong);
	border-radius: 9999px;
	/* Solid fill in the module surface colour (follows the theme), so the
	   scroll line running out of the chip can never show through it. */
	background-color: var(--color-background-surface);
	white-space: nowrap;
}

.chip-bold {
	font-weight: 600;
	border-width: 1px;
}

.chip-small {
	font-size: clamp(0.656rem, calc(0.31 * var(--vw)) + 0.594rem, 0.844rem);
}

.chip-small.chip-bold {
	font-weight: 600;
	border-width: 1px;
}

/* CHIP ICON VARIANT */

.chip-icon {
	gap: 0.5em;
}

.chip-icon .material-symbols-outlined {
	font-size: 1.25em;
	line-height: 1;
}

/* NAV PILLS
   Same visual footprint as .chip.chip-small.chip-bold, but built as a
   standalone class (not .chip) so these never pick up the chip
   scroll-line behaviour wired up in main.js/component-layout.css —
   nav pills should never grow that animated line.

   States:
   .nav-pill            — inactive: transparent fill (shows whatever it's
                           sitting on), 1px #333333 stroke, #333333 text
   .nav-pill-active     — active: filled #333333, white text
   :hover / :focus-visible on an inactive pill — a #333333 "liquid" fill
   rises from the bottom to fill the pill, with the label crossfading
   from #333333 to white as it fills. Implemented with a ::before layer
   that translates up from translateY(100%) to translateY(0). */
.nav-pill {
	position: relative;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	/* Buttons should always hug their own content, never fill the
	   container they're dropped into. inline-flex already sizes to
	   content on its own — but several modules place a .nav-pill as a
	   direct child of a flex-direction:column container (.split-layout-text,
	   plus any future text module) that leaves align-items at its default
	   of stretch, which forces the pill's cross-axis (width, in a column)
	   to fill the column's full width regardless of its own display type.
	   align-self overrides that per-item, so the pill keeps hugging its
	   label wherever it's placed, without having to touch every such
	   container's own align-items (several of those containers need
	   stretch to stay on for their actual text children — headings and
	   paragraphs rely on it to get their line-wrapping width).
	   align-self's cross-axis meaning flips with the parent's direction
	   though: in the nav bar's row-direction .nav-buttons, this same
	   flex-start would mean vertical (top) instead of .nav-buttons' own
	   centred alignment — restored explicitly just below rather than left
	   to this default. */
	align-self: flex-start;
	box-sizing: border-box;
	/* Was overflow:hidden. That clips descendants (the ::before fill
	   layer below) at the PADDING edge — i.e. right at the border's
	   OWN inner edge — which meant the fill and the native border had
	   to rasterize to the exact same sub-pixel boundary with zero
	   overlap for no seam to show. At the many fractional pill heights
	   clamp() produces while resizing, the fill (a separately
	   GPU-composited layer, since it's transform-animated) and the
	   border (painted natively) don't always snap to the same device
	   pixel there: sometimes the fill's edge fell a hair short of the
	   border's inner edge (the hairline white gap between fill and
	   stroke on hover), sometimes a hair past the box's true bottom
	   edge before translateY(100%) had it fully clear (the bottom
	   stroke's apparent flicker in thickness at rest).
	   clip-path's inset() with no extra offset clips at the BORDER box
	   instead (the box's true outer edge) — and, critically, unlike
	   overflow, it still clips ::before even when ::before's own box
	   extends past the padding edge (see the negative inset on
	   ::before below). That lets the fill deliberately overlap the
	   border ring by its full 1px width on every side instead of
	   needing to land exactly on its inner edge, so the boundary
	   between stroke and fill is never a razor's-edge sub-pixel
	   alignment problem — there's no gap possible once the fill
	   generously covers the stroke's own footprint. 9999px is a literal
	   copy of the border-radius below (not `inherit`), since this
	   needs to be the same curve function clip-path's own round-corner
	   syntax understands, not a value it has to re-derive. */
	clip-path: inset(0 round 9999px);
	isolation: isolate;
	font-family: "Open Sans", sans-serif;
	font-weight: 600;
	font-size: clamp(0.656rem, calc(0.31 * var(--vw)) + 0.594rem, 0.844rem);
	line-height: 140%;
	/* Figma "Primary button": 40px tall with 16px side padding on desktop
	   (max-clamp), 32px / 12px on mobile (min-clamp). Both clamps share
	   the font-size clamp's slope, so they hit their ends at exactly the
	   same viewport widths as the text does (see --btn-height in
	   tokens.css). Height includes the 1px border (border-box). */
	height: var(--btn-height);
	padding: 0 var(--btn-padding-x);
	border: 1px solid var(--color-border-strong);
	border-radius: 9999px;
	color: var(--color-text-primary);
	background-color: transparent;
	white-space: nowrap;
	text-decoration: none;
	cursor: pointer;
	transition: color 0.4s ease;
	-webkit-tap-highlight-color: transparent;
}

/* Restores .nav-buttons' own vertical centring for the pills in the top
   nav bar specifically — see the align-self comment on .nav-pill above
   for why that rule's flex-start default would otherwise flip this one
   row-direction context from centred to top-aligned. */
.nav-buttons > .nav-pill {
	align-self: center;
}

.nav-pill::before {
	content: "";
	position: absolute;
	/* -1px, matching the border's own width exactly: this pulls the
	   fill's edge out to (and then slightly past) the border's OUTER
	   edge rather than stopping at its inner one (inset:0, the old
	   value, is the padding edge — see the clip-path comment above for
	   why this overlap is what actually removes the seam, and why
	   clip-path on the parent is what lets it be visible instead of
	   getting clipped straight back to the same old boundary). Because
	   this pseudo-element has a negative z-index inside .nav-pill's own
	   isolated stacking context, it paints ABOVE .nav-pill's own
	   border/background (stacking contexts paint their own box first,
	   negative-z-index children second) — so where this now overlaps
	   the border ring, it simply paints the same #333333 over the same
	   #333333, not a visible change, just margin for error. */
	inset: -1px;
	/* Matches .nav-pill's own border-radius (9999px always resolves to a
	   full capsule, whatever the box's actual height) so this fills its
	   own true rounded shape directly, rather than being a plain
	   rectangle relying on a parent clip to shape it. */
	border-radius: inherit;
	background-color: var(--color-background-inverse);
	transform: translateY(100%);
	transition: transform 0.4s ease;
	z-index: -1;
	pointer-events: none;
}

.nav-pill:hover,
.nav-pill:focus-visible {
	color: var(--color-text-inverse);
	outline: none;
}

.nav-pill:hover::before,
.nav-pill:focus-visible::before {
	transform: translateY(0%);
}

/* Focus: as Hover, plus a 1px white ring just inside the border, so
   keyboard focus reads differently from a mouse hover (Figma: Primary
   button / Focus). Drawn as an overlay, so it never shifts the label. */
.nav-pill::after {
	content: "";
	position: absolute;
	inset: 0;
	border: 1px solid var(--color-text-inverse);
	border-radius: inherit;
	opacity: 0;
	pointer-events: none;
	transition: opacity 0.4s ease;
}

.nav-pill:focus-visible::after {
	opacity: 1;
}

/* Pressed: filled, with the outline darkening to a primary-elements
   800 to 700 gradient (Figma: Primary button / Pressed). The gradient
   is painted as the pill's own border-box background behind a
   transparent border; the fill layer pulls back to the padding box so
   the gradient ring stays visible. */
.nav-pill:active {
	color: var(--color-text-inverse);
	border-color: transparent;
	background: linear-gradient(180deg, var(--color-primary-elements-800), var(--color-primary-elements-700)) border-box;
}

.nav-pill:active::before {
	inset: 0;
	transform: translateY(0%);
}

/* Disabled: grey outline and label, no hover (Figma: Primary button /
   Disabled). Use aria-disabled on links, the disabled attribute on
   <button>. */
.nav-pill[aria-disabled="true"],
.nav-pill:disabled {
	color: var(--color-text-secondary);
	border-color: var(--color-primary-elements-400);
	cursor: default;
	pointer-events: none;
}

.nav-pill[aria-disabled="true"]::before,
.nav-pill:disabled::before {
	display: none;
}

.nav-pill-active {
	background-color: var(--color-background-inverse);
	color: var(--color-text-inverse);
}

.nav-pill-active::before {
	transform: translateY(0%);
}

/* .nav-pill-active is used two ways: as a non-interactive <span> marking
   "you're already on this exact page" (Home on index.html, Case studies
   on case-studies.html — cursor:default, no hover needed), and as a real
   <a> on the case study sub-pages, where "Case studies" is highlighted to
   show the current section but still genuinely links to the hub page, so
   it keeps the normal pointer cursor from .nav-pill. Scoping to the tag
   keeps both correct without needing a second modifier class. */
span.nav-pill-active {
	cursor: default;
}

/* NAV PILL ICON VARIANT (Figma: 8px gap at 13.5px, 6px at 10.5px) */
.nav-pill-icon {
	gap: 0.593em;
}

.nav-pill-icon .material-symbols-outlined {
	font-size: 1.25em;
	line-height: 1;
}

/* SECONDARY BUTTON (Figma: "Secondary button")
   Lower emphasis than the Primary .nav-pill: a text label with no
   container, for inline or repeated actions ("View all", "Read more",
   repeated "View case study" links).

   The underline is one ::after layer painted with three backgrounds:
   two end-caps (radial gradients, a 1px ring around a fill) and the
   1px line between them. At rest it waits as a single end-cap-sized
   point at the centre of the label (opacity 0). On hover it grows
   outwards to the full width by animating left/right, not scaleX,
   because scaling would squash the round end-caps.

   States (custom properties so each state only changes what it needs):
     --sec-ink       label, line and cap ring colour
     --sec-cap-fill  inside of the end-caps (hollow = page colour)
     --sec-cap       end-cap diameter
   Sizes: font, padding and end-caps share the small-copy font-size
   clamp's slope, so desktop = 13.5px / 8px caps / 8px padding and
   mobile = 10.5px / 6px caps / 6px padding, exactly as in Figma. */
.btn-secondary {
	--sec-ink: var(--color-primary-elements-700);
	--sec-cap-fill: var(--color-primary-elements-000);
	--sec-cap: clamp(6px, calc(0.207 * var(--vw)) + 5.33px, 8px);
	position: relative;
	display: inline-flex;
	align-items: center;
	align-self: flex-start;
	font-family: "Open Sans", sans-serif;
	font-weight: 600;
	font-size: clamp(0.656rem, calc(0.31 * var(--vw)) + 0.594rem, 0.844rem);
	line-height: 140%;
	color: var(--color-text-primary);
	padding: 0 var(--sec-cap) var(--sec-cap);
	background: none;
	border: none;
	white-space: nowrap;
	text-decoration: none;
	cursor: pointer;
	transition: color 0.4s ease;
	-webkit-tap-highlight-color: transparent;
}

.btn-secondary::after {
	content: "";
	position: absolute;
	bottom: 0;
	left: calc(50% - var(--sec-cap) / 2);
	right: calc(50% - var(--sec-cap) / 2);
	height: var(--sec-cap);
	opacity: 0;
	pointer-events: none;
	background:
		radial-gradient(closest-side, var(--sec-cap-fill) calc(100% - 1.5px), var(--sec-ink) calc(100% - 1px) calc(100% - 0.5px), transparent 100%) left center / var(--sec-cap) var(--sec-cap) no-repeat,
		radial-gradient(closest-side, var(--sec-cap-fill) calc(100% - 1.5px), var(--sec-ink) calc(100% - 1px) calc(100% - 0.5px), transparent 100%) right center / var(--sec-cap) var(--sec-cap) no-repeat,
		linear-gradient(var(--sec-ink), var(--sec-ink)) center / calc(100% - var(--sec-cap)) 1px no-repeat;
	transition: left 0.4s ease, right 0.4s ease, opacity 0.2s ease;
}

.btn-secondary:hover::after,
.btn-secondary:focus-visible::after,
.btn-secondary:active::after,
.btn-secondary-active::after,
.btn-secondary[aria-current]::after,
.btn-secondary[aria-disabled="true"]::after,
.btn-secondary:disabled::after {
	left: 0;
	right: 0;
	opacity: 1;
}

.btn-secondary:focus-visible {
	outline: none;
	--sec-cap-fill: var(--color-primary-elements-700);
}

/* Pressed: darker ink and slightly smaller caps, so it reads as pushed in. */
.btn-secondary:active {
	--sec-ink: var(--color-primary-elements-800);
	color: var(--color-primary-elements-800);
}

.btn-secondary:active::after {
	background-size: calc(var(--sec-cap) - 2px) calc(var(--sec-cap) - 2px), calc(var(--sec-cap) - 2px) calc(var(--sec-cap) - 2px), calc(100% - var(--sec-cap)) 1px;
}

/* Selected (current page / active filter): a plain full-width line, no caps. */
.btn-secondary-active::after,
.btn-secondary[aria-current]::after {
	background: linear-gradient(var(--sec-ink), var(--sec-ink)) center / 100% 1px no-repeat;
}

.btn-secondary[aria-disabled="true"],
.btn-secondary:disabled {
	--sec-ink: var(--color-primary-elements-400);
	color: var(--color-text-secondary);
	cursor: default;
	pointer-events: none;
}

.btn-secondary-icon {
	gap: 0.593em;
}

.btn-secondary-icon .material-symbols-outlined {
	font-size: 1.25em;
	line-height: 1;
}

/* LINK AND MENU ITEMS */
.menu-item-active {
	cursor: pointer;
	opacity: 0.5;
}

.menu-item {
	cursor: pointer;
	transition: opacity 0.6s;
}

.menu-item:hover {
	opacity: 0.2;
}

.link {
	text-decoration: underline;
	transition: opacity 0.6s;
}

.link:hover {
	opacity: 0.2;
}
/* BUTTON ROW
   A Primary button (.nav-pill) and a Secondary button (.btn-secondary)
   side by side, e.g. "View case study" + "Get the code!". Wraps onto a
   second line when the column is too narrow. Both buttons set
   align-self:flex-start for column layouts; recentred here so they
   share a vertical midline in the row. Same placement rule as a single
   button: last element in its column, after a .space-24. */
.button-row {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--space-16) var(--space-24);
}

.button-row > .nav-pill,
.button-row > .btn-secondary {
	align-self: center;
}
