/* annasumina.com
   Type and colors follow ssemenov.com: SF Pro from the visitor's system, Apple-style greys,
   light or dark from the system setting. Like ssemenov.com there are two type modes:
   phones and touch screens get left-aligned, larger text; desktops with a mouse get
   centered, compact text. Image column widths keep the original Framer breakpoints:
   >=1440, 1024–1439, 820–1023, <820. */

/* ---------- Colors ---------- */
:root {
  color-scheme: light dark;
  --bg: #fff;
  --label: #1d1d1f;
  --label-strong: #1d1d1f;   /* names and links */
  --label-2: #6e6e73;        /* secondary text */
  --placeholder: #f2f2f2;    /* image boxes while loading */
}
@media (prefers-color-scheme: dark) {
  :root { --bg: #080808; --label: #f5f5f7; --label-strong: #f5f5f7; --label-2: #86868b; --placeholder: #191919; }
}
@media (prefers-contrast: more) {
  :root { --label-2: #424245; }
}
@media (prefers-color-scheme: dark) and (prefers-contrast: more) {
  :root { --label-2: #d2d2d7; }
}

/* ---------- Type and spacing (phones and touch screens) ---------- */
:root {
  --font: "SF Pro Display", "SF Pro", -apple-system, BlinkMacSystemFont, system-ui, "Helvetica Neue", Helvetica, Arial, sans-serif;
  --display: 32px;  --display-lh: 1.2;  --display-ls: -0.32px;   /* names, page titles */
  --reading: 22px;  --reading-lh: 1.4;  --reading-ls: -0.01em;   /* descriptions */
  --body: 17px;     --body-lh: 25px;    --body-ls: normal;       /* links, captions */
  --edge: 24px;
  --top: max(28px, env(safe-area-inset-top));
  --bottom: max(36px, env(safe-area-inset-bottom));
  --gap-hero: 68px;      /* contacts row to name */
  --gap-content: 36px;   /* hero to images, images to footer */
}
/* ---------- Desktop with a mouse (same breakpoint as ssemenov.com) ---------- */
@media (min-width: 810px) and (hover: hover) and (pointer: fine) {
  :root {
    --display: 25px;  --display-lh: 30px;  --display-ls: -0.26px;
    --body-lh: 20px;  --body-ls: -0.26px;
    --edge: 48px;
    --top: clamp(32px, 7.8125vh, 80px);
    --bottom: var(--top);
    --gap-hero: 32px;
    --gap-content: 56px;
  }
}
@media (min-width: 810px) and (hover: hover) and (pointer: fine) and (prefers-color-scheme: light) {
  :root { --label-strong: #000; }   /* ssemenov.com draws names and links pure black here */
}

/* ---------- Base ---------- */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; }
body {
  margin: 0;
  background: var(--bg);
  color: var(--label);
  font-family: var(--font);
  font-weight: 400;
  font-size: var(--body);
  line-height: var(--body-lh);
  letter-spacing: var(--body-ls);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}
h1, p, figure { margin: 0; }
h1 { font: inherit; letter-spacing: inherit; }
h1, p { white-space: pre-wrap; }   /* keeps authored spacing such as "Personal Project  · 2023" */
img { display: block; max-width: 100%; }
a { color: var(--label-strong); text-decoration: none; transition: color 0.18s; }
a:hover { color: var(--label-2); }
.muted { color: var(--label-2); }

.display { font-size: var(--display); line-height: var(--display-lh); letter-spacing: var(--display-ls); }

/* Email · Instagram · Linkedin */
.contacts { display: flex; flex-wrap: wrap; column-gap: 0.55em; }
.contacts .dot { color: var(--label-2); }
@media (min-width: 810px) and (hover: hover) and (pointer: fine) {
  .contacts { column-gap: 0.375em; }
  .contacts .dot { color: var(--label-strong); }
}

.closing { color: var(--label-2); }
.closing--phone { display: none; }

/* ======================================================================
   Home page: contacts, name and role, the mosaic, footer
   ====================================================================== */
.home { padding: var(--top) var(--edge) var(--bottom); }

.home-intro {
  display: flex;
  flex-direction: column;
  margin-top: var(--gap-hero);
  font-size: var(--display);
  line-height: var(--display-lh);
  letter-spacing: var(--display-ls);
}
.home-name { color: var(--label-strong); }
.home-role, .home-status { color: var(--label-2); }

@media (min-width: 810px) and (hover: hover) and (pointer: fine) {
  .home .contacts { justify-content: center; }
  .home-intro { max-width: 600px; margin-left: auto; margin-right: auto; text-align: center; }
}

/* The footer, the same on every page: centered on desktops with a mouse, like the name at the top
   of the home page; left-aligned on phones and touch screens, like that name too. */
.site-footer {
  display: flex;
  flex-direction: column;
  gap: 16px;
  margin-top: var(--gap-content);
}
@media (min-width: 810px) and (hover: hover) and (pointer: fine) {
  .site-footer { align-items: center; text-align: center; }
  .site-footer .contacts { justify-content: center; }
}

/* ======================================================================
   Projects menu on the home page (assets/js/menu.js). Without JavaScript it
   is a plain list after the footer. With it (class "has-menu" on <html>),
   "Projects" in the top row opens it full screen: on desktops with a mouse
   the names are large on the left and the painting of the project under the
   mouse shows on the right; elsewhere it is a list of names and formats.
   ====================================================================== */
.menu { margin-top: var(--gap-content); }
.menu-heading {
  margin: 0 0 12px;
  font: inherit;
  font-size: var(--display);
  line-height: var(--display-lh);
  letter-spacing: var(--display-ls);
  color: var(--label-2);
}
.menu-list { list-style: none; margin: 0; padding: 0; }
.menu-list a { display: inline-block; padding: 4px 0; }   /* the focus ring hugs the name */
.menu-name { display: block; font-size: var(--display); line-height: var(--display-lh); letter-spacing: var(--display-ls); }
.menu-meta { display: block; color: var(--label-2); }
.menu .menu-top, .menu .menu-art { display: none; }

.has-menu .menu {
  position: fixed;
  inset: 0;
  z-index: 20;
  margin: 0;
  padding: var(--top) var(--edge) var(--bottom);
  overflow-y: auto;
  background: var(--bg);
  opacity: 0;
  transition: opacity 0.35s ease;
}
.has-menu .menu.is-open { opacity: 1; }
/* Opening, inside the fade: the names rise 14px into place one after another (--i, their place in the
   list, comes from menu.js), the painting fades in and settles from a slight zoom, and the top row fades
   in. Closing is the plain fade, so nothing waits. */
.has-menu .menu-top { opacity: 0; transition: opacity 0.4s ease; }
.has-menu .menu-list li { opacity: 0; transform: translateY(14px);
  transition: opacity 0.45s ease, transform 0.65s cubic-bezier(0.22, 1, 0.36, 1); }
.has-menu .menu-art { opacity: 0; transition: opacity 0.6s ease; }
.has-menu .menu-art img { transform: scale(1.05); transition: transform 1.1s cubic-bezier(0.22, 1, 0.36, 1); }
.has-menu .menu.is-open .menu-top { opacity: 1; }
.has-menu .menu.is-open .menu-list li { opacity: 1; transform: none; transition-delay: calc(0.05s + var(--i, 0) * 0.04s); }
.has-menu .menu.is-open .menu-art { opacity: 1; transition-delay: 0.05s; }
.has-menu .menu.is-open .menu-art img { transform: none; }
.has-menu .page .menu { padding: 18px var(--pad) var(--pad); }   /* project pages: its top row where theirs is */
.menu:focus { outline: none; }                   /* the menu itself takes focus after a mouse click */
.has-menu .menu-heading { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.has-menu .menu-top { display: flex; justify-content: space-between; align-items: flex-start; gap: 24px; }   /* name left, Close right */
.has-menu .menu-body { margin-top: var(--gap-hero); }
.menu-is-open { overflow: hidden; }

@media (min-width: 810px) and (hover: hover) and (pointer: fine) {
  .has-menu .menu-body {
    display: grid;
    grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);   /* the painting on the left, the names on the right */
    gap: 48px;
    align-items: center;
    min-height: calc(100% - 2 * var(--gap-hero));   /* same left and right edges as the top row */
  }
  .has-menu .menu-art { grid-column: 1; grid-row: 1; }    /* placed by the grid only: the names stay first */
  .has-menu .menu-list { grid-column: 2; grid-row: 1; }   /* for screen readers and the keyboard */
  .has-menu .menu-name { font-size: clamp(28px, 3.4vw, 46px); line-height: 1.15; letter-spacing: -0.02em; color: var(--label-2); transition: color 0.18s; }
  .has-menu .menu-list a:hover .menu-name,
  .has-menu .menu-list a.is-active .menu-name { color: var(--label-strong); }
  .has-menu .menu-meta { display: none; }
  .has-menu .menu-art { display: grid; }
  .menu-art figure { grid-area: 1 / 1; margin: 0; opacity: 0; transition: opacity 0.3s ease; }
  .menu-art figure.is-active { opacity: 1; }
  .menu-art figure div { aspect-ratio: 3 / 2; overflow: hidden; background: var(--placeholder); }
  .menu-art img { width: 100%; height: 100%; object-fit: cover; }
  .menu-art figcaption { margin-top: 12px; color: var(--label-2); }
  .menu-caption-name { color: var(--label-strong); }
}

/* Cropped images on project pages */
img.cover { width: 100%; height: 100%; object-fit: cover; object-position: 50% 50%; }

/* ======================================================================
   Project pages: the cover painting edge to edge, then the project name on
   the left and its text on the right, then the other images. Name, text and
   images share one column, so their edges line up on every page.
   ====================================================================== */
.page { --pad: 48px; padding: 0 var(--pad) var(--pad); }   /* the top row brings its own top space */

/* ---------- The top row (project pages, Secret Project, 404) ----------
   Anna Sumina on the left, the links on the right. It stays at the top of the window while the page
   scrolls, and on a page with a cover ("page--cover") the cover starts under it, at the very top.
   Spacing, on one rhythm: each item is 32px tall with 12px either side of its text, so there are 24px
   between words and the hover highlight is a small pill; the hairline after the name splits one of those
   gaps 12 / 12. The outer items reach 12px past the edges, so the text itself sits on the page edge.
   Without JavaScript the row is a frosted bar across the window. With assets/js/header.js (class "pill"
   on <html>), it starts spread across the cover in white and, over the first 240px of scrolling,
   gathers into a frosted capsule in the middle: 40px tall, 4px outside the items, so 16px from the text
   at both ends, in the page's text colour. The script sets --p, --padx, --ink, --rule, --capL, --capR. */
.site-header {
  position: sticky;
  top: 0;
  z-index: 10;                                  /* under the projects menu (20) */
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin: 0 calc(-1 * var(--pad));
  padding: 18px var(--pad);                     /* a 56px row on desktops (61px on phones) */
}
.site-header .site-name, .site-header .contacts { white-space: nowrap; }
.site-header .contacts { flex-wrap: nowrap; column-gap: 0; align-items: center;
  border-left: 1px solid var(--rule, color-mix(in srgb, var(--label) 24%, transparent)); }
.site-header .dot { display: none; }
.site-header a { padding: 6px 12px; margin-block: -6px; border-radius: 999px; transition: color 0.18s, background-color 0.18s; }
.site-header a:hover { color: var(--ink, var(--label-strong)); background: color-mix(in srgb, var(--ink, var(--label-strong)) 12%, transparent); }
.site-header .site-name { margin-left: -12px; }
.site-header .contacts > :last-child { margin-right: -12px; }
.site-header::before {                          /* the frosted bar; with the script, the capsule */
  content: "";
  position: absolute;
  z-index: -1;
  inset: 0;
  pointer-events: none;
  background: color-mix(in srgb, var(--bg) 74%, transparent);
  -webkit-backdrop-filter: saturate(1.8) blur(20px);
  backdrop-filter: saturate(1.8) blur(20px);
  box-shadow: 0 1px 0 color-mix(in srgb, var(--label) 10%, transparent);
}
.pill .site-header { padding-left: var(--padx, var(--pad)); padding-right: var(--padx, var(--pad)); }
.pill .site-header, .pill .site-header a { color: var(--ink, var(--label-strong)); }
.pill .site-header::before {
  top: 8px;
  bottom: 8px;
  left: var(--capL, 0);
  right: var(--capR, 0);
  border-radius: 999px;
  opacity: var(--p, 0);
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--label) 8%, transparent), 0 8px 28px rgba(0, 0, 0, 0.1);
}
/* Over the cover, until the capsule forms, each item starts in white or dark text, whichever reads better
   over the part of the painting behind it (header.js measures it; until the painting has loaded, the
   page's text colour). No shade behind the row; white text only has a faint glow, gone once formed. */
.pill .page--cover .site-header a { text-shadow: 0 0 8px rgba(0, 0, 0, calc(0.18 * var(--glow, 0) * (1 - var(--p, 0)))); }
.page--cover .site-header + main > .project-cover:first-child { margin-top: calc(-1 * (var(--body-lh) + 36px)); }   /* up under the row */

.title {
  font-size: var(--display);
  line-height: var(--display-lh);
  letter-spacing: var(--display-ls);
  color: var(--label-strong);
}

/* The cover spans the window. On wider screens it is at most 86% of the screen height, so the
   project name shows below it; a painting taller than that is cropped to the band, or, with
   --cover-bg, shown whole on a band of that colour. Phones show it whole at full width. */
.project-cover {
  margin: 24px calc(-1 * var(--pad)) 0;
  aspect-ratio: var(--a);
  overflow: hidden;
  background: var(--cover-bg, var(--placeholder));
}
.project-cover img { width: 100%; height: 100%; object-fit: cover; }
@media (min-width: 820px) {
  .project-cover { aspect-ratio: auto; height: min(86vh, calc(100vw / var(--a))); height: min(86svh, calc(100vw / var(--a))); }
  /* shown whole: centred, its left and right edges fading into the band */
  .project-cover--whole img { width: auto; max-width: 100%; margin: 0 auto;
    -webkit-mask-image: linear-gradient(90deg, transparent, #000 7%, #000 93%, transparent);
            mask-image: linear-gradient(90deg, transparent, #000 7%, #000 93%, transparent); }
}

.project-intro,
.gallery { width: 80%; margin-left: auto; margin-right: auto; }

.project-intro {
  display: grid;
  grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
  gap: 20px 48px;
  margin-top: 48px;
}
.project-meta {   /* the format and year under the name: the size of the description beside it */
  font-size: var(--reading);
  line-height: var(--reading-lh);
  letter-spacing: var(--reading-ls);
  color: var(--label-2);
}
.project-about p {
  font-size: var(--reading);
  line-height: var(--reading-lh);
  letter-spacing: var(--reading-ls);
}
.project-about p + p { margin-top: 0.8em; }
.project-credits {
  display: grid;
  grid-template-columns: max-content minmax(0, 1fr);
  gap: 2px 16px;
  margin: 24px 0 0;
}
.project-credits dt { color: var(--label-2); }
.project-credits dd { margin: 0; }
.project-about .request { margin-top: 24px; }

/* "Request a project" and "Request the password": a plain link with an arrow that moves on hover */
.request .cta-arrow { display: inline-block; margin-left: 0.25em; transition: transform 0.25s ease; }
.request a:hover .cta-arrow { transform: translateX(3px); }

.gallery {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-top: var(--gap-content);
}
.shot img { width: 100%; height: auto; }
.shot--crop { aspect-ratio: var(--ratio); overflow: hidden; background: var(--placeholder); }
.shot--crop img { height: 100%; }

/* More projects: two large cards for the next open projects, at the end of every project page */
.more { width: 80%; margin: calc(var(--gap-content) * 1.5) auto 0; }
.more-title {
  margin: 0 0 20px;
  font: inherit;
  font-size: var(--display);
  line-height: var(--display-lh);
  letter-spacing: var(--display-ls);
  color: var(--label-strong);
}
.cards { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 28px 10px; }
.card { display: block; }
.card-image { margin: 0; aspect-ratio: 3 / 2; overflow: hidden; background: var(--placeholder); }
.card-image img { width: 100%; height: 100%; object-fit: cover; }
.card-name { margin-top: 10px; }
.card-meta { color: var(--label-2); }
@media (hover: hover) {
  .card-image img { transition: transform 0.8s cubic-bezier(0.22, 1, 0.36, 1); }
  .card:hover .card-image img,
  .card:focus-visible .card-image img { transform: scale(1.04); }
}

/* ======================================================================
   Column widths (Framer breakpoints)
   ====================================================================== */
@media (max-width: 1439.98px) {
  .page { --pad: 32px; }
}
@media (max-width: 1023.98px) {
  .page { --pad: 24px; }
  .project-intro, .gallery, .more { width: 100%; }
}
@media (max-width: 819.98px) {
  .closing--wide { display: none; }
  .closing--phone { display: block; }
  .site-header .contacts > :not(.menu-open) { display: none; }   /* phones keep only "Projects" */
  .site-header .contacts > .menu-open { margin-right: -12px; }  /* so it is the last item */
  .project-intro { grid-template-columns: minmax(0, 1fr); }
  .cards { grid-template-columns: minmax(0, 1fr); }   /* one card per row, the full width */
}

/* ======================================================================
   Mosaic on the home page. Layout is computed by assets/js/mosaic.js;
   without JavaScript it falls back to a justified flex grid.
   ====================================================================== */
.mosaic {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-top: var(--gap-content);
}
.tile {
  position: relative;
  margin: 0;
  flex: var(--a) 1 calc(var(--a) * 280px);
  aspect-ratio: var(--a);
  overflow: hidden;
  background: var(--placeholder);
}
.tile img { display: block; width: 100%; height: 100%; object-fit: cover; }
.tile--big { flex: 1 1 100%; max-height: 85vh; }   /* the main image of a full-width or stacked block takes a whole row */

.mosaic.is-ready { display: block; position: relative; }
.mosaic.is-ready .tile { position: absolute; top: 0; left: 0; aspect-ratio: auto; max-height: none; }
.mosaic.is-ready .tile img { opacity: 0; transition: opacity 0.6s ease; }
.mosaic.is-ready .tile.is-loaded img { opacity: 1; }

/* Project images link to their project page. Under the mouse (or keyboard focus) the image grows
   slightly inside its frame, which stays put and crops the edges, so the picture seems to move
   towards you. It eases in and settles back slowly. */
@media (hover: hover) {
  .mosaic a.tile img { transition: transform 0.8s cubic-bezier(0.22, 1, 0.36, 1); }
  .mosaic.is-ready a.tile img { transition: opacity 0.6s ease, transform 0.8s cubic-bezier(0.22, 1, 0.36, 1); }
  .mosaic a.tile:hover img,
  .mosaic a.tile:focus-visible img { transform: scale(1.04); }
}

/* The project's name and an arrow, on a small label that follows the mouse over a project image
   (mosaic.js keeps it beside the pointer and inside the image). With the keyboard it shows in the
   top left corner. Touch screens have no hover, so no label. */
.tile-label { display: none; }
@media (hover: hover) and (pointer: fine) {
  .tile-label {
    display: flex;
    align-items: baseline;
    gap: 6px;
    position: absolute;
    top: 0;
    left: 0;
    z-index: 1;
    transform: translate(16px, 16px);
    padding: 7px 14px 8px;
    border-radius: 999px;
    background: var(--bg);
    color: var(--label-strong);
    font-size: 15px;
    line-height: 20px;
    letter-spacing: -0.2px;
    white-space: nowrap;
    box-shadow: 0 4px 18px rgba(0, 0, 0, 0.16);
    opacity: 0;
    transition: opacity 0.2s ease;
    pointer-events: none;
  }
  .tile-arrow { transition: transform 0.25s ease; }
  .mosaic a.tile:hover .tile-label,
  .mosaic a.tile:focus-visible .tile-label { opacity: 1; }
  .mosaic a.tile:hover .tile-arrow { transform: translateX(2px); }
}

/* ======================================================================
   Appear (assets/js/reveal.js). While <html> has the class "reveal", these
   parts wait hidden and 24px lower, then fade and rise into place as they
   come into view. The cover only fades, its painting settling from a slight
   zoom. :where() keeps these rules weak, so .is-shown always wins.
   ====================================================================== */
.reveal :where(.project-name, .project-about, .gallery .shot, .home-intro, .mosaic .tile, .more-title, .card, .site-footer) {
  opacity: 0;
  transform: translateY(24px);
  transition: opacity 0.9s ease, transform 1.1s cubic-bezier(0.22, 1, 0.36, 1);
  transition-delay: var(--reveal-delay, 0s);
}
.reveal :where(.project-cover) {
  opacity: 0;
  transition: opacity 1.2s ease;
  transition-delay: var(--reveal-delay, 0s);
}
.reveal :where(.project-cover) img {
  transform: scale(1.04);
  transition: transform 1.8s cubic-bezier(0.22, 1, 0.36, 1);
  transition-delay: var(--reveal-delay, 0s);
}
.reveal .is-shown,
.reveal .is-shown.project-cover img { opacity: 1; transform: none; }
.reveal .is-instant,
.reveal .is-instant img { transition: none; }
@media print, (prefers-reduced-motion: reduce) {
  .reveal :where(.project-cover, .project-name, .project-about, .gallery .shot, .home-intro, .mosaic .tile, .more-title, .card, .site-footer),
  .reveal :where(.project-cover) img { opacity: 1; transform: none; transition: none; }
}

/* With reduced motion there is no zoom: the image dims slightly instead. */
@media (prefers-reduced-motion: reduce) {
  .mosaic .tile img, .mosaic.is-ready .tile img, .mosaic.is-ready a.tile img { transition: none; }
  .mosaic a.tile:hover img,
  .mosaic a.tile:focus-visible img { transform: none; filter: brightness(0.85); }
  .card-image img { transition: none; }
  .card:hover .card-image img,
  .card:focus-visible .card-image img { transform: none; filter: brightness(0.85); }
  .has-menu .menu, .menu-art figure { transition: none; }
  .has-menu :is(.menu-top, .menu-list li, .menu-art, .menu-art img) { transition: none; transform: none; }
  a { transition: none; }
  .request .cta-arrow { transition: none; }
}
@media (max-width: 819.98px) {
  .mosaic { gap: 8px; }
}
