:root {
  --bg: #0a0a0b;
  --bg-2: #111114;
  --fg: #f4f4f5;
  --muted: #8a8a92;
  --accent: #ff3d2e;      /* sports-creative red */
  --line: #232327;
  --gap: 10px;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  background: var(--bg);
  color: var(--fg);
  font-family: "Helvetica Neue", Arial, system-ui, sans-serif;
  -webkit-font-smoothing: antialiased;
}

a { color: inherit; text-decoration: none; }

/* ---------- Header / nav ---------- */
.site-header {
  position: sticky;
  top: 0;
  z-index: 10;
  background: rgba(10, 10, 11, 0.92);
  backdrop-filter: blur(8px);
  border-bottom: 1px solid var(--line);
  padding: 14px clamp(16px, 4vw, 48px);
}

.brand {
  display: flex;
  align-items: baseline;
  gap: 12px;
  flex-wrap: wrap;
}

.brand-name {
  font-size: clamp(1.4rem, 3.4vw, 2.1rem);
  font-weight: 800;
  letter-spacing: -0.02em;
  text-transform: uppercase;
}

.brand-tag {
  font-size: 0.72rem;
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: var(--accent);
  font-weight: 700;
}

.tab-nav {
  display: flex;
  gap: clamp(10px, 2.5vw, 26px);
  margin-top: 12px;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
}
.tab-nav::-webkit-scrollbar { display: none; }

.tab {
  white-space: nowrap;
  font-size: 0.9rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--muted);
  padding: 4px 0;
  border-bottom: 2px solid transparent;
  transition: color 0.15s, border-color 0.15s;
}
.tab:hover { color: var(--fg); }
.tab.active {
  color: var(--fg);
  border-bottom-color: var(--accent);
}
.tab.disabled {
  color: #4a4a50;
  cursor: default;
}

/* ---------- Gallery grid ---------- */
main { padding: clamp(16px, 4vw, 48px); }

.photo-grid {
  /* Justified rows (round 2): photos read left-to-right in number order, then
     wrap to the next row — not top-to-bottom down columns. Each row is scaled to
     a shared height and sits flush to both edges. A tile's width tracks its own
     aspect ratio (--ar, set inline per photo), so portrait and landscape frames
     sit side by side with no crop. */
  --row-h: 260px;
  display: flex;
  flex-wrap: wrap;
  gap: var(--gap);
}
@media (max-width: 760px) { .photo-grid { --row-h: 200px; } .tile { max-width: none; } }
@media (max-width: 440px) { .photo-grid { --row-h: 165px; } }

.tile {
  --ar: 1;                                  /* width / height — set inline per photo */
  flex-grow: var(--ar);                     /* grow ∝ aspect → every tile in a row scales to one height */
  flex-shrink: 1;
  flex-basis: calc(var(--ar) * var(--row-h));
  max-width: calc(var(--ar) * var(--row-h) * 1.9);  /* bound a lone photo left on the last row — caps WIDTH, so the whole frame always shows (no crop) */
  margin: 0;
  background: var(--bg-2);
  overflow: hidden;
  border-radius: 4px;
  position: relative;
}

.tile img {
  display: block;
  width: 100%;
  height: auto;
  transition: transform 0.35s ease, filter 0.35s ease;
  filter: saturate(0.95);
}
.tile:hover img {
  transform: scale(1.035);
  filter: saturate(1.1);
}

.tile { cursor: zoom-in; }

/* ---------- Social (live Instagram embeds) ---------- */
.social { max-width: 1360px; margin: 0 auto; }
.social-intro {
  color: var(--muted);
  font-size: 0.9rem;
  letter-spacing: 0.01em;
  text-align: center;
  margin: 0 0 24px;
}

.ig-grid {
  /* Masonry via CSS columns: the cards vary a lot in height (single photos, carousels,
     reels, short vs. long captions), so packing them top-to-bottom per column avoids the
     ragged vertical gaps a fixed row-grid leaves. Column count tracks the width — ~4 on a
     wide desktop down to 1 on a phone — and never narrower than an embed's 326px floor. */
  column-width: 320px;
  column-gap: 18px;
}

/* embed.js gives every card a 326px min-width + its own margins; neutralise so a card
   fills its column, keeps an even vertical rhythm, and never splits across a column break.
   Matches the pre-render blockquote AND the injected iframe (both carry .instagram-media). */
.ig-grid .instagram-media {
  break-inside: avoid;
  width: 100% !important;
  max-width: 540px !important;
  min-width: 0 !important;
  margin: 0 0 18px !important;
}

/* Pre-render / no-JS state: a tidy dark card with a themed link rather than a bare blue
   anchor. Once embed.js swaps in the iframe (.instagram-media-rendered), this is gone. */
.ig-grid > .instagram-media:not(.instagram-media-rendered) {
  width: 100%;
  max-width: 540px;
  min-height: 120px;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 36px 20px;
  background: var(--bg-2);
  border: 1px solid var(--line);
  border-radius: 8px;
}
.ig-grid > .instagram-media:not(.instagram-media-rendered) a {
  color: var(--accent);
  font-weight: 600;
  letter-spacing: 0.02em;
}

/* The lazy-load tile: the dark card that stands in for an embed until social.js drops
   the real one into it. The reserved 560px does two jobs. It settles the column layout
   on first paint, so cards arrive without shoving the page around — and it holds the
   queue in place while they arrive. Without it, the first cards hydrating would shrink
   the grid, pull every card below into view, and load the lot at once: the slow tab
   again, by another route. A real card that runs taller than 560px just grows. */
.ig-tile {
  break-inside: avoid;
  width: 100%;
  max-width: 540px;
  min-height: 560px;
  margin: 0 0 18px;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 36px 20px;
  background: var(--bg-2);
  border: 1px solid var(--line);
  border-radius: 8px;
}

/* Once the real embed is in, the tile is just a frame: the card brings its own chrome,
   and the placeholder link steps aside. */
.ig-tile[data-hydrated="true"] {
  display: block;
  padding: 0;
  background: none;
  border: 0;
}
.ig-tile[data-hydrated="true"] .ig-tile-link { display: none; }

.ig-tile .ig-tile-link {
  color: var(--accent);
  font-weight: 600;
  letter-spacing: 0.02em;
}

/* ---- Poster cards (the facade) ----
   A tile with a poster is just the picture: it sizes to the image's own aspect ratio,
   so the masonry packs true and nothing jumps when the real embed arrives. The tall
   empty skeleton only applies to tiles still waiting on a live embed. */
.ig-tile.has-poster {
  min-height: 0;
  padding: 0;
  overflow: hidden;
}
.ig-tile.has-poster .ig-tile-link { display: none; }

.ig-poster {
  display: block;
  position: relative;
  width: 100%;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
  line-height: 0;
}
.ig-poster img {
  display: block;
  width: 100%;
  height: auto;
  transition: opacity 0.18s ease, transform 0.35s ease;
}
.ig-poster:hover img,
.ig-poster:focus-visible img { transform: scale(1.02); opacity: 0.92; }
.ig-poster:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* A small mark so the picture reads as a post to open, not a gallery photo. */
.ig-poster-badge {
  position: absolute;
  left: 12px;
  bottom: 12px;
  padding: 5px 10px;
  border-radius: 999px;
  background: rgba(0, 0, 0, 0.62);
  color: #fff;
  font-size: 0.72rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  line-height: 1.1;
  backdrop-filter: blur(3px);
}

/* While the embed builds, the photo stays in normal flow — it is what gives the
   tile its height, so it must never leave the layout (absolute-positioning it
   collapsed every tile to a strip, Bing 2026-09-15). Instead the embed is the one
   held out of flow, invisible, until the JS has seen a real rendered iframe
   (.embed-ready) — then they trade places in one swap. */
.ig-tile.is-loading { position: relative; overflow: hidden; }
.ig-tile.is-loading blockquote,
.ig-tile.is-loading iframe,
.ig-tile.is-loading .instagram-media {
  position: absolute !important;
  top: 0;
  left: 0;
  width: 100% !important;
  visibility: hidden;
}
.ig-tile.embed-ready .ig-poster { display: none; }

/* ---------- Lightbox ---------- */
.lb-lock { overflow: hidden; }

.lightbox {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: none;
  align-items: center;
  justify-content: center;
  background: rgba(6, 6, 7, 0.96);
  backdrop-filter: blur(4px);
  padding: env(safe-area-inset-top) 12px env(safe-area-inset-bottom);
  touch-action: pan-y;
}
.lightbox[data-open="true"] { display: flex; }

.lb-stage {
  margin: 0;
  max-width: 100%;
  max-height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
}
.lb-stage img {
  max-width: 94vw;
  max-height: 88vh;
  width: auto;
  height: auto;
  display: block;
  border-radius: 4px;
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.6);
}

.lb-btn {
  position: absolute;
  background: rgba(20, 20, 22, 0.6);
  color: var(--fg);
  border: 1px solid var(--line);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  line-height: 1;
  transition: background 0.15s, color 0.15s, border-color 0.15s;
  -webkit-tap-highlight-color: transparent;
}
.lb-btn:hover { background: var(--accent); border-color: var(--accent); color: #fff; }

.lb-prev, .lb-next {
  top: 50%;
  transform: translateY(-50%);
  width: 52px;
  height: 52px;
  border-radius: 50%;
  font-size: 1.9rem;
  font-weight: 700;
}
.lb-prev { left: clamp(8px, 3vw, 28px); }
.lb-next { right: clamp(8px, 3vw, 28px); }

.lb-close {
  top: clamp(10px, 3vw, 24px);
  right: clamp(10px, 3vw, 24px);
  width: 44px;
  height: 44px;
  border-radius: 50%;
  font-size: 1.6rem;
}

@media (max-width: 520px) {
  .lb-prev, .lb-next { width: 44px; height: 44px; font-size: 1.5rem; }
}

/* ---------- About / Contact ---------- */
.about {
  padding: clamp(20px, 4vw, 48px);
  max-width: 1000px;
  margin: 0 auto;
}
.about-grid {
  display: grid;
  grid-template-columns: minmax(220px, 320px) 1fr;
  gap: clamp(24px, 4vw, 56px);
  align-items: start;
}
@media (max-width: 720px) {
  .about-grid { grid-template-columns: 1fr; }
}

/* Headshot: Nicole's real photo in a simple rounded frame. */
.headshot { margin: 0; }
.headshot img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: 10px;
  border: 1px solid var(--line);
}

.about-name {
  margin: 0;
  font-size: clamp(1.8rem, 5vw, 2.6rem);
  letter-spacing: -0.01em;
}
.about-role {
  margin: 4px 0 20px;
  color: var(--accent);
  text-transform: uppercase;
  letter-spacing: 0.14em;
  font-size: 0.82rem;
}
/* Bio: long-form reading text, so it runs looser and slightly dimmer than a heading
   and caps its line length — a full-width line on a desktop monitor is hard to track. */
.about-bio {
  margin: 0 0 14px;
  max-width: 62ch;
  line-height: 1.7;
  color: var(--muted);
  font-size: 0.98rem;
}
.about-bio:last-of-type { margin-bottom: 0; }

.contact-block {
  margin-top: 28px;
  padding-top: 22px;
  border-top: 1px solid var(--line);
}
.contact-block h2 {
  margin: 0 0 12px;
  font-size: 0.82rem;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  color: var(--muted);
}
.contact-list { list-style: none; margin: 0; padding: 0; }
.contact-list li { margin: 0 0 10px; }
.contact-list a {
  color: var(--fg);
  border-bottom: 1px solid transparent;
  transition: color 0.15s, border-color 0.15s;
}
.contact-list a:hover {
  color: var(--accent);
  border-bottom-color: var(--accent);
}

/* ---------- Footer ---------- */
.site-footer {
  border-top: 1px solid var(--line);
  padding: 28px clamp(16px, 4vw, 48px);
  color: var(--muted);
  font-size: 0.8rem;
  letter-spacing: 0.04em;
}
