/* The Art of Brian Walker — site styles
   Modeled on the stark minimalism of karawalkerstudio.com:
   pure white, pure black, no borders, no shadows. */

:root {
  --bg: #ffffff;
  --fg: #000000;
  --serif: "Times New Roman", Times, Georgia, serif;
  --sans: "Helvetica Neue", Helvetica, Arial, sans-serif;
  --header-h: 96px;   /* fallback; measured at runtime on one-work-per-screen pages */
}

* { margin: 0; padding: 0; box-sizing: border-box; }

html, body {
  background: var(--bg);
  color: var(--fg);
  font-family: var(--sans);
  font-size: 14px;
  line-height: 1.6;
}

/* Keeps full-bleed (100vw) blocks from adding a sideways scrollbar.
   Must be "clip", not "hidden": overflow-x:hidden turns the page into a
   scroll container and stops the sticky top bar from sticking. */
body {
  overflow-x: clip;
}

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

/* ---------- LANDING PAGE (full-screen image) ---------- */

.landing-full {
  position: relative;
  width: 100vw;
  height: 100vh;
  overflow: hidden;
}

.landing-bg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;   /* fills the screen; use "contain" to show the whole image uncropped */
  display: block;
}

.landing-bar {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  padding: 28px 36px;
}

.landing-bar h1 {
  font-family: var(--sans);
  font-weight: 700;
  font-size: 48px;
  letter-spacing: 2px;
  text-transform: uppercase;
}

.landing-bar h1 a {
  color: #ffffff;
  text-shadow: 0 1px 4px rgba(0,0,0,0.7), 0 0 18px rgba(0,0,0,0.45);
}

.landing-bar .enter {
  font-family: var(--sans);
  font-size: 20px;
  font-weight: 700;
  letter-spacing: 3px;
  text-transform: uppercase;
  color: #b0b0b0;
  border: 2px solid #b0b0b0;
  padding: 10px 22px;
  transition: background 0.15s, color 0.15s, border-color 0.15s;
}

.landing-bar .enter:hover {
  background: #000000;
  color: #ffffff;
  border-color: #000000;
  text-decoration: none;
}

/* A quiet line along the foot of the landing image.
   It is small and understated, but it is real, readable text. That matters:
   the landing page is otherwise wordless, so this sentence is the only thing
   a search engine can read on the page most likely to be searched for by
   name. Text hidden from visitors purely to feed crawlers — display:none,
   zero opacity, background-coloured type — is treated as a ranking penalty,
   so this stays legible on the photograph instead. The gradient behind it
   keeps it readable whatever the image is doing underneath. */

.landing-foot {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  padding: 48px 36px 18px;
  /* The gradient reaches near-full strength below the halfway mark and only
     then fades out, so the type sits on a consistently dark band rather than
     on whatever the photograph happens to be doing. Measured against the
     actual pixels of hero.jpg, the worst-case contrast is about 5.6:1 —
     past the 4.5:1 WCAG AA threshold for small text. */
  background: linear-gradient(to top,
              rgba(0, 0, 0, 0.72) 0%,
              rgba(0, 0, 0, 0.66) 45%,
              rgba(0, 0, 0, 0) 100%);
  pointer-events: none;
}

.landing-foot p {
  margin: 0;
  max-width: 62ch;
  font-family: var(--sans);
  font-size: 12px;
  line-height: 1.6;
  letter-spacing: 0.07em;
  color: rgba(255, 255, 255, 0.85);
}

@media (max-width: 760px) {
  .landing-bar { padding: 18px 20px; }
  .landing-bar h1 { font-size: 24px; }
  .landing-foot { padding: 34px 20px 14px; }
  .landing-foot p { font-size: 11px; line-height: 1.55; }
}

/* ---------- INNER PAGES: TOP NAV + CONTENT ---------- */

.site {
  max-width: 1100px;
  margin: 0 auto;
  padding: 0 40px 60px;   /* no top padding — the sticky header provides its own */
}

/* Sticky header: name + nav in one row, section title locked beneath */
.topbar {
  position: sticky;
  top: 0;
  z-index: 100;
  background: var(--bg);
  padding: 14px 0 8px;
  margin-bottom: 22px;
}

.topbar-row {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 10px 40px;
}

.topbar .page-title {
  font-family: var(--sans);
  font-weight: 700;
  font-size: 15px;
  letter-spacing: 2px;
  text-transform: uppercase;
  margin: 4px 0 0;
}

.topbar .site-title {
  font-family: var(--sans);
  font-weight: 700;
  font-size: 20px;
  letter-spacing: 2px;
  text-transform: uppercase;
  line-height: 1.2;
}

.topnav > ul {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: 28px;
}

.topnav a {
  font-size: 12px;
  letter-spacing: 1.5px;
  text-transform: uppercase;
  color: #999999;
}

.topnav a:hover { color: var(--fg); text-decoration: none; }

.topnav a.active { color: var(--fg); }

/* Dropdown under SELECTED WORKS — opens on hover or tap */
.dropdown { position: relative; }

.dropdown > a::after { content: " \25BE"; font-size: 9px; }

.dropdown-menu {
  display: none;
  position: absolute;
  top: 100%;
  left: 0;
  list-style: none;
  background: var(--bg);
  padding: 10px 0 4px;
  min-width: 140px;
  z-index: 10;
}

.dropdown-menu li { margin-bottom: 8px; }

.dropdown-menu a { color: #999999; }
.dropdown-menu a:hover,
.dropdown-menu a.active { color: var(--fg); }

.dropdown:hover .dropdown-menu,
.dropdown:focus-within .dropdown-menu {
  display: block;
}

/* Second level — the photography series open to the right of PHOTOGRAPHY.
   To add a series, add one <li> to .submenu-menu in every page's nav;
   nothing in this stylesheet needs to change. */
.dropdown-menu .submenu { position: relative; }

.dropdown-menu .submenu > a::after { content: " \25B8"; font-size: 9px; }

.submenu-menu {
  display: none;
  position: absolute;
  top: 0;
  left: 100%;
  list-style: none;
  background: var(--bg);
  padding: 0 0 4px 18px;
  min-width: 190px;
  z-index: 11;
}

.submenu-menu li { margin-bottom: 8px; }

/* Series names set on one line each. "Shades of Gray" is the longest and
   would otherwise wrap; nowrap also keeps any future longer name intact,
   widening the panel past the min-width instead of breaking. */
.submenu-menu a { color: #999999; white-space: nowrap; }
.submenu-menu a:hover,
.submenu-menu a.active { color: var(--fg); }

.submenu:hover .submenu-menu,
.submenu:focus-within .submenu-menu {
  display: block;
}

/* ---------- CONTENT ---------- */

.content { flex: 1; min-width: 0; max-width: 900px; margin: 0 auto; }

.content h2 {
  font-family: var(--sans);
  font-weight: 700;
  font-size: 28px;
  letter-spacing: 2px;
  text-transform: uppercase;
  margin-bottom: 30px;
}

.content h3.exhibition {
  font-family: var(--serif);
  font-weight: 400;
  font-style: italic;
  font-size: 18px;
  margin: 50px 0 25px;
}

/* Vertical stack — full-width, uncropped images, generous spacing */
.work {
  margin-bottom: 70px;
}

.work img {
  /* full image + caption fit in one view below the sticky header */
  max-height: calc(100vh - 155px);
  max-width: 100%;
  width: auto;
  height: auto;
  display: block;
  margin: 0 auto;     /* centered */
}

.work .caption {
  font-size: 12px;
  margin-top: 10px;
  line-height: 1.5;
  text-align: center;
}

.work .caption em { font-style: italic; }

/* One work per screen: the image and its caption together fill the space
   below the sticky header, so scrolling moves from one painting to the next
   with nothing of the following work showing.

   --header-h is measured by a small script on the page (the sticky header
   grows taller when the nav wraps on narrow screens); 96px is the fallback.
   Scroll snapping then parks each work exactly beneath the header. */
.works-full .work {
  height: calc(100vh - var(--header-h));
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  margin-bottom: 0;
  scroll-snap-align: start;
  scroll-snap-stop: always;
}

html.snap-works {
  scroll-snap-type: y proximity;
  scroll-padding-top: var(--header-h);
}

.works-full .work img {
  /* Fill the frame: take the whole screen below the header, leaving only the
     one-line caption (18px) plus its 10px gap underneath. */
  max-height: calc(100% - 30px);
  max-width: 100%;
  margin: 0;
}

.works-full .work .caption { margin-top: 10px; }

/* Front/back pairs also have to fit their single screen */
.works-full .pair-images { max-height: calc(100% - 30px); }
.works-full .pair-images img { max-height: 100%; }

/* Front/back pairs shown side by side in one row (front left, back right) */
.pair-images {
  display: flex;
  gap: 16px;
  justify-content: center;
  align-items: center;
}

.pair-images img {
  max-width: calc(50% - 8px);
  max-height: calc(100vh - 155px);
  width: auto;
  height: auto;
  display: block;
  margin: 0;
}

/* Placeholder frames until real images exist.
   Delete the .placeholder div and un-comment the <img> when swapping in art. */
.placeholder {
  height: 65vh;
  aspect-ratio: 4 / 5;
  max-width: 100%;
  margin: 0 auto;
  background: #f2f2f2;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #999;
  font-size: 12px;
  letter-spacing: 1px;
  text-transform: uppercase;
}

.placeholder.landscape { aspect-ratio: 3 / 2; }
.placeholder.square { aspect-ratio: 1 / 1; }

/* ---------- PHOTOGRAPHY: GALLERY WALL ---------- */

/* Salon-style grouping of photographs, like Kara's 2020 gallery walls.
   Sizes: gw-s / gw-m / gw-l control each photo's height on the wall. */
.gallery-wall {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  gap: 18px 22px;
  margin: 6px 0 20px;

  /* The wall breaks out of the 900px text column so the whole grouping
     fits on one screen. Text pages keep their narrow measure. */
  width: 1500px;
  max-width: calc(100vw - 80px);
  margin-left: 50%;
  transform: translateX(-50%);
}

/* Every photograph is scaled to the SAME AREA, so a portrait and a
   landscape carry equal visual weight on the wall. Each image sets its
   own --gw (height in vh); the value is derived from its aspect ratio. */
.gallery-wall img {
  display: block;
  width: auto;
  height: calc(var(--gw, 18.5) * 1vh);
  cursor: pointer;
}

.gallery-wall img:hover { outline: 3px solid var(--fg); outline-offset: 3px; }

/* One row of the wall. Splitting a grouping into several .wall-row walls
   fixes how many photographs sit on each row instead of letting the window
   width decide. The row never wraps: its photographs scale together to fit
   whatever width is available, so the count holds on any desktop screen.

   Each row carries --row-w (the sum of its photographs' natural widths, in
   the same vh units as --gw) and --row-gaps (how many gaps it contains). The
   width below is the smallest of: the 1500px wall, the window, and the row at
   its natural size — so the row grows to fill the screen but never past the
   size the --gw values intend. Only the vertical margins are overridden; the
   margin-left and translate that centre the wall come from .gallery-wall. */
/* --wall-s is how many pixels one vh unit is worth on this wall. It is 1vh
   at rest, and shrinks only when the widest row would not fit the window.
   Every row on the page reads the same value, so they all shrink together
   and the bottom row can never end up larger than the top one. --wall-nat
   and --wall-gaps, set on the page's <main>, describe that widest row. */
.content {
  --wall-s: min(1vh,
                calc((min(1500px, 100vw - 80px) - var(--wall-gaps, 0) * 22px)
                     / var(--wall-nat, 100)));
}

.wall-row {
  flex-wrap: nowrap;
  margin-top: 0;
  margin-bottom: 18px;
  width: calc(var(--row-w, 100) * var(--wall-s) + var(--row-gaps, 0) * 22px);
}

.wall-row:last-of-type { margin-bottom: 20px; }

/* flex-basis 0 with a grow factor of --aw (the photograph's natural width)
   splits the row in proportion to those widths and fills it exactly. Every
   photograph in the row is therefore scaled by the same factor, which is
   what keeps them all at equal area. Height follows from the width. */
.wall-row img {
  flex: var(--aw, 20) 1 0;
  width: auto;
  height: auto;
  min-width: 0;
}

/* Legacy fixed sizes, kept for the other work pages. The photography
   wall now uses the equal-area --gw value set on each image instead. */
.gw-s { height: 13vh; }
.gw-m { height: 17vh; }
.gw-l { height: 22vh; }
.gw-xl { height: 30vh; }

/* Expanded view: click a photo on the wall to open it at full scale */
.lightbox {
  position: fixed;
  inset: 0;
  z-index: 200;
  background: var(--bg);
  display: none;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 30px 40px;
}

.lightbox.open { display: flex; }

.lightbox img {
  max-width: 100%;
  max-height: calc(100vh - 140px);
  width: auto;
  height: auto;
  display: block;
  cursor: zoom-out;
}

.lightbox .caption {
  font-size: 12px;
  margin-top: 12px;
  text-align: center;
}

.lightbox-close {
  position: absolute;
  top: 16px;
  right: 24px;
  background: none;
  border: none;
  font-size: 30px;
  line-height: 1;
  color: var(--fg);
  cursor: pointer;
  font-family: var(--sans);
}

@media (max-width: 760px) {
  .gallery-wall {
    gap: 10px 12px;
    width: 100%;
    max-width: 100%;
    margin-left: 0;
    transform: none;
  }
  /* same equal-area ratios, scaled down for a phone screen */
  .gallery-wall img { height: calc(var(--gw, 18.5) * 0.62vh); }

  /* A phone is too narrow to hold a row of six at any readable size, so the
     fixed rows go back to wrapping here and the photographs return to their
     own heights rather than sharing the row's width. */
  .wall-row {
    flex-wrap: wrap;
    width: 100%;
  }
  .wall-row img {
    flex: 0 0 auto;
    width: auto;
    height: calc(var(--gw, 18.5) * 0.62vh);
  }
  /* on a phone let the works flow normally rather than one per screen */
  .works-full .work { height: auto; margin-bottom: 50px; }
  .works-full .work img { max-height: calc(100vh - 200px); }
  .gw-s { height: 9vh; }
  .gw-m { height: 11vh; }
  .gw-l { height: 14vh; }
  .gw-xl { height: 17vh; }
  .lightbox { padding: 20px; }
}

/* ---------- TEXT PAGES (biography, news, contact) ---------- */

/* Photo on the Biography page: full-bleed, fills the screen below the sticky
   header so the text begins only after you scroll past it. The negative side
   margins break the image out of the 1100px .site container. */
.bio-photo {
  width: 100vw;
  max-width: 100vw;
  margin-left: calc(50% - 50vw);
  margin-right: calc(50% - 50vw);
  /* Exactly one screen: viewport minus the sticky header (measured at runtime
     by the script on biography.html, so nav wrapping can't throw it off).
     No bottom margin — the text starts on the very next pixel after the fold,
     which is as far up as it can go without entering the photo's screen. */
  min-height: var(--bio-photo-h, calc(100vh - 96px));
  display: flex;
  flex-direction: column;
  justify-content: center;
  margin-bottom: 0;
}

.bio-photo img {
  width: 100vw;
  height: auto;
  /* Leaves room for the credit line beneath it; never clipped. */
  max-height: calc(var(--bio-photo-h, calc(100vh - 96px)) - 64px);
  object-fit: contain;
  display: block;
}

.bio-photo .photo-credit {
  text-align: center;
  padding: 0 40px;
}

.bio-photo .placeholder {
  height: auto;
  aspect-ratio: 4 / 5;
}

/* Italic credit line under photos and video (like Kara's "Photo: …") */
.photo-credit {
  font-family: var(--serif);
  font-style: italic;
  font-size: 12px;
  margin-top: 8px;
}

.news-video + .photo-credit { max-width: 480px; margin: -22px auto 30px; }

.content .prose { max-width: 620px; margin: 0 auto; }
.content .prose p { margin-bottom: 18px; }

/* Biography text only: a slightly wider column and tighter paragraph spacing
   so the whole bio lands on one screen below the photo. */
.content .bio-prose { max-width: 700px; padding-top: 12px; }
.content .bio-prose p { margin-bottom: 14px; }
.bio-page .site { padding-bottom: 28px; }
/* Artist statement on the Statement page. It was set in italic back when the
   biography sat above it and the slant marked the shift into Brian's own
   voice; the statement now has the page to itself, so it is set upright for
   reading at length. A little extra size and leading carry the serif. */
.content .artist-statement {
  font-family: var(--serif);
  font-size: 17px;
  line-height: 1.7;
  margin-top: 26px;
}

.content .artist-statement p { margin-bottom: 15px; }
.content .artist-statement p:last-child { margin-bottom: 0; }

/* Now that the statement opens the page, it needs no gap above it. */
.content .artist-statement:first-child { margin-top: 0; }

.content .prose h3 {
  font-family: var(--serif);
  font-weight: 400;
  font-size: 18px;
  margin: 34px 0 12px;
}

/* Pull quotes on the News page */
.pull-quote {
  font-family: var(--serif);
  font-style: italic;
  font-size: 17px;
  line-height: 1.5;
  margin: 0 auto 22px;
  max-width: 540px;
}

.pull-quote .quote-source {
  display: block;
  font-family: var(--sans);
  font-style: normal;
  font-size: 11px;
  letter-spacing: 1px;
  text-transform: uppercase;
  margin-top: 6px;
  color: #999999;
}

/* Press clipping images on the News page */
.press-clipping {
  display: block;
  width: 100%;
  max-width: 540px;
  height: auto;
  margin: 12px auto 34px;
}

/* Video on the News page */
.news-video {
  display: block;
  width: 100%;
  max-width: 480px;
  margin: 0 auto 30px;
  background: #000;
}

/* ---------- BACK TO TOP ----------
   A drawn line with an arrowhead, like a pencil stroke. Hidden until the
   visitor has scrolled past the first screen; on hover the stroke grows
   taller and goes solid black. */

.to-top {
  position: fixed;
  right: 34px;
  bottom: 34px;
  z-index: 60;
  width: 34px;
  height: 62px;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
  color: #000;
  opacity: 0;
  visibility: hidden;
  transform: translateY(10px);
  transition: opacity .35s ease, transform .35s ease, visibility .35s;
  -webkit-tap-highlight-color: transparent;
}

.to-top.is-visible {
  opacity: .55;
  visibility: visible;
  transform: translateY(0);
}

.to-top.is-visible:hover,
.to-top.is-visible:focus-visible {
  opacity: 1;
}

/* Stay out of the way while a photo is open in the lightbox */
.lightbox.open ~ .to-top { opacity: 0; visibility: hidden; }

.to-top:focus { outline: none; }
.to-top:focus-visible svg { outline: 1px dotted currentColor; outline-offset: 6px; }

.to-top svg {
  display: block;
  width: 100%;
  height: 100%;
  overflow: visible;
}

.to-top .stem,
.to-top .head {
  fill: none;
  stroke: currentColor;
  stroke-width: 1.1;
  stroke-linecap: round;
  stroke-linejoin: round;
  transition: stroke-width .3s ease, transform .3s ease;
}

/* The stem grows upward from its base; the arrowhead rides up with it. */
.to-top .stem { transform-origin: 17px 56px; }

.to-top:hover .stem,
.to-top:focus-visible .stem {
  stroke-width: 2.4;
  transform: scaleY(1.16);
}

.to-top:hover .head,
.to-top:focus-visible .head {
  stroke-width: 2.4;
  transform: translateY(-6px);
}

.to-top:active .stem,
.to-top:active .head { stroke-width: 3; }

@media (prefers-reduced-motion: reduce) {
  .to-top,
  .to-top .stem,
  .to-top .head { transition-duration: .01ms; }
  .to-top:hover .stem { transform: none; }
  .to-top:hover .head { transform: none; }
}

/* ---------- MOBILE ---------- */

@media (max-width: 760px) {
  .site { padding: 0 20px 40px; }
  .topbar { padding: 12px 0 8px; }
  .topbar-row { gap: 6px 20px; }
  .topbar .site-title { font-size: 17px; }
  .topnav > ul { gap: 16px; }
  .to-top { right: 18px; bottom: 18px; width: 26px; height: 48px; }

  /* Touch screens have no hover, so a flyout would be unreachable: the
     series sit nested under PHOTOGRAPHY instead, always visible once the
     Selected Works menu is open. */
  .submenu-menu {
    display: block;
    position: static;
    min-width: 0;
    padding: 8px 0 0 14px;
  }

  .dropdown-menu .submenu > a::after { content: ""; }
}
