/* OKE design system
 * =================
 * One authoritative typography and spacing layer for the public marketplace.
 *
 * The page had accumulated ten inline <style> blocks, each patching the last
 * (.preview-hero was declared at 850px, then 680px, then 760px). This file is
 * loaded last and owns type, scale and rhythm so that those decisions live in
 * one readable place instead of being reconstructed by reading the overrides
 * in order.
 *
 * Two rules the previous styling broke, and the reason each matters here:
 *
 * 1. Nothing below 12px. The page had twenty rules at 8-10px. Customers read
 *    this on a phone, outdoors, in Tanzanian daylight; sub-11px text is not
 *    small, it is unreadable.
 * 2. No webfont. A downloaded family costs ~100KB before first paint, which is
 *    real money and real waiting on mobile data. The system stack renders a
 *    modern grotesque on every device the audience actually owns.
 */

:root {
  --oke-font: -apple-system, BlinkMacSystemFont, "Segoe UI", Inter, Roboto,
    "Helvetica Neue", "Noto Sans", Arial, sans-serif;

  --oke-ink: #0F1B2D;
  --oke-gold: #F0B323;
  --oke-muted: #5A6472;
  --oke-line: #E3E1DB;
  --oke-paper: #F7F7F5;

  /* Type scale. Steps are far enough apart to read as deliberate hierarchy
     rather than accidental variation. */
  --t-micro: 12px;
  --t-small: 13px;
  --t-body: 15px;
  --t-lead: 17px;
  --t-h3: 21px;
  --t-h2: 30px;
  --t-h1: 46px;

  --space-section: 88px;
}

/* ----------------------------------------------------------- foundations -- */

body {
  /* Never reset anywhere, so the browser default put an 8px band of page
     background around the entire site — visible as a white strip down the right
     edge and under the hero. */
  margin: 0;
  font-family: var(--oke-font);
  font-size: var(--t-body);
  line-height: 1.55;
  color: var(--oke-ink);
  background: var(--oke-paper);
}

h1, h2, h3, .preview-copy h1, .preview-section h2, .preview-modal h2 {
  font-family: var(--oke-font);
  font-weight: 800;
  /* Georgia at -4px tracking read as broken rather than editorial. A grotesque
     at -1.5px is tight enough to feel designed and still legible. */
  letter-spacing: -1.4px;
  line-height: 1.06;
}

/* ------------------------------------------------------------------ hero -- */

/* The hero has one job above the fold: headline plus a working search box. It
   was a fixed 703px tall regardless of the window, so on a scaled 1080p laptop
   (~600px of CSS viewport) the Search button sat below the fold and the page
   opened on a photograph with no visible way to use it.
   svh, not vh: on mobile browsers vh measures the viewport with the address bar
   retracted, which reserves height the visitor cannot see on first paint. */
.preview-hero {
  min-height: 640px;
  min-height: 100svh;
  display: flex;
  flex-direction: column;
}

.preview-copy {
  flex: 1;
  display: flex;
  flex-direction: column;
  justify-content: center;
}


/* The hero frames are pre-cut to the hero's own aspect with the subject already
   placed, so no per-image nudging is needed here. */
.hero-slide { background-position: center center; }

@media (max-width: 700px) {
  /* A narrow viewport crops these landscape frames horizontally, so bias toward
     the right side where every subject stands. */
  .hero-slide { background-position: 68% center; }
}

.preview-nav { height: 88px; }

/* The mobile menu was unusable, and not because of how it looked.
 *
 * .preview-nav was declared z-index 8, then a later rule reset
 * `.preview-nav, .preview-copy` to z-index 3 together. Equal z-index falls back
 * to DOM order, and .preview-copy comes second — so the hero headline painted
 * over the open dropdown. document.elementFromPoint on the "Sign in" button
 * returned the <em> in "moments.", not the button: the headline was swallowing
 * every tap. The panel is genuinely white with dark text; it only looked
 * washed out because the headline was drawn on top of it.
 *
 * The nav and its dropdown now sit above the hero content, and above the
 * search panel (z-index 6) that overlaps the same area.
 */
.preview-nav { position: relative; z-index: 30; }
/* width:100% plus 10px padding and a 1px border under the default content-box
   sizing put the panel's right edge 22px off-screen, clipping the right-hand
   column of menu items. */
.preview-links { z-index: 31; box-sizing: border-box; }
/* Role destinations belong to the phone sheet only. On desktop the bar stays at
   four items and the footer carries them instead. */
.preview-links .nav-secondary { display: none; }

.preview-nav button,
.preview-links button {
  font-family: var(--oke-font);
  font-size: var(--t-small);
  font-weight: 600;
  letter-spacing: 0;
}

.preview-copy { padding: 56px 0 60px; }

.preview-copy .eyebrow {
  font-size: var(--t-micro);
  font-weight: 700;
  letter-spacing: 1.6px;
  text-transform: uppercase;
  opacity: .92;
}

.preview-copy h1 {
  font-size: var(--t-h1);
  font-weight: 800;
  margin: 18px 0 16px;
}

.preview-copy h1 em {
  font-style: normal;
  color: var(--oke-gold);
  font-weight: 800;
}

.preview-copy p {
  font-size: var(--t-lead);
  line-height: 1.5;
  max-width: 620px;
  color: rgba(255, 255, 255, .88);
}

/* ---------------------------------------------------------- search panel -- */

/* Search bar
 * ----------
 * One pill, three cells: which event, what you are looking for, go. The card it
 * replaces wrapped two inputs in a heading, a hint, two uppercase field labels
 * and two example strings — roughly forty-five words of chrome around a form
 * that does one thing. Both fields were also labelled "(optional)", which told
 * a visitor that nothing was required without telling them what to type.
 *
 * The placeholders now carry the instruction, so the teaching sits inside the
 * control instead of stacked above it.
 */

/* The bar is its own white surface; the old card around it was a second one. */
.preview-search {
  background: transparent;
  box-shadow: none;
  padding: 0;
  border-radius: 0;
}

.search-bar {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.35fr) auto;
  gap: 4px;
  padding: 6px;
  background: #fff;
  border-radius: 16px;
  box-shadow: 0 26px 64px rgba(15, 27, 45, .34);
}

.search-field {
  position: relative;
  display: flex;
  align-items: center;
  min-height: 60px;
  padding: 0 16px;
  border-radius: 12px;
  transition: background .15s ease;
}

/* A hairline instead of a border, so the cells read as one control rather than
   two boxes pushed together. */
.search-field + .search-field:before {
  content: "";
  position: absolute;
  left: 0;
  top: 12px;
  bottom: 12px;
  width: 1px;
  background: var(--oke-line);
}

.search-field:focus-within { background: #FAF9F6; }
.search-field:focus-within:before,
.search-field:focus-within + .search-field:before { opacity: 0; }

.search-field input {
  width: 100%;
  border: 0;
  outline: 0;
  background: transparent;
  /* 16px is the floor at which iOS Safari stops zooming the page on focus. */
  font: 600 16px/1.3 var(--oke-font);
  color: var(--oke-ink);
}

.search-field input::placeholder {
  color: #99A0AA;
  font-weight: 500;
}

/* The event cell is a picker, so it says so. */
.search-field-event input { padding-right: 34px; }
.search-field-event:after {
  content: "";
  position: absolute;
  right: 18px;
  top: 50%;
  width: 8px;
  height: 8px;
  margin-top: -6px;
  border-right: 2px solid #99A0AA;
  border-bottom: 2px solid #99A0AA;
  transform: rotate(45deg);
  pointer-events: none;
}

.event-clear-button {
  position: absolute;
  right: 12px;
  top: 50%;
  transform: translateY(-50%);
  width: 26px;
  height: 26px;
  display: grid;
  place-items: center;
  border: 0;
  border-radius: 50%;
  background: #EFEDE7;
  color: var(--oke-ink);
  font-size: 16px;
  line-height: 1;
  cursor: pointer;
  z-index: 2;
}
.event-clear-button:hover { background: var(--oke-gold); }
/* Hidden rather than dimmed when there is nothing to clear — the caret behind it
   is the more useful affordance at that moment. */
.event-clear-button:disabled { display: none; }
.search-field-event:has(.event-clear-button:not(:disabled)):after { display: none; }

/* ---------------------------------------------------------- event picker -- */

.event-picker {
  position: absolute;
  z-index: 40;
  top: calc(100% + 8px);
  left: -6px;
  width: min(420px, calc(100vw - 32px));
  max-height: 330px;
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: 6px;
  background: #fff;
  border: 1px solid var(--oke-line);
  border-radius: 14px;
  box-shadow: 0 24px 60px rgba(15, 27, 45, .26);
}
.event-picker[hidden] { display: none; }

.event-option {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  grid-template-areas: "name date" "meta date";
  align-items: start;
  gap: 2px 14px;
  width: 100%;
  padding: 11px 12px;
  border: 0;
  border-radius: 10px;
  background: transparent;
  text-align: left;
  cursor: pointer;
}
/* Hover and keyboard highlight share one appearance, so arrowing through the
   list looks the same as pointing at it. */
.event-option:hover,
.event-option.is-active { background: #F6F4EF; }
.event-option.is-selected { background: #FFF7E6; }
.event-option:focus-visible { outline: 2px solid var(--oke-gold); outline-offset: -2px; }

.event-option-name {
  grid-area: name;
  font-size: var(--t-body);
  font-weight: 700;
  color: var(--oke-ink);
  /* Event names here run past fifty characters. Two lines, then ellipsis: the
     name is the one thing somebody is scanning for, and truncating it at one
     line turned several of them into the same "MOROGORO SELOUS MARATHON AND T…". */
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  overflow: hidden;
  line-height: 1.3;
}

.event-option-meta {
  grid-area: meta;
  font-size: var(--t-micro);
  color: var(--oke-muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.event-option-date {
  grid-area: date;
  font-size: var(--t-micro);
  font-weight: 700;
  color: var(--oke-muted);
  white-space: nowrap;
}

.event-option.is-selected .event-option-date { color: var(--gold-text, #8A5D06); }

.event-option-empty {
  margin: 0;
  padding: 18px 12px;
  font-size: var(--t-small);
  color: var(--oke-muted);
  text-align: center;
}

.search-go {
  min-height: 60px;
  padding: 0 34px;
  border: 0;
  border-radius: 12px;
  background: var(--oke-gold);
  color: var(--oke-ink);
  font: 700 16px/1 var(--oke-font);
  cursor: pointer;
  transition: filter .15s ease;
}
.search-go:hover { filter: brightness(1.06); }
.search-go:disabled { opacity: .65; cursor: progress; }
.search-go:focus-visible { outline: 3px solid #fff; outline-offset: 2px; }

/* Meta row sits on the hero, not inside the pill, so the pill stays one clean
   object. */
.search-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px 18px;
  margin-top: 14px;
}

.search-trust {
  font-size: var(--t-small);
  font-weight: 600;
  color: rgba(255, 255, 255, .78);
}
.search-trust:before {
  content: "";
  display: inline-block;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--oke-gold);
  margin-right: 8px;
  vertical-align: middle;
}

/* width:max-content is load-bearing. A closed <details> is a block-level flex
   item, so its flex base size resolves to the full container width (830px here)
   and it wrapped onto a row of its own. Its actual summary is 85px wide. */
.search-meta .filter-toggle { margin-left: auto; width: max-content; color: rgba(255, 255, 255, .78); }
.search-meta .filter-toggle summary { color: rgba(255, 255, 255, .88); }
/* Opened, the filter grid needs the full width, so it drops to its own row. */
.search-meta .filter-toggle[open] {
  flex: 1 1 100%;
  width: auto;
  margin-left: 0;
  margin-top: 4px;
  padding: 14px 16px;
  border-radius: 12px;
  background: #fff;
  color: var(--oke-ink);
}
.search-meta .filter-toggle[open] summary { color: var(--oke-ink); margin-bottom: 10px; }

.preview-filters label {
  padding: 10px 13px;
  border: 1px solid var(--oke-line);
  border-radius: 10px;
  background: #fff;
}

.preview-filters label span {
  font-size: var(--t-micro);
  font-weight: 600;
  letter-spacing: .6px;
  text-transform: uppercase;
  color: var(--oke-muted);
  margin-bottom: 5px;
}

.preview-filters input,
.preview-filters select {
  font-size: var(--t-body);
  font-weight: 600;
}

@media (max-width: 700px) {
  .preview-filters input,
  .preview-filters select { font-size: 16px; }
}

.filter-toggle { font-size: var(--t-small); color: var(--oke-muted); }
.filter-toggle summary { font-weight: 700; font-size: var(--t-small); cursor: pointer; padding: 4px 0; }

/* The advanced filters used to ship expanded. On a phone that is six tall
   fields and a hint line standing between the visitor and the Search button,
   before they have typed anything. They are now behind their own summary, and
   the grid reflows on intrinsic width instead of a fixed five columns — at five
   columns the selects were narrower than their own text and rendered as
   "All catego", "All checkp", "All photograp". */
.preview-filters {
  grid-template-columns: repeat(auto-fit, minmax(158px, 1fr));
  gap: 10px;
}
.preview-filters label { min-width: 0; }
.preview-filters label > span {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.preview-filters input,
.preview-filters select { min-width: 0; max-width: 100%; }

@media (max-width: 700px) {
  .preview-filters { grid-template-columns: 1fr 1fr; gap: 8px; }
  /* A datetime-local control cannot render "dd/mm/yyyy --:--" plus its picker
     icon inside half of a 390px screen, so these take the full row. */
  .preview-filters label:has(input[type="datetime-local"]),
  /* "All photographers" does not fit half a phone screen, and photographer
     names are longer still. */
  .preview-filters label:has(#photographer) { grid-column: 1 / -1; }
}

.selfie-search-trigger {
  min-height: 48px;
  font-size: var(--t-small);
  font-weight: 700;
  border-radius: 10px;
}

/* --------------------------------------------------------------- gallery -- */

.preview-section { margin: var(--space-section) auto; }

.preview-section .eyebrow {
  font-size: var(--t-micro);
  font-weight: 700;
  letter-spacing: 1.6px;
  text-transform: uppercase;
  color: var(--oke-muted);
}

.preview-section h2 {
  font-size: var(--t-h2);
  margin: 10px 0 28px;
  max-width: 20ch;
}

.preview-gallery { gap: 22px; }

/* A tile holding a real photograph must not sit on the stock composite while
   its lazy image loads. A quiet neutral reads as "loading"; the stock runner
   read as the photograph itself and then changed under the viewer. */
.preview-image.has-image {
  background-image: none;
  background-color: #E7E9EC;
}

.preview-photo {
  border: 1px solid var(--oke-line);
  border-radius: 14px;
  background: #fff;
  transition: transform .18s ease, box-shadow .18s ease;
}

/* A marketplace should feel responsive to the pointer; the tile is the primary
   interactive object on the page. */
@media (hover: hover) {
  .preview-photo:hover {
    transform: translateY(-3px);
    box-shadow: 0 18px 44px rgba(15, 27, 45, .14);
  }
}

.preview-photo.selected {
  outline: 3px solid var(--oke-gold);
  outline-offset: -1px;
}

/* Arriving on a shared photo link: the one photograph somebody was sent gets a
   moment of emphasis so it is obvious which of them it is. */
.preview-photo.is-shared {
  outline: 3px solid var(--oke-gold);
  outline-offset: -1px;
  animation: shared-photo-pulse 2.2s ease-out 1;
}
@keyframes shared-photo-pulse {
  0%   { box-shadow: 0 0 0 0 rgba(240, 179, 35, .55); }
  70%  { box-shadow: 0 0 0 16px rgba(240, 179, 35, 0); }
  100% { box-shadow: 0 0 0 0 rgba(240, 179, 35, 0); }
}
@media (prefers-reduced-motion: reduce) {
  .preview-photo.is-shared { animation: none; }
}

.preview-image { height: 300px; border-radius: 13px 13px 0 0; }

.preview-photo p {
  padding: 15px 16px;
  font-size: var(--t-small);
  gap: 12px;
  align-items: flex-start;
}

.preview-photo p b {
  font-size: var(--t-body);
  font-weight: 700;
  letter-spacing: -.2px;
}

.preview-photo p strong {
  font-size: var(--t-lead);
  font-weight: 800;
  white-space: nowrap;
}

.photographer-profile-button {
  font-size: var(--t-small);
  font-weight: 600;
  margin-top: 5px;
  display: inline-block;
}

.photo-issues { padding: 0 16px 14px; gap: 14px; }
.photo-issues button { font-size: var(--t-micro); color: var(--oke-muted); }

.gallery-preview-button {
  font-size: var(--t-micro);
  font-weight: 700;
  padding: 9px 13px;
  border-radius: 9px;
}

/* The watermark overlays are legal/deterrent furniture, not decoration: keep
   them legible but stop them competing with the photograph itself. */
.preview-image:after { font-size: 10px; letter-spacing: 1px; }
.preview-image:before { font-size: 9px; letter-spacing: 1.4px; }

/* ------------------------------------------------------------ cart, modal -- */

.preview-cart {
  border-radius: 14px;
  padding: 14px 16px 14px 22px;
  gap: 22px;
}

.preview-cart strong { font-size: var(--t-body); font-weight: 700; }
.preview-cart span { font-size: var(--t-small); }
.preview-cart button { font-size: var(--t-small); font-weight: 700; border-radius: 9px; }

.preview-modal article { border-radius: 16px; padding: 32px; }
.preview-modal h2 { font-size: var(--t-h2); }
.preview-modal p { font-size: var(--t-small); line-height: 1.55; }
.preview-modal button { font-size: var(--t-body); font-weight: 700; min-height: 50px; border-radius: 10px; }
.preview-modal input,
.preview-modal select,
.preview-modal textarea { font-size: 16px; border-radius: 9px; border-color: var(--oke-line); }

.compact-checkout-card label { font-size: var(--t-micro); font-weight: 700; }
.compact-checkout-card label span { font-weight: 500; color: var(--oke-muted); }
.compact-checkout-card input,
.compact-checkout-card select { height: 48px; min-height: 48px; font-size: 16px; }

.selfie-consent-card h2 { font: 800 var(--t-h2) / 1.08 var(--oke-font); letter-spacing: -1.2px; }
.selfie-consent-card p { font-size: var(--t-small); }
.selfie-consent-card .consent-box { font-size: var(--t-small); line-height: 1.5; }

.protected-preview-card p { font-size: var(--t-small); }

/* ----------------------------------------------------------- cross-sell -- */

.related-strip { margin-top: 46px; }
.related-strip[hidden] { display: none; }
.related-strip h3 {
  font-size: var(--t-h3);
  font-weight: 800;
  letter-spacing: -.6px;
  margin: 0 0 4px;
}
.related-note {
  margin: 0 0 22px;
  font-size: var(--t-small);
  color: var(--oke-muted);
}

/* ---------------------------------------------------------------- share -- */

.share-gallery-button {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  flex: none;
  align-self: end;
  margin-bottom: 28px;
  padding: 11px 18px;
  border: 1px solid var(--oke-line);
  border-radius: 999px;
  background: #fff;
  color: var(--oke-ink);
  font: 700 var(--t-small) / 1 var(--oke-font);
  cursor: pointer;
  white-space: nowrap;
}
.share-gallery-button:hover { border-color: var(--oke-gold); background: #FFFBF2; }
.share-gallery-button svg,
.tile-share-button svg {
  width: 17px;
  height: 17px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.7;
  stroke-linecap: round;
}

/* On the tile, opposite the Preview control so the two never collide. */
.tile-share-button {
  position: absolute;
  top: 10px;
  right: 10px;
  z-index: 3;
  display: grid;
  place-items: center;
  width: 36px;
  height: 36px;
  border: 0;
  border-radius: 50%;
  background: rgba(255, 255, 255, .92);
  color: var(--oke-ink);
  cursor: pointer;
}
.tile-share-button:hover { background: var(--oke-gold); }

.share-primary {
  width: 100%;
  min-height: 50px;
  margin: 4px 0 10px !important;
  border: 0;
  border-radius: 10px;
  background: var(--oke-gold) !important;
  color: var(--oke-ink) !important;
  font: 700 var(--t-body) / 1 var(--oke-font);
  cursor: pointer;
}

.share-card { text-align: left; }
.share-card h2 { font-size: var(--t-h3); margin: 0 0 6px; }
.share-message {
  margin: 0 0 16px;
  padding: 12px 14px;
  border-radius: 10px;
  background: var(--oke-paper);
  font-size: var(--t-small);
  color: var(--oke-muted);
  line-height: 1.5;
}
.share-whatsapp {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  min-height: 52px;
  border-radius: 11px;
  /* WhatsApp's own green, because the button is recognised before it is read. */
  background: #25D366;
  color: #06301A;
  font: 700 var(--t-body) / 1 var(--oke-font);
  text-decoration: none;
}
.share-whatsapp:hover { filter: brightness(1.05); }
.share-whatsapp svg { width: 21px; height: 21px; fill: currentColor; stroke: none; }

.share-link-row { display: flex; gap: 8px; margin: 12px 0 4px; }
.share-link-row input {
  flex: 1;
  min-width: 0;
  height: 46px;
  margin: 0 !important;
  padding: 0 12px;
  border: 1px solid var(--oke-line);
  border-radius: 10px;
  background: #fff;
  font-size: var(--t-small);
  color: var(--oke-muted);
}
.share-link-row button {
  width: auto !important;
  min-height: 46px !important;
  margin: 0 !important;
  padding: 0 16px;
  border-radius: 10px;
  background: var(--oke-ink) !important;
  color: #fff !important;
  font-size: var(--t-small) !important;
  font-weight: 700 !important;
}
.share-close {
  width: 100%;
  min-height: 46px;
  margin-top: 8px !important;
  border-radius: 10px;
  background: #F1EFE9 !important;
  color: var(--oke-muted) !important;
  font-size: var(--t-small) !important;
  font-weight: 600 !important;
}

/* Redress links, moved off the gallery tile and next to the photograph. */
.preview-report-actions { display: flex; gap: 10px; justify-content: center; margin: 4px 0 12px; }
.preview-report-actions button {
  width: auto !important;
  min-height: 40px !important;
  margin: 0 !important;
  padding: 0 14px;
  background: #F4F1EA !important;
  color: var(--oke-muted) !important;
  font-size: var(--t-micro) !important;
  font-weight: 600 !important;
}
.preview-report-actions button:hover { background: #E9E5DB !important; }
/* --------------------------------------------------- photographer profile -- */
/* Led by four grey statistic boxes and a floated portrait. A photographer is
 * judged on their work first, so the card now opens on three of their frames,
 * with identity and numbers as a strip beneath. */

.photographer-profile-card { text-align: left; padding: 0 0 24px !important; overflow: hidden; }

.photographer-profile-card .profile-cover {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 2px;
  height: 150px;
  background: var(--oke-ink);
}
.profile-cover[data-count="1"] { grid-template-columns: 1fr; }
.profile-cover[data-count="2"] { grid-template-columns: 1fr 1fr; }
.profile-cover span { background-size: cover; background-position: center; }
.profile-cover.is-empty { background: linear-gradient(120deg, #0F1B2D, #24344c); }

.photographer-profile-card .profile-identity {
  display: flex;
  align-items: flex-start;
  gap: 14px;
  margin: 0 24px;
  padding-top: 12px;
  position: relative;
}
/* Only the avatar straddles the cover. Lifting the whole row put the name inside
   the photograph band, where it was unreadable against the frames behind it. */
.photographer-profile-card .profile-avatar { margin-top: -42px; }
.profile-identity h2 { font-size: var(--t-h3); margin: 0; line-height: 1.15; }
.profile-business { margin: 2px 0 0; font-size: var(--t-small); font-weight: 700; color: var(--gold-text, #8A5D06); }
.profile-region { margin: 1px 0 0; font-size: var(--t-micro); color: var(--oke-muted); }

.photographer-profile-card .profile-avatar {
  position: relative;
  flex: none;
  width: 72px;
  height: 72px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  border: 3px solid #fff;
  background: var(--oke-ink);
  color: #fff;
  font: 800 22px/1 var(--oke-font);
  overflow: hidden;
  box-shadow: 0 6px 20px rgba(15, 27, 45, .22);
}
/* The initials sit underneath permanently; the photograph covers them when it
   loads and removes itself when it cannot. */
.profile-avatar img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }

.photographer-profile-card .profile-stats {
  display: flex;
  gap: 26px;
  margin: 16px 24px 0;
  padding-bottom: 16px;
  border-bottom: 1px solid var(--oke-line);
}
.profile-stats span { display: flex; flex-direction: column; font-size: var(--t-micro); color: var(--oke-muted); }
.profile-stats strong { font-size: var(--t-lead); font-weight: 800; color: var(--oke-ink); }

.photographer-profile-card .profile-bio {
  margin: 14px 24px 0;
  font-size: var(--t-small);
  line-height: 1.55;
  color: var(--oke-muted);
  white-space: pre-line;
}

.profile-actions { display: flex; gap: 10px; margin: 16px 24px 0; }
.photographer-profile-card .profile-primary {
  flex: 1;
  min-height: 50px;
  border: 0;
  border-radius: 11px;
  background: var(--oke-ink);
  color: #fff;
  font: 700 var(--t-body) / 1 var(--oke-font);
  cursor: pointer;
}
.profile-primary:hover { background: #16263F; }
.photographer-profile-card .profile-share {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  flex: none;
  min-height: 50px;
  padding: 0 18px;
  border: 1px solid var(--oke-line);
  border-radius: 11px;
  background: #fff;
  color: var(--oke-ink);
  font: 700 var(--t-small) / 1 var(--oke-font);
  cursor: pointer;
}
.profile-share:hover { border-color: var(--oke-gold); background: #FFFBF2; }
.profile-share svg { width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; }

.photographer-profile-card .profile-portfolio {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 4px;
  margin: 18px 0 0;
}
.photographer-profile-card .profile-portfolio-tile {
  /* height:auto is required: .preview-modal button sets an explicit 48px, and an
     explicit height beats aspect-ratio, so the tiles rendered as 164x50 strips. */
  height: auto;
  aspect-ratio: 1;
  border: 0;
  padding: 0;
  background-size: cover;
  background-position: center;
  cursor: pointer;
  transition: opacity .15s ease;
}
.profile-portfolio-tile:hover { opacity: .82; }

.profile-section { margin: 20px 24px 0; }
.photographer-profile-card .profile-section h3 {
  font-size: var(--t-micro);
  font-weight: 700;
  letter-spacing: 1.2px;
  text-transform: uppercase;
  color: var(--oke-muted);
  margin: 0 0 10px;
}
.profile-events { list-style: none; margin: 0; padding: 0; display: grid; gap: 6px; }
.photographer-profile-card .profile-events button {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  grid-template-areas: "name count" "meta count";
  align-items: center;
  gap: 1px 12px;
  width: 100%;
  padding: 11px 13px;
  border: 1px solid var(--oke-line);
  border-radius: 10px;
  background: #fff;
  text-align: left;
  cursor: pointer;
}
.profile-events button:hover { border-color: var(--oke-gold); background: #FFFBF2; }
.profile-event-name { grid-area: name; font-size: var(--t-small); font-weight: 700; color: var(--oke-ink); }
.profile-event-meta { grid-area: meta; font-size: var(--t-micro); color: var(--oke-muted); }
.profile-event-count { grid-area: count; font-size: var(--t-micro); font-weight: 700; color: var(--oke-muted); }

.profile-empty { margin: 0; font-size: var(--t-small); color: var(--oke-muted); }
.profile-link { display: inline-block; margin: 14px 24px 0; font-size: var(--t-small); font-weight: 700; color: var(--gold-text, #8A5D06); }
.photographer-profile-card .profile-close {
  display: block;
  width: calc(100% - 48px);
  min-height: 46px;
  margin: 18px 24px 0;
  border: 0;
  border-radius: 10px;
  background: #F1EFE9;
  color: var(--oke-muted);
  font: 600 var(--t-small) / 1 var(--oke-font);
  cursor: pointer;
}

@media (max-width: 700px) {
  .profile-cover { height: 118px; }
  .profile-identity, .profile-stats, .photographer-profile-card .profile-bio,
  .profile-actions, .profile-section, .profile-link { margin-left: 16px; margin-right: 16px; }
  .profile-close { width: calc(100% - 32px); margin-left: 16px; margin-right: 16px; }
  .profile-avatar { width: 62px; height: 62px; font-size: 19px; }
  .profile-stats { gap: 18px; }
}

.event-clear-button { font-size: var(--t-micro) !important; height: 26px !important; }

/* ---------------------------------------------------------------- footer -- */

.site-footer h3 {
  font-size: var(--t-micro);
  font-weight: 700;
  letter-spacing: 1.4px;
  text-transform: uppercase;
}

.site-footer a, .footer-note { font-size: var(--t-small); }
.footer-bottom { font-size: var(--t-micro); }
.sihebs-partner small { font-size: var(--t-micro); letter-spacing: 1px; }

/* -------------------------------------------------------------- responsive -- */

@media (max-width: 900px) {
  :root { --t-h1: 38px; --t-h2: 26px; --space-section: 64px; }
}

@media (max-width: 700px) {
  :root { --t-h1: 32px; --t-h2: 23px; --t-lead: 16px; --space-section: 52px; }
  .preview-copy { padding: 30px 0 36px; }
  .preview-copy h1 { letter-spacing: -1px; margin: 12px 0 12px; }
  .preview-copy p { max-width: none; }
  /* Stacked, because three cells across 360px gives each of them about 90px —
     narrower than the word "Photographer". */
  .search-bar { grid-template-columns: 1fr; gap: 2px; padding: 5px; border-radius: 14px; }
  .search-field { min-height: 54px; }
  /* Horizontal rule between stacked cells rather than a vertical one beside. */
  .search-field + .search-field:before {
    left: 14px; right: 14px; top: 0; bottom: auto; width: auto; height: 1px;
  }
  .search-go { min-height: 54px; width: 100%; margin-top: 3px; }
  .search-meta { margin-top: 12px; }
  .preview-image { height: 320px; }
  .preview-modal article { padding: 24px 20px; }
}

/* Short windows: give up display type before giving up the search box. These
   live at the end of the file deliberately — they have the same specificity as
   the base rules above and only win by coming later. Scoped to >700px so they
   never fight the phone layout. */
@media (min-width: 701px) and (max-height: 880px) {
  :root { --t-h1: 40px; }
  .preview-nav { height: 70px; }
  .preview-copy { padding: 26px 0 30px; }
  .preview-copy h1 { margin: 12px 0 12px; }
  .preview-copy p { font-size: 15px; }
  .search-field, .search-go { min-height: 56px; }
}

@media (min-width: 701px) and (max-height: 720px) {
  :root { --t-h1: 32px; }
  .preview-nav { height: 60px; }
  .preview-copy { padding: 14px 0 18px; }
  .preview-copy h1 { margin: 8px 0 8px; }
  .preview-copy p { font-size: 14px; line-height: 1.45; }
  .search-field, .search-go { min-height: 50px; }
  .search-meta { margin-top: 10px; }
  .selfie-search-trigger { min-height: 42px; }
}

/* ============================================================ mobile app -- */
/* On a phone this stops behaving like a shrunken web page and behaves like an
 * app: a fixed tab bar within thumb reach, a compact header that stays put,
 * a hero that gets out of the way so photographs are on screen immediately,
 * and sheets that rise from the bottom edge rather than dropdowns that hang
 * from the top. Nothing here is installed — it is the same page.
 */

.app-tabs { display: none; }
.sheet-backdrop { display: none; }

@media (max-width: 700px) {
  html { overscroll-behavior-y: contain; }
  body {
    /* Room for the tab bar, plus the home-indicator strip on notched phones. */
    padding-bottom: calc(58px + env(safe-area-inset-bottom));
    -webkit-tap-highlight-color: transparent;
  }

  /* ---- tab bar ---- */
  .app-tabs {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 60;
    padding-bottom: env(safe-area-inset-bottom);
    background: rgba(15, 27, 45, .97);
    backdrop-filter: saturate(150%) blur(12px);
    border-top: 1px solid rgba(255, 255, 255, .12);
  }
  .app-tabs button {
    display: grid;
    justify-items: center;
    gap: 3px;
    min-height: 58px;
    padding: 8px 4px calc(8px);
    border: 0;
    background: transparent;
    color: rgba(255, 255, 255, .72);
    font: 600 11px/1 var(--oke-font);
    cursor: pointer;
  }
  .app-tabs svg {
    width: 22px;
    height: 22px;
    fill: none;
    stroke: currentColor;
    stroke-width: 1.8;
    stroke-linecap: round;
    stroke-linejoin: round;
  }
  .app-tabs button:active,
  .app-tabs button[aria-expanded="true"] { color: var(--oke-gold); }

  /* The hamburger duplicated the tab bar, so it goes. */
  .preview-menu { display: none !important; }

  /* ---- "More" opens a sheet, not a dropdown ---- */
  .sheet-backdrop {
    display: block;
    position: fixed;
    inset: 0;
    z-index: 55;
    background: rgba(15, 27, 45, .5);
    backdrop-filter: blur(2px);
  }
  .sheet-backdrop[hidden] { display: none; }

  .preview-links {
    position: fixed;
    left: 0;
    right: 0;
    top: auto;
    bottom: calc(58px + env(safe-area-inset-bottom));
    z-index: 58;
    width: 100%;
    padding: 10px 12px calc(16px);
    border: 0;
    border-radius: 18px 18px 0 0;
    box-shadow: 0 -18px 50px rgba(0, 0, 0, .4);
    gap: 6px;
  }
  /* A grab handle is what tells somebody this is a sheet. */
  .preview-links:before {
    content: "";
    grid-column: 1 / -1;
    justify-self: center;
    width: 38px;
    height: 4px;
    border-radius: 2px;
    background: #DDD9D0;
    margin: 2px 0 8px;
  }
  .preview-links button { min-height: 50px; font-size: 14px; border-radius: 12px; }
  /* Find, My photos and Sign in are permanent tabs now, so repeating them in
     the sheet just makes it longer. */
  .preview-links .tab-duplicate { display: none; }
  /* The sheet is the only navigation on a phone, so the role destinations that
     the desktop bar no longer carries live here instead of only in the footer. */
  .preview-links .nav-secondary {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 50px;
    border-radius: 12px;
    border: 1px solid #E4E0D7;
    color: #4A5568;
    font-size: 14px;
    font-weight: 600;
    text-decoration: none;
  }

  /* ---- header ---- */
  .preview-nav {
    position: sticky;
    top: 0;
    height: 58px;
    /* Deliberately no backdrop-filter here. It creates a containing block for
       position:fixed descendants, and #preview-links lives inside this nav — the
       "More" sheet was being positioned against the 58px header instead of the
       viewport, which put it off the top of the screen. The tab bar can afford
       the blur because nothing fixed lives inside it. */
    background: #0F1B2D;
    border-bottom: 1px solid rgba(255, 255, 255, .12);
    width: 100%;
    padding: 0 16px;
    /* Above the sheet backdrop (55), below the tab bar (60). The nav is a
       stacking context, so #preview-links inside it cannot rise past this value
       no matter what z-index it carries — at 30 the backdrop painted over the
       open sheet and greyed it out. */
    z-index: 57;
  }
  .preview-logo { width: 118px; height: 40px; }

  /* ---- hero: introduce, then get out of the way ---- */
  .preview-hero {
    /* Not full height any more. A photo marketplace that shows no photographs
       until you scroll is working against itself. */
    min-height: auto;
  }
  .preview-copy { padding: 18px 0 16px; }
  /* The wordmark underneath already reads "Event Photography Marketplace". */
  .preview-copy .eyebrow { display: none; }
  :root { --t-h1: 27px; }
  .preview-copy h1 { margin: 0 0 8px; letter-spacing: -.7px; }
  .preview-copy p { font-size: 14px; line-height: 1.45; margin: 0 0 4px; }

  /* ---- event picker as a bottom sheet ---- */
  .event-picker {
    position: fixed;
    left: 0;
    right: 0;
    top: auto;
    bottom: 0;
    z-index: 62;
    width: 100%;
    max-height: 72vh !important;
    padding: 8px 10px calc(12px + env(safe-area-inset-bottom));
    border: 0;
    border-radius: 18px 18px 0 0;
    box-shadow: 0 -18px 50px rgba(0, 0, 0, .4);
  }
  .event-picker:before {
    content: "";
    display: block;
    width: 38px;
    height: 4px;
    margin: 2px auto 8px;
    border-radius: 2px;
    background: #DDD9D0;
  }
  .event-option { padding: 13px 12px; min-height: 56px; }

  /* ---- gallery: a photo grid, two up ---- */
  .preview-gallery { grid-template-columns: 1fr 1fr; gap: 10px; }
  .preview-image { height: 172px; border-radius: 13px 13px 0 0; }
  .preview-photo { border-radius: 14px; }
  /* The protection marks are sized for a 400px desktop tile; on a 170px one the
     rotated text ran off both edges and read as "N · PURCHASE TO DOWNLOAD O". */
  .preview-image:after { font-size: 7px; letter-spacing: .4px; }
  .preview-image:before { font-size: 6px; letter-spacing: .6px; }
  .preview-photo p { padding: 9px 10px 11px; flex-direction: column; gap: 3px; font-size: 12px; }
  .preview-photo p b { font-size: 12px; line-height: 1.25; }
  .preview-photo p strong { font-size: 14px; }
  .photographer-profile-button { font-size: 11px; margin-top: 2px; }
  .gallery-preview-button { font-size: 11px; padding: 7px 10px; }
  .tile-share-button { width: 34px; height: 34px; top: 8px; right: 8px; }
  /* The section heading and the share control stack rather than compete for a
     390px row. */
  .preview-section > div:first-child { flex-direction: column; align-items: flex-start; gap: 4px; }
  .share-gallery-button { align-self: flex-start; margin: 0 0 20px; }
  /* Two report links do not fit a 170px tile. They now live in the preview
     modal, next to the photograph they are about. */
  .photo-issues { display: none; }

  /* ---- fixed furniture clears the tab bar ---- */
  .preview-cart { bottom: calc(66px + env(safe-area-inset-bottom)); }
}

/* Respect a reader's stated preference; the hover lift is decoration. */
@media (prefers-reduced-motion: reduce) {
  .preview-photo, .preview-photo:hover { transition: none; transform: none; }
  html { scroll-behavior: auto; }
}

/* Secondary, deliberately quiet: the primary action is one download of
   everything. These exist for the person who wants a single frame. */
.preview-modal .single-downloads { margin-top: 10px; text-align: left; }
.preview-modal .single-downloads summary {
  cursor: pointer;
  font-size: 12px;
  font-weight: 600;
  color: #5B6574;
  padding: 6px 2px;
  list-style: none;
}
.preview-modal .single-downloads summary::-webkit-details-marker { display: none; }
.preview-modal .single-downloads summary:before { content: "\25B8 "; }
.preview-modal .single-downloads[open] summary:before { content: "\25BE "; }
.preview-modal .single-downloads button {
  background: #EFF1F5;
  color: #33404F;
  font-size: 13px;
  min-height: 40px;
  margin-top: 6px;
}

/* The bib field can be emptied in one tap, like the event field beside it. */
.search-field-bib { position: relative; display: flex; align-items: center; }
.bib-clear-button {
  border: 0;
  background: #EFF1F5;
  color: #4A5464;
  border-radius: 999px;
  width: 26px;
  height: 26px;
  font-size: 15px;
  line-height: 1;
  margin-right: 6px;
  flex: 0 0 auto;
}
.bib-clear-button:hover:not(:disabled) { background: #E2E6EC; }

/* A picker that is working should look like it. Blank white space reads as
   broken, which on a slow connection is most of the wait. */
.event-option-empty.is-loading { color: var(--oke-muted); }
.event-option-empty.is-loading:before {
  content: "";
  display: inline-block;
  width: 12px;
  height: 12px;
  margin-right: 8px;
  vertical-align: -1px;
  border: 2px solid #D8DCE3;
  border-top-color: var(--oke-gold);
  border-radius: 50%;
  animation: event-picker-spin .7s linear infinite;
}
.event-option-empty.is-error { color: #B23B2E; }
@keyframes event-picker-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
  .event-option-empty.is-loading:before { animation: none; }
}

/* Screenshot deterrence.
   A browser cannot stop a screenshot -- the operating system captures the
   screen before any script runs. What these do is make the two easy captures
   (PrintScreen, switching to a capture tool) come away with nothing useful,
   and remind the viewer that what they are looking at is watermarked anyway. */
.previews-shielded .preview-image img,
.previews-shielded .modal-photo img,
.previews-shielded .photo-preview-large {
  filter: blur(22px);
  transition: filter .06s linear;
}
.preview-image img,
.photo-preview-large {
  -webkit-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
  -webkit-user-drag: none;
}
.screenshot-notice {
  position: fixed;
  left: 50%;
  bottom: 24px;
  transform: translate(-50%, 20px);
  z-index: 90;
  max-width: min(520px, calc(100% - 32px));
  padding: 13px 18px;
  border-radius: 12px;
  background: var(--oke-ink);
  color: #fff;
  font-size: var(--t-small);
  line-height: 1.45;
  text-align: center;
  box-shadow: 0 18px 44px rgba(15, 27, 45, .38);
  opacity: 0;
  pointer-events: none;
  transition: opacity .2s ease, transform .2s ease;
}
.screenshot-notice.show { opacity: 1; transform: translate(-50%, 0); }
@media (prefers-reduced-motion: reduce) {
  .screenshot-notice { transition: none; }
}

/* ------------------------------------------------------------ promo rail -- */
/* Recognition before search: a visitor who does not know OKE remembers the race
   they ran, so the event is the hook and the photograph behind it is the proof
   there is something to find. */
.promo-rail {
  width: min(1180px, calc(100% - 36px));
  margin: 64px auto 0;
}
.promo-rail[hidden] { display: none; }
.promo-head { max-width: 640px; margin-bottom: 26px; }
/* The section eyebrow is scoped to .preview-section, which this is not, so it
   fell back to an 8px inline rule and collided with the heading. */
.promo-head .eyebrow {
  display: flex;
  align-items: center;
  gap: 9px;
  font-size: var(--t-micro);
  font-weight: 700;
  letter-spacing: 1.6px;
  line-height: 1.4;
  text-transform: uppercase;
  color: var(--oke-muted);
}
.promo-head .eyebrow > span:first-child {
  width: 26px;
  height: 2px;
  background: var(--oke-gold);
  flex: 0 0 auto;
}
/* A generic `.eyebrow span` rule elsewhere paints every span in an eyebrow as
   that 26x2 gold bar, so the label was overflowing a two-pixel box and landing
   on top of the heading. Named explicitly so no generic selector reaches it. */
.promo-head .eyebrow .promo-eyebrow-text {
  width: auto;
  height: auto;
  background: none;
  flex: 0 1 auto;
}
.promo-head h2 {
  font-size: var(--t-h2);
  font-weight: 800;
  letter-spacing: -1.2px;
  margin: 10px 0 8px;
}
.promo-head p { color: var(--oke-muted); margin: 0; font-size: var(--t-body); }

.promo-cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
  gap: 16px;
}

.promo-card {
  position: relative;
  display: block;
  width: 100%;
  min-height: 290px;
  padding: 0;
  border: 0;
  border-radius: 18px;
  overflow: hidden;
  cursor: pointer;
  background: var(--oke-ink);
  text-align: left;
  isolation: isolate;
  box-shadow: 0 18px 40px -22px rgba(15, 27, 45, .55);
  transition: transform .22s ease, box-shadow .22s ease;
}
.promo-card:hover { transform: translateY(-4px); box-shadow: 0 28px 56px -24px rgba(15, 27, 45, .6); }
.promo-card:focus-visible { outline: 3px solid var(--oke-gold); outline-offset: 3px; }

.promo-cover {
  position: absolute;
  inset: 0;
  z-index: -2;
  background-size: cover;
  background-position: center;
  transform: scale(1.02);
  transition: transform .5s ease;
}
.promo-card:hover .promo-cover { transform: scale(1.07); }
/* The headline has to stay readable over any photograph, so the gradient does
   the work rather than hoping the image is dark where the text sits. */
.promo-card:before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(180deg, rgba(15, 27, 45, .12) 0%, rgba(15, 27, 45, .78) 58%, rgba(15, 27, 45, .95) 100%);
}

.promo-body {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 6px;
  height: 100%;
  min-height: 290px;
  justify-content: flex-end;
  padding: 20px;
  color: #fff;
}
.promo-kicker {
  font-size: var(--t-micro);
  font-weight: 700;
  letter-spacing: 1.1px;
  text-transform: uppercase;
  color: var(--oke-gold);
}
.promo-title {
  font-size: 23px;
  font-weight: 800;
  line-height: 1.12;
  letter-spacing: -.6px;
}
.promo-meta { font-size: var(--t-small); color: rgba(255, 255, 255, .82); }
.promo-cta {
  margin-top: 8px;
  font-size: var(--t-small);
  font-weight: 700;
  color: var(--oke-gold);
}

@media (max-width: 700px) {
  .promo-rail { width: calc(100% - 28px); margin-top: 44px; }
  .promo-head h2 { font-size: 25px; }
  /* A rail, not a stack: four full-height cards would bury the gallery. */
  .promo-cards {
    display: flex;
    gap: 12px;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    padding-bottom: 4px;
  }
  .promo-cards::-webkit-scrollbar { display: none; }
  .promo-card {
    flex: 0 0 78%;
    scroll-snap-align: start;
    min-height: 232px;
  }
  .promo-body { min-height: 232px; padding: 16px; }
  .promo-title { font-size: 20px; }
}

@media (prefers-reduced-motion: reduce) {
  .promo-card, .promo-cover { transition: none; }
  .promo-card:hover { transform: none; }
  .promo-card:hover .promo-cover { transform: scale(1.02); }
}

/* One line under the search: the newest gallery, above the fold. Deliberately a
   strip and not a card -- the hero has to keep fitting a short laptop screen
   without scrolling, which a second block would break. */
.hero-promo {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  margin-top: 14px;
  padding: 8px 14px 8px 8px;
  border-radius: 999px;
  background: rgba(255, 255, 255, .12);
  border: 1px solid rgba(255, 255, 255, .22);
  color: #fff;
  text-decoration: none;
  font-size: var(--t-small);
  max-width: 100%;
  transition: background .16s ease, border-color .16s ease;
}
.hero-promo[hidden] { display: none; }
.hero-promo:hover { background: rgba(255, 255, 255, .2); border-color: rgba(255, 255, 255, .38); }
.hero-promo-flag {
  flex: 0 0 auto;
  background: var(--oke-gold);
  color: var(--oke-ink);
  font-size: 11px;
  font-weight: 800;
  letter-spacing: .8px;
  text-transform: uppercase;
  border-radius: 999px;
  padding: 4px 9px;
}
.hero-promo-text {
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.hero-promo-go { flex: 0 0 auto; color: var(--oke-gold); font-weight: 800; }

@media (max-width: 700px) {
  .hero-promo { margin-top: 12px; font-size: var(--t-micro); padding: 7px 12px 7px 7px; }
}
/* Measured on a 1080p laptop at 125% Windows scaling — a ~687px tall viewport,
   the single most common shape here — the promo ends at 545px and the Search
   button at 432px.  Both clear the fold, so there is nothing to protect by
   hiding it, and the promo is the reason somebody clicks. */
@media (min-width: 701px) and (max-height: 470px) {
  .hero-promo { display: none; }
}

/* --------------------------------------------- mobile: photographs on sight --
 * These must come after the .promo-rail / .promo-head rules above.  An earlier
 * attempt put them in the mobile block near the top of this file, where they
 * lost to the later base rules: a media query adds no specificity, so at equal
 * specificity the last declaration wins regardless of the query.
 *
 * Measured on a 360x740 phone with the fixed tab bar covering from 681px: the
 * promo cards began at 718px, so the photographs -- the entire product -- were
 * never on screen without scrolling.
 */
@media (max-width: 700px) {
  .promo-rail { margin-top: 16px; }
  .promo-head { margin-bottom: 12px; }
  .promo-head h2 { margin: 4px 0 4px; }
  /* The heading directly underneath says the same thing in plainer words. */
  .promo-head .eyebrow { display: none; }
  .preview-copy { padding: 14px 0 12px; }
}

/* Post-download landing.
 *
 * Closing the download dialog returned the buyer to the results grid with the
 * selection bar still offering to sell them the photographs they had just
 * downloaded. This is what a finished order leaves behind instead: where the
 * files went, how long the link lasts, and the three things people do next.
 */
.download-done {
  position: fixed;
  left: 50%;
  bottom: 15px;
  transform: translateX(-50%);
  z-index: 11;
  width: min(680px, calc(100vw - 24px));
  background: #0F1B2D;
  color: #E7EAF0;
  border-radius: 14px;
  padding: 16px 18px;
  box-shadow: 0 20px 50px #0006;
}
.download-complete-note {
  margin: 0 0 12px;
  font-size: 14px;
  font-weight: 800;
  color: #1f7a4d;
}
.download-done-head { display: flex; align-items: flex-start; gap: 13px; }
.download-done-head > span {
  flex: none; width: 30px; height: 30px; border-radius: 50%;
  background: #1f7a4d; color: #fff; display: grid; place-items: center;
  font-size: 16px; font-weight: 900;
}
.download-done-head > div { flex: 1; min-width: 0; }
.download-done strong { display: block; font-size: 17px; color: #fff; }
.download-done small {
  display: block; margin-top: 3px; font-size: 13px; color: #9aa5b4; line-height: 1.55;
}
.download-done-close {
  flex: none; border: 0; background: transparent; color: #8b94a0;
  font-size: 22px; line-height: 1; cursor: pointer; padding: 0 2px;
}
.download-done-actions {
  display: flex; flex-wrap: wrap; gap: 9px; margin-top: 14px;
}
.download-done-actions button {
  border: 1px solid #34435a; background: #17263c; color: #E7EAF0;
  border-radius: 9px; padding: 10px 14px;
  font-size: 13px; font-weight: 800; cursor: pointer;
}
.download-done-actions button:first-child {
  background: #F0B323; border-color: #F0B323; color: #22190a;
}
@media (max-width: 700px) {
  .download-done { padding: 14px; border-radius: 12px; bottom: 10px; }
  .download-done small { font-size: 12px; }
  /* Two per row rather than one per row: three stacked full-width buttons
     pushed the panel tall enough to cover the photographs behind it. */
  .download-done-actions button { flex: 1 1 calc(50% - 5px); padding: 10px 8px; font-size: 12px; }
}

/* Photo card, reworked.
 *
 * The product is the photograph, and the card was spending more of itself on
 * text than on the image: an event name repeated on every card of a gallery the
 * visitor had just chosen by name, then time, checkpoint, byline, price and two
 * report links, which were being clipped mid-glyph at the bottom.
 *
 * Selecting also used to be bound to the whole card, so any click -- including
 * the ones people make just to look at something -- put a photograph in the
 * basket. The tile now opens the larger protected view and a button does the
 * selecting, so looking and buying are different actions.
 */
.preview-image { height: 360px; cursor: zoom-in; }
.preview-photo { overflow: hidden; }

.tile-hint {
  position: absolute; right: 10px; bottom: 10px; z-index: 3;
  border-radius: 7px; background: #ffffffee; color: #0F1B2D;
  padding: 7px 10px; font-size: 11px; font-weight: 900;
  box-shadow: 0 8px 24px #0004; pointer-events: none;
}

.photo-line {
  display: flex; align-items: baseline; flex-wrap: wrap; gap: 2px 10px;
  padding: 12px 14px 0; margin: 0;
}
.photo-event {
  flex: 1 0 100%; font-size: 13px; font-weight: 800; color: #0F1B2D;
}
.photo-when { flex: 1; min-width: 0; font-size: 12px; color: #6b7280; }
.photo-price { font-size: 15px; font-weight: 900; color: #0F1B2D; white-space: nowrap; }

.photo-select {
  display: block; width: calc(100% - 28px); margin: 11px 14px 0;
  border: 1px solid #0F1B2D; border-radius: 9px; background: #fff; color: #0F1B2D;
  padding: 11px; font-size: 14px; font-weight: 900; cursor: pointer;
}
.photo-select:hover { background: #0F1B2D; color: #fff; }
.preview-photo.selected .photo-select { background: #F0B323; border-color: #F0B323; color: #22190a; }
.preview-photo.selected .photo-select::before { content: "\2713  "; }

.preview-photo .photographer-profile-button {
  display: block; width: 100%; text-align: left;
  padding: 9px 14px 0; font-size: 12px;
}

/* Given room of their own, these stop being clipped. */
.preview-photo .photo-issues {
  display: flex; gap: 14px; padding: 10px 14px 13px; margin-top: 2px;
}
.preview-photo .photo-issues button {
  font-size: 11px; color: #8b94a0; background: none; border: 0;
  text-decoration: underline; cursor: pointer; padding: 0; line-height: 1.4;
}

@media (max-width: 700px) {
  /* One per row on a phone, so the photograph gets the whole width. */
  .preview-image { height: 400px; }
  .photo-select { padding: 13px; font-size: 15px; }
  .preview-photo .photo-issues { display: flex; }
}

/* Enlarged photograph.
 *
 * The point of opening a photograph is to see it, and three rows of chrome sat
 * under it: a sentence repeating what the watermark already says across the
 * image itself, two report links, and a full-width Close button. The sentence
 * is gone, Close is an X on the image, and the photograph takes the room they
 * were using.
 */
.preview-modal article.protected-preview-card { padding: 0; overflow: hidden; position: relative; }
.preview-modal article.protected-preview-card img {
  display: block; width: 100%; max-height: 78vh; object-fit: contain; background: #0b1422;
}
.preview-dismiss {
  position: absolute; top: 10px; right: 10px; z-index: 4;
  width: 36px; height: 36px; border: 0; border-radius: 50%;
  background: #0f1b2dcc; color: #fff; font-size: 22px; line-height: 1; cursor: pointer;
}
.protected-preview-card .preview-cta { display: flex; gap: 9px; padding: 12px 14px 0; }
.protected-preview-card .preview-add { flex: 1; }

/* The enlarged photograph, corrected.
 *
 * The modal styles every button inside it as a full-width gold bar, so the
 * close control was drawn as a thick yellow band across the top of the picture,
 * over the faces, and a row of three buttons each took the full width and shoved
 * the next one off the edge. These are deliberately specific enough to win,
 * because the whole point of opening a photograph is to see it.
 */
.preview-modal article.protected-preview-card { max-height: none !important; }
.preview-modal article.protected-preview-card .preview-dismiss {
  position: absolute !important;
  top: 10px !important;
  right: 10px !important;
  width: 38px !important;
  height: 38px !important;
  min-width: 0 !important;
  margin: 0 !important;
  padding: 0 !important;
  border-radius: 50% !important;
  background: #0f1b2dd9 !important;
  color: #fff !important;
  font-size: 21px !important;
  line-height: 1 !important;
  box-shadow: 0 4px 14px #0006;
}
/* The card already carries 14px of padding, so the button lines up with the
   edges of the picture rather than sitting inside a second margin. */
.preview-modal article.protected-preview-card .preview-cta {
  display: flex !important;
  gap: 9px;
  padding: 12px 0 0 !important;
  margin: 0 !important;
}
.preview-modal article.protected-preview-card .preview-cta .preview-add {
  flex: 1;
  width: 100% !important;
  margin: 0 !important;
  height: 52px !important;
  border-radius: 10px !important;
  background: var(--oke-gold) !important;
  color: #0F1B2D !important;
  border: 0 !important;
  font-size: 16px !important;
  font-weight: 900 !important;
  cursor: pointer;
}
/* Already in the basket: still the same control, but it should not shout the
   offer a second time. */
.preview-modal article.protected-preview-card .preview-cta .preview-add[aria-pressed="true"] {
  background: #ffffff1f !important;
  color: #fff !important;
  border: 1px solid #ffffff4d !important;
  font-weight: 700 !important;
}

/* Room for the photograph.
 *
 * The card asked for 100vw - 24px inside a modal that keeps 20px of padding on
 * each side, so it was 16px wider than the space it had and hung off the right
 * edge -- which is where the third button in the old row disappeared to. The
 * gutter is cut to 8px for this card alone and the width now fits inside it, so
 * the picture gains the difference instead of losing the controls.
 *
 * :has() is the narrow way to reach the wrapper from the card. Where it is not
 * supported the first rule alone still fits, which is the point of the pair.
 */
.preview-modal article.protected-preview-card {
  width: min(900px, calc(100vw - 40px)) !important;
}
.preview-modal:has(> article.protected-preview-card) { padding: 8px; }
.preview-modal:has(> article.protected-preview-card) article.protected-preview-card {
  width: min(900px, calc(100vw - 16px)) !important;
}
/* One row of controls under the picture instead of three, so the cap can rise
   by what the other two were using. dvh, because the phone browser's address
   bar is part of the 100vh it reports and the button went under it. */
.preview-modal article.protected-preview-card img {
  max-height: calc(100vh - 132px);
  max-height: calc(100dvh - 132px);
}

/* What you are about to pay for, shown before you pay for it. */
.checkout-basket {
  display: flex; flex-wrap: wrap; gap: 8px;
  margin: 0 0 14px; padding: 10px; border-radius: 10px; background: #F5F1E8;
  max-height: 168px; overflow-y: auto;
}
.checkout-thumb { position: relative; margin: 0; width: 62px; height: 62px; }
.checkout-thumb img, .checkout-thumb span {
  display: block; width: 100%; height: 100%; object-fit: cover;
  border-radius: 8px; background: #e3ded2;
}
.checkout-thumb button {
  position: absolute !important; top: -6px !important; right: -6px !important;
  width: 22px !important; height: 22px !important; min-width: 0 !important;
  margin: 0 !important; padding: 0 !important; border-radius: 50% !important;
  background: #0F1B2D !important; color: #fff !important;
  font-size: 14px !important; line-height: 1 !important;
}

/* A basket drawn from more than one event. There is no product to choose --
   a bundle belongs to a single event -- so this says what is being charged in
   place of the price list. */
.checkout-span {
  margin: 0 0 12px; text-align: left; font-size: 13px; color: #0F1B2D;
}
.checkout-span strong { font-weight: 900; }

/* The way out of the payment sheet used to be "Cancel", which asks somebody
   who is halfway to paying whether they would like to abandon it. The same
   button, doing the same thing -- back to the gallery with the basket intact --
   now offers the reason anyone actually closes this sheet. It needs a wider
   column than "Cancel" did. */
.preview-modal article.compact-checkout-card .compact-checkout-actions {
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
}
.preview-modal article.compact-checkout-card .compact-checkout-actions .checkout-keep-shopping {
  font-size: 13px;
  font-weight: 800;
  padding: 0 6px;
}
