/* SlyFox Solutions — Design System
   Generated by Frontend Wireframe Engine, Phase 4
   DNA Hash: e1f322961756
   Do not edit by hand. Regenerate via the engine.

   Axes: humanist-warm-readable / editorial-understated / editorial-magazine /
         offset-editorial / underline-reveal / photography-editorial /
         subtle-elegant / airy / off-white-sophisticated / solid-minimal /
         topographic-map / cultural: none
   Mutations: grid-break (spatial), topographic-pattern (textural), accent-font (typographic)
*/

:root {
  /* ── Typography ──────────────────────────────────────────────
     Single family: Raleway, per client direction. The three roles are now
     separated by weight, size, and tracking rather than by typeface.
     One family is comfortably inside the Font Buffet ceiling of three. */
  --font-display: 'Raleway', system-ui, sans-serif;
  --font-body: 'Raleway', system-ui, sans-serif;
  --font-data: 'Raleway', system-ui, sans-serif;

  --scale-ratio: 1.333;
  --display-weight: 800;
  --heading-weight: 700;
  --body-weight: 400;
  --display-tracking: -0.03em;   /* floor is -0.04em; we stay above it */
  --heading-tracking: -0.02em;
  --data-tracking: 0.13em;
  --display-leading: 1.02;
  --heading-leading: 1.15;
  --body-leading: 1.72;
  --body-size: 17.5px;
  --measure: 68ch;
  --measure-tight: 46ch;

  /* Fluid display scale, brand register */
  --step-hero: clamp(2.6rem, 1.15rem + 5.6vw, 5.5rem);
  --step-1: clamp(2rem, 1.15rem + 3.4vw, 3.75rem);
  --step-2: clamp(1.55rem, 1.1rem + 1.8vw, 2.5rem);
  --step-3: clamp(1.25rem, 1.05rem + 0.85vw, 1.65rem);
  --step-4: 1.125rem;

  /* ── Colour ──────────────────────────────────────────────────
     Every ratio below was measured, not estimated.
     The ground is cool, carrying a trace of the fox tail's navy.
     It is deliberately NOT cream: that band is the 2026 AI tell. */
  --paper:        #f6f7f9;   /* base surface */
  --surface:      #eceef3;   /* second surface, alternating bands */
  --navy:         #1e2a5a;   /* fox tail navy, contrast bands */
  --navy-deep:    #151b2e;   /* ink */
  --ink:          #151b2e;   /* 15.95:1 on paper */
  --slate:        #4a5468;   /*  7.10:1 on paper, secondary body */
  --steel:        #3f6e97;   /*  5.04:1 on paper, tertiary and metadata */
  --mist:         #b9c4da;   /*  7.80:1 on navy, body inside dark bands */
  --line:         rgba(21, 27, 46, 0.14);
  --line-strong:  rgba(21, 27, 46, 0.30);
  --line-invert:  rgba(246, 247, 249, 0.22);
  --abyss:        #151b2e;   /* deepest band. fox orange reaches 5.21:1 here */
  --abyss-line:   rgba(246, 247, 249, 0.16);

  /* The single locked accent. Fox orange, straight off the logo. */
  --fox:        #f0601e;   /* 3.06:1 on paper. LARGE type, rules, fills ONLY. */
  --fox-amber:  #f0901a;   /* 5.68:1 on navy. Small accent text on dark only. */
  --rust:       #b8410f;   /* 5.15:1 on paper. Any orange below 24px. */

  /* ── Spacing, from the airy philosophy ─────────────────────── */
  --s-1: 8px;   --s-2: 16px;  --s-3: 24px;  --s-4: 32px;
  --s-5: 48px;  --s-6: 64px;  --s-7: 80px;  --s-8: 96px;  --s-9: 128px;
  --section-gap: 96px;
  --pad-x: 24px;
  --maxw: 1440px;

  /* ── Motion, subtle-elegant over the craft floor ───────────── */
  --ease-out: cubic-bezier(0.23, 1, 0.32, 1);
  --ease-in-out: cubic-bezier(0.77, 0, 0.175, 1);
  --ease-drawer: cubic-bezier(0.32, 0.72, 0, 1);
  --enter-duration: 500ms;
  --stagger: 60ms;
  --control-duration: 160ms;   /* controls stay on the fast floor */
  --hover-duration: 200ms;
}

@media (min-width: 768px)  { :root { --pad-x: 48px; } }
@media (min-width: 1280px) { :root { --pad-x: 80px; --section-gap: 128px; } }

/* ══ Base ══════════════════════════════════════════════════════ */
* { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }

body {
  margin: 0;
  background-color: var(--paper);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: var(--body-size);
  font-weight: var(--body-weight);
  line-height: var(--body-leading);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

h1, h2, h3, h4 {
  font-family: var(--font-display);
  font-weight: var(--heading-weight);
  letter-spacing: var(--heading-tracking);
  line-height: var(--heading-leading);
  margin: 0;
  text-wrap: balance;
}

p { margin: 0 0 var(--s-3); max-width: var(--measure); }

a { color: inherit; }

img { max-width: 100%; display: block; }

::selection { background: var(--fox); color: var(--navy-deep); }

:focus-visible {
  outline: 2px solid var(--fox);
  outline-offset: 3px;
}

/* ══ Layout primitives ═════════════════════════════════════════ */
.shell {
  max-width: var(--maxw);
  margin-inline: auto;
  padding-inline: var(--pad-x);
}

/* editorial-magazine: a real 12-column grid so no two sections
   have to share a composition. */
.grid12 {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  gap: var(--s-4);
}

.section { padding-block: var(--section-gap); }
.section--tight { padding-block: var(--s-6); }
.section--surface { background-color: var(--surface); }

/* Inner-page head. Without this, a full section-gap below the headline plus a
   full section-gap above the next block stacks to roughly 256px of dead air. */
.section--pagehead { padding-block: var(--s-7) var(--s-5); }
.section--pagehead + .section,
.section--pagehead + .section--tight { padding-top: var(--s-6); }

/* Contrast bands. Prevent the page reading as one continuous document.
   band-abyss is the deepest: at #151b2e the fox orange reaches 5.21:1 and
   becomes legal for small text, which it is not on the lighter navy. */
.band-navy  { background-color: var(--navy);  color: var(--paper); }
.band-abyss { background-color: var(--abyss); color: var(--paper); }

/* ── Dark surface contract ────────────────────────────────────
   EVERY dark context is listed here, once: .band-navy, .band-abyss,
   .hero--dark, .footer, .mobile-menu. This has now been missed FOUR times,
   each time shipping something broken: steel #3f6e97 measures 2.53:1 on navy,
   and a navy .btn on a navy surface measures 1.00:1 and is invisible.
   Any new dark surface MUST be added to these selectors rather than given its
   own overrides, and must be checked for BOTH text colour and button fill. */
.band-navy h1, .band-navy h2, .band-navy h3, .band-navy h4,
.band-abyss h1, .band-abyss h2, .band-abyss h3, .band-abyss h4,
.hero--dark h1, .hero--dark h2, .hero--dark h3, .hero--dark h4,
.footer h1, .footer h2, .footer h3, .footer h4 { color: var(--paper); }

.band-navy p, .band-abyss p, .hero--dark p, .footer p, .mobile-menu p,
.band-navy .lede, .band-abyss .lede,
.band-navy .muted, .band-abyss .muted, .hero--dark .muted, .footer .muted { color: var(--mist); }

/* The data layer switches to amber on navy (5.68:1) and to full fox orange
   on the deepest band (5.21:1). Steel is a light-ground token only. */
.band-navy .data, .footer .data, .hero--dark .data,
.mobile-menu .data { color: var(--fox-amber); }
.band-abyss .data { color: var(--fox); }

.band-navy .entry, .band-abyss .entry, .hero--dark .entry, .footer .entry { border-bottom-color: var(--line-invert); }

.band-navy .link, .band-abyss .link, .hero--dark .link, .footer .link,
.mobile-menu .link { color: var(--paper); }
.band-navy .link::after, .hero--dark .link::after { background-color: var(--fox-amber); }
.band-abyss .link::after { background-color: var(--fox); }

.band-navy .figure, .band-abyss .figure, .hero--dark .figure { color: var(--paper); }
.band-navy .figure .unit, .hero--dark .figure .unit { color: var(--fox-amber); }
.band-abyss .figure .unit { color: var(--fox); }

.band-navy .btn--ghost, .band-abyss .btn--ghost, .hero--dark .btn--ghost { color: var(--paper); border-color: var(--line-invert); }
.band-navy .exp, .band-abyss .exp, .hero--dark .exp { border-top-color: var(--line-invert); }
.band-navy .exp__sign, .band-abyss .exp__sign, .hero--dark .exp__sign { border-color: var(--line-invert); }
.band-navy .tags li, .band-abyss .tags li, .hero--dark .tags li { color: var(--mist); border-color: var(--line-invert); }

.band-navy .rule, .hero--dark .rule, .footer .rule {
  background-image:
    linear-gradient(to right, var(--fox-amber) 0 68px, transparent 68px),
    linear-gradient(to right, var(--line-invert) 0 1px, transparent 1px);
}
.band-abyss .rule {
  background-image:
    linear-gradient(to right, var(--fox) 0 68px, transparent 68px),
    linear-gradient(to right, var(--abyss-line) 0 1px, transparent 1px);
}

/* On dark, the primary button inverts. A filled navy button on a navy band is
   almost invisible, so it becomes the accent fill with ink text (5.21:1). */
.band-navy .btn:not(.btn--ghost),
.band-abyss .btn:not(.btn--ghost),
.hero--dark .btn:not(.btn--ghost),
.mobile-menu .btn:not(.btn--ghost) {
  background-color: var(--fox);
  border-color: var(--fox);
  color: var(--navy-deep);
}
@media (hover: hover) and (pointer: fine) {
  .band-navy .btn:not(.btn--ghost):hover,
  .band-abyss .btn:not(.btn--ghost):hover,
  .hero--dark .btn:not(.btn--ghost):hover,
  .mobile-menu .btn:not(.btn--ghost):hover {
    background-color: var(--paper);
    border-color: var(--paper);
    color: var(--navy-deep);
  }
}

/* ══ Texture: the fox field ════════════════════════════════════
   Mutation: topographic-pattern, reimagined. The wave contours are gone.
   This is a minimal fox head (two ears tapering to a chin) scattered at
   three scales and slight rotations, so it reads as an ambient fox motif
   rather than as the logo used as wallpaper. Navy on light surfaces, fox
   orange on dark ones. Opacity is kept low enough to be texture, not pattern. */
.foxfield {
  position: relative;
  isolation: isolate;
  /* The motif layer is inset negatively so pointer drift never exposes an
     edge. Without clipping here that bleed becomes real page width: at 1440px
     the -8% inset added exactly 115px of horizontal scroll. */
  overflow: hidden;
}
.foxfield::before {
  content: '';
  position: absolute;
  inset: -8%;
  z-index: -1;
  pointer-events: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='290' height='290' viewBox='0 0 290 290'%3E%3Cg fill='%231e2a5a'%3E%3Cpath d='M 7 4 L 20 24 L 44 24 L 57 4 L 56 31 L 32 54 L 8 31 Z' opacity='.11' transform='translate(22,20)'/%3E%3Cpath d='M 7 4 L 20 24 L 44 24 L 57 4 L 56 31 L 32 54 L 8 31 Z' opacity='.08' transform='translate(196,146) rotate(-9) scale(0.62)'/%3E%3Cpath d='M 7 4 L 20 24 L 44 24 L 57 4 L 56 31 L 32 54 L 8 31 Z' opacity='.095' transform='translate(96,176) rotate(11) scale(0.42)'/%3E%3C/g%3E%3C/svg%3E");
  background-size: 290px 290px;
  will-change: transform;
}
.band-navy.foxfield::before,
.band-abyss.foxfield::before,
.hero--dark.foxfield::before {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='290' height='290' viewBox='0 0 290 290'%3E%3Cg fill='%23f0901a'%3E%3Cpath d='M 7 4 L 20 24 L 44 24 L 57 4 L 56 31 L 32 54 L 8 31 Z' opacity='.075' transform='translate(22,20)'/%3E%3Cpath d='M 7 4 L 20 24 L 44 24 L 57 4 L 56 31 L 32 54 L 8 31 Z' opacity='.05' transform='translate(196,146) rotate(-9) scale(0.62)'/%3E%3Cpath d='M 7 4 L 20 24 L 44 24 L 57 4 L 56 31 L 32 54 L 8 31 Z' opacity='.065' transform='translate(96,176) rotate(11) scale(0.42)'/%3E%3C/g%3E%3C/svg%3E");
}

/* ══ Typography roles ══════════════════════════════════════════ */
.display {
  font-family: var(--font-display);
  font-weight: var(--display-weight);
  font-size: var(--step-hero);
  line-height: var(--display-leading);
  letter-spacing: var(--display-tracking);
}
/* Display at heading scale. Same reason as .figure--word: a Tailwind
   font-size utility cannot beat .display on an equal-specificity tie. */
.display--md { font-size: var(--step-1); }

/* The heading classes carry family, weight, tracking and leading, not just
   size, so they behave identically on a <span> as on an <h2>. Without this
   a .h2 on a span silently inherits body weight from its parent. */
.h1, .h2, .h3 {
  font-family: var(--font-display);
  font-weight: var(--heading-weight);
  letter-spacing: var(--heading-tracking);
  line-height: var(--heading-leading);
}
.h1 { font-size: var(--step-1); }
.h2 { font-size: var(--step-2); }
.h3 { font-size: var(--step-3); }
.h4 { font-size: var(--step-4); font-weight: 600; font-family: var(--font-body); letter-spacing: 0; }

.lede {
  font-size: clamp(1.125rem, 1rem + 0.55vw, 1.375rem);
  line-height: 1.55;
  color: var(--slate);
  max-width: var(--measure);
}
.band-navy .lede { color: var(--mist); }

.muted { color: var(--slate); }
.band-navy .muted { color: var(--mist); }

/* The mono data layer. Mutation: accent-font.
   Reserved for measured facts: figures, clearances, locations, counts.
   Never used for decoration and never dropped inside a heading. */
.data {
  font-family: var(--font-data);
  font-size: 0.8125rem;      /* 13px, above the 12px floor */
  letter-spacing: var(--data-tracking);
  text-transform: uppercase;
  color: var(--steel);
  font-weight: 700;          /* carries the label role now that family cannot */
}
.band-navy .data { color: var(--fox-amber); }

.figure {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: clamp(2.5rem, 1.5rem + 3.6vw, 4.25rem);
  line-height: 1;
  letter-spacing: -0.03em;
  font-variant-numeric: tabular-nums;
  color: var(--ink);
}
.band-navy .figure { color: var(--paper); }
.figure .unit { color: var(--fox); font-size: 0.5em; }
/* Fox orange measures 3.06:1 on paper, which clears AA-large, but only 2.83:1
   on the second surface, which does not. The unit carries meaning (9 versus
   9%), so on the darker light surface it steps down to rust at 4.76:1. Same
   trap as the dark-surface contract: a token that passes on one surface can
   fail on another. */
.section--surface .figure .unit { color: var(--rust); }
.band-navy .figure .unit { color: var(--fox-amber); }

/* A figure whose value is a word rather than a number. Declared here, not as
   a Tailwind arbitrary value: the CDN injects its stylesheet ABOVE this file,
   so on an equal-specificity tie these component rules always win and a
   utility override silently does nothing. */
.figure--word {
  font-size: clamp(1.6rem, 1.1rem + 1.5vw, 2.25rem);
  letter-spacing: -0.02em;
  padding-top: 12px;
}

/* ══ The measured rule ═════════════════════════════════════════
   A chart scale bar. This is the site's sectioning device, used in
   place of the uppercase tracked eyebrow above every section, which
   is the 2023-era AI tell the anti-pattern set calls out. */
.rule {
  display: block;
  width: 100%;
  height: 9px;
  border: 0;
  margin: 0 0 var(--s-4);
  background-image:
    linear-gradient(to right, var(--fox) 0 68px, transparent 68px),
    linear-gradient(to right, var(--line-strong) 0 1px, transparent 1px);
  background-size: 100% 2px, 17px 9px;
  background-position: left top, left top;
  background-repeat: no-repeat, repeat-x;
}
.band-navy .rule {
  background-image:
    linear-gradient(to right, var(--fox-amber) 0 68px, transparent 68px),
    linear-gradient(to right, var(--line-invert) 0 1px, transparent 1px);
}

/* ══ Components: editorial-understated ═════════════════════════
   Zero radius. No shadows. Bottom rule only. Hover is a weight shift,
   which is layout-stable because the weight change is compensated. */
.entry {
  border: 0;
  border-bottom: 1px solid var(--line);
  padding-block: var(--s-4);
  background: transparent;
}
.band-navy .entry { border-bottom-color: var(--line-invert); }

/* ══ Service block ════════════════════════════════════════════
   The repeatable unit behind the extensible services architecture.
   A new service line is one more <article class="svc">. Nothing here
   or in the markup around it has to change to accept it. */
.svc {
  padding-block: var(--s-6);
  border-top: 1px solid var(--line);
}
.svc:first-child { border-top: 0; padding-top: 0; }
.svc--lead { border-top: 2px solid var(--fox); padding-top: var(--s-5); }

/* Capability keywords. Outlined and square, per editorial-understated.
   Deliberately not pills: pill-playful conflicts with this component set. */
.tags {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}
.tags li {
  font-family: var(--font-data);
  font-size: 12.5px;
  letter-spacing: 0.03em;
  color: var(--slate);
  border: 1px solid var(--line-strong);
  border-radius: 0;
  padding: 7px 11px;
  white-space: nowrap;
}
.band-navy .tags li { color: var(--mist); border-color: var(--line-invert); }

/* ══ Buttons: three tiers, each internally consistent ══════════ */
/* Tier 1, primary. The single documented deviation from the
   underline-reveal archetype: a recruiting-first site whose only
   conversion action is a ghost link would fail the brief. */
.btn {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-family: var(--font-body);
  font-size: 15px;
  font-weight: 600;
  letter-spacing: 0.02em;
  padding: 15px 28px;
  border-radius: 0;
  border: 1px solid var(--navy);
  background-color: var(--navy);
  color: var(--paper);            /* 12.77:1 */
  text-decoration: none;
  cursor: pointer;
  transition: background-color var(--control-duration) var(--ease-out),
              border-color var(--control-duration) var(--ease-out),
              color var(--control-duration) var(--ease-out),
              transform var(--control-duration) var(--ease-out);
}
.btn .arrow { transition: transform var(--control-duration) var(--ease-out); }
.btn:active { transform: scale(0.97); }

@media (hover: hover) and (pointer: fine) {
  .btn:hover {
    background-color: var(--fox);
    border-color: var(--fox);
    color: var(--navy-deep);       /* 5.21:1. Ink on orange, never white. */
  }
  .btn:hover .arrow { transform: translateX(5px); }
}

/* Tier 2, secondary. Outlined, same geometry as tier 1. */
.btn--ghost {
  background-color: transparent;
  color: var(--navy);
  border-color: var(--line-strong);
}
.band-navy .btn--ghost { color: var(--paper); border-color: var(--line-invert); }
@media (hover: hover) and (pointer: fine) {
  .btn--ghost:hover {
    background-color: transparent;
    border-color: var(--fox);
    color: var(--rust);
  }
  .band-navy .btn--ghost:hover { color: var(--fox-amber); }
}

/* Tier 3, tertiary. The underline-reveal archetype proper. */
.link {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  position: relative;
  font-weight: 500;
  font-size: 16px;
  letter-spacing: 0.01em;
  padding: 8px 0;
  text-decoration: none;
  color: var(--ink);
}
.link::after {
  content: '';
  position: absolute;
  left: 0;
  bottom: 2px;
  height: 2px;
  width: 100%;
  background-color: var(--fox);
  /* The underline-reveal archetype describes this as width 0 to 100%, but
     animating width forces layout on every frame. scaleX from a left origin
     is visually identical and stays on the compositor. */
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform 300ms var(--ease-out);
}
.link .arrow { transition: transform var(--control-duration) var(--ease-out); }
.link:active { transform: scale(0.97); }
.band-navy .link { color: var(--paper); }
.band-navy .link::after { background-color: var(--fox-amber); }
@media (hover: hover) and (pointer: fine) {
  .link:hover::after { transform: scaleX(1); }
  .link:hover .arrow { transform: translateX(5px); }
}
.link:focus-visible::after { transform: scaleX(1); }

/* ══ Navigation: solid-minimal ═════════════════════════════════ */
.nav {
  position: sticky;
  top: 0;
  z-index: 50;
  background-color: var(--paper);
  border-bottom: 1px solid var(--line);
}
.nav__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-4);
  min-height: 76px;
}
/* The logo is a light-on-dark lockup: its wordmark is #CCCCCC, which is
   effectively invisible on the paper ground. The brand lock forbids altering
   the mark, so it gets the dark ground it was drawn for instead. The plate
   also echoes the navy bands, so it reads as deliberate rather than patched. */
.nav__logo {
  display: inline-flex;
  align-items: center;
  background-color: var(--navy);
  padding: 11px 18px;
  flex: none;
}
.nav__logo img { height: 30px; width: auto; }
.nav__links { display: none; gap: var(--s-4); align-items: center; }
@media (min-width: 1024px) { .nav__links { display: flex; } }

.nav__link {
  font-size: 15px;
  font-weight: 500;
  letter-spacing: 0.01em;
  text-decoration: none;
  color: var(--slate);
  padding: 6px 0;
  position: relative;
  transition: color var(--control-duration) var(--ease-out);
}
.nav__link::after {
  content: '';
  position: absolute;
  left: 0; bottom: 0;
  height: 2px; width: 100%;
  background-color: var(--fox);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform 240ms var(--ease-out);
}
@media (hover: hover) and (pointer: fine) {
  .nav__link:hover { color: var(--ink); }
  .nav__link:hover::after { transform: scaleX(1); }
}
.nav__link[aria-current] { color: var(--ink); font-weight: 600; }
.nav__link[aria-current]::after { transform: scaleX(1); }

.nav__toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px; height: 44px;
  background: transparent;
  border: 1px solid var(--line-strong);
  color: var(--ink);
  cursor: pointer;
  transition: border-color var(--control-duration) var(--ease-out),
              transform var(--control-duration) var(--ease-out);
}
.nav__toggle:active { transform: scale(0.97); }
@media (min-width: 1024px) { .nav__toggle { display: none; } }

/* Mobile menu: full-viewport overlay, explicit close button. */
.mobile-menu {
  position: fixed;
  top: 0;
  left: 0;
  width: 100vw;
  height: 100vh;
  height: 100dvh;
  z-index: 100;
  display: none;
  flex-direction: column;
  overflow-y: auto;
  background-color: var(--navy);
  color: var(--paper);
  padding: 24px;
  padding-top: max(24px, env(safe-area-inset-top));
  padding-bottom: max(24px, env(safe-area-inset-bottom));
}
.mobile-menu.is-open { display: flex; }
.mobile-menu__close {
  position: absolute;
  top: 16px; right: 16px;
  width: 44px; height: 44px;
  display: inline-flex; align-items: center; justify-content: center;
  background: transparent;
  border: 1px solid var(--line-invert);
  color: var(--paper);
  cursor: pointer;
  transition: border-color var(--control-duration) var(--ease-out),
              transform var(--control-duration) var(--ease-out);
}
.mobile-menu__close:active { transform: scale(0.97); }
.mobile-menu__list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--s-1);
  margin-top: 88px;
}
.mobile-menu__link[aria-current] {
  color: var(--fox-amber);              /* 5.68:1 on the navy menu */
  border-bottom-color: var(--fox);
}
.mobile-menu__link {
  display: block;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(1.75rem, 1.2rem + 3vw, 2.5rem);
  letter-spacing: var(--heading-tracking);
  text-decoration: none;
  color: var(--paper);
  padding: 12px 0;
  border-bottom: 1px solid var(--line-invert);
}

/* ══ Hero: offset-editorial + grid-break ═══════════════════════ */
.hero { position: relative; padding-top: var(--s-7); padding-bottom: var(--s-8); }
@media (min-width: 1024px) { .hero { padding-top: var(--s-8); } }  /* stays under the pt-24 cap */

.hero__media {
  position: relative;
  background-color: var(--surface);
  border: 1px solid var(--line);
  aspect-ratio: 4 / 5;
  max-height: 520px;
  overflow: hidden;
}
.hero__media img { width: 100%; height: 100%; object-fit: cover; }

/* grid-break: on desktop the portrait escapes the container to the
   viewport edge while the headline column stays held. Height is capped
   rather than left to the aspect ratio, which at a 7-column span would
   drive the hero past 1200px and push everything below the fold. */
@media (min-width: 1024px) {
  .hero__media {
    margin-right: calc(-1 * var(--pad-x));
    aspect-ratio: auto;
    height: min(74vh, 640px);
    max-height: none;
  }
}
@media (min-width: 1440px) {
  .hero__media { margin-right: calc((100vw - var(--maxw)) / -2 - var(--pad-x)); }
}

/* ══ Photography placeholders ══════════════════════════════════
   Marked, not fabricated. Each carries a shot brief. */
.shot {
  position: relative;
  background-color: var(--surface);
  border: 1px solid var(--line);
  display: flex;
  align-items: flex-end;
  overflow: hidden;
}
.shot::before {
  content: '';
  position: absolute;
  inset: 0;
  background-image:
    linear-gradient(135deg, transparent 0 49.6%, var(--line) 49.6% 50.4%, transparent 50.4%),
    linear-gradient(45deg, transparent 0 49.6%, var(--line) 49.6% 50.4%, transparent 50.4%);
  opacity: 0.5;
}
.shot__brief {
  position: relative;
  padding: var(--s-3);
  font-family: var(--font-data);
  font-size: 12px;
  line-height: 1.5;
  letter-spacing: 0.04em;
  color: var(--slate);
  background-color: color-mix(in srgb, var(--paper) 92%, transparent);
  border-top: 1px solid var(--line);
  width: 100%;
}
.shot__brief b { color: var(--rust); font-weight: 500; text-transform: uppercase; }

/* ══ Entrances: fade-only, per subtle-elegant ══════════════════
   The signature moment. Section text cross-fades in gently enough
   that the reader notices the content, never the animation. */
[data-animate] {
  opacity: 0;
  transition: opacity var(--enter-duration) var(--ease-in-out);
}
[data-animate].is-in { opacity: 1; }
[data-animate-group] > * { transition-delay: calc(var(--i, 0) * var(--stagger)); }

/* The set-piece: the fox tail curve draws itself once, on load.
   Derived from the existing mark's tail. The logo itself is untouched. */
.tail-draw path {
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
  pathLength: 1;
  animation: tail-draw 1600ms var(--ease-out) 260ms forwards;
}
@keyframes tail-draw { to { stroke-dashoffset: 0; } }


/* ══ Scroll progress ══════════════════════════════════════════
   A chart scale that fills as you read. scaleX only, so it never
   touches layout. */
.progress {
  position: fixed;
  top: 0; left: 0;
  width: 100%;
  height: 3px;
  z-index: 60;
  background: transparent;
  pointer-events: none;
}
.progress__bar {
  height: 100%;
  background: var(--fox);
  transform: scaleX(0);
  transform-origin: left center;
  will-change: transform;
}

/* ══ Pointer-reactive fox field ═══════════════════════════════
   The motif layer drifts a few pixels against the pointer. Transform
   only, gated to fine pointers, and disabled under reduced motion. */
@media (hover: hover) and (pointer: fine) {
  .foxfield--live::before {
    transition: transform 600ms var(--ease-out);
    transform: translate3d(var(--px, 0px), var(--py, 0px), 0);
  }
}

/* ══ Hero, dark ═══════════════════════════════════════════════ */
.hero--dark {
  background-color: var(--abyss);
  color: var(--paper);
}
.hero--dark .display,
.hero--dark h1 { color: var(--paper); }

/* The boat photograph, framed as a porthole. It is the real SlyFox,
   the thirty foot sailboat the company is named after. */
.porthole {
  position: relative;
  /* Leave room for the ring, which sits 26px outside the circle. At 375px a
     full-width porthole pushed the ring past the viewport edge. */
  width: min(calc(100% - 64px), 440px);
  margin-inline: auto;
  aspect-ratio: 1;
  isolation: isolate;
}
/* The image is clipped, not the container. Clipping the container would eat
   the ring, which sits outside the circle on purpose. */
.porthole img {
  width: 100%; height: 100%;
  object-fit: cover;
  border-radius: 50%;
  transform: scale(1.02);
  transition: transform 700ms var(--ease-out);
}
@media (hover: hover) and (pointer: fine) {
  .porthole:hover img { transform: scale(1.06); }
}
.porthole::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: 50%;
  border: 1px solid var(--line-invert);
  pointer-events: none;
}
.porthole__ring {
  position: absolute;
  inset: -26px;
  border-radius: 50%;
  border: 1px dashed rgba(240, 144, 26, 0.5);
  pointer-events: none;
}
.porthole__ring::after {
  content: '';
  position: absolute;
  inset: 14px;
  border-radius: 50%;
  border: 1px solid rgba(246, 247, 249, 0.16);
}


/* ══ Hero background video ════════════════════════════════════
   The scrim below is not a taste decision. Sampling all 25 seconds of the
   source found pure-white pixels (relative luminance 1.0) in the node
   highlights, so unscrimmed hero text would sit at roughly 1:1 in places.
   Minimum alpha of #151b2e over a pure-white pixel to reach 4.5:1:
     paper #f6f7f9 -> 0.620    mist #b9c4da -> 0.765
     amber #f0901a -> 0.855    fox  #f0601e -> 0.950
   The scrim is a flat 0.66 at every breakpoint so the video reads as one
   background across the whole hero. Every string over it is paper (floor
   0.620) or sits on .cap-chip, which composites its own backing on top. Fox
   orange is never used as text over video because its floor is 0.950.
   Because of that 0.95 figure, fox orange is never used as text over video. */
.hero__video {
  position: absolute;
  inset: 0;
  z-index: -2;                 /* under the fox field, over the section fill */
  overflow: hidden;
  pointer-events: none;
}
.hero__video video,
.hero__video img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.hero__video::after {
  content: '';
  position: absolute;
  inset: 0;
  /* Uniform, so the video reads as a background for the whole hero rather
     than an accent on one side. Flat 0.66 puts about a third of the video
     through everywhere. This is only affordable because the hero lede runs
     on paper rather than mist: paper's floor over a pure-white video pixel
     is 0.620, mist's is 0.765, and a mist lede would have forced 0.80 across
     the full width and shown barely a fifth. Same value at every breakpoint,
     which also removes the stacked-versus-two-column hazard entirely. */
  background: rgba(21, 27, 46, 0.66);
}
/* A vignette so the video never fights the nav or the section edge. */
.hero__video::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 1;
  background:
    linear-gradient(to bottom, rgba(21,27,46,0.45) 0%, rgba(21,27,46,0) 14%),
    linear-gradient(to top, rgba(21,27,46,0.70) 0%, rgba(21,27,46,0) 20%);
}

/* Captions sitting over the video use paper, not the amber data colour.
   Amber needs a 0.855 scrim to clear AA over a white pixel and the right
   edge of the gradient is 0.74; paper only needs 0.62. */
.hero--dark .data--onmedia,
.band-navy .data--onmedia,
.band-abyss .data--onmedia { color: var(--paper); }

/* The hero lede runs on paper, not the mist used on other dark bands. Over
   video, mist needs an 0.765 scrim and paper needs 0.620, and that difference
   is the entire budget for a full-bleed uniform background. Declared after the
   dark-surface contract so it wins on source order at equal specificity. */
.hero--dark .lede { color: var(--paper); }

/* A caption sitting over raw video carries its own backing rather than forcing
   the whole scrim up to protect it. Freeing the right side this way is what
   lets the gradient fall to 0.30 there instead of stopping at paper's 0.62
   floor. Reads as an instrument label, which suits the chart language. */
.cap-chip {
  display: inline-block;
  background-color: rgba(21, 27, 46, 0.82);
  border: 1px solid rgba(246, 247, 249, 0.16);
  padding: 8px 15px;
}
@supports (backdrop-filter: blur(4px)) {
  .cap-chip { background-color: rgba(21, 27, 46, 0.68); backdrop-filter: blur(5px); }
}

/* ══ Expandable competency ════════════════════════════════════
   The panel is toggled, not animated open: only opacity and a small
   translate are transitioned, so no layout property is ever tweened. */
.exp { border-top: 1px solid var(--line); }
.band-abyss .exp, .band-navy .exp { border-top-color: var(--abyss-line); }
.exp:first-of-type { border-top: 2px solid var(--fox); }

.exp__head {
  width: 100%;
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  gap: var(--s-3);
  text-align: left;
  background: transparent;
  border: 0;
  border-radius: 0;
  padding: var(--s-4) 0;
  cursor: pointer;
  color: inherit;
  font-family: inherit;
  transition: opacity var(--hover-duration) var(--ease-out);
}
.exp__head .h2 { font-weight: 600; }
.exp__head:active { transform: scale(0.995); }
@media (hover: hover) and (pointer: fine) {
  .exp__head:hover { opacity: 0.72; }
}

.exp__sign {
  position: relative;
  width: 34px; height: 34px;
  flex: none;
  border: 1px solid var(--line-strong);
}
.band-abyss .exp__sign, .band-navy .exp__sign { border-color: var(--line-invert); }
.exp__sign::before, .exp__sign::after {
  content: '';
  position: absolute;
  top: 50%; left: 50%;
  width: 13px; height: 1.5px;
  background: var(--fox);
  transform: translate(-50%, -50%);
  transition: transform 260ms var(--ease-out), opacity 260ms var(--ease-out);
}
.exp__sign::after { transform: translate(-50%, -50%) rotate(90deg); }
.exp[open] .exp__sign::after,
.exp__head[aria-expanded="true"] .exp__sign::after { transform: translate(-50%, -50%) rotate(0deg); opacity: 0; }

.exp__panel { display: none; padding-bottom: var(--s-5); }
.exp__panel.is-open { display: block; }
.exp__panel.is-open > * {
  animation: exp-in 380ms var(--ease-out) both;
}
@keyframes exp-in {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* ══ Testimonials ═════════════════════════════════════════════ */
.quote { border-top: 1px solid var(--abyss-line); padding-top: var(--s-4); }
.quote__mark {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 3rem;
  line-height: 0.7;
  color: var(--fox);
  display: block;
  margin-bottom: 10px;
}
.quote__text {
  font-size: 1.0625rem;
  line-height: 1.62;
  font-style: italic;
  color: var(--mist);
  max-width: 46ch;
}
.quote__who {
  display: flex;
  align-items: center;
  gap: 14px;
  font-weight: 700;
  font-size: 0.875rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--fox);
  margin-top: var(--s-3);
}


/* ══ Quote avatar ═════════════════════════════════════════════
   SlyFox has no photographs of the people who gave these testimonials. The
   five testimonial assets on the live site are quote text rendered as images,
   not portraits. Rather than fake a face or leave the attribution bare, each
   quote gets a real portrait slot carrying a monogram, framed with the same
   ring language as the boat porthole.

   TO DROP IN A REAL PHOTO: replace the monogram text node with
   <img src="assets/img/slyfoxian-adam.webp" alt="Adam, Solutions Architect">
   and nothing else has to change. The img rule below is already here. */
.avatar {
  position: relative;
  flex: none;
  width: 54px;
  height: 54px;
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 19px;
  letter-spacing: 0;
  color: var(--paper);                       /* 15.95:1 on the abyss band */
  background-color: rgba(246, 247, 249, 0.09);
  border: 1px solid rgba(246, 247, 249, 0.20);
  overflow: hidden;
}
.avatar img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: 50%;
}
/* The tail arc, echoing the porthole ring. Drawn outside the circle so it
   survives a photo being dropped in. */
.avatar::after {
  content: '';
  position: absolute;
  inset: -5px;
  border-radius: 50%;
  border: 1px solid transparent;
  border-top-color: var(--fox);
  border-right-color: var(--fox-amber);
  transform: rotate(-32deg);
}

/* ══ Real photography ═════════════════════════════════════════ */
.portrait {
  position: relative;
  overflow: hidden;
  background-color: var(--surface);
  border: 1px solid var(--line);
  /* All five real portraits are 538x675. Using their true 4:5 ratio keeps
     heads framed instead of cropping them to a landscape box. */
  aspect-ratio: 4 / 5;
}
.portrait img {
  width: 100%; height: 100%;
  object-fit: cover;
  transition: transform 600ms var(--ease-out), filter 400ms var(--ease-out);
}
@media (hover: hover) and (pointer: fine) {
  .portrait:hover img { transform: scale(1.045); }
}

/* Charity logos. Real marks, normalised to one optical weight. */
.charities {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s-4) var(--s-5);
}
.charities img {
  height: 44px;
  width: auto;
  opacity: 0.9;
  transition: opacity var(--hover-duration) var(--ease-out);
}
@media (hover: hover) and (pointer: fine) {
  .charities a:hover img, .charities img:hover { opacity: 1; }
}

/* ══ Forms ════════════════════════════════════════════════════ */
.field { display: block; margin-bottom: var(--s-4); }
.field__label {
  display: block;
  font-family: var(--font-data);
  font-size: 12px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--steel);
  margin-bottom: 8px;
}
.field__input,
.field__select,
.field__textarea {
  width: 100%;
  font-family: var(--font-body);
  font-size: 16px;
  color: var(--ink);
  background-color: transparent;
  border: 0;
  border-bottom: 1px solid var(--line-strong);
  border-radius: 0;
  padding: 12px 0;
  transition: border-color var(--control-duration) var(--ease-out);
}
.field__textarea { resize: vertical; min-height: 132px; }
.field__input:focus,
.field__select:focus,
.field__textarea:focus {
  outline: none;
  border-bottom: 2px solid var(--fox);
  padding-bottom: 11px;
}

/* ══ Footer ═══════════════════════════════════════════════════ */
.footer { background-color: var(--navy); color: var(--paper); }
.footer a { color: var(--mist); text-decoration: none; }
@media (hover: hover) and (pointer: fine) {
  .footer a:hover { color: var(--fox-amber); }
}

/* ══ Reduced motion ═══════════════════════════════════════════
   Gentler, not zero: opacity and colour survive, movement does not.
   Scroll-driven rules are nulled explicitly, since they are not
   duration-based and a duration reset alone will not stop them. */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto !important; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
  [data-parallax], [class*="parallax"], .zoom-element, .scroll-rotate {
    animation: none !important;
    animation-timeline: none !important;
    transform: none !important;
  }
  [data-animate] { opacity: 1 !important; }
  .tail-draw path { animation: none !important; stroke-dashoffset: 0 !important; }
  .btn:hover .arrow, .link:hover .arrow { transform: none !important; }
  .foxfield--live::before { transform: none !important; transition: none !important; }
  .hero__video video { display: none; }
  .porthole img, .portrait img { transform: none !important; }
  .exp__panel.is-open > * { animation: none !important; opacity: 1 !important; transform: none !important; }
}
