/* =====================================================================
   LIGHT HOME PAGE  (item 139)
   ---------------------------------------------------------------------
   Loaded ONLY by frontend/templates/frontend/home.html, which is served at
   "/". The page it replaced is parked at /home-legacy/ and does not load
   this file.

   Built section by section, each in its own commit. Only the hero is here
   so far.

   ---------------------------------------------------------------------
   WHERE RAW VALUES ARE ALLOWED HERE, AND WHY

   Three carve-outs, all of them narrow and all of them following a
   convention this project already set rather than inventing one.

   1. DISPLAY TYPE SIZES: 60px and 36px. The --text-* scale tops out at
      --text-6xl (32px) because it was built for app UI, where 14px is the
      base. Marketing display type starts where that scale ends. This is
      the same carve-out preview-home.css took, with the same reason, and
      the same warning attached: do NOT widen the shared scale to cover
      these, because that would put 50px and 60px in reach of every
      dashboard rule in style.css.

   2. DISPLAY LEADING: 1.1. The --leading-* family has three values (1,
      1.4, 1.55) and all three are wrong for a 60px headline: at that size
      1.4 opens the two lines into separate objects. Leading has to FALL as
      type size rises, which is the mirror of the rule recorded against
      --leading-normal, where it has to rise as line length rises. Kept
      page-local rather than tokenised, by the same argument as the sizes.

   3. COMPONENT HEIGHTS: 42px and 52px buttons, the 700px hero minimum, the
      4px rule. Heights are not spacing steps, and preview-home.css already
      treats them this way: every padding in it is a var(--space-*) and
      every height in it is a raw px. Followed rather than re-litigated.

   EVERY PADDING, MARGIN AND GAP IS A TOKEN. Four of the design's values
   were off the spacing scale and are snapped to it rather than admitted:
   72px to --space-16 (80), 64px to --space-15 (60), 28px to --space-11
   (30) and 26px to --space-10 (25). Largest move is 8px.

   EVERY COLOUR IS A TOKEN. All 24 hex values in the design output already
   existed in the system; none is new.
   ===================================================================== */

:root {
	/* Hero rotation timing. Read by js/home-hero.js from the computed
	   style, so this stylesheet is the single source of truth and the hero
	   can be retimed without opening the JavaScript. Same names and same
	   values as preview-home.css, so the two heroes cannot drift; they are
	   never loaded together. */
	--hero-fade: 1.2s;
	--hero-interval: 6s;

	/* --marketing-surface (#12161F) with its channels separated, so the
	   scrim's nine alpha stops all compose from ONE value instead of nine
	   hand-written rgba() literals that would have to be corrected
	   together. The hex is pinned by item 103 and must not be edited here:
	   change it in style.css and this follows. */
	--hm-scrim-rgb: 18, 22, 31;
}

/* ---- page base ---------------------------------------------------- */
.hm {
	background: var(--color-surface-page);
	color: var(--color-text-body);
	font-family: var(--font-sans);
	line-height: var(--leading-tight);
	overflow-x: hidden;
}

/* The paragraph and list reset, wrapped in :where() so it contributes ZERO
   specificity. As a plain `.hm p` this would be (0,1,1) and would silently
   beat every single-class rule in this file, which is exactly the defect
   that cost preview-home.css two declarations before it was found. */
:where(.hm) p,
:where(.hm) ul,
:where(.hm) h1,
:where(.hm) h2,
:where(.hm) h3 { margin: 0; padding: 0; }
:where(.hm) ul { list-style: none; }

.hm *,
.hm *::before,
.hm *::after { box-sizing: border-box; }

/* =====================================================================
   HERO
   ===================================================================== */

.hm__hero-pad { padding: var(--space-7) var(--space-7) var(--space-16); }

.hm__hero {
	position: relative;
	min-height: 700px;
	display: flex;
	flex-direction: column;
	border-radius: var(--radius-lg);
	overflow: hidden;
	/* The panel ground shows through wherever the photograph has not
	   painted yet, so the first frame fades up from the brand dark rather
	   than from white. */
	background: var(--marketing-surface);
}

/* ---- rotating photography ------------------------------------------ */
.hm__frames {
	position: absolute;
	inset: 0;
	pointer-events: none;
}

.hm__frame {
	position: absolute;
	inset: 0;
	opacity: 0;
	transition: opacity var(--hero-fade) var(--ease-standard);
}

.hm__frame.is-active { opacity: 1; }

.hm__frame img {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
	object-position: 50% 50%;
}

/* Deferred frames are display:none so the browser does not fetch them
   during first paint. home-hero.js removes the attribute once the page is
   interactive, and the normal <picture> negotiation then runs as usual. */
.hm__frame[data-defer] { display: none; }

/* ---- scrims -------------------------------------------------------- */
/* Decoration, and load-bearing for legibility: every piece of text in this
   hero sits on photography, so these are what item 88 is about. Measured
   per text node on composited pixels, not assumed. */
.hm__scrim {
	position: absolute;
	pointer-events: none;
}

.hm__scrim--across {
	inset: 0;
	background: linear-gradient(90deg,
		rgba(var(--hm-scrim-rgb), 0.62) 0%,
		rgba(var(--hm-scrim-rgb), 0.56) 40%,
		rgba(var(--hm-scrim-rgb), 0.55) 52%,
		rgba(var(--hm-scrim-rgb), 0.22) 64%,
		rgba(var(--hm-scrim-rgb), 0) 76%);
}

/* Behind the nav, which sits on the brightest part of several frames. */
.hm__scrim--top {
	left: 0;
	right: 0;
	top: 0;
	height: 170px;
	background: linear-gradient(180deg,
		rgba(var(--hm-scrim-rgb), 0.78) 0%,
		rgba(var(--hm-scrim-rgb), 0.55) 45%,
		rgba(var(--hm-scrim-rgb), 0) 100%);
}

/* ---- the bar's DARK skin, for the light hero -----------------------
   The shared bar normally sits above the content on white. Inside the
   photographic hero it sits ON the image instead, so it loses its own
   background and border and takes the marketing text colours. Doubled
   class, .hm__bar.hm__bar--dark, so it beats the base rules on specificity
   rather than on where it happens to sit in the file: that ordering trap
   has already cost this stylesheet three times. */
.hm__bar.hm__bar--dark {
	background: transparent;
	border-bottom: 0;
	padding: 0 var(--space-9);
}

.hm__bar--dark .hm__bar-logo img { width: 87px; height: 52px; }
.hm__bar.hm__bar--dark .hm__bar-nav a { color: var(--marketing-text); }
.hm__bar.hm__bar--dark .hm__bar-nav a:hover {
	color: var(--marketing-text);
	border-bottom-color: var(--marketing-accent-blue);
}
.hm__bar.hm__bar--dark .hm__bar-login { color: var(--marketing-text); }
.hm__bar.hm__bar--dark .hm__bar-login:hover {
	color: var(--marketing-text);
	text-decoration: underline;
	text-underline-offset: 4px;
}

/* ---- the old in-hero nav, kept only for anything still referencing it - */
.hm__nav {
	position: relative;
	z-index: 4;
	flex: 0 0 auto;
	height: var(--header-height);
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: var(--space-8);
	padding: 0 var(--space-9);
}

.hm__nav-left,
.hm__nav-right {
	display: flex;
	align-items: center;
	gap: var(--space-14);
}

.hm__nav-right { gap: var(--space-9); }

.hm__logo { display: flex; align-items: center; text-decoration: none; }
.hm__logo img { display: block; width: 87px; height: 52px; }

.hm__nav-links {
	display: flex;
	align-items: center;
	gap: var(--space-11);
}

.hm__nav-links a,
.hm__login {
	font-size: var(--text-md);
	color: var(--marketing-text);
	white-space: nowrap;
	text-decoration: none;
	padding-bottom: var(--space-2);
	border-bottom: 2px solid transparent;
	transition: border-color var(--duration-base) var(--ease-standard);
}

.hm__nav-links a:hover { color: var(--marketing-text); border-bottom-color: var(--marketing-accent-blue); }

.hm__login { font-weight: var(--weight-bold); border-bottom: 0; padding-bottom: 0; }
.hm__login:hover { color: var(--marketing-text); text-decoration: underline; text-underline-offset: 4px; }

/* ---- buttons ------------------------------------------------------- */
.hm__btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	height: 52px;
	padding: 0 var(--space-11);
	border: 1px solid transparent;
	border-radius: var(--btn-radius);
	font-family: inherit;
	font-size: var(--text-lg);
	font-weight: var(--weight-bold);
	white-space: nowrap;
	text-decoration: none;
	cursor: pointer;
	transition: background var(--duration-base) var(--ease-standard),
	            border-color var(--duration-base) var(--ease-standard),
	            box-shadow var(--duration-base) var(--ease-standard),
	            transform var(--duration-base) var(--ease-standard);
}

.hm__btn--sm {
	height: 42px;
	padding: 0 var(--space-8);
	font-size: var(--text-md);
}

.hm__btn--primary {
	background: var(--btn-primary-bg);
	color: var(--color-action-primary-fg);
}

.hm__btn--primary:hover {
	background: var(--btn-primary-bg-hover);
	color: var(--color-action-primary-fg);
	box-shadow: var(--elevation-brand-lg);
	transform: translateY(-2px);
}

/* On the photograph, so the border is the only thing separating it from
   whatever is behind. --neutral-400 rather than a marketing token because
   it is a graphic boundary, not text. */
.hm__btn--ghost {
	background: transparent;
	border-color: var(--neutral-400);
	color: var(--marketing-text);
}

.hm__btn--ghost:hover {
	background: var(--marketing-surface-raised);
	border-color: var(--marketing-accent-blue);
	color: var(--marketing-text);
	transform: translateY(-2px);
}

/* ---- hero copy ----------------------------------------------------- */
.hm__hero-copy {
	position: relative;
	z-index: 2;
	flex: 1 1 auto;
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	justify-content: center;
	max-width: 728px;
	padding: var(--space-13) var(--space-9) var(--space-15);
}

/* The brand gradient as a short bar. Decoration only: it names nothing and
   sits above a heading that already does. */
.hm__rule {
	width: 72px;
	height: 4px;
	border-radius: var(--radius-pill);
	background: var(--gradient-brand-diagonal);
}

.hm__hero h1 {
	margin-top: var(--space-10);
	font-size: 60px;               /* display carve-out, see the header */
	line-height: 1.1;              /* display carve-out, see the header */
	font-weight: var(--weight-bold);
	letter-spacing: var(--tracking-tight);
	color: var(--marketing-text);
	text-wrap: pretty;
}

.hm__hero-list {
	margin-top: var(--space-12);
	display: flex;
	flex-direction: column;
	gap: var(--space-4);
}

.hm__hero-list li {
	display: grid;
	grid-template-columns: 22px 1fr;
	align-items: start;
	gap: var(--space-5);
	font-size: var(--text-4xl);
	line-height: var(--leading-tight);
	color: var(--marketing-text);
}

/* The icon replaced an 8px dot in item 145. Width and height are set here
   rather than left to the SVG's attributes so the glyph can follow the type
   down through the breakpoints from one place.

   align-items is start, not baseline: a line that wraps to two keeps its
   icon against the first line instead of drifting to the optical centre of
   both. The 2px is what puts the 22px glyph on the 24px cap centre -- a
   measured nudge, not a spacing step, the same as the playful hero's list.

   THE LOGO GREEN, which has been decoration-only all project because it is
   2.08:1 on white. A 1.5px stroke is a finer mark than the dot it replaces,
   so it is measured against the composited scrim rather than assumed; it is
   non-text either way, aria-hidden and duplicated by the words beside it. */
.hm__hero-list li > .hm__icon {
	width: 22px;
	height: 22px;
	margin-top: 2px;
	color: var(--marketing-accent);
}

.hm__hero-actions {
	margin-top: var(--space-13);
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--space-6);
}

/* =====================================================================
   SEARCH ROW

   Carried over from the page this one replaces. Same two fields, same
   labels, same placeholders, same destination. Only the styling is new.

   WHY THE LABELS SIT INSIDE THE WHITE BAR. On the old page they sat above
   it, which here would put two more text nodes onto the photograph for no
   gain. Inside the bar they are on a known opaque surface, so they are
   legible by construction rather than by measurement, and the row reads as
   one component instead of three. They stay PERSISTENT AND VISIBLE either
   way, which the system requires: a placeholder is a hint, not a label,
   and the note on --color-text-placeholder says so explicitly.
   ===================================================================== */

/* The reveal wrapper. Carries data-r so reveal.css animates this and the
   bar below keeps its own focus transition. See the note in home.html. */
.hm__search-wrap { width: 100%; }

.hm__search {
	margin-top: var(--space-9);
	width: 100%;
	display: flex;
	align-items: stretch;
	padding: var(--space-2);
	border-radius: var(--radius-lg);
	background: var(--color-surface-raised);
	box-shadow: var(--elevation-3);
	transition: box-shadow var(--duration-base) var(--ease-standard);
}

/* THE BRAND BLOOM, ON FOCUS ONLY.
   --------------------------------------------------------------------
   --elevation-glow-brand is the system's green-to-blue lift, added in item
   133 for "hover on dark marketing surfaces". This bar sits on one, so the
   glow is legal here by the token's own rule rather than by extension.

   WHY IT IS A FOCUS STATE AND NOT THE RESTING LOOK. A bloom needs a ground
   that is dark AND flat. This bar sits on photography that rotates through
   five frames every six seconds. Measured as the p90 luminance of the 40px
   band the bloom would land on: 0.030 on trading, 0.101 on robotics2,
   against about 0.004 in the reference it was modelled on, so 7x to 25x too
   light. Rendered and looked at rather than argued from the numbers: at
   rest the glow is invisible, and at four times the strength it reads off
   the left of the bar where the photo is dark and vanishes on the right
   where it is bright. Inconsistent across the width of one bar and across
   time as the hero rotates.

   A resting state has to hold on all five frames. A focus state does not:
   it is momentary, the person has just clicked into the bar, and they are
   looking straight at it. So the same aesthetic lands where it survives.

   IT IS NOT THE FOCUS INDICATOR. The outline below is, and it stays. A
   glow that washes out over three of five photographs cannot be what tells
   someone where the keyboard is.
   -------------------------------------------------------------------- */
.hm__search:focus-within {
	box-shadow: var(--elevation-3), var(--elevation-glow-brand);
}

.hm__search-field {
	flex: 1 1 0;
	min-width: 0;
	display: flex;
	flex-direction: column;
	justify-content: center;
	gap: var(--space-1);
	padding: var(--space-4) var(--space-6);
}

/* The divider between the two fields. A border on the second one rather
   than a separate element, so there is nothing to keep in sync. */
.hm__search-field + .hm__search-field {
	border-left: 1px solid var(--color-border-subtle);
}

.hm__search-field label {
	font-size: var(--text-xs);
	font-weight: var(--weight-bold);
	letter-spacing: var(--tracking-wide);
	color: var(--color-text-muted);
	cursor: pointer;
}

/* The four resets here are not defensive boilerplate, they are undoing
   real declarations: style.css styles every input on the site for the
   dashboard forms, and three of them reached in here. Measured on the
   rendered page rather than guessed at, which is the only way to find
   them, because none of it fails loudly:

     box-shadow  --elevation-1, which drew a faint rule under each field
                 that read as a stray underline
     margin      16px below every input, which pushed the bar off its
                 own vertical centre
     height      a fixed 48px, which fought the flex sizing
     transition  0.1s on all properties, which is not this page's timing

   Written as explicit properties rather than `all: unset` so that what is
   being undone stays readable. */
.hm__search-field input {
	width: 100%;
	height: auto;
	margin: 0;
	border: 0;
	padding: 0;
	box-shadow: none;
	background: transparent;
	font-family: inherit;
	font-size: var(--text-lg);
	line-height: var(--leading-tight);
	color: var(--color-text-heading);
	transition: none;
}

.hm__search-field input::placeholder {
	color: var(--color-text-placeholder);
	opacity: 1;   /* Firefox dims placeholders by default, which would put
	                 this below the contrast floor the token guarantees. */
}

/* An offset outline rather than a box-shadow ring: the bar has
   overflow-hidden ancestors and a shadow ring would be clipped by them. */
.hm__search-field input:focus-visible,
.hm__search-submit:focus-visible,
.hm__btn:focus-visible,
.hm__menu summary:focus-visible {
	outline: var(--focus-ring-width) solid var(--focus-ring-color);
	outline-offset: var(--focus-ring-offset);
}

.hm__search-submit {
	flex: 0 0 auto;
	height: auto;
	align-self: stretch;
	margin-left: var(--space-2);
}

/* =====================================================================
   SECTIONS ON THE LIGHT GROUND
   ===================================================================== */

.hm__section {
	padding: var(--space-16) var(--space-13);
	background: var(--color-surface-page);
	border-top: 1px solid var(--color-border-subtle);
}

.hm__section-head {
	display: flex;
	align-items: flex-end;
	justify-content: space-between;
	gap: var(--space-13);
}

.hm__section h1,
.hm__section h2 {
	margin-top: var(--space-10);
	font-size: 50px;               /* display carve-out, see the header */
	line-height: 1.1;              /* display carve-out, see the header */
	font-weight: var(--weight-bold);
	letter-spacing: var(--tracking-tight);
	color: var(--color-text-heading);
}

.hm__section-head p {
	margin-top: var(--space-5);
	max-width: 60ch;
	font-size: var(--text-lg);
	line-height: var(--leading-normal);
	color: var(--color-text-body);
}

.hm__section-link {
	flex: 0 0 auto;
	font-size: var(--text-lg);
	font-weight: var(--weight-bold);
	color: var(--color-link);
	text-decoration: none;
	white-space: nowrap;
	padding-bottom: 3px;
	border-bottom: 2px solid transparent;
	transition: border-color var(--duration-base) var(--ease-standard),
	            color var(--duration-base) var(--ease-standard);
}

.hm__section-link:hover {
	color: var(--color-action-primary-hover);
	border-bottom-color: var(--color-action-primary);
}

.hm__section-link:focus-visible,
.hm__cat:focus-visible {
	outline: var(--focus-ring-width) solid var(--focus-ring-color);
	outline-offset: var(--focus-ring-offset);
}

/* The bar on /categories/, which has no hero to sit in. */
.hm__plainbar {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: var(--space-8);
	height: var(--header-height);
	padding: 0 var(--space-13);
	background: var(--marketing-surface);
}

.hm__plainbar-logo img { display: block; width: 87px; height: 52px; }

/* =====================================================================
   CATEGORY CARDS

   Two treatments in one frame. The object-backed card and the monogram card
   differ ONLY in the right-hand zone; everything else is shared, which is
   what stops a category with no art looking like a broken version of one
   that has it.

   ---------------------------------------------------------------------
   THE PALETTE IS ONE VARIABLE SET, NOT TWO RULE SETS

   Blue and white cards differ in seven properties across four elements. The
   first version of this declared all seven again for every breakpoint AND a
   matching set to undo them, because the checkerboard's nth-child pattern
   changes with the column count and a four-column rule has to be switched
   off before a two-column one can apply. That was about ninety lines of
   override whose only job was to cancel other overrides, and adding a third
   column count would have added thirty more.

   Instead the card reads its colours from --cat-* and each breakpoint sets
   ONLY those, on whichever cards are blue at that width. Nothing needs
   undoing, because the next media query simply assigns different values.
   ===================================================================== */

.hm__cats {
	margin-top: var(--space-13);
	display: grid;
	grid-template-columns: repeat(4, minmax(0, 1fr));
	gap: var(--space-8);

	/* PROPOSED TOKEN, NOT YET ADOPTED. Page-local rather than in style.css
	   :root, because a new gradient geometry goes through review first.
	   Every COLOUR in it is an existing token; only the angle and the stop
	   positions are new. To promote it, move this to :root as
	   --gradient-brand-card.

	   THE 54% HOLD IS LOAD-BEARING, NOT DECORATIVE. The card's text occupies
	   the left 54% and this gradient stays solid blue across exactly that
	   span before ramping. Substituting --gradient-brand-reverse was tried
	   and fails: it ramps from 0%, so at the text's right edge the ground is
	   already teal (#1A8C8C) and the 12px LEARN MORE label measures 4.06:1
	   where small text needs 4.5. The stop positions are what keep that
	   label legible, which is why an existing token cannot stand in. */
	--hm-cat-gradient: linear-gradient(100deg,
		var(--gradient-stop-blue) 0%,
		var(--gradient-stop-blue) 54%,
		var(--gradient-stop-teal) 82%,
		var(--gradient-stop-green) 100%);
}

/* The white card. Every blue rule below overrides these same six. */
.hm__cat {
	--cat-bg:        var(--color-surface-raised);
	--cat-border:    var(--color-border-subtle);
	--cat-fg:        var(--color-text-heading);
	--cat-fg-muted:  var(--color-text-muted);
	--cat-dot-bg:    var(--color-action-primary);
	--cat-dot-fg:    var(--color-action-primary-fg);
	--cat-glyph:     var(--blue-50);
	--cat-glyph-opacity: 1;

	position: relative;
	display: flex;
	flex-direction: column;
	justify-content: space-between;
	gap: var(--space-7);
	min-height: 200px;
	padding: var(--space-9);
	border-radius: var(--radius-lg);
	overflow: hidden;
	text-decoration: none;
	background: var(--cat-bg);
	border: 1px solid var(--cat-border);
	box-shadow: var(--elevation-2);
	transition: box-shadow var(--duration-base) var(--ease-standard),
	            transform var(--duration-base) var(--ease-standard);
}

/* The blue card: the palette, and nothing else. Which cards get it is
   decided per column count further down. */
.hm__cat--blue {
	--cat-bg:        var(--hm-cat-gradient);
	--cat-border:    var(--gradient-stop-blue);
	--cat-fg:        var(--marketing-text);
	/* --marketing-text-muted rather than the design's rgba(255,255,255,0.72),
	   which is not a token. Measured on this gradient: the token gives
	   4.33:1 against 4.36:1 for the raw value, so the two are
	   indistinguishable and one of them is already in the system. */
	--cat-fg-muted:  var(--marketing-text-muted);
	--cat-dot-bg:    var(--marketing-text);
	--cat-dot-fg:    var(--color-action-primary);
	--cat-glyph:     var(--marketing-text);
	/* The white token dimmed, rather than a fifth hardcoded rgba. Opacity is
	   already how this codebase fades a decorative layer. */
	--cat-glyph-opacity: 0.16;
}

/* The same green-to-blue lift the search bar uses. It reads properly here,
   unlike in the hero: the ground is a flat white page rather than a
   photograph that changes every six seconds. */
.hm__cat:hover {
	box-shadow: var(--elevation-glow-brand);
	transform: translateY(-2px);
}

/* ---- right-hand zone, treatment one: the 3D object ----------------- */
.hm__cat-art {
	position: absolute;
	right: var(--space-3);
	top: var(--space-3);
	bottom: var(--space-3);
	width: 44%;
	display: flex;
	align-items: center;
	justify-content: center;
}

.hm__cat-art img {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: contain;
	/* drop-shadow() takes ONE shadow and no spread, and --elevation-2 is
	   exactly that shape, so the token composes here as-is. Worth saying,
	   because the other elevation tokens are box-shadow LISTS and would not:
	   drop-shadow(var(--elevation-glow-brand)) is invalid and fails silently
	   by dropping the entire filter rather than erroring. */
	filter: drop-shadow(var(--elevation-2));
	transition: transform var(--duration-slow) var(--ease-out);
}

.hm__cat:hover .hm__cat-art img { transform: translateY(-4px) rotate(-3deg); }

/* ---- right-hand zone, treatment two: the monogram ------------------ */
/* Cropped off the corner on purpose so it reads as a watermark rather than
   as text, which is also why it is aria-hidden: the card's name says it. */
.hm__cat-glyph {
	position: absolute;
	right: -6px;
	bottom: -30px;
	font-size: 168px;              /* display carve-out, see the header */
	line-height: var(--leading-none);
	font-weight: var(--weight-bold);
	letter-spacing: var(--tracking-tighter);
	color: var(--cat-glyph);
	opacity: var(--cat-glyph-opacity);
	pointer-events: none;
}

/* ---- shared card contents ------------------------------------------ */
.hm__cat-name {
	position: relative;
	z-index: 1;
	max-width: 54%;
	font-size: var(--text-4xl);
	line-height: 1.2;              /* display carve-out, see the header */
	font-weight: var(--weight-bold);
	letter-spacing: var(--tracking-snug);
	color: var(--cat-fg);
}

.hm__cat-name span { color: var(--cat-fg-muted); }

/* A monogram card has no artwork to keep clear of, so its name is not held
   to the 54% the object-backed card needs. Measured before changing it: at
   54%, 11 of the 21 monogram categories wrapped past two lines and two of
   them reached four, which pushed those cards taller than their row. The
   watermark sits BEHIND the text, so the extra width costs nothing. */
.hm__cat--mono .hm__cat-name { max-width: 72%; }

.hm__cat-more {
	position: relative;
	z-index: 1;
	display: flex;
	align-items: center;
	gap: var(--space-4);
	font-size: var(--text-xs);
	font-weight: var(--weight-bold);
	letter-spacing: var(--tracking-wider);
	color: var(--cat-fg);
}

.hm__cat-arrow {
	flex: 0 0 auto;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 32px;
	height: 32px;
	border-radius: var(--radius-circle);
	background: var(--cat-dot-bg);
	color: var(--cat-dot-fg);      /* the svg strokes currentColor */
}

/* =====================================================================
   HIRE WELL, PAY SAFELY: the escrow explainer
   ===================================================================== */

.hm__feature-grid {
	display: grid;
	grid-template-columns: minmax(0, 1fr) 600px;
	gap: var(--space-15);
	align-items: center;
}

.hm__feature-copy { max-width: 560px; }

.hm__feature-lead {
	margin-top: var(--space-8);
	font-size: var(--text-xl);
	line-height: var(--leading-normal);
	color: var(--color-text-body);
	text-wrap: pretty;
}

/* ---- the escrow callout -------------------------------------------- */
.hm__escrow {
	position: relative;
	margin-top: var(--space-13);
	padding: var(--space-10) var(--space-10) var(--space-10) var(--space-11);
	border-radius: var(--radius-lg);
	background: var(--color-surface-raised);
	border: 1px solid var(--color-border-subtle);
	box-shadow: var(--elevation-2);
	overflow: hidden;
}

/* The brand ramp turned on its side as a 5px rail. Decoration: it names
   nothing, and the heading beside it already says what the card is. */
.hm__escrow-rail {
	position: absolute;
	left: 0;
	top: 0;
	bottom: 0;
	width: var(--space-2);
	/* --gradient-brand-diagonal rather than the design's raw 180deg. On a
	   5px-wide rail a couple of hundred px tall the gradient line is
	   dominated by the height, so 135deg and 180deg render the same thing,
	   and this keeps a second proposed gradient geometry out of the page. */
	background: var(--gradient-brand-diagonal);
}

.hm__escrow-head {
	display: flex;
	align-items: center;
	gap: var(--space-5);
}

.hm__escrow h3 {
	margin: 0;
	font-size: var(--text-5xl);
	line-height: 1.3;              /* display carve-out, see the header */
	font-weight: var(--weight-bold);
	color: var(--color-text-heading);
}

.hm__escrow p {
	margin-top: var(--space-6);
	font-size: var(--text-lg);
	line-height: var(--leading-normal);
	color: var(--color-text-body);
}

/* ---- the three supporting points ----------------------------------- */
.hm__points {
	margin-top: var(--space-12);
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	gap: var(--space-11);
}

/* The 48px gradient rule that used to sit above each heading went with item
   145: the icon says what the rule only decorated. --space-5 of top margin
   went with it, since there is nothing above to clear.

   flex, so a heading that wraps keeps its icon on the first line. 3px is the
   nudge onto the 18px cap centre, as drawn. */
.hm__points h4 {
	margin: 0 0 var(--space-1);
	display: flex;
	align-items: flex-start;
	gap: var(--space-3);
	font-size: var(--text-xl);
	line-height: var(--leading-tight);
	font-weight: var(--weight-bold);
	color: var(--color-text-heading);
}

.hm__points h4 > .hm__icon { margin-top: 3px; }

.hm__points p {
	font-size: var(--text-base);
	line-height: var(--leading-normal);
	color: var(--color-text-body);
}

/* ---- the illustration ----------------------------------------------
   COMPOSITED, NOT CUT OUT. The file is RGB with no alpha and a near-white
   ground, so multiply against the white section drops that ground and lets
   the illustration's own soft shadows blend rather than sit in a box.

   The ground is 254,254,254 rather than pure white, verified after encoding
   rather than assumed: multiply against anything darker than the section
   would show as a grey rectangle, and that is the failure mode this blend
   has. tools/build_home_feature.py exits non-zero if it ever drifts.

   IF mix-blend-mode IS UNSUPPORTED the fallback is close to invisible, and
   that is measured rather than hoped for: painting the illustration with
   the blend off changes its ink coverage from 44.5% to 45.0% of its own
   box. An unblended 254-white ground against a 255-white section differs by
   one value per channel.

   ONE MASK AT EVERY WIDTH, which took two attempts. The design uses a
   single vertical gradient in its mobile frame, and that works there only
   because the frame bleeds the illustration off the right of the canvas so
   there is no right edge to resolve. Contained, it cut the dark cuff off on
   a hard vertical line.

   The first fix gave the stacked layout its own two-layer mask with gentler
   vertical stops (58% to 92%). That still did not reach the background:
   measured at the visual right edge it stopped at rgb(183,192,211) instead
   of white, because with `add` the alpha is L1 + L2 - L1*L2, and a vertical
   layer still 35% opaque across the cuff holds the edge visible no matter
   what the horizontal layer does. The wide layout's 66% to 76% stops put L2
   at zero before the cuff starts, so the horizontal layer alone governs the
   edge and it fades to nothing. Same mask everywhere is both simpler and
   the one that works.

   Verified by sampling the rendered pixels across the edge rather than by
   eye, which was wrong twice here: 127,142,176 through 254,254,255 at the
   last pixel inside the box, then pure white outside it.

   NO mask-composite. The two mask layers therefore compose with the CSS
   default, which is add, so the visible area is their UNION. An earlier
   version of this rule set intersect, on the reasoning that the design
   "meant" to fade both edges; that was an unrequested change and it cropped
   a third of the illustration away, from 44.5% ink to 31.4%. The design
   ships no composite property, so the default is what it was drawn against.

   scaleX(-1) is the designer's: the hand reads better pointing inward,
   toward the text it belongs to.

   Two masks, not one. The horizontal one fades the inner edge so the
   illustration dissolves into the text column instead of ending on a line;
   the vertical one lifts it off the section's bottom edge. -webkit- first,
   because Safari needs the prefix and takes the unprefixed one too. */
.hm__feature-art img {
	display: block;
	width: 100%;
	height: auto;
	aspect-ratio: 1 / 1;
	transform: scaleX(-1);
	mix-blend-mode: multiply;
	-webkit-mask-image: linear-gradient(90deg, transparent 0%, #000 24%),
	                    linear-gradient(180deg, #000 66%, transparent 76%);
	mask-image: linear-gradient(90deg, transparent 0%, #000 24%),
	            linear-gradient(180deg, #000 66%, transparent 76%);
}

/* =====================================================================
   THE CHECKERBOARD

   The design alternates blue and white by (row + column) being even, so the
   pattern depends on the column count and has to be restated per
   breakpoint. Now that the palette is one variable set, each breakpoint is
   a single selector list.

   Four columns repeats every 8 cards:   B W B W / W B W B
   Two columns repeats every 4:          B W / W B
   An ODD column count degenerates to simple alternation, because the parity
   of (row + column) flips on every cell. So three columns and one column
   share the same rule, which is also what the design's own mobile frame
   does.
   ===================================================================== */

/* Four columns, and ONLY from 1400px up. See the column-count note in the
   breakpoint section: four columns is not safe below that. */
@media (min-width: 1400px) {
	.hm__cats > .hm__cat:nth-child(8n+1),
	.hm__cats > .hm__cat:nth-child(8n+3),
	.hm__cats > .hm__cat:nth-child(8n+6),
	.hm__cats > .hm__cat:nth-child(8n+8) {
		--cat-bg:        var(--hm-cat-gradient);
		--cat-border:    var(--gradient-stop-blue);
		--cat-fg:        var(--marketing-text);
		--cat-fg-muted:  var(--marketing-text-muted);
		--cat-dot-bg:    var(--marketing-text);
		--cat-dot-fg:    var(--color-action-primary);
		--cat-glyph:     var(--marketing-text);
		--cat-glyph-opacity: 0.16;
	}
}

/* Three columns and one column: simple alternation, starting blue.
   --------------------------------------------------------------------
   THE COLUMN COUNT IS SET BY THE LONGEST WORD, NOT BY TASTE.

   "Software Development" sets 174px wide at --text-4xl, and the name is
   capped at 54% of the card so it stays clear of the artwork. A long word
   has no break opportunity, so below a certain card width it OVERFLOWS that
   cap and runs under the 3D object rather than wrapping.

   Measured rather than guessed: at 1440 nothing collides; at 1280 one card
   does, by 23px; at 1100 six of eight do, by up to 48px. That put the word
   "Translation" at 1.50:1 against the pen artwork where it needs 3.0, which
   is a real failure and the reason this band exists.

   The same 1100 to 1285 range is already on record in the design handoff
   pack as clipping the job cards. Same cause: four columns is too many
   there.

   Four columns needs a 322px card to hold that word, so it is confined to
   1400 and up. Below that: three columns, one step down the type scale, a
   narrower artwork zone and a wider name. That leaves 189px of room for a
   160px word at the tightest point in the band. */
@media (max-width: 1399px) {
	/* The job grid keeps three columns here. Unlike the category card it has
	   no fixed artwork zone competing with its text, so it degrades by
	   wrapping rather than by colliding.

	   THE CARD FOOTER STACKS FROM HERE DOWN, and not because it looks nicer:
	   side by side it relies on flex-wrap, and whether the button wraps
	   depends on how wide that particular salary happens to be. At 768 that
	   put "Apply now" on a second line for "N171,606 - N1,432,991" and not
	   for "N276,212 - N753,609", so two cards in the same row had their
	   footers at different heights and the margin-top:auto alignment was
	   defeated by the content. Stacking makes it independent of the number.
	   It also gives the button a full-width tap target on a narrow card. */
	.hm__job-foot { flex-direction: column; align-items: stretch; }
	.hm__btn--apply { margin-left: 0; width: 100%; }


	.hm__cats { grid-template-columns: repeat(3, minmax(0, 1fr)); }
	.hm__cat-name { max-width: 58%; font-size: var(--text-3xl); }
	.hm__cat--mono .hm__cat-name { max-width: 76%; }
	.hm__cat-art { width: 38%; }

	/* THE EXPLAINER STACKS HERE TOO, AND FOR THE SAME REASON THE CARDS DROP
	   A COLUMN: a fixed 600px illustration column beside a 1fr text column
	   does not degrade, it just eats the text. Measured at 1100: the text
	   column collapses to 360px, which leaves the three supporting points
	   about 100px each and wraps every one of their headings.

	   Stacked, the text gets the full width and the illustration sits below
	   it at a sane size. This is also the design's own mobile arrangement,
	   and it is what the handoff pack's fourth open question was asking for:
	   the dark preview put its artwork BEHIND the cards at narrow widths and
	   the note records the result, "on mobile, the explainer artwork is
	   mostly hidden". */
	.hm__feature-grid { grid-template-columns: minmax(0, 1fr); gap: var(--space-13); }
	.hm__feature-copy { max-width: none; }
	.hm__feature-art { max-width: 520px; }


	.hm__cats > .hm__cat:nth-child(odd) {
		--cat-bg:        var(--hm-cat-gradient);
		--cat-border:    var(--gradient-stop-blue);
		--cat-fg:        var(--marketing-text);
		--cat-fg-muted:  var(--marketing-text-muted);
		--cat-dot-bg:    var(--marketing-text);
		--cat-dot-fg:    var(--color-action-primary);
		--cat-glyph:     var(--marketing-text);
		--cat-glyph-opacity: 0.16;
	}
}

/* Two columns: back to a true checkerboard, repeating every 4. */
@media (max-width: 1099px) and (min-width: 768px) {
	.hm__cats > .hm__cat:nth-child(odd) {
		--cat-bg:        var(--color-surface-raised);
		--cat-border:    var(--color-border-subtle);
		--cat-fg:        var(--color-text-heading);
		--cat-fg-muted:  var(--color-text-muted);
		--cat-dot-bg:    var(--color-action-primary);
		--cat-dot-fg:    var(--color-action-primary-fg);
		--cat-glyph:     var(--blue-50);
		--cat-glyph-opacity: 1;
	}
	.hm__cats > .hm__cat:nth-child(4n+1),
	.hm__cats > .hm__cat:nth-child(4n+4) {
		--cat-bg:        var(--hm-cat-gradient);
		--cat-border:    var(--gradient-stop-blue);
		--cat-fg:        var(--marketing-text);
		--cat-fg-muted:  var(--marketing-text-muted);
		--cat-dot-bg:    var(--marketing-text);
		--cat-dot-fg:    var(--color-action-primary);
		--cat-glyph:     var(--marketing-text);
		--cat-glyph-opacity: 0.16;
	}
}

/* The load-more link. It spans the whole grid row rather than sitting in a
   cell, so it reads as the end of the list rather than as a card. */
.hm__more {
	grid-column: 1 / -1;
	display: flex;
	align-items: center;
	justify-content: center;
	gap: var(--space-5);
	min-height: 56px;
	margin-top: var(--space-3);
	padding: 0 var(--space-11);
	border-radius: var(--radius-lg);
	background: var(--color-surface-raised);
	border: 1px solid var(--color-border-default);
	font-size: var(--text-lg);
	font-weight: var(--weight-bold);
	color: var(--color-link);
	text-decoration: none;
	transition: border-color var(--duration-base) var(--ease-standard),
	            color var(--duration-base) var(--ease-standard);
}

.hm__more:hover {
	border-color: var(--color-action-primary);
	color: var(--color-action-primary-hover);
}

.hm__more:focus-visible {
	outline: var(--focus-ring-width) solid var(--focus-ring-color);
	outline-offset: var(--focus-ring-offset);
}

/* Dimmed while a page is in flight, so a slow connection shows that the
   click landed rather than looking ignored. */
.hm__more[aria-busy="true"] { opacity: 0.6; pointer-events: none; }

.hm__more-count {
	font-size: var(--text-sm);
	font-weight: var(--weight-regular);
	color: var(--color-text-muted);
	font-variant-numeric: tabular-nums;
}

/* =====================================================================
   FEATURED JOBS
   ===================================================================== */

/* The one section on a tinted ground, which is what separates it from the
   white explainer above and the white page below without adding a rule. */
.hm__section--sunken { background: var(--color-surface-sunken); }

/* The development-data notice. Deliberately NOT styled as a warning: it is
   a statement of fact about the rows below, and amber would make the page
   look broken to a client reviewing it. Bordered and quiet. */
.hm__notice {
	margin-top: var(--space-9);
	padding: var(--space-5) var(--space-8);
	border-radius: var(--radius-md);
	border: 1px solid var(--color-border-default);
	background: var(--color-surface-raised);
	font-size: var(--text-base);
	line-height: var(--leading-normal);
	color: var(--color-text-body);
}

.hm__notice strong { color: var(--color-text-heading); }

.hm__jobs {
	margin-top: var(--space-13);
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	gap: var(--space-9);
	align-items: stretch;
}

.hm__job {
	position: relative;
	display: flex;
	flex-direction: column;
	padding: var(--space-8);
	border-radius: var(--radius-lg);
	background: var(--color-surface-raised);
	border: 1px solid var(--color-border-subtle);
	box-shadow: var(--elevation-1);
	transition: box-shadow var(--duration-base) var(--ease-standard),
	            border-color var(--duration-base) var(--ease-standard),
	            transform var(--duration-base) var(--ease-standard);
}

.hm__job:hover {
	box-shadow: var(--elevation-glow-brand);
	border-color: var(--color-border-strong);
	transform: translateY(-2px);
}

/* The focus ring goes on the CARD when its title link is focused, because
   the link's own box is just the text while the clickable area is the whole
   card. Ringing the text would point at the wrong shape. */
.hm__job:focus-within {
	outline: var(--focus-ring-width) solid var(--focus-ring-color);
	outline-offset: var(--focus-ring-offset);
}

.hm__job-top {
	display: flex;
	align-items: center;
	gap: var(--space-5);
}

.hm__job-logo {
	flex: 0 0 44px;
	width: 44px;
	height: 44px;
	border-radius: var(--radius-circle);
	overflow: hidden;
	background: var(--color-surface-raised);
	border: 1px solid var(--color-border-subtle);
}

.hm__job-logo img {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: contain;
}

/* No logo: the brand ramp as a ring around the company's initial. The 2px
   padding is what makes the gradient read as a ring rather than a disc. */
.hm__job-logo--initial {
	display: block;
	padding: 2px;
	border: 0;
	background: var(--gradient-brand-diagonal);
}

.hm__job-logo--initial > span {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 100%;
	height: 100%;
	border-radius: var(--radius-circle);
	background: var(--color-surface-raised);
	font-size: var(--text-xl);
	font-weight: var(--weight-bold);
	color: var(--color-text-heading);
}

.hm__job-who { flex: 1 1 auto; min-width: 0; }

.hm__job-company {
	font-size: var(--text-md);
	line-height: var(--leading-tight);
	font-weight: var(--weight-bold);
	color: var(--color-text-heading);
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
}

.hm__job-posted {
	margin-top: 1px;
	font-size: var(--text-sm);
	color: var(--color-text-muted);
	white-space: nowrap;
}

/* The title is the card's real link. Its ::after stretches over the whole
   card, so the accessible name stays the job title instead of every word on
   the card being read out as one link. */
.hm__job-title {
	margin-top: var(--space-7);
	font-size: var(--text-2xl);
	line-height: 1.35;             /* display carve-out, see the header */
	font-weight: var(--weight-bold);
	color: var(--color-text-heading);
	text-decoration: none;
	text-wrap: pretty;
}

.hm__job-title::after {
	content: "";
	position: absolute;
	inset: 0;
	z-index: 1;
	border-radius: var(--radius-lg);
}

.hm__job-title:hover {
	color: var(--color-text-heading);
	text-decoration: underline;
	text-decoration-color: var(--color-action-primary);
	text-underline-offset: 4px;
}

/* The stretched link would swallow the focus ring's own outline, so the
   ring is drawn on the card (above) and suppressed here. */
.hm__job-title:focus-visible { outline: none; }

.hm__job-tags {
	margin-top: var(--space-6);
	display: flex;
	flex-wrap: wrap;
	gap: var(--space-3);
}

.hm__pill {
	display: inline-flex;
	align-items: center;
	gap: var(--space-2);
	padding: var(--space-2) var(--space-5);
	border-radius: var(--radius-pill);
	background: var(--color-surface-subtle);
	border: 1px solid var(--color-border-subtle);
	font-size: var(--text-sm);
	line-height: var(--leading-tight);
	color: var(--color-text-body);
	white-space: nowrap;
}

.hm__pill--featured {
	background: var(--color-feedback-success-surface);
	border-color: var(--color-feedback-success-surface);
	font-weight: var(--weight-bold);
	color: var(--color-feedback-success);
}

/* The development-data flag. Uses the warning pair rather than the danger
   one: a seeded row is not an error, it is something to be honest about. */
.hm__pill--flag {
	background: var(--color-feedback-warning-surface);
	border-color: var(--color-feedback-warning-surface);
	font-weight: var(--weight-bold);
	color: var(--color-feedback-warning);
}

/* margin-top:auto pins the footer to the bottom however tall the title runs,
   so the pay lines up across a row of cards with different title lengths. */
.hm__job-foot {
	margin-top: auto;
	padding-top: var(--space-8);
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: var(--space-5);
}

.hm__job-pay { min-width: 0; }

.hm__job-money {
	font-size: var(--text-lg);
	line-height: var(--leading-tight);
	font-weight: var(--weight-bold);
	color: var(--color-text-heading);
	white-space: nowrap;
	font-variant-numeric: tabular-nums;
}

.hm__job-money--none {
	font-weight: var(--weight-regular);
	color: var(--color-text-muted);
}

.hm__job-where {
	margin-top: 2px;
	font-size: var(--text-sm);
	color: var(--color-text-muted);
}

/* Above the stretched title link, or it would not be clickable. */
.hm__btn--apply {
	position: relative;
	z-index: 2;
	flex: 0 0 auto;
	margin-left: auto;
	height: 40px;
	padding: 0 var(--space-8);
	font-size: var(--text-base);
}

/* =====================================================================
   CLOSING CTA
   ===================================================================== */

.hm__cta-sec { border-top: 0; }

.hm__cta {
	position: relative;
	display: grid;
	grid-template-columns: minmax(0, 1fr) 380px;
	gap: var(--space-14);
	padding: 0 var(--space-16);
	border-radius: var(--radius-lg);
	background: var(--blue-50);
	border: 1px solid var(--blue-100);
	/* The phone is taller than the panel and is cropped by this, which is
	   what makes it read as rising out of the surface. */
	overflow: hidden;
}

/* The brand ramp across the top edge. Decoration: the heading below says
   what the panel is. */
.hm__cta-rule {
	position: absolute;
	left: 0;
	right: 0;
	top: 0;
	height: 4px;
	/* --gradient-brand, not --gradient-brand-reverse. The design runs green
	   at the left to blue at the right, and reverse is the other way round,
	   so the first version was mirrored. The token is 135deg against the
	   design's 90deg, which on a 4px-tall bar 1360px wide is
	   indistinguishable: the gradient line is dominated by the width. */
	background: var(--gradient-brand);
}

.hm__cta-copy {
	align-self: center;
	padding: var(--space-16) 0;
	max-width: 580px;
}

.hm__cta-copy h2 {
	margin: 0;
	font-size: 50px;               /* display carve-out, see the header */
	line-height: 1.1;              /* display carve-out, see the header */
	font-weight: var(--weight-bold);
	letter-spacing: var(--tracking-tight);
	color: var(--color-text-heading);
	text-wrap: balance;
}

.hm__cta-copy p {
	margin-top: var(--space-7);
	max-width: 500px;
	font-size: var(--text-xl);
	line-height: var(--leading-normal);
	color: var(--color-text-body);
	text-wrap: pretty;
}

.hm__cta-actions { margin-top: var(--space-11); display: flex; }

.hm__cta-art {
	position: relative;
	height: 468px;
	margin-top: var(--space-14);
}

/* =====================================================================
   THE PHONE

   Markup rather than an image: it carries figures that would go stale as a
   picture, it stays sharp at any density, and it costs no bytes.
   ===================================================================== */

.hm__phone {
	position: absolute;
	top: 0;
	left: 50%;
	transform: translateX(-50%);
	width: 300px;
	height: 620px;
	padding: var(--space-4);
	border-radius: 46px;
	background: var(--marketing-surface);
	border: 1px solid var(--neutral-800);
	box-shadow: var(--elevation-3);
}

.hm__phone-screen {
	position: relative;
	height: 100%;
	border-radius: 36px;
	overflow: hidden;
	background: var(--color-surface-subtle);
}

.hm__phone-notch {
	position: absolute;
	top: var(--space-4);
	left: 50%;
	transform: translateX(-50%);
	width: 88px;
	height: 24px;
	border-radius: var(--radius-pill);
	background: var(--marketing-surface);
}

.hm__phone-status {
	height: 44px;
	padding: 0 var(--space-10);
	display: flex;
	align-items: center;
	justify-content: space-between;
	font-size: var(--text-sm);
	font-weight: var(--weight-bold);
	color: var(--color-text-heading);
}

.hm__phone-bars { display: flex; align-items: flex-end; gap: 2px; }
.hm__phone-bars i {
	display: block;
	width: 3px;
	border-radius: 1px;
	background: var(--color-text-heading);
}
.hm__phone-bars i:nth-child(1) { height: 5px; }
.hm__phone-bars i:nth-child(2) { height: 7px; }
.hm__phone-bars i:nth-child(3) { height: 9px; }

.hm__phone-nav {
	height: 40px;
	padding: 0 var(--space-7);
	display: flex;
	align-items: center;
	gap: var(--space-4);
	color: var(--color-action-primary);
}

.hm__phone-nav span {
	font-size: var(--text-md);
	font-weight: var(--weight-bold);
	color: var(--color-text-heading-app);
}

.hm__phone-card {
	margin: var(--space-1) var(--space-5) 0;
	padding: var(--space-6);
	border-radius: var(--radius-lg);
	background: var(--color-surface-raised);
}

.hm__phone-title {
	font-size: var(--text-base);
	line-height: 1.35;             /* display carve-out, see the header */
	font-weight: var(--weight-bold);
	color: var(--color-text-heading-app);
}

.hm__phone-sub {
	margin-top: 3px;
	font-size: var(--text-xs);
	color: var(--color-text-muted);
}

.hm__phone-escrow {
	margin-top: var(--space-5);
	padding: var(--space-5);
	border-radius: var(--radius-md);
	background: var(--color-feedback-success-surface);
}

.hm__phone-held {
	display: flex;
	align-items: center;
	gap: var(--space-2);
	font-size: var(--text-xs);
	font-weight: var(--weight-bold);
	color: var(--color-feedback-success);
}

.hm__phone-amount {
	margin-top: var(--space-1);
	font-size: var(--text-5xl);
	line-height: 1.2;              /* display carve-out, see the header */
	font-weight: var(--weight-bold);
	letter-spacing: var(--tracking-snug);
	color: var(--color-text-heading-app);
	/* The figure counts up, so the digits must not reflow while it does. */
	font-variant-numeric: tabular-nums;
}

.hm__phone-note {
	margin-top: var(--space-1);
	font-size: var(--text-xs);
	line-height: 1.45;             /* display carve-out, see the header */
	color: var(--color-text-body);
}

/* ---- the timeline --------------------------------------------------- */
.hm__phone-steps {
	position: relative;
	margin: var(--space-4) var(--space-5) 0;
	padding: var(--space-6);
	border-radius: var(--radius-lg);
	background: var(--color-surface-raised);
	display: flex;
	flex-direction: column;
	gap: var(--space-7);
}

.hm__phone-rail,
.hm__phone-fill {
	position: absolute;
	left: 22px;
	top: 30px;
	width: 2px;
	height: 128px;
}

.hm__phone-rail { background: var(--color-border-default); }

.hm__phone-fill {
	background: var(--color-feedback-success);
	transform-origin: top;
	/* Resting at scaleY(1): complete. home-escrow.js winds it back to 0.4
	   before animating forward, so a failed script leaves a finished
	   contract rather than an empty rail. */
	transform: scaleY(1);
	transition: transform var(--duration-slow) var(--ease-standard);
}

.hm__step { display: flex; align-items: flex-start; gap: var(--space-4); }

.hm__step-dot {
	position: relative;
	z-index: 1;
	flex: 0 0 18px;
	width: 18px;
	height: 18px;
	border-radius: var(--radius-circle);
	background: var(--color-surface-raised);
	border: 2px solid var(--color-border-strong);
	display: flex;
	align-items: center;
	justify-content: center;
	color: var(--color-action-primary-fg);
	transition: background var(--duration-slow) var(--ease-standard),
	            border-color var(--duration-slow) var(--ease-standard);
}

.hm__step-dot svg { opacity: 0; transition: opacity var(--duration-base) var(--ease-standard); }

.hm__step-dot--done {
	background: var(--color-feedback-success);
	border-color: var(--color-feedback-success);
}

.hm__step-dot--done svg { opacity: 1; }

.hm__step-dot--now { border-color: var(--color-action-primary); }
.hm__step-dot--now > span {
	width: 6px;
	height: 6px;
	border-radius: var(--radius-circle);
	background: var(--color-action-primary);
}

.hm__step-name {
	font-size: var(--text-sm);
	line-height: 1.3;              /* display carve-out, see the header */
	font-weight: var(--weight-bold);
	color: var(--color-text-heading-app);
}

.hm__step-name--todo { color: var(--color-text-muted); }

.hm__step-when {
	margin-top: 2px;
	font-size: var(--text-xs);
	color: var(--color-text-muted);
}

/* =====================================================================
   FOOTER
   ===================================================================== */

.hm__footer {
	padding: var(--space-16) var(--space-13) var(--space-11);
	background: var(--color-surface-subtle);
	border-top: 1px solid var(--color-border-subtle);
}

.hm__footer-top {
	display: grid;
	grid-template-columns: 1.6fr 1fr 1fr 1fr;
	gap: var(--space-14);
}

.hm__footer-logo img { display: block; width: 80px; height: 48px; }

.hm__footer-brand p {
	margin-top: var(--space-6);
	max-width: 42ch;
	font-size: var(--text-base);
	line-height: var(--leading-normal);
	color: var(--color-text-body);
}

.hm__footer-col { display: flex; flex-direction: column; }

.hm__footer-head {
	margin-bottom: var(--space-6);
	font-size: var(--text-xs);
	font-weight: var(--weight-bold);
	letter-spacing: var(--tracking-wider);
	text-transform: uppercase;
	color: var(--color-text-heading);
}

.hm__footer-col a,
.hm__footer-legal a {
	font-size: var(--text-base);
	line-height: var(--leading-tight);
	color: var(--color-text-body);
	text-decoration: none;
	transition: color var(--duration-base) var(--ease-standard);
}

.hm__footer-col a { padding: var(--space-2) 0; }

.hm__footer-col a:hover,
.hm__footer-legal a:hover { color: var(--color-link); }

.hm__footer-col a:focus-visible,
.hm__footer-legal a:focus-visible,
.hm__footer-logo:focus-visible {
	outline: var(--focus-ring-width) solid var(--focus-ring-color);
	outline-offset: var(--focus-ring-offset);
}

/* Every active category, flowed across the footer's width rather than
   stacked in a column. auto-fill with a minimum track means the count can
   grow without anyone revisiting this: an admin adding a category adds a
   cell, not a longer column. */
.hm__footer-cats {
	margin-top: var(--space-14);
	padding-top: var(--space-8);
	border-top: 1px solid var(--color-border-subtle);
}

.hm__footer-catlist {
	margin-top: var(--space-6);
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
	gap: var(--space-2) var(--space-8);
}

.hm__footer-catlist a {
	padding: var(--space-2) 0;
	font-size: var(--text-base);
	line-height: var(--leading-tight);
	color: var(--color-text-body);
	text-decoration: none;
	transition: color var(--duration-base) var(--ease-standard);
}

.hm__footer-catlist a:hover { color: var(--color-link); }

.hm__footer-catlist a:focus-visible {
	outline: var(--focus-ring-width) solid var(--focus-ring-color);
	outline-offset: var(--focus-ring-offset);
}

.hm__footer-trust {
	margin-top: var(--space-14);
	padding-top: var(--space-8);
	border-top: 1px solid var(--color-border-subtle);
	display: flex;
	flex-wrap: wrap;
	gap: var(--space-11);
	font-size: var(--text-base);
	font-weight: var(--weight-bold);
	color: var(--color-text-heading);
}

.hm__footer-trust span { display: inline-flex; align-items: center; gap: var(--space-3); }

/* The icons here inherit the row's heading ink rather than the family's
   green. On a tinted footer at 16px the green outline reads as decoration
   fighting the bold label beside it; matching the text makes the pair read
   as one statement. The escrow section keeps the green, where the icons sit
   beside body copy and need to separate from it. */
.hm__footer-trust .hm__icon { color: currentColor; }

.hm__footer-legal {
	margin-top: var(--space-8);
	padding-top: var(--space-8);
	border-top: 1px solid var(--color-border-subtle);
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: var(--space-6);
	font-size: var(--text-base);
	color: var(--color-text-muted);
}

.hm__footer-legal div { display: flex; flex-wrap: wrap; gap: var(--space-8); }

/* =====================================================================
   PLAYFUL HERO  (item 140)

   The second hero option, served at /preview-playful/. No photography: a
   tinted panel, a cut-out figure, decorative shapes and the search built in.

   ITEM 88 DOES NOT ENGAGE ANYWHERE ON THIS PAGE. Every piece of text sits
   on a flat token colour rather than on an image, so the whole per-frame
   scrim measurement the light hero needed simply does not apply here. That
   is the single biggest difference between the two options and it is worth
   knowing before choosing between them.

   The icon family used by the playful escrow section is --green-600, the
   feedback success colour, used DECORATIVELY. See partials/icon.html.
   ===================================================================== */

/* ---- the header bar, which is outside the hero ---------------------- */
.hm__bar {
	position: relative;
	z-index: 5;
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: var(--space-8);
	height: var(--header-height);
	padding: 0 var(--space-13);
	background: var(--color-surface-raised);
	border-bottom: 1px solid var(--color-border-subtle);
}

.hm__bar-left,
.hm__bar-right { display: flex; align-items: center; gap: var(--space-14); }
.hm__bar-right { gap: var(--space-9); }

.hm__bar-logo img { display: block; width: 80px; height: 48px; }

.hm__bar-nav { display: flex; align-items: center; gap: var(--space-11); }

.hm__bar-nav a {
	font-size: var(--text-md);
	color: var(--color-text-body);
	white-space: nowrap;
	text-decoration: none;
	padding-bottom: var(--space-2);
	border-bottom: 2px solid transparent;
	transition: color var(--duration-base) var(--ease-standard),
	            border-color var(--duration-base) var(--ease-standard);
}

.hm__bar-nav a:hover {
	color: var(--color-link);
	border-bottom-color: var(--color-action-primary);
}

.hm__bar-login {
	font-size: var(--text-md);
	font-weight: var(--weight-bold);
	color: var(--color-link);
	text-decoration: none;
}

.hm__bar-login:hover { color: var(--color-action-primary-hover); }

.hm__bar-nav a:focus-visible,
.hm__bar-login:focus-visible,
.hm__bar-logo:focus-visible {
	outline: var(--focus-ring-width) solid var(--focus-ring-color);
	outline-offset: var(--focus-ring-offset);
}

/* ---- the hero panel -------------------------------------------------- */
.hm__phero {
	position: relative;
	overflow: hidden;
	background: var(--blue-50);
}

.hm__phero-grid {
	display: grid;
	grid-template-columns: minmax(0, 1fr) 560px;
	gap: var(--space-13);
	align-items: end;
	padding: var(--space-12) var(--space-13) 0;
}

.hm__phero-copy { position: relative; padding-bottom: var(--space-16); }

/* A soft bloom behind the headline's first line. Decoration: it identifies
   nothing and sits under text that is already at full contrast on the
   panel, so it cannot pull anything below its ratio. */
.hm__phero-glow {
	position: absolute;
	left: -56px;
	top: -24px;
	width: 150px;
	height: 150px;
	border-radius: var(--radius-circle);
	background: radial-gradient(circle,
		var(--blue-100) 0%, rgba(199, 206, 247, 0) 70%);
	pointer-events: none;
}

.hm__phero h1 {
	position: relative;
	margin-top: var(--space-10);
	max-width: 560px;
	font-size: 64px;               /* display carve-out, see the header */
	line-height: 1.1;              /* display carve-out, see the header */
	font-weight: var(--weight-extrabold);
	letter-spacing: var(--tracking-tight);
	color: var(--color-text-heading);
	text-wrap: balance;
}

.hm__phero-lead {
	margin-top: var(--space-7);
	max-width: 520px;
	font-size: var(--text-2xl);
	line-height: 1.5;              /* display carve-out, see the header */
	color: var(--color-text-body);
	text-wrap: pretty;
}

/* ---- the search, which this design draws in ------------------------- */
.hm__psearch {
	margin-top: var(--space-12);
	max-width: 700px;
	display: flex;
	align-items: center;
	gap: var(--space-3);
	padding: var(--space-1) var(--space-1) var(--space-1) 0;
	padding: 6px;
	border-radius: var(--radius-lg);
	background: var(--color-surface-raised);
	border: 1px solid var(--color-border-subtle);
	box-shadow: var(--elevation-2);
	transition: box-shadow var(--duration-base) var(--ease-standard);
}

.hm__psearch:focus-within { box-shadow: var(--elevation-3), var(--elevation-glow-brand); }

.hm__psearch-field {
	position: relative;
	flex: 1 1 0;
	min-width: 0;
	display: flex;
	flex-direction: column;
	justify-content: center;
	gap: 2px;
	height: 60px;
	padding: 0 var(--space-7);
}

/* The keyword field takes the extra room: a job title is longer than a city
   name, and the design weights it 1.3 to 1. */
.hm__psearch-field:first-of-type { flex: 1.3 1 0; }

.hm__psearch-field > span {
	font-size: var(--text-sm);
	line-height: 1.3;              /* display carve-out, see the header */
	font-weight: var(--weight-bold);
	color: var(--color-text-heading);
	cursor: pointer;
}

/* The same four resets the other search bar needs: style.css dresses every
   input on the site for the dashboard forms, and its shadow, margin, height
   and transition all reach in here. */
.hm__psearch-field input {
	width: 100%;
	height: auto;
	margin: 0;
	border: 0;
	padding: 0;
	box-shadow: none;
	background: transparent;
	font-family: inherit;
	font-size: var(--text-md);
	line-height: var(--leading-tight);
	color: var(--color-text-heading);
	transition: none;
}

.hm__psearch-field input::placeholder {
	color: var(--color-text-placeholder);
	opacity: 1;    /* Firefox dims placeholders, which would drop it below
	                  the floor the token guarantees. */
}

.hm__psearch-sep {
	flex: 0 0 1px;
	width: 1px;
	height: 32px;
	background: var(--color-border-subtle);
}

.hm__psearch-submit {
	flex: 0 0 auto;
	height: 52px;
	padding: 0 var(--space-11);
}

.hm__psearch-field input:focus-visible,
.hm__psearch-submit:focus-visible {
	outline: var(--focus-ring-width) solid var(--focus-ring-color);
	outline-offset: var(--focus-ring-offset);
}

/* ---- points and the flip link --------------------------------------- */
.hm__phero-points {
	margin-top: var(--space-9);
	display: flex;
	flex-wrap: wrap;
	gap: var(--space-4) var(--space-9);
}

.hm__phero-points li {
	display: flex;
	align-items: flex-start;
	gap: var(--space-3);
	font-size: var(--text-md);
	line-height: var(--leading-tight);
	color: var(--color-text-body);
}

/* The list used a CSS dot on the first pass. The design draws an icon per
   line instead, each one illustrating its own claim, so the dot is gone
   rather than sitting beside them. margin-top nudges the 16px glyph onto
   the first line's optical centre; align-items is flex-start so a wrapping
   line keeps the icon at the top rather than centring it against two. */
.hm__phero-points li > .hm__icon { margin-top: 2px; }

.hm__phero-flip {
	margin-top: var(--space-8);
	font-size: var(--text-md);
	color: var(--color-text-muted);
}

.hm__phero-flip a {
	font-weight: var(--weight-bold);
	color: var(--color-link);
	text-decoration: none;
	border-bottom: 2px solid transparent;
	padding-bottom: 2px;
	transition: border-color var(--duration-base) var(--ease-standard);
}

.hm__phero-flip a:hover { border-bottom-color: var(--color-action-primary); }

/* =====================================================================
   THE ART COLUMN: shapes, figure, floating cards
   ===================================================================== */

.hm__phero-art { position: relative; height: 560px; }

.hm__blob { position: absolute; pointer-events: none; }

/* The organic shapes. Four-value border-radius with a slash gives each
   corner a different horizontal and vertical radius, which is what stops
   them reading as circles. Decoration, so the brand green is legal here
   despite being 2.08:1 on white and illegal as text anywhere. */
.hm__blob--main {
	left: 50%;
	bottom: var(--space-13);
	width: 340px;
	height: 300px;
	transform: translateX(-50%);
	border-radius: 62% 38% 46% 54% / 55% 48% 52% 45%;
	background: var(--gradient-brand-diagonal);
	opacity: 0.14;
}

.hm__blob--ring {
	left: 50%;
	top: 200px;
	width: 400px;
	height: 128px;
	transform: translateX(-50%) rotate(-10deg);
	border-radius: var(--radius-circle);
	border: 1px solid var(--blue-100);
}

.hm__blob--a {
	right: 56px;
	top: 64px;
	width: 44px;
	height: 56px;
	border-radius: 48% 52% 60% 40% / 40% 45% 55% 60%;
	background: var(--gradient-stop-blue);
	opacity: 0.22;
}

.hm__blob--b {
	left: 64px;
	bottom: 96px;
	width: 28px;
	height: 32px;
	border-radius: 45% 55% 40% 60% / 60% 40% 60% 40%;
	background: var(--gradient-stop-green);
	opacity: 0.35;
}

.hm__blob--c {
	right: 120px;
	bottom: var(--space-13);
	width: 10px;
	height: 10px;
	border-radius: var(--radius-circle);
	background: var(--gradient-stop-teal);
	opacity: 0.5;
}

.hm__figure {
	position: absolute;
	z-index: 2;
	left: 50%;
	bottom: 0;
	transform: translateX(-50%);
}

.hm__figure img {
	display: block;
	width: 277px;
	height: 540px;
	filter: drop-shadow(var(--elevation-2));
}

/* ---- the two floating cards ----------------------------------------- */
.hm__float {
	position: absolute;
	z-index: 3;
	padding: var(--space-6);
	border-radius: var(--radius-lg);
	background: var(--color-surface-raised);
	border: 1px solid var(--color-border-subtle);
	box-shadow: var(--elevation-3);
}

.hm__float--job { left: -24px; top: 110px; width: 248px; }
.hm__float--cta { right: -16px; bottom: 150px; width: 196px; }

.hm__float-top { display: flex; align-items: center; gap: var(--space-4); }

.hm__float-avatar {
	flex: 0 0 36px;
	width: 36px;
	height: 36px;
	padding: 2px;
	border-radius: var(--radius-circle);
	background: var(--gradient-brand-diagonal);
}

.hm__float-avatar > span {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 100%;
	height: 100%;
	border-radius: var(--radius-circle);
	background: var(--color-surface-raised);
	font-size: var(--text-base);
	font-weight: var(--weight-bold);
	color: var(--color-text-heading);
}

.hm__float-who { min-width: 0; }

.hm__float-title {
	font-size: var(--text-base);
	line-height: 1.35;             /* display carve-out, see the header */
	font-weight: var(--weight-bold);
	color: var(--color-text-heading);
	overflow: hidden;
	text-overflow: ellipsis;
	display: -webkit-box;
	-webkit-line-clamp: 2;
	-webkit-box-orient: vertical;
}

.hm__float-sub {
	font-size: var(--text-xs);
	color: var(--color-text-muted);
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
}

.hm__float-foot {
	margin-top: var(--space-5);
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: var(--space-4);
}

.hm__float-pay {
	font-size: var(--text-sm);
	font-weight: var(--weight-bold);
	color: var(--color-text-heading);
	white-space: nowrap;
	font-variant-numeric: tabular-nums;
}

.hm__float-btn {
	height: 32px;
	padding: 0 var(--space-5);
	margin-left: auto;
	font-size: var(--text-xs);
}

.hm__float-live {
	display: flex;
	align-items: center;
	gap: var(--space-3);
	font-size: var(--text-2xs);
	font-weight: var(--weight-bold);
	letter-spacing: var(--tracking-wide);
	color: var(--color-feedback-success);
}

.hm__float--cta .hm__icon { color: var(--color-feedback-success); }

.hm__float-claim {
	margin-top: var(--space-3);
	font-size: var(--text-md);
	line-height: 1.35;             /* display carve-out, see the header */
	font-weight: var(--weight-bold);
	color: var(--color-text-heading);
	text-wrap: pretty;
}

.hm__float--cta a {
	margin-top: var(--space-3);
	display: inline-block;
	font-size: var(--text-xs);
	font-weight: var(--weight-bold);
	color: var(--color-link);
	text-decoration: none;
}

.hm__float--cta a:hover { color: var(--color-action-primary-hover); text-decoration: underline; }

/* ---- the icon family ------------------------------------------------- */
/* Used on both home pages since item 145, not just the playful one. */
/* --green-600. It is the feedback success token being used DECORATIVELY:
   these illustrate features, they do not report that something succeeded.
   See partials/icon.html. */
.hm__icon { flex: 0 0 auto; color: var(--color-feedback-success); }

.hm__escrow-icon {
	flex: 0 0 auto;
	display: inline-flex;
	align-items: center;
	justify-content: center;
}

.hm__feature-cta {
	margin-top: var(--space-11);
	display: inline-flex;
	align-items: center;
	gap: var(--space-3);
	min-height: 44px;              /* tap target, not the type size */
	font-size: var(--text-xl);
	font-weight: var(--weight-bold);
	color: var(--color-link);
	text-decoration: none;
	transition: color var(--duration-base) var(--ease-standard),
	            gap var(--duration-base) var(--ease-standard);
}

.hm__feature-cta:hover { color: var(--color-action-primary-hover); gap: var(--space-5); }
.hm__feature-cta .hm__icon { color: currentColor; }

.hm__feature-cta:focus-visible {
	outline: var(--focus-ring-width) solid var(--focus-ring-color);
	outline-offset: var(--focus-ring-offset);
}

/* The light menu button, for the white header bar. The dark one is drawn
   for a photograph and is invisible on white.

   DOUBLED CLASS SELECTORS, on purpose. Written as .hm__menu--light summary
   these are (0,2,0), exactly the same as the .hm__menu summary rules they
   need to beat, so which one applies comes down to which appears later in
   the file. It did not: the generic rules sit ~25 lines below these and
   won, leaving a dark scrim-tinted button with white bars on a white bar.
   That is the third time this file's two media-query regions have produced
   an order-dependent override.

   .hm__menu.hm__menu--light is (0,3,0) and wins wherever it sits, so this
   cannot break again when the file grows. */
.hm__menu.hm__menu--light summary {
	background: var(--color-surface-raised);
	border-color: var(--color-border-default);
}
.hm__menu.hm__menu--light summary span { background: var(--color-text-heading); }
.hm__menu-panel.hm__menu-panel--light {
	background: var(--color-surface-raised);
	border-color: var(--color-border-subtle);
}
.hm__menu-panel.hm__menu-panel--light a {
	color: var(--color-text-body);
	border-bottom-color: var(--color-border-subtle);
}
.hm__menu-panel.hm__menu-panel--light a:hover { color: var(--color-link); }

/* =====================================================================
   THE FIND WORK DROPDOWN  (item 141)

   Jobs and tasks are both "find work" but they are different products: one
   is employment you apply to, the other a project you bid on. Separate
   models, pages, taxonomies and visibility rules, so the nav offers a
   choice rather than pretending there is one list.

   Built on <details>. It opens on click rather than hover, which is what a
   touch device needs and what stops a hover menu getting stuck open on one.
   js/home-nav.js adds click-outside and Escape; neither is the mechanism.
   ===================================================================== */

.hm__drop { position: relative; }

.hm__drop > summary {
	display: inline-flex;
	align-items: center;
	gap: var(--space-2);
	font-size: var(--text-md);
	color: var(--color-text-body);
	white-space: nowrap;
	cursor: pointer;
	list-style: none;
	padding-bottom: var(--space-2);
	border-bottom: 2px solid transparent;
	transition: color var(--duration-base) var(--ease-standard),
	            border-color var(--duration-base) var(--ease-standard);
}

.hm__drop > summary::-webkit-details-marker { display: none; }

/* The caret, drawn rather than shipped as an icon: it is punctuation for
   the control, not a member of the icon family. It turns when open, which
   is the only signal that the panel state changed for someone who cannot
   see the panel itself. */
.hm__drop > summary::after {
	content: "";
	width: 7px;
	height: 7px;
	border-right: 2px solid currentColor;
	border-bottom: 2px solid currentColor;
	transform: translateY(-2px) rotate(45deg);
	transition: transform var(--duration-base) var(--ease-standard);
}

.hm__drop[open] > summary::after { transform: translateY(1px) rotate(-135deg); }

.hm__drop > summary:hover {
	color: var(--color-link);
	border-bottom-color: var(--color-action-primary);
}

.hm__drop > summary:focus-visible {
	outline: var(--focus-ring-width) solid var(--focus-ring-color);
	outline-offset: var(--focus-ring-offset);
}

.hm__drop-panel {
	position: absolute;
	z-index: 6;
	left: 0;
	top: calc(100% + var(--space-4));
	width: max-content;
	min-width: 220px;
	display: flex;
	flex-direction: column;
	padding: var(--space-2);
	border-radius: var(--radius-lg);
	background: var(--color-surface-raised);
	border: 1px solid var(--color-border-subtle);
	box-shadow: var(--elevation-2);
}

.hm__drop-panel a {
	display: flex;
	flex-direction: column;
	gap: 1px;
	padding: var(--space-4) var(--space-6);
	border-radius: var(--radius-md);
	text-decoration: none;
	transition: background var(--duration-base) var(--ease-standard);
}

.hm__drop-panel a:hover { background: var(--color-surface-subtle); }

.hm__drop-panel a:focus-visible {
	outline: var(--focus-ring-width) solid var(--focus-ring-color);
	outline-offset: -2px;
}

.hm__drop-panel strong {
	font-size: var(--text-md);
	font-weight: var(--weight-bold);
	color: var(--color-text-heading);
}

.hm__drop-panel span {
	font-size: var(--text-sm);
	color: var(--color-text-muted);
}

/* The dark variant, for the light hero where the nav sits on photography.
   Doubled class on purpose: a single .hm__drop--dark would tie with the
   base rules above and be settled by file order, which is the trap this
   stylesheet has already sprung three times. */
.hm__drop.hm__drop--dark > summary { color: var(--marketing-text); }
.hm__drop.hm__drop--dark > summary:hover {
	color: var(--marketing-text);
	border-bottom-color: var(--marketing-accent-blue);
}

.hm__drop-panel.hm__drop-panel--dark {
	background: var(--marketing-surface);
	border-color: var(--neutral-800);
	box-shadow: var(--elevation-3);
}
.hm__drop-panel.hm__drop-panel--dark a:hover { background: var(--marketing-surface-raised); }
.hm__drop-panel.hm__drop-panel--dark strong { color: var(--marketing-text); }
.hm__drop-panel.hm__drop-panel--dark span { color: var(--marketing-text-muted); }

/* =====================================================================
   MOBILE MENU

   A native <details>, so it works with no JavaScript. The marker is
   removed and the summary is drawn as the three-bar button from the
   design.
   ===================================================================== */

.hm__menu { display: none; position: relative; }

.hm__menu summary {
	width: 44px;
	height: 44px;
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: var(--space-2);
	border: 1px solid var(--neutral-400);
	border-radius: var(--radius-md);
	background: rgba(var(--hm-scrim-rgb), 0.6);
	cursor: pointer;
	list-style: none;
	transition: border-color var(--duration-base) var(--ease-standard);
}

.hm__menu summary::-webkit-details-marker { display: none; }
.hm__menu summary:hover { border-color: var(--marketing-accent-blue); }

.hm__menu summary span {
	display: block;
	width: 18px;
	height: 2px;
	background: var(--marketing-text);
}

.hm__menu-panel {
	position: absolute;
	z-index: 5;
	right: 0;
	top: calc(100% + var(--space-3));
	width: max-content;
	min-width: 180px;
	display: flex;
	flex-direction: column;
	padding: 0 var(--space-7);
	border: 1px solid var(--neutral-800);
	border-radius: var(--radius-lg);
	background: var(--marketing-surface);
	box-shadow: var(--elevation-3);
}

.hm__menu-panel a {
	padding: var(--space-6) 0;
	font-size: var(--text-xl);
	color: var(--marketing-text);
	text-decoration: none;
	border-bottom: 1px solid var(--neutral-800);
}

.hm__menu-panel a:last-child { border-bottom: 0; }
.hm__menu-panel a:hover { color: var(--marketing-accent-blue); }

/* =====================================================================
   BREAKPOINTS

   1100 is where the hero photography swaps art direction, matching the
   breakpoint preview-home.html already uses so the two pages do not
   disagree about where a landscape crop becomes a portrait one.
   ===================================================================== */

/* =====================================================================
   WHY THIS BLOCK IS DOWN HERE AND NOT WITH THE OTHER 1399 RULES

   There is already an @media (max-width: 1399px) higher up, next to the
   checkerboard. These rules cannot live in it, and the reason is ordering
   rather than taste: that block sits ABOVE the .hm__cta base rule, and two
   rules of equal specificity are settled by which comes last. Putting the
   stacking there meant the base rule won and the panel never stacked at
   all, at any width. Measured before this was moved: grid-template-columns
   read "0px 380px" at 375, so the copy column had collapsed to nothing and
   the text was rendering one word per line behind the phone.

   Nothing warns about this. The rule is valid, the media query matches, and
   the declaration is simply overridden afterwards.
   ===================================================================== */
@media (max-width: 1399px) {
	/* The CTA panel stacks. A fixed 380px art column beside 1fr has the same
	   failure as the explainer's 600px one: it does not degrade, it eats the
	   text. The phone moves below the copy and stays cropped. */
	.hm__cta {
		grid-template-columns: minmax(0, 1fr);
		gap: 0;
		padding: 0 var(--space-13);
	}
	.hm__cta-copy { padding: var(--space-15) 0 var(--space-11); max-width: none; }
	.hm__cta-art { height: 380px; margin-top: 0; }

	/* PLAYFUL HERO: the art column narrows before it stacks. A fixed 560px
	   beside 1fr has the same failure as every other fixed column on this
	   page, so it gives ground first rather than eating the copy. */
	.hm__phero-grid { grid-template-columns: minmax(0, 1fr) 420px; }
	.hm__phero h1 { font-size: 52px; }
	.hm__phero-art { height: 480px; }
	.hm__figure img { width: 232px; height: 452px; }
	.hm__float--job { left: -12px; top: 80px; width: 216px; }
	.hm__float--cta { right: -8px; bottom: 120px; }

	.hm__footer-top { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-11); }
	.hm__footer-brand { grid-column: 1 / -1; }
}

@media (max-width: 1099px) {
	.hm__nav-links { display: none; }
	.hm__menu { display: block; }
	.hm__nav-left, .hm__nav-right { gap: var(--space-4); }

	.hm__hero { min-height: 820px; }
	.hm__hero h1 { font-size: 44px; }
	.hm__hero-list li { grid-template-columns: 20px 1fr; font-size: var(--text-2xl); }
	.hm__hero-list li > .hm__icon { width: 20px; height: 20px; margin-top: 1px; }

	/* Portrait crop, so the subject sits low and the copy sits over the
	   top two thirds. */
	.hm__frame img { object-position: 50% 100%; }

	/* One gradient down the page rather than one across it: at this width
	   there is no empty right-hand side for the copy to avoid. */
	.hm__scrim--across {
		background: linear-gradient(180deg,
			rgba(var(--hm-scrim-rgb), 0.72) 0%,
			rgba(var(--hm-scrim-rgb), 0.60) 72%,
			rgba(var(--hm-scrim-rgb), 0.24) 86%,
			rgba(var(--hm-scrim-rgb), 0) 100%);
	}

	.hm__section { padding: var(--space-15) var(--space-12); }
	.hm__section h1, .hm__section h2 { font-size: 40px; }
	.hm__plainbar { padding: 0 var(--space-12); }

	/* THE COLUMN COUNT IS DRIVEN BY THE LONGEST WORD, NOT BY TASTE.
	   "Software Development" sets 174px wide at --text-4xl, and the name is
	   capped at 54% of the card so it stays clear of the artwork. A long
	   word has no break opportunity, so below a certain card width it
	   OVERFLOWS that cap and runs under the 3D object instead of wrapping.

	   Measured rather than guessed: at 1440 no card collides; at 1280 one
	   does, by 23px; at 1100 six of eight do, by up to 48px. That put
	   "Translation" at 1.50:1 against the pen artwork where it needs 3.0.
	   The same 1100 to 1285 band is already on record in the design handoff
	   pack as clipping the job cards, for the same reason: four columns is
	   simply too many there.

	   Four columns needs a 322px card to hold that word, so it is confined
	   to 1400px and up. This band gets three, and the name drops one step of
	   the type scale, which takes the longest word to 160px against 176px of
	   room at the narrowest point. */
	/* Two columns. The type and zone widths set in the 1399 band above
	   still apply and are still correct here: the cards get WIDER as the
	   column count drops, so the longest word has more room, not less. */
	.hm__cats { grid-template-columns: repeat(2, minmax(0, 1fr)); }

	/* The playful header's nav collapses into the menu, exactly as the light
	   hero's does. Without this the full nav stays laid out and pushes the
	   bar past the viewport: measured 263px of horizontal overflow at 375,
	   all of it the header rather than the hero. */
	.hm__bar-nav { display: none; }
	.hm__bar-left, .hm__bar-right { gap: var(--space-4); }

	/* PLAYFUL HERO STACKS. Below this the copy needs the full width for the
	   search bar, which is the one element here that cannot shrink
	   gracefully: two labelled fields and a button do not fit beside a
	   figure. The art moves under the copy and keeps the figure and both
	   cards, which is what the design's own mobile frame does. */
	.hm__phero-grid {
		grid-template-columns: minmax(0, 1fr);
		gap: 0;
		padding: var(--space-11) var(--space-12) 0;
	}
	.hm__phero-copy { padding-bottom: var(--space-11); }
	.hm__phero h1 { font-size: 44px; }
	.hm__phero-art { height: 420px; }
	.hm__figure img { width: 200px; height: 390px; }

	/* Inside the panel now, not hanging off its edge: at this width there is
	   no gutter for a negative offset to sit in and it would overflow. */
	.hm__float--job { left: 0; top: 40px; }
	.hm__float--cta { right: 0; bottom: 90px; }
	.hm__jobs { grid-template-columns: repeat(2, minmax(0, 1fr)); }

}

@media (max-width: 767px) {
	.hm__hero-pad { padding: var(--space-3) var(--space-3) var(--space-15); }
	.hm__nav { height: var(--header-height-mobile); padding: 0 var(--space-5); }
	.hm__logo img { width: 67px; height: 40px; }
	.hm__login { display: none; }

	.hm__hero-copy { padding: var(--space-8) var(--space-7) var(--space-11); }
	.hm__hero h1 { font-size: 36px; }   /* display carve-out */
	.hm__hero-list { margin-top: var(--space-9); }
	.hm__hero-list li {
		grid-template-columns: 18px 1fr;
		gap: var(--space-4);
		font-size: var(--text-xl);
	}
	.hm__hero-list li > .hm__icon { width: 18px; height: 18px; margin-top: 1px; }

	/* The two hero buttons go full width and stack. Side by side at this
	   width they are 150px each, which is under the comfortable tap target
	   for a primary action and leaves both labels one word from wrapping. */
	.hm__hero-actions { flex-direction: column; align-items: stretch; width: 100%; }
	.hm__hero-actions .hm__btn { width: 100%; }

	/* The search bar stacks. The divider moves from the left edge of the
	   second field to its top edge, or it would draw a vertical line across
	   a horizontal layout. */
	.hm__search { flex-direction: column; padding: var(--space-3); }
	.hm__search-field + .hm__search-field {
		border-left: 0;
		border-top: 1px solid var(--color-border-subtle);
	}
	.hm__search-submit {
		height: 52px;
		margin-left: 0;
		margin-top: var(--space-3);
	}

	.hm__section { padding: var(--space-15) var(--space-6); }
	.hm__section h1, .hm__section h2 { font-size: 32px; }
	.hm__section-head { flex-direction: column; align-items: flex-start; gap: var(--space-9); }
	.hm__plainbar { padding: 0 var(--space-6); }

	/* One column. The alternation rule for odd column counts already
	   applies; only the layout changes here. */
	.hm__cats { grid-template-columns: minmax(0, 1fr); gap: var(--space-5); }
	.hm__jobs { grid-template-columns: minmax(0, 1fr); }

	.hm__cat { min-height: 148px; padding: var(--space-8); }

	.hm__feature-lead { font-size: var(--text-lg); }
	.hm__escrow { padding: var(--space-8); }
	.hm__escrow h3 { font-size: var(--text-3xl); }
	.hm__escrow p { font-size: var(--text-md); }
	.hm__points { grid-template-columns: minmax(0, 1fr); gap: var(--space-10); }
	.hm__feature-art { max-width: none; }

	/* PLAYFUL HERO at phone widths. The search bar stacks: a 60px field, a
	   second 60px field and a button will not sit on one line at 375, and
	   squeezing them produced a 14px-wide input and 338px of horizontal
	   overflow before this existed. */
	.hm__phero-grid { padding: var(--space-8) var(--space-6) 0; }
	.hm__phero h1 { font-size: 36px; }
	.hm__phero-lead { font-size: var(--text-lg); }
	.hm__phero-glow { display: none; }

	.hm__psearch {
		flex-direction: column;
		align-items: stretch;
		max-width: none;
		gap: 0;
	}
	.hm__psearch-field { height: 56px; }
	.hm__psearch-field:first-of-type { flex: 1 1 auto; }
	/* The divider runs across, not down, once the fields are stacked. */
	.hm__psearch-sep { width: auto; height: 1px; align-self: stretch; margin: 0 var(--space-7); }
	.hm__psearch-submit { width: 100%; margin-top: var(--space-3); }

	.hm__phero-points { gap: var(--space-4); flex-direction: column; }
	.hm__phero-art { height: 360px; }
	.hm__figure img { width: 174px; height: 340px; }
	.hm__float { padding: var(--space-5); }
	.hm__float--job { left: 0; top: 20px; width: 200px; }
	.hm__float--cta { right: 0; bottom: 60px; width: 172px; }

	.hm__bar { padding: 0 var(--space-6); }
	.hm__bar-login { display: none; }

	.hm__cta { padding: 0 var(--space-8); }
	.hm__cta-copy h2 { font-size: 32px; }   /* --text-6xl, back on the scale */
	.hm__cta-copy p { font-size: var(--text-lg); }
	.hm__cta-actions .hm__btn { width: 100%; }
	.hm__cta-art { height: 320px; }

	.hm__footer { padding: var(--space-15) var(--space-6) var(--space-11); }
	.hm__footer-top { grid-template-columns: minmax(0, 1fr); gap: var(--space-11); }
	.hm__footer-legal { flex-direction: column; align-items: flex-start; }
}

/* The design output carried a reduced-motion block and this page did not
   port it on the first pass. Both hero buttons lift on hover and the search
   bar fades its shadow, so there was real motion running for someone who
   had asked for none. The reveal is handled separately in reveal.css. */
@media (prefers-reduced-motion: reduce) {
	.hm__btn:hover { transform: none; }
	.hm__search { transition: none; }
}

@media (max-width: 479px) {
	.hm__phero h1 { font-size: 32px; }   /* --text-6xl, back on the scale */
	.hm__phero-art { height: 330px; }
	.hm__float--job { width: 176px; }
	.hm__float--cta { width: 156px; bottom: 40px; }

	.hm__hero { min-height: 760px; }
	.hm__hero h1 { font-size: 32px; }   /* --text-6xl, back on the scale */
	.hm__hero-list li { grid-template-columns: 16px 1fr; font-size: var(--text-lg); }
	.hm__hero-list li > .hm__icon { width: 16px; height: 16px; }
}
