/* ==========================================================================
   Milo & Mol — Base: reset, typography, shared primitives
   ========================================================================== */

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: 6.5rem; /* clears the sticky header on anchor jumps */
}

body, h1, h2, h3, h4, p, figure, blockquote, dl, dd, ul, ol {
  margin: 0;
  padding: 0;
}

ul[class], ol[class] { list-style: none; }

img, picture, svg, video {
  display: block;
  max-width: 100%;
  height: auto;
}

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

/* --- Page ----------------------------------------------------------------- */
body {
  position: relative;
  min-height: 100vh;
  background-color: var(--bg-page);
  color: var(--text-primary);
  font-family: var(--font-body);
  font-size: var(--text-base);
  font-weight: 350;
  line-height: var(--leading-body);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
}

/* Linen grain across the whole page. The logo sits on a linen card, so the
   site should feel printed rather than screen-flat. */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: var(--z-texture);
  background-image: var(--texture-linen);
  opacity: 0.32;
  mix-blend-mode: multiply;
  pointer-events: none;
}

main { position: relative; z-index: var(--z-content); }

/* --- Typography -----------------------------------------------------------
   Fraunces is variable. SOFT rounds the terminals and WONK swaps in the
   hand-cut alternates, which is what gives the headings their warmth.     */
h1, h2, h3, h4 {
  font-family: var(--font-display);
  font-weight: 500;
  font-variation-settings: "SOFT" 40, "WONK" 1;
  line-height: var(--leading-snug);
  letter-spacing: var(--track-tight);
  color: var(--text-primary);
  text-wrap: balance;
}

h1 {
  font-size: var(--text-hero);
  line-height: var(--leading-tight);
  font-variation-settings: "opsz" 144, "SOFT" 48, "WONK" 1;
  font-weight: 400;
}
h2 {
  font-size: var(--text-h2);
  font-variation-settings: "opsz" 96, "SOFT" 44, "WONK" 1;
  font-weight: 400;
}
h3 { font-size: var(--text-h3); }

p { text-wrap: pretty; }

/* Small tracked caps: the recurring label voice across the page. */
.eyebrow {
  display: block;
  font-family: var(--font-body);
  font-size: var(--text-eyebrow);
  font-weight: 500;
  letter-spacing: var(--track-wide);
  text-transform: uppercase;
  color: var(--text-muted);
  margin-bottom: var(--space-sm);
}

.lead {
  font-size: var(--text-lead);
  line-height: 1.62;
  color: var(--text-secondary);
  max-width: var(--measure);
}

.text-measure { max-width: var(--measure); }

a {
  color: var(--accent);
  text-decoration-thickness: 1px;
  text-underline-offset: 0.22em;
  transition: color var(--duration-fast) var(--ease-out-soft);
}
a:hover { color: var(--accent-hover); }

/* --- Focus ---------------------------------------------------------------- */
:focus-visible {
  outline: 2px solid var(--focus-ring);
  outline-offset: 3px;
  border-radius: var(--radius-sm);
}
:focus:not(:focus-visible) { outline: none; }

.skip-link {
  position: absolute;
  top: var(--space-sm);
  left: var(--space-sm);
  z-index: var(--z-skip);
  padding: var(--space-xs) var(--space-md);
  background: var(--c-ink);
  color: var(--text-invert);
  font-size: var(--text-sm);
  letter-spacing: var(--track-mid);
  text-transform: uppercase;
  text-decoration: none;
  transform: translateY(-160%);
  transition: transform var(--duration-normal) var(--ease-out-expo);
}
.skip-link:focus { transform: translateY(0); color: var(--text-invert); }

/* --- Layout primitives ---------------------------------------------------- */
.wrap {
  width: min(100% - (var(--gutter) * 2), var(--width-page));
  margin-inline: auto;
}
.wrap--narrow { width: min(100% - (var(--gutter) * 2), var(--width-narrow)); }

.section {
  position: relative;
  padding-block: var(--space-section);
}
.section--band { background-color: var(--bg-band); }

/* A torn-paper edge where one sheet of the album meets the next, instead of
   a hard colour change. */
.section--deckle-top::before,
.section--deckle-bottom::after {
  content: "";
  position: absolute;
  left: 0;
  width: 100%;
  height: 18px;
  background-image: var(--edge-deckle);
  background-repeat: no-repeat;
  background-size: 100% 100%;
  pointer-events: none;
}
.section--deckle-top::before { top: 0; transform: translateY(-100%); }
.section--deckle-bottom::after { bottom: 0; transform: translateY(100%) scaleY(-1); }

/* --- Section headings -----------------------------------------------------
   Each section is numbered like a plate in a keepsake album. The numeral is
   decorative and hidden from screen readers. */
.section__head { position: relative; margin-bottom: var(--space-xl); }

/* The numeral sits behind the heading text, but must stay in front of the
   section's own background — so it takes z-index 0 and the real content is
   lifted above it, rather than pushing the numeral to -1. */
.section__head > *:not(.section__num) { position: relative; z-index: 1; }

.section__num {
  position: absolute;
  top: -0.78em;
  left: -0.14em;
  z-index: 0;
  font-family: var(--font-display);
  font-size: var(--text-numeral);
  font-weight: 400;
  font-variation-settings: "opsz" 144, "SOFT" 60, "WONK" 1;
  line-height: 1;
  color: var(--c-taupe);
  opacity: 0.17;
  user-select: none;
  pointer-events: none;
}

.section__head--centred {
  text-align: center;
  margin-inline: auto;
  max-width: 44rem;
}
.section__head--centred .lead { margin-inline: auto; }
.section__head--centred .section__num {
  left: 50%;
  transform: translateX(-50%);
}

/* --- Botanical decoration -------------------------------------------------
   Oversized pressed sprigs, set very pale, bleeding off the edges. They are
   the single most characterful thing on the page, so they are placed by
   hand per section rather than repeated on a loop. */
.botanical {
  position: absolute;
  z-index: var(--z-botanical);
  color: var(--c-sage);
  opacity: 0.17;
  pointer-events: none;
  user-select: none;
}
.botanical svg { width: 100%; height: auto; }

.botanical--tl { top: -3rem; left: -7rem; width: min(22rem, 40vw); transform: rotate(-14deg); }
.botanical--tr { top: -2rem; right: -8rem; width: min(26rem, 46vw); transform: rotate(18deg) scaleX(-1); }
.botanical--br { bottom: -5rem; right: -6rem; width: min(20rem, 38vw); transform: rotate(-6deg); }
.botanical--bl { bottom: -4rem; left: -8rem; width: min(24rem, 42vw); transform: rotate(9deg) scaleX(-1); }

@media (max-width: 48rem) {
  .botanical { opacity: 0.11; }
  .botanical--tr, .botanical--br { display: none; }
}

/* --- Botanical rule -------------------------------------------------------
   A hairline interrupted by a small leaf, lifted from the logo sprig. */
.sprig-rule {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-md);
  margin-block: var(--space-lg);
  color: var(--c-sage);
}
.sprig-rule::before,
.sprig-rule::after {
  content: "";
  height: 1px;
  width: min(7rem, 18vw);
  background: linear-gradient(to right, transparent, var(--rule-strong), transparent);
}
.sprig-rule svg { width: 26px; height: auto; flex: none; }

/* --- Buttons -------------------------------------------------------------- */
.btn {
  --btn-bg: var(--accent);
  --btn-fg: var(--c-ivory);
  --btn-bd: var(--accent);
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-xs);
  padding: 0.95em 2.1em;
  background-color: var(--btn-bg);
  color: var(--btn-fg);
  border: 1px solid var(--btn-bd);
  border-radius: var(--radius-sm);
  font-size: var(--text-sm);
  font-weight: 500;
  letter-spacing: var(--track-mid);
  text-transform: uppercase;
  text-decoration: none;
  cursor: pointer;
  overflow: hidden;
  transition: color var(--duration-normal) var(--ease-out-soft),
              border-color var(--duration-normal) var(--ease-out-soft),
              transform var(--duration-fast) var(--ease-out-soft),
              box-shadow var(--duration-normal) var(--ease-out-soft);
}
/* The fill wipes upward from the base rather than simply changing colour. */
.btn::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background-color: var(--accent-hover);
  transform: scaleY(0);
  transform-origin: bottom;
  transition: transform var(--duration-normal) var(--ease-out-expo);
}
.btn:hover::before { transform: scaleY(1); }
.btn:hover {
  color: var(--c-ivory);
  border-color: var(--accent-hover);
  transform: translateY(-2px);
  box-shadow: var(--shadow-md);
}
.btn:active { transform: translateY(0); box-shadow: var(--shadow-sm); }
.btn[disabled] { opacity: 0.55; cursor: not-allowed; transform: none; box-shadow: none; }

.btn--ghost {
  --btn-bg: transparent;
  --btn-fg: var(--c-ink);
  --btn-bd: var(--c-taupe);
}
.btn--ghost::before { background-color: var(--c-ink); }
.btn--ghost:hover { color: var(--c-ivory); border-color: var(--c-ink); }

/* Understated editorial link whose rule wipes away on hover. */
.link-quiet {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2xs);
  font-size: var(--text-sm);
  font-weight: 500;
  letter-spacing: var(--track-mid);
  text-transform: uppercase;
  text-decoration: none;
  color: var(--c-ink);
  min-height: 2.75rem;      /* matches the adjacent button's tap target */
  padding-bottom: 2px;
  background-image: linear-gradient(var(--accent), var(--accent));
  background-repeat: no-repeat;
  background-position: 0 100%;
  background-size: 100% 1px;
  transition: background-size var(--duration-normal) var(--ease-out-expo),
              color var(--duration-fast) var(--ease-out-soft);
}
.link-quiet:hover {
  color: var(--accent);
  background-size: 0% 1px;
  background-position: 100% 100%;
}
.link-quiet svg { transition: transform var(--duration-normal) var(--ease-out-expo); }
.link-quiet:hover svg { transform: translateX(4px); }

/* --- Media frames ---------------------------------------------------------
   Photographs are mounted on the page like prints in an album: a tinted
   card, a hairline inset, and a tight warm shadow. */
.frame {
  position: relative;
  overflow: hidden;
  background-color: var(--c-taupe-soft);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-md);
}
.frame::after {
  content: "";
  position: absolute;
  inset: 0;
  border: 1px solid rgba(47, 61, 36, 0.1);
  border-radius: inherit;
  pointer-events: none;
}
.frame img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform var(--duration-slow) var(--ease-out-expo);
}

/* Mounted slightly off-square, as though laid down by hand. */
.frame--tipped { transform: rotate(-1.1deg); }
.frame--tipped-alt { transform: rotate(0.9deg); }

/* Placeholder shown until real photography is dropped in. */
.frame--placeholder {
  display: grid;
  place-items: center;
  background: linear-gradient(135deg,
    var(--c-sage-soft) 0%, var(--c-taupe-soft) 55%, var(--c-rose-soft) 100%);
}
.frame__note {
  max-width: 22ch;
  padding: var(--space-md);
  text-align: center;
  font-size: var(--text-eyebrow);
  font-weight: 500;
  letter-spacing: var(--track-wide);
  text-transform: uppercase;
  line-height: 1.8;
  color: var(--c-ink);
  opacity: 0.55;
}

/* --- Page-load orchestration ----------------------------------------------
   One well-timed arrival on load beats scattered micro-animations. Children
   of .load-stagger rise in sequence; nothing else animates on first paint. */
@keyframes rise-in {
  from { opacity: 0; transform: translateY(18px); }
  to   { opacity: 1; transform: none; }
}

/* `backwards` fill, and no opacity:0 on the base rule. During the delay the
   element holds the keyframe's start state; once the animation ends it falls
   back to its natural, visible state. So if the animation is throttled,
   blocked or unsupported, the content is simply there — it is never left
   hidden by a reveal that failed to run. */
.load-stagger > * {
  animation: rise-in var(--duration-slow) var(--ease-out-expo) backwards;
}
.load-stagger > *:nth-child(1) { animation-delay: 80ms; }
.load-stagger > *:nth-child(2) { animation-delay: 200ms; }
.load-stagger > *:nth-child(3) { animation-delay: 320ms; }
.load-stagger > *:nth-child(4) { animation-delay: 440ms; }
.load-stagger > *:nth-child(5) { animation-delay: 560ms; }

/* The hero image arrives last and a little slower, settling into place. */
@keyframes settle-in {
  from { opacity: 0; transform: translateY(26px) scale(1.02); }
  to   { opacity: 1; transform: none; }
}
.load-settle {
  animation: settle-in var(--duration-draw) var(--ease-out-expo) 420ms backwards;
}

/* --- Scroll reveal --------------------------------------------------------
   Opacity and transform only, so it stays on the compositor. */
/* Visible by default. JavaScript adds .is-pending only to items that are
   below the fold, so nothing is ever hidden unless something is there to
   bring it back — and with JS off the whole page still reads. */
.reveal {
  transition: opacity var(--duration-slow) var(--ease-out-soft),
              transform var(--duration-slow) var(--ease-out-expo);
}
.reveal.is-pending { opacity: 0; transform: translateY(22px); }

/* The arrival stagger lives here, not in JavaScript. A strict style-src
   blocks writes to element.style, so any JS-applied delay is dropped. */
.reveal:nth-child(1) { transition-delay: 0ms; }
.reveal:nth-child(2) { transition-delay: 90ms; }
.reveal:nth-child(3) { transition-delay: 180ms; }
.reveal:nth-child(4) { transition-delay: 270ms; }
.reveal:nth-child(5) { transition-delay: 360ms; }
.reveal.is-visible { opacity: 1; transform: none; }
/* Tipped frames must keep their rotation when they finish revealing. */
.reveal.is-visible .frame--tipped { transform: rotate(-1.1deg); }
.reveal.is-visible .frame--tipped-alt { transform: rotate(0.9deg); }

/* The decorative SVG sprite. Taken out of flow with a class rather than a
   style attribute, which a strict style-src blocks. */
.sprite { position: absolute; width: 0; height: 0; overflow: hidden; }

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

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
  .reveal, .reveal.is-pending { opacity: 1; transform: none; }
  .load-stagger > *, .load-settle { opacity: 1; animation: none; }
}
