/* ============================================================
   Meryl Mathews — single-screen cover page
   Tokens first; everything below is driven from them.
   ============================================================ */

:root {
  /* Brand — carried over from the Squarespace original /7C2D1C/ */
  --brick:        #8d0f0f;
  --brick-deep:   #4A0E17; 
  --brick-soft:   #C0674D;
  --brick-tint:   rgba(154, 58, 37, .08);

  /* Neutrals */
  --ink:          #241C19;
  --ink-soft:     #4A3E39;
  --muted:        #6E615B;
  --panel:        #F6F3F1;
  --panel-edge:   rgba(154, 58, 37, .55);
  --cream:        #FFFCFA;
  --wash-top:     #AFA3A1;
  --wash-mid:     #D5CDCB;
  --wash-bot:     #FFFFFF;

  /* Type — three roles, two voices
     --font         UI and the tagline (Poppins, from Google)
     --font-display the name (Inter Display, self-hosted, see fonts/)
     --font-serif   the bio (Source Serif 4, from Google)

     Swaps for the serif, all on the same Google request: "Merriweather",
     "Lora", "Newsreader", "Spectral". Change it here AND in the <link>,
     since the request only carries the families it names. */
  --font: "Poppins", ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --font-display: "InterDisplay", ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --font-serif: "Source Serif 4", "Lora", Georgia, "Times New Roman", Times, serif;

  /* The two name weights. Both sit on one continuous axis in the variable
     font, so these are free to be any value from 100 to 900. */
  --wt-first: 200;
  --wt-last:  400;

  /* Geometry */
  --r-sm: 10px;
  --r-md: 16px;
  --r-lg: 24px;
  --r-pill: 999px;
  --gutter: clamp(20px, 4vw, 56px);

  /* Headshot. It is out of flow above 860px, so nothing about the content
     column feeds back into its size: --photo-h is the only knob, the width
     follows from the intrinsic ratio, and --photo-left places it from the
     left edge of the viewport rather than from the grid.
     --photo-left may go negative on purpose; see the tablet block. */
  --photo-h: min(77dvh, 960px);
  --photo-w: 1400;
  --photo-ht: 1703;
  --photo-width: calc(var(--photo-h) * var(--photo-w) / var(--photo-ht));
  --photo-left: max(16px, calc(55vw - 600px));

  /* Width of the text column once the photo stops reserving space for it. */
  --col-w: 45vw;

  /* Depth */
  --lift-1: 0 1px 2px rgba(36, 28, 25, .06), 0 6px 18px rgba(36, 28, 25, .07);
  --lift-2: 0 2px 4px rgba(36, 28, 25, .07), 0 18px 44px rgba(36, 28, 25, .13);

  /* Motion */
  --ease: cubic-bezier(.22, .61, .36, 1);
  --fast: 160ms;
  --slow: 420ms;
}

/* Inter v4, SIL OFL 1.1. Subset to Latin, pinned to the Display optical
   size and converted to WOFF2; fonts/NOTICE.md records exactly what was
   changed, and fonts/LICENSE.txt has to stay beside the file.

   Because opsz is baked in at 32, there is no font-variation-settings on
   .card__name. Setting "opsz" there now would do nothing, and setting
   "wght" there would take the weight away from font-weight and flatten
   the two name spans into one. The weight axis is still live, which is
   what --wt-first and --wt-last drive. */
@font-face {
  font-family: "InterDisplay";
  font-style: normal;
  font-weight: 100 900;          /* the axis survived subsetting */
  font-display: swap;
  src: url("../fonts/InterDisplay-latin.woff2") format("woff2");
}

/* ─── Reset ────────────────────────────────────────────────── */

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

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

body {
  margin: 0;
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  font-family: var(--font);
  font-weight: 400;
  color: var(--ink);
  background: var(--wash-bot);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

img { display: block; max-width: 100%; height: auto; }
ul  { list-style: none; margin: 0; padding: 0; }
a   { color: inherit; text-decoration: none; }

:focus-visible {
  outline: 2px solid var(--brick);
  outline-offset: 3px;
  border-radius: 4px;
}

.skip-link {
  position: absolute; left: 12px; top: -60px; z-index: 100;
  background: var(--brick); color: #fff;
  padding: 10px 18px; border-radius: var(--r-pill);
  font-size: .875rem; font-weight: 500;
  transition: top var(--fast) var(--ease);
}
.skip-link:focus { top: 12px; }

/* Sprite icons inherit surrounding colour via currentColor. */
.ico { width: 19px; height: 19px; flex: none; color: currentColor; }
.ico--sm { width: 15px; height: 15px; }

/* ============================================================
   Hero — the entire page
   ============================================================ */

.hero {
  flex: 1;
  position: relative;
  display: flex;
  /* The photo no longer stretches this box, so without a floor the hero can
     end up shorter than the headshot and crop it through the head. */
  min-height: var(--photo-h);
  overflow: hidden;
  padding-top: clamp(11px, 2vh, 22px);
  background:
    radial-gradient(120% 78% at 22% 0%, rgba(154, 58, 37, .12) 0%, transparent 62%),
    linear-gradient(180deg,
      var(--wash-top)  0%,
      var(--wash-mid) 34%,
      #EFEBE9 62%,
      var(--wash-bot) 90%);
}

.hero__inner {
  position: relative;
  z-index: 1;              /* lifts the whole block off the hero background */
  display: flex;
  width: min(1180px, 100%);
  margin-inline: auto;
  padding-inline: var(--gutter);
  flex: 1;
}

/* — Photo — */
.hero__photo {
  position: absolute;
  left: var(--photo-left);
  bottom: 0;
  z-index: 0;
  width: var(--photo-width);
  /* It is allowed to sit under the text column at narrower widths, so it
     must not intercept clicks meant for the card or the contact links. */
  pointer-events: none;
}
.hero__photo picture { display: block; }
.hero__photo img {
  width: 100%;
  /* height: auto is required, or the img height attribute wins. */
  height: auto;
  aspect-ratio: var(--photo-w) / var(--photo-ht);
  /* Meets the bottom edge of the screen the way the original did. */
  margin-bottom: -1px;
  filter: drop-shadow(0 22px 40px rgba(36, 28, 25, .22));
}
.hero__glow {
  position: absolute;
  left: 50%; bottom: 4%;
  width: 92%; aspect-ratio: 1;
  transform: translateX(-50%);
  border-radius: 50%;
  background: radial-gradient(circle,
    rgba(255, 255, 255, .72) 0%,
    rgba(255, 255, 255, .26) 44%,
    transparent 70%);
  pointer-events: none;
}

/* — Right column: bio card, then contact card — */
.hero__col {
  min-width: 0;
  width: min(var(--col-w), 100%);
  margin-inline-start: auto;      /* pinned right; the photo owns the left */
  align-self: center;
  display: flex;
  flex-direction: column;
  gap: clamp(0px, 0vw, 0px);
  margin-bottom: clamp(24px, 6vh, 72px);
  margin-left: min(var(--col-w), 45%);

}

/* The headshot is a sibling of these two inside .hero__col, and z-index on
   the shared ancestor cannot separate them. Left to tie-break on DOM order
   the photo wins, because it comes after the card; these two rules are what
   actually keep the copy above the overlap. */
.card,
.cc {
  position: relative;
  z-index: 1;
}

.card {
  min-width: 0;
  padding: clamp(22px, 2.4vw, 32px) clamp(24px, 2.2vw, 26px);
  /*background: linear-gradient(180deg, var(--panel) 0%, var(--cream) 58%);
  border: 1px solid var(--panel-edge); 
    box-shadow: var(--lift-2)
  border-radius: var(--r-lg); ;*/
	backdrop-filter:blur(11px);


}

.card__name {
  margin: 0;
  font-family: var(--font-display);
  font-size: clamp(3.45rem, 2.73rem + 4.1vw, 4.735rem);
  line-height: 1.0;
  letter-spacing: -.02em;
  text-align: center;
  text-wrap: balance;
}
.card__name-first { color: var(--ink-soft); font-weight: var(--wt-first); }
.card__name-last  { color: var(--ink);      font-weight: var(--wt-last); }

.card__tagline {
  margin: clamp(10px, 1.4vw, 18px) 0 0;
  text-align: center;
  font-family:var(--font-serif);
  font-size: clamp(1.42rem, .9rem + .75vw, 1.72rem);
  font-weight: 400;
  color: var(--brick);
  letter-spacing: .005em;
}
.card__tagline span::before,
.card__tagline span::after { content: "\2013"; opacity: .85; }

.card__bio {
  margin: clamp(20px, 2.6vw, 32px) 0 0;
  /* Newlines in the content come through as paragraph breaks;
     no markup is ever accepted here. */
  white-space: pre-line;
  font-family: var(--font-display);
  /* A serif reads larger than Poppins at the same size, so this sits a
     touch below the old value and carries more leading. */
  font-size: clamp(.977rem, 1.087rem + .26vw, 1.148rem);
  line-height: 1.48;
  letter-spacing: .002em;
  color: var(--ink-soft);
}
.card__bio::before {
  content: "";
  display: block;
  width: 46px; height: 2px;
  margin: 0 auto clamp(18px, 2.2vw, 26px);
  background: linear-gradient(90deg, var(--brick), var(--brick-soft));
  border-radius: 2px;
}


/* ============================================================
   Contact card — an engraved calling card under the bio
   ============================================================ */

.cc {
  padding: 7px;                 /* the gap between the two rules */
  background: var(--cream);
  border: 1px solid var(--brick);
  border-radius: 4px;           /* print stock barely rounds */
  box-shadow: var(--lift-2);
}

.cc__plate {
  border: 1px solid rgba(154, 58, 37, .28);
  border-radius: 2px;
  padding: clamp(16px, 2.6vw, 22px) clamp(12px, 2vw, 16px) clamp(10px, 1.6vw, 14px);
}

.cc__eyebrow {
  display: flex; align-items: center; gap: 14px;
  margin: 0 0 clamp(14px, 2.2vw, 20px);
  font-size: .877rem; font-weight: 600; letter-spacing: .28em;
  text-transform: uppercase;
  color: var(--brick);
}
.cc__eyebrow::before, .cc__eyebrow::after {
  content: ""; flex: 1; height: 1px; background: rgba(154, 58, 37, .3);
}

.cc__row { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); }

/* The renderer sets data-count rather than an inline grid-template, so
   the stack query below can still win. :where keeps these at class
   specificity so source order decides, not the attribute selector. */
.cc__row:where([data-count="1"]) { grid-template-columns: minmax(0, 1fr); }
.cc__row:where([data-count="2"]) { grid-template-columns: repeat(2, minmax(0, 1fr)); }
/* Four across, not 2x2. A 2x2 grid adds ~100px to the contact card, which
   clips under the 95dvh cap at 1280x800 and 980x800; four in a row keeps the
   card at the same height as three. The trade is that the detail line
   ellipsizes below ~1100px wide when the text is long. */
.cc__row:where([data-count="4"]) { grid-template-columns: repeat(4, minmax(0, 1fr)); }

/* The rule lives on the cell, not on the link: an inset shadow on a
   rounded box follows its radius and bows at the ends. */
.cc__cell + .cc__cell { border-left: 1px solid rgba(154, 58, 37, .18); }

/* The vCard is the one action worth weighting, so its cell carries a
   tint. It sits on the cell rather than the link so it reaches the
   hairlines; the link's own hover tint then layers on top of it,
   which is why no separate emphasis-hover rule is needed. */
.cc__cell--emph {
  background: linear-gradient(180deg,
    rgba(154, 58, 37, .06) 0%, rgba(154, 58, 37, .13) 100%);
}
.cc__cell--emph .cc__label { color: var(--brick); }
.cc__cell--emph .cc__value { color: var(--ink-soft); }

.cc__item {
  display: flex; flex-direction: column; align-items: center; gap: 9px;
  height: 100%;
  padding: 14px 8px 16px;
  border-radius: 2px;           /* engraved cells read as rectangles */
  color: var(--ink-soft);
  text-align: center;
  transition: background var(--fast) var(--ease), color var(--fast) var(--ease);
}
.cc__item .ico { color: var(--brick); width: 32px; height: 32px; }

.cc__text {
  display: flex; flex-direction: column; gap: 3px;
  min-width: 0; max-width: 100%;
}
.cc__label {
  font-size: .82rem; font-weight: 500;
  letter-spacing: .06em; text-transform: uppercase;
}
.cc__value {
  font-size: .72rem; color: var(--muted); letter-spacing: .01em;
  max-width: 100%;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

.cc__item:hover { background: var(--brick-tint); color: var(--brick); }
.cc__item:focus-visible { outline: 2px solid var(--brick); outline-offset: -2px; }

/* ============================================================
   Responsive
   ============================================================ */

/* The engraved columns stack into rows once three no longer fit. */
@media (max-width: 720px) {
  .cc__row { grid-template-columns: minmax(0, 1fr); }
  .cc__cell + .cc__cell {
    border-left: 0;
    border-top: 1px solid rgba(154, 58, 37, .18);
  }
  .cc__item {
    flex-direction: row; justify-content: flex-start;
    gap: 14px; text-align: left; padding: 14px 12px;
  }
  .cc__text { flex: 1; }
}

/* Tablet. The column stays pinned right at a fixed width while the photo
   keeps its own viewport-driven size, so the two converge and the headshot's
   right edge tucks under the card. --photo-left goes negative to keep the
   overlap on her shoulder rather than her face; the card paints over it. */
@media (max-width: 1180px) {
  :root {
    --photo-h: min(72dvh, 760px);
    --photo-left: clamp(-130px, calc(46vw - 480px), 16px);
    --col-w: 600px;
  }
  .card { padding: clamp(22px, 3vw, 34px); }
}

@media (max-width: 1000px) {
  :root {
    --photo-h: min(66dvh, 680px);
    --photo-left: clamp(-190px, calc(44vw - 470px), -20px);
    --col-w: 540px;
  }
}

/* Phone and small tablet: the headshot rejoins the flow. Its DOM position
   is already between the bio card and the contact box, so it simply lands
   there once position is reset. */
@media (max-width: 860px) {
  :root { --photo-h: min(46dvh, 460px); }

  .hero { min-height: 0; }        /* the floor was only for the absolute case */
  .hero__inner { align-items: start; }
  .hero__col {
    width: 100%;
    max-width: 640px;
    margin-inline: auto;
    align-self: start;
    margin-bottom: clamp(16px, 3vw, 28px);
    flex-direction: column-reverse;
  }
  .hero__photo {
    position: static;
    width: var(--photo-width);
    min-width: 100%;
    margin-inline: auto;
    pointer-events: auto;
  }
  /* In flow it is a sibling with real height, so the -1px that let it meet
     the footer would just pull the contact box up against it. */
  .hero__photo img { margin-bottom: 0; }
  /* Absolutely positioned, the cutout runs off the bottom of the hero and
     reads as standing in frame. In flow it just stops, so the source's flat
     waistline shows as a hard horizontal edge; fade it out instead. The
     mask goes on the wrapper, not the img, so it takes the drop-shadow with
     it rather than leaving a shadow under nothing. */
  .hero__photo {
    -webkit-mask-image: linear-gradient(180deg, #000 78%, transparent 99%);
    mask-image: linear-gradient(180deg, #000 78%, transparent 99%);
  }
}

@media (max-width: 480px) {
  .card__name { font-size: clamp(2.775rem, 1.3rem + 4.4vw, 3.7rem); }
}

/* ── The 95dvh cap ───────────────────────────────────────────
   Capping the hero shows a band of the footer's dark accent on the first
   screen. It is a clip, not a fit: .hero has overflow: hidden, so anything
   past the cap is gone rather than scrollable. Both guards below exist to
   make sure nothing ever is.

   min-width 861px  — below this the layout stacks and the column runs to
                      ~1200px. The cap would swallow the headshot and the
                      whole contact box with no way to reach them.
   min-height 800px — below this the column cannot shrink far enough and the
                      cap cuts into the contact card. The hero sizes itself
                      instead, so the dark band simply does not appear on
                      short windows. That is the intended trade.

   The padding and margin trims are what buy the room; without them this
   clips at 1440x800, 1366x800 and 1280x800. Verified across 24 viewport
   sizes from 1920x1080 down to 864x780: no clipping at the top of the card,
   the bottom of the contact box, or the top of the headshot. */
@media (min-width: 861px) and (min-height: 800px) {
  .hero {
    /* Both bounds, not `height`. .hero is a flex item with `flex: 1`, which
       sets flex-basis: 0 — and flex-basis beats `height` on the main axis,
       so `height: 95dvh` is silently ignored here. Pinning min and max to
       the same value is what actually fixes the size.
       Max alone is not enough either: the trims below can leave the hero
       shorter than the cap, and the dark band then wanders between 1% and
       21% of the viewport depending on size. Both bounds make it 5% flat.
       The base min-height: var(--photo-h) is overridden but never mattered,
       since --photo-h tops out at 80dvh. */
    min-height: 85dvh;
    max-height: 95dvh;
    padding-top: clamp(11px, 4vh, 44px);
  }
  .hero__col { margin-bottom: clamp(8px, 2vh, 44px); }
}

/* In the narrow-column band the bio runs to more lines, so the same cap
   needs more reclaimed before it stops cutting the contact card. */
@media (min-width: 861px) and (max-width: 1180px)
   and (min-height: 800px) and (max-height: 920px) {
  .card { padding: clamp(16px, 2.2vw, 26px);  }
  .card__bio { line-height: 1.58; }
  .hero__col { gap: 12px; }
}

/* Short desktop windows: shrink the headshot rather than clip the card. */
@media (min-width: 861px) and (max-height: 760px) {
  :root { --photo-h: min(74dvh, 640px); }
  .hero__col { margin-bottom: 16px; gap: 12px; }
  .card__bio { line-height: 1.6; }
}

/* ============================================================
   Entrance motion
   ============================================================ */

@media (prefers-reduced-motion: no-preference) {
  .card, .cc, .hero__photo {
    animation: rise var(--slow) var(--ease) both;
  }
  .hero__photo { animation-delay: 60ms;  }
  .card        { animation-delay: 120ms; }
  .cc          { animation-delay: 200ms; }

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

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    transition-duration: .01ms !important;
  }
}

@media print {
  .hero { background: none; }
  .cc { box-shadow: none; }
}
