/* ---------------------------------------------------------------
   Eternal Opera — holding page
   Warm paper, ink, and one photograph. No accent colour.
   --------------------------------------------------------------- */

/* Helsa Display (ParaType) is a licensed typeface, so it is not shipped in
   this repo. It is used automatically on machines that have it installed.
   To serve it to every visitor, drop the licensed webfont into
   /public/fonts and uncomment the url() source below — nothing else
   changes. See public/fonts/README.md. */
@font-face {
  font-family: 'Helsa Display';
  src:
    /* url('/fonts/HelsaDisplay-Regular.woff2') format('woff2'), */
    local('Helsa Display'),
    local('HelsaDisplay-Regular'),
    local('Helsa Display Regular');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

:root {
  --paper: #f3f1ec;
  --ink: #171511;
  --ink-soft: #6d675c;

  --font-display: 'Helsa Display', 'Cormorant Garamond', 'Cormorant', 'Times New Roman', serif;
  --frame-inset: clamp(11px, 2.1vw, 26px);
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
}

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

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

body {
  margin: 0;
  min-height: 100vh;
  min-height: 100svh;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-display);
  font-synthesis: none;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
}

/* --- stage -----------------------------------------------------
   Nothing between <body> and the photograph may create a stacking
   context, or the multiply blend below stops seeing the paper.
   That rules out transform, opacity and filter on .stage/.plate. */

.stage {
  display: grid;
  place-items: center;
  min-height: 100vh;
  min-height: 100svh;
  padding: calc(var(--frame-inset) * 2);
}

/* The portrait was shot on a blank studio backdrop, so multiplying it
   against the paper dissolves the edges of the photograph and leaves
   only the figure and their shadows standing on the page. */
.plate {
  position: relative;
  margin: 0;
}

.plate img {
  display: block;
  height: min(84vh, 860px);
  height: min(84svh, 860px);
  width: auto;
  mix-blend-mode: multiply;
}

/* Paper scrim that lifts away on load: the figure develops onto the
   page. Fading this instead of the photograph keeps the blend intact. */
.plate::after {
  content: '';
  position: absolute;
  inset: -1px;
  background: var(--paper);
  pointer-events: none;
  animation: develop 1400ms var(--ease-out) both;
}

/* --- type ------------------------------------------------------
   Anchored to the figure rather than to the viewport, so the wordmark
   lands across the bright shirt on every screen shape. 57% is the
   optical middle of the photograph's clean band: below the dark hair,
   hands and chin shadow, above the black trousers. */

.billing {
  position: absolute;
  top: 57%;
  left: 50%;
  z-index: 1;
  width: max-content;
  max-width: 88vw;
  transform: translate(-50%, -50%);
  text-align: center;
}

.wordmark {
  margin: 0;
  font-weight: 300;
  /* The svh term keeps the wordmark in proportion to the figure on
     short, wide viewports instead of crowding it off the shirt. */
  font-size: clamp(3rem, min(13vw, 21vh), 11.5rem);
  font-size: clamp(3rem, min(13vw, 21svh), 11.5rem);
  line-height: 0.88;
  letter-spacing: -0.015em;
  animation: rise 1250ms var(--ease-out) 420ms both;
}

.wordmark span {
  display: inline-block;
}

.notice {
  margin: clamp(1.5rem, 3.4vh, 2.8rem) 0 0;
  font-size: clamp(0.58rem, 1.4vw, 0.7rem);
  letter-spacing: 0.42em;
  text-indent: 0.21em;
  text-transform: uppercase;
  color: var(--ink-soft);
  animation: rise 1100ms var(--ease-out) 820ms both;
}

.rule {
  display: block;
  width: 42px;
  height: 1px;
  margin: 0 auto clamp(0.9rem, 2vh, 1.35rem);
  background: currentColor;
  opacity: 0.4;
}

/* --- frame + grain --------------------------------------------- */

.frame {
  position: fixed;
  inset: var(--frame-inset);
  z-index: 3;
  border: 1px solid rgb(23 21 17 / 0.13);
  pointer-events: none;
  animation: veil 900ms ease-out 1100ms both;
}

.year {
  position: absolute;
  right: 1.1rem;
  bottom: -0.66em;
  padding: 0 0.7rem;
  background: var(--paper);
  font-size: 0.6rem;
  letter-spacing: 0.34em;
  color: var(--ink-soft);
}

.grain {
  position: fixed;
  inset: 0;
  z-index: 4;
  opacity: 0.055;
  mix-blend-mode: multiply;
  pointer-events: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* --- motion ---------------------------------------------------- */

@keyframes develop {
  from {
    opacity: 1;
  }
  to {
    opacity: 0;
  }
}

@keyframes rise {
  from {
    opacity: 0;
    transform: translateY(12px);
    filter: blur(5px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
    filter: blur(0);
  }
}

@keyframes veil {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

/* --- narrow viewports ------------------------------------------ */

@media (max-width: 640px) {
  .plate img {
    height: auto;
    width: min(76vw, 400px);
  }

  .year {
    right: 0.8rem;
    font-size: 0.55rem;
  }
}

@media (prefers-reduced-motion: reduce) {
  .plate::after,
  .wordmark,
  .notice,
  .frame {
    animation: none;
  }

  .plate::after {
    display: none;
  }
}
