/*
 * Reusable components. Class names are part of the style agreements in
 * CLAUDE.md; reuse them in new pages (e.g. the gallery in phase 5).
 */

/* --- Buttons --- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  min-height: var(--tap);
  padding: 0 var(--space-5);
  border: 1px solid var(--color-accent);
  border-radius: var(--radius);
  background: var(--color-accent);
  color: var(--color-accent-contrast);
  font-family: var(--font-body);
  font-weight: 600;
  line-height: 1;
  text-decoration: none;
  cursor: pointer;
  transition: background-color var(--transition), color var(--transition);
}
.btn:hover {
  background: var(--color-accent-hover);
  border-color: var(--color-accent-hover);
  color: var(--color-accent-contrast);
  text-decoration: none;
}
.btn--secondary { background: transparent; color: var(--color-accent); }
.btn--secondary:hover { background: var(--color-surface); color: var(--color-accent-hover); }
/* For something that can't be undone; the label always says what happens */
.btn--danger { border-color: var(--color-error); background: var(--color-error); }
.btn--danger:hover { border-color: var(--color-ink); background: var(--color-ink); }
/* A button that can't be used right now (e.g. "Vorige" at the first photo).
   Muted and dashed, so it is not shown by colour alone. */
.btn[aria-disabled="true"],
.btn:disabled {
  border-style: dashed;
  border-color: var(--color-field-border);
  background: transparent;
  color: var(--color-ink-muted);
  cursor: default;
}
/* Looks like a link, behaves like a button (e.g. log out, which must POST) */
.btn--link {
  padding: 0;
  border: 0;
  background: none;
  color: var(--color-accent);
  font-weight: 400;
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.18em;
}
.btn--link:hover { background: none; color: var(--color-accent-hover); text-decoration-thickness: 2px; }
.button-row { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3) var(--space-4); }

/* --- Card: a sheet lying on the paper --- */
.card {
  display: grid;
  gap: var(--space-4);
  align-content: start;
  padding: var(--space-5);
  background: var(--color-surface);
  border: 1px solid var(--color-rule);
  border-radius: var(--radius);
  box-shadow: var(--shadow-sheet);
}

/* --- Breadcrumb --- */
.breadcrumb {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0 var(--space-2);
  font-size: var(--text-sm);
  font-variant: small-caps;
  letter-spacing: 0.06em;
  color: var(--color-ink-muted);
}
.breadcrumb a {
  min-height: 36px;
  display: inline-flex;
  align-items: center;
  color: var(--color-ink-muted);
  text-decoration: none;
}
.breadcrumb a:hover { color: var(--color-accent); text-decoration: underline; }
.breadcrumb__sep { color: var(--color-ornament); }
.breadcrumb [aria-current] { color: var(--color-ink); }

/* --- Back link, right under the breadcrumb --- */
.breadcrumb + .back-link { margin-top: calc(var(--space-4) * -1); }
.back-link a {
  min-height: var(--tap);
  display: inline-flex;
  align-items: center;
  font-weight: 600;
}

/* --- Alerts (messages) --- */
.alert {
  padding: var(--space-3) var(--space-4);
  border-left: 4px solid;
  border-radius: var(--radius);
}
.alert--error { background: var(--color-error-bg); color: var(--color-error); border-color: var(--color-error); }
.alert--success { background: var(--color-success-bg); color: var(--color-success); border-color: var(--color-success); }
.alert ul { margin: 0; padding-left: var(--space-5); }

/* --- Forms --- */
.form { display: grid; gap: var(--space-4); }
.form-field { display: grid; gap: var(--space-1); }
/* Two fields side by side when there is room (e.g. first and last name) */
.form-row { display: grid; gap: var(--space-4); }
@media (min-width: 40rem) {
  .form-row { grid-template-columns: 1fr 1fr; }
}
.form-row > .form-field { min-width: 0; }
.form-field label { font-weight: 600; }
.form-field__label { font-weight: 600; }
/* A checkbox goes before its label (e.g. confirming a deletion) */
.form-field:has(> input[type="checkbox"]) { grid-template-columns: auto 1fr; align-items: start; gap: var(--space-1) var(--space-3); }
.form-field > input[type="checkbox"] { order: -1; width: 1.25rem; height: 1.25rem; margin: 0.15rem 0 0; accent-color: var(--color-accent); }
.form-field:has(> input[type="checkbox"]) > :not(input, label) { grid-column: 1 / -1; }
.form-field__value { margin: 0; overflow-wrap: anywhere; }
.form-field input:not([type="checkbox"]):not([type="radio"]):not([type="file"]),
.form-field select,
.form-field textarea {
  width: 100%;
  min-height: var(--tap);
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--color-field-border);
  border-radius: var(--radius);
  background: var(--color-surface);
  color: var(--color-ink);
}
.form-field textarea { min-height: 7rem; }
.form-field input:focus-visible,
.form-field select:focus-visible,
.form-field textarea:focus-visible { outline-offset: 1px; box-shadow: none; }
.form-field__help { font-size: var(--text-sm); color: var(--color-ink-muted); }
.form-field__help ul { margin: var(--space-1) 0 0; padding-left: var(--space-5); }
.form-field__error { font-size: var(--text-sm); font-weight: 600; color: var(--color-error); }
.form-field.has-error input,
.form-field.has-error select,
.form-field.has-error textarea { border: 2px solid var(--color-error); }

/* --- Info button and dialog (category description, see info-dialog.js) --- */
.info-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
  width: var(--tap);
  height: var(--tap);
  margin-block: calc(var(--space-3) * -1);
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: none;
  color: var(--color-accent);
  font-family: var(--font-display);
  font-style: italic;
  font-size: var(--text-lg);
  cursor: pointer;
}
.info-toggle[hidden] { display: none; }
.info-toggle__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.6rem;
  height: 1.6rem;
  border: 1px solid currentColor;
  border-radius: 50%;
  background: var(--color-surface);
  line-height: 1;
  transition: background-color var(--transition), color var(--transition);
}
.info-toggle:hover .info-toggle__icon,
.info-toggle[aria-expanded="true"] .info-toggle__icon { background: var(--color-accent); color: var(--color-accent-contrast); }

/* A small popup right next to the info button (positioned by info-dialog.js).
   Non-modal: no backdrop, the page stays as it is. */
.info-popup {
  position: fixed;
  inset: auto;
  margin: 0;
  z-index: 20;
  width: max-content;
  max-width: min(20rem, calc(100vw - 2 * var(--space-4)));
  max-height: min(60vh, 24rem);
  overflow: auto;
  padding: 0;
  border: 1px solid var(--color-rule);
  border-radius: var(--radius);
  background: var(--color-surface);
  color: var(--color-ink);
  box-shadow: var(--shadow-lifted);
  text-align: left;
}
.info-popup[open] { animation: info-popup-in 0.12s ease-out; }
.info-popup__body {
  position: relative;
  display: grid;
  gap: var(--space-1);
  padding: var(--space-3) var(--space-4);
  padding-right: calc(var(--tap) + var(--space-1));
}
.info-popup__title { font-size: var(--text-lg); font-style: normal; overflow-wrap: anywhere; }
.info-popup__text {
  font-family: var(--font-body);
  font-style: normal;
  font-size: var(--text-sm);
  line-height: 1.5;
  overflow-wrap: anywhere;
}
.info-popup__close {
  position: absolute;
  top: 0;
  right: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--tap);
  height: var(--tap);
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: none;
  color: var(--color-ink-muted);
  font-size: 1.5rem;
  line-height: 1;
  cursor: pointer;
  transition: color var(--transition);
}
.info-popup__close:hover { color: var(--color-accent); }
@keyframes info-popup-in {
  from { opacity: 0; }
}

/* --- Page heading with optional info button --- */
.page-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--space-2) var(--space-3); }

/* --- Sort button with drop-down menu (see sort-menu.js) --- */
.sort-menu { position: relative; margin-left: auto; align-self: center; }
.sort-menu__toggle {
  list-style: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--tap);
  height: var(--tap);
  border-radius: 50%;
  color: var(--color-accent);
  cursor: pointer;
}
.sort-menu__toggle::-webkit-details-marker { display: none; }
.sort-menu__icon {
  width: 2rem;
  height: 2rem;
  padding: 0.3rem;
  border: 1px solid currentColor;
  border-radius: 50%;
  background: var(--color-surface);
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
  transition: background-color var(--transition), color var(--transition);
}
.sort-menu__toggle:hover .sort-menu__icon,
.sort-menu[open] .sort-menu__icon { background: var(--color-accent); color: var(--color-accent-contrast); }
.sort-menu__list {
  position: absolute;
  top: calc(100% + var(--space-1));
  right: 0;
  z-index: 20;
  display: grid;
  min-width: 12rem;
  padding: var(--space-2);
  border: 1px solid var(--color-rule);
  border-radius: var(--radius);
  background: var(--color-surface);
  box-shadow: var(--shadow-lifted);
}
.sort-menu__title {
  padding: var(--space-1) var(--space-3);
  font-size: var(--text-sm);
  font-variant: small-caps;
  letter-spacing: 0.08em;
  color: var(--color-ink-muted);
}
.sort-menu__option {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  min-height: var(--tap);
  padding: 0 var(--space-3);
  border: 0;
  border-radius: var(--radius);
  background: none;
  text-align: left;
  cursor: pointer;
}
/* A check mark for the active choice, so it's not shown by colour alone */
.sort-menu__option::before { content: ""; width: 1em; }
.sort-menu__option[aria-pressed="true"] { font-weight: 600; color: var(--color-accent); }
.sort-menu__option[aria-pressed="true"]::before { content: "✓"; }
.sort-menu__option:hover { background: var(--color-paper); color: var(--color-accent); }

/* A page of running text, such as the privacy statement */
.prose { width: 100%; max-width: 46rem; justify-self: center; }
.prose ul { padding-left: var(--space-5); }
.prose li + li { margin-top: var(--space-2); }

.profile-delete { margin-top: var(--space-4); font-size: var(--text-sm); }

/* --- Profile menu at the top right (see profile-menu.js) --- */
.profile-menu { position: relative; align-self: center; }
.profile-menu__toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--tap);
  height: var(--tap);
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: none;
  color: var(--color-accent);
  cursor: pointer;
}
.profile-menu__toggle[hidden] { display: none; }
.profile-menu__icon {
  width: 2.25rem;
  height: 2.25rem;
  padding: 0.35rem;
  border: 1px solid currentColor;
  border-radius: 50%;
  background: var(--color-surface);
  fill: none;
  stroke: currentColor;
  stroke-width: 1.75;
  stroke-linecap: round;
  stroke-linejoin: round;
  transition: background-color var(--transition), color var(--transition);
}
.profile-menu__toggle:hover .profile-menu__icon,
.profile-menu__toggle[aria-expanded="true"] .profile-menu__icon {
  background: var(--color-accent);
  color: var(--color-accent-contrast);
}
.profile-menu__panel {
  position: absolute;
  top: calc(100% + var(--space-1));
  right: 0;
  z-index: 30;
  width: max-content;
  min-width: 13rem;
  /* Always within the screen, also on a narrow phone */
  max-width: calc(100vw - 2 * var(--space-4));
  padding: var(--space-2);
  border: 1px solid var(--color-rule);
  border-radius: var(--radius);
  background: var(--color-surface);
  box-shadow: var(--shadow-lifted);
}
.profile-menu__who {
  margin: 0;
  padding: var(--space-1) var(--space-3) var(--space-2);
  border-bottom: 1px solid var(--color-rule);
  font-size: var(--text-sm);
  color: var(--color-ink-muted);
  overflow-wrap: anywhere;
}
.profile-menu__who strong { color: var(--color-ink); }

/* The account options: a list in the profile menu and on the profile page */
.account-links { display: grid; margin: 0; padding: var(--space-1) 0 0; list-style: none; }
.account-links form { margin: 0; }
.account-links__item {
  display: flex;
  align-items: center;
  width: 100%;
  min-height: var(--tap);
  padding: 0 var(--space-3);
  border: 0;
  border-radius: var(--radius);
  background: none;
  color: var(--color-ink);
  font: inherit;
  text-align: left;
  text-decoration: none;
  cursor: pointer;
}
.account-links__item:hover { background: var(--color-paper); color: var(--color-accent); text-decoration: none; }

/* --- Photo grid: albums (subcategories) first, then photos --- */
.photo-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-4) var(--space-3);
  list-style: none;
  padding: 0;
}
.photo-grid > li { max-width: none; }

/* A photo keeps its own shape inside a square cell, with a thin white edge */
.photo-frame {
  display: grid;
  gap: var(--space-2);
  align-content: start;
  color: var(--color-ink);
  text-decoration: none;
}
.photo-frame__mat { aspect-ratio: 1; display: flex; align-items: center; justify-content: center; }
.photo-frame__mat img {
  max-width: 100%;
  max-height: 100%;
  width: auto;
  height: auto;
  padding: var(--photo-edge);
  background: var(--color-surface);
  box-shadow: var(--shadow-photo);
  transition: transform var(--transition), box-shadow var(--transition);
}
.photo-frame:hover { color: var(--color-accent); }
.photo-frame:hover .photo-frame__mat img { transform: translateY(var(--lift)); box-shadow: var(--shadow-lifted); }
.photo-frame__caption {
  font-family: var(--font-display);
  font-style: italic;
  line-height: 1.3;
  text-align: center;
  overflow-wrap: anywhere;
}

/* An album (category) in the grid: an album cover, clearly not a photo.
   The tile holds the link and, next to it, an optional info button. */
.album-tile { position: relative; }
.album-tile__link { display: grid; color: var(--color-ink); text-decoration: none; }
.album-tile__cover {
  position: relative;
  aspect-ratio: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-1);
  padding: var(--space-6) var(--space-4);
  text-align: center;
  background: var(--color-album);
  border-left: 12px solid var(--color-album-spine);
  border-radius: 2px var(--radius) var(--radius) 2px;
  box-shadow: var(--shadow-photo);
  transition: transform var(--transition), box-shadow var(--transition);
}
/* Stitched edge, like a cloth album cover */
.album-tile__cover::after {
  content: "";
  position: absolute;
  inset: 8px;
  border: 1px dashed var(--color-ornament);
  border-radius: 2px;
  pointer-events: none;
}
.album-tile__name {
  font-family: var(--font-display);
  font-size: var(--text-lg);
  line-height: 1.2;
  overflow-wrap: anywhere;
  text-wrap: balance;
}
.album-tile__label {
  font-size: var(--text-sm);
  font-variant: small-caps;
  letter-spacing: 0.08em;
  color: var(--color-ink-muted);
}
.album-tile .info-toggle {
  position: absolute;
  top: var(--space-1);
  right: var(--space-1);
  margin: 0;
}
/* On hover the cover, the info button and an open info popup lift together.
   Each gets its own transform: a transform on .album-tile itself would break
   the fixed position of the popup. The popup is inside .album-tile, so the
   tile stays "hovered" while the pointer is on the popup. */
.album-tile .info-toggle,
.album-tile .info-popup { transition: transform var(--transition); }
.album-tile:hover .album-tile__cover,
.album-tile:hover .info-toggle,
.album-tile:hover .info-popup { transform: translateY(var(--lift)); }
.album-tile:hover .album-tile__cover { box-shadow: var(--shadow-lifted); }
.album-tile__link:hover .album-tile__name { color: var(--color-accent); }

/* The overview only holds albums, so its tiles are a bit larger */
.photo-grid--albums .album-tile__name { font-size: var(--text-xl); }

/* --- Pagination --- */
.pagination {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: var(--space-3);
  font-size: var(--text-sm);
  color: var(--color-ink-muted);
}

/* --- Single photo page --- */
.photo-view { display: grid; gap: var(--space-4); justify-items: center; }
.photo-view__image {
  max-height: 80vh;
  width: auto;
  padding: 4px;
  background: var(--color-surface);
  box-shadow: var(--shadow-photo);
}
.photo-text { width: 100%; max-width: var(--text-width); display: grid; gap: var(--space-2); }
/* Star for favorites: an outline when off, filled when on (shape, not only colour) */
.star-icon {
  width: 1.25rem;
  height: 1.25rem;
  flex: none;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.75;
  stroke-linejoin: round;
}
.star-icon--filled { fill: currentColor; }
.favorite-form { margin: 0; }
.favorite-toggle { display: inline-flex; align-items: center; gap: var(--space-2); }
.photo-text__date { font-size: var(--text-sm); color: var(--color-ink-muted); }

/* --- Empty state and plain messages --- */
.empty-state {
  padding: var(--space-6) var(--space-4);
  text-align: center;
  font-family: var(--font-display);
  font-style: italic;
  font-size: var(--text-lg);
  color: var(--color-ink-muted);
  border: 1px dashed var(--color-rule);
  border-radius: var(--radius);
}
.empty-state p { margin-inline: auto; }

/* --- Larger screens --- */
@media (min-width: 40rem) {
  .photo-grid { grid-template-columns: repeat(auto-fill, minmax(10rem, 1fr)); gap: var(--space-5) var(--space-4); }
  .photo-grid--albums { grid-template-columns: repeat(auto-fill, minmax(12rem, 1fr)); }
}
@media (min-width: 64rem) {
  .photo-grid { grid-template-columns: repeat(auto-fill, minmax(11rem, 1fr)); }
  .photo-grid--albums { grid-template-columns: repeat(auto-fill, minmax(14rem, 1fr)); }
}
