/* ============================================================
   DANIEL GRÜNFELD — client galleries
   Same look as the portfolio: Cutive Mono, white paper, hairlines,
   classic link blue. Nothing is loaded from another server.
   ============================================================ */

/* The font is taken from this folder if it is there, otherwise from the
   portfolio next door. So the app works inside the site and, with the two
   .woff2 files copied into galleries/assets/fonts/, also on its own. */
@font-face {
  font-family: "Cutive Mono";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/cutive-mono-latin-400.woff2") format("woff2"),
       url("../../../assets/fonts/cutive-mono-latin-400.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Cutive Mono";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/cutive-mono-latin-ext-400.woff2") format("woff2"),
       url("../../../assets/fonts/cutive-mono-latin-ext-400.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
    U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
    U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

:root {
  --ink: #111111;
  --paper: #ffffff;
  --blue: #0000EE;
  --red: #e02b20;
  --mute: #555555;
  --hair: #d9d9d9;
  --mono: "Cutive Mono", "Courier New", Courier, monospace;
  --gap: 20px;
}

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

html { scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { transition: none !important; animation: none !important; }
}

body {
  font-family: var(--mono);
  font-size: 16px;
  line-height: 1.5;
  color: var(--ink);
  background: var(--paper);
  -webkit-font-smoothing: antialiased;
}

::selection { background: var(--blue); color: #fff; }

a { color: var(--blue); text-decoration: underline; text-underline-offset: 2px; }
a:hover { background: var(--blue); color: #fff; text-decoration: none; }
a:focus-visible, button:focus-visible, input:focus-visible {
  outline: 2px solid var(--blue);
  outline-offset: 3px;
}

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

.mono { font-family: var(--mono); font-size: 13px; letter-spacing: 0.02em; }
.small { font-size: 13px; }

/* ---------- Frame ---------- */

.wrap {
  max-width: 1400px;
  margin: 0 auto;
  padding: 28px 40px 120px;
}

.top {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 24px;
  flex-wrap: wrap;
}

.brand a, .brand span:first-child {
  font-size: 22px;
  letter-spacing: -0.01em;
  color: var(--ink);
  text-decoration: none;
}
.brand a:hover { background: none; color: var(--blue); }
.brand .role {
  display: block;
  font-size: 13px;
  color: var(--mute);
  margin-top: 6px;
}

.tools { color: var(--mute); }
.tools a { white-space: nowrap; }

.topline {
  display: flex;
  justify-content: space-between;
  gap: 16px;
  font-size: 13px;
  letter-spacing: 0.02em;
  color: var(--mute);
  border-bottom: 1px solid var(--hair);
  padding-bottom: 14px;
  margin: 42px 0 48px;
}
.topline span:first-child { color: var(--ink); }

main { min-width: 0; }

.notice { font-size: 17px; color: var(--mute); margin: 40px 0; }
.notice.small { font-size: 13px; margin-top: 56px; }

/* ---------- Masonry (plain CSS columns, no JavaScript) ---------- */

.masonry {
  column-count: 3;
  column-gap: var(--gap);
}
.masonry > * {
  break-inside: avoid;
  page-break-inside: avoid;      /* older browsers */
  display: block;
  margin: 0 0 var(--gap);
}
.masonry img {
  display: block;
  width: 100%;
  height: auto;
  outline: 1px solid transparent;
  outline-offset: 4px;
  transition: outline-color 0.15s ease-out;
  background: #f4f4f4;
}

/* Cover pictures on the front page — a grid, not a masonry: every cover
   is cropped to the same 3:2 shape, so the rows and captions line up
   whether the picture is landscape or portrait. "cover-focus:" in
   info.txt moves the crop (object-position). */
.covers {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 52px var(--gap);
  column-count: auto;
}
.covers > * { margin: 0; }
.cover {
  text-decoration: none;
  color: var(--ink);
}
.covers img {
  aspect-ratio: 3 / 2;
  object-fit: cover;
  object-position: 50% 50%;
}
.cover:hover { background: none; }
.cover:hover img { outline-color: var(--blue); }
.cover .cap {
  display: block;
  margin-top: 12px;
  font-size: 13px;
  letter-spacing: 0.02em;
}
.cover .cap .t { color: var(--blue); text-decoration: underline; text-underline-offset: 2px; }
.cover:hover .cap .t { background: var(--blue); color: #fff; text-decoration: none; }
.cover .cap .s { display: block; color: var(--mute); margin-top: 4px; }
.cover .nocover {
  display: flex;
  align-items: center;
  justify-content: center;
  aspect-ratio: 3 / 2;
  border: 1px solid var(--hair);
  color: var(--mute);
  font-size: 13px;
}

/* Photos inside a gallery */
.photos { column-count: 3; }
.shot { line-height: 0; cursor: zoom-in; }
.shot:hover { background: none; }
.shot:hover img { outline-color: var(--blue); }

@media (min-width: 1500px) {
  .photos { column-count: 4; }
}
@media (max-width: 1000px) {
  .masonry, .photos { column-count: 2; }
}
@media (max-width: 620px) {
  .masonry, .photos { column-count: 1; }
  .covers { grid-template-columns: minmax(0, 1fr); }
  .wrap { padding: 18px 20px 80px; }
  .topline { margin: 28px 0 32px; }
}

/* ---------- Tabs (a gallery with several picture folders) ---------- */

/* With JavaScript the tabs switch between the parts. Without it they are
   plain links down to the parts, which are then all visible at once. */
.tabs {
  display: flex;
  gap: 26px;
  flex-wrap: wrap;
  border-bottom: 1px solid var(--hair);
  padding-bottom: 12px;
  margin-bottom: 44px;
}

.tab {
  color: var(--blue);
  text-decoration: none;
  padding: 2px 4px;
}
.tab .n { color: var(--mute); margin-left: 8px; font-size: 12px; }
.tab:hover, .tab:hover .n { background: var(--blue); color: #fff; }
.tabs-on .tab.is-on { color: var(--red); box-shadow: inset 0 -1px 0 var(--red); }
.tabs-on .tab.is-on:hover, .tabs-on .tab.is-on:hover .n { background: var(--red); color: #fff; }

.shots[hidden] { display: none; }
.shots + .shots { margin-top: 80px; }
.tabs-on .shots + .shots { margin-top: 0; }   /* one part at a time, no gap above it */

.sec-name {
  font-size: 13px;
  font-weight: normal;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--ink);
  margin: 0 0 20px;
  padding-top: 14px;
  border-top: 1px solid var(--hair);
}
.shots:first-of-type .sec-name { padding-top: 0; border-top: none; }
.tabs-on .sec-name { display: none; }

/* ---------- Favourites ---------- */

.shot-wrap { position: relative; }
.shot-wrap.is-liked .shot img { outline-color: var(--red); }

.like { line-height: 0; }
.like-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-top: 8px;
  padding: 2px 6px 2px 0;
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: 0.02em;
  line-height: 1.4;
  color: var(--mute);
  background: none;
  border: none;
  cursor: pointer;
}
.like-btn .h {
  width: 13px;
  height: 13px;
  flex: none;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
}
.like-btn:hover { color: var(--blue); }
.like-btn.is-liked { color: var(--red); }
.like-btn.is-liked .h { fill: currentColor; }

.favs { color: var(--mute); margin-top: 20px; }
.favs a { color: var(--blue); }

/* The box that asks once for the address */
.ask-mail {
  position: fixed;
  inset: 0;
  z-index: 20;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
  background: rgba(255, 255, 255, 0.93);
}
.ask-mail[hidden] { display: none; }
.ask-mail form {
  width: 340px;
  max-width: 100%;
  padding: 24px;
  background: var(--paper);
  border: 1px solid var(--hair);
}
.ask-mail label { display: block; color: var(--mute); margin-bottom: 8px; }
.ask-mail .hint { color: var(--mute); margin-top: 20px; line-height: 1.7; }
.ask-mail .error { color: var(--red); margin-top: 14px; }

.plain {
  font-family: var(--mono);
  font-size: 13px;
  background: none;
  border: none;
  color: var(--blue);
  text-decoration: underline;
  cursor: pointer;
  padding: 4px 6px;
  margin-left: 8px;
}
.plain:hover { background: var(--blue); color: #fff; text-decoration: none; }

/* ---------- Head of a gallery ---------- */

.head { margin-bottom: 56px; }
.head .facts { color: var(--mute); font-size: 13px; letter-spacing: 0.02em; }
.head .note { margin-top: 20px; max-width: 64ch; }
.head .note p { font-size: 17px; line-height: 1.65; margin-bottom: 0.8em; }

.download {
  display: flex;
  align-items: center;
  gap: 16px;
  flex-wrap: wrap;
  margin-top: 28px;
}
.download .meta { color: var(--mute); }

.button {
  display: inline-block;
  font-family: var(--mono);
  font-size: 14px;
  letter-spacing: 0.02em;
  color: var(--blue);
  background: none;
  border: 1px solid var(--blue);
  padding: 10px 18px;
  text-decoration: none;
  cursor: pointer;
}
.button:hover { background: var(--blue); color: #fff; }
.button[disabled] { color: var(--mute); border-color: var(--hair); cursor: default; }
.button[disabled]:hover { background: none; color: var(--mute); }

/* ---------- Password gate ---------- */

.gate {
  display: flex;
  gap: 56px;
  align-items: flex-start;
  flex-wrap: wrap;
}
.gate-cover { width: 420px; max-width: 100%; }
.gate-form { max-width: 320px; flex: 1 1 260px; }
.gate-form label { display: block; color: var(--mute); margin-bottom: 8px; }
.gate-form input[type="password"],
.gate-form input[type="email"],
.ask-mail input[type="email"] {
  display: block;
  width: 100%;
  font-family: var(--mono);
  font-size: 16px;
  color: var(--ink);
  background: none;
  border: 1px solid var(--hair);
  padding: 10px 12px;
  margin-bottom: 16px;
}
.gate-form input:focus, .ask-mail input:focus { border-color: var(--blue); }
.gate-form .error { color: var(--red); margin-top: 16px; }
.gate-form .hint { color: var(--mute); margin-top: 24px; line-height: 1.7; }

/* ---------- Dashboard ---------- */

.dash-section { margin-bottom: 64px; max-width: 900px; }
.dash-section[hidden] { display: none; }

.dash-section h2 {
  font-size: 13px;
  font-weight: bold;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--ink);
  border-top: 1px solid var(--hair);
  padding-top: 12px;
  margin-bottom: 22px;
}
.dash-section h2.second { margin-top: 48px; }

/* With the tabs switched on, each one already names the section above it. */
.tabs-on .dash-section > h2:first-child {
  border-top: none;
  padding-top: 0;
}

.field { margin-bottom: 18px; max-width: 560px; }
.field > label {
  display: block;
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: 0.02em;
  color: var(--mute);
  margin-bottom: 5px;
}
.field input[type="text"],
.field input[type="password"],
.field input[type="number"],
.field input[type="search"],
.field select,
.field textarea {
  display: block;
  width: 100%;
  font-family: var(--mono);
  font-size: 14px;
  color: var(--ink);
  background: none;
  border: 1px solid var(--hair);
  padding: 8px 10px;
}
.field input:focus, .field select:focus, .field textarea:focus { border-color: var(--blue); }
.field textarea { resize: vertical; }
.field .hint { margin-top: 5px; color: var(--mute); line-height: 1.6; }

.field .switch { display: flex; align-items: center; gap: 8px; }
.field .switch input { width: 15px; height: 15px; accent-color: var(--blue); }
.field .switch-word {
  font-family: var(--mono);
  font-size: 13px;
  color: var(--ink);
  cursor: pointer;
}

.cron {
  max-width: 620px;
  margin: 32px 0 8px;
  padding-top: 20px;
  border-top: 1px solid var(--hair);
}
.cron h3 {
  font-size: 12px;
  font-weight: bold;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  margin-bottom: 12px;
}
.cron .hint { margin: 12px 0; }
.cron .codeblock { margin: 10px 0 14px; }
.cron .codeblock pre { font-size: 11px; }

.dash-save { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; margin-top: 26px; }
.dash-save .hint { color: var(--mute); }
.dash-tools { display: flex; gap: 12px; flex-wrap: wrap; margin-bottom: 16px; }

/* Tools: one row per button, the button on the left and what it does on the
   right. The buttons share a column width so they read as a list of things
   to press rather than a paragraph with a button in it. */
.tool-list { margin-bottom: 22px; }
.tool {
  display: grid;
  /* wide enough that the longest label — "Look for new galleries" at 14px
     plus the button's 18px of side padding — stays on one line, so every
     button in the column is the same height */
  grid-template-columns: 255px 1fr;
  gap: 6px 24px;
  align-items: start;
  padding: 16px 0;
  border-top: 1px solid var(--hair);
}
.tool:last-child { border-bottom: 1px solid var(--hair); }
.tool form { margin: 0; }
.tool .button { width: 100%; text-align: center; }
.tool .what {
  margin: 0;
  color: var(--mute);
  line-height: 1.7;
  max-width: 62ch;
}
@media (max-width: 640px) {
  .tool { grid-template-columns: 1fr; gap: 10px; }
  .tool .button { width: auto; }
}

/* the cache figures on the Tools tab */
.cache-facts { border-collapse: collapse; margin-bottom: 18px; }
.cache-facts th,
.cache-facts td { text-align: left; padding: 6px 22px 6px 0; vertical-align: baseline; }
.cache-facts th { font-weight: normal; color: var(--mute); white-space: nowrap; }
.cache-facts td.note { color: var(--mute); }
.dash-section .hint { color: var(--mute); line-height: 1.7; max-width: 620px; }


.flash {
  border: 1px solid var(--blue);
  color: var(--blue);
  padding: 10px 14px;
  margin-bottom: 28px;
  max-width: 900px;
  line-height: 1.6;
}
.flash.is-bad  { border-color: var(--red); color: var(--red); }
.flash.is-warn { border-color: var(--hair); color: var(--mute); }

.result {
  font-family: var(--mono);
  font-size: 13px;
  white-space: pre-wrap;
  border: 1px solid var(--hair);
  padding: 12px 14px;
  margin-bottom: 28px;
  max-width: 900px;
  line-height: 1.6;
}

.dash-intro { max-width: 560px; }
.dash-intro code, .field code, .hint code {
  font-family: var(--mono);
  background: #f4f4f4;
  padding: 1px 4px;
}

/* the list of what clients marked */
.fav-filter { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin-bottom: 18px; }
.fav-filter label { color: var(--mute); }
.fav-filter input {
  font-family: var(--mono);
  font-size: 14px;
  color: var(--ink);
  background: none;
  border: 1px solid var(--hair);
  padding: 8px 10px;
  min-width: 280px;
  flex: 0 1 340px;
}
.fav-filter input:focus { border-color: var(--blue); }

.fav { margin-bottom: 28px; }
.fav[hidden] { display: none; }
.fav-head {
  display: flex;
  align-items: baseline;
  gap: 14px;
  flex-wrap: wrap;
  margin-bottom: 8px;
}
.fav-head strong { font-weight: bold; }
.fav-head .fav-meta { color: var(--mute); }

/* A list of marked pictures, shown the way code is shown */
.codeblock {
  position: relative;
  border: 1px solid var(--hair);
  background: #fafafa;
}
.codeblock pre {
  margin: 0;
  padding: 12px 84px 12px 14px;      /* room for the button on the right */
  overflow-x: auto;
  font-family: var(--mono);
  font-size: 12px;
  line-height: 1.7;
  color: var(--ink);
  white-space: pre-wrap;
  word-break: break-word;
}
.codeblock code { font-family: inherit; }

.codeblock .copy {
  position: absolute;
  top: 6px;
  right: 6px;
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.02em;
  color: var(--blue);
  background: var(--paper);
  border: 1px solid var(--hair);
  padding: 3px 8px;
  cursor: pointer;
}
.codeblock .copy:hover { background: var(--blue); color: #fff; border-color: var(--blue); }
.codeblock .copy.is-done { color: var(--red); border-color: var(--red); }
.codeblock .copy.is-done:hover { background: var(--red); color: #fff; }

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

.section {
  margin-top: 140px;
  border-top: 1px solid var(--hair);
  padding-top: 16px;
}
.footer-line { color: var(--mute); }

/* The version stamp, dashboard only. Floated rather than made a flex item:
   the footer is an inline run of links and "·" separators, and turning it
   into a flex row would make every one of those a box of its own. On a
   narrow screen it drops onto its own line instead. */
.footer-line .version { float: right; opacity: 0.75; }
@media (max-width: 620px) {
  .footer-line .version { float: none; display: block; margin-top: 8px; }
}

/* ---------- Lightbox ---------- */

.lightbox {
  position: fixed;
  inset: 0;
  background: var(--paper);
  z-index: 10;
  display: none;
  flex-direction: column;
  padding: 20px;
}
.lightbox.open { display: flex; }

/* Centred, not baseline-aligned: the mark button is a flex box of its own,
   so its "baseline" would be taken from the heart and sit too high. */
.lightbox .bar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 16px;
  flex-wrap: wrap;
}
.lightbox .nav-btns { display: flex; gap: 12px; align-items: center; flex-wrap: wrap; }
.lightbox button, .lightbox .nav-btns a {
  font-family: var(--mono);
  font-size: 13px;
  /* Set on purpose, and it has to stay. A <button> does not inherit
     line-height from the page — the browser's own stylesheet gives it
     "normal" — so its height came from whatever font each glyph in it landed
     in. "prev" and "next" carry ← and →, and Cutive Mono has no arrows at
     all (the woff2 files hold 220 glyphs and not one of them is an arrow),
     so those two characters fall back to a system face. Where that face is
     Courier New, as on Windows, its metrics happen to match and nothing
     shows; on Android it is Roboto, which is taller, and only the two
     buttons holding an arrow grew — measured 26px against 23px. Centred
     boxes of unequal height put their text on different baselines, which is
     why "close (Esc)" sat above "next →" once the row wrapped. A number
     here makes the line box the same height whatever font a stray glyph
     pulls in. */
  line-height: 1.5;
  background: none;
  border: none;
  color: var(--blue);
  text-decoration: underline;
  cursor: pointer;
  padding: 4px 6px;
}
.lightbox button:hover, .lightbox .nav-btns a:hover {
  background: var(--blue);
  color: #fff;
  text-decoration: none;
}

.lightbox .lb-like {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  line-height: 1.5;          /* the same box height as the plain buttons */
  text-decoration: none;
}
.lightbox .lb-like .h {
  width: 13px;
  height: 13px;
  flex: none;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
}
.lightbox .lb-like.is-liked { color: var(--red); }
.lightbox .lb-like.is-liked .h { fill: currentColor; }
.lightbox .lb-like.is-liked:hover { background: var(--red); color: #fff; }

.lightbox .stage {
  flex: 1;
  min-height: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px 0;
}
.lightbox .stage img {
  max-width: 100%;
  max-height: 100%;
  width: auto;
  height: auto;
  display: block;
  cursor: e-resize;              /* the right half goes on … */
}
.lightbox .stage img.to-prev { cursor: w-resize; }   /* … the left half goes back */

.lightbox .caption {
  color: var(--mute);
  text-align: center;
  min-height: 1.5em;
}
