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

/*
 * The ground is painted on BOTH html and body.
 *
 * Body-background propagation covers the canvas in the normal case, but
 * any condition where the body box does not span the full viewport —
 * fractional zoom, an embedded preview pane, a host that paints its own
 * ground behind the document — leaves a strip showing whatever is
 * underneath. Painting html too means that strip is her pink, never dark.
 */
/*
 * The ground lives on html, and it is a complete design on its own.
 *
 * This is the shader's fallback, not a placeholder: with WebGL blocked,
 * unavailable, or simply switched off, the page still sits on a warm
 * pearl wash that reads as her paper. Nothing below depends on the canvas
 * existing.
 */
html {
  -webkit-text-size-adjust: 100%;
  /* The hero CTA jumps to the grid; this is the only scrolling behaviour
     on the page and it is disabled under reduced motion below. */
  scroll-behavior: smooth;
  min-height: 100%;
  background:
    radial-gradient(ellipse 90% 60% at 22% 8%, rgba(255, 255, 255, .85) 0%, rgba(255, 255, 255, 0) 62%),
    radial-gradient(ellipse 80% 55% at 84% 74%, rgba(248, 216, 216, .8) 0%, rgba(248, 216, 216, 0) 60%),
    var(--ground-1);
  background-attachment: fixed;
}

body {
  margin: 0;
  min-width: 100%;
  min-height: 100svh;
  /* Transparent so the two fixed paper layers below can sit at negative
     z-index and still be seen; html carries the ground. */
  background: transparent;
  position: relative;
  color: var(--ink);
  font-family: ui-rounded, "SF Pro Rounded", system-ui, -apple-system, "Segoe UI", sans-serif;
  font-size: clamp(15px, 0.55vw + 13px, 17px);
  line-height: 1.55;
  overflow-x: hidden;
}

img { max-width: 100%; display: block; }

h1, h2, h3 { line-height: 1.2; text-wrap: balance; }

a { color: var(--accent-text); text-underline-offset: 3px; }

a:focus-visible,
button:focus-visible,
[tabindex]:focus-visible {
  outline: 2px solid var(--accent-text);
  outline-offset: 3px;
  border-radius: 4px;
}

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

/* Skip link becomes visible on focus. */
.skip:focus-visible {
  position: fixed;
  inset: 12px auto auto 12px;
  width: auto;
  height: auto;
  margin: 0;
  padding: 10px 16px;
  clip-path: none;
  background: var(--white);
  border-radius: 999px;
  z-index: 100;
}

.tnum { font-variant-numeric: tabular-nums; }


/*
 * The two paper layers. Both are fixed, both are decorative, neither is
 * ever in the tab order or the accessibility tree, and neither receives
 * a single pointer event.
 */
.paper,
.hearts {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: -2;
  pointer-events: none;
  /* SVG has an intrinsic 300x150 default; without this the heart sheet
     silently refuses to fill the viewport. */
  display: block;
}

.hearts {
  z-index: -1;
  /*
   * Low enough to be texture rather than pattern. At .40 with a 53px cell
   * this read as gift wrap: a rigid, uniform grid that buried the shader
   * completely and competed with the lockup. Bigger cell, fainter ink.
   */
  opacity: .26;
  /* Densest at the top where the hero is open, quieting as the eye moves
     down. The section surfaces in page.css continue the fade — between
     them the texture never stops, it only gets softer. */
  mask-image: linear-gradient(to bottom, #000 0%, rgba(0, 0, 0, .74) 48%, rgba(0, 0, 0, .42) 100%);
}

.hearts rect {
  transform: scale(var(--field-scale, 1.55));
  transform-origin: center;
}


@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
}
