/* ═══════════════════════════════════════════════════════════════
   Nadya Denisenko — baker portfolio

   Mobile-first (390px base); the desktop frame (1440) starts at the
   --bp breakpoint below, where the top bar gives way to a fixed
   sidebar. Values come from the design handoff and are deliberate:
   the type scale, the 160/80px section rhythm and the 88/20px
   gutters are all specified, not guessed.

   Two rules that are easy to break and that the design depends on:
     · Only the hero is centred. Everything else is flush left with
       the whitespace carried on the right.
     · Surface (--surface) is always LIGHTER than ground (--ground).
       Tiles, photo slots and form fields sit on surface.
   ═══════════════════════════════════════════════════════════════ */

:root {
  --ground: #E8DDD0;
  --surface: #F4F2EC;
  --ink: #16161A;
  --muted: #5F5A4E;
  --rule: #D8C9B8;
  --link: #2E4A66;
  --link-hover: #16161A;
  --on-filled: #F4F2EC;
  --on-filled-muted: #C9C2B6;
  --error: #8C3A2B;
  --placeholder: #9A9284;

  --font-display: 'Fraunces', Georgia, serif;
  --font-body: 'Karla', system-ui, sans-serif;

  --scrim: linear-gradient(to top, rgba(22, 22, 26, .62), rgba(22, 22, 26, 0));

  --gutter: 20px;
  --sidebar-w: 260px;
  --rhythm: 80px;        /* major section rhythm */
  --rhythm-minor: 64px;
}

*, *::before, *::after { box-sizing: border-box; }

/* The UA's `[hidden] { display: none }` is a plain author-overridable default,
   so any class rule that sets `display` beats it — which silently un-hides
   .menu (display:flex) and .form (display:flex) the moment they're toggled via
   the `hidden` property. Make `hidden` mean hidden. */
[hidden] { display: none !important; }

html { scroll-behavior: smooth; }

body {
  margin: 0;
  background: var(--ground);
  color: var(--ink);
  font: 400 18px/29px var(--font-body);
  -webkit-font-smoothing: antialiased;
}

/* Fraunces is variable; these axes are what the design specifies. */
.fr {
  font-family: var(--font-display);
  font-variation-settings: 'SOFT' 100, 'opsz' 96;
  font-weight: 500;
}

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

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

h1, h2, h3, p { margin: 0; }

button { font: inherit; color: inherit; }

/* One focus treatment everywhere — never the browser default. */
:focus-visible {
  outline: 1px solid var(--link);
  outline-offset: 2px;
}

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 100;
  background: var(--surface);
  padding: 12px 16px;
  font: 500 16px/24px var(--font-body);
}
.skip-link:focus { left: 0; }

/* ── Shared type ──────────────────────────────────────────── */

.label {
  margin: 0;
  font: 500 12px/18px var(--font-body);
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--muted);
}

.label-optional {
  text-transform: none;
  letter-spacing: 0;
  font-weight: 400;
}

.text-link {
  font: 500 16px/24px var(--font-body);
  color: var(--link);
  border-bottom: 1px solid var(--link);
  padding-bottom: 3px;
}
.text-link:hover { color: var(--link-hover); border-bottom-color: var(--link-hover); }

.text-button {
  font: 500 16px/24px var(--font-body);
  color: var(--link);
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
}
.text-button:hover { color: var(--link-hover); }

/* Filled button. The size string beside the label is part of the button,
   not a sibling — hence inline-flex with a baseline alignment. */
.btn {
  display: inline-flex;
  align-items: baseline;
  gap: 10px;
  font: 500 16px/24px var(--font-body);
  color: var(--on-filled);
  background: var(--ink);
  border: 1px solid var(--ink);
  border-radius: 0;
  padding: 14px 28px;
  cursor: pointer;
  transition: background 200ms ease, border-color 200ms ease;
}
.btn:hover {
  color: var(--on-filled);
  background: var(--link);
  border-color: var(--link);
}
.btn[disabled] { opacity: .45; cursor: default; }
.btn-meta { color: var(--on-filled-muted); font: 400 15px/24px var(--font-body); }

/* ── Mobile chrome ────────────────────────────────────────── */

.topbar {
  position: sticky;
  top: 0;
  z-index: 30;
  height: 60px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 var(--gutter);
  background: var(--ground);
  border-bottom: 1px solid var(--rule);
}

.topbar-name { font-size: 19px; line-height: 1; letter-spacing: -.01em; }

.menu-toggle {
  font: 500 16px/24px var(--font-body);
  background: none;
  border: 0;
  padding: 4px 0;
  cursor: pointer;
}

/* The overlay replaces the page rather than covering it — main is
   hidden while the menu is open (see nav.js). */
.menu {
  display: flex;
  flex-direction: column;
  min-height: calc(100dvh - 60px);
  padding: 48px var(--gutter) 32px;
}

.menu-nav { display: flex; flex-direction: column; align-items: flex-start; gap: 8px; }
.menu-nav a {
  font-family: var(--font-display);
  font-variation-settings: 'SOFT' 100, 'opsz' 96;
  font-weight: 500;
  font-size: 36px;
  line-height: 48px;
  color: var(--ink);
}
.menu-nav a.is-current { color: var(--link); }

.menu-spacer { flex: 1; min-height: 48px; }
.menu-rule { height: 1px; background: var(--rule); }

.menu-socials { display: flex; flex-direction: column; gap: 4px; margin-top: 20px; }
.menu-socials a { font: 400 16px/26px var(--font-body); color: var(--muted); }
.menu-socials a:hover { color: var(--ink); }

.sidebar { display: none; }

/* ── Layout ───────────────────────────────────────────────── */

.content > section { padding-left: var(--gutter); padding-right: var(--gutter); }

/* ── Hero — the one centred block ─────────────────────────── */

.hero {
  position: relative;
  padding-top: 48px;
  padding-bottom: 120px;
  text-align: center;
  overflow: hidden;
}

.hero-bg {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 150px;
  opacity: .32;
  filter: grayscale(.65) contrast(.92);
  -webkit-mask-image: linear-gradient(to top, #000 45%, transparent);
  mask-image: linear-gradient(to top, #000 45%, transparent);
}
.hero-bg img { width: 100%; height: 100%; object-fit: cover; }

.hero-inner {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
}

/* The design specifies a correction filter here — brightness(1.36) and a sepia
   wash — for a portrait shot in direct sun with the face in shadow. The handoff
   says to prefer baking that into the asset, and the exported asset is already
   correctly exposed, so applying the filter on top only bleaches it. No filter:
   the correction lives in the crop and the export, where it belongs. */
.hero-portrait {
  width: 200px;
  height: 200px;
  border-radius: 999px;
  overflow: hidden;
  background: var(--surface);
}
.hero-portrait img { width: 100%; height: 100%; object-fit: cover; }

.hero-eyebrow { margin-top: 28px; font: 400 18px/29px var(--font-body); color: var(--muted); }
.hero-title { margin-top: 8px; font-size: 40px; line-height: 44px; letter-spacing: -.015em; }
.hero-intro { margin-top: 20px; font: 400 18px/29px var(--font-body); max-width: 30em; }
.hero-link { margin-top: 28px; }

/* ── Statement ────────────────────────────────────────────── */

.statement { margin-top: var(--rhythm); }
.statement-title { font-size: 32px; line-height: 38px; letter-spacing: -.015em; max-width: 16em; }
.statement-sub { margin-top: 18px; font: 400 18px/29px var(--font-body); color: var(--muted); max-width: 34em; }

/* ── Selected work ────────────────────────────────────────── */

.work { margin-top: var(--rhythm-minor); }

.work-head { padding-bottom: 16px; border-bottom: 1px solid var(--rule); }

.filters { display: flex; align-items: baseline; gap: 24px; margin-top: 16px; }

.filter {
  font: 500 16px/24px var(--font-body);
  color: var(--muted);
  background: none;
  border: 0;
  border-bottom: 1px solid transparent;
  border-radius: 0;
  padding: 0 0 3px;
  cursor: pointer;
  transition: color 200ms ease, border-color 200ms ease;
}
.filter:hover { color: var(--ink); }
.filter.is-active { color: var(--link); border-bottom-color: var(--link); }

.filter-long { display: none; }

.work-grid { display: grid; grid-template-columns: 1fr; gap: 16px; margin-top: 24px; }

.tile {
  position: relative;
  margin: 0;
  min-width: 0;
  aspect-ratio: 4 / 5;
  background: var(--surface);
  overflow: hidden;
  transition: transform 400ms cubic-bezier(.2, .7, .2, 1);
}
.tile img { width: 100%; height: 100%; object-fit: cover; }

.tile-cap {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  display: flex;
  flex-direction: column;
  padding: 20px;
  background: var(--scrim);
  color: var(--surface);
  pointer-events: none;
}
.tile-title { font: 500 15px/22px var(--font-body); }
.tile-note { font: 400 14px/20px var(--font-body); }

/* ── About ────────────────────────────────────────────────── */

.about { margin-top: var(--rhythm); }

.about-media { aspect-ratio: 4 / 5; background: var(--surface); overflow: hidden; }
.about-media img { width: 100%; height: 100%; object-fit: cover; }

.about-text { margin-top: 28px; }
.about-text .label { margin-bottom: 20px; }
.about-text p { font: 400 18px/29px var(--font-body); }
.about-text p + p { margin-top: 20px; }

.btn-download {
  margin-top: 32px;
  width: 100%;
  justify-content: center;
}

/* ── Contact ──────────────────────────────────────────────── */

.contact {
  margin-top: var(--rhythm);
  border-top: 1px solid var(--rule);
  padding-top: 64px;
  padding-bottom: 80px;
}

.contact-title { margin-top: 24px; font-size: 34px; line-height: 40px; letter-spacing: -.015em; max-width: 16em; }

.contact-body { margin-top: 48px; }

.form { display: flex; flex-direction: column; gap: 20px; }

.form-summary {
  border-top: 1px solid var(--error);
  padding-top: 16px;
  font: 500 16px/24px var(--font-body);
  color: var(--error);
}

.field { display: flex; flex-direction: column; }
.field .label { margin-bottom: 8px; }

.field input,
.field textarea {
  width: 100%;
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: 0;
  padding: 13px 14px;
  font: 400 17px/26px var(--font-body);
  color: var(--ink);
}
.field textarea { resize: vertical; }
.field input::placeholder,
.field textarea::placeholder { color: var(--placeholder); }

/* The design asks for a 1px border plus a 1px ring, never the UA outline. */
.field input:focus-visible,
.field textarea:focus-visible {
  outline: none;
  border-color: var(--link);
  box-shadow: 0 0 0 1px var(--link);
}

.field.has-error input,
.field.has-error textarea { border-color: var(--error); }

.field-error { margin-top: 8px; font: 400 14px/20px var(--font-body); color: var(--error); }

#form-submit { width: 100%; justify-content: center; }

.form-done { border-top: 1px solid var(--rule); padding-top: 40px; }
.form-done-title { font-size: 32px; line-height: 38px; letter-spacing: -.015em; max-width: 16em; }
.form-done-sub { margin-top: 20px; font: 400 18px/29px var(--font-body); color: var(--muted); max-width: 34em; }
#form-reset { margin-top: 32px; }

/* ═══ Desktop ═════════════════════════════════════════════════ */

@media (min-width: 900px) {
  :root {
    --gutter: 88px;
    --rhythm: 160px;
    --rhythm-minor: 96px;
  }

  body { font: 400 21px/34px var(--font-body); }

  .topbar, .menu { display: none; }

  .sidebar {
    position: fixed;
    left: 0;
    top: 0;
    bottom: 0;
    width: var(--sidebar-w);
    display: flex;
    flex-direction: column;
    padding: 44px 32px;
    border-right: 1px solid var(--rule);
    background: var(--ground);
    z-index: 2;
  }

  .sidebar-name { font-size: 23px; line-height: 1; letter-spacing: -.01em; }
  .sidebar-role { margin-top: 6px; font: 400 13px/20px var(--font-body); color: var(--muted); }

  .sidebar-nav { display: flex; flex-direction: column; align-items: flex-start; gap: 2px; margin-top: 56px; }
  .sidebar-nav a { font: 500 16px/24px var(--font-body); color: var(--muted); padding: 4px 0; }
  .sidebar-nav a:hover { color: var(--ink); }
  .sidebar-nav a.is-current { color: var(--link); }

  .sidebar-spacer { flex: 1; }
  .sidebar-rule { height: 1px; background: var(--rule); }

  .sidebar-socials { display: flex; flex-direction: column; gap: 2px; margin-top: 20px; }
  .sidebar-socials a { font: 400 15px/24px var(--font-body); color: var(--muted); }
  .sidebar-socials a:hover { color: var(--ink); }

  .content { margin-left: var(--sidebar-w); }

  .hero {
    min-height: 900px;
    padding-top: 132px;
    padding-bottom: 0;
  }
  .hero-bg { height: 210px; }

  .hero-portrait {
    width: 268px;
    height: 268px;
    position: relative;
    left: 5px;              /* optical centring against the backdrop */
  }
  .hero-eyebrow { margin-top: 36px; font-size: 21px; line-height: 34px; }
  .hero-title { font-size: 72px; line-height: 76px; }
  .hero-intro { margin-top: 28px; font-size: 21px; line-height: 34px; }
  .hero-link { margin-top: 40px; }

  .statement-title { font-size: 52px; line-height: 60px; }
  .statement-sub { margin-top: 24px; font-size: 21px; line-height: 34px; }

  .work-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    padding-bottom: 20px;
  }
  .filters { margin-top: 0; gap: 32px; }
  .filter-long { display: inline; }
  .filter-short { display: none; }

  .work-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 24px; }

  .tile:hover { transform: scale(1.02); }
  .tile-cap { opacity: 0; transition: opacity 400ms ease; }
  .tile:hover .tile-cap,
  .tile:focus-within .tile-cap { opacity: 1; }

  .about { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); gap: 24px; }
  .about-media {
    grid-column: 1 / span 5;
    aspect-ratio: 2 / 3;
    margin-top: 52px;       /* line the photo up with the first paragraph */
    /* Both halves of this section are capped, and they have to be capped
       together. Uncapped, a wider viewport rewraps the paragraphs shorter
       while the 2/3 box keeps getting taller, so the two drift apart instead
       of scaling together — at 2400px the portrait was 1369px tall against
       228px of text. Capping only the photo swaps that for a photo stranded
       in a half-empty column. 404px is the size the design handoff specifies
       (404x606), and it pairs with the measure cap on .about-text p below. */
    max-width: 404px;
  }
  .about-text { grid-column: 7 / span 6; margin-top: 0; padding-top: 8px; }
  .about-text .label { margin-bottom: 24px; }
  /* Cap the reading measure. Without this the paragraphs keep widening with
     the viewport and each rewrap makes the text block shorter, which is what
     pulled it out of proportion with the portrait.

     490px is not an arbitrary cap: at exactly 1440 the handoff's frame width,
     columns 7-12 of this grid measure 490px, and the handoff specifies the
     text block as "about 490x772" against a "404x606" portrait. Freezing both
     at their 1440 values is what holds the designed proportion — the portrait
     shorter than the text beside it — on any wider screen. */
  .about-text p { font-size: 21px; line-height: 34px; max-width: 490px; }
  .about-text p + p { margin-top: 24px; }
  .btn-download { margin-top: 40px; width: auto; justify-content: flex-start; }

  .contact { padding-top: 120px; padding-bottom: 140px; }
  .contact .label { margin-bottom: 28px; }
  .contact-title { margin-top: 0; font-size: 56px; line-height: 64px; }
  .contact-body {
    margin-top: 80px;
    display: grid;
    grid-template-columns: repeat(12, minmax(0, 1fr));
    gap: 24px;
  }
  .form, .form-done { grid-column: 1 / span 6; }
  .form { gap: 24px; }
  .field input, .field textarea { padding: 14px 16px; }
  #form-submit { width: auto; align-self: flex-start; justify-content: flex-start; }
  .form-done-title { font-size: 36px; line-height: 44px; }
  .form-done-sub { font-size: 21px; line-height: 34px; }
}

/* ═══ Reduced motion ══════════════════════════════════════════ */

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }

  .tile, .tile-cap, .btn, .filter { transition: none !important; }
  .tile:hover { transform: none !important; }

  /* Captions must never be hover-gated when motion is off — otherwise the
     technique notes are simply unreachable. */
  .tile-cap { opacity: 1 !important; }
}
