/* ===========================================================================
   XAVO Advisory — redesign preview
   PREVIEW ONLY. This file does not touch the existing project.

   Palette: deep navy ground, warm ivory paper, and the brand gold sampled
   from the XAVO logo as the single accent. Gold is the firm's own asset, so
   the palette is built to serve it rather than compete with it. The paper is
   kept warm rather than cool, which stops the navy reading cold and keeps the
   gold looking like gold.

   Gold exists as two values and they are not interchangeable:
     --accent-bright  #C6A664  dark grounds, rules and CTAs   (6.8:1 on navy)
     --accent         #7A6133  gold text on ivory             (5.5:1 on paper)
   =========================================================================== */

:root {
  /* Palette per the brief. Navy and warm white carry the page; gold is an
     accent and never a surface. */
  --brand: #172b43; /* midnight blue — panel ground */
  --brand-deep: #101c2c; /* deep navy — the deepest ground */
  --brand-soft: #27446a; /* the lit side of a panel */
  --brand-tint: #e7ecf2;

  /* Gold exists as two values and they are NOT interchangeable.
     #B89A62 on warm white measures 2.6:1 and fails WCAG, so gold text on a
     light ground uses the darker value. */
  --accent: #6f5a2f; /* gold ink — text on warm white, 5.9:1 */
  --accent-bright: #b89a62; /* champagne gold — dark grounds, rules, CTAs */
  --accent-warm: #6f5a2f;

  --paper: #f7f6f2; /* warm white */
  --paper-raised: #ffffff; /* pure white */
  --paper-sunk: #eceae4;
  --rule: #dcd9d0;

  --ink: #101c2c;
  /* The brief suggests #667085 for muted slate. Measured on the sunk panel
     (#ECEAE4) that lands at 4.14:1 and fails WCAG AA, so the slate is taken
     two steps darker. It reads the same; it just passes. */
  --ink-soft: #5e6775;

  --on-brand: #f4f2ea;
  --on-brand-soft: rgba(244, 242, 234, 0.74);
  --rule-on-brand: rgba(244, 242, 234, 0.18);

  /* --- Panel system ------------------------------------------------------
     Taken from the Aurex Advisors reference: the page itself is white, and
     each tonal section sits on it as a large rounded panel with a gutter of
     white around it. Their radii are 50px on panels, 20px on cards and a
     100px pill on buttons; those proportions are kept, the colours are not. */
  --page: #ffffff;
  --gutter: clamp(0.5rem, 1.6vw, 1.25rem);
  --radius-panel: clamp(1.5rem, 3.2vw, 2.75rem);
  --radius-card: 1.25rem;
  --radius-pill: 999px;

  /* The fixed header is two stacked rows: a slim contact bar and the main
     navigation. --nav-h is their combined height, because that is what the
     hero and the page heads clear themselves against; change either row and
     the clearance follows on its own. */
  --nav-bar-h: 5rem;
  --topbar-h: 2.5rem;
  --nav-h: calc(var(--nav-bar-h) + var(--topbar-h));
}

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

html {
  scroll-behavior: smooth;
  /* Anchored sections must clear the whole fixed header, contact bar included. */
  scroll-padding-top: calc(var(--nav-h) + 1rem);
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  background: var(--page);
  color: var(--ink);
  font-family: 'IBM Plex Sans', system-ui, -apple-system, 'Segoe UI', sans-serif;
  font-size: 1.0625rem;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

h1,
h2,
h3 {
  font-family: 'Newsreader', Georgia, serif;
  font-weight: 400;
  color: var(--brand);
  line-height: 1.1;
  letter-spacing: -0.015em;
  margin: 0;
  text-wrap: balance;
}

h1 {
  /* Sized so each sentence of the hero headline holds its own line in the
     two-column layout rather than breaking mid-phrase. */
  font-size: clamp(2.1rem, 1.2rem + 2.6vw, 3.1rem);
}
h2 {
  font-size: clamp(2rem, 1.2rem + 2.9vw, 3.25rem);
}
h3 {
  font-size: 1.4rem;
  line-height: 1.22;
}

p {
  margin: 0;
  text-wrap: pretty;
}
img {
  max-width: 100%;
  height: auto;
  display: block;
}
a {
  color: inherit;
}

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: 1px;
}
.on-brand :focus-visible {
  outline-color: var(--accent-bright);
}

::selection {
  background: var(--brand);
  color: var(--on-brand);
}

.wrap {
  width: 100%;
  max-width: 80rem;
  margin-inline: auto;
  padding-inline: 1.25rem;
}
@media (min-width: 640px) {
  .wrap {
    padding-inline: 2.5rem;
  }
}
@media (min-width: 1100px) {
  .wrap {
    padding-inline: 3.5rem;
  }
}

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

.skip {
  position: absolute;
  left: 1rem;
  top: -4rem;
  z-index: 200;
  background: var(--accent-bright);
  color: var(--brand-deep);
  padding: 0.75rem 1.25rem;
  font-weight: 600;
  text-decoration: none;
  transition: top 0.2s;
}
.skip:focus {
  top: 1rem;
}

/* ===========================================================================
   Shared pieces
   =========================================================================== */
.eyebrow {
  font-size: 0.8125rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--accent);
  margin-bottom: 1.25rem;
  display: flex;
  align-items: center;
  gap: 0.75rem;
}
.eyebrow::after {
  content: '';
  flex: 1;
  height: 1px;
  background: var(--rule);
  max-width: 7rem;
}
.on-brand .eyebrow {
  color: var(--accent-bright);
}
.on-brand .eyebrow::after {
  background: var(--rule-on-brand);
}

.lead {
  font-size: 1.1875rem;
  line-height: 1.7;
  color: var(--ink-soft);
}
.on-brand .lead {
  color: var(--on-brand-soft);
}
@media (min-width: 900px) {
  .lead {
    font-size: 1.3125rem;
  }
}

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  padding: 1rem 1.9rem;
  font-size: 0.9875rem;
  font-weight: 600;
  text-decoration: none;
  position: relative;
  overflow: hidden;
  isolation: isolate;
  border: 1px solid transparent;
  border-radius: var(--radius-pill);
  cursor: pointer;
  transition:
    background-color 0.3s ease,
    color 0.3s ease,
    border-color 0.3s ease,
    box-shadow 0.3s ease;
}

/* A light sweep crosses the button on hover — one pass, no loop */
.btn::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  transform: translateX(-101%);
  background: linear-gradient(
    100deg,
    transparent 0%,
    rgba(255, 255, 255, 0.28) 45%,
    transparent 100%
  );
  transition: transform 0.75s cubic-bezier(0.22, 1, 0.36, 1);
}
.btn:hover::after,
.btn:focus-visible::after {
  transform: translateX(101%);
}
.btn-primary {
  background: var(--brand);
  color: var(--on-brand);
  border-color: var(--brand);
}
.btn-primary:hover {
  background: var(--brand-soft);
  border-color: var(--brand-soft);
}
.btn-accent {
  background: var(--accent-bright);
  color: var(--brand-deep);
  border-color: var(--accent-bright);
}
.btn-accent:hover {
  background: var(--on-brand);
  border-color: var(--on-brand);
}
.btn-ghost {
  border-color: var(--rule-on-brand);
  color: var(--on-brand);
}
.btn-ghost:hover {
  border-color: var(--on-brand);
  background: var(--on-brand);
  color: var(--brand);
}
.btn-outline {
  border-color: color-mix(in srgb, var(--brand) 30%, transparent);
  color: var(--brand);
}
.btn-outline:hover {
  background: var(--brand);
  color: var(--on-brand);
  border-color: var(--brand);
}

.section {
  padding-block: clamp(4.5rem, 8vw, 8rem);
}

/* A tonal section becomes a rounded panel inset from the white page. */
.on-brand,
.sunk {
  border-radius: var(--radius-panel);
  margin-inline: var(--gutter);
  overflow: hidden;
  isolation: isolate;
}

/* Consecutive panels of the same tone keep a little air between them */
.on-brand + .on-brand,
.sunk + .sunk,
.on-brand + .sunk,
.sunk + .on-brand {
  margin-top: var(--gutter);
}

.on-brand {
  background: var(--brand);
  color: var(--on-brand);
}
.on-brand h2,
.on-brand h3 {
  color: var(--on-brand);
}
.sunk {
  background: var(--paper-sunk);
}

.head-grid {
  display: grid;
  gap: 2rem;
  align-items: end;
}
@media (min-width: 900px) {
  .head-grid {
    grid-template-columns: 1.15fr 1fr;
    gap: 4rem;
  }
}

/* ===========================================================================
   Navigation
   =========================================================================== */
/* The header sits on the white page above the hero panel, the way the
   reference does, rather than floating over the artwork. */
/* Contact bar. The top row of the fixed header: the two ways to reach the
   firm directly, kept in reach on every page rather than only at the foot of
   the contact section. Navy, so it reads as a band above the white header
   rather than as part of it. */
.topbar {
  background: var(--brand-deep);
  color: color-mix(in srgb, var(--paper) 84%, transparent);
}
.topbar-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
  height: var(--topbar-h);
  font-size: 0.8125rem;
}
.topbar-contact {
  display: flex;
  align-items: center;
  gap: 1.75rem;
  list-style: none;
  margin: 0;
  padding: 0;
}
.topbar-contact a {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  /* WCAG 2.2 target size (minimum) is 24px; the bar is slim by design, so
     the targets are held at the floor rather than the 44px used elsewhere. */
  min-height: 24px;
  color: inherit;
  text-decoration: none;
  transition: color 0.25s ease;
}
.topbar-contact a:hover {
  color: var(--accent-bright);
}
.topbar-contact svg {
  width: 14px;
  height: 14px;
  flex: none;
  opacity: 0.7;
}
.topbar-where {
  margin: 0;
  letter-spacing: 0.03em;
  white-space: nowrap;
}
.topbar-where span {
  opacity: 0.5;
  margin-inline: 0.4rem;
}
/* Narrow screens cannot hold the offices as well, and the phone number is
   the thing most worth keeping there, so the offices step aside. */
@media (max-width: 639px) {
  :root {
    --topbar-h: 2.25rem;
  }
  .topbar-where {
    display: none;
  }
  .topbar-inner {
    font-size: 0.75rem;
  }
  .topbar-contact {
    gap: 1.1rem;
    flex-wrap: nowrap;
  }
}
/* At 320px the number and the address together leave no slack at all, and the
   row starts to buckle. The icons are the first thing that can go: they label
   what the text already says. */
@media (max-width: 359px) {
  .topbar-contact svg {
    display: none;
  }
  .topbar-contact {
    gap: 0.9rem;
  }
}

.nav {
  position: fixed;
  inset-inline: 0;
  top: 0;
  z-index: 100;
  background: var(--page);
  border-bottom: 1px solid transparent;
  transition:
    box-shadow 0.4s ease,
    border-color 0.4s ease;
}
.nav.is-stuck {
  border-bottom-color: var(--rule);
  box-shadow: 0 10px 30px -26px rgba(12, 35, 64, 0.7);
}
.nav-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: var(--nav-bar-h);
  gap: 2rem;
}
.nav-logo img {
  height: 2.1rem;
  width: auto;
}
.nav-links {
  display: none;
  list-style: none;
  margin: 0;
  padding: 0;
  gap: 2.1rem;
}
@media (min-width: 1024px) {
  .nav-links {
    display: flex;
  }
}
.nav-links a {
  text-decoration: none;
  font-size: 0.95rem;
  color: var(--ink-soft);
  padding-block: 0.5rem;
  position: relative;
  transition: color 0.25s ease;
}
.nav-links a:hover,
.nav-links a[aria-current] {
  color: var(--brand);
}
.nav-links a::after {
  content: '';
  position: absolute;
  left: 0;
  bottom: 0.1rem;
  height: 1px;
  width: 0;
  background: var(--accent);
  transition: width 0.35s ease;
}
.nav-links a:hover::after,
.nav-links a[aria-current]::after {
  width: 100%;
}
.nav-cta {
  display: none;
}
@media (min-width: 1024px) {
  .nav-cta {
    display: inline-flex;
    padding: 0.7rem 1.4rem;
    font-size: 0.9rem;
  }
}
.nav-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.75rem;
  height: 2.75rem;
  margin-right: -0.6rem;
  background: none;
  border: 0;
  color: var(--brand);
  cursor: pointer;
}
@media (min-width: 1024px) {
  .nav-toggle {
    display: none;
  }
}
.nav-panel {
  background: var(--page);
  border-top: 1px solid var(--rule);
  /* On a short phone the full menu is taller than the screen left below the
     header, and the body is locked while it is open — so the panel scrolls
     itself rather than stranding the last few links off-screen. */
  max-height: calc(100svh - var(--nav-h));
  overflow-y: auto;
  overscroll-behavior: contain;
}
.nav-panel[hidden] {
  display: none;
}
.nav-panel ul {
  list-style: none;
  margin: 0;
  padding: 0.5rem 0 1.5rem;
}
.nav-panel a {
  display: block;
  padding: 0.95rem 0;
  text-decoration: none;
  color: var(--ink);
  border-bottom: 1px solid var(--rule);
}
.nav-panel li:last-child a {
  border-bottom: 0;
}
.nav-panel .btn {
  width: 100%;
  margin-top: 1rem;
}

/* ===========================================================================
   Hero
   =========================================================================== */
.hero {
  position: relative;
  background: var(--brand-deep);
  color: var(--on-brand);
  /* The fixed header already provides clearance above the panel, so the top
     padding here is only breathing room, not clearance. */
  padding-block: 3.25rem 3rem;
  margin-top: calc(var(--nav-h) + var(--gutter));
  margin-inline: var(--gutter);
  border-radius: var(--radius-panel);
  overflow: hidden;
  isolation: isolate;
}
@media (min-width: 900px) {
  .hero {
    padding-block: 7rem 0;
    min-height: calc(100svh - var(--nav-h) - var(--gutter) * 2);
    display: flex;
    flex-direction: column;
    justify-content: center;
  }
}

/* The contact bar sits above everything, so on a phone it pushes the hero
   down by its own height. The hero gives a little of its top padding back
   to keep the balance it was tuned to. */
@media (max-width: 639px) {
  .hero {
    padding-block: 2.25rem 2.5rem;
  }
}

/* Themed atmosphere: a soft mesh plus a fine measured grid. No image file,
   so it recolours instantly with the theme. */
/* The photograph. Cropped to the upper facade, where the dusk sky meets the
   warm bronze fins — the same navy-and-gold relationship the palette uses.
   It sits under the wash below, so it reads as depth rather than as a picture
   competing with the headline. Swap assets/hero-photo.jpg to change it. */
.hero-photo {
  position: absolute;
  inset: -8% 0 -8%; /* overhang gives the parallax room to move */
  z-index: -3;
  /* WebP where supported (195 KB), JPEG for anything older (367 KB).
     image-set lets the browser pick without a <picture> element. */
  background-image: url('assets/hero-photo.jpg');
  background-image: image-set(
    url('assets/hero-photo.webp') type('image/webp'),
    url('assets/hero-photo.jpg') type('image/jpeg')
  );
  background-size: cover;
  background-position: 62% 18%;
  will-change: transform;
}

/* Phones get a 900px-wide file — 101 KB instead of 195 KB */
@media (max-width: 760px) {
  .hero-photo {
    background-image: url('assets/hero-photo.jpg');
    background-image: image-set(
      url('assets/hero-photo-900.webp') type('image/webp'),
      url('assets/hero-photo.jpg') type('image/jpeg')
    );
    background-position: 68% 12%;
  }
}

/* Golden-hour depth over the photograph. The reference lays a 0.68 dark wash
   over its image; this does the same job with a tinted field — a warm key
   light high right, a cool fill low left — so the navy stays dominant and the
   headline keeps its contrast. */
.hero-bg {
  position: absolute;
  inset: 0;
  z-index: -2;
  background:
    radial-gradient(
      58rem 40rem at 82% 4%,
      color-mix(in srgb, var(--accent-bright) 42%, transparent),
      transparent 58%
    ),
    radial-gradient(
      40rem 30rem at 68% 28%,
      color-mix(in srgb, #e8c88a 18%, transparent),
      transparent 60%
    ),
    radial-gradient(
      52rem 38rem at 8% 96%,
      color-mix(in srgb, var(--brand-soft) 92%, transparent),
      transparent 66%
    ),
    linear-gradient(
      158deg,
      color-mix(in srgb, var(--brand) 86%, transparent) 0%,
      color-mix(in srgb, var(--brand-deep) 93%, transparent) 72%
    );
}

/* Readability scrim.
   A photograph's brightness is not under our control, so text contrast cannot
   rest on the wash alone. This lays near-solid navy under the column the text
   occupies and releases to the right, where the facade is allowed to show.
   Behind the headline the ground is at least 92% brand-deep, which keeps the
   measured contrast the same as it would be on a flat panel. */
.hero::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background:
    linear-gradient(
      100deg,
      color-mix(in srgb, var(--brand-deep) 94%, transparent) 0%,
      color-mix(in srgb, var(--brand-deep) 88%, transparent) 38%,
      color-mix(in srgb, var(--brand-deep) 45%, transparent) 62%,
      transparent 88%
    ),
    radial-gradient(
      110% 80% at 18% 44%,
      color-mix(in srgb, var(--brand-deep) 55%, transparent) 0%,
      transparent 60%
    );
}

/* Below the large breakpoint the text spans the full width, so the scrim does */
@media (max-width: 899px) {
  .hero::after {
    background: linear-gradient(
      170deg,
      color-mix(in srgb, var(--brand-deep) 86%, transparent) 0%,
      color-mix(in srgb, var(--brand-deep) 93%, transparent) 55%,
      color-mix(in srgb, var(--brand-deep) 88%, transparent) 100%
    );
  }
}
.hero-grid {
  position: absolute;
  inset: 0;
  z-index: -1;
  background-image:
    linear-gradient(to right, var(--rule-on-brand) 1px, transparent 1px),
    linear-gradient(to bottom, var(--rule-on-brand) 1px, transparent 1px);
  background-size: 7.5rem 7.5rem;
  mask-image: linear-gradient(115deg, rgba(0, 0, 0, 0.5), transparent 58%);
  -webkit-mask-image: linear-gradient(115deg, rgba(0, 0, 0, 0.5), transparent 58%);
  opacity: 0.8;
}
.hero-arc {
  position: absolute;
  right: -10%;
  bottom: -18%;
  width: 78%;
  max-width: 60rem;
  z-index: -1;
  color: var(--accent-bright);
  opacity: 0.5;
  pointer-events: none;
}

/* The arcs draw themselves once the page settles */
.hero-arc path {
  stroke-dasharray: 1400;
  stroke-dashoffset: 1400;
  animation: arc-draw 2.4s cubic-bezier(0.33, 1, 0.68, 1) 0.75s forwards;
}
.hero-arc path:nth-of-type(2) {
  animation-delay: 0.95s;
}
.hero-arc path:nth-of-type(3) {
  animation-delay: 1.15s;
}
.hero-arc circle {
  opacity: 0;
  animation: dot-in 0.6s ease 2.1s forwards;
}
@keyframes arc-draw {
  to {
    stroke-dashoffset: 0;
  }
}
@keyframes dot-in {
  to {
    opacity: 1;
  }
}

/* The warm key light breathes very slowly, so the hero is never quite static */
.hero-bg {
  animation: field-drift 22s ease-in-out infinite alternate;
}
@keyframes field-drift {
  from {
    transform: scale(1) translate3d(0, 0, 0);
  }
  to {
    transform: scale(1.06) translate3d(-1.2%, 1%, 0);
  }
}

/* --- Two-column hero ----------------------------------------------------
   Asymmetric on purpose: the argument gets the wider column, the graphic the
   narrower one, so the headline always leads. Stacks on tablet and below. */
.hero-split {
  display: grid;
  gap: 2.5rem;
}
@media (min-width: 980px) {
  .hero-split {
    grid-template-columns: 1.15fr 0.85fr;
    gap: 4rem;
    align-items: center;
  }
}

.hero-content {
  max-width: 44rem;
}

.hero-kicker {
  margin-top: 2.25rem;
  padding-top: 1.25rem;
  border-top: 1px solid var(--rule-on-brand);
  font-size: 0.9375rem;
  letter-spacing: 0.01em;
  color: var(--on-brand-soft);
}

/* --- The analytical graphic -------------------------------------------- */
.hero-figure {
  position: relative;
  border-radius: var(--radius-card);
  overflow: hidden;
  aspect-ratio: 4 / 5;
  min-height: 18rem;
  color: var(--accent-bright);
  /* keeps the panel from collapsing before the image decodes */
  background: linear-gradient(165deg, var(--brand-soft), var(--brand-deep));
}
/* Below the two-column breakpoint the figure is dropped entirely. Stacked, it
   pushed the hero to 1035px on a phone — past a full screen — and the hero
   already carries the same photograph as its own background, so the panel was
   repeating itself. The analytical graphic is a desktop-only flourish. */
@media (max-width: 979px) {
  .hero-figure {
    display: none;
  }
}

.hero-figure-photo {
  position: absolute;
  inset: 0;
  background-image: url('assets/hero-photo.jpg');
  background-image: image-set(
    url('assets/hero-photo-900.webp') type('image/webp'),
    url('assets/hero-photo.jpg') type('image/jpeg')
  );
  background-size: cover;
  background-position: 58% 24%;
  filter: grayscale(0.3) brightness(0.72);
  /* refined clip reveal rather than a plain fade */
  clip-path: inset(0 0 100% 0);
  animation: figure-reveal 1.1s cubic-bezier(0.16, 1, 0.3, 1) 0.45s forwards;
}
@keyframes figure-reveal {
  to {
    clip-path: inset(0 0 0 0);
  }
}

.hero-figure::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(
    200deg,
    color-mix(in srgb, var(--brand-deep) 30%, transparent) 0%,
    color-mix(in srgb, var(--brand-deep) 72%, transparent) 100%
  );
}

.hero-net {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: 1;
}

/* The network draws itself, then the points arrive */
.hero-net .net-lines path,
.hero-net .net-trend {
  stroke-dasharray: 900;
  stroke-dashoffset: 900;
  animation: net-draw 1.8s cubic-bezier(0.33, 1, 0.68, 1) forwards;
}
.hero-net .net-trend {
  animation-delay: 1.1s;
  animation-duration: 2.1s;
}
.hero-net .net-lines path:nth-child(1) { animation-delay: 0.75s; }
.hero-net .net-lines path:nth-child(2) { animation-delay: 0.95s; }
.hero-net .net-lines path:nth-child(3) { animation-delay: 1.1s; }
.hero-net .net-lines path:nth-child(4) { animation-delay: 1.25s; }
.hero-net .net-lines path:nth-child(5) { animation-delay: 1.4s; }

.hero-net .net-dots circle,
.hero-net .net-halo {
  opacity: 0;
  animation: net-dot 0.5s ease forwards;
}
.hero-net .net-dots circle:nth-child(1) { animation-delay: 1.0s; }
.hero-net .net-dots circle:nth-child(2) { animation-delay: 1.15s; }
.hero-net .net-dots circle:nth-child(3) { animation-delay: 1.3s; }
.hero-net .net-dots circle:nth-child(4) { animation-delay: 1.45s; }
.hero-net .net-dots circle:nth-child(5) { animation-delay: 1.6s; }
.hero-net .net-dots circle:nth-child(6) { animation-delay: 1.8s; }
.hero-net .net-halo { animation-delay: 2.1s; }

@keyframes net-draw {
  to {
    stroke-dashoffset: 0;
  }
}
@keyframes net-dot {
  to {
    opacity: 1;
  }
}

/* --- Headline: each line rises out of its own mask -----------------------
   The signature moment of the page. One sequence, on load, and nothing else
   on the site animates without the visitor asking for it. */
.reveal-lines .line {
  display: block;
  overflow: hidden;
  /* room for descenders, which a tight mask would otherwise clip */
  padding-bottom: 0.08em;
  margin-bottom: -0.08em;
}
.reveal-lines .line > span {
  display: block;
  animation: line-rise 1s cubic-bezier(0.16, 1, 0.3, 1) backwards;
}
.reveal-lines .line:nth-child(1) > span {
  animation-delay: 0.15s;
}
.reveal-lines .line:nth-child(2) > span {
  animation-delay: 0.29s;
}
@keyframes line-rise {
  from {
    transform: translateY(108%);
  }
  to {
    transform: none;
  }
}
.hero h1 {
  color: var(--on-brand);
}
.hero .lead {
  margin-top: 2rem;
  max-width: 44rem;
}
.hero-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.875rem;
  margin-top: 2.75rem;
}

/* On a phone the two buttons stack, so give them equal full width rather
   than letting the label length decide. */
@media (max-width: 640px) {
  .hero-actions {
    flex-direction: column;
    align-items: stretch;
  }
  .hero-actions .btn {
    width: 100%;
  }
}

/* Touch targets: small inline links are 18-24px tall, below the 44px
   minimum. Give them the height on touch-sized screens without changing how
   they look on a desktop. */
@media (max-width: 899px) {
  .office a,
  .foot-base a,
  .link-ruled {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
  }

  /* Footer column links are things people tap, so they get the full target
     height. List spacing is removed so the column does not double in length.
     Links sitting inline inside a sentence are left alone — WCAG 2.5.8
     exempts those, and stretching them would break the paragraph. */
  .foot-top li a {
    display: flex;
    align-items: center;
    min-height: 44px;
  }
  .foot-top li {
    margin-bottom: 0;
  }
}

/* Practice strip across the foot of the hero.
   Hidden below the large breakpoint: stacked, it added roughly 570px to the
   hero on a phone and simply repeated the three practices that follow
   immediately underneath in full. */
.hero-strip {
  display: none;
  margin-top: 5rem;
  border-top: 1px solid var(--rule-on-brand);
}

@media (min-width: 800px) {
  .hero-strip {
    display: block;
  }
}
.hero-strip ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 1px;
  background: var(--rule-on-brand);
}
@media (min-width: 800px) {
  .hero-strip ul {
    grid-template-columns: repeat(3, 1fr);
  }
}
.hero-strip li {
  background: color-mix(in srgb, var(--brand-deep) 72%, transparent);
  padding: 1.6rem 1.75rem 1.9rem;
}
.hero-strip a {
  text-decoration: none;
  display: block;
}
.hero-strip strong {
  display: block;
  font-family: 'Newsreader', Georgia, serif;
  font-size: 1.2rem;
  font-weight: 400;
  color: var(--on-brand);
  margin-bottom: 0.35rem;
}
.hero-strip span {
  font-size: 0.9rem;
  color: var(--on-brand-soft);
}
.hero-strip li:hover {
  background: color-mix(in srgb, var(--brand-soft) 55%, transparent);
}

/* ===========================================================================
   About
   =========================================================================== */
.about-grid {
  display: grid;
  gap: 3rem;
}
@media (min-width: 1000px) {
  .about-grid {
    grid-template-columns: 1.1fr 0.9fr;
    gap: 5rem;
  }
}
.about-body p + p {
  margin-top: 1.25rem;
}
.about-quote {
  margin: 2.75rem 0 0;
  padding-left: 1.75rem;
  border-left: 2px solid var(--accent);
  font-family: 'Newsreader', Georgia, serif;
  font-size: 1.25rem;
  line-height: 1.55;
  color: var(--brand);
}
.facts {
  border-top: 1px solid var(--rule);
}
.facts div {
  border-bottom: 1px solid var(--rule);
  padding: 1.6rem 0;
}
.facts dt {
  font-family: 'Newsreader', Georgia, serif;
  font-size: 1.2rem;
  color: var(--brand);
}
.facts dd {
  margin: 0.45rem 0 0;
  font-size: 0.975rem;
  color: var(--ink-soft);
}

/* ===========================================================================
   Practice areas
   =========================================================================== */
.practice + .practice {
  border-top: 1px solid var(--rule);
}

/* Hovering a practice row lights its gold rule and lifts the label a touch —
   motion that answers the pointer, not motion for its own sake. */
.practice {
  position: relative;
}

/* --- Per-practice backgrounds -------------------------------------------
   Each row carries a photograph specific to its own subject, rather than one
   image repeated three times. All three are the instruments of accounting
   rather than buildings: quoted prices, a bookkeeping ledger, an adding
   machine. None contains a person, so nothing here implies a client or an
   endorsement. */
.has-tex {
  isolation: isolate;
}
.practice-tex {
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
}

/* Each practice row carries its own photograph on the right-hand side, fading
   out before it reaches the text. Visible, not a ghost: the mask holds the
   image clear where there is nothing to read and removes it where there is. */
.practice-tex {
  background-size: cover;
  filter: grayscale(0.2) contrast(1.02);
  opacity: 0.9;
  -webkit-mask-image: linear-gradient(to left, #000 0%, rgba(0, 0, 0, 0.55) 30%, transparent 58%);
  mask-image: linear-gradient(to left, #000 0%, rgba(0, 0, 0, 0.55) 30%, transparent 58%);
}

/* Commercial Advisory — the business press: a share-price chart over columns
   of quoted figures. Positioned right so the dense number tables fill the
   panel and the one named company on the chart stays out of frame. Pulled
   down in brightness because newsprint is close to white. */
.tex-commercial .practice-tex {
  background-image: url('assets/markets.webp');
  background-position: 88% 62%;
  filter: grayscale(0.35) contrast(0.92) brightness(1.02);
}

/* Financial Advisory — a nineteenth-century bookkeeping ledger, entries in
   ink, with the inkwell and bound volumes behind it. The paper and leather
   already sit in the gold range, so it needs almost no correction. */
.tex-financial .practice-tex {
  background-image: url('assets/ledger.webp');
  background-position: 45% 72%;
  filter: grayscale(0.12) contrast(0.88) brightness(1.1);
}

/* Management Consulting — the numbered keybank of a mechanical adding
   machine: ordered rows, every figure in its place. The keys are mint and
   cream, which is outside the palette, so this one is desaturated hard and
   warmed back towards the page. */
.tex-management .practice-tex {
  background-image: url('assets/keys.webp');
  background-position: 50% 50%;
  filter: grayscale(0.62) sepia(0.18) contrast(0.7) brightness(1.28);
}

/* The photographs are documents, so they carry fine detail and deep shadow
   where the architectural images they replaced carried sky and glass. The
   service links sit directly on top of them, so each row lays a veil of the
   section's own paper colour over its photograph, between the image and the
   text. The amount is measured, not guessed: it is the lightest veil that
   holds every link above 4.5:1 against the darkest pixel it can fall on,
   plus a margin. Raising the amount fades the photograph; lowering it below
   these figures breaks the contrast requirement. */
.has-tex::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background: color-mix(in srgb, var(--paper-sunk) var(--scrim, 0%), transparent);
}
.tex-commercial {
  --scrim: 24%;
}
.tex-financial {
  --scrim: 36%;
}
.tex-management {
  --scrim: 40%;
}

/* Below the two-column breakpoint the text runs full width, so the image
   drops behind it and is pulled back hard to stay out of the way. */
/* Below the two-column breakpoint the text runs the full width, so a
   photograph behind it could only ever be a faint ghost — which is what it
   was. Instead each row ends with its photograph as a band: the text clears
   it entirely, so the image can be shown at full strength with nothing laid
   over it, and nothing needs to be read against it. */
@media (max-width: 999px) {
  /* .practice-inner's own padding-block is declared later in the file, so
     this needs the extra class to win rather than relying on order. */
  .has-tex .practice-inner {
    padding-bottom: calc(clamp(3rem, 5vw, 4.5rem) + 12.5rem);
  }
  .practice-tex {
    inset: auto 0 clamp(3rem, 5vw, 4.5rem) 0;
    height: 10rem;
    opacity: 1;
    border-radius: var(--radius-card);
    -webkit-mask-image: none;
    mask-image: none;
  }
  /* Nothing sits on the band, so the images no longer need the shadow lift
     that keeps link text legible on the wide layout, and the veil has
     nothing to veil. */
  .has-tex {
    --scrim: 0%;
  }
  .tex-commercial .practice-tex {
    filter: grayscale(0.3) contrast(1.02);
  }
  .tex-financial .practice-tex {
    filter: grayscale(0.1) contrast(1.03);
  }
  .tex-management .practice-tex {
    filter: grayscale(0.55) sepia(0.15) contrast(1.02);
  }
}
.practice::before {
  content: '';
  position: absolute;
  inset-inline: 0;
  top: -1px;
  height: 1px;
  background: var(--accent-bright);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.6s cubic-bezier(0.22, 1, 0.36, 1);
}
.practice:hover::before,
.practice:focus-within::before {
  transform: scaleX(1);
}
.practice-no {
  transition:
    color 0.35s ease,
    transform 0.45s cubic-bezier(0.22, 1, 0.36, 1);
}
.practice:hover .practice-no {
  color: var(--brand);
  transform: translateX(3px);
}

.practice-inner {
  display: grid;
  gap: 2rem;
  padding-block: clamp(3rem, 5vw, 4.5rem);
}
@media (min-width: 1000px) {
  .practice-inner {
    grid-template-columns: 0.85fr 1.15fr;
    gap: 5rem;
  }
}
.practice-no {
  font-family: 'Newsreader', Georgia, serif;
  font-size: 0.95rem;
  color: var(--accent);
  letter-spacing: 0.04em;
  margin-bottom: 0.9rem;
}
.practice h3 {
  font-size: clamp(1.6rem, 1rem + 1.6vw, 2.25rem);
}
.practice-sum {
  margin-top: 1.1rem;
  color: var(--ink-soft);
  max-width: 34rem;
}
.practice ul {
  list-style: none;
  margin: 0;
  padding: 0;
  columns: 1;
}
@media (min-width: 620px) {
  .practice ul {
    columns: 2;
    column-gap: 2.5rem;
  }
}
.practice li {
  break-inside: avoid;
  padding: 0.7rem 0 0.7rem 1.5rem;
  border-bottom: 1px solid var(--rule);
  position: relative;
  font-size: 0.975rem;
}
.practice li::before {
  content: '';
  position: absolute;
  left: 0;
  top: 1.2rem;
  width: 0.5rem;
  height: 1px;
  background: var(--accent);
}

/* ===========================================================================
   Approach
   =========================================================================== */
.steps {
  list-style: none;
  margin: 3.5rem 0 0;
  padding: 0;
  display: grid;
  gap: 2.5rem;
}
@media (min-width: 850px) {
  .steps {
    grid-template-columns: repeat(4, 1fr);
    gap: 2rem;
  }
}
.steps li {
  padding-left: 1.6rem;
  border-left: 1px solid var(--rule-on-brand);
  position: relative;
}
@media (min-width: 850px) {
  .steps li {
    padding: 1.75rem 0 0;
    border-left: 0;
    border-top: 1px solid var(--rule-on-brand);
  }
}
/* The connector grows along the stages as the section arrives: horizontal on
   a wide screen, vertical on a phone. The text never moves, so it stays
   readable the whole time. */
.steps li {
  position: relative;
  overflow: visible;
}
.js .steps li::after {
  content: '';
  position: absolute;
  background: var(--accent-bright);
  opacity: 0.55;
  transform-origin: top;
  transform: scaleY(0);
  transition: transform 0.9s cubic-bezier(0.22, 1, 0.36, 1);
  left: -1px;
  top: 0;
  width: 1px;
  height: 100%;
}
.js .steps.in li::after {
  transform: scaleY(1);
}
.js .steps.in li:nth-child(1)::after { transition-delay: 0.1s; }
.js .steps.in li:nth-child(2)::after { transition-delay: 0.35s; }
.js .steps.in li:nth-child(3)::after { transition-delay: 0.6s; }
.js .steps.in li:nth-child(4)::after { transition-delay: 0.85s; }

@media (min-width: 850px) {
  .js .steps li::after {
    left: 0;
    top: -1px;
    width: 100%;
    height: 1px;
    transform-origin: left;
    transform: scaleX(0);
    transition-property: transform;
  }
  .js .steps.in li::after {
    transform: scaleX(1);
  }
}

.steps li::before {
  content: '';
  position: absolute;
  background: var(--accent-bright);
  width: 7px;
  height: 7px;
  border-radius: 50%;
  left: -4px;
  top: 0.45rem;
  z-index: 1;
}
@media (min-width: 850px) {
  .steps li::before {
    left: 0;
    top: -4px;
  }
}
.steps .n {
  font-family: 'Newsreader', Georgia, serif;
  font-size: 2.6rem;
  line-height: 1;
  color: var(--accent-bright);
  display: block;
  margin-bottom: 0.9rem;
}
.steps h3 {
  font-size: 1.3rem;
  margin-bottom: 0.6rem;
}
.steps p {
  font-size: 0.95rem;
  color: var(--on-brand-soft);
}

/* ===========================================================================
   Why XAVO
   =========================================================================== */
.why {
  display: grid;
  gap: 1px;
  background: var(--rule);
  border: 1px solid var(--rule);
  border-radius: var(--radius-card);
  overflow: hidden;
  margin-top: 3.5rem;
}
@media (min-width: 760px) {
  .why {
    grid-template-columns: repeat(2, 1fr);
  }
}
@media (min-width: 1100px) {
  .why {
    grid-template-columns: repeat(4, 1fr);
  }
}
.why > div {
  background: var(--paper-raised);
  padding: 2.25rem 1.9rem 2.5rem;
}
.why h3 {
  font-size: 1.2rem;
  margin-bottom: 0.7rem;
}
.why p {
  font-size: 0.95rem;
  color: var(--ink-soft);
}

/* ===========================================================================
   Locations + contact
   =========================================================================== */
.contact-grid {
  display: grid;
  gap: 3rem;
}
@media (min-width: 1000px) {
  .contact-grid {
    grid-template-columns: 0.95fr 1.05fr;
    gap: 5rem;
  }
}
.office {
  border-top: 1px solid var(--rule-on-brand);
  padding-block: 1.6rem;
}
.office h3 {
  font-size: 1.25rem;
  margin-bottom: 0.5rem;
}
.office address {
  font-style: normal;
  font-size: 0.95rem;
  color: var(--on-brand-soft);
  line-height: 1.65;
}
.office a {
  display: inline-block;
  margin-top: 0.7rem;
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--accent-bright);
  text-decoration: none;
  border-bottom: 1px solid color-mix(in srgb, var(--accent-bright) 45%, transparent);
}
.office a:hover {
  border-bottom-color: var(--accent-bright);
}

/* Email and telephone. These are the two things a visitor is most likely to
   reach for on a phone, so each gets a full 44px target rather than the
   hairline the Maps link uses. The rule is drawn with text-decoration so it
   stays against the text while the box around it grows. */
.office-contact {
  list-style: none;
  /* The browser's own indent on a <ul> would push these in past the heading
     and the addresses above them; everything in an office block shares one
     left edge. */
  margin: 0.35rem 0 0;
  padding: 0;
  display: grid;
  justify-items: start;
  gap: 0.35rem;
}
.office-contact a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  margin-top: 0;
  font-size: 1rem;
  border-bottom: 0;
  text-decoration: underline;
  text-decoration-color: color-mix(in srgb, var(--accent-bright) 45%, transparent);
  text-underline-offset: 0.25em;
}
.office-contact a:hover {
  text-decoration-color: var(--accent-bright);
}

.form-card {
  background: var(--paper-raised);
  padding: clamp(1.75rem, 3vw, 2.75rem);
  border-radius: var(--radius-card);
}
.field {
  margin-bottom: 1.1rem;
}
.field label {
  display: block;
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--brand);
  margin-bottom: 0.4rem;
}
.field .opt {
  font-weight: 400;
  color: var(--ink-soft);
}
.field input,
.field select,
.field textarea {
  width: 100%;
  font: inherit;
  font-size: 1rem;
  color: var(--ink);
  background: var(--paper);
  border: 1px solid var(--rule);
  border-radius: 2px;
  padding: 0.8rem 0.9rem;
  transition:
    border-color 0.2s ease,
    box-shadow 0.2s ease;
}
.field textarea {
  resize: vertical;
  min-height: 7.5rem;
}
.field input:focus,
.field select:focus,
.field textarea:focus {
  outline: none;
  border-color: var(--brand);
  box-shadow: inset 0 -2px 0 var(--accent);
}
.field-row {
  display: grid;
  gap: 1.1rem;
}
@media (min-width: 560px) {
  .field-row {
    grid-template-columns: 1fr 1fr;
  }
}
.form-note {
  margin-top: 1.25rem;
  font-size: 0.875rem;
  color: var(--ink-soft);
  border-left: 2px solid var(--accent);
  padding-left: 0.9rem;
}

/* ===========================================================================
   Legal + footer
   =========================================================================== */
.legal-grid {
  display: grid;
  gap: 1px;
  background: var(--rule);
  border: 1px solid var(--rule);
  border-radius: var(--radius-card);
  overflow: hidden;
  margin-top: 3rem;
}
@media (min-width: 900px) {
  .legal-grid {
    grid-template-columns: 1fr 1fr;
  }
}
.legal-grid > div {
  background: var(--paper-raised);
  padding: 2.25rem 2rem;
}
.legal-grid h3 {
  font-family: 'IBM Plex Sans', sans-serif;
  font-size: 1rem;
  font-weight: 600;
  margin-bottom: 1rem;
}
.legal-grid p {
  font-size: 0.9375rem;
  line-height: 1.75;
  color: var(--ink-soft);
}

.foot {
  background: var(--brand-deep);
  color: var(--on-brand-soft);
  border-radius: var(--radius-panel) var(--radius-panel) 0 0;
  margin-inline: var(--gutter);
  margin-top: var(--gutter);
  overflow: hidden;
}
.foot-top {
  display: grid;
  gap: 2.75rem;
  padding-block: 4rem 3rem;
}
@media (min-width: 900px) {
  .foot-top {
    grid-template-columns: 1.6fr 1fr 1fr 1.2fr;
    gap: 3rem;
  }
}
.foot img {
  height: 2.2rem;
  width: auto;
  margin-bottom: 1.5rem;
}
.foot h4 {
  font-family: 'IBM Plex Sans', sans-serif;
  font-size: 0.85rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--accent-bright);
  margin: 0 0 1.1rem;
}
.foot ul {
  list-style: none;
  margin: 0;
  padding: 0;
}
.foot li {
  margin-bottom: 0.7rem;
}
.foot a {
  color: var(--on-brand-soft);
  text-decoration: none;
  font-size: 0.95rem;
}
.foot a:hover {
  color: var(--on-brand);
}
/* Was an inline style, which no media query could reach. */
.foot-blurb {
  font-size: 0.95rem;
  max-width: 24rem;
}
.foot-legal {
  border-top: 1px solid var(--rule-on-brand);
  padding-block: 2rem;
  font-size: 0.85rem;
  line-height: 1.75;
}
.foot-base {
  border-top: 1px solid var(--rule-on-brand);
  padding-block: 1.5rem;
  display: flex;
  flex-wrap: wrap;
  gap: 1rem 1.75rem;
  justify-content: space-between;
  font-size: 0.85rem;
}
/* These sit on one line at the foot of every page and were the only targets
   on the site under the 24px minimum. */
.foot-base a {
  display: inline-block;
  padding-block: 0.3rem;
}

/* ---------------------------------------------------------------------------
   Phone reading sizes. The body scale is tuned for a desktop column; on a
   handset the same copy is read closer to the eye and at a third of the
   width, so the smallest sizes are lifted to 16px — below that, running text
   is uncomfortable, and iOS zooms form fields that sit under it.
   --------------------------------------------------------------------------- */
@media (max-width: 639px) {
  .practice-inner p,
  .foot-blurb,
  .foot-top ul,
  /* .foot a sets its own size, so the link needs the extra step to be lifted
     with the rest of the column. */
  .foot-top ul a {
    font-size: 1rem;
  }
  .foot-legal {
    font-size: 0.9rem;
  }
  .foot-base {
    font-size: 0.875rem;
  }
}

/* ===========================================================================
   Founders page
   Structure follows the Aurex Advisors reference: a heading, one intro line,
   then profiles stacked in a single column — photo, name, role, prose, core
   practice areas, track record. Content is XAVO's own.
   =========================================================================== */
.page-head {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  background: var(--brand-deep);
  color: var(--on-brand);
  margin-top: calc(var(--nav-h) + var(--gutter));
  margin-inline: var(--gutter);
  border-radius: var(--radius-panel);
  padding-block: clamp(3.5rem, 7vw, 6rem);
}
.page-head h1 {
  color: var(--on-brand);
}

.founder {
  display: grid;
  gap: 2rem;
  padding-block: clamp(2.5rem, 5vw, 4rem);
}
.founder + .founder {
  border-top: 1px solid var(--rule);
}
@media (min-width: 860px) {
  .founder {
    grid-template-columns: 22rem 1fr;
    gap: 3.5rem;
  }
}

.founder-photo {
  margin: 0;
  border-radius: var(--radius-card);
  overflow: hidden;
  background: var(--paper-sunk);
  align-self: start;
}
.founder-photo img {
  width: 100%;
  height: auto;
  aspect-ratio: 3 / 4;
  object-fit: cover;
  display: block;
}

.founder-body h2 {
  font-size: clamp(1.6rem, 1.1rem + 1.4vw, 2.1rem);
}
.founder-role {
  margin-top: 0.5rem;
  font-size: 1rem;
  font-weight: 600;
  color: var(--accent);
}
.founder-body > p {
  margin-top: 1.1rem;
  max-width: 60ch;
  color: var(--ink-soft);
}
.founder-sub {
  margin-top: 2rem;
  font-family: var(--font-sans);
  font-size: 0.95rem;
  font-weight: 700;
  letter-spacing: 0.01em;
  color: var(--brand);
}
.founder-list {
  list-style: none;
  margin: 0.9rem 0 0;
  padding: 0;
  display: grid;
  gap: 0;
  border-top: 1px solid var(--rule);
}
@media (min-width: 560px) {
  .founder-list {
    grid-template-columns: 1fr 1fr;
    column-gap: 2.5rem;
  }
}
.founder-list li {
  position: relative;
  padding: 0.65rem 0 0.65rem 1.4rem;
  border-bottom: 1px solid var(--rule);
  font-size: 0.975rem;
}
.founder-list li::before {
  content: '';
  position: absolute;
  left: 0;
  top: 1.15rem;
  width: 0.5rem;
  height: 1px;
  background: var(--accent);
}
.founder-track {
  margin-top: 0.9rem !important;
  padding-left: 1.1rem;
  border-left: 2px solid var(--accent-bright);
}

.founder-cta {
  display: grid;
  gap: 2rem;
  align-items: center;
}
@media (min-width: 900px) {
  .founder-cta {
    grid-template-columns: 1fr auto;
    gap: 3rem;
  }
}

/* ===========================================================================
   Section background photographs
   Abstract architecture, sat well behind a heavy navy wash so the panels read
   as textured depth rather than as pictures competing with the text.
   Credits: assets/SECTION-IMAGE-CREDITS.txt
   =========================================================================== */
.has-photo {
  position: relative;
  isolation: isolate;
}

.has-photo > .section-photo {
  position: absolute;
  inset: 0;
  z-index: -2;
  background-size: cover;
  background-position: center;
  /* The photograph now carries the panel. Lightly desaturated so it sits in
     the navy palette, but at full opacity — previously 0.4 with a heavy
     filter, which made it invisible. The wash below does the contrast work
     instead, the way the Aurex reference does it. */
  filter: grayscale(0.25) brightness(0.92) contrast(1.05);
  opacity: 1;
}

/* The wash. Text contrast cannot depend on a photograph, so this lays
   near-solid navy over it and only lifts where there is no text. */
/* One directional wash: near-solid where the text sits, releasing sharply so
   the photograph is clearly readable on the open side. */
.has-photo > .section-wash {
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background:
    linear-gradient(
      100deg,
      color-mix(in srgb, var(--brand-deep) 94%, transparent) 0%,
      color-mix(in srgb, var(--brand-deep) 86%, transparent) 38%,
      color-mix(in srgb, var(--brand-deep) 55%, transparent) 68%,
      color-mix(in srgb, var(--brand-deep) 34%, transparent) 100%
    );
}

/* On a phone the text spans the full width, so the wash does too — but
   lighter than before, so the image still shows through. */
@media (max-width: 899px) {
  .has-photo > .section-wash {
    background: linear-gradient(
      175deg,
      color-mix(in srgb, var(--brand-deep) 72%, transparent) 0%,
      color-mix(in srgb, var(--brand-deep) 88%, transparent) 42%,
      color-mix(in srgb, var(--brand-deep) 86%, transparent) 100%
    );
  }
}

.photo-approach > .section-photo {
  background-image: url('assets/section-approach.webp');
  background-position: 70% 45%;
}

.photo-contact > .section-photo {
  background-image: url('assets/section-contact.webp');
  background-position: 60% 40%;
}

/* The footer takes the hero image again, very faint, to close the page with
   the same material it opened with. */
.foot {
  position: relative;
  isolation: isolate;
}
.foot > .section-photo {
  position: absolute;
  inset: 0;
  z-index: -2;
  background-image: url('assets/hero-photo.webp');
  background-size: cover;
  background-position: 50% 30%;
  filter: grayscale(0.7) brightness(0.5);
  opacity: 0.26;
}
.foot > .section-wash {
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background: color-mix(in srgb, var(--brand-deep) 90%, transparent);
}

/* ===========================================================================
   Legal document pages (privacy, terms)
   =========================================================================== */
.doc {
  max-width: 44rem;
}
.doc > section {
  padding-block: 2rem;
  border-bottom: 1px solid var(--rule);
}
.doc > section:last-of-type {
  border-bottom: 0;
}
.doc h2 {
  font-size: clamp(1.4rem, 1rem + 1.2vw, 1.8rem);
}
.doc h3 {
  margin-top: 1.5rem;
  font-family: var(--font-sans);
  font-size: 1rem;
  font-weight: 700;
  color: var(--brand);
}
.doc p,
.doc li {
  margin-top: 0.9rem;
  color: var(--ink-soft);
}
.doc ul {
  margin: 0.4rem 0 0;
  padding: 0;
  list-style: none;
}
.doc li {
  position: relative;
  padding-left: 1.3rem;
}
.doc li::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0.85em;
  width: 0.5rem;
  height: 1px;
  background: var(--accent);
}
.doc dl {
  margin: 1rem 0 0;
  border-top: 1px solid var(--rule);
}
.doc dt {
  margin-top: 1rem;
  font-weight: 600;
  color: var(--brand);
}
.doc dd {
  margin: 0.3rem 0 1rem;
  color: var(--ink-soft);
}
/* The grievance email and telephone stand on their own lines rather than
   inside a sentence, so they get the 24px minimum like any other target. */
.doc dd a {
  display: inline-block;
  padding-block: 0.2rem;
}
.doc-notice {
  margin-top: 1.5rem;
  padding: 1.25rem 1.5rem;
  border-left: 2px solid var(--accent-bright);
  background: var(--paper-sunk);
  border-radius: 0 var(--radius-card) var(--radius-card) 0;
}
.doc-notice p {
  margin-top: 0.4rem;
}
.doc-notice strong {
  color: var(--brand);
}

/* ===========================================================================
   Scroll-driven motion (CSS only, no library)

   Uses `animation-timeline: view()`, which ties an animation to an element's
   own pass through the viewport rather than to a scroll listener — so it runs
   on the compositor and costs no main-thread work.

   Progressive enhancement, deliberately:
     - the default state is the finished, visible one
     - the effect is applied only inside @supports
     - `prefers-reduced-motion` switches it off
   A browser without support simply shows the content. Nothing is hidden
   behind a feature that might not exist.
   =========================================================================== */
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    /* Section photographs drift and settle as their panel crosses the screen */
    .has-photo > .section-photo {
      animation: photo-settle linear both;
      animation-timeline: view();
      animation-range: entry 0% cover 60%;
    }

    @keyframes photo-settle {
      from {
        transform: scale(1.12) translateY(2%);
      }
      to {
        transform: scale(1) translateY(0);
      }
    }

    /* Practice photographs ease in rather than snapping on */
    .practice-tex {
      animation: tex-in linear both;
      animation-timeline: view();
      animation-range: entry 10% entry 90%;
    }

    @keyframes tex-in {
      from {
        opacity: 0;
        transform: scale(1.06);
      }
      to {
        opacity: 0.9;
        transform: scale(1);
      }
    }

    @media (max-width: 999px) {
      @keyframes tex-in {
        from {
          opacity: 0;
        }
        to {
          opacity: 0.16;
        }
      }
    }
  }
}

/* ===========================================================================
   Motion — one restrained reveal, switched off on request
   =========================================================================== */
/* Content is visible by default. It is only hidden for the reveal once
   JavaScript has confirmed it is running (the .js class is set inline in
   <head>), so a script failure can never leave the page blank. */
.js .reveal {
  opacity: 0;
  transform: translateY(16px);
  transition:
    opacity 0.7s cubic-bezier(0.22, 1, 0.36, 1),
    transform 0.7s cubic-bezier(0.22, 1, 0.36, 1);
}
.js .reveal.in {
  opacity: 1;
  transform: none;
}

/* Children of a staggered group arrive in sequence rather than together */
.js .stagger > * {
  opacity: 0;
  transform: translateY(14px);
  transition:
    opacity 0.65s cubic-bezier(0.22, 1, 0.36, 1),
    transform 0.65s cubic-bezier(0.22, 1, 0.36, 1);
}
.js .stagger.in > * {
  opacity: 1;
  transform: none;
}
.js .stagger.in > *:nth-child(1) {
  transition-delay: 0.05s;
}
.js .stagger.in > *:nth-child(2) {
  transition-delay: 0.14s;
}
.js .stagger.in > *:nth-child(3) {
  transition-delay: 0.23s;
}
.js .stagger.in > *:nth-child(4) {
  transition-delay: 0.32s;
}
.js .stagger.in > *:nth-child(5) {
  transition-delay: 0.41s;
}

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }
  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    animation-delay: 0ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    transition-delay: 0ms !important;
  }
  .js .reveal,
  .js .stagger > * {
    opacity: 1;
    transform: none;
  }
  /* Everything below would otherwise be left mid-animation */
  .reveal-lines .line > span {
    transform: none;
  }
  .hero-arc path {
    stroke-dashoffset: 0;
  }
  .hero-arc circle {
    opacity: 1;
  }
  /* The hero figure and its network must land fully drawn, not mid-animation */
  .hero-figure-photo {
    clip-path: inset(0 0 0 0);
  }
  .hero-net .net-lines path,
  .hero-net .net-trend {
    stroke-dashoffset: 0;
  }
  .hero-net .net-dots circle,
  .hero-net .net-halo {
    opacity: 1;
  }
  /* Process connectors land drawn rather than at zero scale */
  .js .steps li::after {
    transform: none !important;
  }
  .hero-bg {
    transform: none;
  }
  .btn::after {
    display: none;
  }
}
