/* QI Path — shared dark component kit.
   Linked by every page. Page-specific rules stay inline in each page.

   HARD RULE: never put a bare .element-XXXX hash in here. The builder reused
   the same hashes across pages with different meanings (.element-ZgaK is the
   hero on about-us AND careers AND contact, styled differently in each), so a
   shared definition would have pages overwriting each other. Only
   .element-home-*, renderer-hM1n-*, renderer-hhDS-* and the body base belong here. */

/* =========================================================================
   HOMEPAGE PALETTE — values supplied by design.

     #081a2e  dark blue
     #091a2d  dark blue, hero variant
     #1285f9  bright blue
     #f1c40f  brand gold                    (existing site color)
     #deb40d  gold hover                    (existing site color)
     #febf04  icon yellow — NOT a brand colour and not referenced in CSS.
              It is the yellow baked into the Icon-*.svg set, recorded here
              only so the near-match against #f1c40f is on the record.
     #a8b8d4  muted body copy on dark
     #dce6f5  card body copy

     rgba(255, 255, 255, 0.14) card border
     rgba(255, 255, 255, 0.05) card fill
     rgba(255, 255, 255, 0.12) hairline rule

   BODY BACKGROUND MUST STAY #fff. It is not merely the overscroll colour:
   every translucent gradient stop below composites against it, so changing
   it silently reprices half the page. Verified against the Canva comp
   (~/Desktop/QI Path Website/Home.png) — see the note on alpha below.

   SECTION GRADIENTS — all 180deg, as supplied by design.

   The design specs are written as "#1285f9 with N% transparency", where N
   is TRANSPARENCY, not opacity: CSS alpha = (100 - N) / 100. So
   "70% transparency" is alpha 0.3, and "5% transparency" is alpha 0.95 —
   nearly solid. Getting this backwards inverts every gradient on the page.

   Confirmed by sampling the comp: its palest pixel and its final pixel are
   both #b8dafd, and blue at alpha 0.30 over white is exactly #b8dafd. The
   hero's last row is #1d89f5, and blue at alpha 0.95 over white is #1d8bf9.

     Menu + Hero     #091a2d -> #091a2d -> #1285f9 @a0.95
     Mission         #1285f9 -> #1285f9 @a0.30

     Why QI Path  ┐  #1285f9 @a0.30 -> #1285f9 -> #081a2e
     What We Prov.┘  one ramp across both, on .element-home-band

     Our Clients     #081a2e (flat)
     Closing CTA     #081a2e -> #1285f9 -> #1285f9 @a0.30

   Boundaries are seamless because adjacent stops match: the hero ends at
   near-solid blue where the mission opens on solid blue, and the mission
   ends at @a0.30 where the Why/Provide band opens on @a0.30.
   ========================================================================= */

body {
  margin: 0;
  padding: 0;
  font-size: 16px;
  min-height: 100vh;
  font-family: 'Inter', sans-serif;
  background-color: #fff;
}

@media (max-width: 768px) {
  body {
    font-size: 14px;
  }
}

@media (max-width: 390px) {
  body {
    font-size: 12px;
  }
}

/* =========================================================================
   NAVBAR — copied verbatim from the other pages. Do not edit these rules;
   the dark treatment lives in the HOME DARK override block below so this
   block stays diffable against about-us.html / careers.html / etc.
   (The .renderer-hM1n-element-A8yI "Home" rules are omitted — that link is
   removed on this page.)
   ========================================================================= */

.renderer-hM1n-element-FNT3 {
  top: 0;
  width: 100%;
  z-index: 100;
  position: fixed;
}

.renderer-hM1n-element-ydzY {
  display: flex;
  padding: 20px 10px;
  transition: all 0.3s ease;
  align-items: center;
  justify-content: space-between;
  background-color: #fff;
}

@media (max-width: 1024px) {
  .renderer-hM1n-element-ydzY {
    width: 100%;
    overflow: hidden;
    position: relative;
    flex-flow: column;
    transition: all 0.6s ease;
  }
}

@media (max-width: 428px) {
  .renderer-hM1n-element-ydzY {
    padding: 10px;
  }
}

.renderer-hM1n-element-O3Hn {
  display: flex;
  flex-flow: row;
}

@media (max-width: 1024px) {
  .renderer-hM1n-element-O3Hn {
    width: 100%;
    align-items: center;
    justify-content: space-between;
  }
}

.renderer-hM1n-element-H3GU {
  display: flex;
  padding: 10px;
  align-items: center;
}

@media (max-width: 1024px) {
  .renderer-hM1n-element-H3GU {
    flex: 1 1 auto;
  }
}

.renderer-hM1n-element-LLtv {
  font-family: 'Inter', sans-serif;
  text-decoration: none;
}

.renderer-hM1n-element-0nA6 {
  height: 35px;
}

@media (max-width: 428px) {
  .renderer-hM1n-element-0nA6 {
    height: 24px;
  }
}

@media (max-width: 1024px) {
  .renderer-hM1n-element-McAt {
    height: 40px;
    display: flex;
    padding: 0 10px;
    position: relative;
    align-items: center;
    justify-content: flex-end;
  }
}

@media (max-width: 1024px) {
  .renderer-hM1n-element-1prZ {
    top: 0;
    right: 0;
    width: 100%;
    cursor: pointer;
    height: 100%;
    display: block;
    position: absolute;
  }
}

.renderer-hM1n-element-1hED {
  width: 30px;
  height: 0;
  display: none;
  position: relative;
}

@media (max-width: 1024px) {
  .renderer-hM1n-element-1hED {
    top: -10px;
    display: block;
    pointer-events: none;
  }
}

.renderer-hM1n-element-NLOs {
  top: 0;
  left: 0;
  color: #232e37;
  width: 100%;
  height: 2px;
  display: block;
  opacity: 1;
  position: absolute;
  background: #232e37;
  transition: all 0.3s ease;
  font-family: 'Inter', sans-serif;
  font-weight: 300;
  border-radius: 5px;
}

@media (max-width: 1024px) {
  .renderer-hM1n-element-NLOs {
    background-color: #072253;
  }
}

.renderer-hM1n-element-e3KN {
  top: 10px;
  left: 0;
  color: #232e37;
  width: 100%;
  height: 2px;
  display: block;
  opacity: 1;
  position: absolute;
  background: #232e37;
  transition: all 0.3s ease;
  font-family: 'Inter', sans-serif;
  font-weight: 300;
  border-radius: 5px;
}

@media (max-width: 1024px) {
  .renderer-hM1n-element-e3KN {
    background-color: #072253;
  }
}

.renderer-hM1n-element-CFA4 {
  top: 20px;
  left: 0;
  color: #232e37;
  width: 100%;
  height: 2px;
  display: block;
  opacity: 1;
  position: absolute;
  background: #232e37;
  transition: all 0.3s ease;
  font-family: 'Inter', sans-serif;
  font-weight: 300;
  border-radius: 5px;
}

@media (max-width: 1024px) {
  .renderer-hM1n-element-CFA4 {
    background-color: #072253;
  }
}

.renderer-hM1n-element-EGqT {
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
}

@media (max-width: 1024px) {
  .renderer-hM1n-element-EGqT {
    width: 100%;
    opacity: 0;
    max-height: 0;
    transition: all 0.6s ease;
    visibility: hidden;
    align-items: flex-start;
    justify-content: center;
  }
}

@media (max-width: 428px) {
  .renderer-hM1n-element-EGqT {
    height: 100dvh;
    font-size: 24px;
  }
}

.renderer-hM1n-element-QeGx {
  display: flex;
  flex-flow: row;
  align-items: center;
  justify-content: end;
}

@media (max-width: 1024px) {
  .renderer-hM1n-element-QeGx {
    gap: 20px;
    padding: 20px;
    flex-flow: column;
    text-align: center;
    align-items: center;
    justify-content: flex-start;
  }
}

@media (max-width: 428px) {
  .renderer-hM1n-element-QeGx {
    height: 100%;
    align-items: stretch;
    justify-content: space-evenly;
  }
}

.renderer-hM1n-element-LScG {
  color: #232e37;
  margin: 0 1em;
  padding: 0.5em;
  transition: all 0.2s ease;
  font-family: 'Inter', sans-serif;
  font-weight: 500;
  text-decoration: none;
}

.renderer-hM1n-element-LScG:hover {
  color: #0185ff;
}

.renderer-hM1n-element-KKTT {
  color: #232e37;
  margin: 0 1em;
  padding: 0.5em;
  transition: all 0.2s ease;
  font-family: 'Inter', sans-serif;
  font-weight: 500;
  text-decoration: none;
}

.renderer-hM1n-element-KKTT:hover {
  color: #0185ff;
}

.renderer-hM1n-element-ryuG {
  color: #232e37;
  margin: 0 1em;
  padding: 0.5em;
  transition: all 0.2s ease;
  font-family: 'Inter', sans-serif;
  font-weight: 500;
  text-decoration: none;
}

.renderer-hM1n-element-ryuG:hover {
  color: #0185ff;
}

.renderer-hM1n-element-0B2j {
  margin: 0 0.5em;
  display: flex;
  flex-flow: row;
  align-items: center;
  justify-content: flex-end;
}

@media (max-width: 1024px) {
  .renderer-hM1n-element-0B2j {
    width: 100%;
    margin: 0.5em;
    flex-flow: row wrap;
    justify-content: space-around;
  }
}

@media (max-width: 428px) {
  .renderer-hM1n-element-0B2j {
    margin: 0.5em 0.5em 2em;
  }
}

.renderer-hhDS-element-3r9Y {
  margin: 0;
  padding: 0;
}

.renderer-hhDS-element-mVG1 {
  color: #232e37;
  border: 2px solid #f1c40f;
  display: inline-block;
  padding: 0.8em 1.5em;
  font-size: 1em;
  transition: all 0.2s ease;
  font-family: 'Inter', sans-serif;
  font-weight: 600;
  border-radius: 0;
  letter-spacing: 0.7px;
  text-decoration: none;
  background-color: #f1c40f;
}

@media (max-width: 768px) {
  .renderer-hhDS-element-mVG1 {
    font-size: 0.75em;
  }
}

.renderer-hhDS-element-mVG1:hover {
  border: 2px solid #deb40d;
  background-color: #deb40d;
}

/* =========================================================================
   HOME DARK: navbar overrides
   Must stay AFTER the copied nav rules above so the .line color wins
   inside the 1024px media query.
   ========================================================================= */

.element-home-nav {
  background-color: transparent;
}

#navbar.element-home-nav.scrolled {
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
  background-color: rgba(8, 26, 46, 0.72);
}

#navbar.element-home-nav.is-active {
  background-color: #081a2e;
}

.element-home-nav .renderer-hM1n-element-LScG,
.element-home-nav .renderer-hM1n-element-KKTT,
.element-home-nav .renderer-hM1n-element-ryuG {
  color: #fff;
}

.element-home-nav .renderer-hM1n-element-LScG:hover,
.element-home-nav .renderer-hM1n-element-KKTT:hover,
.element-home-nav .renderer-hM1n-element-ryuG:hover {
  color: #f1c40f;
}

.element-home-nav .line {
  background: #fff;
  background-color: #fff;
}

/* Desktop-only layout: links sit immediately left of the logo instead of
   being pushed right, with the CTA alone on the far right. Scoped to
   min-width 1025px because these selectors are more specific than the
   copied `@media (max-width: 1024px)` rules and would otherwise break the
   stacked mobile menu. */
@media (min-width: 1025px) {
  .element-home-nav .renderer-hM1n-element-EGqT {
    flex: 1 1 auto;
  }

  .element-home-nav .renderer-hM1n-element-QeGx {
    width: 100%;
    justify-content: flex-start;
  }

  .element-home-nav .renderer-hM1n-element-0B2j {
    margin-left: auto;
  }
}

.element-home-nav .renderer-hM1n-element-LScG,
.element-home-nav .renderer-hM1n-element-KKTT,
.element-home-nav .renderer-hM1n-element-ryuG {
  font-size: 1em;
  font-weight: 400;
  letter-spacing: 1px;
  text-transform: uppercase;
}

/* =========================================================================
   HOME DARK: shared tokens
   Used by three or more sections each — defined once here.
   ========================================================================= */

/* SUB-PIXEL SEAM FIX.
   Section heights land on fractional pixels (em padding, vh padding, and a
   14/12px root font-size), so adjacent section backgrounds don't quite meet
   and a hairline of the white body shows through — worst on mobile, where
   device pixel ratios differ. Each band is pulled 1px into the next so the
   following section's background covers the gap.
   This only works because every following edge is OPAQUE: the mission and
   band gradients open on pre-composited solids (#1e8bf9 / #4da4fa) rather
   than translucent stops, which would otherwise double-composite over that
   1px and leave a visible line instead of a seam. */
.element-home-hero,
/*.element-home-mission,*/
.element-home-band,
.element-home-clients
/*.element-home-cta */ {
  margin-bottom: -1px;
}

.element-home-section {
  width: 100%;
  padding: 80px 5%;
}

@media (max-width: 768px) {
  .element-home-section {
    padding: 60px 5%;
  }
}

.element-home-inner {
  margin: 0 auto;
  max-width: 1200px;
}

.element-home-eyebrow {
  color: #f1c40f;
  display: block;
  font-size: 1.25em;
  font-family: 'Inter', sans-serif;
  font-weight: 600;
  letter-spacing: 2px;
  text-transform: uppercase;
}

.element-home-h2 {
  color: #fff;
  font-size: 2.75em;
  font-family: 'Inter', sans-serif;
  font-weight: 500;
  line-height: 118%;
  letter-spacing: -1px;
}

@media (max-width: 768px) {
  .element-home-h2 {
    font-size: 2em;
  }
}

.element-home-muted {
  color: #fff;
  font-family: 'Inter', sans-serif;
  font-weight: 400;
  line-height: 150%;
  font-size: 1.25em;
  position: relative;
  top: 1em;
}

.element-home-img {
  width: 100%;
  height: auto;
  display: block;
  max-width: 100%;
}

.element-home-btn-row {
  gap: 1em;
  display: flex;
  flex-flow: row wrap;
  align-items: center;
}

@media (max-width: 428px) {
  .element-home-btn-row {
    flex-flow: column;
    align-items: stretch;
  }
}

.element-home-btn-gold {
  color: #081a2e;
  border: 2px solid #f1c40f;
  display: inline-block;
  padding: 0.8em 1.5em;
  font-size: 1em;
  text-align: center;
  transition: all 0.2s ease;
  font-family: 'Inter', sans-serif;
  font-weight: 600;
  border-radius: 0;
  letter-spacing: 0.7px;
  text-decoration: none;
  text-transform: uppercase;
  background-color: #f1c40f;
}

/* Hover resolves to the ghost button's resting state: dark fill, gold text and
   gold border. Border stays 2px (the ghost's is 1px + padding compensation) so
   the button doesn't change size on hover. */
.element-home-btn-gold:hover {
  color: #f1c40f;
  border: 2px solid #f1c40f;
  background-color: #081a2e;
}

/* Dark fill, gold text, hairline gold border — per the comp, which uses a
   1px border here against the gold button's 2px. The padding adds that 1px
   back so the two render at identical heights side by side. */
.element-home-btn-ghost {
  color: #f1c40f;
  border: 1px solid #f1c40f;
  display: inline-block;
  padding: calc(0.8em + 1px) calc(1.5em + 1px);
  font-size: 1em;
  text-align: center;
  transition: all 0.2s ease;
  font-family: 'Inter', sans-serif;
  font-weight: 600;
  border-radius: 0;
  letter-spacing: 0.7px;
  text-decoration: none;
  text-transform: uppercase;
  background-color: #081a2e;
}

.element-home-btn-ghost:hover {
  color: #081a2e;
  background-color: #f1c40f;
}

/* Faint "Q" watermark, used by the mission band and the closing CTA band.
   Source PNG is already white with an alpha channel, so this is a plain
   background image at low opacity — no mask, no vendor prefixes.
   Sized in px on purpose: it is decorative art and should not compound
   with the 16 -> 14 -> 12px body font-size steps.
   The host section MUST set `position: relative; overflow: hidden` or this
   box overflows the document and creates a horizontal scrollbar. */
.element-home-watermark {
  top: 50%;
  left: 50%;
  width: 50%;
  height: 100%;
  opacity: 0.07;
  z-index: 0;
  position: absolute;
  transform: translate(-50%, -50%);
  background-size: contain;
  background-image: url('/__PUBLIC_LIGHT/assets/QI-logomark-white.png');
  background-repeat: no-repeat;
  pointer-events: none;
  background-position: center;
}

/* Right-aligned variant. Hangs slightly off the right edge, which the host
   section's `overflow: hidden` crops. */
.element-home-watermark-right {
  left: auto;
  right: -140px;
  transform: translate(0, -50%);
}

@media (max-width: 768px) {
  .element-home-watermark {
    width: 560px;
    height: 560px;
    opacity: 0.06;
  }

  .element-home-watermark-right {
    right: -100px;
  }
}

@media (max-width: 428px) {
  .element-home-watermark {
    width: 380px;
    height: 380px;
  }

  .element-home-watermark-right {
    right: -70px;
  }
}

/* The Icon-*.svg set ships already coloured, so these are plain <img> —
   no mask, no tint. (Their exports carried two opaque white background
   rects, which were stripped; re-exports need the same treatment or the
   icons render as white squares on the dark section.) */
.element-home-pillar-icon {
  width: 3.5em;
  height: 3.5em;
  display: block;
}

/* =========================================================================
   SECTION 2 — HERO
   ========================================================================= */

/* Not width-limited: the hero image runs flush to the right edge, so only
   the left side gets padding. */
.element-home-hero {
  width: 100%;
  padding: 9em 5% 6em;
  background: linear-gradient(180deg, #091a2d, #091a2d, rgba(18, 133, 249, 0.95));
}

@media (max-width: 768px) {
  .element-home-hero {
    padding: 8em 5% 4em;
  }
}

/* Deliberately NOT capped at 1200px like the other sections — the hero runs
   the full width of the viewport, held in only by the section's 5% padding. */
.element-home-hero-inner {
  gap: 4%;
  display: flex;
  flex-flow: row;
  align-items: center;
}

@media (max-width: 768px) {
  .element-home-hero-inner {
    gap: 3em;
    flex-flow: column;
  }
}

/* 1/3 text, 2/3 image. The two bases plus the 4% gap total 100%. */
.element-home-hero-copy {
  gap: 1.5em;
  flex: 1 1 45%;
  display: flex;
  flex-flow: column;
  align-items: flex-start;
}

@media (max-width: 428px) {
  .element-home-hero-copy {
    align-items: stretch;
  }
}

.element-home-hero-title {
  color: #fff;
  font-size: 4em;
  font-family: 'Inter', sans-serif;
  font-weight: 500;
  line-height: 118%;
  letter-spacing: -2px;
}

@media (max-width: 768px) {
  .element-home-hero-title {
    font-size: 2.5em;
    letter-spacing: -1px;
  }
}

.element-home-hero-lede {
  color: #fff;
  font-size: 1.8em;
  max-width: 600px;
  font-family: 'Inter', sans-serif;
  font-weight: 400;
}

.element-home-hero-media {
  flex: 1 1 55%;
}

/* The homepage hero art (hero-UI.png) is a transparent cut-out, so by default a
   hero image gets no shadow or radius — both would apply to the bounding box
   rather than the artwork, drawing a rectangle around empty space. */
.element-home-hero-media img {
  width: 100%;
  height: auto;
  display: block;
}

/* Opt-in for heroes whose image is a rectangular photo (About Us, Careers),
   where a radius and a lift shadow do read correctly. */
.element-home-hero-media-photo img {
  box-shadow: 0 24px 60px rgba(0, 0, 0, 0.45);
  border-radius: 10px;
}

/* =========================================================================
   SECTION 3 — MISSION STATEMENT
   ========================================================================= */

.element-home-mission {
  width: 100%;
  padding: 25vh 5%;
  overflow: hidden;
  position: relative;
  /* First stop is #1e8bf9, the pre-composited value of blue @a0.95 over the
     white body — identical on screen, but opaque, which lets this section
     overlap the hero and cover the sub-pixel seam. See the seam note below. */
  background: linear-gradient(180deg, #1e8bf9, #1285f9, rgba(18, 133, 249, 0.75));
}

@media (max-width: 768px) {
  .element-home-mission {
    padding: 120px 5%;
  }
}

.element-home-mission-inner {
  margin: 0 auto;
  z-index: 1;
  position: relative;
  max-width: 1200px;
  text-align: center;
}

.element-home-mission-text {
  color: #fff;
  font-size: 2.75em;
  font-family: 'Inter', sans-serif;
  font-weight: 500;
  line-height: 135%;
  letter-spacing: -1px;
}

@media (max-width: 768px) {
  .element-home-mission-text {
    font-size: 1.85em;
    letter-spacing: -0.5px;
  }
}

/* =========================================================================
   SECTION 4 — WHY QI PATH
   ========================================================================= */

/* "Why QI Path" and "What We Provide" share ONE gradient spanning both
   sections, so it lives on the wrapper and the two sections stay
   transparent. Do not give either section its own background. */
.element-home-band {
  width: 100%;
  /* First stop is #4da4fa, the pre-composited value of blue @a0.75 over the
     white body — see the note on .element-home-mission. */
  background: linear-gradient(180deg, #4da4fa, #1285f9, #081a2e);
}

.element-home-why-head {
  gap: 4%;
  display: flex;
  flex-flow: row;
  align-items: flex-end;
}

@media (max-width: 768px) {
  .element-home-why-head {
    gap: 1.5em;
    flex-flow: column;
    align-items: flex-start;
  }
}

.element-home-why-head-left {
  gap: 0.75em;
  flex: 1 1 52%;
  display: flex;
  flex-flow: column;
}

.element-home-why-head-right {
  flex: 1 1 44%;
}

.element-home-pillars {
  gap: 2.5em;
  display: grid;
  margin-top: 4em;
  grid-template-columns: repeat(4, 1fr);
}

@media (max-width: 768px) {
  .element-home-pillars {
    gap: 2em;
    margin-top: 3em;
    grid-template-columns: repeat(2, 1fr);
  }
}

@media (max-width: 428px) {
  .element-home-pillars {
    grid-template-columns: 1fr;
  }
}

.element-home-pillar {
  gap: 0.75em;
  display: flex;
  flex-flow: column;
}

/* Brand gold. These headings sit directly under the Icon-*.svg set, which ships
   in #febf04 — close enough to read as the same colour at icon scale. If the
   icons are ever re-exported far from this hue, revisit whether the headings
   should track them instead. */
.element-home-pillar-title {
  color: #f1c40f;
  font-size: 1.5em;
  font-family: 'Inter', sans-serif;
  font-weight: 600;
  line-height: 130%;
}

.element-home-pillar-text {
  color: #fff;
  font-size: 1em;
  font-family: 'Inter', sans-serif;
  font-weight: 400;
  line-height: 155%;
}

/* =========================================================================
   SECTION 8 — CLOSING CTA
   ========================================================================= */

.element-home-cta {
  width: 100%;
  padding: 160px 5%;
  overflow: hidden;
  position: relative;
  background: linear-gradient(180deg, #081a2e, #1285f9, rgba(18, 133, 249, 0.3));
}

@media (max-width: 768px) {
  .element-home-cta {
    padding: 100px 5%;
  }
}

.element-home-cta-inner {
  max-width: 1200px;
  gap: 2em;
  margin: 0 auto;
  display: flex;
  z-index: 1;
  position: relative;
  flex-flow: column;
  align-items: flex-start;
}

@media (max-width: 428px) {
  .element-home-cta-inner {
    align-items: stretch;
  }
}

.element-home-cta-title {
  color: #fff;
  font-size: 3.5em;
  max-width: 800px;
  font-family: 'Inter', sans-serif;
  font-weight: 500;
  line-height: 125%;
  letter-spacing: -1.5px;
}

@media (max-width: 768px) {
  .element-home-cta-title {
    font-size: 2.25em;
    letter-spacing: -1px;
  }
}

/* =========================================================================
   FOOTER — slim copyright banner. The sticky header carries navigation on
   this page, so the full link footer used by the other pages is dropped.
   ========================================================================= */

.element-home-footer {
  color: #666;
  width: 100%;
  border-top: 1px solid rgba(255, 255, 255, 0.08);
  display: flex;
  padding: 0.5em;
  font-size: 1em;
  align-items: center;
  font-family: 'Inter', sans-serif;
  justify-content: flex-end;
  background-color: rgba(18, 133, 249, 0.3);
}

/* =========================================================================
   SCROLL REVEAL
   Driven by qip-reveal.js. Opt an element in with
   data-reveal="left|right|up|fade"; it starts hidden and offset, and gets
   .is-revealed the first time it scrolls into view.

   The hidden state is gated behind .reveal-on, which the script adds to
   <html> only after confirming it can both observe and animate. A visitor
   with JS off, without IntersectionObserver, or with prefers-reduced-motion
   set never matches these selectors and simply sees the finished page — the
   one failure mode worth engineering against here is content stuck at
   opacity 0 with nothing left to un-hide it.
   ========================================================================= */

.reveal-on [data-reveal] {
  opacity: 0;
  transition:
    opacity 1.4s cubic-bezier(0.22, 1, 0.36, 1),
    transform 1.4s cubic-bezier(0.22, 1, 0.36, 1);
}

.reveal-on [data-reveal='left'] {
  transform: translateX(-40px);
}

.reveal-on [data-reveal='right'] {
  transform: translateX(40px);
}

.reveal-on [data-reveal='up'] {
  transform: translateY(40px);
}

/* data-reveal="fade" matches no transform rule, so it fades in place. */

.reveal-on [data-reveal].is-revealed {
  opacity: 1;
  transform: none;
}

/* Sideways reveals become vertical below the desktop breakpoint, for two
   reasons. The sections hold their content in with 5% padding, which drops
   under the 40px offset around 800px wide and would let a revealing element
   push a horizontal scrollbar. And once a row has stacked into one column
   there is no longer a left or right for anything to arrive from. */
@media (max-width: 1024px) {
  .reveal-on [data-reveal='left'],
  .reveal-on [data-reveal='right'] {
    transform: translateY(30px);
  }
}

/* Stagger. Children of a .reveal-stagger container step 0.24s apart. Each
   child is still observed on its own, so the delay counts from the moment
   that child enters view, not the container.
   Kept proportional to the 1.4s duration above — against a fade that long, a
   step much shorter than this stops reading as a stagger at all. */
.reveal-on .reveal-stagger > [data-reveal]:nth-child(2) {
  transition-delay: 0.24s;
}

.reveal-on .reveal-stagger > [data-reveal]:nth-child(3) {
  transition-delay: 0.48s;
}

.reveal-on .reveal-stagger > [data-reveal]:nth-child(4) {
  transition-delay: 0.72s;
}

/* Stacked, the columns already arrive one at a time, so a delay on top of
   that reads as lag rather than rhythm. */
@media (max-width: 768px) {
  .reveal-on .reveal-stagger > [data-reveal] {
    transition-delay: 0s;
  }
}

/* Nav interaction states — previously inline in each page's <body> after the
   nav markup. The nav <script> that toggles these classes stays inline. */
#navbar {
  -webkit-backdrop-filter: blur(15px);
  backdrop-filter: blur(15px);
}

#navbar.scrolled {
  background-color: rgba(255, 255, 255, 0.5);
  padding: 10px;
}

.hover-underline-animation:hover:after {
  transform: scaleX(1);
  transform-origin: bottom left;
}

.active-link:after {
  transform: scaleX(1);
  transform-origin: bottom left;
}

#nav-links.is-active {
  visibility: visible;
  opacity: 1;
  max-height: 100vh;
}

#navbar.is-active {
  background-color: #fff;
  height: auto;
}

#hamburger.is-active {
  transition: all 0.3s ease-in-out;
  transition-delay: 0.6s;
  transform: translateX(12px) rotate(45deg);
}

#hamburger.is-active .line:nth-child(2) {
  width: 0px;
}

#hamburger.is-active .line:nth-child(1),
#hamburger.is-active .line:nth-child(3) {
  transition-delay: 0.3s;
}

#hamburger.is-active .line:nth-child(1) {
  transform: translateY(15px);
}

#hamburger.is-active .line:nth-child(3) {
  transform: translateY(-5px) rotate(90deg);
}
