/* ---------------------------------------------------------------------------
   Base: element defaults plus the layout helpers every section shares.
   --------------------------------------------------------------------------- */

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

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

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}

body {
  margin: 0;
  background: var(--surface-page);
  color: var(--text-primary);
  font-family: var(--type-body-family);
  font-weight: var(--type-body-weight);
  font-size: var(--type-body-size);
  line-height: var(--type-body-lh);
  text-wrap: pretty;
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3 { margin: 0; font-family: var(--font-display); }
p { margin: 0; }
img { display: block; max-width: 100%; }
strong { font-weight: var(--type-body-strong-weight); }
::selection { background: var(--ilp-red-100); color: var(--ilp-black-900); }

/* Visible focus on everything interactive, using the brand's green ring — the
   design system makes it green on purpose, so focus never reads as a red CTA. */
a:focus-visible,
button:focus-visible,
[tabindex]:focus-visible {
  outline: var(--focus-ring-width) solid var(--focus-ring-color);
  outline-offset: var(--focus-ring-offset);
  border-radius: var(--radius-sm);
}

/* --- In-page navigation -------------------------------------------------
   Clicking a menu link used to jump instantly, and landed the section
   underneath the sticky header. Both are the same measurement problem, so
   the offset is defined once, here.

   --header-height mirrors the band heights measured in sections/header.css.
   scroll-margin-top parks each anchor target that far below the top of the
   viewport, so a section's own heading clears the header instead of hiding
   behind it. js/smooth-scroll.js reads this computed value back rather than
   recomputing a header height of its own.

   scroll-behavior here is the no-JS baseline only: js/smooth-scroll.js sets
   data-smooth-scroll on <html> and takes over, because native smooth
   scrolling would re-animate every frame that script scrolls and fight it. */
:root { --header-height: 86px; }

@media (min-width: 768px)  { :root { --header-height: 96px; } }
@media (min-width: 1025px) { :root { --header-height: 92px; } }

main[id],
main > section[id] {
  scroll-margin-top: calc(var(--header-height) + var(--space-5));
}

html:not([data-smooth-scroll]) { scroll-behavior: smooth; }

@media (prefers-reduced-motion: reduce) {
  html:not([data-smooth-scroll]) { scroll-behavior: auto; }
}

/* --- Container ---------------------------------------------------------- */

.ils-container {
  width: 100%;
  max-width: var(--container-max);
  margin-inline: auto;
  padding-inline: var(--container-pad-sm);
}

@media (min-width: 960px) {
  .ils-container { padding-inline: var(--space-6); }
}

@media (min-width: 1360px) {
  .ils-container { padding-inline: var(--container-pad-lg); }
}

/* --- Screen-reader helpers ---------------------------------------------- */

.ils-visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

.ils-skip-link {
  position: absolute;
  top: var(--space-2);
  left: var(--space-2);
  z-index: 100;
  transform: translateY(-200%);
  padding: var(--space-3) var(--space-4);
  background: var(--surface-inverse);
  color: var(--text-inverse);
  border-radius: var(--radius-control);
  font-family: var(--type-cta-family);
  font-weight: var(--type-cta-weight);
  font-size: var(--type-cta-size);
  letter-spacing: var(--type-cta-tracking);
  text-transform: var(--type-cta-transform);
  text-decoration: none;
  transition: transform var(--dur-base) var(--ease-standard);
}

.ils-skip-link:focus-visible { transform: translateY(0); }

/* --- Reveal on scroll ---------------------------------------------------
   Per direct request, this now reuses the live site's own animation
   exactly, not an approximation of it — pulled straight from its
   stylesheet (@keyframes fadeInUp, inspected directly): opacity 0 -> 1,
   transform translate3d(0, 100%, 0) -> none, 1.25s ease. Percentage
   translateY is relative to the item's OWN height, which is why this only
   became reasonable to copy literally once the items being animated were
   individual boxes/rows rather than whole multi-thousand-pixel sections
   (see the script) — at that scale, 100% would have been an enormous,
   broken-looking slide.

   The section itself (its background) never animates — only the content
   blocks inside it do (js/reveal-on-scroll.js marks each section's
   grandchildren, and each row within a grid, as .reveal-item). Each block
   triggers independently the moment IT scrolls into view, the same
   mechanism confirmed on the live site's own Elementor markup: no element
   there carries an explicit stagger delay.

   Gated behind .js-reveal (added by the script itself) so a JS failure
   never leaves content stuck invisible — this is progressive enhancement,
   not a hard dependency. */
@keyframes ils-reveal-fade-up {
  0% { opacity: 0; transform: translate3d(0, 100%, 0); }
  100% { opacity: 1; transform: none; }
}

.js-reveal .reveal-item { opacity: 0; }

.js-reveal .reveal-item.is-visible {
  animation: ils-reveal-fade-up 1.25s ease both;
}
