/**
 * Anna — emerald and black.
 *
 * Where jjrhymes.com is heavy display type on near-black, this leans lighter: a serif that has
 * some air in it, wider letter-spacing, thin rules instead of solid blocks, and emerald used
 * sparingly as an accent rather than as a fill.
 */

:root {
  --an-bg:      #000000;   /* true black */
  --an-panel:   #070707;
  --an-raised:  #0e0e0e;
  --an-fg:      #f4faf7;
  --an-muted:   #adc2ba;   /* body copy — was too near the background to read easily */
  --an-dim:     #7d918a;   /* labels and captions */
  /* Deep emerald. The bright mint reads as neon against this much black — especially as text,
     where it was the loudest thing on the page. These sit back into the ground instead. */
  --an-accent:   #0b6e4f;  /* fills: buttons, the progress of things */
  --an-accent-2: #0f8a63;  /* hovers, and the large italic display type */
  --an-accent-tx:#12946a;  /* small labels — the floor for legibility on near-black */
  --an-line:    rgba(255,255,255,.15);
  --an-r:       3px;       /* squared — no pills anywhere */

  --an-serif: 'Cormorant Garamond', 'Didot', 'Georgia', serif;
  --an-sans:  'Jost', -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
  --an-ease:  cubic-bezier(.22,1,.36,1);
}

* { box-sizing: border-box; }
html { scroll-behavior: smooth; }
body {
  margin: 0; background: var(--an-bg); color: var(--an-fg);
  font: 400 16px/1.65 var(--an-sans);
  -webkit-font-smoothing: antialiased;
}
/* True black, flat. There was a vignette here and it was working against itself: darkening the
   edges is exactly what makes the middle read as a lighter grey. Nothing beats nothing. */
img { max-width: 100%; display: block; }
a { color: inherit; }

.an-wrap { width: min(1180px, calc(100vw - 48px)); margin-inline: auto; }

/* ── header ─────────────────────────────────────────────────────────── */
.an-head {
  position: fixed; inset: 0 0 auto; z-index: 100;
  /* Three columns rather than space-between: the nav is centred on the page, not on whatever
     room the brand and the portal button happen to leave it. */
  display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: 20px;
  padding: 18px clamp(16px, 4vw, 40px);
  background: color-mix(in oklab, var(--an-bg) 82%, transparent);
  -webkit-backdrop-filter: blur(14px); backdrop-filter: blur(14px);
  border-bottom: 1px solid transparent;
  transition: border-color .3s var(--an-ease), background .3s var(--an-ease);
}
.an-head.is-stuck { border-bottom-color: var(--an-line); }
.an-brand {
  font: 400 1.35rem/1 var(--an-serif); letter-spacing: .14em; text-transform: uppercase;
  text-decoration: none; color: var(--an-fg);
}
.an-brand em { font-style: normal; color: var(--an-accent-tx); }
.an-nav { display: flex; gap: clamp(14px, 3vw, 30px); justify-content: center; }
.an-brand { justify-self: start; }
.an-portal-link { justify-self: end; }
.an-nav a {
  font: 500 .7rem/1 var(--an-sans); letter-spacing: .18em; text-transform: uppercase;
  color: var(--an-muted); text-decoration: none; padding: 6px 0;
  border-bottom: 1px solid transparent; transition: color .2s, border-color .2s;
}
.an-nav a:hover { color: var(--an-fg); border-bottom-color: var(--an-accent); }
@media (max-width: 700px) { .an-nav a { letter-spacing: .1em; font-size: .64rem; } }

/* ── hero ───────────────────────────────────────────────────────────── */
.an-hero { position: relative; min-height: 100svh; display: grid; place-items: center; overflow: hidden; }
.an-hero-media { position: absolute; inset: 0; }
.an-hero-media img { width: 100%; height: 100%; object-fit: cover; opacity: .5; }
.an-hero-scrim {
  position: absolute; inset: 0;
  background:
    radial-gradient(80% 60% at 50% 45%, transparent 0%, var(--an-bg) 100%),
    linear-gradient(180deg, color-mix(in oklab, var(--an-bg) 70%, transparent) 0%, transparent 30%, var(--an-bg) 100%);
}
.an-hero-copy { position: relative; text-align: center; padding: 120px 20px 80px; }
.an-kicker {
  font: 500 .68rem/1 var(--an-sans); letter-spacing: .38em; text-transform: uppercase;
  color: var(--an-accent-tx); margin: 0 0 22px;
}
.an-hero h1 {
  margin: 0; font: 300 clamp(3rem, 11vw, 7.5rem)/0.95 var(--an-serif);
  letter-spacing: -.01em;
}
.an-hero h1 em { font-style: italic; color: var(--an-accent-2); }
.an-hero-sub {
  margin: 24px auto 0; max-width: 46ch; color: var(--an-muted);
  font: 300 1.02rem/1.7 var(--an-sans);
}
.an-hero-cta { margin-top: 38px; display: flex; gap: 12px; justify-content: center; flex-wrap: wrap; }

/* ── buttons ────────────────────────────────────────────────────────── */
.an-btn {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 13px 26px; border-radius: var(--an-r); cursor: pointer;
  font: 500 .72rem/1 var(--an-sans); letter-spacing: .16em; text-transform: uppercase;
  text-decoration: none; border: 1px solid var(--an-accent);
  background: var(--an-accent); color: #eaf5ef;
  transition: background .18s var(--an-ease), color .18s, border-color .18s;
}
.an-btn:hover { background: var(--an-accent-2); border-color: var(--an-accent-2); }
.an-btn-ghost { background: transparent; color: var(--an-fg); border-color: var(--an-line); }
.an-btn-ghost:hover { background: transparent; border-color: var(--an-accent); color: var(--an-accent-tx); }

/* ── sections ───────────────────────────────────────────────────────── */
.an-sec { padding: clamp(70px, 11vw, 130px) 0; }
.an-sec-head { margin-bottom: 46px; }
.an-sec-num {
  font: 500 .66rem/1 var(--an-sans); letter-spacing: .3em; text-transform: uppercase;
  color: var(--an-accent-tx); display: block; margin-bottom: 14px;
}
.an-sec-title { margin: 0; font: 300 clamp(2rem, 5vw, 3.2rem)/1.08 var(--an-serif); }
.an-sec-title em { font-style: italic; color: var(--an-accent-2); }
.an-lede { margin: 18px 0 0; max-width: 58ch; color: var(--an-muted); font-weight: 300; }
.an-rule { height: 1px; background: var(--an-line); border: 0; margin: 0; }

/* ── portfolio grid ─────────────────────────────────────────────────── */
/* Column count comes from the page: with one or two photos, three columns would render
   work as thumbnails. --cols is set inline from how many there actually are. */
.an-grid { columns: var(--cols, 3); column-gap: 14px; }
@media (max-width: 900px) { .an-grid { columns: min(var(--cols, 2), 2); } }
@media (max-width: 560px) { .an-grid { columns: 1; } }
.an-card {
  break-inside: avoid; margin-bottom: 14px; position: relative;
  border-radius: var(--an-r); overflow: hidden; background: var(--an-panel);
}
.an-card img { width: 100%; transition: transform .6s var(--an-ease), opacity .3s; }
.an-card:hover img { transform: scale(1.03); }
.an-card-tag {
  position: absolute; left: 12px; bottom: 12px;
  font: 500 .62rem/1 var(--an-sans); letter-spacing: .18em; text-transform: uppercase;
  color: var(--an-fg); background: rgba(0,0,0,.55); padding: 7px 11px; border-radius: var(--an-r);
  -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
  opacity: 0; transform: translateY(4px); transition: opacity .25s, transform .25s;
}
.an-card:hover .an-card-tag { opacity: 1; transform: none; }
/* A placeholder frame, until real photographs go in. */
.an-ph {
  aspect-ratio: var(--r, 3/4);
  background: linear-gradient(135deg, #101010 0%, var(--an-panel) 62%);
  display: grid; place-items: center;
  color: var(--an-dim); font: 500 .62rem/1 var(--an-sans); letter-spacing: .22em; text-transform: uppercase;
}

/* ── services ───────────────────────────────────────────────────────── */
.an-svc { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 1px; background: var(--an-line); }
.an-svc-item { background: var(--an-bg); padding: 34px 28px; }
.an-svc-item h3 { margin: 0 0 10px; font: 400 1.3rem/1.2 var(--an-serif); }
/* No trailing margin: the price line that used to sit under this is gone, so the padding of
   the card is what should set the bottom edge. */
.an-svc-item p { margin: 0; color: var(--an-muted); font-size: .92rem; font-weight: 300; }

/* ── footer ─────────────────────────────────────────────────────────── */
.an-foot { border-top: 1px solid var(--an-line); padding: 44px 0 60px; }
.an-foot-in { display: flex; align-items: center; justify-content: space-between; gap: 20px; flex-wrap: wrap; }
.an-foot small { color: var(--an-dim); font-size: .76rem; }
.an-foot-links { display: flex; gap: 18px; }
.an-foot-links a {
  font: 500 .68rem/1 var(--an-sans); letter-spacing: .16em; text-transform: uppercase;
  color: var(--an-muted); text-decoration: none;
}
.an-foot-links a:hover { color: var(--an-accent-tx); }

/* ── reveal on scroll ───────────────────────────────────────────────── */
.an-reveal { opacity: 0; transform: translateY(16px); transition: opacity .7s var(--an-ease), transform .7s var(--an-ease); }
.an-reveal.is-in { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) {
  .an-reveal { opacity: 1; transform: none; transition: none; }
  html { scroll-behavior: auto; }
}

/* The hero placeholder carries no label: it sits directly behind the headline, and its caption
   read as a watermark over her name. A real photograph goes here and the question disappears. */
.an-ph-hero { background: linear-gradient(165deg, #0e0e0e 0%, #000 70%); }


/* ── error pages ───────────────────────────────────────────────────────── */
.an-err { min-height: 100svh; display: grid; place-content: center; text-align: center; gap: 6px; padding: 40px 24px; }
.an-err-h { margin: 0; font: 300 clamp(2.4rem, 7vw, 4.2rem)/1.05 var(--an-serif); }
.an-err-p { margin: 6px 0 26px; color: var(--an-muted); font-weight: 300; }
.an-err .an-btn { justify-self: center; }

/* ── client portal, in the header ────────────────────────────────────────
   Set apart from the nav: those are places to browse, this is the way in to work already paid
   for. Bordered so it reads as an action at a glance. */
.an-portal-link {
  display: inline-flex; align-items: center; gap: 7px; flex: 0 0 auto;
  padding: 8px 14px; border-radius: var(--an-r); text-decoration: none;
  border: 1px solid var(--an-line); color: var(--an-muted);
  font: 500 .66rem/1 var(--an-sans); letter-spacing: .16em; text-transform: uppercase;
  transition: color .2s, border-color .2s;
}
.an-portal-link:hover { color: var(--an-accent-tx); border-color: var(--an-accent); }
.an-portal-link svg { opacity: .8; }
@media (max-width: 640px) {
  /* The word is the first thing to go; the padlock still says what it is. */
  .an-portal-link span { display: none; }
  .an-portal-link { padding: 8px 10px; }
  .an-nav { gap: 14px; }
}

/* A phone's hero is tall and narrow, which the desktop scrim was never shaped for. An ellipse
   80% wide and 60% tall leaves most of a 100svh screen outside its clear centre, and the linear
   gradient then lays solid black across the bottom. Stacked on a photograph already held at half
   opacity, three dark layers deep, the slideshow read as a grey rectangle rather than a picture.
   Open the clear area up, start the fade later, and let more of the photo through — then put the
   contrast back where it is actually needed, behind the words, instead of over the whole frame. */
@media (max-width: 640px) {
  .an-hero-media img,
  .an-hero-slide img { opacity: .7; }
  .an-hero-scrim {
    background:
      radial-gradient(130% 80% at 50% 38%, transparent 0%, var(--an-bg) 100%),
      linear-gradient(180deg, color-mix(in oklab, var(--an-bg) 55%, transparent) 0%, transparent 44%, var(--an-bg) 100%);
  }
  .an-hero-copy { text-shadow: 0 1px 18px var(--an-bg), 0 0 42px var(--an-bg); }
}

/* ── work lightbox ───────────────────────────────────────────────────────
   Same shape and same behaviour as jjrhymes.com/photo: close top-right, the photo capped at
   90vw/80vh, prev · counter · next grouped at the foot, and a hint under that. No minimap —
   that belongs to the client portal, where a gallery is long enough to get lost in. */
.an-card.is-open { cursor: zoom-in; }
body.an-locked { overflow: hidden; position: fixed; width: 100%; }

.an-lb {
  position: fixed; inset: 0; z-index: 200;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  background: rgba(0,0,0,.95);
  opacity: 0; transition: opacity .28s var(--an-ease);
}
.an-lb.is-in { opacity: 1; }
.an-lb[hidden] { display: none !important; }

.an-lb-wrap {
  flex: 1; display: flex; align-items: center; justify-content: center;
  width: 100%; overflow: hidden; cursor: default; position: relative;
}
.an-lb-img {
  max-width: 90vw; max-height: 80vh; object-fit: contain; cursor: zoom-in;
  transition: transform .32s var(--an-ease); will-change: transform;
  user-select: none; -webkit-user-drag: none;
}
.an-lb-wrap.is-zoomed { cursor: grab; }
.an-lb-wrap.is-zoomed .an-lb-img { cursor: grab; transition: transform .12s linear; }

.an-lb-close {
  position: absolute; top: 18px; right: 18px; z-index: 2;
  width: 40px; height: 40px; display: grid; place-items: center;
  background: transparent; border: 1px solid var(--an-line); border-radius: var(--an-r);
  color: var(--an-fg); font-size: 1.5rem; line-height: 1; cursor: pointer;
  transition: border-color .18s, color .18s;
}
.an-lb-nav {
  display: flex; align-items: center; gap: 18px; padding: 18px 0 6px;
}
.an-lb-prev, .an-lb-next {
  width: 42px; height: 38px; display: grid; place-items: center;
  background: transparent; border: 1px solid var(--an-line); border-radius: var(--an-r);
  color: var(--an-fg); font-size: 1.05rem; line-height: 1; cursor: pointer;
  transition: border-color .18s, color .18s;
}
.an-lb-close:hover, .an-lb-prev:hover, .an-lb-next:hover {
  border-color: var(--an-accent); color: var(--an-accent-tx);
}
.an-lb-count {
  min-width: 58px; text-align: center;
  font: 500 .7rem/1 var(--an-sans); letter-spacing: .18em; color: var(--an-muted);
  font-variant-numeric: tabular-nums;
}
/* Zoom minimap — the same cue as jjrhymes.com's lightboxes: a thumbnail of the whole frame with
   a box showing which part of it you are currently looking at. Without it, zooming into a large
   photograph on a small screen leaves you with no idea where you are in the picture. Her accent
   green marks the viewport rather than his gold. */
.an-lb-minimap {
  position: absolute; bottom: 16px; right: 16px; z-index: 10;
  width: 120px; height: 120px; overflow: hidden;
  border: 1px solid rgba(255,255,255,.25); background: rgba(0,0,0,.6);
  opacity: 0; pointer-events: none; transition: opacity .2s;
}
.an-lb-minimap img { width: 100%; height: 100%; object-fit: contain; }
.an-lb-minimap-view {
  position: absolute; pointer-events: none;
  border: 1.5px solid var(--an-accent-tx); background: rgba(255,255,255,.08);
}

.an-lb-hint {
  margin: 0 0 22px; font: 400 .66rem/1 var(--an-sans); letter-spacing: .14em;
  text-transform: uppercase; color: var(--an-dim);
}
@media (max-width: 640px) {
  .an-lb-close { top: 12px; right: 12px; }
  /* Top-left on a phone, clear of the close control on the right. */
  .an-lb-minimap { top: 12px; left: 12px; bottom: auto; right: auto; width: 78px; height: 78px; }
  .an-lb-img { max-width: 96vw; }
  .an-lb-hint { display: none; }
  /* Zoomed on a phone the frame takes the height available, so a landscape photo is not stuck
     in a letterbox. It still gets a cap: removing the cap entirely laid the image out at its
     natural size — thousands of pixels wide — and the 2.5x transform then multiplied THAT, which
     is why zooming used to land you somewhere deep inside the photo with no way to tell where. */
  .an-lb-wrap.is-zoomed .an-lb-img { max-width: 100vw; max-height: calc(100dvh - 108px); }
}
@media (prefers-reduced-motion: reduce) { .an-lb, .an-lb-img { transition: none; } }

/* ── hero slideshow ──────────────────────────────────────────────────────
   Stacked and cross-faded. Held at low opacity because the headline sits on top of it — the
   photograph is atmosphere here, not the subject. */
.an-hero-slide {
  position: absolute; inset: 0;
  opacity: 0; transition: opacity 1.6s var(--an-ease);
}
.an-hero-slide.is-active { opacity: 1; }
.an-hero-slide img { width: 100%; height: 100%; object-fit: cover; opacity: .5; }
@media (prefers-reduced-motion: reduce) { .an-hero-slide { transition: none; } }

/* ── loading ─────────────────────────────────────────────────────────────
   Held until the first hero frame has decoded, then faded out. The page underneath is fully
   laid out the whole time — this only covers the moment where the hero would otherwise pop. */
.an-load {
  position: fixed; inset: 0; z-index: 300;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 22px;
  background: var(--an-bg);
  transition: opacity .55s var(--an-ease);
}
/* The visibility delay belongs to the hiding direction only — on the base rule it also delayed
   the curtain appearing, which matters the moment anything shows it again. */
body:not(.is-loading) .an-load {
  opacity: 0; visibility: hidden;
  transition: opacity .55s var(--an-ease), visibility 0s linear .55s;
}
.an-load-mark {
  font: 400 1.5rem/1 var(--an-serif); letter-spacing: .34em; text-transform: uppercase;
  color: var(--an-fg); padding-left: .34em;   /* the tracking would otherwise sit it off-centre */
}
.an-load-bar {
  width: 132px; height: 1px; background: rgba(255,255,255,.14); overflow: hidden;
}
.an-load-bar span {
  display: block; width: 40%; height: 100%; background: var(--an-accent-tx);
  animation: an-sweep 1.15s var(--an-ease) infinite;
}
@keyframes an-sweep { 0% { transform: translateX(-110%); } 100% { transform: translateX(360%); } }

/* Nothing should move behind the curtain — reveals wait until it lifts. */
body.is-loading { overflow: hidden; }

@media (prefers-reduced-motion: reduce) {
  .an-load { transition: none; }
  .an-load-bar span { animation: none; width: 100%; opacity: .5; }
}


/* ── about ───────────────────────────────────────────────────────────────
   A reading page, so it is built around measure rather than around images: one column of prose
   at a comfortable line length, with her photograph beside it on a wide screen and above it on a
   narrow one. The landing page carries a short version of the same text and links here. */
.an-about { padding: 128px 0 96px; }
.an-about-head { max-width: 46rem; }
.an-about-title {
  margin: 0; font: 300 clamp(2.6rem, 8vw, 5rem)/1.02 var(--an-serif); letter-spacing: -.01em;
}
.an-about-title em { font-style: italic; color: var(--an-accent-2); }
.an-about-lede {
  margin: 20px 0 0; max-width: 40ch;
  color: var(--an-muted); font: 300 1.08rem/1.7 var(--an-sans);
}

.an-about-body {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr);
  gap: clamp(28px, 5vw, 64px); align-items: start; margin-top: clamp(44px, 7vw, 72px);
}
.an-about-fig { margin: 0; overflow: hidden; border: 1px solid var(--an-line); }
.an-about-fig img { display: block; width: 100%; height: auto; }

/* 68 characters is about as wide as a line can get before the eye starts losing its place on
   the way back to the left margin. */
.an-prose { max-width: 68ch; }
.an-prose p {
  margin: 0 0 1.15em; color: var(--an-fg);
  font: 300 1.06rem/1.85 var(--an-sans);
}
.an-prose p:last-child { margin-bottom: 0; }
.an-prose p:first-child::first-letter {
  float: left; margin: .06em .1em 0 0;
  font: 300 3.1rem/0.82 var(--an-serif); color: var(--an-accent-2);
}

.an-about-what { margin-top: clamp(40px, 6vw, 64px); }
.an-about-what .an-sec-title { margin-bottom: 26px; }
.an-about-cta { display: flex; gap: 12px; flex-wrap: wrap; margin-top: clamp(40px, 6vw, 64px); }

/* The landing page's short bio needs a way through to the long one. */
.an-about-more { margin-top: 22px; }

@media (max-width: 820px) {
  .an-about { padding: 104px 0 72px; }
  /* Her photograph leads on a phone: it is the first thing that says who the page is about. */
  .an-about-body { grid-template-columns: 1fr; }
  .an-about-fig { order: -1; max-width: 420px; }
  .an-prose p { font-size: 1rem; line-height: 1.8; }
  .an-prose p:first-child::first-letter { font-size: 2.7rem; }
}


/* ── touch targets ───────────────────────────────────────────────────────
   Measured on a 375px screen, the nav links came out 23px tall and the footer links 11px. A
   finger pad is nearer 44px, so those were a game of darts. The hit area is widened with a
   pseudo-element rather than with padding: padding would push the fixed header from 59px to
   nearly 80px, and vertical space is the one thing a phone has least of. The element stays
   exactly where it is and only the area that answers a tap grows.

   Insets are kept smaller than the gap between neighbours so two targets never overlap:
   the nav sits on a 14px gap, the footer links on 18px. */
@media (pointer: coarse) {
  .an-nav a, .an-foot-links a, .an-brand, .an-portal-link { position: relative; }
  .an-nav a::after,
  .an-foot-links a::after,
  .an-brand::after,
  .an-portal-link::after {
    content: ''; position: absolute; left: -6px; right: -6px;
    top: 50%; transform: translateY(-50%); height: 44px;
  }
  /* The buttons measured 40px — close, and reachable with a little more vertical padding
     without changing how they read. */
  .an-btn { padding: 15px 26px; }
}


/* ── back link ───────────────────────────────────────────────────────────
   Sits above the page title on the About page. Muted until hovered, and the arrow slides left
   on approach so the direction is felt before the word is read. */
/* A muted text link was too quiet for the one control that gets a visitor off this page, so it
   carries the same button shape as the rest of the site. The border makes it a thing you press
   rather than a caption you read past. */
.an-back { margin-bottom: clamp(26px, 4vw, 40px); }
.an-back-arrow { display: inline-block; transition: transform .2s var(--an-ease); }
.an-back:hover .an-back-arrow { transform: translateX(-4px); }

/* The read-more was a ghost button, which put it at the same weight as "See the work" and read
   as an aside. It is the only route to the full page, so it gets the solid treatment. */
.an-about-more-arrow { display: inline-block; transition: transform .2s var(--an-ease); }
.an-about-more:hover .an-about-more-arrow { transform: translateX(3px); }

@media (prefers-reduced-motion: reduce) {
  .an-back-arrow, .an-about-more-arrow { transition: none; }
}
