/*
Theme Name: Ogbonna
Theme URI: https://bradogbonna.com
Author: Brad Ogbonna
Description: Minimal image-forward portfolio theme. Full-bleed slideshow home, click-through project viewers, a Motion section, and a per-section thumbnail index.
Version: 3.4
Requires at least: 6.0
Tested up to: 6.6
Requires PHP: 7.4
License: GNU General Public License v2 or later
License URI: http://www.gnu.org/licenses/gpl-2.0.html
Text Domain: ogbonna
*/

/* ============================================================
   TOKENS — the only numbers you should need to change
   ============================================================ */

:root {
  --bg:   #FFFFFF;
  --ink:  #111111;
  --mute: #999999;
  --hair: #E5E5E5;

  --nav-h: 56px;        /* top nav height */
  --bar-h: 44px;        /* prev / next / index bar height */
  --sidebar-w: 210px;   /* project sidebar */

  /* Image scale — the white border around every frame.
     --slide-x is the margin left and right, --slide-y top and bottom.
     Both apply to portrait and landscape alike, so a tall frame sits
     inside the same border as a wide one. Lower them for bigger
     images, raise them for more white. */
  --slide-x: 3vw;
  --slide-y: 3vh;

  /* Index sheet grid */
  /* Thumbnail sheet. --sheet-h is the height every thumbnail stands at,
     regardless of whether it's a vertical or a horizontal. Widths follow
     from each image's shape. */
  --sheet-gap-x: 14px;
  --sheet-gap-y: 14px;
  --sheet-h: 290px;

  --pad: 22px;
}

/* ============================================================
   RESET
   ============================================================ */

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

html, body { margin: 0; padding: 0; }

body {
  background: var(--bg);
  color: var(--ink);
  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
  font-size: 12px;
  line-height: 1.45;
  letter-spacing: 0.01em;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

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

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

button {
  font: inherit;
  color: inherit;
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
}

:focus-visible {
  outline: 1px solid var(--ink);
  outline-offset: 2px;
}

.screen-reader-text {
  position: absolute;
  width: 1px; height: 1px;
  overflow: hidden;
  clip: rect(1px, 1px, 1px, 1px);
  white-space: nowrap;
}

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 999;
  background: var(--bg);
  padding: 10px 14px;
}
.skip-link:focus { left: 0; }

/* ============================================================
   TOP NAV
   ============================================================ */

.nav {
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 60;
  height: var(--nav-h);
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 var(--pad);
  background: var(--bg);
}

/* Over a full-bleed image the nav inverts against whatever is behind it. */
.nav.over {
  background: transparent;
  mix-blend-mode: difference;
  color: #FFFFFF;
}

.wordmark {
  font-weight: 500;
  letter-spacing: 0.02em;
}

.nav-right {
  display: flex;
  align-items: center;
  gap: 20px;
}

.nav-right a[aria-current="page"],
.nav-right .work[aria-current="true"] { text-decoration: underline; text-underline-offset: 3px; }

/* Work dropdown */
.work { position: relative; cursor: default; }

.work-list {
  position: absolute;
  top: 100%;
  left: 0;
  display: none;
  flex-direction: column;
  gap: 6px;
  padding: 10px 0 0;
  white-space: nowrap;
}
.work:hover .work-list,
.work:focus .work-list,
.work:focus-within .work-list { display: flex; }

.menu-btn { display: none; }

/* ============================================================
   VIEWER — one image at a time, used by home, projects, motion
   ============================================================ */

.viewer {
  position: relative;
  height: calc(100vh - var(--nav-h) - var(--bar-h));
  height: calc(100svh - var(--nav-h) - var(--bar-h));
  margin-top: var(--nav-h);
  overflow: hidden;
}

.slide {
  position: absolute;
  inset: 0;
  display: none;
  align-items: center;
  justify-content: center;
  padding: var(--slide-y) var(--slide-x);
}
.slide.on { display: flex; }

/* Portrait: as tall as the stage allows, minus the border. */
.slide.is-portrait img {
  height: 100%;
  width: auto;
  max-width: 100%;
  object-fit: contain;
}

/* Landscape: as wide as the stage allows, minus the border, and
   capped by the height so a very wide frame gains side margin rather
   than losing its top and bottom. */
.slide.is-landscape img,
.slide.is-square img {
  width: auto;
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
}

/* Horizontal placement. Each image gets one of these, so paging through
   shifts the eye rather than dropping every picture in the same spot.
   These only bite when the image is narrower than the frame — a
   landscape already filling the width has no room to move. */
.slide.pos-left   { justify-content: flex-start; }
.slide.pos-center { justify-content: center; }
.slide.pos-right  { justify-content: flex-end; }

/* To switch this off and centre everything, delete the three rules
   above — the default is already centred. */

/* Caption — the attachment's Caption field, centered under the photo
   near the bottom of the frame. Sits above the prev/next/index bar,
   inside the same margin every image already has. Doesn't intercept
   clicks, so the left/right advance zones still work underneath it. */
.slide-caption {
  position: absolute;
  left: var(--slide-x);
  right: var(--slide-x);
  bottom: calc(var(--slide-y) * 0.6);
  z-index: 6;
  margin: 0;
  text-align: center;
  color: var(--mute);
  pointer-events: none;
}

.viewer.full .slide-caption {
  bottom: calc(var(--bar-h) + var(--slide-y) * 0.6);
}

/* Follow the photo. A caption stranded in the middle of the page while
   the picture sits far left reads as unrelated to it. */
.slide.pos-left  .slide-caption { text-align: left; }
.slide.pos-right .slide-caption { text-align: right; }

/* Click zones — right half forward, left half back. */
.zone {
  position: absolute;
  top: 0; bottom: 0;
  width: 50%;
  z-index: 5;
  background: transparent;
}
.zone.prev { left: 0;  cursor: w-resize; }
.zone.next { right: 0; cursor: e-resize; }

/* These are mouse conveniences layered over the image, each a half-width
   box taller than the window. A focus ring on one drew its inner edge as
   a hairline straight down the middle of the page. They're out of the tab
   order now — keyboard users get Prev and Next in the bar, which show
   focus properly — and this makes sure no ring can appear on them. */
.zone:focus,
.zone:focus-visible { outline: none; }

/* Home slideshow runs the full height of the window. The nav and the
   bar float over it, so the image still sits inside the same border
   as everywhere else. */
.viewer.full {
  height: 100vh;
  height: 100svh;
  margin-top: 0;
}

/* The nav and bar float over the home slideshow rather than sitting
   above and below it, so the border has to clear them by hand. */
.viewer.full .slide {
  padding:
    calc(var(--nav-h) + var(--slide-y))
    var(--slide-x)
    calc(var(--bar-h) + var(--slide-y));
}

/* ============================================================
   PREV / NEXT / INDEX BAR — the same on every section
   ============================================================ */

.bar {
  position: fixed;
  bottom: 0; left: 0; right: 0;
  z-index: 55;
  height: var(--bar-h);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 0 var(--pad);
  background: var(--bg);
  border-top: 1px solid var(--hair);
}

.bar-nav {
  display: flex;
  align-items: center;
  gap: 18px;
}

.bar button[disabled],
.bar a[aria-disabled="true"] {
  color: var(--mute);
  cursor: default;
  pointer-events: none;
}

.bar-meta {
  color: var(--mute);
  display: flex;
  align-items: center;
  gap: 14px;
}

.bar-title { color: var(--ink); }

/* On project pages the bar clears the sidebar. */
.has-sidebar .bar { left: var(--sidebar-w); }

/* Over the full-bleed home image the bar floats. */
.bar.over {
  background: transparent;
  border-top: 0;
  mix-blend-mode: difference;
  color: #FFFFFF;
}

/* ============================================================
   INDEX SHEET — the thumbnail overlay, one per section
   ============================================================ */

.sheet {
  position: fixed;
  inset: 0;
  z-index: 80;
  background: var(--bg);
  overflow-y: auto;
  padding: calc(var(--nav-h) + 12px) var(--pad) calc(var(--bar-h) + 32px);
  display: none;
}
.sheet.open { display: block; }

.sheet-head {
  position: sticky;
  top: 0;
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  padding-bottom: 14px;
  background: var(--bg);
}

/* Rows of uniform height rather than columns of uniform width. Every
   thumbnail stands the same height and takes whatever width its shape
   needs, so a vertical reads as narrow and a horizontal as wide, and
   the two can be compared at a glance. --sheet-h is the single number
   to change; the rows reflow around it. */
.sheet-grid {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sheet-gap-y) var(--sheet-gap-x);
  align-items: flex-start;
}

.sheet-item {
  display: block;
  width: auto;
  text-align: left;
}
.sheet-item img {
  height: var(--sheet-h);
  width: auto;
  max-width: none;
}
.sheet-item.is-current img { outline: 1px solid var(--ink); outline-offset: 3px; }

.sheet-cap {
  display: block;
  padding-top: 6px;
  color: var(--mute);
}

/* Motion posters stand the same height as everything else, with 16:9
   fixing their width. */
.sheet-item.motion .poster {
  position: relative;
  display: block;
  height: var(--sheet-h);
  aspect-ratio: 16 / 9;
  background: #EEEEEE;
  overflow: hidden;
}
.sheet-item.motion .poster img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* ============================================================
   SELECT WORK — the landing grid
   ============================================================ */

.work-grid {
  margin-top: var(--nav-h);
  padding: 24px var(--pad) 80px;
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 28px;
}

.work-card { position: relative; display: block; }
.work-card img { width: 100%; height: auto; }

.work-card .cap {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  padding: 14px 16px;
  color: #FFFFFF;
  font-weight: 700;
  opacity: 0;
  background: linear-gradient(to top, rgba(0,0,0,0.45), rgba(0,0,0,0));
  transition: opacity 120ms linear;
}
.work-card:hover .cap,
.work-card:focus-visible .cap { opacity: 1; }

/* ============================================================
   PROJECT PAGES — persistent sidebar + viewer
   ============================================================ */

.project-shell {
  display: grid;
  grid-template-columns: var(--sidebar-w) 1fr;
  min-height: 100vh;
}

.sidebar {
  position: fixed;
  top: var(--nav-h);
  bottom: var(--bar-h);
  left: 0;
  width: var(--sidebar-w);
  padding: 8px var(--pad) 20px;
  overflow-y: auto;
}

.sidebar ul { list-style: none; margin: 0; padding: 0; }
.sidebar li { padding: 3px 0; }
.sidebar a[aria-current="page"] { text-decoration: underline; text-underline-offset: 3px; }
.sidebar .group {
  color: var(--mute);
  padding: 16px 0 4px;
}
.sidebar .group:first-child { padding-top: 0; }

.project-main { grid-column: 2; }

/* ============================================================
   MOTION
   ============================================================ */

.motion-frame {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0 var(--slide-x);
}

.motion-embed {
  width: 100%;
  max-width: calc((100vh - var(--nav-h) - var(--bar-h)) * 16 / 9);
  aspect-ratio: 16 / 9;
  background: #000000;
}
.motion-embed iframe,
.motion-embed video {
  width: 100%;
  height: 100%;
  border: 0;
  display: block;
}

/* A URL pasted into the editor body arrives wrapped in WordPress's own
   embed markup, which brings its own aspect-ratio boxes and margins.
   Flatten those so the player fills the frame either way. */
.motion-embed figure,
.motion-embed .wp-block-embed,
.motion-embed .wp-block-embed__wrapper,
.motion-embed p {
  margin: 0;
  padding: 0;
  width: 100%;
  height: 100%;
}
.motion-embed .wp-block-embed__wrapper::before { display: none; }

.motion-empty {
  color: var(--mute);
  text-align: center;
  padding: 40px var(--pad);
}

/* Motion landing grid */
.motion-grid {
  margin-top: var(--nav-h);
  padding: 24px var(--pad) 80px;
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 28px;
}
.motion-grid .poster {
  position: relative;
  aspect-ratio: 16 / 9;
  background: #EEEEEE;
  overflow: hidden;
}
.motion-grid .poster img { width: 100%; height: 100%; object-fit: cover; }
.motion-grid .cap { padding-top: 8px; }
.motion-grid .client { color: var(--mute); }

/* ============================================================
   INFO
   ============================================================ */

.info-doc {
  margin-top: var(--nav-h);
  padding: 28px var(--pad) 80px;
  max-width: none;
}

/* Four columns at 3 / 2 / 2 / 2. The bio column being half again as
   wide as the others is what stops the page reading as a table — the
   short bio leaves a deep well of white before the client list starts.
   Core Columns block does the layout so the page stays editable. */
.info-doc .wp-block-columns {
  align-items: flex-start;
  gap: 12px;
  margin: 0;
}
.info-doc .wp-block-column { min-width: 0; }

/* Section labels. Typed in sentence case in the editor and set in caps
   here, so the caps are a display choice rather than something baked
   into the content. */
.info-doc h2 {
  font-size: 14px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.01em;
  line-height: 1.25;
  margin: 0 0 14px;
}

/* Bio column: larger, with open leading. */
.info-doc p {
  font-size: 16px;
  line-height: 1.625;
  margin: 0 0 16px;
}

/* Client and publication columns: a size down, with the leading pulled
   tight inside each entry and the air placed between entries instead.
   Long names like "The Elder Statesman" then wrap as one compact unit
   rather than opening a gap mid-name. */
.info-doc ul {
  list-style: none;
  margin: 0;
  padding: 0;
}
.info-doc li {
  font-size: 14px;
  line-height: 1.25;
  margin: 0 0 14px;
}

/* Lists sit under a label of the same size, so the label column reads
   a step smaller than the bio. */
.info-doc .wp-block-column:not(:first-child) h2 { font-size: 14px; }

.info-doc em,
.info-doc i { font-style: italic; }

.info-doc a { text-decoration: underline; text-underline-offset: 2px; }
.info-doc a:hover { opacity: 0.5; }

.info-doc figure,
.info-doc .wp-block-image { margin: 0 0 28px; }
.info-doc .wp-block-image img { width: 100%; height: auto; }

/* Trailing credit line, set quiet. */
.info-doc .credit { color: var(--mute); }

/* ============================================================
   MOBILE
   ============================================================ */

@media (max-width: 800px) {
  :root {
    --slide-x: 12px;
    --slide-y: 12px;
    --sheet-h: 175px;
    --pad: 14px;
  }

  .menu-btn { display: block; }

  .nav-right {
    display: none;
    position: absolute;
    top: var(--nav-h);
    left: 0; right: 0;
    flex-direction: column;
    align-items: flex-start;
    gap: 10px;
    padding: 14px var(--pad) 20px;
    background: var(--bg);
    color: var(--ink);
  }
  .nav.is-open .nav-right { display: flex; }
  .nav.is-open { mix-blend-mode: normal; background: var(--bg); color: var(--ink); }

  .work-list { position: static; display: flex; padding: 8px 0 0 12px; }

  .work-grid, .motion-grid { grid-template-columns: 1fr; gap: 20px; }

  /* Sidebar becomes a scrolling row of project names above the image. */
  .project-shell { display: block; }
  .project-main { grid-column: auto; }
  .sidebar {
    position: static;
    width: auto;
    margin-top: var(--nav-h);
    padding: 8px var(--pad);
    overflow-x: auto;
    white-space: nowrap;
    border-bottom: 1px solid var(--hair);
  }
  .sidebar ul { display: inline-flex; gap: 14px; }
  .sidebar .group { display: none; }
  .has-sidebar .bar { left: 0; }
  .has-sidebar .viewer { margin-top: 0; height: calc(100svh - var(--nav-h) - var(--bar-h) - 40px); }

  .bar-meta .bar-count { display: none; }

  /* Info columns stack in source order, and the type steps down a size
     the way the reference does below its desktop breakpoint. */
  .info-doc { padding-top: 24px; }
  .info-doc .wp-block-columns { gap: 0; }
  .info-doc .wp-block-column { flex-basis: 100% !important; margin-bottom: 24px; }
  .info-doc p { font-size: 14px; }
  .info-doc li,
  .info-doc h2 { font-size: 12px; }
  .info-doc li { margin-bottom: 10px; }
}

@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; animation: none !important; }
}
