/* ============================================================================
   rbaker.art
   Robert Baker — algorithmic artist

   No animation anywhere on this site except the video itself. Hover states
   change instantly; nothing fades, rises, or reveals on scroll.
   ========================================================================== */

/* --- Tokens --------------------------------------------------------------- */

:root {
  /* Grayscale, per the client. --rule is only ever seen as the placeholder
     behind an image or video that has not arrived yet. Hover and focus use
     ink and ink-mid; there is no accent colour. */
  --paper:    #fafafa;
  --ink:      #1b1b1b;
  --ink-mid:  #5a5a5a;
  --rule:     #e8e8e8;

  --font: 'Hanken Grotesk', 'Avenir Next', Avenir, 'Segoe UI', sans-serif;

  /* The content column. Text and media share it exactly, so a paragraph is
     always the same width as the image below it. With the body type capped at
     18px (client's choice) a full line runs about 84 characters; the 1.75
     line-height is what keeps a line that long easy to track. */
  --container: 850px;
  --gutter:  clamp(1.25rem, 5vw, 3.5rem);

  /* Vertical breathing room. Generous on a wide screen so the media sits in
     white space rather than filling the viewport. */
  --section:  2.5rem;
  --media-gap: clamp(2.5rem, 6vw, 5.5rem);
  --grid-gap: clamp(0.5rem, 1.1vw, 0.875rem);

  /* Media box proportions. Landscape 4:3, portrait 3:4 — matches the supplied
     video cuts and artwork. Change in one place if the cuts change. */
  --media-aspect: 4 / 3;
}

@media (orientation: portrait) {
  :root { --media-aspect: 3 / 4; }
}

/* --- Reset ---------------------------------------------------------------- */

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

/* One type scale for the whole site. Every size, tap target and the menu
   mark is set in rem, so they all grow together: 16px root on a phone, rising
   evenly to an 18px cap at 1280px wide. Proportions never change. */
html {
  -webkit-text-size-adjust: 100%;
  font-size: clamp(100%, 94.52% + 0.2247vw, 112.5%);
}

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font);
  font-weight: 300;
  font-size: 1rem;
  line-height: 1.75;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

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

figure { margin: 0; }

h1, h2, p { margin: 0; }

ul { margin: 0; padding: 0; list-style: none; }

a { color: inherit; }

/* Phones paint a grey box over anything tapped. Off, so the menu and pager
   behave on touch exactly as they do on click. Keyboard focus is unaffected —
   :focus-visible below still draws its ring. */
a, button { -webkit-tap-highlight-color: transparent; }

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

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

::selection { background: var(--ink); color: var(--paper); }

/* --- Skip link ------------------------------------------------------------ */

.skip {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 100;
  background: var(--ink);
  color: var(--paper);
  padding: 0.6rem 1rem;
  font-size: 0.875rem;
}

.skip:focus {
  left: var(--gutter);
  top: 0.75rem;
}

/* --- Shell ---------------------------------------------------------------- */

/* The gutters sit outside the content column, so on a wide screen the column
   is exactly --container wide rather than --container minus padding. */
.wrap {
  max-width: calc(var(--container) + var(--gutter) * 2);
  margin-inline: auto;
  padding-inline: var(--gutter);
  padding-block: clamp(2rem, 5vw, 3.25rem) clamp(3rem, 7vw, 5rem);
}

/* --- Header --------------------------------------------------------------- */

.head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1.5rem;
  margin-bottom: var(--section);
}

.head h1 {
  font-size: 1.05rem;
  font-weight: 300;
  letter-spacing: 0.085em;
  text-transform: uppercase;
  line-height: 1.3;
  /* The brand lockup must never wrap while the menu sits beside it. */
  white-space: nowrap;
}

/* --- Menu ----------------------------------------------------------------- */

/* The toggle is a 44px+ tap target but the mark inside it is small, so the box
   is pulled up to sit the mark on the title's optical centre line. */
.menu {
  position: relative;
  flex: none;
  margin-top: -0.45rem;
}

.menu__toggle {
  /* 44px minimum tap target at the 16px root, growing with the type */
  display: grid;
  place-items: center;
  min-width: 2.75rem;
  min-height: 2.75rem;
  margin: -0.3rem -0.3rem -0.3rem 0;
}

.menu__mark {
  width: 0.9375rem;
  height: 0.9375rem;
  display: block;
  color: var(--ink);
}

/* Open state: the four dots turn 22.5° counterclockwise, instantly. */
.menu__toggle[aria-expanded='true'] .menu__mark { transform: rotate(-22.5deg); }

.menu__panel {
  position: absolute;
  top: calc(100% + 0.5rem);
  right: 0;
  min-width: 10.5rem;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 0.35rem;
  text-align: right;
  background: var(--paper);
  padding: 0.5rem 0.3rem 0.75rem;
  margin: -0.5rem -0.3rem -0.75rem;
  font-size: 0.95rem;
  line-height: 1.5;
  z-index: 20;
}

.menu__panel[hidden] { display: none; }

.menu__panel a {
  text-decoration: none;
  color: var(--ink-mid);
  padding-block: 0.22rem;
}

.menu__panel a:hover,
.menu__panel a:focus-visible { color: var(--ink); }

/* --- Reading column ------------------------------------------------------- */

/* No max-width of its own: the paragraph column is the content column, which
   is the same width as the media below it. */
.prose { margin-bottom: var(--section); }

.prose p + p { margin-top: 1.5em; }

.prose em { font-style: italic; }

.prose a {
  font-weight: 500;
  text-decoration: underline;
  text-underline-offset: 0.16em;
  text-decoration-thickness: from-font;
}

.prose a:hover,
.prose a:focus-visible { color: var(--ink-mid); }

/* --- Media block ---------------------------------------------------------- */

.work { margin-bottom: var(--media-gap); }

.work:last-child { margin-bottom: 0; }

/* The hero carries the pager as its caption, and the pager supplies the
   spacing below — otherwise the two margins would stack. */
.work--hero { margin-bottom: 0; }

.work__frame {
  position: relative;
  aspect-ratio: var(--media-aspect);
  overflow: hidden;
  background: var(--rule);
}

.work__frame img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* The frame's width is fluid, so its height lands on a fractional pixel and
   the player box rarely matches 4:3 (or 3:4) exactly. Vimeo letterboxes the
   difference with its black background, which showed as hairlines along the
   edges. The player is drawn 3px larger on every side and the frame clips the
   overscan, so any letterboxing falls outside what is visible. Cost: under
   0.5% of the picture at the edges. */
.work__frame iframe {
  position: absolute;
  top: -3px;
  left: -3px;
  width: calc(100% + 6px);
  height: calc(100% + 6px);
  border: 0;
}

/* The player is mounted hidden and shown the moment Vimeo reports it ready,
   so the still underneath is never replaced by a blank box. No fade. */
.work__frame iframe { visibility: hidden; }

.work__frame iframe.is-playing { visibility: visible; }

.caption {
  margin-top: 0.85rem;
  font-size: 0.9rem;
  font-style: italic;
  line-height: 1.5;
  color: var(--ink-mid);
}

/* --- Edge of Space: pager ------------------------------------------------- */

.pager {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  margin-top: 0.85rem;
  margin-bottom: var(--section);
}

.pager__label {
  font-size: 0.9rem;
  font-style: italic;
  color: var(--ink-mid);
  text-align: center;
}

.pager__btn {
  min-width: 2.75rem;
  min-height: 2.75rem;
  display: grid;
  place-items: center;
  font-size: 1.05rem;
  color: var(--ink-mid);
  flex: none;
}

.pager__btn:hover,
.pager__btn:focus-visible { color: var(--ink); }

/* --- Architecture grid ---------------------------------------------------- */

.arch { display: grid; gap: var(--grid-gap); }

/* One tall image beside two stacked ones, as a single grid with a fixed
   proportion. Because the pair has its own aspect-ratio, the whole group
   scales down together as the window narrows — the columns stay locked to each
   other and nothing can overrun its neighbour.

   The ratio: the tall image is 2:3 in a 0.9fr column, so it stands 1.35 units
   high across a 1.9-unit-wide pair. */
.arch__pair {
  display: grid;
  grid-template-columns: minmax(0, 0.9fr) minmax(0, 1fr);
  grid-template-rows: minmax(0, 1fr) minmax(0, 1fr);
  gap: var(--grid-gap);
  aspect-ratio: 1.9 / 1.35;
}

.arch__tall { grid-column: 1; grid-row: 1 / 3; }

.arch figure { overflow: hidden; min-height: 0; min-width: 0; background: var(--rule); }

.arch img { width: 100%; height: 100%; object-fit: cover; }

/* Phone and small tablet: one column, each photo at its natural proportion.
   Two columns below this would make every image unreadably small. */
@media (max-width: 720px) {
  .arch__pair {
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: auto;
    aspect-ratio: auto;
  }
  .arch__tall { grid-column: auto; grid-row: auto; }
  .arch img { height: auto; }
}

/* --- Footer --------------------------------------------------------------- */

.foot {
  margin-top: clamp(3rem, 8vw, 6rem);
  font-size: 0.95rem;
  line-height: 1.75;
  color: var(--ink);
}

.foot__links a {
  color: inherit;
  text-decoration: underline;
  text-underline-offset: 0.16em;
  text-decoration-thickness: from-font;
}

/* Drawn without an underline in his mockups; still a working mailto link. */
.foot__links a[href^='mailto:'] { text-decoration: none; }

.foot__links a:hover,
.foot__links a:focus-visible { color: var(--ink-mid); }

/* A handle with no live account yet: shown as plain text, never a dead link. */
.foot__links [aria-disabled='true'] {
  text-decoration: none;
  cursor: default;
}

.foot__copy {
  margin-top: 1.5rem;
  font-size: 0.9rem;
  color: var(--ink-mid);
}
