/* base.css — resets, defaults, and atmospheric ground for roi.mt
 *
 * The body wears a faint limestone-grain texture: a one-pixel SVG noise
 * baked into a data URI, scaled and held at very low opacity. It's the
 * difference between a flat colour swatch and a sheet of warm paper.
 */

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

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

body {
  margin: 0;
  background-color: var(--color-bg);
  background-image:
    /* faint vignette of warm light from the top-right */
    radial-gradient(
      ellipse 1100px 700px at 92% -10%,
      color-mix(in srgb, var(--color-accent) 10%, transparent) 0%,
      transparent 60%
    ),
    /* limestone grain — encoded SVG fractal noise */
    url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='220' height='220'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 0.11  0 0 0 0 0.10  0 0 0 0 0.09  0 0 0 0.55 0'/></filter><rect width='100%25' height='100%25' filter='url(%23n)' opacity='0.18'/></svg>");
  background-attachment: fixed, fixed;
  background-size: auto, 220px 220px;
  background-repeat: no-repeat, repeat;
  color: var(--color-text);
  font-family: var(--font-body);
  font-size: var(--font-size-base);
  line-height: var(--line-height-normal);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  font-feature-settings: "ss01", "cv11", "kern";
}

h1, h2, h3, h4 {
  font-family: var(--font-display);
  font-weight: 400; /* DM Serif Display has weight built into the letterforms */
  line-height: var(--line-height-tight);
  margin: 0 0 var(--space-4);
  letter-spacing: -0.02em;
}

h1 { font-size: var(--font-size-4xl); letter-spacing: -0.035em; }
h2 { font-size: var(--font-size-2xl); letter-spacing: -0.025em; }
h3 { font-size: var(--font-size-xl); }
h4 { font-size: var(--font-size-lg); }

p {
  margin: 0 0 var(--space-4);
  max-width: var(--max-width-prose);
}

a {
  color: var(--color-accent);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
  text-decoration-color: color-mix(in srgb, var(--color-accent) 40%, transparent);
  transition: color var(--duration-fast) var(--ease-out),
              text-decoration-color var(--duration-fast) var(--ease-out),
              opacity var(--duration-fast) var(--ease-out);
}

a:hover {
  text-decoration-color: var(--color-accent);
}

button {
  font-family: inherit;
  font-size: inherit;
  cursor: pointer;
}

:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 3px;
  border-radius: var(--radius-sm);
}

img {
  max-width: 100%;
  height: auto;
}

/* Remove default list styling when semantic roles are applied */
ul, ol {
  margin: 0;
  padding: 0;
}

/* Fieldset reset */
fieldset {
  border: none;
  margin: 0;
  padding: 0;
}

legend {
  padding: 0;
}

/* ─── Editorial primitives ─── */

/* Eyebrow / kicker — used above titles to identify the section */
.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: var(--space-3);
  font-family: var(--font-body);
  font-size: var(--font-size-xs);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.18em;
  color: var(--color-accent);
  margin: 0 0 var(--space-4);
}
.eyebrow::before {
  content: "";
  width: var(--space-8);
  height: 1px;
  background: currentColor;
  opacity: 0.6;
}

/* Numeric data — tabular figures, monospaced. */
.numeric {
  font-variant-numeric: tabular-nums lining-nums;
  font-feature-settings: "tnum" 1, "lnum" 1;
}

/* Subtle horizontal rule with breathing room */
.rule {
  border: 0;
  border-top: var(--hairline);
  margin: var(--space-12) 0;
}

/* Screen-reader only utility */
.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;
}

/* ─── Selection styling ─── */
::selection {
  background: color-mix(in srgb, var(--color-accent) 30%, transparent);
  color: var(--color-text);
}

/* ─── Reveal on scroll (driven by IntersectionObserver) ─── */
[data-reveal] {
  opacity: 0;
  transform: translateY(14px);
  transition: opacity var(--duration-page) var(--ease-out),
              transform var(--duration-page) var(--ease-out);
  transition-delay: var(--reveal-delay, 0ms);
  will-change: opacity, transform;
}
[data-reveal].is-revealed {
  opacity: 1;
  transform: translateY(0);
}

/* When a hero word-by-word treatment is applied.
 * Two delivery paths share the same visual:
 *   1. Pre-rendered (preferred, e.g. home page <h1 class="split-words">):
 *      spans are in the DOM at first paint and the animation auto-runs as
 *      soon as CSS is parsed — independent of JS execution order. Wins LCP
 *      because the H1's render isn't gated on animations.js loading behind
 *      AdSense on the main thread.
 *   2. JS-driven (legacy, <h1 data-split-words>): animations.js splits the
 *      text at runtime and toggles .is-in to trigger transitions.
 * Both paths use the same word-delay stagger and ease-out curve, so the
 * visual character is identical.
 */
.split-word {
  display: inline-block;
}

/* Pre-rendered (path 1): auto-running CSS keyframe animation */
.split-words .split-word {
  animation: split-word-in var(--duration-page) var(--ease-out) both;
  animation-delay: var(--word-delay, 0ms);
}

@keyframes split-word-in {
  from {
    opacity: 0;
    transform: translateY(0.4em);
    filter: blur(6px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
    filter: blur(0);
  }
}

/* JS-driven (path 2): transition-based, requires .is-in toggle */
[data-split-words] .split-word {
  opacity: 0;
  transform: translateY(0.4em);
  filter: blur(6px);
  transition: opacity var(--duration-page) var(--ease-out),
              transform var(--duration-page) var(--ease-out),
              filter var(--duration-page) var(--ease-out);
  transition-delay: var(--word-delay, 0ms);
}
[data-split-words] .split-word.is-in {
  opacity: 1;
  transform: translateY(0);
  filter: blur(0);
}

@media (prefers-reduced-motion: reduce) {
  [data-reveal],
  .split-word {
    animation: none !important;
    opacity: 1 !important;
    transform: none !important;
    filter: none !important;
  }
}
