/* Keep wheel/touch scrolling on the document. overflow-x:hidden on body
   implicitly creates overflow-y:auto; overscroll:none then traps wheel input. */
html { overflow-x: clip; scroll-behavior: auto; }
body { overflow-x: clip; overflow-y: visible; overscroll-behavior: auto; }

:root {
  --ink: #101010;
  --paper: #F8F8F6;
  --blue: #0F62FE;
  --line: #CDCDCA;
  --muted: #626262;
  --blue-tint: #E9EBFA;
  --blue-soft: #86AAFF;
}
:focus-visible { outline: 3px solid var(--blue); outline-offset: 5px; }
.site-header { background: var(--ink); color: var(--paper); border-color: #545454; }
.keyhole { background: var(--ink); }
.hero-transition { background: var(--paper); }
.arrow svg { stroke: var(--blue); }
.hero-copy > p:not(.eyebrow) { color: var(--muted); }
.contact h2 span { color: var(--blue-soft); }

/* The fixed keyhole must not cover the page without its scroll animation. The
   arrow is no longer tied to it: with the hero CTA removed it is the only
   scroll affordance, so it stays visible even when GSAP never runs. */
.keyhole {
  visibility: hidden;
}

.motion-enabled .keyhole {
  visibility: visible;
}

/* Label plus arrow, stacked and centred. The float keyframes carry the -50%
   horizontal translation because they would otherwise overwrite the centring. */
/* The cue sits in the hero's flow, where the CTA used to be. Absolute
   positioning against a vh fraction collided with the copy on shorter
   viewports, because the headline scales at a different rate than the
   viewport; in flow it simply follows the paragraph and cannot overlap. */
.arrow {
  position: static;
  margin-top: clamp(18px, 3.4vh, 48px);
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  transform: none;
}

.arrow-label {
  color: var(--muted);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: .14em;
  text-transform: uppercase;
}

.arrow svg {
  margin-left: 0;
}

@keyframes float {
  from { transform: translateY(-7px); }
  to { transform: translateY(7px); }
}

/* Let the hero itself be the transition distance, then hand into the canvas. */
.hero-transition {
  height: 100svh;
  min-height: 100svh;
}

.hero {
  position: relative;
  top: auto;
  min-height: calc(100svh - 76px);
  grid-template-columns: 1fr;
  justify-items: center;
  text-align: center;
}

/* The keyhole opening is 50vw x 50vh. The block aims to fill roughly 90% of
   it, leaving a safety margin on every side. The -44px lifts the block onto
   the opening's centre: the hero sits below a 76px header, so its own centre
   is 38px lower than the viewport's. */
.hero-copy {
  width: min(45vw, 1100px);
  max-width: none;
  transform: translateY(-44px);
}

.hero-copy .eyebrow {
  justify-content: center;
}

/* The keyhole opening is a rectangle from 25% to 75% of the viewport on both
   axes, so the hero has 50vh of visible height to work with. The eyebrow and
   the scroll cue have to sit inside it or they land on the near-black surround
   and disappear. Sizing the sentence by height as well as width keeps the whole
   block inside the opening instead of letting it grow past the edge. */
/* Sized against both axes so the sentence fills the opening on any aspect
   ratio instead of being governed by width alone. It settles at three or four
   lines from 1280px to 2560px. */
.hero h1 {
  font-size: clamp(22px, min(4.3vw, 7.4vh), 118px);
  line-height: 1.08;
  margin: clamp(14px, 2.4vh, 34px) 0 0;
}

.hero-copy > p:not(.eyebrow) {
  margin-inline: auto;
  font-size: clamp(12px, 1.25vw, 18px);
}

.hero-link {
  margin: 20px auto 0;
}

.hero-image {
  display: none;
}

.flowchart-section {
  padding-top: 0;
}

/* Keep the reference canvas reachable if JavaScript or GSAP is unavailable. */
html:not(.flow-enhanced) .scroll-wrapper {
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: thin;
}

@media (prefers-reduced-motion: reduce) {
  .keyhole {
    display: none;
  }

  /* Keep the affordance, drop the movement. */
  .arrow {
    animation: none;
  }

  .scroll-instruction {
    animation: none;
  }
}

@media (max-width: 760px) {
  .hero-transition {
    height: auto;
    min-height: calc(100svh - 72px);
  }

  .hero {
    min-height: calc(100svh - 72px);
  }

  .hero-copy {
    width: 44vw;
  }

  .hero h1 {
    font-size: clamp(24px, 7vw, 34px);
    margin: 14px 0;
  }

  .hero-copy .eyebrow {
    font-size: 8px;
    letter-spacing: .08em;
    gap: 5px;
  }

  .hero-copy > p:not(.eyebrow) {
    font-size: clamp(11px, 3vw, 13px);
    line-height: 1.35;
  }

  .hero-link {
    min-height: 42px;
    padding: 8px 10px;
    gap: 12px;
    font-size: 10px;
  }
}

.image-card-placeholder {
  justify-content: center;
  align-items: center;
  text-align: center;
  padding: 12px;
}

/* The only viewport where the cue is dropped: at 699px and under, 72.5vh
   lands on top of the hero copy. */
@media (max-height: 699px) {
  .arrow {
    display: none;
  }
}

/* The sentence settles at four lines, and the fill jumps from 79% to 99% of
   the opening as it does — there is no value in between. Short viewports take
   the four lines and recover the safety margin from the chrome instead: the
   eyebrow and the scroll cue are a fixed height, so they eat 20% of a 360px
   opening against 13% of a 540px one. */
@media (min-width: 1000px) and (min-height: 700px) and (max-height: 880px) and (pointer: fine) {
  .arrow { margin-top: 16px; gap: 6px; }
  .arrow svg { width: 1.5rem; }
}
