/* GLOBAL STYLES */

/* This should be the same Claude link as in the HTML, just pasting it here in case there's a glitch: https://claude.ai/share/175b4cf1-1bc3-4314-8ffd-82123c0980de */

.site-nav{
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    z-index: 100;
    display: flex;
    justify-content: center;
    gap: 3rem;
    padding: 1rem 2rem;
    background: rgba(245,240,232,0.6);
    backdrop-filter: blur(8px);
    border-bottom: 1px solid rgba(44,36,22,0.8);
    opacity: 0;
    transform: translateY(-100);
    transition: opacity 0.5s ease, transform 0.5s ease;
    pointer-events: none;
}

.site-nav.visible{
    opacity: 1;
    transform: translateY(0);
    pointer-events: all;
}

.site-nav a {
  font-family: 'Lora', serif;
  font-size: 0.75rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--ink-muted);
  text-decoration: none;
  transition: color 0.2s ease;
}

.site-nav a:hover{
    color: var(--ink);
}


    /* ============================================================
       CSS CUSTOM PROPERTIES (Variables)
       Defining our color palette and spacing in one place.
       If you want to retheme the whole page, change values here.
       ============================================================ */
    :root {
      --cream:        #f5f0e8;   /* page background — aged paper */
      --cream-dark:   #e8e0cc;   /* slightly darker cream for depth */
      --envelope-tan: #d4b896;   /* envelope body color */
      --flap-tan:     #c4a882;   /* slightly darker for the flaps */
      --flap-shadow:  #b09070;   /* even darker for the side triangles */
      --wax-red:      #8b2020;   /* wax seal accent color */
      --ink:          #2c2416;   /* near-black for text */
      --ink-muted:    #6b5c47;   /* muted brown for secondary text */
      --photo-border: #ffffff;   /* white border around photo card */
      --stamp-bg:     #e8d5b0;   /* stamp background color */
    }

    /* ============================================================
       RESET & BASE STYLES
       A minimal reset so browsers don't add unexpected spacing.
       box-sizing: border-box means padding/border are included
       in an element's total width — much easier to work with.
       ============================================================ */
    *, *::before, *::after {
      box-sizing: border-box;
      margin: 0;
      padding: 0;
    }

    html {
      /* scroll-behavior: smooth makes the page glide when jumping
         to anchor links instead of snapping instantly */
      scroll-behavior: smooth;
    }

    body {
      background-color: var(--cream);
      font-family: 'Lora', Georgia, serif;
      color: var(--ink);

      /* We make the body very tall so there's room to scroll.
         The scroll is what drives the "card falling out" animation.
         We'll adjust this once the content is built out. */
      min-height: 300vh;

      /* A subtle paper texture pattern using CSS radial-gradient.
         This creates tiny dots evenly spaced across the background,
         giving a slight grain that feels like aged paper. */
      background-image: radial-gradient(var(--cream-dark) 1px, transparent 1px);
      background-size: 28px 28px;
    }

    /* ============================================================
       HEADER — POSTMARK STYLE
       A simple top bar that looks like a postmark stamp.
       ============================================================ */
    .postmark-header {
      text-align: center;
      padding: 2rem 1rem 1rem;
      opacity: 0;
      /* We'll fade this in via JS after the page loads */
      animation: fadeInDown 0.8s ease 0.2s forwards;
    }

    .postmark-header h1 {
      font-family: 'Playfair Display', serif;
      font-size: clamp(1.4rem, 4vw, 2.4rem);
      /* clamp(min, preferred, max) keeps font size responsive:
         never smaller than 1.4rem, never bigger than 2.4rem */
      font-style: italic;
      font-weight: 500;
      color: var(--ink);
      letter-spacing: 0.02em;
    }

    .postmark-header .subtitle {
      font-size: 0.8rem;
      letter-spacing: 0.25em;
      text-transform: uppercase;
      color: var(--ink-muted);
      margin-top: 0.3rem;
    }

    /* A decorative horizontal rule styled like a postmark line */
    .postmark-line {
      width: 80px;
      height: 2px;
      background: var(--wax-red);
      margin: 0.6rem auto 0;
      border-radius: 2px;
    }

    /* ============================================================
       MAIN STAGE
       This is the fixed viewport-centered container that holds
       our entire envelope animation.

       position: fixed + top/left/transform: translate(-50%,-50%)
       is the classic CSS trick for perfectly centering something
       both horizontally and vertically in the viewport, regardless
       of scroll position. We want it to stay in place while the
       user scrolls.

       z-index: 10 keeps it above any background elements.
       ============================================================ */
    .stage {
      position: fixed;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
      z-index: 10;

      /* We use a CSS custom property here so JavaScript can update
         the envelope's vertical position as the user scrolls */
      --env-offset-y: 0px;
      --env-scale: 1;
    }

    /* ============================================================
       THE ENVELOPE WRAPPER
       This is the element JS will animate on scroll.
       It wraps both the envelope body and the photo card.
       ============================================================ */
    .envelope-wrapper {
      position: relative;
      width: 360px;
      height: 240px;

      /* We use CSS variables for the scroll-driven transform.
         JS will update --env-offset-y and --env-scale, and this
         transform will automatically react. This is much more
         performant than setting style.transform in a loop. */
      transform:
        translateY(var(--env-offset-y))
        scale(var(--env-scale));

      /* transition adds a tiny smoothing buffer so it doesn't look
         jittery — but we keep it short so it stays responsive */
      transition: opacity 0.6s ease, transform 0.05s linear;

      /* On hover, we'll add a wiggle class via JS */
      cursor: pointer;
    }

    .envelope-wrapper.hidden {
        opacity: 0;
        pointer-events: none;
    }

    /* ============================================================
       ENVELOPE BODY
       The main rectangle of the envelope. All the triangle flaps
       are positioned absolutely on top of / behind this.
       ============================================================ */
    .env-body {
      position: absolute;
      bottom: 0;
      left: 0;
      width: 360px;
      height: 220px;
      background-color: var(--envelope-tan);
      border-radius: 3px;

      /* We need overflow: visible so the flap triangle can poke
         above the top edge of the body rectangle */
      overflow: visible;
      perspective: 900px;
      transform-style: preserve-3d;
    }

    /* ============================================================
       TRIANGLE FLAPS — THE CSS BORDER TRICK
       CSS can't draw triangles natively, but we can exploit how
       borders work: if an element has zero width and height, and
       thick borders, those borders form triangles.

       Imagine 4 thick borders meeting at a 0x0 point — each one
       is a triangle. We make 3 of them transparent and one solid
       to get a pointing triangle of any color.

       Reference: https://css-tricks.com/snippets/css/css-triangle/
       ============================================================ */

    /* Back flap — the triangle BEHIND the card.
       This is the flap that visually "opens" by rotating.
       border-bottom creates a triangle pointing DOWN (toward envelope).
       We size it exactly to match the envelope width (180 + 180 = 360). */
   

.flap-back {
  position: absolute;
  top: 0px;           /* sits above the envelope body */
  left: -1px;
  width: 362px;          /* matches envelope width */
  height: 220px;         /* controls how deep the V point goes */
  background-color: var(--flap-tan);

  /*
    clip-path: polygon() draws a triangle using three points.
    Each point is written as "X% Y%" where:
      0% 0% = top-left corner of the element
      100% 0% = top-right corner
      50% 100% = bottom-center (the downward point, touching the envelope)

    This gives us a triangle that is:
      - wide across the top (the full envelope width)
      - pointing DOWN toward the envelope body
    ...which is exactly how a real envelope flap looks when closed.
  */
  clip-path: polygon(0% 0%, 100% 0%, 50% 100%);

  /*
    The hinge is at the bottom of this element — where the flap
    meets the envelope body — so transform-origin is bottom center.
    This is the "fold line" on a real envelope.
  */
  transform-origin: bottom center;

  transition: transform 0.7s cubic-bezier(0.4, 0, 0.2, 1);
  z-index: 1;
}

.flap-back.open {
  /*
    rotateX(-180deg) folds the flap outward toward the viewer.
    Negative = forward fold (like lifting a flap up toward you).
    Positive = backward fold (into the screen, away from you).
  */
  transform: scaleY(0);
}

    /* Left side triangle — points right, creating the left fold */
    .tri-left {
      position: absolute;
      bottom: 0;
      left: -1px;
      width: 0;
      height: 0;
      /* border-bottom creates upward point; border-right makes right side slant */
      border-bottom: 110px solid var(--flap-shadow);
      border-right:  181px solid transparent;
      z-index: 0;
    }

    /* Right side triangle — mirror of tri-left */
    .tri-right {
      position: absolute;
      bottom: 0;
      right: -1px;
      width: 0;
      height: 0;
      border-bottom: 110px solid var(--flap-shadow);
      border-left:   181px solid transparent;
      z-index: 0;
    }

    /* Bottom triangle — the V-flap at the bottom of the envelope */
    .tri-bottom {
      position: absolute;
      bottom: -1px;
      left: -1px;
      width: 0;
      height: 0;
      border-right: 181px solid transparent;
      border-left:  181px solid transparent;
      /* This points UP into the envelope */
      border-bottom: 120px solid var(--flap-shadow);
      z-index: 3;
    }

    /* ============================================================
       WAX SEAL
       A decorative circle centered on the bottom flap join.
       Pure CSS circle: border-radius: 50% on a square element.
       ============================================================ */
    .wax-seal {
      position: absolute;
      bottom: 55px; /* sits over the bottom triangle */
      left: 50%;
      transform: translateX(-50%);
      width: 44px;
      height: 44px;
      background-color: var(--wax-red);
      border-radius: 50%;
      z-index: 4;

      /* Inner decorative ring using outline */
      box-shadow:
        0 0 0 3px var(--cream),
        0 0 0 5px var(--wax-red);

      display: flex;
      align-items: center;
      justify-content: center;
      font-family: 'Playfair Display', serif;
      font-size: 1rem;
      font-style: italic;
      color: rgba(255,255,255,0.85);
      letter-spacing: 0.05em;

      /* Seal hides when the envelope opens */
      transition: opacity 0.3s ease, transform 0.3s ease;
    }

    .wax-seal.hidden {
      opacity: 0;
      transform: translateX(-50%) scale(0.7);
      pointer-events: none;
    }

    /* ============================================================
       STAMP (decorative top-right corner detail)
       ============================================================ */
    .stamp {
      position: absolute;
      top: 12px;
      right: 14px;
      width: 50px;
      height: 62px;
      background: var(--stamp-bg);
      border: 2px solid var(--flap-shadow);
      z-index: 5;

      /* Perforated stamp edges using repeating-linear-gradient.
         This draws tiny dashes along the border to mimic
         the dotted perforations of a real postage stamp. */
      outline: 4px dashed var(--cream);
      outline-offset: -5px;

      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      gap: 2px;
    }

    .stamp-icon {
      font-size: 1.5rem;
      line-height: 1;
    }

    .stamp-value {
      font-family: 'Lora', serif;
      font-size: 0.55rem;
      letter-spacing: 0.1em;
      color: var(--ink-muted);
      text-transform: uppercase;
    }

    /* ============================================================
       PHOTO CARD
       The card that "lives inside" the envelope and slides out.

       It's absolutely positioned and starts below the envelope's
       visual top (z-index: 2 puts it above the back flap but
       below the front elements when closed).

       translateY(0) = tucked inside
       translateY(-200px) = fully slid out (driven by scroll)
       ============================================================ */
    .photo-card {
      position: absolute;

      /* Centered horizontally inside the envelope */
      left: 50%;
      /* Starts near the bottom of the envelope */
      bottom: 20px;

      /* We use CSS custom properties so JS can animate this
         without touching the element's style directly in a loop.
         --card-y is updated by our scroll handler. */
      transform:
        translateX(-50%)
        translateY(var(--card-y, 0px));

      width: 220px;
      height: 160px;
      background: white;
      border-radius: 4px;

      /* Classic photo-print white border effect */
      padding: 10px 10px 30px 10px; /* extra bottom padding = caption area */
      box-shadow:
        0 2px 8px rgba(0,0,0,0.12),
        0 0 0 1px rgba(0,0,0,0.06);

      /* z-index: 2 means it's above the back flap (z:1) but below
         the wax seal (z:4) and bottom tri (z:3) when closed */
      z-index: 2;

      /* Starts invisible; JS adds .visible class after flap opens */
      opacity: 0;
      transition:
        opacity 0.4s ease,
        transform 0.06s linear; /* quick update from scroll */
    }

    .photo-card.visible {
      opacity: 1;
    }

    /* The photo area inside the card */
    .photo-area {
      width: 100%;
      height: 110px;
      background: transparent;
      border-radius: 2px;
      overflow: hidden;
      display: flex;
      align-items: center;
      justify-content: center;
      position: relative;
    }

    /* Placeholder for when no real photo is added yet */
    .photo-placeholder-icon {
      width: 100%;
      height: 100%;
      display: flex;
      align-items: center;
      justify-content: center;
    }

    /* If you have a real photo, add an <img> inside .photo-area
       and remove the placeholder icon. These styles will handle it. */
    .photo-area img {
      width: 100%;
      height: 100%;
      object-fit: cover; /* fills the box without stretching */
    }

    /* The caption area at the bottom of the photo card */
    .photo-caption {
      position: absolute;
      bottom: 6px;
      left: 10px;
      right: 10px;
      font-family: 'Lora', serif;
      font-size: 0.65rem;
      font-style: italic;
      color: var(--ink-muted);
      text-align: center;
      letter-spacing: 0.06em;
    }

    /* ============================================================
       LETTER CONTENT — visible after card slides out
       This div is in normal document flow (not fixed), so it
       appears as the user scrolls down the page.
       It fades in via IntersectionObserver in the JS section.
       ============================================================ */
    .letter-section {
      position: relative;
      z-index: 5;
      margin-top: 100vh; /* pushes below the viewport initially */
      padding: 4rem 2rem 6rem;
      display: flex;
      flex-direction: column;
      align-items: center;
      gap: 2rem;
    }

    .letter-paper {
      background: white;
      max-width: 560px;
      width: 100%;
      padding: 3rem 3.5rem;
      border-radius: 2px;
      box-shadow:
        0 4px 20px rgba(0,0,0,0.08),
        0 1px 3px rgba(0,0,0,0.06);

      /* Starts invisible; IntersectionObserver fades it in */
      opacity: 0;
      transform: translateY(30px);
      transition: opacity 0.7s ease, transform 0.7s ease;
    }

    .letter-paper.in-view {
      opacity: 1;
      transform: translateY(0);
    }

    /* Lined paper effect using repeating-linear-gradient.
       Every 2rem, we draw a very subtle horizontal line. */
    .letter-paper {
      background-image: repeating-linear-gradient(
        to bottom,
        transparent,
        transparent calc(2rem - 1px),
        rgba(0,0,0,0.04) calc(2rem - 1px),
        rgba(0,0,0,0.04) 2rem
      );
      background-size: 100% 2rem;
    }

    .letter-date {
      font-size: 0.75rem;
      letter-spacing: 0.15em;
      text-transform: uppercase;
      color: var(--ink-muted);
      margin-bottom: 1.5rem;
    }

    .letter-greeting {
      font-family: 'Playfair Display', serif;
      font-size: 1.6rem;
      font-style: italic;
      font-weight: 500;
      color: var(--ink);
      margin-bottom: 1.2rem;
    }

    .letter-body {
      font-size: 1rem;
      line-height: 1.9;
      color: var(--ink);
    }

    .letter-body p + p {
      margin-top: 1rem; /* space between paragraphs */
    }

    .letter-sign {
      font-family: 'Playfair Display', serif;
      font-size: 1.4rem;
      font-style: italic;
      margin-top: 2rem;
      color: var(--ink);
    }

    /* ============================================================
       SCROLL HINT
       A small animated arrow that prompts the user to scroll.
       It fades out once they start scrolling (handled in JS).
       ============================================================ */
    .scroll-hint {
      position: fixed;
      bottom: 2rem;
      left: 50%;
      transform: translateX(-50%);
      z-index: 20;
      display: flex;
      flex-direction: column;
      align-items: center;
      gap: 0.4rem;
      opacity: 1;
      transition: opacity 0.4s ease;
      pointer-events: none; /* doesn't block clicks */
    }

    .scroll-hint.hidden {
      opacity: 0;
    }

    .scroll-hint span {
      font-size: 0.65rem;
      letter-spacing: 0.2em;
      text-transform: uppercase;
      color: var(--ink-muted);
    }

    /* The bouncing arrow: a rotated square with two borders */
    .scroll-arrow {
      width: 16px;
      height: 16px;
      border-right: 2px solid var(--ink-muted);
      border-bottom: 2px solid var(--ink-muted);
      transform: rotate(45deg);
      animation: bounce 1.4s ease infinite;
    }

/* ============================================================
   PAGE SECTIONS — shared base styles
   Each section takes up at least the full viewport height,
   so every nav link lands on a clean full-screen view.
   padding-top accounts for the fixed nav bar height so
   content doesn't hide underneath it when scrolled to.
   ============================================================ */
.page-section {
  min-height: 100vh;
  padding: 8rem 2rem 6rem;
  display: flex;
  align-items: center;
  justify-content: center;

  /* Smooth fade-in — same pattern as the letter paper.
     JS IntersectionObserver will add .in-view when scrolled to. */
  opacity: 0;
  transform: translateY(24px);
  transition: opacity 0.7s ease, transform 0.7s ease;
}

.page-section.in-view {
  opacity: 1;
  transform: translateY(0);
}

/* ============================================================
   INDIVIDUAL SECTION BACKGROUNDS
   Each gets its own background to create visual separation.
   These are deliberately subtle — variations on the cream
   palette so it still feels like one cohesive document.
   Swap these out freely for whatever suits your taste!
   ============================================================ */
#about {
  background-color: var(--cream);

  /* Same dot texture as the body for continuity */
  background-image: radial-gradient(var(--cream-dark) 1px, transparent 1px);
  background-size: 28px 28px;
}

/*
  FILM STRIP
  Uses flexbox to line up the sprocket columns and photo frames
  side by side. The dark background and monospace font sell the
  "film negative" look without any actual images.
*/
.film-strip-wrapper {
  display: inline-flex;       /* shrinks to fit content, not full width */
  flex-direction: row;        /* sprockets | frames | sprockets left to right */
  align-items: stretch;       /* all columns match height */
  background: #1a1a1a;        /* dark film base color */
  border-radius: 3px;
  box-shadow: 2px 4px 16px rgba(0, 0, 0, 0.35);
  padding: 10px 4px 6px;
  gap: 4px;
}

/*
  .strip-frames wraps the actual photo slots so they sit
  between the two sprocket columns cleanly.
*/
.strip-frames {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

/*
  Each photo frame is a fixed-size dark rectangle.
  overflow: hidden ensures photos don't spill outside the frame.
  When you add a real <img>, the .strip-frame img rule below
  will size it correctly automatically.
*/
.strip-frame {
  width: 200px;
  height: 150px;
  background: transparent;  
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* When a real photo is added, fill the frame completely */
.strip-frame img {
  width: 100%;
  height: 100%;
  object-fit: cover;          /* crops to fill without stretching */
}

/* Emoji placeholder — remove this div once you add real photos */
.strip-placeholder {
  font-size: 2rem;
  opacity: 1;
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
}

/*
  The text label at the bottom of the strip.
  font-family: 'Courier New' mimics old film canister text.
*/
.strip-label {
  text-align: center;
  font-family: 'Courier New', monospace;
  font-size: 0.55rem;
  color: #888;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  padding: 2px 0 4px;
}

/*
  SPROCKET HOLES
  The two columns of small dark rectangles that run down each
  side of the film strip. They're just divs — no images.
  justify-content: space-around distributes them evenly
  to match the height of the frames column beside them.
*/
.sprocket-col {
  display: flex;
  flex-direction: column;
  justify-content: space-around;
  align-items: center;
  width: 12px;
  padding: 4px 0;
}

/*
  Each hole is a small rounded rectangle in near-black —
  darker than the strip background so they read as punch-outs.
*/
.sprocket-hole {
  width: 6px;
  height: 6px;
  background: #0a0a0a;
  border-radius: 1px;
  flex-shrink: 0;             /* prevents holes from collapsing if strip is short */
}

/*
  SCATTERED PHOTOS
  The container is position: relative with a fixed size —
  this is the "table" the photos sit on. Its height needs to
  be large enough to contain the tallest photo including its
  rotation offset. Adjust width/height if photos clip at edges.
*/
.photo-scatter {
  position: relative;
  width: 480px;
  height: 340px;
}

/*
  Each photo is a white polaroid-style card with thick bottom
  padding (the caption area) and a soft shadow.

  --base-rotate stores the resting rotation so the hover scale
  can reference it. Without this, hover would reset the rotation
  back to 0deg while scaling, which looks broken.

  transition on transform and box-shadow creates the smooth
  lift effect on hover. z-index transitions instantly (0s)
  so the photo snaps to the front immediately on hover.
*/
.scatter-photo {
  position: absolute;
  background: white;
  padding: 10px 10px 36px;
  box-shadow: 2px 3px 10px rgba(0, 0, 0, 0.15);
  transition: transform 0.25s ease, box-shadow 0.25s ease;
  cursor: default;
}

/*
  On hover, the photo lifts (larger shadow) and scales up
  slightly. z-index: 10 brings it in front of all siblings.
  !important is needed here because the base transform is set
  inline via --base-rotate, and we need hover to override it.
*/
.scatter-photo:hover {
  transform: var(--base-rotate) scale(1.05) !important;
  box-shadow: 4px 8px 20px rgba(0, 0, 0, 0.22);
  z-index: 10 !important;
}

/*
  The photo image area inside each card.
  Fixed size keeps all three photos the same dimensions
  regardless of the actual image proportions.
*/
.s-photo {
  width: 190px;
  height: 150px;
  background: transparent;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
}

.s-photo img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.scatter-caption {
  font-family: 'Lora', Georgia, serif;
  font-size: 0.58rem;
  font-style: italic;
  color: var(--ink-muted);
  text-align: center;
  margin-top: 4px;
  letter-spacing: 0.04em;
  width: 190px;
  white-space: normal;
}

/*
  INDIVIDUAL PHOTO POSITIONS
  Each photo gets its own position (top/left) and rotation.
  --base-rotate stores the rotation so the hover rule can
  reference it without losing the angle.
  z-index controls which photo appears on top by default —
  higher number = closer to the viewer.

  Tweak top/left/rotate values freely to rearrange the scatter.
*/
.scatter-photo:nth-child(1) {
  --base-rotate: rotate(-5deg);
  transform: var(--base-rotate);
  top: 20px;
  left: 0px;
  z-index: 1;
}

.scatter-photo:nth-child(2) {
  --base-rotate: rotate(3deg);
  transform: var(--base-rotate);
  top: 40px;
  left: 140px;
  z-index: 2;
}

.scatter-photo:nth-child(3) {
  --base-rotate: rotate(-1.5deg);
  transform: var(--base-rotate);
  top: 15px;
  left: 275px;
  z-index: 3;
}

#human-skills {
  /* A slightly warmer, darker cream to distinguish it */
  background-color: #ede5d5;
  background-image: radial-gradient(rgba(176, 144, 112, 0.25) 1px, transparent 1px);
  background-size: 28px 28px;
}

/*
  STAMP FRAME
  The perforated edge is created entirely with CSS using
  radial-gradient on the ::before pseudo-element.

  How the perforation trick works:
    radial-gradient(circle at top, transparent Npx, color Npx)
    draws a row of semicircles punched into the top edge.
    Repeating this on all four sides with repeat-x / repeat-y
    creates the classic stamp tooth effect.
*/
.stamp-outer {
  position: relative;
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  background: #e8d5b0;        /* warm paper/stamp color */
  padding: 12px 12px 18px;
  box-shadow: 2px 3px 14px rgba(0, 0, 0, 0.18);
}

/*
  The ::before pseudo-element is positioned over all four edges
  and draws the perforated teeth using layered radial-gradients.
  Each gradient layer handles one edge:
    - top edge: semicircles punched from the top
    - bottom edge: semicircles punched from the bottom
    - left edge: semicircles punched from the left
    - right edge: semicircles punched from the right
  background-size controls how far apart the teeth are spaced.
*/
.stamp-outer::before {
  content: '';
  position: absolute;
  inset: -4px;                /* slightly outside the element edges */
  background:
    radial-gradient(circle at top, transparent 4px, #e8d5b0 4px)
      top / 12px 6px repeat-x,
    radial-gradient(circle at bottom, transparent 4px, #e8d5b0 4px)
      bottom / 12px 6px repeat-x,
    radial-gradient(circle at left, transparent 4px, #e8d5b0 4px)
      left / 6px 12px repeat-y,
    radial-gradient(circle at right, transparent 4px, #e8d5b0 4px)
      right / 6px 12px repeat-y;
  z-index: 1;                 /* sits above the stamp background */
}

/* The denomination label in the top-right corner */
.stamp-value-tag {
  position: absolute;
  top: 8px;
  right: 10px;
  font-family: 'Courier New', monospace;
  font-size: 0.5rem;
  font-weight: bold;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--wax-red);
  z-index: 3;                 /* above the perforations */
}

/*
  The photo slot inside the stamp.
  z-index: 2 keeps it above the ::before perforation layer
  so photos aren't obscured by the gradient overlay.
*/
.stamp-photo {
  width: 240px;
  height: 200px;
  background: transparent;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  position: relative;
  z-index: 2;
}

.stamp-photo img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}


.stamp-caption {
  font-family: 'Courier New', monospace;
  font-size: 0.6rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-muted);
  margin-top: 8px;
  text-align: center;
  position: relative;
  z-index: 2;                 /* above the perforation pseudo-element */
}

/*
  SUBSECTION ROW
  This is the two-column layout that pairs a photo component
  with its text description side by side.

  flex-wrap: wrap means on small screens the columns will
  stack vertically rather than overflowing off screen.
*/
.subsection-row {
  display: flex;
  flex-direction: row;
  align-items: flex-start;   /* photo and text align at the top */
  gap: 2.5rem;               /* space between photo and text */
  flex-wrap: wrap;           /* stacks on mobile */
  margin-top: 2rem;          /* breathing room above each row */
  margin-bottom: 3rem;       /* breathing room below each row */
}

/*
  When the photo component is on the RIGHT instead of the left,
  add class .row-reverse to the .subsection-row.
  This alternates the layout so not every row looks identical.
*/
.subsection-row.row-reverse {
  flex-direction: row-reverse;
}

/*
  The text column beside the photo.
  flex: 1 means it takes up all remaining space after the
  photo component has claimed its natural width.
  min-width: 200px prevents it from collapsing too narrow
  before flex-wrap kicks in on small screens.
*/
.subsection-text {
  flex: 1;
  min-width: 280px;
}

.subsection-text h3 {
  font-family: 'Playfair Display', serif;
  font-size: 1.3rem;
  font-style: italic;
  font-weight: 500;
  color: var(--ink);
  margin-bottom: 0.6rem;
}

.subsection-text p {
  font-size: 0.95rem;
  line-height: 1.8;
  color: var(--ink);
}

/*
  STAMP ROW — two stamps side by side
  The Human Skills section has two stamp photos per subsection.
  This wrapper lines them up horizontally with a gap.
*/
.stamp-row {
  display: flex;
  flex-direction: row;
  gap: 1.5rem;
  flex-wrap: wrap;           /* wraps to two rows on mobile */
  align-items: flex-start;
}

/*
  The .stamp-ph opacity was set to 0.4 which was dimming
  the real photos. This resets it now that real images are in.
*/
.stamp-ph {
  opacity: 1;
  width: 100%;
  height: 100%;
}

.stamp-ph img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/*
  Stagger the two stamps vertically so they feel naturally
  placed rather than perfectly aligned.
  nth-child targets the second .stamp-outer inside any
  .stamp-row specifically, so this won't affect the envelope
  stamp decoration elsewhere on the page.
*/
.stamp-row .stamp-outer:nth-child(1) {
  margin-top: 0px;      /* first stamp sits at normal position */
}

.stamp-row .stamp-outer:nth-child(2) {
  margin-top: 145px;     /* second stamp drops down, creating the offset */
}


/*
  The .strip-placeholder was also dimming real photos.
  Same fix — opacity back to 1 once real images are loaded.
*/
.strip-placeholder {
  opacity: 1;
  width: 100%;
  height: 100%;
  font-size: 2rem;           /* keeps emoji fallback readable */
}

.strip-placeholder img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/*
  .s-placeholder fix for scatter photos — same opacity issue.
*/
.s-placeholder {
  opacity: 1;
  width: 100%;
  height: 100%;
}

.s-placeholder img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/*
  Add some spacing between subsection headings and the content
  that follows them so the page breathes a bit more.
*/
.about-sections h3 {
  font-family: 'Playfair Display', serif;
  font-size: 1.3rem;
  font-style: italic;
  font-weight: 500;
  color: var(--ink);
  margin-top: 3rem;
  margin-bottom: 1rem;
}


#ai-skills {
  /* Deepest tone of the three — grounds the bottom of the page */
  background-color: #e4d9c4;
  background-image: radial-gradient(rgba(176, 144, 112, 0.35) 1px, transparent 1px);
  background-size: 28px 28px;
}

/* ============================================================
   NAV ITEM WRAPPER
   position: relative is required here so the dropdown can
   use position: absolute relative to THIS element, not the
   whole page. Without this the dropdown would fly off
   somewhere unexpected.
   ============================================================ */
.nav-item {
  position: relative;
  display: flex;
  align-items: center;
  padding-bottom: 1rem;
  margin-bottom: -1rem;
}

/* ============================================================
   DROPDOWN PANEL
   Starts invisible and slightly above its final position.
   The transition makes it slide down and fade in smoothly
   when the parent is hovered.
   ============================================================ */
.nav-dropdown {
  position: absolute;

  /* Sits directly below the nav link that triggers it */
  top: calc(100% + 0px);
  left: 50%;

  /* Centers the dropdown under its parent link */
  transform: translateX(-50%) translateY(-6px);

  display: flex;
  flex-direction: column;
  gap: 0.1rem;
  padding: 0.5rem 0.4rem 0.6rem 0.4rem;
  min-width: 160px;

  /* Matches the nav bar's frosted glass look */
  background: rgba(245, 240, 232, 0.92);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);

  border: 1px solid rgba(44, 36, 22, 0.08);
  border-radius: 4px;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.08);

  /* Hidden by default */
  opacity: 0;
  pointer-events: none;

  /* Smooth slide + fade on hover */
  transition: opacity 0.25s ease, transform 0.25s ease;
}

/* ============================================================
   HOVER TRIGGER
   When .nav-item is hovered, its child .nav-dropdown
   becomes visible. The sibling ~ selector won't work here
   because dropdown is a child, not a sibling — so we use
   the descendant pattern instead.
   ============================================================ */
.nav-item:hover .nav-dropdown {
  opacity: 1;
  pointer-events: all;
  transform: translateX(-50%) translateY(0);
}

/* Dropdown links inherit the nav style but with tighter sizing */
.nav-dropdown a {
  font-family: 'Lora', serif;
  font-size: 0.7rem;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--ink-muted);
  text-decoration: none;
  padding: 0.4rem 0.8rem;
  border-radius: 3px;
  transition: background 0.15s ease, color 0.15s ease;
  white-space: nowrap; /* stops links wrapping to two lines */
}

.nav-dropdown a:hover {
  background: rgba(44, 36, 22, 0.06);
  color: var(--ink);
}

/* ============================================================
   SECTION INNER — constrains content width for readability
   ============================================================ */
.section-inner {
  max-width: 1100px;
  width: 100%;
}

/*
  Paragraphs sitting directly inside .section-inner —
  these are the intro/body text blocks in About Me, Human
  Skills, and AI Skills that felt heavier than the rest.

  line-height: 1.9 matches what .letter-body and
  .subsection-text already use, so all text on the page
  will feel consistent.

  The paragraph + paragraph selector adds margin only
  between consecutive paragraphs, not above the first one,
  so it doesn't push the first paragraph away from the
  heading above it.
*/
.section-inner > p {
  font-size: 1rem;
  line-height: 1.5;       /* matches the rest of the page */
  color: var(--ink);
  max-width: 100%;       /* keeps long lines readable — very long lines
                             are harder to track across the page */
}

.section-inner > p + p {
  margin-top: 0.8rem;     /* breathing room between consecutive paragraphs */
}

/* Small numbered label above each heading — like a document index */
.section-label {
  font-family: 'Lora', serif;
  font-size: 0.7rem;
  letter-spacing: 0.3em;
  color: var(--ink-muted);
  text-transform: uppercase;
  margin-bottom: 0.6rem;
}

.section-heading {
  font-family: 'Playfair Display', serif;
  font-size: clamp(2rem, 5vw, 3.2rem);
  font-weight: 500;
  font-style: italic;
  color: var(--ink);
  margin-bottom: 1rem;
}

/* A short decorative rule below each heading,
   styled like the postmark line in the header */
.section-divider {
  width: 50px;
  height: 2px;
  background: var(--wax-red);
  border-radius: 2px;
  margin-bottom: 2rem;
}

/* scroll-margin-top creates an invisible buffer above the element
   when the browser is scrolling to it via an anchor link.
   The value should be slightly more than your nav bar height
   (nav is about 56px tall with padding) so the heading lands
   visibly below the nav bar with a little breathing room. */

#about,
#human-skills,
#ai-skills,
#about-engagement,
#about-carolina,
#about-recognition,
#human-skills-prodev,
#human-skills-volunteer {
  scroll-margin-top: 80px;
}

/* ============================================================
   SITE FOOTER
   position: relative keeps it in normal document flow so
   it naturally appears after all the page sections when
   the user scrolls to the bottom.
   ============================================================ */
.site-footer {
  position: relative;
  background-color: #2c2416;   /* var(--ink) — dark, grounds the page */
  color: #f5f0e8;              /* var(--cream) — light text on dark bg */
  padding: 5rem 2rem 2rem;
  z-index: 20;
}

/* Constrains the footer content to a readable max width,
   same pattern as .section-inner */
.footer-inner {
  max-width: 1100px;
  width: 100%;
  margin: 0 auto;              /* centers the inner block */
}

/* ── DECORATIVE HEADING ROW ── */
/*
  Three items in a row: line — text — line
  The lines are flex: 1 so they stretch to fill equal space
  on either side of the heading text.
*/
.footer-heading-wrap {
  display: flex;
  align-items: center;
  gap: 1.2rem;
  margin-bottom: 3rem;
}

.footer-line {
  flex: 1;
  height: 1px;
  background: rgba(245, 240, 232, 0.2);  /* subtle cream line */
}

.footer-heading {
  font-family: 'Lora', serif;
  font-size: 0.7rem;
  letter-spacing: 0.35em;
  text-transform: uppercase;
  color: rgba(245, 240, 232, 0.5);       /* muted cream */
  white-space: nowrap;
}

/* ── THREE COLUMN LAYOUT ── */
/*
  Same flex pattern as .subsection-row — columns sit side by
  side and wrap to vertical on narrow screens.
*/
.footer-columns {
  display: flex;
  flex-direction: row;
  gap: 3rem;
  flex-wrap: wrap;
  align-items: flex-start;
}

.footer-col {
  flex: 1;
  min-width: 220px;            /* wraps below this width */
}

/* The middle column gets a subtle left and right border
   to visually separate it from its neighbours */
.footer-col-center {
  border-left: 1px solid rgba(245, 240, 232, 0.12);
  border-right: 1px solid rgba(245, 240, 232, 0.12);
  padding-left: 3rem;
  padding-right: 3rem;
}

.footer-col-heading {
  font-family: 'Playfair Display', serif;
  font-size: 1.1rem;
  font-style: italic;
  font-weight: 500;
  color: #f5f0e8;
  margin-bottom: 0.5rem;
}

/* Short red divider under each column heading —
   matches the section-divider style used above */
.footer-divider {
  width: 30px;
  height: 2px;
  background: var(--wax-red);
  border-radius: 2px;
  margin-bottom: 1.2rem;
}

/* ── CONTACT FORM ── */
.contact-form {
  display: flex;
  flex-direction: column;
  gap: 0.8rem;
}

/*
  Each label + input pair sits in its own .form-field div
  so they stack vertically with consistent spacing.
*/
.form-field {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
}

.form-field label {
  font-family: 'Lora', serif;
  font-size: 0.65rem;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: rgba(245, 240, 232, 0.55);
}

/*
  Input and textarea share the same base styles.
  background: transparent keeps them on the dark footer background.
  border-bottom only gives a clean underline style.
*/
.form-field input,
.form-field textarea {
  background: transparent;
  border: none;
  border-bottom: 1px solid rgba(245, 240, 232, 0.25);
  color: #f5f0e8;
  font-family: 'Lora', serif;
  font-size: 0.85rem;
  padding: 0.4rem 0;
  outline: none;
  transition: border-color 0.2s ease;
  resize: none;                /* prevents textarea from being draggable */
}

/* On focus, the underline brightens to show the field is active */
.form-field input:focus,
.form-field textarea:focus {
  border-bottom-color: rgba(245, 240, 232, 0.7);
}

/* Placeholder text is slightly dimmer than real input text */
.form-field input::placeholder,
.form-field textarea::placeholder {
  color: rgba(245, 240, 232, 0.25);
  font-style: italic;
}

.form-submit {
  align-self: flex-start;      /* button doesn't stretch full width */
  margin-top: 0.5rem;
  background: transparent;
  border: 1px solid rgba(245, 240, 232, 0.35);
  color: #f5f0e8;
  font-family: 'Lora', serif;
  font-size: 0.75rem;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  padding: 0.5rem 1.2rem;
  cursor: pointer;
  border-radius: 2px;
  transition: background 0.2s ease, border-color 0.2s ease;
}

.form-submit:hover {
  background: rgba(245, 240, 232, 0.08);
  border-color: rgba(245, 240, 232, 0.6);
}

/* ── CONTACT INFO LIST ── */
.contact-list {
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 1.2rem;
}

.contact-item {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
}

.contact-label {
  font-family: 'Lora', serif;
  font-size: 0.6rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: rgba(245, 240, 232, 0.4);
}

.contact-item a,
.contact-item span {
  font-family: 'Lora', serif;
  font-size: 0.85rem;
  color: #f5f0e8;
  text-decoration: none;
  transition: color 0.2s ease;
}

.contact-item a:hover {
  color: var(--envelope-tan);  /* warm tan on hover — ties to the envelope theme */
}

/* Decorative wax seal in the center column */
.footer-seal {
  margin-top: 2rem;
  width: 40px;
  height: 40px;
  background: var(--wax-red);
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  color: rgba(255, 255, 255, 0.8);
  font-size: 1rem;
  box-shadow:
    0 0 0 3px #2c2416,
    0 0 0 5px var(--wax-red);
}

/* ── DISCLAIMER TEXT ── */
.disclaimer-text {
  font-family: 'Lora', serif;
  font-size: 0.8rem;
  line-height: 1.8;
  color: rgba(245, 240, 232, 0.55);
  margin-bottom: 0.8rem;
}

/* ── BOTTOM BAR ── */
/*
  A thin rule and small text at the very bottom —
  like the postmark line at the top of the page but inverted.
*/
.footer-bottom {
  margin-top: 4rem;
  padding-top: 1.5rem;
  border-top: 1px solid rgba(245, 240, 232, 0.1);
  text-align: center;
  font-family: 'Lora', serif;
  font-size: 0.65rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: rgba(245, 240, 232, 0.3);
}

/* ── FOOTER RESPONSIVE ── */
/*
  On narrow screens the three columns stack vertically and
  the center column loses its side borders since they don't
  make sense in a single column layout.
*/
@media (max-width: 768px) {
  .footer-col-center {
    border-left: none;
    border-right: none;
    border-top: 1px solid rgba(245, 240, 232, 0.12);
    border-bottom: 1px solid rgba(245, 240, 232, 0.12);
    padding-left: 0;
    padding-right: 0;
    padding-top: 2rem;
    padding-bottom: 2rem;
  }
}


    @keyframes bounce {
      0%, 100% { transform: rotate(45deg) translateY(0); }
      50%       { transform: rotate(45deg) translateY(5px); }
    }

    /* ============================================================
       KEYFRAME ANIMATIONS
       ============================================================ */

    /* Used for the header fade-in on page load */
    @keyframes fadeInDown {
      from { opacity: 0; transform: translateY(-16px); }
      to   { opacity: 1; transform: translateY(0); }
    }

    /* The hover wiggle — called via JS adding/removing a class */
    @keyframes wiggle {
      0%   { transform: translateY(var(--env-offset-y)) scale(var(--env-scale)) rotate(0deg); }
      15%  { transform: translateY(var(--env-offset-y)) scale(var(--env-scale)) rotate(-3deg); }
      35%  { transform: translateY(var(--env-offset-y)) scale(var(--env-scale)) rotate(3deg); }
      55%  { transform: translateY(var(--env-offset-y)) scale(var(--env-scale)) rotate(-2deg); }
      75%  { transform: translateY(var(--env-offset-y)) scale(var(--env-scale)) rotate(1.5deg); }
      100% { transform: translateY(var(--env-offset-y)) scale(var(--env-scale)) rotate(0deg); }
    }

    /* Applied to the wrapper when user hovers (before clicking) */
    .envelope-wrapper.wiggling {
      animation: wiggle 0.5s ease;
    }

    /* ============================================================
       RESPONSIVE — keeps envelope usable on smaller screens
       ============================================================ */
    @media (max-width: 480px) {
      .envelope-wrapper,
      .env-body {
        width: 290px;
      }
      .flap-back  { width: 29px; }
      .tri-left   { border-right-width: 146px; }
      .tri-right  { border-left-width:  146px; }
      .tri-bottom { border-right-width: 146px; border-left-width: 146px; }
    }