/* ===========================================================================
   BASE — reset, surfaces, textures, metal, and the shared components
   ---------------------------------------------------------------------------
   Textures are generated with SVG feTurbulence rather than shipped as images:
   they are resolution-independent, cost about 400 bytes each, and never go
   soft on a high-DPI phone the way a tiling JPEG does.
   =========================================================================== */

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

* {
  margin: 0;
}

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

body {
  min-height: 100vh;
  min-height: 100svh;
  font-family: var(--font-body);
  font-size: var(--step-0);
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

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

button,
input,
textarea,
select {
  font: inherit;
  color: inherit;
}

h1,
h2,
h3,
h4 {
  font-weight: 400;
  line-height: 1.15;
  text-wrap: balance;
}

p {
  text-wrap: pretty;
}

/* --- Surfaces ------------------------------------------------------------ */

/* Rich Black ground.

   Every layer is a plain rgba() over #0B0B0B — no blend modes. The previous
   version soft-light-blended grey turbulence at 0.5 opacity, which lifted the
   whole field off black into grey and lost the brand colour entirely. Grain on
   a near-black surface has to be light to be visible at all, so it is light —
   but at 5% rather than 50%.

   The layers are fixed rather than absolute so the light stays pooled where
   the mark is, instead of scrolling away with the content. */
.surface-dark {
  position: relative;
  background-color: var(--black);
  color: var(--ivory);
  isolation: isolate;
}

/* Leather grain. 5% over #0B0B0B lands around #121212 — felt, not seen. */
.surface-dark::before {
  content: '';
  position: fixed;
  inset: 0;
  z-index: -3;
  pointer-events: none;
  opacity: 0.05;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='200' height='200'%3E%3Cfilter id='p'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.75' numOctaves='4' seed='7'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='200' height='200' filter='url(%23p)'/%3E%3C/svg%3E");
  background-size: 170px 170px;
}

/* The light: a warm pool where the mark sits, falling off to near-black at the
   corners. One layer, two gradients, both plain alpha. */
.surface-dark::after {
  content: '';
  position: fixed;
  inset: 0;
  z-index: -2;
  pointer-events: none;
  background:
    radial-gradient(58% 42% at 50% 44%, rgba(217, 106, 24, 0.1) 0%, rgba(217, 106, 24, 0.035) 48%, transparent 74%),
    radial-gradient(115% 95% at 50% 46%, transparent 42%, rgba(0, 0, 0, 0.6) 100%);
}

/* Antique eggshell parchment. */
.surface-parchment {
  position: relative;
  background-color: var(--ivory);
  color: var(--espresso);
  isolation: isolate;
}

.surface-parchment::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -2;
  pointer-events: none;
  opacity: 0.55;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='300' height='300'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.045' numOctaves='5' seed='3'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='300' height='300' filter='url(%23g)' opacity='0.35'/%3E%3C/svg%3E"),
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='f'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='3' seed='11'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='120' height='120' filter='url(%23f)' opacity='0.3'/%3E%3C/svg%3E");
  background-size: 320px 320px, 110px 110px;
  mix-blend-mode: multiply;
}

.surface-parchment::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  /* Age at the edges, the way an old sheet darkens where it was handled. */
  background: radial-gradient(115% 95% at 50% 45%, transparent 52%, rgba(57, 35, 23, 0.13) 100%);
}

/* --- Metal --------------------------------------------------------------- */

/* Mirror-copper foil with a beveled highlight. The text-shadow underneath
   gives the letterform a struck edge; without it the gradient reads flat. */
.foil {
  background-image: var(--foil);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  /* Fallback for anything that can't clip a background to text. */
  -webkit-text-fill-color: transparent;
}

/* The same foil on the parchment ground. --foil's near-white crest vanishes
   against ivory; this keeps the bevel but never goes lighter than Copper
   Orange, so the letterform holds its shape. */
.foil--dark {
  background-image: var(--foil-dark);
}

@supports not ((background-clip: text) or (-webkit-background-clip: text)) {
  .foil {
    color: var(--copper);
    -webkit-text-fill-color: var(--copper);
    background-image: none;
  }

  .foil--dark {
    color: var(--copper-text);
    -webkit-text-fill-color: var(--copper-text);
  }
}

/* A struck copper rule — used to separate sections. */
.rule {
  height: 1px;
  border: 0;
  background-image: var(--foil-rule);
  opacity: 0.85;
}

.rule--double {
  height: 5px;
  background:
    linear-gradient(90deg, transparent, var(--copper-a55), transparent) 0 0 / 100% 1px no-repeat,
    linear-gradient(90deg, transparent, var(--copper-a55), transparent) 0 100% / 100% 1px no-repeat;
}

/* --- Ornament ------------------------------------------------------------ */

/* A centred rule interrupted by an ornament — the classic engraved divider. */
.divider {
  display: flex;
  align-items: center;
  gap: var(--sp-4);
  width: 100%;
}

.divider::before,
.divider::after {
  content: '';
  flex: 1;
  height: 1px;
  background-image: var(--foil-rule);
  opacity: 0.75;
}

.divider__mark {
  flex: none;
  color: var(--copper);
  line-height: 1;
}

/* --- Type utilities ------------------------------------------------------ */
.display {
  font-family: var(--font-display);
  letter-spacing: var(--track-display);
  text-transform: uppercase;
}

.script {
  font-family: var(--font-script);
  font-weight: 400;
  letter-spacing: 0.01em;
  /* Pinyon and Bickham both sit high in the em box; nudge the baseline so a
     script line optically centres against caps beside it. */
  line-height: 1.35;
}

.smallcaps {
  font-family: var(--font-secondary);
  letter-spacing: var(--track-secondary);
  text-transform: uppercase;
}

.motto {
  font-family: var(--font-secondary);
  letter-spacing: var(--track-wide);
  text-transform: uppercase;
  font-size: var(--step--1);
}

/* --- Frames --------------------------------------------------------------
   Triple-line ornate border. Built from stacked rings rather than nested
   elements so any block can take it with one class. The gap rings use the
   surface colour, which is why there are two variants. */
.frame {
  position: relative;
  border: 2px solid var(--copper-burnished);
}

.frame--parchment {
  box-shadow:
    inset 0 0 0 1px var(--ivory-shade),
    0 0 0 3px var(--ivory),
    0 0 0 4px var(--copper),
    0 0 0 7px var(--ivory),
    0 0 0 8px var(--copper-burnished),
    0 2px 24px rgba(57, 35, 23, 0.16);
}

.frame--dark {
  border-color: var(--copper-burnished);
  box-shadow:
    inset 0 0 0 1px rgba(217, 106, 24, 0.25),
    0 0 0 3px var(--black),
    0 0 0 4px var(--copper-burnished),
    0 0 0 7px var(--black),
    0 0 0 8px rgba(168, 78, 19, 0.55);
}

/* --- Buttons -------------------------------------------------------------
   Copper Orange with black borders, a subtle bevel, and Warm Ivory text —
   exactly as the brand specifies.

   Ivory on Copper Orange is 2.8:1. That is the brand's chosen combination, so
   the type does the work instead: 600 weight, wide tracking, and a dark rim
   shadow that separates every stroke from the copper behind it. Between the
   rim and the tracking the label holds up far better than the raw number
   suggests, but it is a knowing trade. */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-7);
  border: 2px solid var(--black);
  border-radius: 2px;
  background-image: var(--copper-face);
  color: var(--ivory);
  font-family: var(--font-secondary);
  font-size: var(--step-0);
  font-weight: 600;
  letter-spacing: var(--track-secondary);
  text-indent: var(--track-secondary);
  text-transform: uppercase;
  text-decoration: none;
  cursor: pointer;
  /* The rim. Tight and dark on all four sides so the ivory strokes read as
     struck into the metal rather than floating on it. */
  text-shadow:
    0 1px 1px rgba(43, 20, 6, 0.85),
    0 -1px 1px rgba(43, 20, 6, 0.55),
    1px 0 1px rgba(43, 20, 6, 0.55),
    -1px 0 1px rgba(43, 20, 6, 0.55);
  box-shadow:
    inset 0 1px 0 rgba(255, 234, 205, 0.6),
    inset 0 -2px 0 rgba(67, 32, 10, 0.42),
    0 2px 6px rgba(11, 11, 11, 0.3);
  transition: filter var(--fade), box-shadow var(--fade), transform var(--fade);
}

.btn:hover {
  filter: brightness(1.06);
  transform: translateY(-1px);
  box-shadow:
    inset 0 1px 0 rgba(255, 234, 205, 0.75),
    inset 0 -2px 0 rgba(67, 32, 10, 0.42),
    0 4px 12px rgba(11, 11, 11, 0.42);
}

.btn:active {
  transform: translateY(1px);
  box-shadow:
    inset 0 2px 4px rgba(67, 32, 10, 0.45),
    0 1px 3px rgba(11, 11, 11, 0.3);
}

.btn--quiet {
  background-image: none;
  background-color: transparent;
  border-color: var(--copper-burnished);
  color: var(--copper);
  /* No copper behind it, so nothing to lift the type off. */
  text-shadow: none;
  box-shadow: none;
}

.btn--quiet:hover {
  background-color: var(--copper-a12);
  filter: none;
  box-shadow: none;
}

/* --- Links --------------------------------------------------------------- */
a:not(.btn) {
  color: var(--copper-burnished);
  text-underline-offset: 0.22em;
  text-decoration-thickness: 1px;
  transition: color var(--fade);
}

a:not(.btn):hover {
  color: var(--copper);
}

.surface-dark a:not(.btn) {
  color: var(--copper);
}

.surface-dark a:not(.btn):hover {
  color: var(--copper-highlight);
}

/* --- Focus ---------------------------------------------------------------
   Visible on both grounds. Never removed — the survey has to be completable
   from the keyboard alone. */
:focus-visible {
  /* Copper Orange is only 2.8:1 on ivory; the focus ring has to clear 3:1
     (WCAG 1.4.11) or a keyboard user loses their place. */
  outline: 2px solid var(--copper-text);
  outline-offset: 3px;
  border-radius: 1px;
}

.surface-dark :focus-visible {
  outline-color: var(--copper-highlight);
}

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

.skip-link {
  position: absolute;
  top: var(--sp-3);
  left: var(--sp-3);
  z-index: 100;
  padding: var(--sp-2) var(--sp-4);
  background: var(--ivory);
  color: var(--espresso);
  transform: translateY(-200%);
  transition: transform var(--fade);
}

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

/* The honeypot. Hidden from sight and from assistive tech, but present in the
   DOM for anything that fills every input it finds. */
.decoy {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
  opacity: 0;
}

/* --- Motion --------------------------------------------------------------
   The site's entire animation vocabulary is two things: a fade-up on first
   paint, and a fade-up as a section scrolls into view. Nothing loops, nothing
   bounces, nothing moves more than a few pixels. */

@keyframes rise {
  from {
    opacity: 0;
    transform: translateY(10px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

.rise {
  animation: rise var(--fade-slow) both;
}

/* Scroll reveal. Only hidden when JavaScript is present to un-hide it — the
   `js` class is set by an inline script in <head>, so a failed or blocked
   script leaves the page fully visible rather than blank. */
.js [data-reveal] {
  opacity: 0;
  transform: translateY(8px);
  transition:
    opacity 520ms var(--ease),
    transform 520ms var(--ease);
  /* Hint the compositor, then let it go — a permanent will-change on every
     section costs more than it saves. */
  will-change: opacity, transform;
}

.js [data-reveal].is-revealed {
  opacity: 1;
  transform: none;
  will-change: auto;
}

/* A gentle stagger so a run of questions arrives in sequence rather than as
   one block. Capped at five steps; beyond that it starts to feel like waiting. */
.js [data-reveal][data-reveal-step='1'] { transition-delay: 60ms; }
.js [data-reveal][data-reveal-step='2'] { transition-delay: 120ms; }
.js [data-reveal][data-reveal-step='3'] { transition-delay: 180ms; }
.js [data-reveal][data-reveal-step='4'] { transition-delay: 240ms; }

@media (prefers-reduced-motion: reduce) {
  .rise {
    animation: none;
  }

  .js [data-reveal] {
    opacity: 1;
    transform: none;
    transition: none;
  }
}
