/* ================================================================
   COMPONENT: FOOTER / CTA
   ================================================================ */

/* ── THE FOOTER PANEL ─────────────────────────────────────────────
   A warm-paper panel with rounded top corners — the recessed end of the
   document, on `--surface-alt` like every other plate.

   It was briefly a full-bleed `--teal-hero` INK BLOCK with square corners
   (the "back cover" idea: the warm document bracketed by two dark covers).
   That has been reverted. Do not restore it without a decision — it changed
   the page's one value change into two, inverted the whole ink ladder inside
   one element, and pulled the last block off the content measure.

   The element is a SIBLING of <main> now, which is correct semantically (a
   page footer does not belong inside main). Because it no longer inherits
   `.content-wrap`, it carries that measure ITSELF — keep these three values
   identical to `.content-wrap` or the panel stops lining up with the sections
   above it. */
.footer {
  width: var(--content-width);
  max-width: 1440px;
  /* Empty page-bg gap before the panel so the footer sits on the same
     inter-section rhythm as the rest (the panel's own top padding reads
     as internal inset, not separation). 80px here + 80px section
     padding-bottom above = 160px, matching Work→About. */
  margin: var(--sp-20) auto 0;
  corner-shape: squircle;   /* Apple continuous corner (top corners) */
  background-color: var(--surface-alt);
  border-radius: var(--radius-panel) var(--radius-panel) 0 0;
  overflow: hidden;
  position: relative;
}

/* Paper grain — static fractal-noise texture giving the footer the
   feel of warm paper stock. Sits behind all content (z-index 0). */
.footer::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  border-radius: inherit;
  opacity: var(--paper-grain);
  mix-blend-mode: multiply;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='300' height='300'%3E%3Cfilter id='paper'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='300' height='300' filter='url(%23paper)'/%3E%3C/svg%3E");
  background-repeat: repeat;
}

/* Content sits above the grain. The measure lives on `.footer` itself, so
   this only insets — a second `width: var(--content-width)` here would apply
   the 95% twice and pull every footer edge ~19px inside the sections above
   (which is exactly what it did). */
.footer__cta {
  position: relative;
  z-index: 1;
  padding: var(--sp-20) var(--gutter-inner);
  padding-bottom: 0;
}

/* Top block: heading, CTA, socials (single column, left-aligned) */
.footer__top {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  max-width: 640px;   /* left column of the 2-column grid — heading wraps to 2 lines */
}

/* Full-width folded-paper "KARL" wordmark band */
.footer__wordmark {
  width: 100%;
  margin-top: var(--sp-20);
}

.footer__cta-heading {
  font-family: var(--type-h2-font);
  font-size: var(--type-h2-size);
  line-height: var(--type-h2-line);
  font-weight: var(--weight-regular);
  letter-spacing: var(--tracking-tight);
  color: var(--text-primary);
  margin-bottom: var(--sp-6);
}

/* Each word wraps for the reveal animation */
.footer__cta-heading .word {
  display: inline-block;
  overflow: hidden;
  vertical-align: bottom;
}

.footer__cta-heading .word-inner {
  display: inline-block;
}

/* Designer touch — "something" set in the ultralight italic serif cut + teal */
.footer__cta-em {
  font-weight: 200;            /* PP Editorial New Ultralight */
  font-style: italic;
  /* 40px on --paper-alt: large-text AA needs 3:1. --accent lands at 2.6:1
     here, --accent-dk at 3.7:1. The hue is unchanged; only the value drops. */
  color: var(--accent-dk);
}

/* Folded-paper "KARL" wordmark — custom polygon letterforms, full width.
   Each letter splits into a lit plane and a shadow plane (the fold). */
.footer__art {
  width: 100%;
}

.kw {
  position: relative;
  width: 100%;
}

.kw svg {
  display: block;
  width: 100%;
  height: auto;
}

.kw__noise {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

/* Wordmark: radial gradient fill + fractal noise clipped to letter shapes. */


/* ── Button: Pill CTA ─────────────────────────────────────────── */
.btn-pill {
  /* The arrow disc sits CONCENTRIC with the pill's right end cap: its right
     inset equals its top/bottom inset. So the right padding is derived, never
     chosen — (height − arrow) / 2, less the 1px border. A flat `--sp-5` put the
     disc 10.7px left of the cap's centre, floating in the pill instead of
     seated in its end. Resize via these two properties, not the padding. */
  --pill-height: 48px;
  --pill-arrow: 28px;
  display: inline-flex;
  align-items: center;
  gap: var(--sp-3);
  height: var(--pill-height);
  padding-block: 0;
  padding-inline: var(--sp-5) calc((var(--pill-height) - var(--pill-arrow)) / 2 - 1px);
  border: 1px solid var(--text-primary);
  border-radius: var(--radius-pill);
  font-family: var(--type-body1-font);
  font-size: var(--type-body1-size);
  line-height: var(--type-body1-line);
  font-weight: var(--weight-book);
  color: var(--text-primary);
  background: transparent;
  position: relative;
  isolation: isolate;   /* own stacking context — lets ::before sit at z-index:-1 */
  /* transform + box-shadow are NOT transitioned here: `paper-physics.js`
     (`data-paper="lift"`) writes both per frame through a lerp. They were in
     this list, and unlike `.project-card` nothing ever cancelled them — so the
     lift ran a 320ms CSS ease on top of a per-frame spring, which is the
     "layback" DESIGN.md → Motion warns about. Colour still belongs to CSS. */
  /* `--dur-fill`, matching the sweep below so the label inverts as the fill
     passes it rather than ahead of it. */
  transition:
    color        var(--dur-fill) var(--ease-out),
    border-color var(--dur-fill) var(--ease-out);
}

/* Fill: clip-path circle from bottom-right — no overflow/shape leakage */
/* z-index:-1 inside isolated context → paints above bg but below text */
.btn-pill::before {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background-color: var(--text-primary);
  clip-path: circle(0% at 100% 100%);
  transition: clip-path var(--dur-fill) var(--ease-out);
  z-index: -1;
}

.btn-pill:hover::before {
  clip-path: circle(200% at 100% 100%);
}

.btn-pill:hover {
  color: var(--fill-contrast);
  border-color: transparent;
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.14);
}

.btn-pill__arrow {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--pill-arrow);
  height: var(--pill-arrow);
  border-radius: var(--radius-full);
  /* THE CIRCLE CARRIES THE CONTRAST, NOT THE GLYPH.
     The disc was `--accent` (#00aa90) with a white arrow — 2.9:1, under the
     3:1 WCAG 1.4.11 asks of a non-text UI mark. Darkening the glyph fixed the
     number but changed the button's look (a dark arrow in a bright disc).
     Darkening the DISC keeps the white arrow and clears it comfortably:
     white on `--teal-ink` is 5.3:1. Same hue, one step down the ladder — the
     same move `--text-accent-ink` makes for small teal text on paper. */
  background-color: var(--teal-ink);
  color: var(--white);
  font-size: var(--type-body1-size);
  flex-shrink: 0;
  position: relative;
  z-index: 2;
  transition:
    background-color var(--dur-slow) var(--ease-out),
    color            var(--dur-slow) var(--ease-out),
    transform        var(--dur-slow) var(--ease-spring);
}

/* Grows IN PLACE. It used to nudge right 6px as well, which with the disc now
   seated concentric in the end cap left it ~2.3px from the pill's edge — a
   badge pressed against the rim. Scaling alone keeps the seat (~8px clear). */
.btn-pill:hover .btn-pill__arrow {
  background-color: var(--fill-contrast);
  color: var(--text-primary);
  transform: scale(1.1);
}


/* ── Social Icons ──────────────────────────────────────────────── */
.social-list {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  margin-top: var(--sp-6);
}

.social-link {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 48px;
  height: 48px;
  border-radius: var(--radius-full);
  color: var(--text-body);
  position: relative;
  isolation: isolate;   /* stacking context for ::before fill */
  /* `color` rides the fill (`--dur-fill`) so the glyph inverts as the sweep
     reaches it. The LIFT does not: `transform` and its shadow are the badge
     rising off the paper, a separate beat from the ink arriving, and a 900ms
     spring reads as floating rather than lifting. Same reason
     `.btn-pill__arrow` keeps its own length. */
  transition:
    color      var(--dur-fill) var(--ease-out),
    transform  var(--dur-slow) var(--ease-spring),
    box-shadow var(--dur-slow) var(--ease-out);
}

/* Fill circle: clip-path from bottom-right — stays within circle bounds */
.social-link::before {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background-color: var(--text-primary);
  clip-path: circle(0% at 100% 100%);
  /* `--ease-out`, not `--ease-spring`. A spring overshoots past its target,
     which is meaningless on a radius that has already swallowed the element
     by ~140% — the overshoot is invisible and the fill just appears to finish
     early, leaving the tail of the 600ms as dead time while the colour is
     still easing. Matches `.btn-pill::before`, which is the same gesture. */
  transition: clip-path var(--dur-fill) var(--ease-out);
  z-index: -1;
}

.social-link:hover {
  color: var(--white);
  transform: translateY(-3px);
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.14);
}

.social-link:hover::before {
  clip-path: circle(200% at 100% 100%);
}

.social-link svg {
  width: 22px;
  height: 22px;
  position: relative;
  z-index: 1;
  flex-shrink: 0;
}


/* ── Footer Bar: full-width line + copy/credit ── */
.footer__bar {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  width: 100%;
  margin-top: 0;
  padding: 0 0 var(--sp-8);
  box-sizing: border-box;
}

/* The last ruled line on the site. It stays ruled — it is bar furniture at
   the very bottom of the panel, where the drawn silhouette's tapered ends
   would read as a smudge rather than as a pressed edge. */
.footer__bar-rule {
  width: 100%;
  height: 1px;
  background-color: var(--border-light);
  margin-bottom: var(--sp-6);
  align-self: stretch;
}

.footer__bar-bottom {
  display: flex;
  align-items: center;
  margin-top: var(--sp-6);
  justify-content: space-between;
  width: 100%;
  align-self: stretch;
  gap: var(--sp-3);
}

.footer__bar-copy {
  font-family: var(--type-body2-font);
  font-size: var(--type-body2-size);
  line-height: var(--type-body2-line);
  color: var(--text-tertiary);
}

/* Living-system stamp — live New York time + light phase. Matches the
   copy/credit on either side exactly (same font, size, color, spacing)
   so the bar reads as one consistent line. Empty until JS fills it. */
.footer__bar-stamp {
  font-family: var(--type-body2-font);
  font-size: var(--type-body2-size);
  line-height: var(--type-body2-line);
  color: var(--text-tertiary);
  white-space: nowrap;
}

.footer__bar-stamp:empty {
  display: none;
}

/* -- Responsive ------------------------------------------------- */
@media (max-width: 768px) {
  /* Match the mobile section padding-bottom (48px) above so the empty
     gap before the footer panel = 96px, same as between sections.

     `width: 100%` mirrors the `.content-wrap` mobile override in layout.css —
     the footer re-creates that measure instead of inheriting it, so it has to
     take the override too. It lives HERE rather than beside `.content-wrap`
     because footer.css is linked after layout.css and this `.footer` rule
     would otherwise lose on source order. Change one, change both. */
  .footer {
    width: 100%;
    margin-top: 48px;
  }

  .footer__wordmark {
    margin-top: 40px;
  }

  .footer__cta-heading {
    font-size: var(--type-h2-size);
    line-height: var(--type-h2-line);
    margin-bottom: 16px;
  }

  .footer__cta {
    padding: 48px var(--gutter);
    padding-bottom: 0;
  }

  .footer__bar {
    padding: 0 0 20px;
  }

  .btn-pill {
    --pill-height: 44px;
    --pill-arrow: 24px;
    padding-inline-start: 16px;   /* the end padding derives from the two above */
  }

  .social-list {
    margin-top: 16px;
  }

  .social-link {
    width: 44px;
    height: 44px;
  }

  .social-link svg {
    width: 20px;
    height: 20px;
  }

  .footer__bar-bottom {
    gap: 4px;
  }
}
