/* Home page — recreated from the Figma "home-v2" design
   (node 496:1376), which restyled the CV-as-homepage page this file
   originally held in draft form. Still reuses cv.css wholesale (which
   itself imports site.css) for the print stylesheet and the base .h-resume
   microformat structure, so the printed/PDF version of a CV page never
   drifts out of sync with this one — the rules below only override what
   needs to look different here, scoped under .fig- classnames and the
   .fig-page wrapper so cv.html (no .fig-page present) is completely
   unaffected. */
@import url("cv.css");

/* cv.css narrows <main> to 48rem for the dense resume reading column —
   right for cv.html, too narrow for a homepage hero with large display
   type, which wants more room to breathe before it wraps. Widened here,
   scoped to this page only (cv.html itself is untouched). Figma's content
   column is 882px; main's padding (site.css: 3rem 1.5rem 4rem) eats
   1.5rem off each side, so max-width needs to be 882px + 3rem (48px) =
   930px = 58.125rem for the actual content column to render at 882px. */
/* Figma's content column narrowed from 882px to 759px in the 2026-08
   refresh (496:2496 dark / 496:2766 light) — main's padding (site.css:
   3rem 1.5rem 4rem) eats 1.5rem (48px) off each side, so max-width needs
   to be 759px + 48px = 807px = 50.4375rem for the column to render at
   759px. */
main { max-width: 50.4375rem; }

/* --fig-accent tracks the site's existing --accent-rule (cv.css), which is
   already pink on light mode's page and --yellow on dark mode's page,
   exactly like every other page's resume content — and happens to match
   this refresh's accent hexes (#cb2787 / #f7da50) exactly, so no new
   tokens were needed for it. --fig-grey reuses --muted (also derived from
   --cream) so the small grey labels (skill categories, employment dates)
   re-colour with the theme instead of sitting at a fixed grey. */
.fig-page {
  --fig-accent: var(--accent-rule);
  --fig-grey: var(--muted);
}

/* --- Background refresh (2026-08 Figma pass) ----------------------------
   The new dark/light designs move this page's own background off the
   site-wide --blue/--cream pair (#334673 dark / #ffffff light, set
   site-wide by js/bulb.js) onto a darker navy (#1c2740) and a warm
   off-white (#faf7ee) instead — --cream itself (text) is unchanged in
   both designs, already #fff3b7 dark / #232323 light site-wide.
   Scoped to body.fig-home only (this page), not to :root, specifically so
   it doesn't change bulb.js's site-wide background for cv.html/contact.html/
   illustration.html, which weren't part of this design pass. Works because
   --blue is inherited down from :root (where bulb.js sets it inline) —
   declaring it again directly on body.fig-home, a descendant, overrides
   that inherited value for this page and everything inside it, with no
   specificity fight against the inline style (that only applies at the
   element it's set on, i.e. :root itself). --fig-card-bg is new: the
   "Artwork & animation" highlight card's own fill, a touch lighter/darker
   than the page background in each theme. */
:root[data-theme="dark"] body.fig-home {
  --blue: #1c2740;
  --fig-card-bg: #263557;
}
:root[data-theme="light"] body.fig-home {
  --blue: #faf7ee;
  --fig-card-bg: #fceede;
}

/* --- Bulb toggle, repositioned to match Figma --------------------------
   Figma has no header row on this page at all (the small nav Home icon is
   gone — the big decorative head character above does that job now), and
   places the light/dark bulb in the top-right corner rather than beside a
   left-aligned nav. .bulb-toggle (site.css) is already position:absolute
   against the page itself, not the header, so flipping it from the left
   gutter to the right gutter is all this page needs — same hanging-cord
   mechanic and click behaviour as every other page, just mirrored.
   This fixed-from-viewport-edge position is the fallback for any width
   that can't fit the wide-viewport, gap-matched position below — narrow
   enough that the content column isn't at its full centred width, so
   there's no reliable "distance from the content" to match in the first
   place. */
body.fig-home .bulb-toggle {
  left: auto;
  right: 2.5rem;
}
@media (max-width: 640px) {
  body.fig-home .bulb-toggle { right: 1.75rem; }
}
/* Wide viewports: same distance from the content column's edge as
   .hero-head-lottie keeps on the opposite side (759px content column,
   centred — half its width, 23.71875rem, plus the 7rem gap
   .hero-head-lottie sits at, below). Shares that element's own breakpoint,
   since both need the same safety margin to avoid clipping off the
   viewport edge, and it reads as one wide-screen-only flourish turning on
   together rather than two independently-tuned ones. */
@media (min-width: 1360px) {
  body.fig-home .bulb-toggle {
    left: calc(50% + 30.71875rem);
    right: auto;
  }
}

/* --- Hero ----------------------------------------------------------- */
/* Used to reserve extra top padding at ≥1501px (where the head-lotti/bulb
   are visible) so the heading cleared them, sitting well below — moved to
   the opposite goal instead: the heading (and the contact row just under
   it) now line up with the head-lotti/bulb's own row rather than trailing
   below it, so the same 2.5rem padding applies at every width, character
   visible or not.
   No bottom padding: that used to add 2rem of its own on top of the
   Core Skills section's 2.25rem margin-top right below (padding never
   collapses with a sibling's margin the way two margins do), making the
   gap above Core Skills visibly bigger than the gap below it — which only
   ever comes from that same 2.25rem collapsing against the last skills
   row's own margin-bottom:0. Dropping this to 0 leaves .fig-section's
   margin-top as the single source for both gaps, so they match. */
.fig-hero { position: relative; padding: 2.5rem 0 0; }
.fig-hero h1 {
  margin: 0;
  font-size: clamp(1.9rem, 4vw, 2.25rem);
  font-weight: 700;
  line-height: 1.2;
  color: var(--cream);
  /* Figma's heading text box is 596px (37.25rem) wide and sits on one
     line at this font size — 34rem was forcing an unwanted wrap. */
  max-width: 37.5rem;
}

/* Name/location/email/phone "header" block — the 2026-08 refresh moved the
   heading above this row (it used to be a single location-only eyebrow
   line above the heading) and added email + phone alongside location, all
   three now plain contact facts rather than a decorative eyebrow label. */
.fig-contact-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem 1.5rem;
  margin: 1rem 0 0;
  /* 0.79167rem — one true point smaller than the previous 0.875rem (14px/
     10.5pt on screen), down to 12.667px/9.5pt. Regular weight rather than
     bold, so this reads as understated metadata under the heading rather
     than competing with it. */
  font-size: 0.79167rem;
  font-weight: 400;
  color: var(--cream);
}
.fig-contact-item {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  color: inherit;
  text-decoration: none;
}
/* Email/phone/website (the <a> items — location is a plain <span>, never
   interactive) get the exact same hover/active treatment as .fig-cta
   buttons elsewhere on the page: same opacity dim, same scale, same
   spring-ish transition curve and duration, in place of the plain
   underline this used to be. */
a.fig-contact-item {
  transition: opacity 0.2s ease, transform 0.2s cubic-bezier(0.34, 1.56, 0.64, 1);
}
a.fig-contact-item:hover { opacity: 0.92; transform: scale(1.05); }
a.fig-contact-item:active { opacity: 1; transform: scale(0.95); transition-duration: 0.1s; }
.fig-contact-item svg { flex-shrink: 0; width: 14px; height: 17px; color: var(--fig-accent); }
/* The location pin's own artwork fills almost its entire viewBox with very
   little internal padding, unlike the envelope/phone/globe icons either
   side of it, so forcing it to the same 14x17px box as them still reads
   visibly larger/heavier. Sized down specifically so its drawn ink lines
   up with the other three instead of just matching their bounding box.
   overflow: visible guards against the pin's right edge getting a
   sub-pixel clip at this fractional width in some browsers — the svg's
   own viewBox scaling already keeps the artwork within bounds, so this
   is a no-op anywhere that isn't hitting that rounding issue. */
.fig-contact-row span.fig-contact-item svg { width: 8.5px; height: 11px; overflow: visible; }

/* Decorative character, idle-blinking + eye-tracking (js/hero-head-lottie.js)
   — the exact same head Lottie + behaviour as the small nav Home icon
   (js/home-nav.js). Originally 188x167px beside the intro text, then
   118x105px floating in the top-left margin outside the (759px) content
   column, then shrunk to 84x75px so it fit a normal 1280px+ laptop window;
   doubled back up to 168x150px on request, with the gap to the content
   column pulled in (112px instead of 156px) to offset most of that size
   increase, so the breakpoint only has to move from 1280px to 1360px
   rather than needing a much wider window again. Positioned relative to
   .fig-hero's own box so it tracks the centred column at any viewport
   width rather than a fixed canvas position. Hidden below 1360px — the
   narrowest width where the margin left of the centred, full-width
   content column is still wide enough (280px: the 112px gap plus the
   character's own 168px, plus a bit of buffer) for it to sit fully
   on-screen without clipping or overlapping the content column itself.

   Wrapped in a real link (<a href="index.html">) — still a no-op on this
   page itself, but it makes the character click/tap-able everywhere else
   it appears (the illustration page's own copy of it, below), and reads
   as more obviously interactive wherever it shows up, matching the
   site-wide convention that anything shaped like the head icon (the small
   nav one included) goes home. Position/size live on the link
   (.hero-head-lottie-link) rather than the lottie's own render target
   (.hero-head-lottie, the inner span) — same split as .nav-home/
   .nav-home-lottie in site.css — since an absolutely-positioned element
   nested inside a plain, unpositioned <a> wouldn't give the link itself
   any clickable area over the character. */
.hero-head-lottie-link {
  position: absolute;
  left: -17.5rem;
  /* Measured against .fig-hero's own top edge (which sits right after
     main's 48px top padding, unaffected by .fig-hero's own padding-top
     below) rather than derived purely from the Figma canvas offset, so it
     stays correct regardless of how much reserved space the padding-top
     rule above adds. */
  top: -0.5rem;
  display: block;
  width: 10.5rem;
  height: 9.375rem;
  transition: transform 0.2s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.hero-head-lottie-link:hover { transform: scale(1.08); }
.hero-head-lottie-link:active { transform: scale(0.92); transition: transform 0.1s ease; }
.hero-head-lottie {
  display: block;
  width: 100%;
  height: 100%;
}
@media (max-width: 1359px) {
  .hero-head-lottie-link { display: none; }
}

.fig-intro {
  /* Figma: 36px gap between the header block and the intro paragraph. */
  margin: 2.25rem 0 0;
  font-size: 1rem;
  line-height: 1.7;
  color: var(--cream);
}
.fig-intro p { margin: 0 0 1.2rem; }
.fig-intro p:last-child { margin-bottom: 0; }

/* --- CTA row ---------------------------------------------------------
   4px corner radius (not pill-shaped) and a filled/outline pink pairing,
   matching the Figma buttons exactly — a sharper, more "product UI" look
   than this page's previous fully-rounded CTAs. */
.fig-cta-row {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem;
  margin-top: 2.25rem;
}
.fig-cta {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.625rem;
  height: 48px;
  padding: 0 1.25rem;
  border-radius: 4px;
  font: inherit;
  font-weight: 600;
  font-size: 1rem;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer; /* Download CV is a <button> now (triggers window.print()
    in place instead of navigating to cv.html), browsers don't default a
    button's cursor to pointer the way they do for <a> */
  transition: opacity 0.2s ease, transform 0.2s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.fig-cta:hover { opacity: 0.92; transform: scale(1.05); }
.fig-cta:active { opacity: 1; transform: scale(0.95); transition-duration: 0.1s; }
.fig-cta svg { flex-shrink: 0; }
/* Filled button's label is the page's own background colour (not a fixed
   white/black) — Figma: #faf7ee text on the pink fill in light mode,
   #1c2740 text on the yellow fill in dark mode, i.e. var(--blue) in both
   cases, since that's this page's own current background value. The
   outline button mirrors it: fill is the page background, border/text are
   the accent — both already correct in either theme via --fig-accent and
   --blue, with no separate dark-mode override block needed any more. */
.fig-cta--primary { background: var(--fig-accent); color: var(--blue); border: 1px solid var(--fig-accent); }
.fig-cta--secondary { background: var(--blue); color: var(--fig-accent); border: 1px solid var(--fig-accent); }

/* --- Section headers ---------------------------------------------------
   Short bold label with a 2px pink underline — replaces the old small
   uppercase eyebrow style for this page's section headings (CORE SKILLS,
   EXPERIENCE, EDUCATION, CERTIFICATIONS). */
/* 36px between major sections (was 48px) — the 2026-08 refresh tightened
   this gap uniformly across skills/experience/education/certifications. */
.fig-section { margin: 2.25rem 0 0; }
.fig-section-heading {
  display: inline-block;
  margin: 0 0 1.5rem;
  padding-bottom: 0.5rem;
  border-bottom: 2px solid var(--fig-accent);
  font-size: 0.875rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--cream);
}

/* --- Core skills ---------------------------------------------------------
   Category label (fixed column) beside one flowing, comma-separated line
   of skills — the 2026-08 refresh replaced the previous pill-chip grid
   with plain text, uniformly across all three rows (UX, Collaboration,
   Tools), for an easier, less busy read. */
.fig-skills-row {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem 3rem;
  margin-bottom: 1.5rem;
}
.fig-skills-row:last-child { margin-bottom: 0; }
.fig-skills-label {
  flex: 0 0 13rem;
  margin: 0;
  padding-top: 0.1rem;
  font-size: 0.875rem;
  font-weight: 700;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: var(--fig-grey);
}
.fig-skills-text {
  flex: 1 1 20rem;
  margin: 0;
  font-size: 0.875rem; /* already matches .fig-bullets li's own 0.875rem */
  font-weight: 400; /* was 500 — now matches .fig-bullets li's weight too
    (that rule sets no font-weight of its own, so it's body's plain 400) */
  line-height: 1.6;
  color: var(--cream);
}

/* --- Experience / education / certifications --------------------------- */
.fig-role-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
  margin-bottom: 0.75rem;
}
.fig-role-head h3 {
  margin: 0;
  font-size: 1.25rem;
  font-weight: 700;
  color: var(--cream);
}
.fig-role-dates {
  flex-shrink: 0;
  font-size: 1rem;
  color: var(--fig-grey);
  white-space: nowrap;
}
.fig-role-intro {
  margin: 0 0 1.25rem;
  font-size: 0.875rem; /* matches .fig-bullets li exactly, so the intro
    line reads as part of the same list-weight content rather than a
    heavier lead-in above it */
  font-weight: 400; /* .fig-bullets li sets no font-weight of its own
    (body's plain 400), matched here the same way */
  line-height: 1.6; /* also matches .fig-bullets li's line-height */
  color: var(--cream);
}

.fig-client { margin: 0 0 1.25rem; }
.fig-client:last-child { margin-bottom: 0; }
.fig-client h4 {
  margin: 0 0 1rem;
  padding: 0.6rem 0.9rem;
  border-left: 2px solid var(--fig-accent);
  font-size: 1rem;
  font-weight: 700;
  color: var(--cream);
}
.fig-bullets {
  margin: 0;
  padding: 0;
  list-style: none;
}
.fig-bullets li {
  position: relative;
  margin-bottom: 0.75rem;
  padding-left: 1.1rem;
  font-size: 0.875rem;
  line-height: 1.6;
  color: var(--cream);
}
.fig-bullets li:last-child { margin-bottom: 0; }
.fig-bullets li::before {
  content: "\00b7";
  position: absolute;
  left: 0;
  color: var(--fig-accent);
  font-weight: 700;
}
/* Arctic Shores' bullets sit directly under the role header, no client
   sub-heading above them — a touch more breathing room than the Apadmi
   client blocks' own tighter list spacing. */
.fig-bullets--direct { margin-top: 0.25rem; }
.fig-bullets--direct li { margin-bottom: 1rem; }

/* --- Artwork & animation card -------------------------------------------
   2026-08 refresh: the previous pink-to-white gradient card with three
   fanned-out photo crops is gone, replaced by a plain accent-bordered
   block (page-bg-ish fill, 2px accent left border) matching the rest of
   the page's content-block styling — same simplification spirit as the
   core-skills chips-to-text change above. */
.fig-highlight-card {
  position: relative; /* anchors .fig-highlight-cta::after's stretched
    overlay below, so the whole card is clickable, not just the button */
  margin: 2.25rem 0 0;
  padding: 1.25rem 1.5rem;
  border-left: 2px solid var(--fig-accent);
  border-radius: 4px;
  background: var(--fig-card-bg);
  cursor: pointer;
  transition: transform 0.25s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.fig-highlight-card:hover { transform: scale(1.01); }
.fig-highlight-card:active { transform: scale(0.995); transition-duration: 0.1s; }
.fig-highlight-card h2 {
  margin: 0 0 0.9rem;
  font-size: 1.25rem;
  font-weight: 700;
  color: var(--cream);
}
.fig-highlight-card p {
  margin: 0 0 1.25rem;
  font-size: 0.875rem;
  line-height: 1.6;
  color: var(--cream);
}
.fig-highlight-cta {
  display: inline-flex;
  height: 48px;
  align-items: center;
  color: var(--fig-accent);
  text-decoration: none;
}
/* Stretched-link pattern: this invisible pseudo-element is sized by inset:0
   against its nearest POSITIONED ancestor — .fig-highlight-card (position:
   relative, above), not its own immediate parent .fig-highlight-cta (left
   position: static on purpose) — so it covers the whole card. Clicking
   anywhere in the card, not just the "View artwork & animation" button,
   follows this one link. Keeps the markup to a single real <a> (no
   nested/duplicate links), which also means one sensible accessible name
   for the card. */
.fig-highlight-cta::after {
  content: "";
  position: absolute;
  inset: 0;
}
/* The hover/active "pop" lives on this inner span, not .fig-highlight-cta
   itself — transform on an element makes IT the containing block for its
   own absolutely-positioned descendants (including ::after above), so
   putting the scale transform directly on .fig-highlight-cta would, the
   instant it's hovered, shrink ::after's inset:0 down from covering the
   whole card to covering just this little button instead. With the
   cursor then typically outside that shrunk area, hover is immediately
   lost, the transform reverts, ::after jumps back to full-card size, the
   cursor is back inside it, hover re-fires — an infinite flicker loop
   (this is exactly what was happening: hovering the card made the button
   visibly flicker in and out of its hover state). Keeping the transform
   on a plain, non-positioned descendant instead means .fig-highlight-cta
   itself never transforms, so it never becomes that containing block, and
   ::after stays correctly sized to the whole card throughout. */
.fig-highlight-cta-label {
  display: inline-flex;
  align-items: center;
  gap: 0.625rem;
  border-radius: 4px;
  background: transparent;
  font-weight: 600;
  font-size: 1rem;
  transition: opacity 0.2s ease, transform 0.2s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.fig-highlight-cta:hover .fig-highlight-cta-label { opacity: 0.92; transform: scale(1.05); }
.fig-highlight-cta:active .fig-highlight-cta-label { opacity: 1; transform: scale(0.95); transition-duration: 0.1s; }
.fig-highlight-cta svg { flex-shrink: 0; width: 20px; height: 20px; }

@media (max-width: 760px) {
  .fig-highlight-card { padding: 1.25rem; }
}

@media print {
  /* Screen-only framing — this page is now the actual printed/saved CV
     (the "Download CV" button prints it in place), so this strips it down
     to just the resume part, matching how cv.html always printed.
     .fig-contact-row (location/email/phone) is NOT screen-only framing —
     it's real CV content — so it stays out of this list and prints. It
     was wrongly lumped in here before, which is why location/email/phone
     were silently missing from the downloaded PDF. */
  .hero-head-lottie-link,
  .fig-cta-row,
  .fig-highlight-card { display: none; }
  /* Section-to-section gaps (.fig-section, .fig-section-heading,
     .fig-skills-row) are all set in rem, so the 15px print root above
     blew them up by the same ~38% as the text itself — fine for text, but
     margins read as dead space rather than content, so by that point a
     short row (Tools, one line) left a gap below it that looked like a
     chunk of blank page rather than normal breathing room. Tightened back
     down here, print-only, so sections read as continuous flow rather
     than isolated blocks. */
  .fig-section { margin-top: 2.5rem; }
  .fig-section-heading { margin-bottom: 0.875rem; }
  .fig-skills-row { margin-bottom: 0.875rem; }
  /* Print-only: icons dropped and text brought up to match the bullets'
     own size (0.875rem) — without the four icons eating width, the row
     still fits on one line at that size even though it didn't at the
     body-text print size before (location/email/phone/website together
     were too wide with icons included, wrapping onto two lines). */
  .fig-contact-row { font-size: 0.875rem; }
  .fig-contact-row svg { display: none; }
  /* .fig-float-cta needs its own explicit, !important rule rather than
     relying on its .no-print class alone: .fig-float-cta.is-active (two
     classes, specificity 0,2,0) outranks a plain .no-print (0,1,0)
     whenever both are on the same element — exactly the case once
     scrolled past the hero — and this print block's own plain
     .fig-float-cta selector (0,1,0) is both lower specificity AND earlier
     in the file than that .is-active rule, so neither specificity nor
     source order would let a plain override win here; only !important
     does. Without it, printing mid-scroll left this on screen at
     display:flex. */
  .fig-float-cta { display: none !important; }
  /* .fig-hero's top padding (2.5rem on its own, 10.3125rem at ≥1501px —
     both reserving room for the head-lotti/bulb above the heading) is
     pure dead space once those are hidden for print, and was pushing the
     2-page budget to 3 — dropped to 0, same spirit as cv.css's own
     print-only spacing tightening below. Bottom padding is already 0 at
     the base rule above (kept that way here too, for the same
     even-gap-above-and-below-Core-Skills reason explained there). */
  .fig-hero { padding: 0; }
  .fig-hero h1 { font-size: 1.6rem; }

  /* Apadmi is now one flat bullet list (fig-role--apadmi, matching Arctic
     Shores' own layout) rather than a run of separate per-client blocks,
     so pagination protection moves to the individual bullets: keeps one
     client write-up from splitting mid-sentence across a page break,
     without forcing the whole list (taller than a single page) onto one
     page, which would waste most of page 1 as blank space. */
  .fig-role--apadmi li {
    break-inside: avoid;
    page-break-inside: avoid; /* older/Safari fallback for break-inside */
  }
  /* Every OTHER role/section — Arctic Shores, Core Skills, Education,
     Certifications — is short enough to always fit on one page, so it
     should never straddle a break either: push the whole thing to the
     next page instead of splitting it. :not(.fig-role--apadmi) / the
     :has() exclusion below leave Apadmi and the Experience section that
     contains it out of this, both taller than a page, for the same reason
     fig-role--apadmi's own bullets are protected individually above. */
  .p-experience:not(.fig-role--apadmi),
  .fig-section:not(:has(.fig-role--apadmi)) {
    break-inside: avoid;
    page-break-inside: avoid;
  }
}

@media (max-width: 560px) {
  .fig-cta-row { gap: 0.6rem; }
  .fig-skills-label { flex-basis: 100%; }
}

/* --- Back to top ----------------------------------------------------------
   Same button as home-draft.css's version (this page doesn't import that
   file, so it's repeated here rather than left out) — a long, scrolling
   page benefits from it just as much as the illustration homepage does.
   Styled to match .fig-cta--secondary (page-bg fill, 1px accent border,
   accent-coloured icon), kept circular/icon-only rather than the pill
   label shape. Uses --accent-rule directly (not --fig-accent) since this
   button sits outside .fig-page in the markup, so that scoped alias isn't
   in scope here — --accent-rule itself (from cv.css) is what it aliases
   anyway. */
/* Shared spring easing for both this button and .fig-float-cta below —
   a back-ease overshoot (the 1.7 control point sails past 1 before
   settling), applied to BOTH the hidden->visible and visible->hidden
   transform transitions (each state's own rule spells out the same
   curve explicitly, rather than one side inheriting it implicitly) so
   the bounce reads clearly on the way in and the way out, not just on
   arrival. */
.back-to-top {
  position: fixed;
  right: 1.5rem;
  bottom: 1.5rem;
  z-index: 50;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 48px;
  height: 48px;
  border: 1px solid var(--accent-rule);
  border-radius: 999px;
  background: var(--blue);
  color: var(--accent-rule);
  cursor: pointer;
  opacity: 0;
  visibility: hidden;
  transform: translateY(16px) scale(0.8);
  transition: opacity 0.3s ease, transform 0.35s cubic-bezier(0.34, 1.7, 0.64, 1),
    visibility 0s 0.3s;
}
.back-to-top.is-visible {
  opacity: 1;
  visibility: visible;
  transform: translateY(0) scale(1);
  transition: opacity 0.3s ease, transform 0.35s cubic-bezier(0.34, 1.7, 0.64, 1);
}
.back-to-top:hover { opacity: 0.92; transform: scale(1.05); }
.back-to-top.is-visible:hover { opacity: 0.92; }
.back-to-top:active { opacity: 1; transform: scale(0.95); transition-duration: 0.1s; }
@media (max-width: 768px) {
  .back-to-top { right: 1rem; bottom: 1rem; }
}

/* --- Floating Email me / Download CV ---------------------------------
   js/float-cta.js adds .is-active in lockstep with #back-to-top's own
   .is-visible (it watches that class directly via MutationObserver) —
   so this pair fades in/out at exactly the same scroll position as Back
   to top, with the same spring treatment. Laid out as a horizontal row,
   sharing Back to top's own bottom offset and sitting immediately to
   its left (left-aligned to it, on the same line) rather than stacked
   above it.

   --fig-accent redeclared here for the same reason .back-to-top uses
   --accent-rule directly instead: this wrapper sits outside .fig-page in
   the markup (after </article>, alongside #back-to-top), and --fig-accent
   is only ever defined scoped to .fig-page, so .fig-cta--primary/
   --secondary's var(--fig-accent) backgrounds/borders would otherwise
   resolve to nothing here — exactly what happened before this line
   existed: Email me's fill fell back to transparent, leaving its
   var(--blue) text sitting dark-on-dark against the page background. */
.fig-float-cta {
  --fig-accent: var(--accent-rule);
  position: fixed;
  /* Back to top: right 1.5rem + 48px wide (3rem) = its own left edge sits
     4.5rem in from the viewport's right edge; +0.75rem gap so this sits
     cleanly beside it rather than touching. Same bottom as Back to top
     puts both on one line. */
  right: 5.25rem;
  bottom: 1.5rem;
  z-index: 50;
  display: flex;
  flex-direction: row;
  flex-wrap: wrap; /* safety net on very narrow phones; doesn't engage at
    any width this site actually ships at */
  justify-content: flex-end;
  align-items: center;
  gap: 0.75rem;
  opacity: 0;
  visibility: hidden;
  transform: translateY(16px) scale(0.8);
  transition: opacity 0.3s ease, transform 0.35s cubic-bezier(0.34, 1.7, 0.64, 1),
    visibility 0s 0.3s;
}
.fig-float-cta.is-active {
  opacity: 1;
  visibility: visible;
  transform: translateY(0) scale(1);
  transition: opacity 0.3s ease, transform 0.35s cubic-bezier(0.34, 1.7, 0.64, 1);
}
@media (max-width: 768px) {
  .fig-float-cta { right: 4.75rem; bottom: 1rem; } /* matches .back-to-top's
    own 1rem mobile shift: 1rem + 3rem + 0.75rem gap */
}
/* Below ~460px there's no longer room beside Back to top for both
   buttons without crowding the right edge — fall back to stacking the
   pair above it instead, same spring, just back on the vertical axis. */
@media (max-width: 460px) {
  .fig-float-cta {
    right: 1rem;
    bottom: 4.75rem;
    flex-direction: column;
    align-items: flex-end;
  }
}
