/* Dillon Antunes — photographer portfolio.
   Black background, Space Mono, masonry image grid with thin gaps. */

@import url('https://fonts.googleapis.com/css2?family=Space+Mono:wght@400;700&display=swap');

:root {
  --bg: #000000;
  --ink: #ffffff;
  --muted: #6b6b6b;
  /* V2: dropped the red for a warm teal as the highlight colour. Easy to
     swap once Dillon picks a final shade. */
  --accent: #2dd4bf;
  --pad: 28px;
  --gutter: 36px;
  --gap: 6px;
  --col-count: 4;
  --shot-col-count: 2;
  --header-h: 82px;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: "Space Mono", ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  font-size: 13px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

a {
  color: inherit;
  text-decoration: none;
}
a:hover { color: var(--muted); }

img { display: block; max-width: 100%; height: auto; }

/* Header: IG icon + email on the left, logo dead-centre, Contact on right.
   Sticky so it stays glued to the top while the grid scrolls past. */
.da-header {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  padding: var(--pad) var(--pad) var(--pad) var(--pad);
  gap: 16px;
  position: sticky;
  top: 0;
  z-index: 50;
  background: var(--bg);
}

/* Left cluster: IG icon, vertical separator, email. */
.da-header-left {
  justify-self: start;
  display: flex;
  align-items: center;
  gap: 12px;
  font-size: 13px;
  letter-spacing: 0.01em;
}

.da-header-sep {
  display: inline-block;
  color: var(--muted);
  opacity: 0.6;
  user-select: none;
}

/* Right cluster: Contact link (opens overlay). */
.da-header-right {
  justify-self: end;
  display: flex;
  align-items: center;
  gap: 14px;
  font-size: 13px;
  letter-spacing: 0.01em;
}

.da-contact-trigger {
  background: none;
  border: 0;
  color: inherit;
  font-family: inherit;
  font-size: inherit;
  letter-spacing: inherit;
  cursor: pointer;
  padding: 0;
  user-select: none;
}
.da-contact-trigger { transition: color 200ms ease; }
@media (hover: hover) {
  .da-contact-trigger:hover { color: var(--accent); }
}

/* Logo: short "DNA" by default, expands to "DILLON NATHAN ANTUNES" on hover.
   Both labels live in a single grid cell so they share an exact baseline.
   Container is always sized to the longer label so the centred position
   never shifts mid-animation, and only opacity crossfades. All caps. */
.da-logo {
  justify-self: center;
  text-decoration: none;
  color: inherit;
  font-weight: 400;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  white-space: nowrap;
  cursor: pointer;
  user-select: none;
}

.da-logo:hover { color: inherit; }

.da-logo-stack {
  display: inline-grid;
  grid-template-columns: max-content;
  justify-items: center;
  align-items: baseline;
}

.da-logo-short,
.da-logo-long {
  grid-row: 1;
  grid-column: 1;
  transition: opacity 320ms cubic-bezier(.4,0,.2,1);
  line-height: 1;
}

/* V2: default state is the FULL NAME, hover collapses to the D_N_A mark. */
.da-logo-long { opacity: 1; }
.da-logo-short { opacity: 0; }

.da-logo:hover .da-logo-long,
.da-logo:focus-visible .da-logo-long { opacity: 0; }
.da-logo:hover .da-logo-short,
.da-logo:focus-visible .da-logo-short { opacity: 1; }

.da-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  margin: -6px 0;
  color: inherit;
}
.da-icon { transition: color 200ms ease; }
@media (hover: hover) {
  .da-icon:hover { color: var(--accent); }
}
.da-email { transition: color 200ms ease; }
@media (hover: hover) {
  .da-email:hover { color: var(--accent); }
}

.da-icon svg {
  display: block;
  width: 18px;
  height: 18px;
}

/* ---------- Contact overlay ---------- */
.da-contact-overlay {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: none;
  align-items: center;
  justify-content: center;
  background: rgba(0, 0, 0, 0.72);
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
  cursor: zoom-out;
  -webkit-tap-highlight-color: transparent;
}
.da-contact-overlay.is-open { display: flex; }

.da-contact-content {
  max-width: 720px;
  width: 100%;
  padding: 64px 48px;
  text-align: center;
  cursor: default;
}

.da-contact-mark {
  font-size: 68px;
  letter-spacing: 0.12em;
  margin: 0 0 48px 0;
  font-weight: 400;
  text-transform: uppercase;
  color: var(--ink);
}

.da-contact-bio {
  font-size: 17px;
  line-height: 1.75;
  margin: 0 0 44px 0;
  letter-spacing: 0.04em;
  color: var(--ink);
  max-width: 42ch;
  margin-left: auto;
  margin-right: auto;
}

.da-contact-details {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
  font-size: 16px;
  letter-spacing: 0.05em;
}
.da-contact-details a {
  color: var(--ink);
  border-bottom: 1px solid transparent;
  transition: color 200ms ease, border-color 200ms ease;
}
@media (hover: hover) {
  .da-contact-details a:hover { color: var(--accent); border-bottom-color: var(--accent); }
}

.da-contact-close {
  position: absolute;
  top: 18px;
  right: 22px;
  background: none;
  border: 0;
  color: #fff;
  cursor: pointer;
  padding: 10px;
  line-height: 0;
  opacity: 0.85;
  transition: opacity 180ms ease;
}
.da-contact-close:hover { opacity: 1; }
.da-contact-close svg { display: block; width: 22px; height: 22px; }

body.da-contact-locked { overflow: hidden; }

@media (max-width: 720px) {
  .da-contact-content { padding: 36px 22px; }
  .da-contact-mark { font-size: 32px; margin-bottom: 24px; }
  .da-contact-bio { font-size: 12px; margin-bottom: 24px; }
  .da-contact-details { font-size: 12px; }
}

/* Visibility helpers for mobile/desktop swap (e.g. shrink email label). */
.da-only-mobile { display: none; }
.da-only-desktop { display: inline; }

.da-main {
  display: block;
  padding: 16px var(--pad) 0 var(--pad);
}

/* HOME — masonry image grid, now JS-driven via masonry.js so we get the
   tight Pinterest pack (shortest-column placement) instead of the CSS
   columns balance algorithm, which kept stranding the last tile alone
   at the bottom of one side. --cols is the column count the JS reads. */
.da-grid {
  --cols: var(--col-count);
  position: relative;
  opacity: 0;
  transition: opacity 520ms cubic-bezier(.4,0,.2,1);
}
.da-grid.is-ready { opacity: 1; }


.da-tile {
  display: block;
  width: 100%;
  position: relative;
  overflow: hidden;
  line-height: 0; /* kill the inline-image baseline space */
  background: #050505;
  cursor: pointer;
}

.da-tile img {
  width: 100%;
  height: auto;
  opacity: 0;
  transition: opacity 480ms cubic-bezier(.4,0,.2,1);
}

/* Fade in once decoded — JS adds .is-loaded. Layout is already locked by
   the explicit width/height attributes on each <img>, so this fade only
   touches opacity and never reflows. */
.da-tile img.is-loaded { opacity: 1; }

.da-tile:hover img.is-loaded { opacity: 0.88; }

/* Empty-slot fallback (no image yet). */
.da-tile.is-empty {
  background: #0c0c0c;
  border: 1px dashed #1f1f1f;
  aspect-ratio: 4 / 5;
  line-height: 1.4;
}

/* PROJECT pages: sidebar (project list) + content (numbered shot grid). */
.da-project-layout {
  display: flex;
  align-items: flex-start;
  gap: var(--gutter);
}

.da-sidebar {
  flex: 0 0 auto;
  width: 280px;
  min-width: 240px;
  /* Sticky once the page scrolls — pinned just under the sticky header so
     the PROJECTS title sits clean against the header bottom edge. */
  position: sticky;
  top: calc(var(--header-h) + 8px);
  align-self: flex-start;
}

.da-section-title {
  margin-bottom: 8px;
  color: var(--muted);
  letter-spacing: 0.05em;
  text-transform: uppercase;
  font-size: 11px;
}

.da-project-list {
  list-style: none;
  padding: 0;
  margin: 0;
}

.da-project-list li { padding: 1px 0; letter-spacing: 0.01em; }
.da-project-list a {
  color: var(--muted);
  cursor: pointer;
  user-select: none;       /* no text-cursor over the project name */
}
.da-project-list a:hover { color: var(--ink); }
.da-project-list a.is-current { color: var(--accent); }
.da-project-list .da-project-num { color: var(--muted); }
.da-project-list a.is-current .da-project-num { color: var(--accent); }

.da-content {
  flex: 1 1 auto;
  min-width: 0;
}

/* Project shot grid: JS-driven masonry. The container is a positioning
   context; masonry.js places each .da-shot in the shortest column on
   page load and on resize, giving the tight Pinterest-style pack with
   no holes regardless of aspect mix. Falls back to a stacked single-
   column flow if JS doesn't run. */
.da-shot-grid {
  --cols: var(--shot-col-count);
  position: relative;
  opacity: 0;
  transition: opacity 520ms cubic-bezier(.4,0,.2,1);
}
.da-shot-grid.is-ready { opacity: 1; }

/* In flow before masonry.js runs, .da-shot lays out as a normal block.
   Once masonry.js measures the container it switches each .da-shot to
   absolute positioning with explicit top/left/width, packing the tiles
   tight against each other (no big black gaps under a short image). */
.da-shot {
  display: block;
  width: 100%;
  line-height: 0;
  cursor: pointer;
  background: #050505;
}

.da-shot img {
  width: 100%;
  height: auto;
  opacity: 0;
  transition: opacity 480ms cubic-bezier(.4,0,.2,1);
}
.da-shot img.is-loaded { opacity: 1; }
.da-shot:hover img.is-loaded { opacity: 0.88; }

/* Info / prose pages. */
.da-prose {
  max-width: 56ch;
  font-size: 13px;
  line-height: 1.7;
}
.da-prose p { margin: 0 0 1em; }
.da-prose a { color: var(--ink); border-bottom: 1px dotted #333; }

.da-footer {
  padding: 56px var(--pad) var(--pad) var(--pad);
  font-size: 11px;
  color: var(--muted);
  letter-spacing: 0.04em;
}
/* Desktop, campaign pages only: pin the maker mark to bottom-left of viewport. */
@media (min-width: 720px) {
  .page-project .da-footer {
    position: fixed;
    left: 0;
    bottom: 0;
    padding: 12px var(--pad);
    z-index: 50;
    pointer-events: none;
  }
  .page-project .da-footer .da-mark { pointer-events: auto; }
}
/* Maker mark - small courier signature, discrete, links to fraz.photo. */
.da-mark {
  font-family: 'Courier New', ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 10px;
  letter-spacing: 0.22em;
  color: var(--muted);
  text-decoration: none;
  text-transform: uppercase;
  padding: 4px 0;
  transition: color 200ms ease, letter-spacing 200ms ease;
  -webkit-tap-highlight-color: transparent;
}
.da-mark:hover,
.da-mark:focus-visible {
  color: var(--ink);
  letter-spacing: 0.28em;
  outline: none;
}

/* ---------- Lightbox ---------- */
/* Shown when a .da-shot is clicked; JS toggles .is-open. Backdrop click,
   Escape, or the close button exits. Arrow keys / arrows / swipe cycle. */
.da-lightbox {
  position: fixed;
  inset: 0;
  z-index: 1000;
  display: none;
  align-items: center;
  justify-content: center;
  background: rgba(0, 0, 0, 0.96);
  cursor: zoom-out;
  user-select: none;
  -webkit-tap-highlight-color: transparent;
}

.da-lightbox.is-open { display: flex; }

/* Stage wraps the image AND its caption so the caption can anchor to the
   image's actual rendered edges — title under the left, counter under the
   right. The image carries the viewport-based size limits, and the stage
   auto-shrinks around it so the caption row matches its width exactly. */
.da-lb-stage {
  display: flex;
  flex-direction: column;
  align-items: stretch;
}

.da-lb-image {
  display: block;
  max-width: calc(100vw - 200px);
  max-height: calc(100vh - 140px);
  width: auto;
  height: auto;
  object-fit: contain;
  cursor: default;
}

.da-lb-caption {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  padding-top: 14px;
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}
.da-lb-title { color: var(--ink); }
.da-lb-counter { color: var(--muted); }

.da-lb-btn {
  position: absolute;
  background: none;
  border: 0;
  color: #fff;
  cursor: pointer;
  padding: 12px;
  line-height: 0;
  opacity: 0.85;
  transition: opacity 180ms ease;
  z-index: 2;
}
.da-lb-btn:hover, .da-lb-btn:focus-visible { opacity: 1; outline: none; }
.da-lb-btn svg { display: block; }

.da-lb-close { top: 18px; right: 22px; }
.da-lb-close svg { width: 22px; height: 22px; }

.da-lb-prev,
.da-lb-next {
  top: 50%;
  transform: translateY(-50%);
}
.da-lb-prev { left: 20px; }
.da-lb-next { right: 20px; }
.da-lb-prev svg,
.da-lb-next svg { width: 34px; height: 34px; }

body.da-lb-locked { overflow: hidden; }

/* Lightbox mobile sizing — hide arrows, rely on swipe. */
@media (max-width: 720px) {
  .da-lb-image {
    max-width: calc(100vw - 24px);
    max-height: calc(100vh - 130px);
  }
  .da-lb-prev, .da-lb-next { display: none; }
  .da-lb-close { top: 12px; right: 14px; padding: 8px; }
  .da-lb-close svg { width: 18px; height: 18px; }
  .da-lb-caption { font-size: 10px; padding-top: 10px; }
}

/* Wide desktop — bump campaign shot grid to 3 cols when there's plenty of room. */
@media (min-width: 1600px) {
  :root { --shot-col-count: 3; }
}

/* Tablet. */
@media (max-width: 1100px) {
  :root { --col-count: 3; --shot-col-count: 2; }
}

/* Mobile. */
@media (max-width: 720px) {
  :root { --pad: 14px; --gutter: 18px; --gap: 3px; --col-count: 2; --shot-col-count: 2; --header-h: 60px; }

  body { font-size: 12px; }

  .da-header {
    align-items: center;
    padding: var(--pad) var(--pad) 0 var(--pad);
    gap: 10px;
  }

  .da-logo { font-size: 11px; letter-spacing: 0.08em; }

  /* Mobile keeps both labels in the grid stack so the intro animation can
     flash DILLON NATHAN ANTUNES and condense to DNA. After the intro the
     column stays sized to the longer label, but DNA centres cleanly in it
     and there's still room for the IG icon and email on each side. */
  .da-logo:hover .da-logo-short,
  .da-logo:focus-visible .da-logo-short { opacity: 1; }
  .da-logo:hover .da-logo-long,
  .da-logo:focus-visible .da-logo-long { opacity: 0; }

  .da-header-right {
    gap: 10px;
    font-size: 12px;
  }

  .da-icon { width: 28px; height: 28px; }
  .da-icon svg { width: 17px; height: 17px; }

  /* On phones the full email is too long for the top row, swap for "Email". */
  .da-only-desktop { display: none; }
  .da-only-mobile { display: inline; }

  /* Mobile: hide the email link and "|" separator. Just IG top-left and
     Contact top-right. Email still lives in the Contact overlay. */
  .da-email,
  .da-header-sep { display: none; }

  .da-main { padding-top: 12px; }

  /* Project pages: stack sidebar above content, but compact it so it doesn't
     dominate the viewport. Use a horizontally scrollable strip. */
  .da-project-layout {
    flex-direction: column;
    gap: 14px;
  }

  .da-sidebar {
    width: 100%;
    min-width: 0;
    /* Sticky doesn't make sense in the horizontal-strip layout — reset. */
    position: static;
    top: auto;
  }

  .da-section-title {
    font-size: 10px;
    margin-bottom: 6px;
  }

  .da-project-list {
    list-style: none;
    padding: 0;
    margin: 0;
    display: flex;
    gap: 14px;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    white-space: nowrap;
    scrollbar-width: none;
    padding-bottom: 4px;
  }

  .da-project-list::-webkit-scrollbar { display: none; }

  .da-project-list li {
    padding: 0;
    flex: 0 0 auto;
  }

  .da-project-list li::marker { content: ""; }

  .da-project-list a {
    font-size: 11px;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--muted);
  }

  .da-project-list a.is-current { color: var(--accent); }

  .da-footer { padding: 32px var(--pad) 24px var(--pad); }
}
