/* Look: torypolska.com (Share Tech, 16:9 gallery grid, coral accent). Header proportions, text size and the
   black body follow lesia-lu.com.
   Responsive behaviour follows both Squarespace sites from 768 to 1920px wide; phones have their own sizes:
     < 768px   phone:  menu button, 48px logo in a 72px header, 16px text, 2-column gallery
     768-799   tablet: menu button, full-size logo (106px header row)
     >= 769    3-column gallery
     >= 800    nav shown in the header
     >= 999    21px text, 4-column gallery
     <= 500px tall (phones turned sideways): menu button and a 56px header, whatever the width
   Page margins are 6vw at every size; the gallery gap is ~0.53vw (3px on phones, 10px at 1920). */
@font-face {
  font-family: "Share Tech";
  src: url("fonts/share-tech.woff2") format("woff2");
  font-display: swap;
}
:root {
  /* Header is white with dark ink; page body is black with white ink (as on lesia-lu.com) */
  --header-bg: #fff;
  --header-ink: hsl(180 5.88% 20%);
  --header-muted: hsl(180 4% 45%);
  --bg: #000;
  --ink: #fff;
  --accent: hsl(9.23 80.79% 65.29%);
  --muted: hsl(0 0% 65%);
  --pad: 6vw;
  --max: 1800px;
  --gap: max(3px, 0.53vw);
  --logo-h: 48px; /* diameter of the round logo */
  --header-content: 48px;
  --header-pad-y: 12px;
  --header-h: calc(var(--header-content) + 2 * var(--header-pad-y));
  --page-top: max(28px, 3.3vw);
}
@media (min-width: 768px) and (min-height: 501px) { :root { --logo-h: 85px; --header-content: 106px; --header-pad-y: max(12px, 1.5vw); } }

* { box-sizing: border-box; }
/* The scrollbar's room is always kept, so the page doesn't shift sideways when the lightbox or menu locks scrolling */
html { font-size: 16px; -webkit-text-size-adjust: 100%; scrollbar-gutter: stable; }
@media (min-width: 999px) { html { font-size: 21px; } }
body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: "Share Tech", system-ui, sans-serif;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}
body.is-locked { overflow: hidden; }
a { color: inherit; text-decoration: none; }
img { display: block; max-width: 100%; }
button { -webkit-tap-highlight-color: transparent; }

/* ---------- Header ---------- */
.top-header {
  position: fixed; inset: 0 0 auto 0; z-index: 20;
  background: var(--header-bg); color: var(--header-ink);
}
.top-header__inner {
  height: var(--header-h);
  padding: var(--header-pad-y) var(--pad);
  display: flex; align-items: center;
}
.logo { flex: none; }
/* The logo is always a circle. Its sizes match the round picture inside lesia-lu.com's logo image, which had
   transparent space around it: 85px in the 106px header row. Phones get 48px, as big as the menu button. */
.logo img { width: var(--logo-h); height: var(--logo-h); border-radius: 50%; object-fit: cover; }

/* Shrinking header, like tympanus.net/Blueprints/AnimatedHeader: once the page is scrolled 300px, app.js adds
   .is-shrunk and the header eases to a smaller size in 0.3s. Only the header changes; the page keeps its top
   padding, so nothing below it jumps. The menu overlay's top bar follows, so its close button sits where the menu
   button was. Phones go from 72px to 60px; sideways phones keep their 56px header. */
.top-header__inner, .logo img { transition: height .3s, width .3s, padding .3s; }
.top-header.is-shrunk, .top-header.is-shrunk + .mobile-menu {
  --logo-h: 40px; --header-content: 44px; --header-pad-y: 8px; --header-h: calc(var(--header-content) + 2 * var(--header-pad-y));
}
@media (min-width: 768px) and (min-height: 501px) { .top-header.is-shrunk, .top-header.is-shrunk + .mobile-menu { --logo-h: 45px; --header-content: 56px; --header-pad-y: 12px; } }
@media (max-height: 500px) {
  :root, .top-header.is-shrunk, .top-header.is-shrunk + .mobile-menu { --logo-h: 36px; --header-content: 40px; --header-pad-y: 8px; }
}
@media (prefers-reduced-motion: reduce) { .top-header__inner, .logo img { transition: none; } }

/* When the nav doesn't fit on one line it wraps onto a second line, like lesia-lu.com; the logo never shrinks. */
.nav { display: flex; flex-wrap: wrap; column-gap: 0.9em; row-gap: 0.15em; }
/* The current page stands out: its link is full ink with a 2px coral line right under the letters, the others are
   dimmed. The line grows in from the left when the page changes. */
.nav a { position: relative; color: var(--header-muted); transition: color .15s; white-space: nowrap; }
.nav a::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0.12em; height: 2px; background: var(--accent);
  transform: scaleX(0); transform-origin: left;
}
.nav a.is-active { color: var(--header-ink); }
.nav a.is-active::after { transform: none; animation: nav-line .35s ease-out; }
@keyframes nav-line { from { transform: scaleX(0); } }
@media (prefers-reduced-motion: reduce) { .nav a.is-active::after { animation: none; } }
.top-header .nav { display: none; flex: 1 1 auto; min-width: 0; margin-left: clamp(16px, 2.5vw, 48px); }

/* Gap and colour match the torypolska.com header (1.3vw apart, same ink as the nav); the icons are bigger than
   its 20px, at 28px */
.social { display: flex; align-items: center; gap: 1.3vw; }
.social__icon { display: block; width: 28px; height: 28px; line-height: 0; transition: color .15s; }
.social__icon svg { width: 100%; height: 100%; fill: currentColor; }
.top-header .social { display: none; flex: none; margin-left: clamp(16px, 2.5vw, 48px); }

/* Two-line menu button, as on both reference sites. The lines are 26px wide and line up with the page margin; the
   tappable area around them is 44px. */
.burger, .mobile-menu__close {
  position: relative; flex: none; width: 44px; height: 44px;
  margin-left: auto; margin-right: -9px; padding: 0; border: 0; background: none; color: inherit; cursor: pointer;
}
.burger span, .mobile-menu__close span {
  position: absolute; left: 9px; right: 9px; height: 2px; background: currentColor;
}
.burger span:first-child { top: calc(50% - 5px); }
.burger span:last-child  { top: calc(50% + 3px); }

@media (min-width: 800px) and (min-height: 501px) {
  .top-header .nav, .top-header .social { display: flex; }
  .top-header .social { margin-left: auto; }
  .burger { display: none; }
}

/* Full-screen menu (below 800px, and on phones turned sideways). It fades in rather than popping up: visibility waits for the fade to end when
   closing, so the hidden menu still can't be tapped or tabbed into. */
.mobile-menu {
  position: fixed; inset: 0; z-index: 30; background: var(--header-bg); color: var(--header-ink);
  display: flex; flex-direction: column; overflow-y: auto;
  visibility: hidden; opacity: 0; transition: opacity .3s ease, visibility 0s .3s;
}
.mobile-menu.is-open { visibility: visible; opacity: 1; transition: opacity .3s ease; }
/* The close button starts as the two lines of the menu button and turns into a cross */
.mobile-menu__close span:first-child { top: calc(50% - 5px); }
.mobile-menu__close span:last-child  { top: calc(50% + 3px); }
.mobile-menu__close span { transition: transform .2s, top .2s .15s; }
.mobile-menu.is-open .mobile-menu__close span { top: calc(50% - 1px); transition: top .2s .1s, transform .25s .25s; }
.mobile-menu.is-open .mobile-menu__close span:first-child { transform: rotate(45deg); }
.mobile-menu.is-open .mobile-menu__close span:last-child  { transform: rotate(-45deg); }
/* The links rise in one after another, then the icons; the current page's line draws once they're in */
.mobile-menu .nav a, .mobile-menu .social {
  opacity: 0; transform: translateY(14px); transition: opacity .2s, transform .2s, color .15s;
}
.mobile-menu.is-open .nav a, .mobile-menu.is-open .social {
  opacity: 1; transform: none;
  transition: opacity .4s ease-out, transform .4s cubic-bezier(.2, .7, .3, 1), color .15s;
  transition-delay: calc(.1s + var(--i, 0) * .06s), calc(.1s + var(--i, 0) * .06s), 0s;
}
.mobile-menu.is-open .social { --i: var(--links); }
.mobile-menu .nav a.is-active::after { animation: none; }
.mobile-menu.is-open .nav a.is-active::after { animation: nav-line-menu .35s ease-out .45s backwards; }
@keyframes nav-line-menu { from { transform: scaleX(0); } }
/* With reduced motion the menu only fades */
@media (prefers-reduced-motion: reduce) {
  .mobile-menu .nav a, .mobile-menu .social { transform: none; }
  .mobile-menu .nav a, .mobile-menu .social, .mobile-menu__close span,
  .mobile-menu.is-open .nav a, .mobile-menu.is-open .social, .mobile-menu.is-open .mobile-menu__close span { transition: none; }
  .mobile-menu.is-open .nav a.is-active::after { animation: none; }
}
.mobile-menu__bar { height: var(--header-h); padding: var(--header-pad-y) var(--pad); display: flex; align-items: center; flex: none; }
.mobile-menu .nav {
  flex: 1; flex-direction: column; flex-wrap: nowrap; align-items: center; justify-content: center;
  gap: 0.35em; padding: 0 var(--pad) 2rem; font-size: clamp(1.5rem, 7vw, 2.4rem); line-height: 1.25;
}
.mobile-menu .social { justify-content: center; gap: 1.6rem; padding: 0 0 max(2rem, 8vw); }
.mobile-menu .social__icon { width: 40px; height: 40px; }
/* Sideways phones: smaller links so the menu fits without scrolling */
@media (max-height: 500px) {
  .mobile-menu .nav { font-size: 1.35rem; gap: 0.1em; padding-bottom: 0.5rem; }
  .mobile-menu .social { padding-bottom: 1rem; }
  .mobile-menu .social__icon { width: 32px; height: 32px; }
}
@media (min-width: 800px) and (min-height: 501px) { .mobile-menu { display: none; } }

@media (hover: hover) {
  .nav a:hover, .social__icon:hover { color: var(--accent); }
}

/* ---------- Page body ---------- */
.page {
  max-width: var(--max); margin: 0 auto;
  padding: calc(var(--header-h) + var(--page-top)) var(--pad) max(3rem, 6vw);
}
.section { margin-bottom: max(2.5rem, 5vw); }
.section:last-child { margin-bottom: 0; }
.section__head { max-width: 60ch; margin-bottom: max(0.9rem, 1.2vw); }
.section__title { font-weight: 400; font-size: calc(1.05rem + 0.35vw); letter-spacing: -0.02em; line-height: 1.2; margin: 0 0 0.4rem; }
.section__text { margin: 0; color: var(--muted); white-space: pre-line; }

/* Gallery: images cropped to 16:9; 2 / 3 / 4 columns like the torypolska.com grid */
.grid-169 { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--gap); }
.grid-169 .thumb { aspect-ratio: 16 / 9; }
.grid-169 img { width: 100%; height: 100%; object-fit: cover; }
@media (min-width: 769px) { .grid-169 { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (min-width: 999px) { .grid-169 { grid-template-columns: repeat(4, minmax(0, 1fr)); } }

.thumb {
  display: block; width: 100%; padding: 0; border: 0; background: #111;
  cursor: zoom-in; overflow: hidden;
}
/* Thumbnails fade in as they arrive (app.js adds .is-in when one has loaded) */
.thumb img { opacity: 0; transition: opacity .45s ease, transform .4s ease; }
.thumb img.is-in { opacity: 1; }
@media (hover: hover) { .thumb:hover img { transform: scale(1.03); } }

/* Back to top, at the end of long pages: quiet like the dimmed menu links, coral on hover */
.to-top {
  display: block; margin: 0 auto; padding: 0.6rem 1rem; border: 0; background: none;
  font: inherit; color: var(--muted); cursor: pointer; transition: color .15s;
}
.to-top[hidden] { display: none; }
.to-top span { display: inline-block; margin-left: 0.3em; transition: transform .2s ease; }
@media (hover: hover) {
  .to-top:hover { color: var(--accent); }
  .to-top:hover span { transform: translateY(-3px); }
}

/* ---------- About page ---------- */
/* Phones: the CV at full width, uncropped (Squarespace crops it to a fixed 1039px height there, which hides most of it).
   From 768px: lesia-lu.com's fluid grid, measured at 768-1920px wide. Container = min(1535px, page width - 12vw),
   24 columns with 11px gaps, row height = 2.15% of min(1535px, 88vw). The CV block spans 16 columns x 65 rows and
   the image fills it with object-fit: cover, like Squarespace, so it renders slightly zoomed with the black side
   margins trimmed. 44px social icons, 18px apart, centered below. */
.about { container-type: inline-size; max-width: 1535px; margin: 0 auto; display: flex; flex-direction: column; align-items: center; }
.about__cv { width: 100%; height: auto; }
.about__social { margin-top: 2rem; }
.about__social .social { gap: 18px; justify-content: center; }
.about__social .social__icon { width: 44px; height: 44px; }
@media (min-width: 768px) {
  .about__cv {
    width: calc((100cqw - 23 * 11px) * 16 / 24 + 15 * 11px);
    height: calc(65 * 0.0215 * min(1535px, 88vw) + 64 * 11px);
    object-fit: cover;
  }
  .about__social { margin-top: calc(2 * 11px + 0.0215 * min(1535px, 88vw)); }
}

/* Shown only on the admin's preview of unpublished changes */
.preview-badge {
  position: fixed; left: 50%; bottom: 16px; z-index: 60; transform: translateX(-50%); pointer-events: none;
  padding: 7px 14px; border-radius: 999px; background: rgba(24,24,27,.9); color: #fff;
  font: 500 13px/1.3 system-ui, sans-serif; box-shadow: 0 0 0 1px rgba(255,255,255,.12), 0 6px 20px rgba(0,0,0,.35);
}

/* ---------- Lightbox ---------- */
.lightbox {
  --ink: #fff; --muted: hsl(0 0% 65%); /* always light on black, whatever the page colors are */
  --lb-w: 88vw; --lb-h: 86vh; /* the most room an image may take */
  /* --fade goes from 1 to 0 while the image is dragged down to close (app.js), letting the page show through */
  position: fixed; inset: 0; z-index: 50; background: rgb(0 0 0 / calc(.97 * var(--fade, 1)));
  display: none; align-items: center; justify-content: center; transition: background-color .25s ease-out;
}
.lightbox.is-open { display: flex; }
.lightbox.is-dragging { transition: none; }
/* The page shows faintly through the lightbox; the header's menu button would look like a line under "Close".
   While the image unfolds from the grid, is dragged down or folds back, the page and its header show. */
body:has(.lightbox.is-open:not(.is-opening):not(.is-dragging):not(.is-closing)) .top-header { visibility: hidden; }
.lightbox.is-closing button, .lightbox.is-closing .lb-count { opacity: 0; transition: opacity .15s; }
/* The strip of full-size images: one screen-wide slide per image, snapping so one is always centered */
.lb-track {
  position: absolute; inset: 0; display: flex; overflow-x: auto; overflow-y: hidden;
  scroll-snap-type: x mandatory; overscroll-behavior-x: contain; touch-action: pan-x; scrollbar-width: none;
}
.lb-track::-webkit-scrollbar { display: none; }
.lb-slide { flex: 0 0 100%; display: flex; align-items: center; justify-content: center; scroll-snap-align: center; scroll-snap-stop: always; }
/* The frame has the image's shape and final size before the file arrives (never larger than the file itself). Until
   then it shows the blurred thumbnail and a spinner; the image fades in over them. */
.lb-frame {
  position: relative; flex: none; overflow: hidden; aspect-ratio: var(--ar); transform-origin: 0 0;
  background: #000; /* the page never shows through the image's box, even while it unfolds before loading */
  width: min(var(--w), var(--lb-w), var(--lb-h) * var(--ar));
}
.lb-frame::before {
  content: ""; position: absolute; inset: -24px; background: var(--ph) center / cover;
  filter: blur(18px); opacity: .55; transition: opacity .3s;
}
.lb-frame::after {
  content: ""; position: absolute; top: 50%; left: 50%; width: 34px; height: 34px; margin: -17px 0 0 -17px;
  border: 2px solid rgba(255,255,255,.25); border-top-color: #fff; border-radius: 50%;
  animation: lb-spin .8s linear infinite;
}
@keyframes lb-spin { to { transform: rotate(1turn); } }
.lb-frame img { position: relative; width: 100%; height: 100%; opacity: 0; transition: opacity .35s; transform-origin: 0 0; }
.lb-frame.is-loaded img { opacity: 1; }
.lb-frame.is-instant img { transition: none; }
.lb-frame.is-loaded::before { opacity: 0; }
.lb-frame.is-loaded::after { display: none; }
.lightbox button { position: absolute; background: none; border: 0; font: inherit; color: var(--ink); cursor: pointer; font-size: 2rem; padding: 1rem; line-height: 1; }
.lightbox button, .lb-count { opacity: var(--fade, 1); transition: opacity .25s; }
.lightbox.is-dragging button, .lightbox.is-dragging .lb-count { transition: none; }
/* Zoomed in (app.js): the image may grow past its frame, and the strip stops swiping so a finger moves the image */
.lightbox.is-zoomed .lb-track { overflow: hidden; touch-action: none; }
.lightbox.is-zoomed .lb-frame { overflow: visible; }
@media (hover: hover) {
  .lb-frame img { cursor: zoom-in; }
  .lightbox.is-zoomed .lb-frame img { cursor: zoom-out; }
}
/* While the lightbox opens, the thumbnail covers its part of the big image until that has loaded (app.js) */
.lb-crop { position: absolute; max-width: none; object-fit: cover; }
.lb-prev { left: 1vw; } .lb-next { right: 1vw; }
.lb-close { top: 0.5rem; right: 1vw; font-size: 1.2rem !important; }
.lb-count { position: absolute; bottom: 1.2rem; left: 50%; transform: translateX(-50%); font-size: .85rem; color: var(--muted); }
@media (hover: hover) { .lightbox button:hover { color: var(--accent); } }
/* Phones: the image uses the full width; arrows move to the bottom corners, out of the way of the artwork. Swipe also works. */
@media (max-width: 767px) {
  .lightbox { --lb-w: 100vw; --lb-h: 78vh; }
  .lb-prev, .lb-next { top: auto; bottom: 0.2rem; }
  .lb-count { bottom: 1.6rem; }
}
/* Phones turned sideways: the image takes the full height, between the arrows */
@media (max-height: 500px) {
  .lightbox { --lb-w: calc(100vw - 8rem); --lb-h: calc(100vh - 4.5rem); }
  .lb-prev, .lb-next { bottom: auto; }
  .lb-close { top: 0; }
  .lb-count { bottom: 0.6rem; }
}
