/* ==========================================================================
   Self-hosted fonts. Family names ('Anton', 'Inter') match what
   --font-heading / --font-body reference below.
   Anton loads from WOFF2, with the original TTF listed after it as a
   fallback: if the woff2 path ever 404s, the browser silently uses the TTF
   instead of dropping to a system font. Once you've confirmed in DevTools ->
   Network (filter "Font") that anton.woff2 loads, that TTF line and the old
   Anton TTF file can be deleted.
   Inter stays on its TTF (variable font) — no woff2 for it.
   Paths are case-sensitive on the live server.
   ========================================================================== */
@font-face {
  font-family: 'Anton';
  src: url('assets/fonts/anton.woff2') format('woff2'),
       url('assets/fonts/Anton-Regular.ttf') format('truetype');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: 'Inter';
  /* Variable font — the comma in the filename must be URL-encoded (%2C). */
  src: url('assets/fonts/Inter-VariableFont_opsz%2Cwght.ttf') format('truetype');
  /* The weight range this one file supports — the site only ever uses 400. */
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}

/* ==========================================================================
   Tokens — from GLOBAL spec
   ========================================================================== */
:root {
  --color-bg: #71736E;
  --color-text: #FDFF87;
  --color-interactive: #87EDFF; /* hover (desktop) / pressed (all devices) */

  --font-body: 'Inter', sans-serif;
  --font-heading: 'Anton', sans-serif;

  /* Letter-spacing of -0.6% (Figma) = -0.006em in CSS (em scales with font-size,
     so this stays correct at 20px and 78px alike without recalculating per element) */
  --tracking-tight: -0.006em;

  /* Layout constants, Mobile-S (360px) breakpoint */
  --side-gap: 20px;
  --top-gap: 20px;
  --menu-bottom-gap: 20px;
  --menu-height: 44px;
  --menu-item-width: 82px;
  --heading-menu-gap: 60px; /* space between bottom heading line and menu */

  /* Accounts for a phone's home-indicator/gesture-bar inset. 0px and a
     total no-op on any device without one (most desktops, older phones).
     Requires viewport-fit=cover in the page's <meta name="viewport"> tag
     to have any effect — without that, env() always resolves to 0. */
  --safe-top: env(safe-area-inset-top, 0px);
  --safe-bottom: env(safe-area-inset-bottom, 0px);
}

/* ==========================================================================
   Reset (minimal, only what this page needs)
   ========================================================================== */
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

html, body {
  height: 100%;
}

body {
  background: var(--color-bg);
  color: var(--color-text);
  font-family: var(--font-body);
  /* No hover/focus color changes per spec — but focus outline must stay visible
     for keyboard users since nothing else signals interactivity on this page */
}

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

/* Icons live inside links and should inherit the link's current color
   automatically — build any future icon SVGs with fill="currentColor"
   so this rule covers them without a separate declaration per icon. */

.icon {
  width: 24px;
  height: 24px;
  display: inline-block;
  flex-shrink: 0; /* keeps the icon from being squeezed if its link's
                      layout gets tight (e.g. inside a flex row) */
}

@media (min-width: 1600px) {
  .icon {
    width: 32px;
    height: 32px;
  }
}

/* Pressed state — works on every input type, including touch, so this
   applies at all breakpoints unconditionally. */
a:active {
  color: var(--color-interactive);
}

/* Hover state — gated to devices that actually have a real pointer.
   Without this guard, touchscreens fire :hover on tap and can leave the
   state stuck until the user taps elsewhere, which reads as a bug rather
   than feedback. This is about input capability, not screen width, so it
   applies the same way across all five breakpoints. */
@media (hover: hover) and (pointer: fine) {
  a:hover {
    color: var(--color-interactive);
  }
}

a:focus-visible {
  outline: 2px solid var(--color-text);
  outline-offset: 2px;
}

/* ==========================================================================
   Hero / heading
   ========================================================================== */
.hero {
  position: relative;
  min-height: 100dvh; /* dvh accounts for mobile browser chrome, safer than vh */
  overflow: hidden;
}

.site-name {
  /* One H1 element in the DOM — screen readers announce "MARINA AGLIULLINA"
     as a single continuous heading regardless of the visual split below */
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  align-items: center;
  text-align: center;
  pointer-events: none; /* text itself isn't interactive, avoid stray hit-testing */

  font-family: var(--font-heading);
  font-weight: 400;
  font-size: 78px;
  line-height: 1;
  letter-spacing: var(--tracking-tight);
}

.site-name__first {
  padding-top: calc(var(--top-gap) + var(--safe-top));
}

.site-name__last {
  /* Sits 60px above the menu. Menu occupies (menu-bottom-gap + menu-height)
     from the very bottom, so add heading-menu-gap on top of that.
     --safe-bottom is the actual fix: without it, this reserved space
     doesn't match where the menu really sits once the OS shifts it up to
     clear the home-indicator/gesture-bar area on a real phone — which is
     exactly the "doesn't stick to the menu" symptom at 480px. */
  padding-bottom: calc(var(--menu-bottom-gap) + var(--menu-height) + var(--heading-menu-gap) + var(--safe-bottom));
}

/* ==========================================================================
   Slideshow
   ========================================================================== */
.slideshow {
  position: absolute;
  /* top is set dynamically by script.js — it centers on the actual gap
     between the two heading lines, not the viewport midpoint, since those
     aren't the same point once the menu's reserved space is accounted for */
  top: 50%; /* fallback before JS runs */
  left: 50%;
  transform: translate(-50%, -50%);

  /* Fixed footprint per spec: 320x240 landscape by default.
     JS toggles a --portrait state (240x320) per current image's orientation. */
  width: 320px;
  height: 240px;

  background: #D9D9D9; /* placeholder fill until real photos are in */
  z-index: 1; /* sits below heading text where they overlap, per "covered by heading" */
}

.slideshow.slideshow--portrait {
  width: 240px;
  height: 320px;
}

.slideshow img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.site-name {
  z-index: 2; /* heading renders above the slideshow on overlap */
}

/* ==========================================================================
   Menu
   ========================================================================== */
.menu {
  position: fixed;
  left: var(--side-gap);
  right: var(--side-gap);
  bottom: calc(var(--menu-bottom-gap) + var(--safe-bottom));
  height: var(--menu-height);
  display: flex;
  justify-content: space-between;
  align-items: center;
  z-index: 3; /* menu always on top */
}

.menu__item {
  width: var(--menu-item-width);
  height: var(--menu-height);
  display: flex;
  align-items: center;

  font-family: var(--font-heading);
  font-weight: 400;
  font-size: 20px;
  line-height: 1;
  letter-spacing: var(--tracking-tight);
}

.menu__item--left {
  justify-content: flex-start;
  text-align: left;
}

.menu__item--center {
  justify-content: center;
  text-align: center;
}

.menu__item--right {
  justify-content: flex-end;
  text-align: right;
}

/* ==========================================================================
   Mobile-L (480px+)
   Layout logic is identical to Mobile-S — only type scale and menu
   container size change, to fit the larger font sizes.
   ========================================================================== */
@media (min-width: 480px) {
  :root {
    --menu-height: 48px;
    --menu-item-width: 90px;
    /* --heading-menu-gap, --menu-bottom-gap, --side-gap, --top-gap unchanged —
       the calc() in .site-name__last picks up the new --menu-height
       automatically since it's a CSS custom property, not a hardcoded value */
  }

  .site-name {
    font-size: 86px;
  }

  .menu__item {
    font-size: 24px;
  }
}

/* ==========================================================================
   Desktop-XS (1024px+)
   Bounded to 1024–1199px, explicitly — structurally similar to Desktop-S's
   row layout (both heading halves pinned to the top, same slideshow size),
   but with smaller type and a fixed-size touch-target-style menu container
   rather than Desktop-S's auto-width one. Different enough from 1200+ that
   everything here is scoped so nothing leaks across that boundary either way.
   ========================================================================== */
@media (min-width: 1024px) and (max-width: 1199px) {
  :root {
    --side-gap: 60px;
    --top-gap: 60px;
    --menu-bottom-gap: 60px;
    --menu-height: 44px;
    --menu-item-width: 72px;
    /* .menu and .menu__item already read left/right/bottom/width/height
       from these tokens in their base rules, so updating the tokens here
       is enough — no need to restate those properties directly. */
  }

  .site-name {
    flex-direction: row;
    align-items: flex-start; /* both halves pinned to the top, not split top/bottom */
    justify-content: space-between;
    padding: var(--top-gap) var(--side-gap) 0;
    font-size: 124px;
  }

  .site-name__first {
    padding-top: 0; /* was mobile-only; container padding above handles it now */
    text-align: left;
  }

  .site-name__last {
    padding-bottom: 0; /* mobile reserved space for the menu no longer applies */
    text-align: right;
  }

  .menu__item {
    font-size: 20px;
    letter-spacing: 0; /* flat here, unlike the tracking-tight used at every
                           other breakpoint for this element */
  }

  .slideshow {
    width: 516px;
    height: 387px;
  }

  .slideshow.slideshow--portrait {
    width: 387px;
    height: 516px;
  }
}

/* ==========================================================================
   Desktop-S (1200px+)
   Structural change, not just a scale-up: the heading switches from a
   vertical stack (top line / bottom line) to a horizontal row, both halves
   pinned to the top. Menu drops its fixed touch-target box since pointer
   input doesn't need one. Slideshow image footprint scales up.
   ========================================================================== */
@media (min-width: 1200px) {
  :root {
    --side-gap: 60px;
    --top-gap: 60px;
    --menu-bottom-gap: 60px;
  }

  .site-name {
    flex-direction: row;
    align-items: flex-start; /* both halves pinned to the top, not split top/bottom */
    justify-content: space-between;
    padding: var(--top-gap) var(--side-gap) 0;
    font-size: 148px;
    /* This size is unique to this page/breakpoint — still an <h1> though:
       font-size is presentation, not a reason to change the semantic element */
  }

  .site-name__first {
    padding-top: 0; /* was mobile-only; container padding above handles it now */
    text-align: left;
  }

  .site-name__last {
    padding-bottom: 0; /* mobile reserved space for the menu no longer applies */
    text-align: right;
  }

  .menu {
    left: var(--side-gap);
    right: var(--side-gap);
    bottom: var(--menu-bottom-gap);
    height: auto; /* no fixed touch-target box on desktop */
  }

  .menu__item {
    width: 72px; /* fixed container, per spec — not auto as I'd assumed earlier */
    height: auto; /* TBD: confirm if this should be a fixed value instead */
    font-size: 20px;
  }

  .slideshow {
    width: 516px;
    height: 387px;
  }

  .slideshow.slideshow--portrait {
    width: 387px;
    height: 516px;
  }
}

/* ==========================================================================
   Desktop-M (1400px+)
   Only the heading font-size changes — everything else (paddings, menu,
   image sizes) carries over unchanged from Desktop-S.
   ========================================================================== */
@media (min-width: 1400px) {
  .site-name {
    font-size: 180px;
  }
}

/* ==========================================================================
   Desktop between M and L (1600px+)
   Homepage H1 steps to 200px here (240px at 1920). Every other text style
   already matches the 1920px settings from this width up — the menu labels
   are 40px, and their boxes are 160px wide so the larger text fits.
   ========================================================================== */
@media (min-width: 1600px) {
  .site-name {
    font-size: 200px;
  }

  .menu__item {
    width: 160px;
    font-size: 40px;
  }
}

/* ==========================================================================
   Desktop-L (1920px+)
   Only the heading size and the slideshow image footprint change from 1600
   — paddings and structure carry over from Desktop-S.
   ========================================================================== */
@media (min-width: 1920px) {
  .site-name {
    font-size: 240px;
  }

  .slideshow {
    width: 698px;
    height: 523px;
  }

  .slideshow.slideshow--portrait {
    width: 523px;
    height: 698px;
  }
}

/* ==========================================================================
   About page (and other content pages sharing this pattern)
   ========================================================================== */
.page {
  padding: 0 var(--side-gap) calc(var(--menu-height) + var(--menu-bottom-gap) + 40px);
  /* top padding removed — the fixed header (below) now reserves that space
     dynamically via --header-height, since its height varies by breakpoint */
}

.page-title {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 6; /* same tier as the bottom menu — fixed chrome above scrolling content */
  background: var(--color-bg); /* the title's own box acts as its own backdrop,
                                   since it already spans edge-to-edge */
  padding: var(--top-gap) var(--side-gap) 32px;

  font-family: var(--font-heading);
  font-weight: 400;
  font-size: 78px;
  line-height: 1;
  letter-spacing: var(--tracking-tight);
  text-align: center;
}

.page-content {
  /* Pushes scrollable content below the fixed header. Falls back to an
     approximate value before JS measures the real height, to avoid a flash
     of overlapping content on first paint. */
  padding-top: var(--header-height, 130px);
}

.page-content p {
  font-family: var(--font-body);
  font-weight: 400;
  font-size: 18px;
  line-height: 24px;
  letter-spacing: 0;
  margin: 0 0 10px; /* between paragraphs; collapses correctly against h2 below */
}

.page-content h2 {
  font-family: var(--font-heading);
  font-weight: 400;
  font-size: 20px;
  line-height: 1;
  letter-spacing: 0.008em; /* 0.8% (Figma) converted to em, same approach
                               used for --tracking-tight elsewhere on the
                               site — scales correctly if this size ever
                               changes per breakpoint (it already does, to
                               32px on About at 1920) without recalculating */
  text-transform: uppercase;
  margin: 40px 0 10px;
  /* Margin collapsing does the rest of the work here: this 40px collapses
     against the preceding paragraph's 10px margin-bottom to produce
     exactly 40px between sections (the browser takes the larger of the
     two, not the sum) — and this same h2's 10px margin-bottom collapses
     against the next paragraph's lack of a top margin to produce exactly
     10px after the heading. No extra rules needed to hit those two numbers. */
}

.page-content > h2:first-child {
  /* Direct-child selector matters here: this only zeroes the gap when an H2
     is literally the first element in .page-content (a page with no lead
     paragraph before its sections). It must NOT match an H2 that's merely
     first inside .col-sections — that H2 sits after a whole separate lead
     paragraph in the sibling column, so it still needs its full 40px gap. */
  margin-top: 0;
}

/* Fixed bottom menu, shared pattern: solid backdrop spans full width so
   scrolling content can't visually collide with the menu labels; the menu
   itself keeps the standard side-gap inset. */
.menu-backdrop {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  height: calc(var(--menu-height) + var(--menu-bottom-gap));
  background: var(--color-bg);
  z-index: 5;
}

.menu {
  z-index: 6; /* above the backdrop */
}

/* ==========================================================================
   Content pages at 1200px+ (About, and future pages sharing this pattern):
   the mobile top-bar/bottom-bar header+menu become a left sidebar instead.
   Scoped under .content-page so this can't leak into the homepage, which
   shares the .menu / .menu__item / .page-title class names but keeps its
   own distinct desktop layout (horizontal bar, not a sidebar).
   ========================================================================== */
@media (min-width: 1200px) {
  .content-page .page {
    padding: 0; /* mobile's reserved space for the fixed bottom bar no longer applies */
  }

  .content-page .page-title {
    position: fixed;
    top: 0;
    left: 0;
    right: auto; /* bug fix: mobile's right:0 was still inherited here,
                    stretching this full-width instead of hugging the H1 —
                    which then fed a wrong (huge) --sidebar-width into JS
                    and pushed .page-content off-screen */
    /* Explicit width, computed once in JS from the H1's real rendered size
       plus this box's own padding (see layout.js) — not `auto` relying on
       the browser's shrink-to-fit behavior, which had no guaranteed
       relationship to the separate value used for .page-content's offset.
       Both now come from the same single calculation. */
    width: var(--sidebar-width, 300px);
    text-align: left;
    padding: 60px 60px 0 60px;
    font-size: 92px;
  }

  .content-page .page-content {
    /* Offsets past the sidebar. --sidebar-width is measured at runtime from
       the actual rendered width of .page-title (see layout.js) since the
       sidebar has no fixed value — it hugs whatever title text is on the
       page, so this can't be a hardcoded number. */
    margin-left: var(--sidebar-width, 300px);
    width: 588px;
    padding: 60px 0;
  }

  .content-page .menu-backdrop {
    display: none; /* sidebar and content are separate columns here — no
                       scrolling overlap to hide, unlike on mobile */
  }

  .content-page .menu {
    left: 0;
    right: auto;
    bottom: 0;
    height: auto;
    display: flex;
    flex-direction: column;
    align-items: flex-start; /* menu items align to the left edge, not stretched/centered */
    gap: 20px;
    padding: 0 0 60px 60px;
  }

  .content-page .menu__item {
    width: auto;
    height: auto;
  }
}

/* ==========================================================================
   Content pages, 1400px+ (covers both 1400 and 1600 — identical per spec,
   a single min-width block covers both without duplication)
   ========================================================================== */
@media (min-width: 1400px) {
  .content-page .page-content {
    width: 748px;
  }
}

/* ==========================================================================
   Work page gallery
   ========================================================================== */
.gallery {
  display: flex;
  flex-direction: column;
  gap: 32px; /* spacing between cards */
}

.gallery-card {
  display: block;
  color: inherit;
  text-decoration: none;
}

.gallery-card__image {
  display: block;
  width: 100%;
  aspect-ratio: 3 / 4; /* fixed proportions — width is fluid, height follows */
  object-fit: cover; /* crops real photos to fill the box instead of
                         stretching/distorting them */
  background: #D9D9D9; /* shows briefly while loading, or if a file fails */
}

.gallery-card .gallery-card__caption {
  /* Specificity note: plain .gallery-card__caption alone was losing to the
     About page's ".page-content p" rule (which also matches this element,
     since it's nested inside .page-content too) — that rule's margin
     (0 0 10px) was silently overriding this one's intended margin-top.
     Combining with the parent class here raises specificity enough to win
     without needing !important. */
  margin: 10px 0 0;
  text-align: center;
  font-family: var(--font-body);
  font-weight: 400;
  font-size: 18px;
  line-height: 24px;
  letter-spacing: 0;

  min-height: 24px; /* one line */
  max-height: 48px; /* two lines — hard cap */
  overflow: hidden;

  /* Line-clamp to 2 lines, then ellipsis on overflow. Both the standard and
     -webkit- prefixed properties are included since Safari still needs the
     prefix even though the unprefixed version now works in Chrome/Firefox. */
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  line-clamp: 2;
  text-overflow: ellipsis;
}

/* Work page specifically needs wider side padding at 480px than the shared
   --side-gap token provides (which stays 20px here for the fixed header
   and menu — confirmed by measuring the mockup — and must stay 20px on
   the About page too, which already relies on it at this width). Scoping
   this to .work-page keeps it from leaking into either of those.
   Bounded to max-width:1199px so it can't fight the desktop reset below. */
@media (min-width: 480px) and (max-width: 1199px) {
  .work-page .page {
    padding-left: 32px;
    padding-right: 32px;
  }
}

/* ==========================================================================
   Work page, 1200px+ (identical at 1400px too, per spec — one block covers
   both). Reuses the About page's sidebar (.content-page .page-title /
   .menu) entirely unchanged; only the content area becomes a fixed 3-column
   image grid instead of a text column.
   ========================================================================== */
@media (min-width: 1200px) {
  .work-page .page-content {
    width: auto; /* overrides the About page's fixed 588px column width */
  }

  .work-page .gallery {
    display: grid;
    grid-template-columns: repeat(3, 226px);
    gap: 60px;
    /* Flush-left again (reverted from centered) — grid's default
       justify-content already places fixed-width tracks at the start of
       the container, so no explicit property is needed here. Applies at
       every desktop breakpoint from here up, since nothing below overrides
       it. */
  }

  .work-page .gallery-card__image {
    width: 226px;
    height: 300px;
    aspect-ratio: auto; /* both dimensions are fixed here, unlike mobile's
                            fluid-width/fixed-ratio approach */
  }

  .work-page .gallery-card__caption {
    width: 226px;
    height: 48px; /* fixed, not the mobile min/max range — still capped at
                     2 lines via the line-clamp rules already in place */
  }

  /* Visual reorder only, DOM order stays about/main/contacts (matches the
     already-tested mobile markup — see note below on why this can't just
     be swapped in the HTML). Desktop shows main/about/contacts instead. */
  .work-page .menu__item--left {
    order: 2; /* "about" */
  }

  .work-page .menu__item--center {
    order: 1; /* "main" */
  }

  .work-page .menu__item--right {
    order: 3; /* "contacts" — unchanged position */
  }
  /* Accessibility note: this changes the VISUAL order only. Keyboard tab
     order and screen-reader reading order still follow the DOM sequence
     (about → main → contacts), which will now read in a different order
     than it visually appears at this breakpoint. This is a known trade-off
     of CSS `order` — flagging it rather than treating it as fully solved. */
}

/* ==========================================================================
   Work page, 1600px+ (1920px is identical — nothing further changes there)
   ========================================================================== */
@media (min-width: 1600px) {
  .work-page .gallery {
    grid-template-columns: repeat(3, 301px);
  }

  .work-page .gallery-card__image {
    width: 301px;
    height: 400px;
  }

  .work-page .gallery-card__caption {
    width: 301px;
    /* Caption text uses the 1920px body-text settings (24px/32px) from 1600
       up, so the fixed box is the 60px used at 1920 too — not 2x32 = 64,
       taking the given number as-is. */
    height: 60px;
    font-size: 24px;
    line-height: 32px;
  }
}

/* ==========================================================================
   Gallery detail page (reusable template for each of the 12 project pages
   linked from Work). Isolated in its own class rather than reusing
   .work-page, deliberately — this project's kept hitting bugs from rules
   scoped to a shared class leaking across pages that only coincidentally
   share some values today but may need to diverge once desktop specs for
   this page exist.
   ========================================================================== */
.gallery-detail-page .page-title {
  /* This box now wraps BOTH the H1 and the gallery name (see HTML) instead
     of being the H1 itself, unlike About/Work. All the typography set on
     the shared .page-title rule (font-family, size, line-height, letter-
     spacing, text-align) still reaches the nested <h1> correctly since
     those properties inherit — only non-inherited properties (padding,
     specific overrides below) need restating here. */
  padding-bottom: 16px; /* the box's own bottom spacing, per spec */
}

.page-title h1 {
  /* Fixes a real bug: this selector only ever matches gallery.html, the one
     page where .page-title is a wrapping div around a bare <h1> (About/Work
     apply the class directly to their own <h1>, so they never hit this).
     Browsers ship a default stylesheet rule for h1 (font-size: 2em,
     font-weight: bold, plus block margins) that wins over inheritance from
     the parent, regardless of whatever font-size the parent .page-title
     box actually has. `inherit` here forces it to take the parent's real
     computed values instead of that browser default. */
  font-size: inherit;
  font-weight: inherit;
  letter-spacing: inherit;
  text-transform: inherit;
  margin: 0;
}

.gallery-title {
  margin: 12px 0 0; /* gap from H1 — now an internal gap within the same
                        fixed box, not the old page-content-based mechanism */
  text-align: center;
  font-family: var(--font-body);
  font-weight: 400;
  font-size: 18px;
  line-height: 24px;
  letter-spacing: 0;
  text-transform: none; /* .page-title (its parent) now sets uppercase for
                            the H2-style page title — this is real project
                            /photo-title text, not a heading, and must not
                            inherit that transform */
}

.gallery-images {
  display: flex;
  flex-direction: column;
  gap: 20px; /* 360px default */
}

.gallery-image {
  display: block;
  width: 100%;
  object-fit: cover; /* crops real photos to fill the box instead of
                         stretching/distorting them */
  background: #D9D9D9; /* shows briefly while loading, or if a file fails */
}

.gallery-image--portrait {
  aspect-ratio: 3 / 4;
}

.gallery-image--landscape {
  aspect-ratio: 4 / 3;
}

@media (max-width: 1199px) {
  .gallery-detail-page .page-content {
    /* The 16px "content's own top spacing" half of the combined 32px gap —
       added on top of the measured header height (which already includes
       the fixed box's other 16px via its own padding-bottom above).
       Bounded to mobile only — at 1200px+ the sidebar/content columns sit
       side by side instead of stacked, so this mobile-specific calculation
       doesn't apply; the shared .content-page rule's flat 60px padding-top
       takes over there instead. Without this bound, this rule's equal
       specificity plus later source position was silently overriding that
       intended 60px at every desktop width too. */
    padding-top: calc(var(--header-height, 130px) + 16px);
  }
}

@media (min-width: 480px) {
  .gallery-detail-page .page {
    padding-left: 32px;
    padding-right: 32px;
  }

  .gallery-detail-page .page-title {
    /* Diverges from the shared chrome side-gap (which stays 20px for
       About/Work's H1) because the gallery name now shares this same box
       and needs to align with the content's 32px inset instead — per the
       original spec that the title "fits the width of the container for
       H1," meaning H1's own container must match that 32px value here. */
    padding-left: 32px;
    padding-right: 32px;
  }

  .gallery-images {
    gap: 32px;
  }
}

/* ==========================================================================
   Gallery detail page, 1200px+ (covers 1400 too — identical per spec).
   Sidebar reuses the About/Work pattern (fixed, auto-width, hugs the H1)
   but this page's .page-title wraps BOTH the H1 and the gallery name, so
   the shared .content-page rule (built assuming .page-title = just the H1)
   needs explicit adjustment here rather than being trusted as-is.
   ========================================================================== */
@media (min-width: 1200px) {
  .gallery-detail-page .page {
    padding-left: 0;
    padding-right: 0; /* the 480px mobile override above no longer applies */
  }

  .gallery-detail-page .page-title {
    /* Resets the mobile-specific 32px side padding — at this breakpoint
       the shared .content-page rule's own 60px padding takes over instead,
       since nothing here overrides it further. */
    padding-left: 60px;
    padding-right: 60px;
  }

  .gallery-detail-page .page-content {
    width: 800px; /* fixed column, not About's 588/748px or Work's centered grid */
  }

  .gallery-title {
    /* Overrides this element's own mobile rule (text-align:center) — direct
       declarations don't get replaced by inheriting the sidebar's left
       alignment, so this has to be stated explicitly. */
    width: 100%; /* wraps within whatever width the sidebar box already
                    has (driven by the H1 alone), rather than contributing
                    its own — often longer — text width back into that
                    calculation */
    text-align: left;
    margin-top: 60px; /* replaces the mobile 12px gap from H1 */
  }

  .gallery-images {
    gap: 60px;
  }

  .gallery-image--portrait {
    width: 602px;
    height: 800px;
    aspect-ratio: auto;
  }

  .gallery-image--landscape {
    width: 800px;
    height: 602px;
    aspect-ratio: auto;
  }
  /* Portrait images end up narrower than the 800px container. No explicit
     alignment rule is needed for that: .gallery-images is a column flex
     container, and a child with an explicit width no longer stretches to
     fill the cross-axis, defaulting to flex-start — which is exactly the
     flush-left placement confirmed by measuring the mockup. */
}

/* ==========================================================================
   Gallery detail page, 1600px+ (covers 1920 too — identical per spec).
   Same logic as 1200/1400 — only the container width and image dimensions
   change. The H1↔H2 gap and the gap between images both stay 60px, already
   set at 1200px, so nothing needs restating for either of those here.
   ========================================================================== */
@media (min-width: 1600px) {
  .gallery-detail-page .page-content {
    width: 986px;
  }

  .gallery-image--portrait {
    width: 742px;
    height: 986px;
  }

  .gallery-image--landscape {
    width: 986px;
    height: 742px;
  }
}

/* ==========================================================================
   Gallery detail page, 1600px+: the gallery name uses the 1920px body-text
   settings (24px/32px), same as About's paragraphs and Work's captions.
   ========================================================================== */
@media (min-width: 1600px) {
  .gallery-title {
    font-size: 24px;
    line-height: 32px;
  }
}

/* ==========================================================================
   Content pages, 1600px+: text styles use the 1920px settings from here up
   (every text style except the homepage H1, which has its own scale).
   Only text-related rules live here; layout and spacing still start at
   1920px in the block below.
   ========================================================================== */
@media (min-width: 1600px) {
  .content-page .page-title {
    font-size: 120px;
  }

  .content-page .menu__item {
    font-size: 40px;
    letter-spacing: 0; /* menu tracking is normally -0.6% (--tracking-tight) —
                           explicitly flat from here up per spec */
  }

  .about-page .page-content p {
    font-size: 24px;
    line-height: 32px;
  }

  .about-page .page-content h2 {
    font-size: 32px;
  }
}

/* ==========================================================================
   Content pages, 1920px+: About moves to two fixed-width columns instead of
   one (column 1 = lead paragraph, column 2 = the H2 sections), the sidebar
   menu gap grows, and About's paragraph/H2 spacing doubles.
   ========================================================================== */
@media (min-width: 1920px) {
  .content-page .menu {
    gap: 40px;
  }

  .about-page .page-content {
    display: flex;
    flex-direction: row;
    gap: 60px;
    width: auto; /* two fixed-width children below define the real width,
                    not this container */
  }

  .about-page .col-lead,
  .about-page .col-sections {
    width: 612px;
    flex-shrink: 0;
  }

  .about-page .col-sections > h2:first-child {
    /* Below 1920px this same H2's 40px margin-top is correct — it collapses
       with .col-lead's paragraph margin in single-column flow, producing
       the intended section gap. But once .col-lead/.col-sections become
       flex items (this breakpoint), each is its own box: that margin no
       longer collapses with anything outside it and just pushes this
       column's content down from the top, misaligning it against the
       lead column. Zeroing it here (and only here) keeps both columns
       flush at the top while leaving the narrower-breakpoint behavior intact. */
    margin-top: 0;
  }

  .about-page .page-content h2,
  .about-page .page-content p {
    /* Section/paragraph rhythm doubles at this breakpoint (10px → 20px).
       Applying this to both columns is harmless — the lead column only
       has one paragraph, so there's nothing adjacent for it to space
       against; the visible effect is entirely in .col-sections. */
    margin-bottom: 20px;
  }
}

/* ==========================================================================
   Contacts page. Content is bottom-anchored within the space between the
   fixed header and fixed menu, not top-anchored like About/Work — this
   needs an explicit height to align "to the bottom" within, rather than
   relying on natural document flow.
   Side padding needs no override here — the shared 20px --side-gap already
   matches this page's spec at both 360 and 480 (unlike Work, which needed
   its own wider value at 480).
   ========================================================================== */
.contacts-page .page {
  /* The generic .page rule reserves bottom space for the menu via
     padding-bottom — but .contacts-content (below) already calculates its
     own precise bottom spacing via min-height + padding-bottom. Keeping
     both would double-count that reserved space. */
  padding-bottom: 0;
}

.contacts-content {
  min-height: calc(100dvh - var(--menu-height) - var(--menu-bottom-gap));
  padding-top: var(--header-height, 130px);
  padding-bottom: 40px; /* the 40px gap to the menu — this box's bottom
                            edge is defined to land exactly at the menu's
                            top edge, so this padding IS that gap */
  display: flex;
  flex-direction: column;
  justify-content: flex-end; /* mobile: .contacts-photo is hidden (below),
                                 so .contact-info is the only visible child
                                 and this still pushes it to the bottom
                                 exactly as before */
}

.contacts-photo {
  display: none; /* no photo on this page below 1024px */
}

/* Added by contacts-photo.js when the space between the photo and the
   contact info drops below 60px, at any breakpoint where the photo exists.
   The doubled class makes this win over the per-breakpoint display:block
   rules regardless of where they sit in the file. */
.contacts-photo.contacts-photo--hidden {
  display: none;
}

.contact-info {
  display: flex;
  flex-direction: column;
  gap: 40px; /* between the Email and Instagram sections */
  /* Keeps this block pinned to the bottom of .contacts-content even when the
     photo is hidden. With the photo present, justify-content:space-between
     does that job — but with a single child left it would push the block to
     the TOP instead. An auto top margin works in both cases. */
  margin-top: auto;
}

.contact-section h2 {
  /* Overrides the shared .page-content h2 rule's margin-top:40px — this
     page uses flex `gap` on .contacts-content (above) for the between-
     section spacing instead, so keeping that margin here would double it
     up (flex gap and margin both add space; they don't collapse together
     the way adjacent block-level margins do). Typography (Anton, uppercase,
     20px) still comes from that shared rule — only margin is reset here. */
  margin: 0 0 10px;
}

.contact-link {
  display: inline-flex;
  align-items: center;
  gap: 10px; /* icon-to-text spacing */
  /* Color and its hover/press states come for free from the site-wide
     a:hover / a:active rules — this is a plain <a> tag, no extra color
     CSS needed here. */
}

.contact-link__text {
  font-family: var(--font-body);
  font-weight: 400;
  font-size: 18px;
  line-height: 24px;
  letter-spacing: 0;
  text-decoration: underline;
}

/* ==========================================================================
   Contacts page, 1024px+ (bounded to 1024–1199px).
   This page moves to the sidebar layout a full breakpoint earlier than
   About/Work/gallery currently do (those still start it at 1200px) — so
   this duplicates the relevant structural pieces of the shared
   .content-page rule under .contacts-page specifically, rather than
   changing that shared rule's breakpoint and prematurely affecting pages
   that haven't been designed for this yet.
   Menu here is a deliberate hybrid: stacked vertically like the desktop
   sidebar pattern, but with mobile-style fixed touch-target boxes (60x44,
   zero gap) instead of the auto-width/20px-gap treatment used at 1200+.
   Confirmed by measuring the mockup: sidebar width (410px) = H1's own
   rendered width + the standard 60px side padding on each side — so the
   existing --sidebar-width JS measurement (unchanged) already produces
   the right value here with no code changes needed for that part.
   ========================================================================== */
@media (min-width: 1024px) and (max-width: 1199px) {
  .contacts-page .page {
    /* Resets the base .page rule's own side padding (--side-gap, which is
       60px at this breakpoint via the homepage's shared token override) —
       without this, it would stack with .contacts-content's own explicit
       60px right-padding below and double it to 120px. */
    padding: 0;
  }

  .contacts-page .page-title {
    position: fixed;
    top: 0;
    left: 0;
    right: auto;
    width: var(--sidebar-width, 300px);
    text-align: left;
    padding: 60px 60px 0 60px;
    font-size: 80px;
  }

  .contacts-page .page-content {
    margin-left: var(--sidebar-width, 300px);
    width: auto;
  }

  .contacts-page .menu-backdrop {
    display: none; /* sidebar and content are separate columns here — no
                       scrolling overlap to hide, unlike below this breakpoint */
  }

  .contacts-page .menu {
    position: fixed;
    top: auto;
    left: 0;
    right: auto;
    bottom: 0;
    height: auto;
    display: flex;
    flex-direction: column;
    gap: 0; /* stacked with no spacing between items, unlike the 20px gap
                used at 1200px+ */
    /* Bug fix: this was `padding: 0`, leaving the menu flush against the
       viewport edge instead of matching the H1's own 60px left inset —
       the menu is positioned at left:0 same as .page-title, so it needs
       the same padding treatment to actually line up with it. */
    padding: 0 0 60px 60px;
  }

  .contacts-page .menu__item {
    width: 60px;
    height: 44px;
    font-size: 20px;
    letter-spacing: var(--tracking-tight); /* -0.6%, not the flat 0% used
                                               by the homepage's own menu
                                               at this same breakpoint */
    justify-content: flex-start; /* all three items left-aligned — no
                                     left/center/right modifier needed here,
                                     unlike the horizontal mobile menu */
  }

  .contacts-content {
    min-height: 100dvh;
    padding: 60px 60px 60px 0; /* top / right / bottom / left — explicitly
                                   no left inset, content sits flush against
                                   the sidebar */
    justify-content: space-between; /* photo at top, info block at bottom */
  }

  .contacts-photo {
    display: block;
    width: 385px;
    height: 290px;
    object-fit: cover;
    background: #D9D9D9;
  }
}

/* ==========================================================================
   Contacts page, 1200px+ (covers 1400 too — identical per spec).
   Photo appears (hidden below this breakpoint), positioned near the top;
   the email/Instagram block anchors near the bottom instead — same
   justify-content: space-between technique already used for the sidebar's
   own H1-top / menu-bottom layout, just applied to this content column.
   No left inset: content sits flush against the sidebar, per spec.
   ========================================================================== */
@media (min-width: 1200px) {
  .contacts-page .page-content {
    width: auto; /* overrides About's fixed 588px column width */
  }

  .contacts-content {
    min-height: 100dvh; /* full viewport — desktop's menu lives inside the
                            sidebar itself, not as a separate overlapping
                            fixed bar the way it does on mobile, so there's
                            no menu height to subtract here */
    padding: 60px 0;
    justify-content: space-between; /* photo at top, info block at bottom */
  }

  .contacts-photo {
    display: block;
    width: 586px;
    height: 441px;
    object-fit: cover; /* crops the real photo to fill the box instead of
                           stretching/distorting it */
    background: #D9D9D9; /* shows briefly while loading, or if it fails */
  }
}

/* ==========================================================================
   Contacts page, 1600px+: photo grows to 806x606 (586x441 at 1200/1400).
   Icon size comes from the global .icon rule, which is 32px from 1600 up.
   ========================================================================== */
@media (min-width: 1600px) {
  .contacts-photo {
    width: 806px;
    height: 606px;
  }
}

/* ==========================================================================
   Contacts page, 1920px+: H2→link and between-section spacing both grow.
   Icon-to-text gap stays 10px, unchanged.
   ========================================================================== */
@media (min-width: 1920px) {
  .contact-section h2 {
    margin-bottom: 20px;
  }

  .contact-info {
    gap: 40px;
  }
}

/* ==========================================================================
   About page, 1024px+ (bounded to 1024–1199px).
   Same approach as the Contacts page at this breakpoint: the sidebar layout
   starts here, a breakpoint earlier than the shared .content-page rule
   (1200px), so the relevant pieces are duplicated under .about-page
   specifically instead of moving that shared rule and affecting Work and
   the gallery pages, which haven't been designed for this yet.
   Sidebar total width = 304px = 60 + H1's own 184px + 60 — confirmed by
   measuring the mockup — so the existing --sidebar-width JS measurement
   already produces the right value with no changes.
   Text styles (body, links, H2s) and the 40px/10px section/paragraph
   spacing need nothing here: they already match the shared
   .page-content h2 / p rules.
   ========================================================================== */
@media (min-width: 1024px) and (max-width: 1199px) {
  .about-page .page {
    /* Resets the base .page rule's own side padding (--side-gap is 60px at
       this breakpoint via the homepage's shared token override) so it can't
       stack with .page-content's explicit right padding below. */
    padding: 0;
  }

  .about-page .page-title {
    position: fixed;
    top: 0;
    left: 0;
    right: auto;
    width: var(--sidebar-width, 300px);
    text-align: left;
    padding: 60px 60px 0 60px;
    font-size: 80px;
  }

  .about-page .page-content {
    margin-left: var(--sidebar-width, 300px);
    width: auto;
    padding: 60px 100px 60px 0; /* top / right / bottom / left — no left
                                    inset, content sits flush against the
                                    sidebar; 100px on the right per spec */
  }

  .about-page .menu-backdrop {
    display: none; /* sidebar and content are separate columns here — no
                       scrolling overlap to hide */
  }

  .about-page .menu {
    position: fixed;
    top: auto;
    left: 0;
    right: auto;
    bottom: 0;
    height: auto;
    display: flex;
    flex-direction: column;
    gap: 0; /* stacked with no spacing between items */
    padding: 0 0 60px 60px; /* matches the H1's own 60px left inset, plus
                                60px of clearance from the bottom */
  }

  .about-page .menu__item {
    width: 60px;
    height: 44px;
    font-size: 20px;
    letter-spacing: var(--tracking-tight); /* -0.6%, not the flat 0% the
                                               homepage's own menu uses at
                                               this same breakpoint */
    justify-content: flex-start; /* all items left-aligned — the
                                     left/center/right modifiers only matter
                                     for the horizontal mobile menu */
  }
}

/* ==========================================================================
   Work page, 1024px+ (bounded to 1024–1199px).
   Same approach as Contacts and About at this breakpoint: the sidebar
   layout starts here, a breakpoint earlier than the shared .content-page
   rule (1200px), duplicated under .work-page specifically rather than
   moving that shared rule and affecting the gallery detail pages.
   Sidebar width needs nothing here — the existing --sidebar-width JS
   measurement hugs the H1 ("WORK" is narrower than "CONTACTS" or "ABOUT"
   at 80px, so this one comes out narrower: ~60 + 170 + 60).
   Gallery is two columns here (three from 1200px up). Card image is 301x400
   — the mockup shows portrait covers, so that's width x height (the spec
   said 400x301, reversed, same swap seen on other pages). Caption box matches
   the photo's width with a fixed 48px height. No right padding on the
   content: the fixed-width grid sits flush left and whatever screen width
   remains is simply empty space.
   Body text and the 2-line clamp on captions come from the base rules.
   ========================================================================== */
@media (min-width: 1024px) and (max-width: 1199px) {
  .work-page .page {
    padding: 0; /* resets the base padding and the 480px+ gallery side padding */
  }

  .work-page .page-title {
    position: fixed;
    top: 0;
    left: 0;
    right: auto;
    width: var(--sidebar-width, 300px);
    text-align: left;
    padding: 60px 60px 0 60px;
    font-size: 80px;
  }

  .work-page .page-content {
    margin-left: var(--sidebar-width, 300px);
    width: auto;
    padding: 60px 0; /* top 60 per spec; bottom 60 matches the 1200px+ layout */
  }

  .work-page .menu-backdrop {
    display: none; /* sidebar and content are separate columns here */
  }

  .work-page .menu {
    position: fixed;
    top: auto;
    left: 0;
    right: auto;
    bottom: 0;
    height: auto;
    display: flex;
    flex-direction: column;
    gap: 0;
    padding: 0 0 60px 60px;
  }

  .work-page .menu__item {
    width: 60px;
    height: 44px;
    font-size: 20px;
    letter-spacing: var(--tracking-tight);
    justify-content: flex-start;
  }

  /* Visual reorder only — DOM order stays about / main / contacts, which is
     what the horizontal mobile menu needs. Same accessibility caveat as the
     1200px+ version of this: tab and screen-reader order still follow the
     DOM, not what's shown. */
  .work-page .menu__item--left {
    order: 2; /* about */
  }

  .work-page .menu__item--center {
    order: 1; /* main */
  }

  .work-page .menu__item--right {
    order: 3; /* contacts */
  }

  .work-page .gallery {
    display: grid;
    grid-template-columns: repeat(2, 301px);
    gap: 60px; /* between cards in a row, and between rows */
  }

  .work-page .gallery-card__image {
    width: 301px;
    height: 400px;
    aspect-ratio: auto;
  }

  .work-page .gallery-card__caption {
    width: 301px;
    height: 48px;
  }
}

/* ==========================================================================
   Gallery detail page, 1024px+ (bounded to 1024–1199px).
   Same approach as Contacts, About and Work at this breakpoint: sidebar
   layout starts here instead of at 1200px, duplicated under
   .gallery-detail-page rather than moving the shared .content-page rule.
   Here .page-title wraps BOTH the H1 and the gallery name. The sidebar
   width is still driven by the H1 alone (layout.js hides the gallery name
   while measuring), and the gallery name is 100% of that width so it wraps
   inside it with no height limit.
   Mobile-only rules for this page that are still active at 1024px and have
   to be overridden here: the 32px side padding (480px+), the 16px bottom
   padding on the title box, the header-height padding-top on the content,
   and the 32px image gap.
   ========================================================================== */
@media (min-width: 1024px) and (max-width: 1199px) {
  .gallery-detail-page .page {
    padding: 0;
  }

  .gallery-detail-page .page-title {
    position: fixed;
    top: 0;
    left: 0;
    right: auto;
    width: var(--sidebar-width, 300px);
    text-align: left;
    padding: 60px 60px 0 60px;
    font-size: 80px; /* the nested <h1> inherits this */
  }

  .gallery-title {
    width: 100%;
    text-align: left;
    margin-top: 60px; /* H1 to gallery name */
  }

  .gallery-detail-page .page-content {
    margin-left: var(--sidebar-width, 300px); /* no left spacing */
    width: 664px; /* the landscape image width, same idea as the 800px
                     container at 1200px+ */
    padding: 60px 0; /* top 60 per spec; bottom matches the other pages */
  }

  .gallery-images {
    gap: 60px;
  }

  .gallery-image--portrait {
    width: 500px;
    height: 664px;
    aspect-ratio: auto;
  }

  .gallery-image--landscape {
    width: 664px;
    height: 500px;
    aspect-ratio: auto;
  }
  /* Portrait images are narrower than the 664px container and sit flush
     left, same as at 1200px+ — a flex child with an explicit width doesn't
     stretch across the container. */

  .gallery-detail-page .menu-backdrop {
    display: none; /* sidebar and content are separate columns here */
  }

  .gallery-detail-page .menu {
    position: fixed;
    top: auto;
    left: 0;
    right: auto;
    bottom: 0;
    height: auto;
    display: flex;
    flex-direction: column;
    gap: 0;
    padding: 0 0 60px 60px;
  }

  .gallery-detail-page .menu__item {
    width: 60px;
    height: 44px;
    font-size: 20px;
    letter-spacing: var(--tracking-tight);
    justify-content: flex-start;
  }
}

/* Gallery pages' menu order on desktop: main / about / contacts, as in the
   mockups, while the DOM (and the horizontal mobile menu) stays
   about / main / contacts. Starts at 1024px, where the menu turns into the
   vertical sidebar stack, and carries through 1200px+ too — the order
   wasn't being applied there before, so the gallery pages showed
   about / main / contacts instead of what the 1200px+ mockups show. Same
   accessibility caveat as on the Work page: tab and screen-reader order
   still follow the DOM, not what's displayed. */
@media (min-width: 1024px) {
  .gallery-detail-page .menu__item--left {
    order: 2; /* about */
  }

  .gallery-detail-page .menu__item--center {
    order: 1; /* main */
  }

  .gallery-detail-page .menu__item--right {
    order: 3; /* contacts */
  }
}
