@font-face {
  font-family: Inter;
  src: url('../fonts/inter-latin-400-normal.woff2') format('woff2');
  font-display: swap;
  font-style: normal;
  font-weight: 400;
}

@font-face {
  font-family: Inter;
  src: url('../fonts/inter-latin-800-normal.woff2') format('woff2');
  font-display: swap;
  font-style: normal;
  font-weight: 800;
}

/* Fraunces also ships in upgrade.css (same files — the browser fetches once);
   declared here too so the editor's typeface samples render truthfully. */
@font-face {
  font-family: 'Fraunces';
  src: url('../fonts/fraunces-latin-wght-normal.woff2') format('woff2-variations');
  font-display: swap;
  font-style: normal;
  font-weight: 100 900;
}
@font-face {
  font-family: 'Fraunces';
  src: url('../fonts/fraunces-latin-wght-italic.woff2') format('woff2-variations');
  font-display: swap;
  font-style: italic;
  font-weight: 100 900;
}

:root {
  --ink: #11130f;
  --paper: #f4f1eb;
  --white: #ffffff;
  --green: #304720;
  --green-light: #c5d7b8;
  --muted: #676c65;
  --line: rgba(17, 19, 15, 0.13);
  --shell: min(1160px, calc(100vw - 64px));
  --shadow: 0 30px 90px rgba(17, 19, 15, 0.15);
  color: var(--ink);
  background: var(--paper);
  font-family: Inter, ui-sans-serif, system-ui, sans-serif;
  font-synthesis: none;
  text-rendering: optimizeLegibility;
}

* { box-sizing: border-box; }
html { background: var(--paper); scroll-behavior: smooth; }
body { min-width: 320px; margin: 0; overflow-x: hidden; background: var(--paper); }
button, a { font: inherit; -webkit-tap-highlight-color: transparent; }
button { cursor: pointer; }
a { color: inherit; }
img { display: block; max-width: 100%; }
::selection { color: var(--ink); background: var(--green-light); }
:focus-visible { outline: 3px solid #d3a64e; outline-offset: 4px; }
.content-shell { width: var(--shell); margin-inline: auto; }

.skip-link {
  position: fixed;
  z-index: 1000;
  top: 12px;
  left: 12px;
  padding: 12px 16px;
  border-radius: 10px;
  background: #fff;
  color: #111;
  opacity: 0;
  pointer-events: none;
  transform: translateY(-150%);
}
.skip-link:focus { opacity: 1; pointer-events: auto; transform: none; }

/* With the R1 announcement banner (fixed 42px) in flow above, the absolutely
   positioned header shifts down by the banner height. Must precede the
   media-query .site-header overrides so those still win at small widths.
   T17: once scrolled the header goes position:fixed (upgrade.css .is-scrolled)
   and the banner has scrolled away — the offset must NOT apply then, or the
   glass bar floats 64px below the viewport top. */
.pm-announce ~ div .site-header { top: 64px; }
.pm-announce ~ div .site-header.is-scrolled { top: 0; }

.site-header {
  position: absolute;
  z-index: 20;
  top: 22px;
  right: max(24px, calc((100vw - 1160px) / 2));
  left: max(24px, calc((100vw - 1160px) / 2));
  min-height: 56px;
  padding: 0;
  display: flex;
  align-items: center;
  gap: 22px;
  color: #fff;
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  color: inherit;
  font-size: 19px;
  font-weight: 800;
  letter-spacing: -.04em;
  text-decoration: none;
}
.brand img { border-radius: 10px; }
.desktop-nav { margin-left: auto; display: flex; align-items: center; gap: 2px; }
.desktop-nav a {
  min-height: 44px;
  padding: 0 13px;
  display: inline-flex;
  align-items: center;
  border-radius: 11px;
  color: rgba(255,255,255,.72);
  font-size: 13px;
  font-weight: 800;
  text-decoration: none;
}
.desktop-nav a:hover { color: #fff; background: rgba(255,255,255,.1); }
.menu-button, .mobile-nav { display: none; }
.account-link {
  width: 46px;
  height: 46px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  color: #fff;
  text-decoration: none;
  transition: background .2s ease, transform .2s ease;
}
.account-link:hover { background: rgba(255,255,255,.12); transform: translateY(-1px); }
.account-link svg { width: 27px; height: 27px; stroke-width: 1.7; }

.button {
  min-height: 52px;
  padding: 0 20px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  border: 1px solid transparent;
  border-radius: 14px;
  font-size: 13px;
  font-weight: 800;
  text-decoration: none;
  transition: transform .2s ease, box-shadow .2s ease;
}
.button:hover { transform: translateY(-2px); }
.button svg, .text-action svg { width: 17px; height: 17px; }
.button-light { border-color: rgba(255,255,255,.28); background: #fff; color: var(--ink); box-shadow: 0 14px 35px rgba(0,0,0,.12); }
.button-accent { background: #36ffb6; color: #06301f; box-shadow: none; }
.button-accent:hover { background: #2bf2aa; }
.text-action {
  min-height: 48px;
  display: inline-flex;
  align-items: center;
  gap: 9px;
  color: rgba(255,255,255,.82);
  font-size: 13px;
  font-weight: 800;
  text-decoration: none;
}

.eyebrow {
  margin: 0;
  display: flex;
  align-items: center;
  gap: 11px;
  color: var(--green-light);
  font-size: 12px;
  font-weight: 800;
  letter-spacing: .12em;
  text-transform: uppercase;
}
.eyebrow::before { content: ""; width: 30px; height: 1px; background: currentColor; }
.eyebrow.dark { color: #607057; }

.hero {
  min-height: 100vh;
  min-height: 100svh;
  padding: 100px 0 100px;
  position: relative;
  display: grid;
  align-items: center;
  overflow: hidden;
  color: #fff;
  background:
    linear-gradient(90deg, rgba(13,15,12,.92) 0%, rgba(13,15,12,.68) 48%, rgba(13,15,12,.18) 82%),
    url('../images/hero3.jpg') center bottom / cover no-repeat;
}
.hero::after {
  content: "";
  position: absolute;
  right: 0;
  bottom: 0;
  left: 0;
  height: 150px;
  background: linear-gradient(transparent, rgba(13,15,12,.28));
  pointer-events: none;
}
.hero-content { position: relative; z-index: 2; }
.hero h1 {
  max-width: 890px;
  margin: 42px 0 26px;
  font-size: clamp(72px, 9vw, 132px);
  line-height: .95;
  letter-spacing: -.062em;
}
.hero-lead { max-width: 610px; margin: 0; color: rgba(255,255,255,.72); font-size: 18px; line-height: 1.65; }
.hero-actions { margin-top: 32px; display: flex; flex-wrap: wrap; align-items: center; gap: 20px; }
.hero-checks { margin-top: 26px; display: flex; flex-wrap: wrap; gap: 18px; color: rgba(255,255,255,.62); font-size: 12px; }
.hero-checks span { display: inline-flex; align-items: center; gap: 7px; }
.hero-checks svg { width: 15px; color: var(--green-light); }
.hero-credit-mark { display: none; position: absolute; z-index: 4; right: max(28px, calc((100vw - 1160px) / 2)); bottom: 26px; opacity: .5; color: #fff; font-size: 12px; line-height: 1.5; text-align: right; letter-spacing: .02em; text-shadow: 0 1px 3px rgba(0,0,0,.35); }
.hero-credit-mark a { color: #fff; text-decoration: underline; text-underline-offset: 2px; }
.hero-gallery-note {
  position: absolute;
  z-index: 3;
  right: max(28px, calc((100vw - 1160px) / 2));
  bottom: 150px;
  width: 325px;
  padding: 18px;
  display: grid;
  gap: 6px;
  border: 1px solid rgba(255,255,255,.22);
  border-radius: 17px;
  background: rgba(13,15,12,.55);
  backdrop-filter: blur(14px);
}
.hero-gallery-note small, .hero-gallery-note span { color: rgba(255,255,255,.64); font-size: 12px; }
.hero-gallery-note small { text-transform: uppercase; letter-spacing: .08em; }
.hero-gallery-note strong { font-family: Georgia, serif; font-size: 22px; font-weight: 400; }
.hero-gallery-note a { color: #fff; text-decoration: underline; text-underline-offset: 2px; }

.gallery-section { padding-block: 80px; background: var(--paper); }
.gallery-intro { display: grid; grid-template-columns: 1.25fr .75fr; align-items: end; gap: 80px; }
.gallery-intro h2, .faq-heading h2 {
  max-width: 810px;
  margin: 26px 0 0;
  font-size: clamp(50px, 6vw, 80px);
  line-height: .98;
  letter-spacing: -.052em;
}
.gallery-intro > p, .faq-heading > p {
  margin: 0;
  color: var(--muted);
  font-size: 16px;
  line-height: 1.7;
}

.gallery-browser {
  position: relative;
  margin-top: 62px;
  max-height: min(88vh, 900px);
  overflow: hidden;
  border: 1px solid var(--line);
  border-radius: 24px;
  background: #fff;
  box-shadow: var(--shadow);
}
/* Fade the clipped bottom edge so the window reads as a real, scrollable browser. */
.gallery-browser::after, .profile-browser::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 64px;
  background: linear-gradient(180deg, rgba(255,255,255,0), #fff);
  pointer-events: none;
}
.browser-bar {
  min-height: 48px;
  padding: 0 17px;
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 12px;
  border-bottom: 1px solid var(--line);
  background: #f8f6f2;
}
.browser-bar > span { display: flex; gap: 5px; }
.browser-bar i { width: 8px; height: 8px; border-radius: 50%; background: #c8c5bd; }
.browser-bar small { color: #858a82; font-size: 12px; }
.browser-bar svg { width: 16px; margin-left: auto; color: #737870; }
.browser-cover { position: relative; height: 360px; overflow: hidden; background: #d9d5ce; }
.browser-cover > img { width: 100%; height: 100%; object-fit: cover; }
.browser-cover::after { content: ""; position: absolute; inset: 0; background: linear-gradient(180deg, rgba(17,19,15,.12) 0%, rgba(17,19,15,0) 40%, rgba(17,19,15,.66) 100%); }
.browser-cover-copy { position: absolute; z-index: 1; left: 26px; bottom: 22px; color: #fff; display: grid; gap: 4px; }
.browser-cover-copy small { font-size: 12px; text-transform: uppercase; letter-spacing: .08em; color: rgba(255,255,255,.85); }
.browser-cover-copy strong { font-family: Georgia, serif; font-size: 34px; font-weight: 400; letter-spacing: -.02em; }
.browser-cover-copy span { font-size: 13px; color: rgba(255,255,255,.82); }
.browser-toolbar { min-height: 70px; padding: 14px 22px; display: flex; align-items: center; justify-content: space-between; gap: 16px; border-bottom: 1px solid var(--line); }
.browser-toolbar-title { display: grid; gap: 2px; }
.browser-toolbar-title strong { font-family: Georgia, serif; font-size: 19px; font-weight: 400; }
.browser-toolbar-title span { color: var(--muted); font-size: 12.5px; }
.browser-toolbar-actions { display: flex; align-items: center; gap: 10px; }
.browser-toolbar-actions span { min-height: 40px; padding: 0 13px; display: flex; align-items: center; gap: 7px; border: 1px solid var(--line); border-radius: 11px; color: var(--muted); font-size: 12px; font-weight: 800; }
.browser-download-mock { min-height: 44px; padding: 0 14px; display: flex; align-items: center; gap: 7px; border: 1px solid var(--line); border-radius: 11px; background: #fff; color: var(--ink); font-size: 12px; font-weight: 800; }
.browser-toolbar-actions svg { width: 16px; color: var(--green); }
.browser-download-mock svg { color: var(--ink); }
.browser-grid { padding: 12px; columns: 200px; column-gap: 10px; }
.browser-grid figure { position: relative; margin: 0 0 10px; break-inside: avoid; overflow: hidden; border-radius: 12px; }
.browser-grid img { width: 100%; height: auto; display: block; }
.browser-heart-mock { width: 44px; height: 44px; position: absolute; top: 8px; right: 8px; display: grid; place-items: center; border: 0; border-radius: 50%; background: rgba(255,255,255,.92); color: #62675f; box-shadow: 0 8px 20px rgba(0,0,0,.14); }
.browser-heart-mock.active { background: var(--green); color: #fff; }
.browser-heart-mock.active svg { fill: currentColor; }
.browser-heart-mock svg { width: 17px; }
.trust-row { padding-top: 42px; display: grid; grid-template-columns: repeat(3, 1fr); }
.trust-row span { padding: 6px 24px; display: flex; align-items: center; justify-content: center; gap: 13px; color: #42483f; font-size: 14px; font-weight: 700; }
.trust-row span + span { border-left: 1px solid var(--line); }
.trust-row svg { flex: 0 0 auto; width: 40px; height: 40px; padding: 10px; border-radius: 50%; background: #eef3e9; color: var(--green); }

.portfolio-section { padding-block: 125px; border-top: 1px solid var(--line); background: #fff; }
.portfolio-layout { display: grid; grid-template-columns: .78fr 1.22fr; align-items: center; gap: 90px; }
.portfolio-copy h2 {
  margin: 26px 0 22px;
  font-size: clamp(50px, 5.6vw, 74px);
  line-height: .98;
  letter-spacing: -.052em;
}
.portfolio-copy > p:not(.eyebrow) { margin: 0; color: var(--muted); font-size: 16px; line-height: 1.72; }
.portfolio-copy > p strong { color: var(--ink); font-weight: 800; }
.portfolio-points { margin: 28px 0 0; padding: 0; display: grid; gap: 13px; list-style: none; }
.portfolio-points li { display: flex; align-items: center; gap: 10px; color: #464c44; font-size: 13px; }
.portfolio-points svg { width: 17px; color: var(--green); }
/* T12: text links → outline-pill buttons (matches .pm-demo-links a). */
.portfolio-link { min-height: 48px; margin-top: 24px; display: inline-flex; align-items: center; gap: 9px; padding: 0 20px; border: 1.5px solid var(--green); border-radius: 999px; color: var(--green); font-size: 13.5px; font-weight: 700; text-decoration: none; transition: background .15s ease, color .15s ease, transform .18s ease; }
.portfolio-link:hover { background: var(--green); color: #fff; transform: scale(1.04); }
.portfolio-link svg { width: 17px; }
/* T12: grow-on-hover replaces the retired magnetic cursor effect. */
.button, .compare-plans-button, .events-action { transition: transform .18s ease, background .18s ease, color .18s ease, border-color .18s ease, box-shadow .18s ease; }
.button:hover, .compare-plans-button:hover, .events-action:hover { transform: scale(1.045); }
.button:active, .compare-plans-button:active, .events-action:active, .portfolio-link:active, .pm-demo-links a:active { transform: scale(.98); }

.profile-browser { position: relative; max-height: min(66vh, 560px); overflow: hidden; border: 1px solid var(--line); border-radius: 22px; background: #fff; box-shadow: var(--shadow); }
.profile-browser-bar { min-height: 46px; padding: 0 16px; display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: 12px; border-bottom: 1px solid var(--line); background: #f8f6f2; }
.profile-browser-bar > span { display: flex; gap: 5px; }
.profile-browser-bar i { width: 8px; height: 8px; border-radius: 50%; background: #c8c5bd; }
.profile-browser-bar small { color: #7d827a; font-size: 12px; }
.profile-browser-bar svg { width: 16px; margin-left: auto; color: #737870; }
.profile-summary { min-height: 100px; padding: 24px 22px 14px; display: grid; grid-template-columns: auto 1fr auto; align-items: center; gap: 16px; }
.profile-summary > img { width: 82px; height: 82px; border: 3px solid #fff; border-radius: 50%; object-fit: cover; object-position: 50% 27%; box-shadow: 0 12px 28px rgba(17,19,15,.14); }
.profile-summary > div { display: grid; gap: 4px; min-width: 0; }
.profile-summary h3 { margin: 0; font-family: Georgia, serif; font-size: 25px; font-weight: 400; letter-spacing: -.01em; }
.profile-summary small { color: #777d74; font-size: 12.5px; font-weight: 700; }
.profile-handle { margin: 0; display: flex; flex-wrap: wrap; align-items: center; gap: 4px 10px; font-size: 12.5px; }
.profile-handle b { color: var(--ink); font-weight: 800; }
.profile-handle > span:not(.profile-verified) { color: #777d74; font-weight: 700; }
.profile-verified { display: inline-flex; align-items: center; gap: 4px; color: var(--green); font-weight: 800; }
.profile-verified svg { width: 13px; }
.profile-bio { margin: 0 22px 14px; color: #555b51; font-size: 13px; line-height: 1.62; }
.profile-summary > .profile-summary-actions { display: flex; align-items: center; gap: 8px; }
.profile-contact { min-height: 44px; padding: 0 14px; display: flex; align-items: center; gap: 7px; border: 0; border-radius: 11px; background: var(--green); color: #fff; font-size: 12px; font-weight: 800; }
.profile-contact svg { width: 16px; }
.profile-share { width: 44px; height: 44px; display: grid; place-items: center; border: 1px solid var(--line); border-radius: 11px; background: #fff; color: var(--ink); }
.profile-share svg { width: 16px; }
.profile-meta { padding: 0 22px 18px; display: flex; align-items: center; justify-content: space-between; gap: 16px; }
.profile-meta > span { display: inline-flex; align-items: center; gap: 7px; color: var(--muted); font-size: 12.5px; }
.profile-meta > span svg { width: 15px; color: var(--green); }
.profile-socials { display: flex; gap: 10px; color: #5a6056; }
.profile-socials svg { width: 17px; }
.profile-tabs { min-height: 48px; padding: 0 22px; display: flex; align-items: center; gap: 26px; border-top: 1px solid var(--line); border-bottom: 1px solid var(--line); color: #888d85; font-size: 12px; font-weight: 800; }
.profile-tabs strong { height: 48px; display: flex; align-items: center; border-bottom: 2px solid var(--ink); color: var(--ink); }
.profile-grid { padding: 11px; columns: 150px; column-gap: 8px; }
.profile-grid img { width: 100%; height: auto; margin: 0 0 8px; display: block; border-radius: 9px; break-inside: avoid; }

.events-section {
  padding-block: 125px;
  overflow: hidden;
  border-top: 1px solid rgba(80, 51, 105, .1);
  background:
    radial-gradient(circle at 88% 18%, rgba(144, 102, 194, .2), transparent 34%),
    linear-gradient(135deg, #f5ecff, #e8d9f5);
}
.events-layout { display: grid; grid-template-columns: 1fr .72fr; align-items: center; gap: 90px; }
.events-name { margin-bottom: 38px; display: flex; align-items: center; gap: 10px; font-size: 16px; font-weight: 800; }
.events-name img { border-radius: 9px; }
.events-name strong { color: #7655ad; }
.events-eyebrow { color: #80632f; }
.events-copy h2 {
  max-width: 740px;
  margin: 26px 0 22px;
  font-size: clamp(50px, 5.7vw, 76px);
  line-height: .98;
  letter-spacing: -.052em;
}
.events-copy > p:not(.eyebrow) { max-width: 690px; margin: 0; color: #655e69; font-size: 16px; line-height: 1.72; }
.events-points { margin-top: 28px; display: grid; grid-template-columns: repeat(3, 1fr); gap: 9px; }
.events-points span { min-height: 72px; padding: 12px; display: flex; align-items: center; gap: 8px; border: 1px solid rgba(82,56,105,.12); border-radius: 14px; background: rgba(255,255,255,.46); color: #504957; font-size: 12px; font-weight: 800; }
.events-points svg { width: 18px; flex: 0 0 auto; color: #7655ad; }
.events-action { min-height: 50px; margin-top: 25px; padding: 0 17px; display: inline-flex; align-items: center; gap: 9px; border-radius: 13px; background: #7655ad; color: #fff; font-size: 13px; font-weight: 800; text-decoration: none; box-shadow: 0 16px 38px rgba(118,85,173,.22); }
.events-action svg { width: 17px; }

.event-preview { width: 360px; max-width: 100%; margin-inline: auto; padding: 13px; position: relative; border: 1px solid rgba(255,255,255,.68); border-radius: 31px; background: rgba(255,255,255,.76); box-shadow: 0 30px 80px rgba(76,49,102,.2); transform: rotate(3deg); backdrop-filter: blur(12px); }
.event-preview-head { min-height: 61px; padding: 0 9px; display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.event-preview-head > div { display: grid; gap: 3px; }
.event-preview-head small { color: #7c7580; font-size: 12px; text-transform: uppercase; letter-spacing: .06em; }
.event-preview-head strong { font-size: 16px; }
.event-preview-head > span { padding: 6px 9px; border-radius: 999px; background: #e6f1df; color: var(--green); font-size: 12px; font-weight: 800; text-transform: uppercase; }
/* T15: the mockup mirrors the real event wall — dark surface, guest photo tiles. */
.event-preview-wall { display: grid; grid-template-columns: 1fr 1fr; gap: 7px; padding: 7px; border-radius: 22px; background: #16140f; }
.event-preview-wall img { width: 100%; height: 116px; object-fit: cover; border-radius: 12px; display: block; }
.event-preview-wall .event-wall-wide { grid-column: 1 / -1; height: 186px; }
.event-wall-more { position: relative; display: block; }
.event-wall-more em { position: absolute; inset: 0; display: grid; place-items: center; border-radius: 12px; background: rgba(12,11,8,.55); color: #f2ede3; font-style: normal; font-size: 13px; font-weight: 800; letter-spacing: .02em; }
.event-preview-stats { padding: 14px 7px 5px; display: flex; justify-content: space-between; gap: 12px; color: #746d78; font-size: 12px; }
.event-preview-stats span { display: flex; align-items: center; gap: 5px; }
.event-preview-stats strong { color: var(--ink); font-size: 16px; }
.event-preview-stats svg { width: 15px; }
.event-upload-mock { width: 100%; min-height: 46px; margin-top: 11px; display: flex; align-items: center; justify-content: center; gap: 7px; border: 0; border-radius: 13px; background: #7655ad; color: #fff; font-size: 12px; font-weight: 800; }
.event-upload-mock svg { width: 16px; }
.event-preview aside { width: 112px; height: 132px; position: absolute; top: 92px; right: -70px; display: grid; place-items: center; border-radius: 18px; background: #fff; box-shadow: 0 18px 45px rgba(76,49,102,.17); transform: rotate(-9deg); }
.event-preview aside svg { width: 60px; height: 60px; stroke-width: 1.25; }
.event-preview aside span { margin-top: -20px; color: #7d7581; font-size: 12px; font-weight: 800; text-transform: uppercase; }

.pricing-section { padding-block: 125px; border-top: 1px solid var(--line); background: #fff; }
.pricing-preview { display: grid; grid-template-columns: .82fr 1.18fr; align-items: center; gap: clamp(58px, 7vw, 105px); }
.pricing-copy h2 {
  max-width: 580px;
  margin: 26px 0 0;
  font-size: clamp(50px, 5.6vw, 76px);
  line-height: .98;
  letter-spacing: -.052em;
}
.pricing-copy > p:not(.eyebrow) { max-width: 520px; margin: 25px 0 0; color: var(--muted); font-size: 16px; line-height: 1.7; }
.compare-plans-button,
.faq-more-link {
  min-height: 48px;
  margin-top: 26px;
  padding: 0;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  border: 0;
  background: transparent;
  color: var(--green);
  font-size: 14px;
  font-weight: 850;
  text-align: left;
  cursor: pointer;
}
.compare-plans-button svg,
.faq-more-link svg { width: 17px; transition: transform .2s ease; }
.compare-plans-button:hover svg,
.faq-more-link:hover svg { transform: translateX(4px); }
.faq-more-link { text-decoration: none; }
.plan-preview-list { display: grid; gap: 15px; }
.plan-preview {
  min-height: 116px;
  padding: 20px;
  position: relative;
  display: grid;
  grid-template-columns: minmax(150px, .8fr) auto;
  align-items: center;
  gap: 8px 22px;
  border: 1px solid var(--line);
  border-radius: 18px;
  background: var(--paper);
  transform-origin: center;
  transition: transform .35s cubic-bezier(.22,1,.36,1), border-color .35s ease, box-shadow .35s ease, background-color .35s ease;
}
.plan-preview.featured { border-color: #8fa181; background: #f3f7ef; }

@media (hover: hover) and (pointer: fine) {
  .plan-preview:hover {
    z-index: 1;
    border-color: #adb7a5;
    box-shadow: 0 18px 42px rgba(28, 35, 25, .11);
    transform: translateY(-5px) scale(1.018);
  }
  .plan-preview.featured:hover {
    border-color: #718564;
    box-shadow: 0 20px 46px rgba(48, 71, 32, .16);
  }
}

.plan-preview-badge {
  padding: 6px 9px;
  position: absolute;
  top: -10px;
  right: 16px;
  border-radius: 999px;
  background: #d9ae45;
  color: #49370e;
  font-size: 11px;
  font-weight: 900;
  text-transform: uppercase;
}
.plan-preview-name { display: grid; gap: 3px; }
.plan-preview-name h3 { margin: 0; font-size: 17px; }
.plan-preview-name span, .plan-preview-summary { color: var(--muted); font-size: 12px; line-height: 1.45; }
.plan-preview-price { margin: 0; display: flex; align-items: end; justify-content: flex-end; gap: 4px; }
.plan-preview-price strong { font-size: 29px; line-height: 1; letter-spacing: -.045em; font-variant-numeric: tabular-nums; }
.plan-preview-price span { margin-bottom: 2px; color: var(--muted); font-size: 11px; font-weight: 700; }
.plan-preview-summary { min-width: 0; margin: 0; }
.plan-preview-action {
  min-height: 44px;
  padding: 0 14px;
  justify-self: end;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px solid #b9c0b4;
  border-radius: 999px;
  color: var(--ink);
  background: rgba(255,255,255,.55);
  font-size: 12px;
  font-weight: 850;
  line-height: 1;
  text-decoration: none;
  white-space: nowrap;
  transition: color .2s ease, background-color .2s ease, border-color .2s ease, transform .2s ease;
}
.plan-preview-action:hover { border-color: var(--green); color: #fff; background: var(--green); transform: scale(1.025); }
.plan-preview-action.primary { border-color: var(--green); color: #fff; background: var(--green); }
.plan-preview-action.primary:hover { background: #223519; }

.plan-dialog-backdrop {
  padding: 24px;
  position: fixed;
  inset: 0;
  z-index: 1000;
  display: grid;
  place-items: center;
  background: rgba(12,14,11,.68);
  backdrop-filter: blur(8px);
}
.plan-dialog {
  width: min(1180px, 100%);
  max-height: min(900px, calc(100dvh - 48px));
  padding: 28px;
  overflow-y: auto;
  border: 1px solid rgba(255,255,255,.58);
  border-radius: 26px;
  background: #fbfaf7;
  box-shadow: 0 30px 100px rgba(0,0,0,.3);
}
.plan-dialog-header { margin-bottom: 25px; display: flex; align-items: start; justify-content: space-between; gap: 30px; }
.plan-dialog-header h2 { margin: 12px 0 0; font-size: clamp(35px, 4vw, 54px); line-height: 1; letter-spacing: -.045em; }
.plan-dialog-close {
  width: 46px;
  height: 46px;
  flex: 0 0 auto;
  display: grid;
  place-items: center;
  border: 1px solid var(--line);
  border-radius: 50%;
  background: #fff;
  color: var(--ink);
  cursor: pointer;
}
.plan-dialog-close svg { width: 20px; }
.plan-comparison-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px; }
.plan-comparison-grid article {
  min-height: 470px;
  padding: 22px;
  position: relative;
  display: flex;
  flex-direction: column;
  border: 1px solid var(--line);
  border-radius: 19px;
  background: #fff;
}
.plan-comparison-grid article.featured { border-color: var(--green); background: #f1f6ed; box-shadow: 0 18px 45px rgba(48,71,32,.12); }
.comparison-badge {
  position: absolute;
  top: 18px;
  right: 18px;
  color: var(--green);
  font-size: 11px;
  font-weight: 900;
  text-transform: uppercase;
}
.comparison-plan-name { margin: 0; font-size: 17px; font-weight: 850; }
.comparison-price { margin: 35px 0 0; display: flex; align-items: end; gap: 5px; }
.comparison-price strong { font-size: 43px; line-height: .92; letter-spacing: -.06em; font-variant-numeric: tabular-nums; }
.comparison-price span { margin-bottom: 3px; color: var(--muted); font-size: 11px; }
.comparison-description { min-height: 66px; margin: 20px 0 0; color: var(--muted); font-size: 13px; line-height: 1.55; }
.plan-comparison-grid ul { margin: 22px 0; padding: 21px 0 0; display: grid; gap: 12px; border-top: 1px solid var(--line); list-style: none; }
.plan-comparison-grid li { display: flex; align-items: flex-start; gap: 8px; color: #4f554d; font-size: 12px; line-height: 1.45; }
.plan-comparison-grid li svg { width: 15px; height: 15px; flex: 0 0 auto; color: var(--green); }
.comparison-action {
  min-height: 48px;
  margin-top: auto;
  padding: 0 14px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--paper);
  color: var(--ink);
  font-size: 12px;
  font-weight: 850;
  text-decoration: none;
}
.comparison-action.primary { border-color: var(--green); background: var(--green); color: #fff; }
.comparison-action svg { width: 16px; }

/* Account sign-in modal */
.auth-dialog-backdrop {
  padding: 24px;
  position: fixed;
  inset: 0;
  z-index: 1000;
  display: grid;
  place-items: center;
  background: rgba(12,14,11,.68);
  backdrop-filter: blur(8px);
  opacity: 0;
  transition: opacity .26s ease;
}
.auth-dialog-backdrop.is-open { opacity: 1; }
.auth-dialog-backdrop.is-closing { opacity: 0; }
.auth-dialog {
  width: min(860px, 100%);
  min-height: min(602px, calc(100dvh - 48px));
  max-height: min(660px, calc(100dvh - 48px));
  display: grid;
  grid-template-columns: .9fr 1.1fr;
  overflow: hidden;
  border: 1px solid rgba(255,255,255,.58);
  border-radius: 26px;
  background: #fbfaf7;
  box-shadow: 0 30px 100px rgba(0,0,0,.3);
  position: relative;
  transform: scale(.9);
  opacity: 0;
  transition: transform .34s cubic-bezier(.2,.85,.3,1), opacity .26s ease;
}
.auth-dialog-backdrop.is-open .auth-dialog { transform: scale(1); opacity: 1; }
.auth-dialog-backdrop.is-closing .auth-dialog { transform: scale(.95); opacity: 0; }
@media (prefers-reduced-motion: reduce) {
  .auth-dialog-backdrop, .auth-dialog { transition: none; }
}
@media (max-width: 640px) {
  .auth-dialog-backdrop { padding: 10px; }
  /* Outranks the 31px .auth-panel-body h2 rule further down (0,2,1 vs 0,1,1). */
  .auth-dialog .auth-panel-body h2 { font-size: 1.5em; }
}
.auth-visual { position: relative; overflow: hidden; background: var(--ink); }
.auth-visual > img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; opacity: .85; }
.auth-visual::after { content: ""; position: absolute; inset: 0; background: linear-gradient(185deg, rgba(17,19,15,.08) 0%, rgba(17,19,15,.82) 78%); }
.auth-brand { position: relative; z-index: 1; margin: 26px; display: inline-flex; align-items: center; gap: 10px; color: #fff; font-size: 17px; font-weight: 800; letter-spacing: -.02em; text-decoration: none; }
.auth-brand img { width: 34px; height: 34px; }
.auth-quote { position: absolute; z-index: 1; left: 28px; right: 28px; bottom: 28px; }
.auth-quote blockquote { margin: 0; color: #fff; font-family: Georgia, serif; font-size: 21px; line-height: 1.32; }
.auth-quote p { margin: 12px 0 0; color: rgba(255,255,255,.72); font-size: 13px; line-height: 1.55; }
.auth-panel { padding: 30px 32px 34px; display: flex; flex-direction: column; overflow-y: auto; }
.auth-panel-head { display: flex; align-items: start; justify-content: space-between; gap: 18px; }
.auth-dialog-close { position: absolute; z-index: 2; top: 12px; right: 12px; width: 44px; height: 44px; display: grid; place-items: center; border: 0; border-radius: 50%; background: transparent; color: var(--muted); cursor: pointer; transition: background .15s ease, color .15s ease; }
.auth-dialog-close:hover { background: rgba(17,19,15,.07); color: var(--ink); }
.auth-dialog-close svg { width: 19px; }
.auth-panel-body { margin-top: 18px; }
.auth-panel-body h2 { margin: 0; font-family: Georgia, serif; font-weight: 400; font-size: 31px; line-height: 1.06; letter-spacing: -.02em; }
.auth-sub { margin: 12px 0 0; color: var(--muted); font-size: 14px; line-height: 1.62; }
.auth-sub strong { color: var(--ink); font-weight: 700; word-break: break-word; }
.auth-social { margin-top: 22px; display: grid; gap: 10px; }
.auth-social a { min-height: 50px; display: flex; align-items: center; justify-content: center; gap: 11px; border: 1px solid var(--line); border-radius: 14px; background: #fff; color: var(--ink); font: inherit; font-size: 14px; font-weight: 700; text-decoration: none; cursor: pointer; transition: transform .15s ease, border-color .15s ease; }
.auth-social a:hover { transform: translateY(-1px); border-color: rgba(17,19,15,.3); }
.auth-divider { margin: 20px 0; display: flex; align-items: center; gap: 14px; color: #a09e96; font-size: 11px; font-weight: 800; letter-spacing: .1em; text-transform: uppercase; }
.auth-divider::before, .auth-divider::after { content: ""; height: 1px; flex: 1; background: var(--line); }
.auth-form { display: grid; gap: 9px; }
.auth-form label { font-size: 12px; font-weight: 800; color: #42483f; }
.auth-email-input { width: 100%; min-height: 50px; padding: 0 15px; border: 1px solid var(--line); border-radius: 14px; background: #fff; color: var(--ink); font: inherit; font-size: 14px; }
.auth-email-input::placeholder { color: #a8a59d; }
.auth-email-input:focus { outline: none; border-color: var(--green); box-shadow: 0 0 0 3px rgba(48,71,32,.13); }
.auth-submit { min-height: 52px; margin-top: 3px; display: flex; align-items: center; justify-content: center; gap: 9px; border: 0; border-radius: 14px; background: var(--green); color: #fff; font: inherit; font-size: 14px; font-weight: 800; cursor: pointer; transition: transform .15s ease, background .15s ease; }
.auth-submit:hover { transform: translateY(-1px); background: #2a3f1c; }
.auth-submit svg { width: 17px; }
.auth-status { margin: 14px 0 0; padding: 11px 14px; border: 1px solid var(--line); border-radius: 12px; background: rgba(255,255,255,.6); color: #4f554d; font-size: 13px; font-weight: 600; }
.auth-status.is-error { border-color: rgba(196,74,74,.4); background: rgba(196,74,74,.08); color: #a03d3d; }
.auth-submit:disabled, .auth-resend:disabled { opacity: .55; cursor: wait; }
.auth-fineprint { margin: 18px 0 0; color: #9c9a92; font-size: 11.5px; line-height: 1.55; }
/* The 2px top was tuned for the old position, tucked under the code input.
   It now follows the submit button, where 2px read as part of the button.
   14px separates them without floating it away from the action it qualifies —
   the client-login gates override margin themselves (.gal-gate-remember), so
   they keep their own tighter spacing. */
.auth-remember { display: flex; align-items: flex-start; gap: 8px; margin: 14px 0 4px; color: #6d726a; font-size: 12.5px; line-height: 1.5; cursor: pointer; }
.auth-remember-input { margin-top: 2px; accent-color: #304720; }
.auth-fineprint a { color: #5f6a55; }
.auth-code-input { text-align: center; font-size: 26px; font-weight: 800; letter-spacing: .42em; text-indent: .42em; font-variant-numeric: tabular-nums; min-height: 60px; }
.auth-code-input::placeholder { color: #cbc8c0; font-weight: 700; }
.auth-code-foot { margin-top: 20px; display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.auth-code-foot .auth-back { margin-top: 0; }
.auth-resend { padding: 0; border: 0; background: none; color: var(--muted); font: inherit; font-size: 13px; font-weight: 700; cursor: pointer; }
.auth-resend:hover { color: var(--ink); text-decoration: underline; }
.auth-confirm { padding: 6px 0; }
.auth-confirm-badge { width: 56px; height: 56px; display: grid; place-items: center; border-radius: 50%; background: #e6f1df; color: var(--green); }
.auth-confirm-badge svg { width: 25px; }
.auth-confirm h2 { margin: 20px 0 0; }
.auth-back { margin-top: 20px; padding: 0; border: 0; background: none; color: var(--green); font: inherit; font-size: 13px; font-weight: 800; cursor: pointer; }
.auth-back:hover { text-decoration: underline; }
@media (max-width: 760px) {
  .auth-dialog { grid-template-columns: 1fr; min-height: 0; max-height: 92dvh; }
  .auth-visual { display: none; }
  .auth-panel { padding: 22px 20px 26px; }
}

.faq-section { padding-block: 125px; border-top: 1px solid var(--line); background: #fff; }
.faq-layout { display: grid; grid-template-columns: .72fr 1.28fr; align-items: start; gap: 100px; }
.faq-heading { position: sticky; top: 40px; }
.faq-heading h2 { font-size: clamp(48px, 5vw, 68px); }
.faq-heading > p { max-width: 390px; margin-top: 22px; }
.faq-list { border-top: 1px solid var(--line); }
.faq-list article { border-bottom: 1px solid var(--line); }
.faq-list h3 { margin: 0; }
.faq-list h3 button { width: 100%; min-height: 82px; padding: 18px 4px; display: flex; align-items: center; justify-content: space-between; gap: 20px; border: 0; background: transparent; color: var(--ink); text-align: left; font-size: 18px; font-weight: 800; }
.faq-list h3 button svg { width: 20px; flex: 0 0 auto; color: #777c74; transition: transform .2s ease; }
.faq-list article.open h3 button svg { transform: rotate(180deg); }
.faq-list article > div { overflow: hidden; }
.faq-list article p { max-width: 690px; margin: 0; padding: 0 46px 25px 4px; color: var(--muted); font-size: 15px; line-height: 1.7; }

footer { color: #fff; background: var(--ink); }
.footer-main {
  padding-block: 70px 62px;
  display: grid;
  grid-template-columns: minmax(260px, 1.45fr) repeat(3, minmax(140px, .72fr));
  align-items: start;
  gap: clamp(38px, 5vw, 78px);
}
.footer-lead { max-width: 410px; }
.footer-lead .brand { width: max-content; }
.footer-lead > p { margin: 25px 0 0; color: rgba(255,255,255,.54); font-size: 14px; line-height: 1.7; }
.footer-account-link {
  min-height: 45px;
  margin-top: 24px;
  display: inline-flex;
  align-items: center;
  gap: 9px;
  color: rgba(255,255,255,.82);
  font-size: 13px;
  font-weight: 800;
  text-decoration: none;
}
.footer-account-link svg { width: 19px; }
.footer-column { display: grid; align-content: start; gap: 13px; }
.footer-column strong { margin-bottom: 5px; color: #fff; font-size: 13px; letter-spacing: .035em; }
.footer-column a, .footer-column .pm-consent-link { width: fit-content; color: rgba(255,255,255,.56); font-size: 13px; line-height: 1.45; text-decoration: none; text-align: left; }
.footer-column a:hover, .footer-column .pm-consent-link:hover, .footer-account-link:hover { color: #fff; }
.footer-bottom { padding-block: 19px 28px; display: flex; justify-content: space-between; border-top: 1px solid rgba(255,255,255,.1); color: rgba(255,255,255,.36); font-size: 12px; text-transform: uppercase; letter-spacing: .07em; }

@media (max-width: 900px) {
  :root { --shell: min(100vw - 40px, 840px); }
  .site-header { right: 20px; left: 20px; }
  .hero { min-height: 100vh; min-height: 100svh; }
  .hero-gallery-note { right: 20px; width: 265px; }
  .gallery-intro, .portfolio-layout, .events-layout, .pricing-preview, .faq-layout { grid-template-columns: 1fr; gap: 50px; }
  .events-copy { max-width: 780px; }
  .pricing-copy { max-width: 670px; }
  .plan-comparison-grid { grid-template-columns: repeat(2, 1fr); }
  .faq-heading { position: static; }
  .footer-main { grid-template-columns: 1.25fr repeat(3, 1fr); gap: 35px; }
}

@media (max-width: 700px) {
  :root { --shell: calc(100vw - 28px); }
  .site-header { top: 10px; right: 14px; left: 14px; min-height: 54px; }
  .pm-announce ~ div .site-header { top: 52px; }
  .pm-announce ~ div .site-header.is-scrolled { top: 0; right: 0; left: 0; }
  .desktop-nav { display: none; }
  .account-link { display: none; }
  .menu-button { margin-left: auto; }
  .menu-button { width: 44px; height: 44px; padding: 0; display: grid; place-items: center; border: 1px solid rgba(255,255,255,.18); border-radius: 12px; background: rgba(255,255,255,.08); color: #fff; }
  .menu-button svg { width: 20px; }
  .mobile-nav { padding: 12px; position: absolute; top: calc(100% + 8px); right: 0; left: 0; display: grid; border: 1px solid rgba(255,255,255,.14); border-radius: 16px; background: rgba(13,15,12,.97); box-shadow: 0 20px 60px rgba(0,0,0,.24); }
  .mobile-nav a { min-height: 51px; padding: 0 9px; display: flex; align-items: center; justify-content: space-between; border-bottom: 1px solid rgba(255,255,255,.09); color: rgba(255,255,255,.78); font-size: 13px; font-weight: 800; text-decoration: none; }
  .mobile-nav a:last-child { border-bottom: 0; }
  .mobile-nav svg { width: 17px; }
  .mobile-nav a span { display: flex; align-items: center; gap: 9px; }
  .mobile-nav a span svg { width: 19px; }
  .hero { min-height: 100vh; min-height: 100svh; padding: 100px 0 150px; align-items: end;}
  .hero::before { content: ""; position: absolute; inset: 0; background: linear-gradient(180deg,rgba(13,15,12,.65),rgba(13,15,12,.22) 38%,rgba(13,15,12,.88) 82%); }
  .hero h1 { margin-top: 35px; font-size: clamp(55px,16vw,74px); line-height: .92; letter-spacing: -.055em; }
  .hero-lead { font-size: 16px; }
  .hero-actions { display: grid; gap: 8px; }
  .hero-actions .button { width: 100%; }
  .hero-actions .text-action { justify-content: center; }
  .hero-checks { gap: 10px 15px; }
  .hero-checks span:last-child { display: none; }
  .hero-gallery-note { display: none; }
  .hero-credit-mark { display: block; }
  .gallery-section, .portfolio-section, .events-section, .pricing-section, .faq-section { padding-block: 50px; }
  .gallery-intro h2, .portfolio-copy h2, .events-copy h2, .pricing-copy h2, .faq-heading h2 { font-size: 44px; }
  .gallery-browser { width: calc(100vw - 20px); margin-top: 42px; margin-left: 10px; border-radius: 18px; }
  .browser-bar small { max-width: 190px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .browser-cover { height: 240px; }
  .browser-cover-copy strong { font-size: 26px; }
  .browser-toolbar { padding: 12px 14px; }
  .browser-toolbar-actions span { display: none; }
  .browser-grid { columns: 140px; }
  .trust-row { grid-template-columns: 1fr; padding-top: 26px; }
  .trust-row span { justify-content: flex-start; padding: 13px 6px; }
  .trust-row span + span { border-left: 0; border-top: 1px solid var(--line); }
  .profile-summary { padding: 18px 14px 12px; grid-template-columns: auto 1fr; }
  .profile-summary > .profile-summary-actions { grid-column: 1 / -1; justify-content: center; }
  .profile-meta { padding: 0 14px 14px; }
  .profile-tabs { gap: 18px; overflow-x: auto; }
  .profile-grid { columns: 130px; }
  .profile-grid img:last-child { display: none; }
  .events-name { margin-bottom: 30px; }
  .events-points { grid-template-columns: 1fr; }
  .events-points span { min-height: 56px; }
  .events-action { width: 100%; justify-content: center; }
  .event-preview { width: min(330px, calc(100vw - 72px)); }
  .event-preview > img { height: 285px; }
  .event-preview aside { width: 94px; height: 112px; right: -24px; }
  .event-preview aside svg { width: 50px; height: 50px; }
  .pricing-preview { gap: 42px; }
  .plan-preview { min-height: 104px; padding: 17px; grid-template-columns: 1fr auto; }
  .plan-preview-name h3 { font-size: 16px; }
  .plan-preview-price strong { font-size: 25px; }
  .plan-dialog-backdrop { padding: 0; align-items: end; }
  .plan-dialog { width: 100%; max-height: 92dvh; padding: 22px 14px 28px; border-radius: 24px 24px 0 0; }
  .plan-dialog-header { position: sticky; top: -22px; z-index: 2; margin: -22px -14px 20px; padding: 20px 14px 15px; background: rgba(251,250,247,.96); backdrop-filter: blur(10px); }
  .plan-dialog-header h2 { font-size: 34px; }
  .plan-comparison-grid { grid-template-columns: 1fr; }
  .plan-comparison-grid article { min-height: 0; }
  .comparison-description { min-height: 0; }
  .faq-list h3 button { min-height: 76px; font-size: 16px; }
  .footer-main { padding-block: 56px 44px; grid-template-columns: 1fr 1fr; gap: 38px 24px; }
  .footer-lead { max-width: 100%; grid-column: 1 / -1; padding-bottom: 5px; }
  .footer-column:last-child { grid-column: 1 / -1; grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .footer-column:last-child strong { grid-column: 1 / -1; }
  .footer-bottom { display: grid; gap: 6px; }
}

@media (max-width: 420px) {
  .hero h1 { font-size: 52px; }
  .footer-main { grid-template-columns: 1fr; }
  .footer-lead, .footer-column:last-child { grid-column: auto; }
  .footer-column:last-child { grid-template-columns: 1fr; }
  .footer-column:last-child strong { grid-column: auto; }
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
  }
}


[hidden] { display: none !important; }

/* ===================== Studio dashboard ===================== */
.ic { width: 20px; height: 20px; display: block; }
.dash-body { background: var(--paper); }
.dash-shell { display: grid; grid-template-columns: 266px 1fr; min-height: 100vh; }

.dash-sidebar { position: sticky; top: 0; height: 100vh; display: flex; flex-direction: column; padding: 22px 16px; border-right: 1px solid var(--line); background: #fff; }
.dash-brand { display: flex; align-items: center; gap: 10px; margin: 4px 8px 24px; color: var(--ink); font-size: 20px; font-weight: 850; letter-spacing: -.03em; text-decoration: none; }
.dash-brand img { width: 34px; height: 34px; }
.dash-nav { display: grid; gap: 4px; }
.dash-nav-item { display: flex; align-items: center; gap: 12px; padding: 11px 13px; border-radius: 13px; color: #4f554d; font-size: 14.5px; font-weight: 700; text-decoration: none; transition: background .15s ease, color .15s ease; }
.dash-nav-item .ic { width: 19px; height: 19px; color: #8b9183; }
.dash-nav-item:hover { background: rgba(17,19,15,.04); color: var(--ink); }
.dash-nav-item.active { background: #eef3e9; color: var(--green); }
.dash-nav-item.active .ic { color: var(--green); }
.dash-side-foot { margin-top: auto; display: grid; gap: 9px; }
.dash-account { display: flex; align-items: center; gap: 11px; padding: 10px; border: 1px solid var(--line); border-radius: 14px; }
.dash-account img { width: 40px; height: 40px; border-radius: 50%; object-fit: cover; }
.dash-account strong { display: block; font-size: 14px; }
.dash-account small { color: var(--muted); font-size: 12px; }
.dash-logout { display: flex; align-items: center; gap: 10px; padding: 11px 13px; border: 1px solid var(--line); border-radius: 13px; color: var(--ink); font-size: 14px; font-weight: 700; text-decoration: none; transition: background .15s ease, border-color .15s ease, color .15s ease; }
.dash-logout .ic { width: 18px; height: 18px; color: var(--muted); transition: color .15s ease; }
.dash-logout:hover { border-color: #e7c4c0; background: #fdf3f2; color: #a4382f; }
.dash-logout:hover .ic { color: #a4382f; }

.dash-main { min-width: 0; display: flex; flex-direction: column; }
.dash-topbar { position: sticky; top: 0; z-index: 5; display: flex; align-items: center; justify-content: space-between; gap: 16px; padding: 18px 30px; border-bottom: 1px solid var(--line); background: rgba(244,241,235,.85); backdrop-filter: blur(10px); }
/* margin-right:auto keeps the logo and title together on the left and pushes
   the actions right. Without it, space-between strands the title mid-header,
   miles from the logo it belongs to. */
.dash-topbar h1 { margin: 0; margin-right: auto; font-family: Georgia, serif; font-weight: 400; font-size: 26px; letter-spacing: -.02em; }
.dash-topbar-actions { display: flex; align-items: center; gap: 10px; }

/* Account dropdown (topbar) — only surfaced on mobile, where the sidebar is hidden */
.dash-account-menu { display: none; position: relative; }
.dash-account-btn { display: grid; place-items: center; width: 44px; height: 44px; padding: 0; border: 1px solid var(--line); border-radius: 50%; background: #fff; color: var(--ink); cursor: pointer; overflow: hidden; }
.dash-account-btn img { width: 100%; height: 100%; object-fit: cover; }
/* Phone-only rows inside the account menu (desktop reaches these elsewhere) */
.dash-pop-phone-only { display: none; }
/* Logo beside the page title — hidden on desktop, where the sidebar has one */
.dash-topbar-logo { display: none; }
.pm-sr-only { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0; }
/* Gallery filter: pills on desktop, one native select on a phone */
/* margin-bottom matches the card grid's own 16px gap, so the filter sits in the
   same rhythm instead of flush against the first card. The native arrow cannot
   be positioned, so appearance:none plus a background chevron gives it real
   breathing room from the edge (16px, with padding to match). */
.dash-filter-select { display: none; margin-bottom: 16px; }
.dash-filter-select select { width: 100%; min-height: 46px; padding: 11px 44px 11px 14px; border: 1px solid var(--line); border-radius: 12px; color: var(--ink); font: inherit; font-size: 16px; font-weight: 600; appearance: none; -webkit-appearance: none; background-color: #fff; background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2342483f' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E"); background-repeat: no-repeat; background-position: right 16px center; background-size: 15px; }
.dash-filter-select select:focus-visible { outline: none; border-color: var(--green); box-shadow: 0 0 0 3px rgba(48,71,32,.12); }
.dash-account-btn .ic { width: 20px; height: 20px; }
/* Holds the whole account list (profile, billing, invites, admin, log out), so
   it is capped to the viewport and scrolls rather than running off a short phone. */
.dash-account-pop { position: absolute; top: calc(100% + 8px); right: 0; z-index: 60; min-width: 220px; max-height: calc(100vh - 84px); overflow-y: auto; display: grid; gap: 6px; padding: 8px; border: 1px solid var(--line); border-radius: 14px; background: #fff; box-shadow: 0 18px 50px rgba(0,0,0,.16); }
.dash-account-pop[hidden] { display: none; }
.dash-account-pop-head { display: flex; align-items: center; gap: 11px; padding: 8px 10px 10px; border-bottom: 1px solid var(--line); margin-bottom: 4px; }
.dash-account-pop-head img { width: 40px; height: 40px; border-radius: 50%; object-fit: cover; flex: none; }
.dash-account-pop-head strong { display: block; font-size: 14px; }
.dash-account-pop-head small { color: var(--muted); font-size: 12px; }
.dash-account-pop-link { display: flex; align-items: center; gap: 10px; padding: 10px; border-radius: 10px; color: var(--ink); font-size: 14px; font-weight: 700; text-decoration: none; }
.dash-account-pop-link .ic { width: 18px; height: 18px; color: var(--muted); }
.dash-account-pop-link:hover { background: rgba(17, 19, 15, 0.05); }
.dash-account-pop-link.danger:hover { background: #fdf3f2; color: #a4382f; }
.dash-account-pop-link.danger:hover .ic { color: #a4382f; }
/* T15: menu entries rendered as proper buttons (owner: bare links looked broken on mobile) */
.dash-account-pop-btn { display: flex; align-items: center; justify-content: center; gap: 9px; min-height: 44px; padding: 0 14px; border: 1px solid var(--line); border-radius: 12px; background: #fff; color: var(--ink); font-size: 13.5px; font-weight: 800; text-decoration: none; transition: background .15s ease, border-color .15s ease; }
.dash-account-pop-btn .ic { width: 16px; height: 16px; }
.dash-account-pop-btn:hover { background: rgba(17,19,15,.05); border-color: #cfc9bd; }
/* Sits apart from the navigation entries above it — leaving is not a destination. */
.dash-account-pop-btn.danger { color: #a4382f; border-color: rgba(164,56,47,.35); margin-top: 4px; }
.dash-account-pop-btn.danger:hover { background: #fdf3f2; }
.dash-account-pop .dash-account-pop-btn + .dash-account-pop-btn { margin-top: 6px; }
.dash-content { padding: 26px 30px 90px; }

.dash-btn { display: inline-flex; align-items: center; justify-content: center; gap: 8px; min-height: 44px; padding: 0 16px; border: 1px solid transparent; border-radius: 12px; font: inherit; font-size: 13.5px; font-weight: 800; text-decoration: none; cursor: pointer; transition: transform .15s ease, background .15s ease, border-color .15s ease; }
.dash-btn .ic { width: 16px; height: 16px; }
.dash-btn:hover { transform: translateY(-1px); }
.dash-btn-primary { background: var(--green); color: #fff; }
.dash-btn-primary:hover { background: #2a3f1c; }
.dash-btn-light { background: #fff; color: var(--ink); border-color: var(--line); }
.dash-btn-light:hover { border-color: rgba(17,19,15,.25); }

.dash-card { border: 1px solid var(--line); border-radius: 18px; background: #fff; box-shadow: 0 12px 36px rgba(17,19,15,.05); }
.dash-section { display: none; }
.dash-section.active { display: block; animation: dashFade .25s ease; }
@keyframes dashFade { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
.dash-section-head { margin-bottom: 18px; }

.dash-welcome { position: relative; overflow: hidden; display: flex; align-items: center; justify-content: space-between; gap: 24px; padding: 30px 32px; border-radius: 22px; background: linear-gradient(120deg, #243218, #314620 58%, #3a5226); color: #fff; }
.dash-welcome-copy { position: relative; z-index: 2; max-width: 58%; }
.dash-welcome-art { position: absolute; top: 0; right: 0; bottom: 0; width: 48%; }
.dash-welcome-art img { width: 100%; height: 100%; object-fit: cover; display: block; }
.dash-welcome-art::before { content: ""; position: absolute; inset: 0; z-index: 1; background: linear-gradient(90deg, #354b23 0%, rgba(53,75,35,.35) 45%, rgba(53,75,35,0) 100%); }
@media (max-width: 720px) {
  .dash-welcome-copy { max-width: 100%; }
  .dash-welcome-art { width: 100%; }
  .dash-welcome-art::before { background: rgba(36,50,24,.82); }
}
.dash-welcome .eyebrow { color: var(--green-light); }
.dash-welcome h2 { margin: 8px 0 10px; font-family: Georgia, serif; font-weight: 400; font-size: 34px; letter-spacing: -.02em; }
.dash-welcome p:not(.eyebrow) { margin: 0; max-width: 560px; color: rgba(255,255,255,.74); font-size: 15px; line-height: 1.6; }

/* Admin redesign (T7): underline tab bar, grouped setting cards, aligned rows. */
.adm-tabs { display: flex; gap: 2px; margin: 0 0 22px; border-bottom: 1px solid var(--line); overflow-x: auto; scrollbar-width: none; }
.adm-tabs::-webkit-scrollbar { display: none; }
.adm-tab { flex: 0 0 auto; min-height: 44px; display: inline-flex; align-items: center; padding: 10px 14px 12px; border-bottom: 2px solid transparent; margin-bottom: -1px; color: var(--muted); font-size: 13.5px; font-weight: 700; text-decoration: none; white-space: nowrap; }
.adm-tab:hover { color: var(--ink); }
.adm-tab.active { color: var(--green); border-bottom-color: var(--green); }
.adm-setting-jumps { display: flex; gap: 8px; margin: -6px 0 18px; overflow-x: auto; scrollbar-width: none; }
.adm-setting-jumps::-webkit-scrollbar { display: none; }
.adm-setting-jumps a { flex: 0 0 auto; min-height: 44px; display: inline-flex; align-items: center; padding: 0 15px; border: 1px solid var(--line); border-radius: 999px; background: #fff; color: var(--muted); font-size: 13px; font-weight: 750; text-decoration: none; }
.adm-setting-jumps a:hover { border-color: rgba(17,19,15,.25); color: var(--ink); }
.adm-settings-anchor { scroll-margin-top: 126px; }
.adm-card { padding: 0; overflow: hidden; margin-bottom: 16px; }
.adm-card-head { padding: 20px 24px 14px; border-bottom: 1px solid var(--line); }
.adm-card-head h3 { margin: 0 0 3px; font-size: 16px; }
.adm-card-head p { margin: 0; color: var(--muted); font-size: 13px; line-height: 1.5; }
.adm-row { display: grid; grid-template-columns: minmax(0, 1fr) minmax(170px, 250px); gap: 4px 24px; align-items: center; padding: 12px 24px; border-bottom: 1px solid #f0ede5; }
.adm-row:last-of-type { border-bottom: 0; }
.adm-row-label span { display: block; font-size: 14px; font-weight: 600; color: var(--ink); }
.adm-row-label small { color: var(--muted); font-size: 12px; }
.adm-row-control input, .adm-row-control select { width: 100%; min-height: 44px; padding: 9px 12px; border: 1px solid var(--line); border-radius: 10px; background: #fff; color: var(--ink); font: inherit; font-size: 14px; }
.adm-row-control input:focus, .adm-row-control select:focus { outline: none; border-color: var(--green); box-shadow: 0 0 0 3px rgba(48,71,32,.12); }
.adm-card-foot { display: flex; justify-content: flex-end; padding: 13px 24px; background: #fafaf7; border-top: 1px solid var(--line); }
.adm-tiergrid { display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); }
.adm-tier { border-right: 1px solid #f0ede5; min-width: 0; }
.adm-tier:last-child { border-right: 0; }
.adm-tier h4 { margin: 0; padding: 12px 24px; font-size: 12px; text-transform: uppercase; letter-spacing: .06em; color: var(--muted); background: #fafaf7; border-bottom: 1px solid #f0ede5; }
.adm-tier .adm-row { grid-template-columns: minmax(0, 1fr); padding: 10px 24px; }
/* Consistent tables across every admin tab */
[data-section="admin"] .dash-table th { font-size: 11.5px; text-transform: uppercase; letter-spacing: .05em; color: var(--muted); }
[data-section="admin"] .dash-table tbody tr:hover { background: #fafaf7; }
@media (max-width: 700px) {
  .adm-row { grid-template-columns: 1fr; }
  .adm-card-head, .adm-row, .adm-card-foot, .adm-tier h4 { padding-left: 16px; padding-right: 16px; }
  /* The tier grid collapses to one column here, so a RIGHT border separates
     nothing — Free/Starter/Pro/Studio stacked with no divider between them.
     Move the rule to the edge they actually meet on. */
  .adm-tier { border-right: 0; border-bottom: 1px solid #f0ede5; }
  .adm-tier:last-child { border-bottom: 0; }
  .adm-setting-jumps { position: sticky; top: 76px; z-index: 4; margin: -6px -16px 18px; padding: 8px 16px; background: rgba(244,241,235,.96); backdrop-filter: blur(10px); }
}

/* Create-modal access picker (T5/T10 — the server generates the code). */
.dash-access input { accent-color: var(--green); }

/* Editor top-level view nav (hash-routed) + access + delivery log + design controls */
.ed-chrome { position: sticky; top: 0; z-index: 20; background: rgba(255,255,255,.86); -webkit-backdrop-filter: blur(14px); backdrop-filter: blur(14px); border-bottom: 1px solid var(--line); }
.ed-nav { display: flex; gap: 2px; padding: 0 clamp(16px, 3vw, 30px); overflow-x: auto; scrollbar-width: none; }
.ed-nav::-webkit-scrollbar { display: none; }
.ed-nav-tab { display: flex; align-items: center; justify-content: center; gap: 7px; min-height: 46px; padding: 12px 15px; border: 0; border-bottom: 2.5px solid transparent; background: none; color: var(--muted); font: inherit; font-size: 13.5px; font-weight: 700; white-space: nowrap; cursor: pointer; }
.ed-nav-tab .ic { flex: 0 0 auto; width: 17px; height: 17px; }
.ed-nav-tab:hover { color: var(--ink); }
.ed-nav-tab.active { color: var(--green); border-bottom-color: var(--green); }
.ed-event .ed-nav-tab.active { color: #7655ad; border-bottom-color: #7655ad; }
/* Unsaved-design marker. Amber, not red: this is "you have work in progress",
   not an error. Visible from any tab, which is the point — on a phone the apply
   bar is inside the preview sheet, so this is what says there is something to
   apply at all. aria-live text is not needed: the dot mirrors state the apply
   controls already announce when the sheet opens. */
.ed-nav-tab { position: relative; }
.ed-nav-tab.is-dirty::after { content: ""; position: absolute; top: 9px; right: 8px; width: 8px; height: 8px; border-radius: 50%; background: #e2a52b; box-shadow: 0 0 0 2px #fff; }
.ed-view { display: none; }
.ed-view.active { display: block; }
.ed-access { display: grid; gap: 9px; padding: 15px 0 0; border-top: 1px solid var(--line); margin-top: 16px; }
.ed-access > span { display: grid; gap: 2px; }
.ed-access small { color: var(--muted); }
.ed-access-code { display: inline-flex; align-items: center; gap: 10px; justify-self: start; padding: 10px 16px; border: 1px dashed var(--green); border-radius: 12px; background: #eef3e9; color: var(--green); font-family: Consolas, Menlo, monospace; font-size: 19px; font-weight: 700; letter-spacing: 3px; }
.ed-access-actions { display: flex; flex-wrap: wrap; gap: 8px; }
.ed-sendlog { display: grid; gap: 6px; padding: 14px 0 0; border-top: 1px solid var(--line); margin-top: 16px; }
.ed-sendlog strong { font-size: 13px; }
.ed-sendlog small { color: var(--muted); font-size: 12.5px; line-height: 1.5; overflow-wrap: anywhere; }
.ed-design-group { display: grid; gap: 8px; padding: 13px 0; border-bottom: 1px solid #f0ede5; }
.ed-design-group:last-of-type { border-bottom: 0; }
.ed-design-group > strong { font-size: 13.5px; color: var(--ink); }
.ed-design-opts { display: flex; flex-wrap: wrap; gap: 7px; }
.ed-design-opts label { display: inline-flex; align-items: center; gap: 7px; padding: 8px 13px; border: 1.5px solid var(--line); border-radius: 999px; background: #fff; font-size: 12.5px; font-weight: 700; color: #42483f; cursor: pointer; transition: border-color .15s ease; }
.ed-design-opts label:has(input:checked) { border-color: var(--green); background: #eef3e9; color: var(--green); }
.ed-design-opts input { position: absolute; opacity: 0; pointer-events: none; }
.ed-design-swatch { width: 15px; height: 15px; border-radius: 50%; border: 1px solid rgba(0,0,0,.15); }

/* Delivered soft-lock bar (T5) */
.ed-locked-bar { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 12px; margin: 0 0 18px; padding: 14px 18px; border: 1px solid #e4dbbf; border-radius: 14px; background: #f4efdf; color: #5c522f; font-size: 13.5px; }
.ed-locked-bar strong { color: #4a4226; }
.ed-locked-bar.is-unlocked { border-color: #c9d8bd; background: #eef3e9; color: #3f5330; }
.ed-locked-bar.is-unlocked strong { color: var(--green); }
.ed-settings-form .dash-btn-primary { margin-bottom: 15px; }

/* Galleries filter pills + archive states (T4) */
.dash-filter { display: flex; flex-wrap: wrap; gap: 8px; margin: 0 0 16px; }
.dash-filter-pill { min-height: 44px; padding: 10px 16px; border: 1px solid var(--line); border-radius: 999px; background: #fff; color: var(--muted); font: inherit; font-size: 13px; font-weight: 700; cursor: pointer; transition: background .15s ease, color .15s ease; }
.dash-filter-pill:hover { color: var(--ink); }
.dash-filter-pill.active { background: var(--green); border-color: var(--green); color: #fff; }
.dash-gcard.is-archived { opacity: .72; }
.dash-archived-badge { background: #e4e0d6 !important; color: #6d7466 !important; }
.dash-closed-badge { background: #f4e9d7 !important; color: #9a7b16 !important; }
.dash-delivered-badge { background: #e6f1df !important; color: #3f7d2f !important; }
.dash-locked-badge { background: #f4efdf !important; color: #7a6a34 !important; }

/* Action centre (R3) */
.dash-announce { margin-top: 14px; padding: 12px 18px; border-radius: 14px; background: #f4efdf; border: 1px solid #e4dbbf; color: #5c522f; font-size: 13.5px; font-weight: 600; }
.dash-actions { margin-top: 14px; display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: 14px; }
.dash-action { position: relative; display: grid; gap: 6px; align-content: start; padding: 20px; }
.dash-action-ic { width: 36px; height: 36px; display: grid; place-items: center; border-radius: 50%; background: #eef3e9; color: var(--green); margin-bottom: 4px; }
.dash-action-ic .ic { width: 16px; height: 16px; }
.dash-action strong { font-size: 14.5px; color: var(--ink); padding-right: 42px; }
.dash-action small { color: var(--muted); font-size: 12.5px; line-height: 1.5; }
.dash-action-cta { margin-top: 8px; }
.dash-action-dismiss { position: absolute; top: 4px; right: 4px; width: 44px; height: 44px; display: grid; place-items: center; border: 0; border-radius: 50%; background: transparent; color: var(--muted); cursor: pointer; }
.dash-action-dismiss:hover { background: #f0ece4; color: var(--ink); }
.dash-action-dismiss .ic { width: 14px; height: 14px; }
.dash-action-progress { margin-top: 4px; }
.dash-action-pct { color: var(--muted); }
.dash-actions-restore { margin-top: 10px; border: 0; background: none; padding: 0; cursor: pointer; }
.dash-allset { margin: 18px 2px 0; color: var(--muted); font-size: 14px; }
.dash-panel-solo { margin-top: 14px; }

.dash-stats { margin-top: 18px; display: grid; grid-template-columns: repeat(4, 1fr); gap: 16px; align-items: stretch; }
.dash-stat { padding: 20px; display: flex; flex-direction: column; }
.dash-stat-top { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.dash-stat-top span { color: var(--muted); font-size: 13px; font-weight: 700; }
.dash-stat-ic { width: 36px; height: 36px; display: grid; place-items: center; border-radius: 11px; background: #eef3e9; color: var(--green); }
.dash-stat-ic .ic { width: 18px; height: 18px; }
.dash-stat strong { margin: 16px 0 4px; font-size: 38px; font-weight: 850; line-height: 1; letter-spacing: -.04em; font-variant-numeric: tabular-nums; }
.dash-stat-note { color: var(--muted); font-size: 12.5px; font-weight: 600; }
.dash-stat-note.up { color: var(--green); }

/* Empty-gallery hero: a photographic invitation instead of a bare panel. */
.dash-empty-hero { display: grid; grid-template-columns: 1.1fr .9fr; overflow: hidden; }
.dash-empty-hero-art { position: relative; min-height: 230px; }
.dash-empty-hero-art img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.dash-empty-hero-copy { padding: 34px 32px; display: flex; flex-direction: column; align-items: flex-start; justify-content: center; gap: 4px; }
.dash-empty-hero-copy h3 { margin: 0; font-family: Georgia, serif; font-weight: 400; font-size: 26px; letter-spacing: -.02em; }
.dash-empty-hero-copy p { margin: 4px 0 16px; color: var(--muted); font-size: 14px; line-height: 1.65; max-width: 44ch; }
@media (max-width: 720px) {
  .dash-empty-hero { grid-template-columns: 1fr; }
  .dash-empty-hero-art { min-height: 150px; order: -1; }
  .dash-empty-hero-copy { padding: 22px 20px; }
}

/* Settings: full content width like every other section (the 760px
   .dash-settings cap stays for the profile forms only), two columns on wide
   screens — Sign-in & security right, Danger zone under Account on the left;
   stacks back in DOM order on mobile. */
[data-section="settings"] .dash-settings { max-width: none; }
@media (min-width: 1100px) {
  [data-section="settings"] .dash-settings { grid-template-columns: 1fr 1fr; align-items: start; }
  [data-section="settings"] .dash-settings > .dash-settings-group:nth-child(2) { grid-column: 2; grid-row: 1 / span 2; }
  [data-section="settings"] .dash-settings > .dash-danger-zone { grid-column: 1; grid-row: 2; }
}

/* Invites (referral programme) section */
.dash-inv-hero { display: grid; grid-template-columns: 1.12fr .88fr; overflow: hidden; border-radius: 22px; background: linear-gradient(120deg, #243218, #314620 58%, #3a5226); color: #fff; }
.dash-inv-hero-copy { padding: 32px 36px 30px; }
.dash-inv-hero-copy .eyebrow { color: var(--green-light); }
.dash-inv-hero-copy h2 { margin: 8px 0 12px; font-family: Georgia, serif; font-weight: 400; font-size: 40px; line-height: 1.04; letter-spacing: -.02em; }
.dash-inv-hero-copy > p:not(.eyebrow):not(.dash-inv-hero-note) { margin: 0 0 20px; max-width: 52ch; color: rgba(255,255,255,.76); font-size: 15px; line-height: 1.65; }
.dash-inv-hero-copy strong { color: #fff; }
.dash-inv-linkrow { display: flex; gap: 9px; flex-wrap: wrap; }
.dash-inv-linkrow input { flex: 1; min-width: 210px; min-height: 46px; padding: 0 14px; border: 1px solid rgba(255,255,255,.28); border-radius: 12px; background: rgba(255,255,255,.09); color: #fff; font-size: 13.5px; }
.dash-inv-copy { background: #fff; border-color: #fff; color: var(--ink); }
.dash-inv-copy:hover { background: var(--green-light); border-color: var(--green-light); }
.dash-inv-hero-note { margin: 12px 0 0; color: rgba(255,255,255,.55); font-size: 12.5px; line-height: 1.6; max-width: 56ch; }
.dash-inv-hero-art { position: relative; min-height: 260px; }
.dash-inv-hero-art img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.dash-inv-hero-art::before { content: ""; position: absolute; inset: 0; z-index: 1; background: linear-gradient(90deg, #314620 0%, rgba(49,70,32,0) 48%); }
.dash-inv-steps { margin-top: 14px; display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px; }
.dash-inv-step { position: relative; padding: 22px 24px; }
.dash-inv-step-num { position: absolute; top: 14px; right: 20px; font-family: Georgia, serif; font-size: 44px; line-height: 1; color: rgba(17,19,15,.1); }
.dash-inv-step-ic { width: 52px; height: 52px; display: grid; place-items: center; border-radius: 16px; margin-bottom: 14px; }
.dash-inv-step-ic svg { width: 24px; height: 24px; }
.dash-inv-step-ic.sage { background: #eef3e9; color: var(--green); }
.dash-inv-step-ic.sand { background: #f5edda; color: #8a6d3b; }
.dash-inv-step-ic.clay { background: #f6e9e2; color: #a05c3b; }
.dash-inv-step h4 { margin: 0 0 6px; font-size: 15.5px; font-weight: 800; letter-spacing: -.01em; }
.dash-inv-step p { margin: 0; color: var(--muted); font-size: 13.5px; line-height: 1.62; }
.dash-inv-stats { margin: 14px 0; display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px; }
.dash-inv-rules { margin: 0; padding: 0; list-style: none; display: grid; gap: 12px; }
.dash-inv-rules li { display: flex; gap: 11px; color: var(--muted); font-size: 13.5px; line-height: 1.62; }
.dash-inv-rules li strong { color: var(--ink); }
.dash-inv-rules svg { flex: 0 0 auto; width: 16px; height: 16px; margin-top: 3px; color: var(--green); }
@media (max-width: 960px) {
  .dash-inv-hero { grid-template-columns: 1fr; }
  .dash-inv-hero-art { order: -1; min-height: 170px; }
  .dash-inv-hero-art::before { background: linear-gradient(0deg, #243218 0%, rgba(36,50,24,0) 55%); }
  .dash-inv-hero-copy { padding: 26px 24px; }
  .dash-inv-hero-copy h2 { font-size: 31px; }
  .dash-inv-steps, .dash-inv-stats { grid-template-columns: 1fr; }
}

.dash-grid { margin-top: 14px; display: grid; grid-template-columns: 1.6fr 1fr; gap: 14px; }
.dash-panel { padding: 22px 24px; }
/* Heading on the left, an action/search on the right — but the pair must wrap
   rather than squeeze: at phone width the two columns forced .dash-search past
   the viewport edge. min-width:0 lets the heading text shrink first. */
.dash-panel-head { display: flex; flex-wrap: wrap; align-items: flex-start; justify-content: space-between; gap: 12px 16px; }
.dash-panel-head > div:first-child { min-width: 0; flex: 1 1 240px; }
.dash-panel-head h2 { margin: 0; font-family: Georgia, serif; font-weight: 400; font-size: 27px; letter-spacing: -.02em; }
.dash-panel-head h3 { margin: 0; font-size: 18px; font-weight: 800; letter-spacing: -.02em; }
.dash-panel-head p { margin: 4px 0 0; color: var(--muted); font-size: 13px; }
.dash-text-link { position: relative; color: var(--green); font-size: 13px; font-weight: 800; text-decoration: none; white-space: nowrap; }
.dash-text-link:hover { text-decoration: underline; }
/* These sit in fact rows ("Free plan · Billing"), not in prose, so WCAG 2.5.8's
   inline-link exception does not really cover them — a 16px-tall target is
   fiddly on a phone. The overlay grows the hit area without moving anything. */
.dash-text-link::after { content: ''; position: absolute; inset: -6px -4px; }
/* A standalone action rendered as a text link was only ~15px tall — under the
   24px WCAG 2.5.8 minimum. Padding plus a matching negative margin grows the
   hit area without moving anything on screen. Only standalone links get this;
   links inside a sentence keep their line box so hit areas cannot overlap. */
.dash-panel-head > .dash-text-link, .dash-stat-link { display: inline-flex; align-items: center; padding: 6px 2px; margin: -6px -2px; }

.dash-stat-progress { margin-top: 10px; }

/* Settings: read-only account facts rendered as plain rows, not inputs. */
.dash-fact-list { display: flex; flex-direction: column; }
.dash-fact { display: flex; align-items: baseline; justify-content: space-between; gap: 16px; padding: 11px 0; border-bottom: 1px solid var(--line); }
.dash-fact:last-child { border-bottom: 0; }
.dash-fact span { color: var(--muted); font-size: 13px; font-weight: 600; }
.dash-fact strong { color: var(--ink); font-size: 14px; font-weight: 700; overflow-wrap: anywhere; text-align: right; }

.dash-table { width: 100%; margin-top: 16px; border-collapse: collapse; }
.dash-table th { padding: 0 0 12px; text-align: left; color: #9a9890; font-size: 11px; font-weight: 800; letter-spacing: .07em; text-transform: uppercase; border-bottom: 1px solid var(--line); }
.dash-table td { padding: 13px 0; border-bottom: 1px solid var(--line); color: #3f453d; font-size: 14px; vertical-align: middle; }
.dash-table tr:last-child td { border-bottom: 0; }
.dash-table th:not(:first-child), .dash-table td:not(:first-child) { width: 1%; padding-left: 20px; white-space: nowrap; }
.dash-table-wrap { width: 100%; max-width: 100%; overflow-x: auto; overscroll-behavior-inline: contain; -webkit-overflow-scrolling: touch; }
.dash-table-wrap .dash-table { min-width: 640px; }
/* Admin tables scroll inside their card instead of spilling out of it — measured
   at 390px, the email log ran 34px past the card edge and that overhang was
   simply cut off, invisible. No forced min-width here: a table that already fits
   must not gain a scrollbar, and the nowrap columns make the wide ones scroll on
   their own. The 640px floor above stays for the diagnostics email log. */
[data-section="admin"] .dash-table-wrap .dash-table { min-width: 0; }
/* A file input's intrinsic width is set by the browser's own button + filename
   text, so it ignores the flex row and pushed 5px past the form edge at 390px. */
[data-section="admin"] input[type="file"] { max-width: 100%; }
.dash-gallery-cell { display: flex; align-items: center; gap: 12px; }
.dash-gallery-cell img { width: 48px; height: 38px; border-radius: 9px; object-fit: cover; }
.dash-gallery-cell strong { display: block; color: var(--ink); font-size: 14px; font-weight: 700; }
.dash-gallery-cell small { color: var(--muted); font-size: 12px; }
.dash-status { display: inline-flex; align-items: center; padding: 4px 11px; border-radius: 999px; font-size: 12px; font-weight: 800; }
.dash-status.live { background: #e6f1df; color: var(--green); }
.dash-status.draft { background: #f0ece4; color: #8a8276; }
.dash-status.warn { background: #fbe9e7; color: #a03d3d; }

/* Setup checklist (setup.php) */
.setup-table td { white-space: normal; }
.setup-table td:last-child { white-space: nowrap; vertical-align: top; padding-top: 16px; }
.setup-section td { padding-top: 22px; padding-bottom: 6px; border-bottom: 0; color: #9a9890; font-size: 11px; font-weight: 800; letter-spacing: .07em; text-transform: uppercase; }
.setup-hint { display: block; margin-top: 3px; color: var(--muted); font-size: 12.5px; font-weight: 500; line-height: 1.5; max-width: 460px; }

.dash-activity { margin-top: 14px; display: grid; }
.dash-activity-item { display: flex; gap: 12px; padding: 13px 0; border-bottom: 1px solid var(--line); }
.dash-activity-item:last-child { border-bottom: 0; }
.dash-activity-item i { flex: 0 0 auto; width: 36px; height: 36px; display: grid; place-items: center; border-radius: 50%; background: #eef3e9; color: var(--green); }
.dash-activity-item i .ic { width: 16px; height: 16px; }
.dash-activity-item strong { display: block; color: var(--ink); font-size: 14px; }
.dash-activity-item small { color: var(--muted); font-size: 12.5px; }

.dash-storage { margin-top: 14px; padding: 22px 24px; }
.dash-storage-head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; margin-bottom: 14px; }
.dash-storage-head strong { font-size: 15px; }
.dash-storage-head span { color: var(--muted); font-size: 13px; }
.dash-progress { height: 10px; border-radius: 999px; background: #ece8e0; overflow: hidden; }
.dash-progress span { display: block; height: 100%; border-radius: 999px; background: linear-gradient(90deg, #3a5226, var(--green)); transition: background .2s ease; }
/* Running out is a different message from making progress, so it gets a
   different colour — but never colour ALONE (see pmUsageState): the note beside
   the meter says "1 left" / "Full" too. */
.dash-progress.is-warn span { background: linear-gradient(90deg, #c2560f, #e8761f); }
.dash-progress.is-full span { background: linear-gradient(90deg, #8f3333, #b84a4a); }
.dash-usage-flag { font-weight: 800; }
.dash-stat .dash-usage-flag { color: var(--green); }
.dash-stat.is-warn .dash-usage-flag { color: #a8480a; }
.dash-stat.is-full .dash-usage-flag { color: #8f3333; }

.dash-search { display: flex; align-items: center; gap: 9px; min-height: 44px; min-width: 0; max-width: 100%; padding: 0 14px; border: 1px solid var(--line); border-radius: 13px; background: #fff; }
.dash-search .ic { flex: 0 0 auto; width: 17px; height: 17px; color: var(--muted); }
/* width is a preference, not a floor — min-width:0 is what lets it shrink
   inside the flex row instead of pushing the row wider than the screen. */
.dash-search input { border: 0; outline: 0; background: none; font: inherit; font-size: 16px; width: 200px; min-width: 0; flex: 1 1 auto; }
@media (max-width: 640px) {
  /* Full-width search under the heading reads better than a cramped pill. */
  .dash-search { flex: 1 1 100%; }
  .dash-search input { width: auto; }
}
.dash-search:focus-within { border-color: var(--green); box-shadow: 0 0 0 3px rgba(48,71,32,.12); }

.dash-gallery-cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 16px; align-items: stretch; }
.dash-gallery-cards > .dash-gcard { display: flex; flex-direction: column; }
.dash-gcard-body { flex: 1; display: flex; flex-direction: column; }
.dash-gcard { overflow: hidden; display: flex; flex-direction: column; }
.dash-gcard > img { width: 100%; height: 180px; object-fit: cover; }
.dash-gcard-body { flex: 1 1 auto; padding: 18px 20px 20px; display: flex; flex-direction: column; gap: 6px; }
/* Long gallery names used to wrap to four or five lines on a phone and push the
   badges around. The clamp is on the TITLE span, not the h3 — clamping the h3
   would swallow the badges with it. */
.dash-gcard-body h3 { margin: 0; font-size: 19px; font-weight: 800; letter-spacing: -.02em; }
.dash-gcard-title { display: -webkit-box; -webkit-line-clamp: 2; line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; overflow-wrap: anywhere; }
.dash-gcard-body > p { margin: 0; color: var(--muted); font-size: 13px; }
.dash-gcard-meta { display: flex; flex-wrap: wrap; gap: 6px 16px; margin: 4px 0 14px; color: #6b7064; font-size: 12.5px; }
/* T16: the timeline line — delivery date + upload-close/expiry promise */
.dash-gcard-when { display: flex; align-items: flex-start; gap: 7px; margin: -8px 0 14px; color: #6b7064; font-size: 12px; }
.dash-gcard-when .ic { width: 13px; height: 13px; flex: none; margin-top: 1px; }
/* The PHP joins the facts with newlines; pre-line turns each into its own row
   without needing markup per item. */
.dash-gcard-when span { white-space: pre-line; line-height: 1.5; }
.dash-gcard-when.is-expired { color: #a4382f; }
.dash-gcard-actions { margin-top: auto; display: flex; gap: 9px; }
.dash-gcard-actions .dash-btn { flex: 1; }
.dash-empty { margin-top: 20px; color: var(--muted); font-size: 14px; }

.dash-portfolio { display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px; }
.dash-portfolio figure { margin: 0; border-radius: 16px; overflow: hidden; aspect-ratio: 4 / 3; }
.dash-portfolio img { width: 100%; height: 100%; object-fit: cover; transition: transform .4s ease; }
.dash-portfolio figure:hover img { transform: scale(1.04); }

.dash-settings { display: grid; grid-template-columns: minmax(0, 1fr); gap: 16px; max-width: 760px; }
.dash-settings-wide { max-width: 980px; } /* T12: the tabbed profile section breathes wider */
.dash-settings-wide .ed-tabs { margin-bottom: 0; }

/* Profile section tabs (Details / Photos / Portfolio). dashboard-app.js toggles
   .active on a tab and its matching [data-ed-panel]; without these rules the
   panels all rendered at once, so clicking a tab changed nothing visible and
   the buttons showed as unstyled browser defaults. Same underline language as
   the gallery editor's .ed-nav-tab, borrowed rather than reinvented. */
.ed-tabs { display: flex; gap: 2px; overflow-x: auto; scrollbar-width: none; border-bottom: 1px solid var(--line); }
.ed-tabs::-webkit-scrollbar { display: none; }
.ed-tab { min-height: 46px; padding: 12px 16px; margin-bottom: -1px; border: 0; border-bottom: 2.5px solid transparent; background: none; color: var(--muted); font: inherit; font-size: 13.5px; font-weight: 700; white-space: nowrap; cursor: pointer; }
.ed-tab:hover { color: var(--ink); }
.ed-tab.active { color: var(--green); border-bottom-color: var(--green); }
.ed-tabpanel { display: none; }
.ed-tabpanel.active { display: block; }
.dash-settings-group { padding: 22px 24px; }
.dash-settings-group h3 { margin: 0 0 18px; font-size: 18px; font-weight: 800; }
.dash-form-grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 16px; }
.dash-form-grid label { display: flex; flex-direction: column; gap: 7px; font-size: 13px; font-weight: 800; color: #42483f; }
.dash-form-wide { grid-column: 1 / -1; }
.dash-form-grid input, .dash-form-grid textarea, .dash-modal-form input, .dash-modal-form select, .ed-password-form input { min-height: 46px; padding: 11px 14px; border: 1px solid var(--line); border-radius: 12px; background: #fff; color: var(--ink); font: inherit; font-size: 14px; font-weight: 500; }
.dash-form-grid textarea { min-height: 84px; resize: vertical; }
/* :not(radio/checkbox) — this is the text-field focus treatment; on a radio it
   drew a green-tinted box around the little circle, which is what made clicking
   the access options look wrong. Radios get their ring on the card instead. */
.dash-form-grid input:focus:not([type="radio"]):not([type="checkbox"]), .dash-form-grid textarea:focus, .dash-modal-form input:focus:not([type="radio"]):not([type="checkbox"]), .dash-modal-form select:focus, .ed-password-form input:focus { outline: none; border-color: var(--green); box-shadow: 0 0 0 3px rgba(48,71,32,.12); }
.dash-form-grid button { grid-column: 1 / -1; justify-self: start; }
/* wrap + a smaller gap: at 390px the label and its switch could not both fit on
   one line, so the text overflowed its box (measured 313px of content in 294px).
   overflow-wrap catches long unbroken words like a handle or URL. */
.dash-toggle-row { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 12px 20px; padding: 15px 0; border-top: 1px solid var(--line); }
.dash-toggle-row > span { min-width: 0; flex: 1 1 200px; overflow-wrap: anywhere; }
.dash-toggle-row span { display: flex; flex-direction: column; gap: 3px; }
.dash-toggle-row strong { font-size: 14.5px; font-weight: 700; }
.dash-toggle-row small { color: var(--muted); font-size: 13px; max-width: 380px; }
.dash-switch { flex: 0 0 auto; width: 46px; height: 27px; position: relative; border: 0; border-radius: 999px; background: #d9d4ca; cursor: pointer; transition: background .2s ease; }
.dash-switch::after { content: ""; position: absolute; top: 3px; left: 3px; width: 21px; height: 21px; border-radius: 50%; background: #fff; box-shadow: 0 1px 3px rgba(0,0,0,.2); transition: left .2s ease; }
.dash-switch.on { background: var(--green); }
.dash-switch.on::after { left: 22px; }
.dash-billing { margin: 0 0 16px; color: #42483f; font-size: 14px; }

/* T17: shared confirm dialog (pm-confirm.js) — must also sit above the viewer */
.pm-confirm-backdrop { z-index: 1300; }
.pm-confirm { position: relative; width: min(420px, 100%); }
/* Size comes from .dash-modal-close (44px, a proper touch target). */
.pm-confirm-close { position: absolute; top: 14px; right: 14px; }
/* Room for the corner close so a long title never runs under it. */
.pm-confirm h2 { margin: 0 0 10px; padding-right: 46px; font-size: 20px; }
.pm-confirm p { margin: 0 0 20px; color: #42483f; font-size: 14.5px; line-height: 1.55; }
.pm-confirm .dash-btn { min-height: 44px; }

/* T16: admin-managing-demo banner */
.dash-impersonate { display: flex; align-items: center; justify-content: space-between; gap: 16px; flex-wrap: wrap; margin: 18px 30px 0; padding: 12px 18px; border: 1px solid rgba(201,138,54,.45); border-radius: 14px; background: #fdf2d8; color: #6b5312; font-size: 13.5px; }
.dash-impersonate .dash-btn { min-height: 36px; }

/* Settings extras (T16): sign-in history + danger zone + modal action rows. */
.dash-login-list .dash-fact span { display: flex; flex-direction: column; gap: 2px; }
.dash-login-ip { color: var(--muted); font-size: 11.5px; font-weight: 500; }
.dash-login-note { margin: 14px 0 0; color: var(--muted); font-size: 12.5px; }
.dash-danger-zone { border-color: rgba(164,56,47,.3); }
.dash-danger-zone h3 { color: #a4382f; }
.dash-btn-danger { background: #a4382f; color: #fff; }
.dash-btn-danger:hover { background: #8d2f27; transform: translateY(-1px); }
.dash-btn-danger[disabled] { opacity: .5; cursor: not-allowed; transform: none; }
/* Wraps because a three-choice confirm ("Stay here / Discard & leave /
   Apply & leave") cannot fit one row at 390px. */
.dash-modal-actions { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 10px; margin-top: 6px; }

/* Plan tab (T15): current-plan card, usage meters and the four-tier ladder. */
.dash-plan { display: grid; gap: 22px; }
.dash-plan-current { padding: 22px 24px; }
/* The head carries no bottom margin, so whatever follows it inside a card sat
   flush against the description. Cards that stack plain blocks need the space. */
.dash-plan-current .dash-panel-head { margin-bottom: 14px; }
.dash-plan-actions { margin-top: 18px; }
.dash-plan-actions .dash-btn { min-height: 44px; }
.dash-plan-usage { display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: 18px 28px; margin-top: 6px; }
.dash-plan-meter-row { display: flex; justify-content: space-between; align-items: baseline; gap: 12px; margin-bottom: 8px; font-size: 13px; color: var(--muted); }
.dash-plan-meter-row strong { color: var(--ink); font-size: 14px; font-weight: 800; }
.dash-plan-ladder-head { margin-top: 4px; }
.dash-plan-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(215px, 1fr)); gap: 16px; align-items: stretch; }
.dash-plan-card { position: relative; display: flex; flex-direction: column; gap: 14px; padding: 22px 24px; }
.dash-plan-card.is-featured { border-color: var(--green); box-shadow: 0 10px 34px rgba(48,71,32,.14); }
.dash-plan-card.is-current { background: #f4f2ec; }
.dash-plan-flag { position: absolute; top: -10px; right: 16px; padding: 2px 10px; border-radius: 999px; background: var(--green); color: #fff; font-size: 10.5px; font-weight: 800; letter-spacing: .04em; text-transform: uppercase; }
.dash-plan-card h4 { margin: 0 0 6px; font-size: 16px; font-weight: 800; }
.dash-plan-price { margin: 0; font-size: 26px; font-weight: 800; letter-spacing: -.02em; }
.dash-plan-price span { font-size: 13px; font-weight: 600; color: var(--muted); }
.dash-plan-blurb { margin: 4px 0 0; color: var(--muted); font-size: 13px; }
.dash-plan-feats { margin: 0; padding: 0; list-style: none; display: grid; gap: 8px; font-size: 13.5px; color: #42483f; flex: 1; }
.dash-plan-feats li { padding-left: 20px; position: relative; }
.dash-plan-feats li::before { content: "✓"; position: absolute; left: 0; color: var(--green); font-weight: 800; }
.dash-plan-now { display: inline-block; padding: 9px 0 0; font-size: 13px; font-weight: 800; color: var(--green); }
.dash-plan-now-muted { color: var(--muted); font-weight: 600; }
.dash-plan-note { margin: -6px 0 0; color: var(--muted); font-size: 13px; }
.dash-billing-note { margin: 16px 0 0; color: var(--muted); font-size: 12.5px; line-height: 1.55; }
.dash-stat-link { color: var(--green); font-weight: 700; text-decoration: none; }
.dash-stat-link:hover { text-decoration: underline; }
.dash-modal-upsell { align-self: start; }

.dash-modal-backdrop { position: fixed; inset: 0; z-index: 1000; padding: 24px; display: grid; place-items: center; background: rgba(12,14,11,.62); backdrop-filter: blur(7px); }
.dash-modal { width: min(460px, 100%); max-height: calc(100vh - 48px); max-height: calc(100dvh - 48px); overflow-y: auto; overflow-x: hidden; padding: 28px 26px 30px; border: 1px solid rgba(255,255,255,.5); border-radius: 22px; background: #fbfaf7; box-shadow: 0 30px 100px rgba(0,0,0,.3); overscroll-behavior: contain; }
/* Upgrade modal. Wider than a form modal because it carries plan cards side by
   side; it still collapses to one column on a phone. */
.dash-modal-wide { width: min(820px, 100%); }
.dash-up-now { margin-bottom: 20px; padding: 15px 17px; border-radius: 15px; background: #f2f0ea; }
.dash-up-now-head { margin: 0 0 11px; font-size: 13.5px; color: var(--muted); }
.dash-up-now-head strong { color: var(--ink); }
.dash-up-meters { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 12px 20px; }
.dash-up-meter { display: grid; gap: 6px; }
.dash-up-meter > span { font-size: 12.5px; font-weight: 700; color: #42483f; }
.dash-up-meter .dash-progress { height: 8px; background: #e0dbd1; }

.dash-up-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(225px, 1fr)); gap: 16px; align-items: stretch; }
/* One rung left (Pro → Studio) must not read as a leftover: give it the full
   width and let the gains carry it, rather than a lone card in a wide modal. */
.dash-up-grid.is-single { grid-template-columns: minmax(0, 1fr); }
.dash-up-card { position: relative; display: flex; flex-direction: column; gap: 14px;
  padding: 22px 22px 20px; border: 1px solid var(--line); border-radius: 18px; background: #fff; }
/* The recommendation stands out by WEIGHT, not a new hue: a 2px brand border,
   a tinted head fading into the card, and a deeper lift. Gold was tried here
   and reverted — the owner did not want it. */
.dash-up-card.is-recommended { border-color: var(--green); border-width: 2px;
  background: linear-gradient(180deg, #f3f7ef 0%, #fff 38%);
  box-shadow: 0 14px 42px rgba(48,71,32,.2); }
.dash-up-flag { position: absolute; top: -10px; left: 22px; padding: 3px 11px; border-radius: 999px;
  background: var(--green); color: #fff; font-size: 10.5px; font-weight: 800; letter-spacing: .04em; text-transform: uppercase; }
.dash-up-head h3 { margin: 0; font-size: 16px; font-weight: 800; }
.dash-up-price { margin: 6px 0 0; font-size: 30px; font-weight: 800; letter-spacing: -.025em; }
.dash-up-price span { font-size: 13px; font-weight: 600; color: var(--muted); letter-spacing: 0; }
.dash-up-blurb { margin: 4px 0 0; color: var(--muted); font-size: 13px; }
.dash-up-gainlead { margin: 0; font-size: 11px; font-weight: 800; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); }
.dash-up-gains { margin: 0; padding: 0; list-style: none; display: grid; gap: 12px; flex: 1; }
.dash-up-grid.is-single .dash-up-gains { grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); }
.dash-up-gains li { display: flex; align-items: flex-start; gap: 10px; }
.dash-up-gains i { flex: 0 0 auto; width: 28px; height: 28px; display: grid; place-items: center;
  border-radius: 9px; background: rgba(48,71,32,.1); color: var(--green); }
.dash-up-gains .ic { width: 16px; height: 16px; }
.dash-up-gains span { min-width: 0; display: block; }
.dash-up-gains strong { display: block; font-size: 13.5px; font-weight: 800; }
.dash-up-gains small { display: block; margin-top: 1px; color: var(--muted); font-size: 12.5px; line-height: 1.45; }
/* Last-rung storage step (Pro → Studio). Storage is the only real difference
   there, so it gets shown rather than listed — a bullet reading "500 GB" made
   the single-card modal look like a leftover. */
.dash-up-step { display: grid; gap: 9px; padding: 16px 17px; border-radius: 14px; background: #f5f3ed; }
.dash-up-step-row { display: grid; grid-template-columns: 62px minmax(0, 1fr) auto; align-items: center; gap: 12px; }
.dash-up-step-label { font-size: 11.5px; font-weight: 800; letter-spacing: .04em; text-transform: uppercase; color: var(--muted); }
.dash-up-step-row .dash-progress { height: 12px; background: #e2ddd3; }
.dash-up-step-row.is-new .dash-progress span { background: linear-gradient(90deg, var(--green), #4a6b30); }
.dash-up-step-row strong { font-size: 14px; font-weight: 800; white-space: nowrap; }
.dash-up-step-row.is-new strong { color: var(--green); }
.dash-up-step-note { margin: 3px 0 0; font-size: 13px; color: #42483f; line-height: 1.5; }
.dash-up-keeps { margin: 0; flex: 1; color: var(--muted); font-size: 13px; line-height: 1.55; }
@media (max-width: 460px) {
  .dash-up-step-row { grid-template-columns: 52px minmax(0, 1fr) auto; gap: 9px; }
}
/* Must out-specify `.dash-modal > p` above (0-1-1), which otherwise zeroes the
   top margin and forces 14px — measured: the footer sat flush against the plan
   cards with no gap at all. */
.dash-modal > .dash-up-foot { margin: 18px 0 0; color: var(--muted); font-size: 12.5px; line-height: 1.55; }
@media (max-width: 560px) {
  .dash-modal-wide { padding-left: 18px; padding-right: 18px; }
  .dash-up-card { padding: 20px 17px 18px; }
  /* Stacked, the ascending price ladder buries the recommendation below the
     fold and the cheapest plan is what gets read. Desktop keeps DOM order,
     where all the cards are visible at once and the ladder makes sense. */
  .dash-up-grid > .dash-up-card.is-recommended { order: -1; }
  .dash-up-grid { padding-top: 10px; }
}

.dash-modal-head { display: flex; align-items: center; justify-content: space-between; gap: 16px; margin-bottom: 8px; }
.dash-modal-head h2 { margin: 0; font-family: Georgia, serif; font-weight: 400; font-size: 24px; }
.dash-modal-close { width: 44px; height: 44px; flex: 0 0 auto; display: grid; place-items: center; border: 1px solid var(--line); border-radius: 50%; background: #fff; color: var(--ink); cursor: pointer; }
.dash-modal-close .ic { width: 18px; height: 18px; }
.dash-modal > p { margin: 0 0 18px; color: var(--muted); font-size: 14px; line-height: 1.55; }
.dash-modal-form { display: grid; grid-template-columns: minmax(0, 1fr); gap: 16px; padding-bottom: 4px; }
/* Collapsed "Optional settings" disclosure in the create modal. Native
   <details>, so it opens with JavaScript off and needs no inline handler. */
/* Shown only when the plan's gallery cap is actually reached — the running
   count that used to sit here was noise every other day of the year. */
/* A .dash-optional used AS a card: the card already draws the border and
   padding, so the disclosure must not draw a second one inside it. */
.dash-optional-card { padding: 0; overflow: hidden; }
/* Card-sized disclosures (Archive or delete, Sign-in & security) are only
   collapsible where the screen is small enough for it to matter — see the
   `open` attribute in the markup and the phone-only close in the app scripts. */
/* The 44px right padding is what keeps the +/- clear of the title — it must be
   in THIS rule. Split across a second, lower-specificity rule it was silently
   dropped the moment `details.` was added here, and the icon landed on top of
   the wrapped title on phones. */
details.dash-optional-card > summary { padding: 16px 44px 16px 18px; font-size: 15px; }
/* `details.` again, and for the same reason: without it these tie with
   `.dash-optional > summary::before` further down, the later rule wins, and the
   +/- stays at left:15px — landing directly on top of the title, which is
   exactly how it rendered on phones. */
details.dash-optional-card > summary::before { left: auto; right: 20px; }
details.dash-optional-card > summary::after { left: auto; right: 24.5px; }
/* Desktop block sits AFTER the base rules on purpose. Two ordering traps here,
   both of which silently ate an earlier attempt at this:
   1. `.dash-optional-card > summary` ties on specificity with
      `.dash-optional > summary` further down, so the plain form always lost —
      hence `details.` to outrank it.
   2. Equal-specificity rules are decided by source order, and a @media block
      earns no extra weight, so this must come after the base sizes it overrides. */
@media (min-width: 701px) {
  .dash-optional-card > summary { pointer-events: none; }
  details.dash-optional-card > summary::before, details.dash-optional-card > summary::after { display: none; }
  /* Where it cannot collapse it is not a disclosure, it is a card heading — so
     it matches .dash-settings-group h3 (18px/800) and the card's own padding.
     At 13.5px beside 18px siblings it read as a hidden title with a stray
     collapse button, which is exactly what it looked like. */
  details.dash-optional-card > summary { padding: 22px 24px 0; font-size: 18px; cursor: default; }
  details.dash-optional-card > summary small { font-size: 13px; margin-top: 4px; font-weight: 500; }
  /* `[open]` is needed to outrank `.dash-optional[open] .dash-optional-body`
     (0-3-0) further down, which otherwise sets a 2px top and butts the body
     text straight into the summary's sub-line. */
  details.dash-optional-card[open] > .dash-optional-body { padding: 16px 24px 22px; }
}
.dash-optional-card > .dash-optional-body { padding: 0 18px 18px; }
/* Gallery cap card — one row: what happened, what it means, one way forward.
   It deliberately carries no plan facts; those live in the upgrade modal, under
   the price each one belongs to.

   It wears the SAME "full" red as the galleries meter (--pm-full, used by
   .dash-progress.is-full), because it appears at exactly the moment that meter
   turns red — the two are reporting one fact. Green read as a promotion while
   the owner was actually blocked. This is deliberately the meter's colour and
   not a louder invented alarm: being at your plan limit is a state, not a
   fault, and dressing a sales surface as an error to hurry a purchase is a
   dark pattern. The colour carries the urgency; the icon stays the subject
   (galleries), so nothing implies the owner did something wrong. */
.dash-cap-card { display: flex; align-items: center; flex-wrap: wrap; gap: 14px;
  margin-bottom: 16px; padding: 18px 20px;
  border-color: rgba(143,51,51,.3);
  background: linear-gradient(135deg, #fdfbfa 0%, #faf0ee 100%); }
.dash-cap-ic { flex: 0 0 auto; width: 40px; height: 40px; display: grid; place-items: center;
  border-radius: 12px; background: #8f3333; color: #fff; }
.dash-cap-ic .ic { width: 20px; height: 20px; }
.dash-cap-copy { flex: 1 1 260px; min-width: 0; }
.dash-cap-card strong { display: block; font-size: 15px; font-weight: 800; }
.dash-cap-card small { display: block; margin-top: 3px; color: var(--muted); font-size: 13px; line-height: 1.5; }
/* Brand green, like every other primary action. Ink and gold were both tried
   here and both reverted — the owner wants the standard primary button. */
.dash-cap-btn { flex: 0 0 auto; }
@media (max-width: 560px) {
  /* The copy wraps to three lines here, and a vertically-centred icon then
     floats beside the middle of the paragraph. Align it to the first line. */
  .dash-cap-card { padding: 16px; align-items: flex-start; }
  .dash-cap-btn { flex: 1 1 100%; justify-content: center; }
}
.dash-optional { border: 1px solid var(--line); border-radius: 14px; background: #fff; overflow: hidden; }
.dash-optional > summary { min-height: 48px; display: flex; flex-direction: column; justify-content: center; gap: 2px; padding: 8px 14px 8px 38px; position: relative; list-style: none; cursor: pointer; font-size: 13.5px; font-weight: 800; color: #42483f; }
.dash-optional > summary::-webkit-details-marker { display: none; }
.dash-optional > summary small { font-size: 12px; font-weight: 500; color: var(--muted); line-height: 1.4; }
/* The +/− is drawn rather than typed so it stays centred at any font size. */
.dash-optional > summary::before,
.dash-optional > summary::after { content: ""; position: absolute; left: 15px; background: #42483f; transition: transform .18s, opacity .18s; }
.dash-optional > summary::before { top: 50%; width: 11px; height: 2px; margin-top: -1px; }
.dash-optional > summary::after { top: 50%; left: 20px; width: 2px; height: 11px; margin-top: -6px; }
.dash-optional[open] > summary::after { transform: rotate(90deg); opacity: 0; }
.dash-optional > summary:hover { background: #f7f5ef; }
.dash-optional > summary:focus-visible { outline: 2px solid #7655ad; outline-offset: -2px; }
/* Only style the body when the disclosure is OPEN. Setting `display` on it
   unconditionally overrides the browser's own collapse, which leaves the fields
   laid out and keyboard-focusable behind `overflow: hidden` — visually closed,
   still tabbable. */
.dash-optional[open] .dash-optional-body { display: grid; gap: 16px; padding: 2px 14px 16px; }
/* The first block sits directly under the summary, which already separates it. */
.dash-optional-body > :first-child { margin-top: 0; padding-top: 0; border-top: 0; }
.dash-modal-form label { display: flex; flex-direction: column; gap: 7px; min-width: 0; font-size: 13px; font-weight: 800; color: #42483f; }
.dash-modal-form button { margin-top: 4px; }
body.modal-open { overflow: hidden; }
.dash-crop-stage { max-height: 52vh; margin: 10px 0 16px; background: #f0ece4; border-radius: 14px; overflow: hidden; }
.dash-crop-stage img { display: block; max-width: 100%; }
.dash-crop-controls { display: flex; align-items: center; gap: 16px; margin-bottom: 14px; }
.dash-crop-zoom { display: flex; align-items: center; gap: 10px; flex: 1; font-size: 13px; font-weight: 800; color: #42483f; }
.dash-crop-zoom input[type="range"] { flex: 1; min-height: 0; padding: 0; accent-color: var(--green); }
.dash-crop-actions { display: flex; gap: 10px; justify-content: flex-end; }

/* Profile setup (Q3): substantial five-step work belongs in the dashboard
   page, not inside a nested-scroll modal. */
.dash-profile-setup { width: 100%; margin: 0; padding-bottom: 48px; scroll-margin-top: 24px; }
.dash-profile-setup .dash-wizard { width: 100%; padding: clamp(26px, 4vw, 42px); overflow: visible; }
.dash-wizard-top { display: flex; align-items: center; justify-content: space-between; gap: 20px; margin-bottom: 26px; }
.dash-wizard-top > span { color: var(--muted); font-size: 12px; font-weight: 800; letter-spacing: .035em; text-transform: uppercase; text-align: right; }
.dash-wizard-exit { min-height: 44px; padding: 8px 2px; border: 0; background: transparent; color: var(--muted); font: inherit; font-size: 13px; font-weight: 800; cursor: pointer; text-decoration: underline; text-decoration-color: transparent; text-underline-offset: 3px; transition: color .15s ease, text-decoration-color .15s ease; }
.dash-wizard-exit:hover { color: var(--green); text-decoration-color: currentColor; }
.dash-wizard-exit:focus-visible { outline: 2px solid var(--green); outline-offset: 3px; border-radius: 4px; }
.dash-wizard-heading { margin-bottom: 18px; }
.dash-wizard-heading .dash-eyebrow { margin: 0 0 5px; color: var(--green); font-size: 11px; font-weight: 800; letter-spacing: .11em; text-transform: uppercase; }
.dash-wizard-heading h2 { margin: 0; font-family: Georgia, serif; font-size: clamp(28px, 4vw, 36px); font-weight: 400; line-height: 1.1; }
.dash-wizard-progress { height: 4px; margin-bottom: 28px; overflow: hidden; border-radius: 999px; background: #ded9cf; }
.dash-wizard-progress span { display: block; width: 20%; height: 100%; border-radius: inherit; background: var(--green); transition: width .22s ease; }
.dash-wizard .dash-modal-form { max-width: 720px; gap: 18px; }
.dash-wizard fieldset { display: grid; grid-template-columns: minmax(0, 1fr); gap: 16px; margin: 0; padding: 0; border: 0; min-width: 0; }
.dash-wizard-lead { margin: 0 0 2px; color: var(--muted); font-size: 15px; line-height: 1.65; }
.dash-example-link { justify-self: start; min-height: 44px; margin-top: -10px !important; padding: 6px 0; border: 0; background: transparent; color: var(--green); font: inherit; font-size: 13px; font-weight: 800; text-decoration: underline; text-underline-offset: 3px; cursor: pointer; }
.dash-example-link:hover { color: var(--ink); }
/* The link belongs beside the field it fills in, on the label's own line —
   under the box it read as a note about the answer already typed there. */
.dash-field { display: grid; gap: 7px; min-width: 0; }
.dash-field-head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; }
.dash-modal-form .dash-field-head label { display: block; }
.dash-field-head .dash-example-link { margin-top: 0 !important; position: relative; min-height: 0; padding: 0; white-space: nowrap; }
/* 16px of ink, a 40px target. Same hit-area trick as .dash-text-link, and
   ui-audit follows the negative inset rather than reporting a tiny tap area.
   Vertical only: the link is ~130px wide already, and it sits flush right, so
   a horizontal inset overhangs the form and pushes its scrollWidth out. */
.dash-field-head .dash-example-link::before { content: ''; position: absolute; inset: -12px 0; }
.dash-wizard-avatar { display: flex; align-items: center; gap: 16px; }
.dash-wizard-avatar img { width: 84px; height: 84px; flex: 0 0 auto; border-radius: 50%; object-fit: cover; border: 1px solid var(--line); background: #f0ece4; }
.dash-wizard-avatar > div { display: grid; gap: 8px; justify-items: start; }
.dash-wizard-hint { color: var(--muted); font-size: 12.5px; font-weight: 500; }
.dash-wizard-review { margin: 0; padding: 12px 14px; border-radius: 12px; background: #f0ece4; color: #42483f; font-size: 13.5px; font-weight: 600; }
.dash-wizard-nav { display: flex; gap: 10px; margin-top: 8px; padding-top: 20px; border-top: 1px solid var(--line); }
.dash-wizard .dash-btn { min-height: 44px; }
.dash-wizard-nav .dash-btn { min-width: 150px; justify-content: center; }
.dash-wizard-nav .dash-btn-primary { margin-left: auto; }
/* T11: profile intro (the only thing shown before setup) */
.dash-profile-intro { max-width: 620px; padding: 34px 32px; display: grid; gap: 10px; justify-items: start; }
.dash-profile-intro h3 { margin: 0; font-family: Georgia, serif; font-weight: 400; font-size: 26px; }
.dash-profile-intro p { margin: 0; color: #42483f; font-size: 14.5px; line-height: 1.65; }
.dash-profile-intro-cta { margin-top: 10px; min-height: 50px; padding-inline: 28px; }
/* T11: live handle availability */
.dash-handle-status { min-height: 17px; font-weight: 600; color: var(--muted); }
.dash-handle-status.is-ok { color: var(--green); }
.dash-handle-status.is-bad { color: #a03d3d; }
/* T11: About-tab choice in the wizard */
/* (.dash-wizard-about / .dash-wizard-radio removed with the About-portrait
   choice — no markup used them any more.) */
.dash-wizard-drop { padding: 26px 16px; }
/* T11: portfolio tile — single remove control that always fits */
.dash-portfolio-x { position: absolute; top: 6px; right: 6px; width: 28px; height: 28px; display: grid; place-items: center; border: 0; border-radius: 50%; background: rgba(17,19,15,.62); color: #fff; cursor: pointer; opacity: 0; transition: opacity .15s ease; }
.dash-portfolio-x .ic { width: 13px; height: 13px; }
.dash-portfolio-item:hover .dash-portfolio-x, .dash-portfolio-x:focus-visible { opacity: 1; }
@media (hover: none) { .dash-portfolio-x { opacity: 1; } }

/* Admin-set announcement banner (R1) — first element on the homepage.
   Fixed 42px single-line bar (ellipsis when narrow) so the absolutely
   positioned .site-header below can use a constant offset. */
.pm-announce { position: relative; z-index: 25; height: 42px; display: flex; align-items: center; justify-content: center; padding: 0 18px; background: var(--green, #304720); color: #fff; font-size: 14px; font-weight: 600; }
.pm-announce span { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* Cookie consent (R5): non-blocking bottom bar; a choice is required before
   optional storage would run, but the page stays fully usable behind it. */
.pm-consent { position: fixed; left: 0; right: 0; bottom: 0; z-index: 1300; display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 12px 22px; padding: 14px 18px calc(14px + env(safe-area-inset-bottom)); background: var(--ink, #1e241b); color: #e9e6de; box-shadow: 0 -8px 30px rgba(0,0,0,.25); }
.pm-consent-copy { margin: 0; max-width: 640px; font-size: 13px; line-height: 1.55; }
.pm-consent-copy a { color: #cfe3c2; }
.pm-consent-actions { display: flex; flex-wrap: wrap; gap: 9px; }
.pm-consent-btn { min-height: 44px; padding: 10px 18px; border: 1px solid rgba(255,255,255,.35); border-radius: 999px; background: transparent; color: #fff; font: inherit; font-size: 13.5px; font-weight: 700; cursor: pointer; }
.pm-consent-btn.primary { background: #fff; border-color: #fff; color: var(--ink, #1e241b); }
/* Bare reset so the consent button inherits whichever footer's link look
   surrounds it — the footer selectors above/in legal.css do the styling. */
.pm-consent-link { min-height: 44px; display: inline-flex; align-items: center; border: 0; background: none; padding: 0; margin: 0; color: inherit; font: inherit; cursor: pointer; }

/* Demo experience (R2): sticky "you're viewing a demo" bar + homepage links. */
/* Fixed 38px, never wraps — gallery controls sit below it on demo pages. */
.pm-demo-bar { position: sticky; top: 0; z-index: 30; display: flex; align-items: center; justify-content: center; gap: 5px; height: 38px; padding: 0 16px; background: var(--ink, #1e241b); color: #fff; white-space: nowrap; overflow: hidden; font-size: 13px; font-weight: 700; }
/* The bar is a flex row, so this link is a flex item, not inline text — WCAG's
   inline-in-a-sentence exemption doesn't apply and padding costs no line height.
   24px is the 2.5.8 minimum; the 38px bar centres it. */
.pm-demo-bar a { display: inline-flex; align-items: center; min-height: 24px; color: #cfe3c2; text-underline-offset: 2px; }
.pm-demo-bar ~ main .gal-toolbar { top: 38px; }
/* The gallery-intro's right column: paragraph + demo button together (T12). */
.pm-demo-links { display: grid; gap: 16px; justify-items: start; margin: 0; }
.gallery-intro .pm-demo-links { grid-column: 2; }
@media (max-width: 900px) { .gallery-intro .pm-demo-links { grid-column: auto; } }
.pm-demo-links p { margin: 0; color: var(--muted); font-size: 16px; line-height: 1.7; }
.pm-demo-links a { padding: 11px 20px; border: 1.5px solid var(--green, #304720); border-radius: 999px; color: var(--green, #304720); font-size: 14px; font-weight: 700; text-decoration: none; transition: background .15s ease, color .15s ease, transform .18s ease; }
.pm-demo-links a:hover { background: var(--green, #304720); color: #fff; transform: scale(1.04); }

.dash-toast { position: fixed; left: 50%; bottom: 28px; z-index: 1100; padding: 13px 20px; border-radius: 13px; background: var(--ink); color: #fff; font-size: 14px; font-weight: 600; box-shadow: 0 18px 50px rgba(0,0,0,.3); opacity: 0; transform: translateX(-50%) translateY(12px); transition: opacity .25s ease, transform .25s ease; }
.dash-toast.show { opacity: 1; transform: translateX(-50%) translateY(0); }

.dash-mobile-nav { display: none; }

@media (max-width: 1040px) {
  .dash-stats { grid-template-columns: repeat(2, 1fr); }
  .dash-grid { grid-template-columns: 1fr; }
}
@media (max-width: 820px) {
  .dash-shell { grid-template-columns: 1fr; }
  .dash-sidebar { display: none; }
  .dash-topbar { padding: 16px 18px; gap: 10px; }
  .dash-topbar h1 { font-size: 22px; }
  .dash-account-menu { display: block; }
  .dash-topbar-actions .dash-btn-light { display: none; }
  .dash-content { padding: 18px 16px 100px; }
  .dash-welcome { flex-direction: column; align-items: flex-start; gap: 18px; padding: 24px; }
  .dash-welcome h2 { font-size: 29px; }
  .dash-portfolio { grid-template-columns: repeat(2, 1fr); }
  .dash-form-grid { grid-template-columns: minmax(0, 1fr); }
  .dash-mobile-nav { display: flex; position: fixed; left: 0; right: 0; bottom: 0; z-index: 50; justify-content: space-around; padding: 8px 6px calc(8px + env(safe-area-inset-bottom)); border-top: 1px solid var(--line); background: rgba(255,255,255,.96); backdrop-filter: blur(10px); }
  .dash-mobile-nav a { display: flex; flex-direction: column; align-items: center; gap: 3px; padding: 6px 8px; border-radius: 10px; color: var(--muted); font-size: 10.5px; font-weight: 700; text-decoration: none; }
  .dash-mobile-nav a .ic { width: 21px; height: 21px; }
  .dash-mobile-nav a.active { color: var(--green); }
  /* A panel head's action wraps to its own row at this width, where a
     content-width button looks stranded and sits tight under the description.
     Full width and a bigger row gap makes it read as a deliberate action. */
  .dash-panel-head { gap: 16px; }
  .dash-panel-head > .dash-btn { width: 100%; justify-content: center; }
  .dash-plan-actions .dash-btn { width: 100%; justify-content: center; }
  /* Label and value stack rather than fighting over one line — "Event photos"
     was breaking across two lines to make room for its own value. */
  .dash-fact { flex-direction: column; align-items: flex-start; gap: 3px; }
  .dash-fact strong { text-align: left; }
  /* Badges drop to their own row under the title on a phone: inline they either
     squeezed the name into fewer characters or wrapped awkwardly mid-title. */
  .dash-gcard-body h3 { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
  .dash-gcard-body h3 .dash-gcard-title { flex: 1 0 100%; }
  .dash-gcard-body h3 .dash-event-badge { margin-left: 0; }
  /* Phone: one home for account things. The topbar button goes; the bottom
     bar's Account icon opens the same menu, anchored as a bottom sheet. */
  /* Hide the BUTTON, not the menu — the popup lives inside it, so hiding the
     wrapper would make the bottom-bar sheet open into a display:none ancestor
     and render nothing at all. */
  .dash-topbar .dash-account-btn { display: none; }
  .dash-topbar-logo { display: inline-flex; align-items: center; flex: none; }
  .dash-pop-phone-only { display: flex; }
  .dash-filter { display: none; }
  .dash-filter-select { display: block; }
  /* backdrop-filter on an ancestor makes it the containing block for fixed
     descendants, which anchored this sheet to the topbar instead of the
     viewport (it rendered above the fold, off-screen). Dropping the blur here
     restores the viewport as the containing block; the bar is opaque enough
     at this width that the effect was not doing visible work anyway. */
  .dash-topbar { backdrop-filter: none; background: var(--paper); }
  .dash-account-pop { position: fixed; top: auto; left: 12px; right: 12px; bottom: calc(72px + env(safe-area-inset-bottom)); min-width: 0; max-height: calc(100dvh - 160px); border-radius: 18px; box-shadow: 0 -10px 40px rgba(0,0,0,.22); }
  /* Recent-galleries table at phone width: drop the date column and let the
     title cell shrink so chips and numbers never collide with wrapped text. */
  .dash-col-created { display: none; }
  .dash-table th:not(:first-child), .dash-table td:not(:first-child) { padding-left: 12px; }
  .dash-gallery-cell img, .dash-cover-empty { display: none; }
  .dash-gallery-cell span { min-width: 0; }
  .dash-gallery-cell strong { overflow-wrap: anywhere; }
}

/* ===================== Client gallery ===================== */
/* T10: gallery appearance variables (set inline on <body> per palette).
   Defaults reproduce the classic look exactly. */
.gal-body { background: var(--galx-bg, #fff); color: var(--galx-ink, var(--ink)); }
.gal-gate { position: fixed; inset: 0; z-index: 1000; display: grid; place-items: center; padding: 24px; background: rgba(17,19,15,.55); backdrop-filter: blur(10px); transition: opacity .35s ease; }
.gal-gate.open { opacity: 0; pointer-events: none; }
.gal-gate-card { width: min(520px, 100%); display: flex; flex-direction: column; align-items: center; gap: 13px; padding: 40px 44px; text-align: center; border-radius: 24px; background: #fff; box-shadow: 0 30px 90px rgba(0,0,0,.3); }
.gal-gate-card img { width: 46px; height: 46px; }
.gal-gate-card h1 { margin: 4px 0 0; font-family: var(--galx-title-font, Georgia, serif); font-weight: var(--galx-title-weight, 400); font-style: var(--galx-title-style, normal); font-size: 30px; letter-spacing: -.02em; }
.gal-gate-card p { margin: 0; color: var(--muted); font-size: 14px; line-height: 1.6; }
.gal-gate-card input { width: 100%; min-height: 50px; margin-top: 6px; padding: 0 15px; border: 1px solid var(--line); border-radius: 14px; font: inherit; font-size: 14px; text-align: center; }
.gal-gate-card input:focus { outline: none; border-color: var(--green); box-shadow: 0 0 0 3px rgba(48,71,32,.13); }
.gal-gate-card .dash-btn { width: 100%; }
.gal-gate-hint { color: #9a9890; font-size: 12.5px; }
.gal-gate-error { color: #a03d3d; font-weight: 600; }
.gal-gate-show { display: inline-flex; align-items: center; gap: 7px; align-self: flex-start; color: var(--muted); font-size: 12.5px; font-weight: 600; cursor: pointer; }
.gal-gate-show input { width: 15px; height: 15px; margin: 0; accent-color: var(--green); }
/* Editor access-mode selector (Public link / Client login). */
.ed-access-modes { display: flex; gap: 6px; flex-wrap: wrap; }
.ed-access-opt.is-on { border-color: var(--green); background: #eef3e9; color: var(--green); font-weight: 800; }
/* Shared-with recipient manager. */
.ed-shared { display: grid; gap: 10px; padding: 15px 0 0; border-top: 1px solid var(--line); margin-top: 16px; }
.ed-shared > span { display: grid; gap: 2px; }
.ed-shared > span strong { font-size: 14px; }
.ed-shared small { color: var(--muted); font-size: 12.5px; line-height: 1.5; }
/* Recipient list in the send modal: one row per address, matching .ed-shared-list
   below (that is the same idea on the Share tab, so they should not look like two
   different components). The list is empty until something is added, hence :empty. */
.ed-recip { display: grid; gap: 9px; }
.ed-recip-label { font-size: 13px; font-weight: 800; color: #42483f; }
.ed-recip-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 6px; }
.ed-recip-list:empty { display: none; }
.ed-recip-chip { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 9px 8px 9px 13px; border: 1px solid var(--line); border-radius: 11px; background: #fff; font-size: 13px; }
.ed-recip-chip span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ed-recip-x { flex: 0 0 auto; min-width: 32px; min-height: 32px; border: 0; background: none; color: var(--muted); font-size: 22px; line-height: 1; cursor: pointer; border-radius: 8px; }
.ed-recip-x:hover { color: #a03d3d; background: #fbe3e0; }
.ed-recip-add { display: flex; gap: 8px; }
.ed-recip-add input { flex: 1; min-width: 0; }
.ed-recip-add .dash-btn { flex: 0 0 auto; }
.ed-shared-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 6px; }
.ed-shared-list li { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 9px 8px 9px 13px; border: 1px solid var(--line); border-radius: 11px; font-size: 13px; }
/* min 32px square: it was 31×22, under the 24px WCAG 2.5.8 floor, and it
   revokes someone's access — a miss is expensive in both directions. */
.ed-shared-remove { display: flex; align-items: center; justify-content: center; flex: 0 0 auto; min-width: 32px; min-height: 32px; border: 0; background: none; color: var(--muted); font-size: 22px; line-height: 1; cursor: pointer; padding: 0 8px; border-radius: 8px; }
.ed-shared-remove:hover { color: #a03d3d; background: #fbe3e0; }

/* Client gallery hub (myphotos.php). */
.mp-body { min-height: 100vh; background: var(--paper); }
.mp-top { display: flex; align-items: center; justify-content: space-between; gap: 16px; padding: 18px clamp(20px, 5vw, 48px); border-bottom: 1px solid var(--line); }
.mp-brand { display: inline-flex; align-items: center; gap: 10px; color: var(--ink); font-weight: 850; text-decoration: none; }
.mp-main { max-width: 1080px; margin: 0 auto; padding: clamp(28px, 5vw, 48px) clamp(20px, 5vw, 48px) 60px; }
.mp-head { margin-bottom: 26px; }
.mp-head h1 { margin: 6px 0 8px; font-family: Georgia, serif; font-weight: 400; font-size: clamp(30px, 5vw, 40px); letter-spacing: -.02em; }
.mp-sub { margin: 0; color: var(--muted); font-size: 15px; }
.mp-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); gap: 18px; }
.mp-card { overflow: hidden; text-decoration: none; color: var(--ink); transition: transform .18s ease, box-shadow .18s ease; }
.mp-card:hover { transform: translateY(-3px); box-shadow: 0 24px 60px rgba(17,19,15,.12); }
.mp-card-cover { position: relative; aspect-ratio: 4 / 3; background: #e7e3da; }
.mp-card-cover img { width: 100%; height: 100%; object-fit: cover; display: block; }
.mp-card-cover[data-empty]::after { content: ""; position: absolute; inset: 0; background: linear-gradient(135deg, #d9d3c6, #e9e5db); }
.mp-badge { position: absolute; top: 10px; left: 10px; z-index: 1; padding: 3px 10px; border-radius: 999px; background: rgba(255,255,255,.9); color: var(--green); font-size: 11px; font-weight: 800; letter-spacing: .02em; }
.mp-badge.is-private { background: rgba(17,19,15,.78); color: #fff; }
.mp-card-body { padding: 14px 16px 16px; display: grid; gap: 3px; }
.mp-card-body strong { font-size: 15px; letter-spacing: -.01em; }
.mp-card-body small { color: var(--muted); font-size: 12.5px; }
.mp-empty { padding: 30px 32px; max-width: 560px; }
.mp-empty h3 { margin: 0 0 6px; font-family: Georgia, serif; font-weight: 400; font-size: 22px; }
.mp-empty p { margin: 0; color: var(--muted); font-size: 14px; line-height: 1.6; }
/* The hub login reuses the dark gallery-gate look; only the two client-step
   wrappers need layout here. */
.gal-gate-card [data-client-step] { width: 100%; display: flex; flex-direction: column; align-items: center; gap: 13px; }
/* Bold, spaced 6-digit code input — matches the homepage sign-in modal. */
.gal-gate-card .gal-gate-code { font-size: 26px; font-weight: 800; letter-spacing: .4em; text-indent: .4em; font-variant-numeric: tabular-nums; min-height: 60px; }
.gal-gate-card .gal-gate-code::placeholder { font-weight: 700; letter-spacing: .4em; }
/* Blurred gallery cover behind the access/login card. */
.gal-gate-cover { position: fixed; inset: 0; z-index: -1; overflow: hidden; }
.gal-gate-cover img { width: 100%; height: 100%; object-fit: cover; transform: scale(1.1); filter: blur(22px) brightness(.62); }
.gal-gate-body.has-cover .gal-gate { background: rgba(17,19,15,.34); }
.gal-gate-by { font-size: 12.5px !important; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; color: var(--green) !important; }
.gal-gate-remember { align-items: center; text-align: left; margin: 2px 0; font-size: 12px; }
.gal-gate-remember span { color: rgba(244,241,235,.6); }
/* The gate stretches every input full-width; keep the remember tick a tick. */
.gal-gate-card input[type="checkbox"] { width: 16px; height: 16px; min-height: 0; margin: 0; padding: 0; flex: 0 0 auto; accent-color: #2bf5b0; }
.gal-gate-linkbtn { border: 0; background: none; padding: 4px; color: var(--green); font: inherit; font-size: 13px; font-weight: 700; cursor: pointer; }
.gal-gate-linkbtn:hover { text-decoration: underline; }

.gal-cover { position: relative; height: 100vh; height: 100dvh; display: flex; align-items: flex-end; overflow: hidden; }
.gal-cover > img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.gal-cover::after { content: ""; position: absolute; inset: 0; background: linear-gradient(180deg, rgba(17,19,15,.05) 30%, rgba(17,19,15,.72)); }
.gal-cover-copy { position: relative; z-index: 1; width: 100%; padding: 48px; text-align: center; color: #fff; }
.gal-cover-copy .eyebrow { justify-content: center; color: rgba(255,255,255,.82); }
.gal-cover-copy .eyebrow::before { display: none; }
.gal-cover-copy h1 { margin: 14px 0 10px; font-family: var(--galx-title-font, Georgia, serif); font-weight: var(--galx-title-weight, 400); font-style: var(--galx-title-style, normal); font-size: calc(clamp(46px * min(var(--galx-title-scale, 1), 1), 7vw * var(--galx-title-scale, 1), 96px * var(--galx-title-scale, 1)) * var(--galx-title-adjust, 1) * var(--galx-title-fit, 1)); line-height: .98; letter-spacing: var(--galx-title-track, -.03em); text-transform: var(--galx-title-transform, none); overflow-wrap: break-word; }
.gal-cover-meta { margin: 0; color: rgba(255,255,255,.78); font-size: 15px; }
.gal-cover-cta { margin-top: 24px; display: inline-flex; align-items: center; gap: 9px; min-height: 50px; padding: 0 22px; border: 1px solid rgba(255,255,255,.5); border-radius: 14px; color: #fff; font-size: 14px; font-weight: 800; text-decoration: none; transition: background .15s ease; }
.gal-cover-cta:hover { background: rgba(255,255,255,.16); }
.gal-cover-cta .ic { width: 17px; }

.gal-toolbar { position: sticky; top: 0; z-index: 20; display: flex; align-items: center; justify-content: space-between; gap: 16px; padding: 16px 28px; border-bottom: 1px solid var(--galx-line, var(--line)); background: var(--galx-surface, rgba(255,255,255,.92)); backdrop-filter: blur(10px); }
.gal-toolbar-title { min-width: 0; display: flex; flex-direction: column; align-items: flex-start; gap: 3px; }
.gal-toolbar-title strong { font-family: var(--galx-title-font, Georgia, serif); font-weight: var(--galx-title-weight, 400); font-style: var(--galx-title-style, normal); font-size: 22px; color: var(--galx-ink, var(--ink)); text-transform: var(--galx-title-transform, none); }
.gal-toolbar-title span { color: var(--galx-muted, var(--muted)); font-size: 13px; }
.gal-toolbar-actions { display: flex; align-items: center; gap: 10px; }
.gal-toolbar-actions .ic { width: 16px; }
.gal-toolbar-actions [data-fav-filter].active { border-color: var(--galx-accent, var(--green)); background: color-mix(in srgb, var(--galx-accent, var(--green)) 11%, transparent); color: var(--galx-accent, var(--green)); }
.gal-more-menu { position: relative; }
.gal-more-menu summary { width: 44px; padding: 0; list-style: none; cursor: pointer; }
.gal-more-menu summary::-webkit-details-marker { display: none; }
.gal-more-menu[open] > .gal-more-menu-panel { position: absolute; top: calc(100% + 8px); right: 0; min-width: 230px; display: flex; flex-direction: column; padding: 6px; border: 1px solid var(--galx-line, var(--line)); border-radius: 14px; background: var(--galx-surface, #fff); box-shadow: 0 16px 38px rgba(28,28,23,.18); z-index: 30; }
.gal-more-menu-panel a, .gal-more-menu-panel button { min-height: 44px; display: flex; align-items: center; gap: 10px; padding: 0 12px; border: 0; border-radius: 9px; background: transparent; color: var(--galx-ink, var(--ink)); font: inherit; font-size: 14px; font-weight: 700; text-align: left; text-decoration: none; cursor: pointer; }
.gal-more-menu-panel a:hover, .gal-more-menu-panel button:hover { background: rgba(48,71,32,.08); }
.gal-more-menu-panel .ic { width: 17px; flex: 0 0 auto; }
.gal-more-download { width: 100%; }
.gal-more-download > summary { width: 100%; min-height: 44px; box-sizing: border-box; display: flex; align-items: center; gap: 10px; padding: 0 12px; border-radius: 9px; color: var(--galx-ink, var(--ink)); font-size: 14px; font-weight: 700; list-style: none; cursor: pointer; }
.gal-more-download > summary span { white-space: nowrap; }
.gal-more-download > summary::-webkit-details-marker { display: none; }
.gal-more-download > summary:hover { background: rgba(48,71,32,.08); }
.gal-more-download .gal-more-chevron { width: 15px; margin-left: auto; transition: transform .18s ease; }
.gal-more-download[open] .gal-more-chevron { transform: rotate(180deg); }
.gal-more-download-options { margin: 2px 4px 6px 28px; padding-left: 6px; border-left: 1px solid var(--galx-line, var(--line)); }
.gal-more-download-options > a, .gal-more-download-options .gal-dlmenu-group > a { min-height: 44px; padding-inline: 10px; font-size: 13px; font-weight: 650; }

/* --galx-gap-set = an explicit owner-picked spacing (inline on <body>); it
   outranks both the size presets and the phone default below. */
/* CSS grid, not multi-column. Multicol BALANCES unbreakable items, so nine
   photos at "4 columns" filled three columns of three and left the fourth
   empty — the chosen count was a hint, never a guarantee. Grid honours it. */
/* Grid gives an EXACT column count (multi-column balanced instead, so nine
   photos at "4 columns" filled three and left the fourth empty). Masonry comes
   from pm-masonry.js setting each tile a row span from its natural height —
   photos stay direct children, so DOM order and the viewer's swipe order are
   untouched. Without JS this stays a plain aligned grid: uncropped, no overlap. */
.gal-grid { display: grid; grid-template-columns: repeat(var(--galx-cols, 4), minmax(0, 1fr)); gap: var(--galx-gap-set, var(--galx-gap, 8px)); padding: 8px 8px 52px; align-items: start; }
.gal-grid.is-masonry { grid-auto-rows: 2px; row-gap: 0; }
.gal-grid.is-masonry .gal-photo { margin-bottom: var(--galx-gap-set, var(--galx-gap, 8px)); }
/* T10 design: thumbnail size + square-grid style */
.gal-size-large { --galx-cols: 3; --galx-gap: 10px; }
.gal-size-compact { --galx-cols: 5; --galx-gap: 5px; }
.gal-grid-square .gal-photo img { aspect-ratio: 1; object-fit: cover; }
/* T10 design: modern-sans typography option (fonts already loaded) */
/* Heading typefaces (design tab): each class only sets the title vars above.
   serif = the Georgia default; Fraunces ships in upgrade.css (loaded by gallery.php). */
.gal-type-sans { --galx-title-font: Inter, Arial, sans-serif; --galx-title-weight: 700; --galx-title-track: -.045em; }
.gal-type-editorial { --galx-title-font: 'Fraunces', Georgia, serif; --galx-title-weight: 440; --galx-title-track: -.02em; }
.gal-type-elegant { --galx-title-font: 'Fraunces', Georgia, serif; --galx-title-style: italic; --galx-title-weight: 420; --galx-title-track: -.01em; }
.gal-type-display { --galx-title-font: 'Fraunces', Georgia, serif; --galx-title-weight: 750; --galx-title-track: -.035em; }
/* Caps titles run wide — the class-level adjust keeps them balanced while the
   owner's title-size scale (inline var) still applies on top. */
.gal-type-caps { --galx-title-font: Inter, Arial, sans-serif; --galx-title-weight: 650; --galx-title-track: .14em; --galx-title-transform: uppercase; --galx-title-adjust: .72; }
.gal-type-typewriter { --galx-title-font: 'Courier New', Courier, monospace; --galx-title-weight: 700; --galx-title-track: -.01em; }
/* T10 design: minimal (typographic) cover */
.gal-cover.is-minimal { align-items: center; justify-content: center; padding: 48px 24px; }
.gal-cover.is-minimal::after { display: none; }
.gal-cover.is-minimal .gal-cover-copy { color: var(--galx-ink, var(--ink)); padding: 0; }
.gal-cover.is-minimal .eyebrow { color: var(--galx-muted, var(--muted)); }
.gal-cover.is-minimal .eyebrow::before { background: var(--galx-muted, var(--muted)); }
.gal-cover.is-minimal .gal-cover-meta { color: var(--galx-muted, var(--muted)); }
.gal-cover.is-minimal .gal-cover-cta { border-color: var(--galx-accent, var(--galx-line, var(--line))); color: var(--galx-accent, var(--galx-ink, var(--ink))); }
.gal-cover.is-minimal .gal-cover-cta:hover { background: color-mix(in srgb, var(--galx-accent, #304720) 8%, transparent); }
/* Grid handles spacing via gap now — a margin here would double it. */
.gal-photo { position: relative; margin: 0; border-radius: var(--galx-radius, 0px); overflow: hidden; }
.gal-corners-soft { --galx-radius: 14px; } /* legacy preset — an explicit radius (inline var) wins */
/* Photo frames + shadow (design tab) */
.gal-border-thin .gal-photo { border: 1px solid var(--galx-line, #e6e2d8); }
.gal-border-card .gal-photo { padding: 9px 9px 13px; background: #fff; box-shadow: 0 1px 4px rgba(15,17,12,.12); }
.gal-border-card .gal-photo img { border-radius: calc(var(--galx-radius, 0px) * .4); }
.gal-shadow-soft .gal-photo { box-shadow: 0 12px 28px rgba(15,17,12,.18); }
/* Banner cover: a shorter hero between full-bleed photo and minimal. */
.gal-cover.is-banner { height: 58vh; min-height: 380px; }
/* Title position (design tab): default sits low; middle/top move the copy and
   re-aim the photo scrim so the text stays readable. Declared after is-minimal
   so an explicit position also wins on typographic covers. */
.gal-titlepos-middle .gal-cover { align-items: center; }
.gal-titlepos-middle .gal-cover::after { background: linear-gradient(180deg, rgba(17,19,15,.28), rgba(17,19,15,.44)); }
.gal-titlepos-middle .gal-cover-copy { padding-bottom: 48px; } /* re-balance upgrade.css's luxury bottom padding */
.gal-titlepos-top .gal-cover { align-items: flex-start; }
.gal-titlepos-top .gal-cover::after { background: linear-gradient(0deg, rgba(17,19,15,.05) 30%, rgba(17,19,15,.72)); }
.gal-titlepos-top .gal-cover-copy { padding-top: clamp(44px, 8vh, 84px); padding-bottom: 48px; }
/* Natural height — masonry is the look, so nothing is cropped. The square
   option below opts a gallery into uniform tiles deliberately. */
.gal-photo img { display: block; width: 100%; height: auto; cursor: default; transition: transform .4s ease; }
.gal-photo:hover img { transform: scale(1.03); }
/* Client galleries like from inside the viewer (O5) — grid tiles carry no heart. */
.gal-grid.only-favs .gal-photo:not(.fav) { display: none; }

.gal-lifecycle { text-align: center; padding: 9px 20px; font-size: 13px; font-weight: 600; color: var(--muted); background: var(--paper); border-bottom: 1px solid var(--line); }
.gal-lifecycle.is-expired { color: #8a4b12; background: #fdf3dc; }

.gal-footer { display: flex; flex-direction: column; align-items: center; gap: 10px; padding: 44px 24px; border-top: 1px solid var(--line); text-align: center; }
/* T2: the global `footer` rule paints a dark brand band on every page, so the
   gallery footer text is ALWAYS light — regardless of the gallery palette. */
.gal-footer .brand { display: inline-flex; align-items: center; gap: 9px; color: #f2ede3; font-weight: 850; text-decoration: none; }
.gal-footer p { margin: 0; color: rgba(242,237,227,.62); font-size: 13px; }
/* (T17: gallery footers carry no links — cookie choices live on the Cookie
   Policy page, which the consent banner links to.) */

/* Maximised photo viewer (Swiper + pinch / double-tap zoom) */
.pm-viewer { position: fixed; inset: 0; z-index: 1100; display: flex; flex-direction: column; background: #0a0b09; }
.pm-viewer[hidden] { display: none; }
.pm-viewer-top { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: max(10px, env(safe-area-inset-top)) 16px 8px; position: relative; z-index: 4; }
.pm-viewer-count { color: rgba(255,255,255,.72); font-size: 13px; font-weight: 700; }
.pm-viewer-actions { display: flex; align-items: center; gap: 8px; }
.pm-viewer-btn { min-height: 44px; min-width: 44px; padding: 0 13px; display: inline-flex; align-items: center; justify-content: center; gap: 7px; border: 1px solid rgba(255,255,255,.2); border-radius: 999px; background: rgba(255,255,255,.08); color: #fff; font: inherit; font-size: 13px; font-weight: 700; cursor: pointer; text-decoration: none; }
.pm-viewer-btn:hover { background: rgba(255,255,255,.18); }
.pm-viewer [data-viewer-close]:focus-visible { outline: none; box-shadow: none; }
.pm-viewer-btn .ic { width: 18px; }
.pm-viewer-swiper { flex: 1; width: 100%; min-height: 0; }
.pm-viewer-swiper .swiper-slide { display: flex; align-items: center; justify-content: center; padding: 6px; }
.pm-viewer-swiper .swiper-zoom-container { display: flex; align-items: center; justify-content: center; width: 100%; height: 100%; }
.pm-viewer-swiper img { max-width: 100%; max-height: 100%; object-fit: contain; border-radius: 0; }
.gal-corners-soft .pm-viewer-swiper img { border-radius: 4px; }
.pm-viewer-ratingbar { flex: 0 0 auto; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px; padding: 6px 12px max(8px, env(safe-area-inset-bottom)); border-top: 1px solid rgba(255,255,255,.12); background: #0a0b09; position: relative; z-index: 4; }
.pm-viewer-rating-label { color: rgba(255,255,255,.58); font-size: 12px; font-weight: 700; }
.pm-viewer-nav { position: absolute; top: 50%; transform: translateY(-50%); z-index: 4; width: 50px; height: 50px; display: grid; place-items: center; border: 0; border-radius: 50%; background: rgba(255,255,255,.1); color: #fff; cursor: pointer; }
.pm-viewer-nav:hover { background: rgba(255,255,255,.2); }
.pm-viewer-nav.prev { left: 16px; }
.pm-viewer-nav.next { right: 16px; }
.pm-viewer-nav.swiper-button-disabled { opacity: .3; cursor: default; }
.pm-viewer-nav .ic { width: 24px; }
.pm-viewer-report { border-color: rgba(255,120,120,.35); }
/* The owner bar occupies the bottom in the editor, so the hint joins the flow
   instead of being absolutely parked on top of the buttons. The bar takes
   order:1 to stay last — moving the hint instead would send it above the top
   bar, since everything else in this flex column sits at the default order 0. */
.pm-viewer-owner { order: 1; }
@media (max-width: 640px) { .pm-viewer-nav { display: none; } .pm-viewer-btn span { display: none; } .pm-viewer-btn { padding: 0; } .pm-viewer-top { gap: 8px; padding-inline: 12px; } }
@media (max-width: 360px) { .pm-viewer-actions { gap: 4px; } .pm-viewer-top { gap: 6px; padding-inline: 10px; } }

/* Share modal (pm-share.js fallback when navigator.share is unavailable) */
.pm-share-backdrop { position: fixed; inset: 0; z-index: 1200; display: flex; align-items: center; justify-content: center; padding: 20px; background: rgba(17,19,15,.55); backdrop-filter: blur(4px); }
.pm-share-modal { width: min(92vw, 400px); padding: 22px; border-radius: 18px; background: #fff; color: #1c1c17; box-shadow: 0 24px 60px rgba(0,0,0,.35); text-align: center; }
.pm-share-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 10px; }
.pm-share-head h2 { margin: 0; font-size: 18px; text-align: left; }
.pm-share-close { display: inline-flex; align-items: center; justify-content: center; width: 44px; height: 44px; border: 1px solid var(--line, #e3e3de); border-radius: 999px; background: #fff; cursor: pointer; }
.pm-share-close svg { width: 16px; height: 16px; }
.pm-share-qr { width: 200px; height: 200px; margin: 6px auto 10px; border: 1px solid var(--line, #e3e3de); border-radius: 12px; display: block; }
.pm-share-url { margin: 0 0 14px; padding: 10px 12px; border-radius: 10px; background: #f6f6f1; font-size: 13px; word-break: break-all; }
.pm-share-actions { display: flex; gap: 10px; justify-content: center; flex-wrap: wrap; }
.pm-share-btn { display: inline-flex; align-items: center; min-height: 44px; padding: 0 18px; border: 1px solid var(--line, #e3e3de); border-radius: 999px; background: #fff; color: inherit; font: inherit; font-size: 14px; font-weight: 700; cursor: pointer; text-decoration: none; }
.pm-share-btn.primary { background: var(--green, #304720); border-color: var(--green, #304720); color: #fff; }
.pm-share-btn:hover { filter: brightness(.96); }

/* Upload acknowledgment modal on event walls (reuses the share-modal shell) */
.ev-welcome-title { margin: 0 0 8px; font-family: Georgia, serif; font-weight: 500; font-size: 22px; }
.ev-welcome-copy { margin: 0 0 16px; color: #55524a; font-size: 14px; line-height: 1.55; }

/* Viewer heart (event pages — D5 moved liking off the grid tiles).
   The GLYPH is filled, not just tinted: the icon ships fill="none" with a
   currentColor stroke, so recolouring the button left a red outline that reads
   as a hover state rather than "liked". A filled heart is the universal signal.
   The border is tinted too — on the light viewer a transparent border on a
   near-white pill loses the pill's edge entirely. */
.pm-viewer-fav b { font-size: 12px; font-weight: 800; }
.pm-viewer-fav.on { background: rgba(255,255,255,.92); color: #c0392b; border-color: rgba(192,57,43,.45); }
.pm-viewer-fav.on:hover { background: #fff; border-color: rgba(192,57,43,.7); }
.pm-viewer-fav.on .ic { fill: currentColor; }

/* Viewer star rating (client galleries — O2). Its own bottom bar keeps the top
   action row usable on phones and makes the rating hierarchy unambiguous. */
.pm-viewer-stars { display: inline-flex; align-items: center; gap: 2px; }
.pm-viewer-star { min-width: 44px; min-height: 44px; padding: 0 3px; border: none; background: none; color: rgba(255,255,255,.55); }
.pm-viewer-star:hover { background: none; color: rgba(255,255,255,.9); }
.pm-viewer-star .ic { width: 20px; }
.pm-viewer-star.on { color: #f5c542; }
.pm-viewer-star.on .ic { fill: #f5c542; stroke: #f5c542; }

/* In-viewer report confirm strip (replaces window.confirm) */
.pm-viewer-confirm { position: absolute; top: 64px; left: 50%; transform: translateX(-50%); z-index: 7; display: flex; align-items: center; gap: 10px; flex-wrap: wrap; justify-content: center; max-width: min(92vw, 520px); padding: 12px 16px; border-radius: 14px; background: #fff; color: #1c1c17; font-size: 14px; font-weight: 600; box-shadow: 0 16px 40px rgba(0,0,0,.4); }
/* Editor-only owner action bar inside the viewer (Q2). Sits above the zoom
   hint so it never covers the Swiper nav arrows, even at 390px. */
/* Owner action row, in flow BELOW the photo (it used to float over the bottom
   of the image you were trying to judge). One line whenever the labels fit;
   wraps rather than overflowing on an event wall, which adds a fourth button. */
.pm-viewer-owner { flex: 0 0 auto; display: flex; align-items: center; gap: 8px; flex-wrap: wrap; justify-content: center; padding: 10px 12px calc(12px + env(safe-area-inset-bottom)); }
.pm-viewer-owner button { display: inline-flex; align-items: center; gap: 8px; min-height: 44px; padding: 0 18px; border-radius: 999px; border: 1px solid rgba(255,255,255,.16); background: rgba(255,255,255,.1); color: #f3f2ec; font: inherit; font-size: 13.5px; font-weight: 700; cursor: pointer; }
.pm-viewer-owner button:hover:not(:disabled) { background: rgba(255,255,255,.18); }
.pm-viewer-owner button:disabled { opacity: .5; cursor: default; }
.pm-viewer-owner-trigger .ic { width: 17px; height: 17px; }

/* Photo-actions sheet. Full-width rows beat a popover on a phone, and adding a
   sixth action later costs nothing here. */
.pm-sheet { position: fixed; inset: 0; z-index: 1200; display: flex; align-items: flex-end; justify-content: center; background: rgba(6,7,5,.62); }
.pm-sheet-panel { width: min(420px, 100%); display: flex; flex-direction: column; gap: 6px; padding: 14px 14px calc(14px + env(safe-area-inset-bottom)); border-radius: 20px 20px 0 0; background: #17190f; box-shadow: 0 -18px 50px rgba(0,0,0,.5); }
.pm-sheet-title { padding: 2px 6px 8px; color: rgba(243,242,236,.5); font-size: 12px; font-weight: 800; letter-spacing: .06em; text-transform: uppercase; }
.pm-sheet-panel button { display: flex; align-items: center; gap: 12px; width: 100%; min-height: 52px; padding: 0 16px; border: 0; border-radius: 13px; background: rgba(255,255,255,.07); color: #f3f2ec; font: inherit; font-size: 15px; font-weight: 700; text-align: left; cursor: pointer; }
.pm-sheet-panel button:hover:not(:disabled) { background: rgba(255,255,255,.14); }
.pm-sheet-panel button:disabled { opacity: .45; cursor: default; }
.pm-sheet-panel .ic { flex: 0 0 auto; width: 19px; height: 19px; }
.pm-sheet-panel .is-danger { color: #ffb4a8; background: rgba(192,57,43,.18); }
.pm-sheet-panel .is-danger:hover { background: rgba(192,57,43,.3); }
.pm-sheet-cancel { justify-content: center; margin-top: 4px; background: transparent !important; color: rgba(243,242,236,.6) !important; }

/* Grid badge for a proofed photo. Bottom-left is the likes flag's corner, so
   this sits alongside the Cover badge and steps aside in selection mode. */
.ed-wm-flag { position: absolute; top: 8px; right: 8px; display: none; align-items: center; gap: 4px; padding: 3px 9px; border-radius: 999px; background: rgba(17,19,15,.78); color: #cfe3f6; font-size: 10.5px; font-weight: 800; letter-spacing: .04em; text-transform: uppercase; }
.ed-wm-flag .ic { width: 11px; height: 11px; }
.ed-photo.is-watermarked .ed-wm-flag { display: inline-flex; }
.ed-grid.is-selecting .ed-wm-flag { display: none; }
.pm-viewer-confirm button { min-height: 44px; padding: 0 14px; border-radius: 999px; border: 1px solid var(--line, #e3e3de); background: #f6f6f1; font: inherit; font-size: 13px; font-weight: 700; cursor: pointer; }
.pm-viewer-confirm [data-viewer-confirm-yes] { background: #c0392b; border-color: #c0392b; color: #fff; }
.pm-viewer-confirm [data-viewer-confirm-yes]:hover { background: #a93226; }
.pm-viewer-confirm [data-viewer-confirm-no]:hover { background: #eceada; }

/* Original-vs-Web download menus (client galleries only) */
.pm-viewer-dl { position: relative; display: inline-flex; }
.pm-viewer-dlmenu { position: absolute; top: calc(100% + 8px); right: 0; display: flex; flex-direction: column; min-width: 170px; background: #fff; border-radius: 12px; box-shadow: 0 12px 32px rgba(0,0,0,.35); overflow: hidden; z-index: 6; }
.pm-viewer-dlmenu a { padding: 11px 15px; font-size: 14px; font-weight: 600; color: #1c1c17; text-decoration: none; }
.pm-viewer-dlmenu a:hover { background: #f1f1ea; }
.gal-dlmenu-label { padding: 9px 15px 3px; margin: 0; font-size: 11px; font-weight: 800; letter-spacing: .04em; text-transform: uppercase; color: var(--muted); }
.gal-dlmenu-group { display: flex; flex-direction: column; border-top: 1px solid var(--line); }
.gal-dlmenu-group[hidden] { display: none; }

@media (max-width: 1100px) { .gal-grid { grid-template-columns: repeat(min(var(--galx-cols, 4), 3), minmax(0, 1fr)); } }
@media (max-width: 820px) {
  .gal-grid { --galx-gap: 4px; grid-template-columns: repeat(2, minmax(0, 1fr)); padding: 4px 4px 44px; }
  .gal-cover-copy { padding: 28px; }
  .gal-toolbar { display: grid; grid-template-columns: minmax(0, 1fr) auto; column-gap: 14px; align-items: start; padding: 12px 16px; }
  .gal-toolbar-title { width: auto; }
  .gal-toolbar-actions { width: auto; gap: 6px; justify-content: flex-end; }
  .gal-toolbar-actions [data-fav-filter] { gap: 6px; padding-inline: 10px; }
  .gal-toolbar-actions [data-fav-filter-label] { display: none; }
  .gal-toolbar { transition: transform .2s ease-out; }
  .gal-toolbar.is-scroll-hidden { transform: translateY(-100%); }
}
@media (max-width: 520px) { .gal-grid { grid-template-columns: minmax(0, 1fr); padding-inline: 0; } }
@media (max-width: 820px) and (prefers-reduced-motion: reduce) { .gal-toolbar { transition: none; } }

.dash-modal-form textarea { min-height: 84px; padding: 11px 14px; border: 1px solid var(--line); border-radius: 12px; background: #fff; color: var(--ink); font: inherit; font-size: 14px; resize: vertical; }
.dash-modal-form textarea:focus { outline: none; border-color: var(--green); box-shadow: 0 0 0 3px rgba(48,71,32,.12); }
/* iOS Safari zooms the page when a focused text field is under 16px, which jerks
   the layout mid-typing — it bit /faq at 15.5px before. Radios, checkboxes and
   range sliders never take text, so they keep the smaller label size. */
.dash-modal-form input:not([type="radio"]):not([type="checkbox"]):not([type="range"]),
.dash-modal-form textarea,
.dash-modal-form select,
.dash-form-grid input:not([type="radio"]):not([type="checkbox"]):not([type="range"]),
.dash-form-grid textarea,
.dash-form-grid select { font-size: 16px; }

/* ===================== Public profile (social) ===================== */
.pf-body { background: var(--paper); }
.shell { width: var(--shell); margin-inline: auto; }
.pf-profile { width: 100%; margin: 0; padding: 0 clamp(16px, 4vw, 40px); }
.pf-head, .pf-tabs, .pf-panel, .pf-foot-inner { max-width: 1320px; margin-inline: auto; }

/* Slim platform bar */
.pf-bar { position: sticky; top: 0; z-index: 30; padding-inline: clamp(16px, 4vw, 40px); border-bottom: 1px solid var(--line); background: rgba(244,241,235,.92); backdrop-filter: blur(10px); }
.pf-bar-inner { max-width: 1320px; margin-inline: auto; display: flex; align-items: center; justify-content: space-between; gap: 16px; min-height: 60px; }
.pf-bar-logo { display: inline-flex; align-items: center; gap: 9px; color: var(--ink); font-size: 17px; font-weight: 850; letter-spacing: -.02em; text-decoration: none; }
.pf-bar-actions { display: flex; align-items: center; gap: 10px; }
.pf-icon-btn { width: 44px; height: 44px; display: grid; place-items: center; border: 1px solid var(--line); border-radius: 12px; background: #fff; color: var(--ink); cursor: pointer; transition: border-color .15s ease, transform .15s ease; }
.pf-icon-btn:hover { border-color: rgba(17,19,15,.25); transform: translateY(-1px); }
.pf-icon-btn .ic { width: 18px; }

/* Profile header */
.pf-head { display: flex; align-items: flex-start; gap: clamp(28px, 5vw, 56px); padding: 40px 0 26px; }
.pf-head-avatar { flex: 0 0 auto; width: 150px; height: 150px; border-radius: 50%; object-fit: cover; border: 3px solid #fff; box-shadow: 0 12px 36px rgba(17,19,15,.16); }
.pf-head-body { flex: 1; min-width: 0; }
.pf-head-top { display: flex; align-items: flex-start; justify-content: space-between; gap: 20px; flex-wrap: wrap; }
.pf-head-top h1 { margin: 0; font-family: Georgia, serif; font-weight: 400; font-size: 34px; line-height: 1; letter-spacing: -.02em; }
.pf-handle { margin: 8px 0 0; color: var(--muted); font-size: 14px; font-weight: 600; }
.pf-head-actions { display: flex; gap: 10px; }
.pf-head-actions .dash-btn { min-height: 44px; }
.pf-head-actions .dash-btn .ic { width: 16px; }
.dash-btn.is-following { background: var(--paper); color: var(--ink); border-color: var(--line); }
.pf-stats { display: flex; gap: 34px; margin: 22px 0 0; }
.pf-stats span { color: #42483f; font-size: 15px; }
.pf-stats b { color: var(--ink); font-weight: 800; }
.pf-bio { margin: 18px 0 0; max-width: 600px; color: #42483f; font-size: 15px; line-height: 1.6; }
.pf-bio strong { color: var(--ink); }
.pf-meta { display: flex; flex-wrap: wrap; gap: 8px 22px; margin: 14px 0 0; }
.pf-meta span, .pf-meta a { display: inline-flex; align-items: center; gap: 7px; color: var(--muted); font-size: 13px; }
.pf-meta a { color: var(--green); font-weight: 700; text-decoration: none; }
.pf-meta a:hover { text-decoration: underline; }
.pf-meta .ic { width: 15px; color: var(--green); }
.pf-socials { display: flex; gap: 8px; margin: 16px 0 0; }
.pf-socials button { width: 44px; height: 44px; display: grid; place-items: center; border: 1px solid var(--line); border-radius: 10px; background: #fff; color: #42483f; cursor: pointer; transition: transform .15s ease, border-color .15s ease, color .15s ease; }
.pf-socials button:hover { transform: translateY(-1px); border-color: rgba(17,19,15,.25); color: var(--green); }
.pf-socials .ic { width: 18px; }

/* Highlights */
.pf-highlights { display: flex; gap: 28px; padding: 8px 0 24px; overflow-x: auto; }
.pf-highlight { flex: 0 0 auto; display: flex; flex-direction: column; align-items: center; gap: 9px; text-decoration: none; color: var(--ink); }
.pf-hl-ring { width: 76px; height: 76px; padding: 3px; border-radius: 50%; border: 2px solid var(--line); background: var(--paper); transition: border-color .2s ease, transform .2s ease; }
.pf-highlight:hover .pf-hl-ring { border-color: var(--green); transform: translateY(-2px); }
.pf-hl-ring img { width: 100%; height: 100%; border-radius: 50%; object-fit: cover; display: block; }
.pf-highlight small { font-size: 12.5px; font-weight: 600; }

/* Tabs */
.pf-tabs { display: flex; justify-content: flex-start; gap: clamp(28px, 6vw, 64px); border-top: 1px solid var(--line); }
.pf-tabs button { display: inline-flex; align-items: center; gap: 8px; padding: 16px 4px; margin-top: -1px; border: 0; border-top: 2px solid transparent; background: none; color: var(--muted); font: inherit; font-size: 12px; font-weight: 800; letter-spacing: .09em; text-transform: uppercase; cursor: pointer; text-decoration: none; transition: color .15s ease, border-color .15s ease; }
.pf-tabs button .ic { width: 16px; }
.pf-tabs button:hover { color: var(--ink); }
.pf-tabs button.active { color: var(--ink); border-top-color: var(--ink); }
.pf-tabs .pf-tab-cta { margin-left: auto; color: var(--green); }
.pf-tabs .pf-tab-cta.active { color: var(--green); border-top-color: var(--green); }

/* Profile client-login panel */
.p3-clientlogin { padding: 10px 0 4px; }
.p3-client-card { width: 100%; }
.p3-client-card h2 { margin: 0 0 6px; }
.p3-client-card [data-client-step] { display: grid; gap: 12px; margin-top: 6px; }
.p3-client-card label { display: grid; gap: 6px; font-size: 13px; font-weight: 700; color: var(--ink); }
.p3-client-remember { flex-direction: row; align-items: flex-start; gap: 8px; font-weight: 600 !important; color: var(--muted) !important; font-size: 12px !important; }
.p3-client-remember input { width: 16px; height: 16px; margin-top: 1px; accent-color: var(--green); }
.p3-client-code { font-size: 22px !important; font-weight: 800; letter-spacing: .35em; text-indent: .35em; text-align: center; }
.p3-client-resend { border: 0; background: none; padding: 4px; color: var(--green); font: inherit; font-size: 13px; font-weight: 700; cursor: pointer; justify-self: center; }
.p3-client-resend:hover { text-decoration: underline; }
.p3-client-actions { display: flex; gap: 10px; flex-wrap: wrap; margin-top: 12px; }
.p3-client-error { margin: 6px 0 0; color: #a03d3d; font-size: 12.5px; font-weight: 600; }

/* Panels */
.pf-panel { display: none; padding: 26px 0 64px; }
.pf-panel.active { display: block; animation: dashFade .25s ease; }

/* Portfolio — masonry (natural ratios) */
.pf-grid { columns: 260px; column-gap: 12px; }
.pf-tile { position: relative; display: block; width: 100%; margin: 0 0 12px; break-inside: avoid; overflow: hidden; border-radius: 12px; padding: 0; border: 0; background: none; cursor: pointer; }
.pf-tile img { width: 100%; height: auto; display: block; transition: transform .5s ease; }
.pf-tile::after { content: ""; position: absolute; inset: 0; background: rgba(17,19,15,0); transition: background .2s ease; }
.pf-tile:hover img { transform: scale(1.04); }
.pf-tile:hover::after { background: rgba(17,19,15,.28); }
.pf-tile-meta { position: absolute; inset: 0; z-index: 1; display: flex; align-items: center; justify-content: center; gap: 8px; color: #fff; font-weight: 800; font-size: 15px; opacity: 0; transition: opacity .2s ease; }
.pf-tile:hover .pf-tile-meta { opacity: 1; }
.pf-tile-meta .ic { width: 18px; }

/* About panel */
.pf-about2 { display: grid; grid-template-columns: .8fr 1fr; gap: clamp(28px, 5vw, 56px); align-items: start; }
.pf-about2-portrait { overflow: hidden; border-radius: 18px; aspect-ratio: 4 / 5; }
.pf-about2-portrait img { width: 100%; height: 100%; object-fit: cover; }
.pf-about2-copy h2 { margin: 0; font-family: Georgia, serif; font-weight: 400; font-size: clamp(26px, 3vw, 38px); line-height: 1.1; letter-spacing: -.02em; }
.pf-about2-copy p { margin: 16px 0 0; color: #42483f; font-size: 16px; line-height: 1.72; }
.pf-signature { display: block; margin-top: 26px; font-family: "Segoe Script", "Brush Script MT", cursive; font-size: 32px; color: var(--green); }

/* Contact panel */
.pf-contact { display: grid; grid-template-columns: 1.3fr .8fr; gap: clamp(28px, 5vw, 48px); align-items: stretch; }
.pf-contact-form h2 { margin: 0; font-family: Georgia, serif; font-weight: 400; font-size: 28px; letter-spacing: -.02em; }
.pf-contact-form > p { margin: 8px 0 18px; color: var(--muted); font-size: 14.5px; line-height: 1.55; }
.pf-contact-form label { display: block; margin-top: 14px; font-size: 13px; font-weight: 700; color: #42483f; }
.pf-field { width: 100%; margin-top: 7px; min-height: 48px; padding: 12px 14px; border: 1px solid var(--line); border-radius: 12px; background: #fff; color: var(--ink); font: inherit; font-size: 14px; }
textarea.pf-field { min-height: auto; resize: vertical; }
.pf-field:focus { outline: none; border-color: var(--green); box-shadow: 0 0 0 3px rgba(48,71,32,.13); }
.pf-field-row { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
.pf-contact-form .dash-btn { margin-top: 18px; min-height: 50px; }
.pf-contact-info { display: flex; flex-direction: column; padding: 26px; border: 1px solid var(--line); border-radius: 18px; background: #fff; box-shadow: 0 12px 36px rgba(17,19,15,.05); }
.pf-contact-info h3 { margin: 0 0 16px; font-size: 18px; font-weight: 800; }
.pf-contact-info ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 16px; }
.pf-contact-info li { display: flex; align-items: center; gap: 13px; }
.pf-contact-info i { flex: 0 0 auto; width: 40px; height: 40px; display: grid; place-items: center; border-radius: 11px; background: #eef3e9; color: var(--green); }
.pf-contact-info i .ic { width: 19px; }
.pf-contact-info span { display: flex; flex-direction: column; font-size: 14px; color: #42483f; }
.pf-contact-info strong { color: var(--muted); font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: .05em; }
.pf-contact-social { display: flex; gap: 8px; margin-top: auto; padding-top: 22px; border-top: 1px solid var(--line); }
.pf-contact-social button { width: 44px; height: 44px; display: grid; place-items: center; border: 1px solid var(--line); border-radius: 50%; background: #fff; color: var(--ink); cursor: pointer; transition: transform .15s ease, border-color .15s ease; }
.pf-contact-social button:hover { transform: translateY(-1px); border-color: rgba(17,19,15,.25); }
.pf-contact-social .ic { width: 18px; }

/* Footer */
.pf-foot { border-top: 1px solid var(--line); }
.pf-foot-inner { display: flex; align-items: center; justify-content: space-between; gap: 16px; flex-wrap: wrap; padding: 26px 0; }
.pf-foot-name { font-family: Georgia, serif; font-size: 16px; }
.pf-foot-made { color: var(--muted); font-size: 12.5px; }

@media (max-width: 720px) {
  .pf-head { flex-direction: column; align-items: center; text-align: center; gap: 18px; padding-top: 28px; }
  .pf-head-avatar { width: 116px; height: 116px; }
  .pf-head-top { flex-direction: column; align-items: center; }
  .pf-meta, .pf-socials { justify-content: center; }
  .pf-bio { text-align: center; }
  /* Keep tab labels on phones — icon-only tabs are unguessable. Left-aligned
     with a hidden-scrollbar overflow: a centred row that doesn't quite fit
     clips both edges and can't be scrolled back. */
  .pf-tabs { gap: 10px; justify-content: flex-start; overflow-x: auto; scrollbar-width: none; }
  .pf-tabs::-webkit-scrollbar { display: none; }
  .pf-tabs button { gap: 5px; padding-inline: 5px; font-size: 10.5px; letter-spacing: .04em; white-space: nowrap; }
  .pf-tabs button .ic { width: 14px; }
  .pf-about2 { grid-template-columns: 1fr; gap: 24px; }
  .pf-about2-portrait { aspect-ratio: 3 / 2; }
  .pf-contact { grid-template-columns: 1fr; }
  .pf-field-row { grid-template-columns: 1fr; }
}

/* -------------------------------------------------- dashboard (live app) */
.dash-cover-empty { width: 44px; height: 44px; flex: 0 0 auto; border-radius: 10px; background: linear-gradient(135deg, #e6ecdf, #cdd8c2); display: inline-block; }
.dash-gcard-placeholder { width: 100%; aspect-ratio: 3 / 2; display: flex; align-items: center; justify-content: center; background: linear-gradient(135deg, #eef2e9, #d8e0cd); color: #93a087; }
.dash-gcard-placeholder .ic { width: 34px; height: 34px; }
.dash-gcard-placeholder.is-event { background: linear-gradient(135deg, #efeaf7, #ddd2ef); color: #7655ad; }
.dash-gcard.is-event { border-color: rgba(118,85,173,.35); box-shadow: 0 10px 34px rgba(118,85,173,.12); }
.dash-gcard.is-event .dash-btn-primary { background: #7655ad; }
.dash-gcard.is-event .dash-btn-primary:hover { background: #684a9c; }
.dash-event-badge { display: inline-block; white-space: nowrap; margin-left: 8px; padding: 3px 9px; border-radius: 999px; background: rgba(118,85,173,.14); color: #7655ad; font-size: 11px; font-weight: 800; letter-spacing: .04em; text-transform: uppercase; vertical-align: middle; }
.dash-status.is-event { background: rgba(118,85,173,.14); color: #7655ad; }
.dash-empty-panel { padding: 44px 30px; text-align: center; display: grid; gap: 10px; justify-items: center; }
.dash-empty-panel p { max-width: 460px; margin: 0; color: var(--muted); }
.dash-type-picker { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.dash-type-option { position: relative; display: block; cursor: pointer; }
.dash-type-option input { position: absolute; opacity: 0; pointer-events: none; }
.dash-type-option span { display: grid; gap: 4px; min-height: 100%; padding: 13px 14px; border: 1.5px solid var(--line); border-radius: 14px; background: #fff; transition: border-color .15s, box-shadow .15s; }
.dash-type-option small { color: var(--muted); font-size: 12px; line-height: 1.45; font-weight: 500; }
.dash-type-option input:checked + span { border-color: var(--green); box-shadow: 0 0 0 3px rgba(74,103,65,.12); }
.dash-type-option.is-event input:checked + span { border-color: #7655ad; box-shadow: 0 0 0 3px rgba(118,85,173,.14); }
.dash-type-option.is-event strong { color: #7655ad; }

/* Event go-live picker (N1) */
.dash-golive { display: grid; gap: 8px; margin: 0; padding: 0; border: 0; }
.dash-golive legend { padding: 0; margin-bottom: 2px; font-size: 14px; font-weight: 600; }
.dash-modal-form .dash-golive label { display: flex; flex-direction: row; align-items: flex-start; gap: 10px; padding: 10px 12px; border: 1.5px solid var(--line); border-radius: 12px; background: #fff; cursor: pointer; transition: border-color .15s, box-shadow .15s; }
.dash-golive input { margin-top: 3px; accent-color: #7655ad; flex: none; }
.dash-golive span { display: grid; gap: 2px; font-size: 14px; }
.dash-golive small { color: var(--muted); font-size: 12px; line-height: 1.45; font-weight: 500; }
.dash-golive label:has(input:checked) { border-color: #7655ad; box-shadow: 0 0 0 3px rgba(118,85,173,.14); }
/* Radios match :focus-visible after a MOUSE click in Chrome and Firefox (arrow
   keys move within a group, so the browser treats them as keyboard-operable).
   That put the global gold ring around the little circle on every click. Drop
   it from the input and give the whole card a ring in the modal's own purple —
   keyboard users keep an indicator, mouse users just see the card select. */
.dash-modal-form .dash-golive input:focus-visible,
.dash-type-option input:focus-visible { outline: none; }
.dash-modal-form .dash-golive label:has(input:focus-visible) { border-color: #7655ad; box-shadow: 0 0 0 3px rgba(118,85,173,.32); }
.dash-type-option:has(input:focus-visible) span { border-color: #7655ad; box-shadow: 0 0 0 3px rgba(118,85,173,.32); }
/* The event window/limit fieldsets reuse .dash-golive for spacing but hold real
   inputs, not radio rows — so the tappable-card styling above is undone here.
   Inputs stay 16px: iOS Safari zooms the page on focus below that. */
/* Title left, "optional" pill hard right on the same line. A legend is
   shrink-to-fit by default, which is what pushed the pill onto its own row —
   hence the explicit full width. */
.dash-event-window legend, .dash-event-limits legend { display: flex; width: 100%; align-items: center; justify-content: space-between; gap: 10px; }
.dash-event-window legend span, .dash-event-limits legend span { flex: none; padding: 3px 8px; border-radius: 999px; background: var(--line); color: var(--muted); font-size: 10.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; }
/* Each optional block reads as its own section rather than more of the form */
.dash-modal-form .dash-event-window, .dash-modal-form .dash-event-limits { gap: 11px; margin-top: 6px; padding-top: 16px; border-top: 1px solid var(--line); }
.dash-modal-form .dash-event-window label, .dash-modal-form .dash-event-limits label { display: grid; gap: 5px; padding: 0; border: 0; background: none; cursor: default; font-size: 13px; font-weight: 600; color: var(--muted); }
.dash-event-window input, .dash-event-limits input { margin-top: 0; width: 100%; min-height: 44px; padding: 10px 12px; border: 1.5px solid var(--line); border-radius: 12px; background: #fff; font: inherit; font-size: 16px; font-weight: 500; color: var(--ink); }
.dash-event-window input:focus-visible, .dash-event-limits input:focus-visible { outline: 2px solid #7655ad; outline-offset: 1px; }
.dash-field-note { margin: 0 0 2px; color: var(--muted); font-size: 12px; line-height: 1.5; }
.dash-slider-label input[type="range"] { min-height: 28px; padding: 0; border: 0; background: none; accent-color: #7655ad; }
.dash-slider-out { display: block; color: var(--ink); font-size: 12.5px; font-weight: 600; line-height: 1.45; }
/* Same controls in the gallery manager's Settings tab */
.ed-event-uploads { display: grid; gap: 10px; }
.ed-event-uploads label { display: grid; gap: 5px; font-size: 13px; font-weight: 600; color: var(--muted); }
.ed-event-uploads input[type="datetime-local"], .ed-event-uploads input[type="number"] { width: 100%; min-height: 44px; padding: 10px 12px; border: 1.5px solid var(--line); border-radius: 12px; background: #fff; font: inherit; font-size: 16px; font-weight: 500; color: var(--ink); }
.ed-event-uploads input[type="range"] { width: 100%; min-height: 28px; accent-color: #7655ad; }
.ed-event-actions { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 4px; }
.dash-modal-error { margin: 0; padding: 10px 14px; border: 1px solid rgba(196,74,74,.4); border-radius: 12px; background: rgba(196,74,74,.08); color: #a03d3d; font-size: 13px; font-weight: 600; }
.dash-avatar-row { display: flex; align-items: center; gap: 16px; margin-bottom: 18px; }
.dash-avatar-row img { width: 72px; height: 72px; border-radius: 50%; object-fit: cover; border: 1px solid var(--line); }
.dash-avatar-row > div { display: grid; gap: 3px; justify-items: start; }
.dash-avatar-row small { color: var(--muted); }
.dash-file-btn { margin-top: 6px; cursor: pointer; }
.dash-avatar-actions { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.dash-avatar-actions .dash-btn { margin-top: 6px; }
.dash-avatar-row img.dash-about-preview { border-radius: 12px; }
.dash-avatar-row img.dash-about-preview.is-empty { opacity: .45; }
.dash-about-avatar-opt { display: flex; align-items: center; gap: 8px; margin-top: 8px; color: #42483f; font-size: 13px; font-weight: 600; cursor: pointer; }
.dash-about-avatar-opt input { accent-color: var(--green); width: 16px; height: 16px; }

/* Cover focal-point picker (Q4) */
.ed-focal { display: grid; gap: 8px; padding: 15px 0 0; border-top: 1px solid var(--line); }
.ed-focal > span { display: grid; gap: 2px; }
.ed-focal small { color: var(--muted); }
.ed-focal-stage { position: relative; border: 1px solid var(--line); border-radius: 12px; overflow: hidden; cursor: crosshair; background: #f0ece4; }
.ed-focal-stage img { display: block; width: 100%; }
.ed-focal-dot { position: absolute; width: 18px; height: 18px; border: 3px solid #fff; border-radius: 50%; background: var(--green); box-shadow: 0 1px 6px rgba(0,0,0,.45); transform: translate(-50%, -50%); pointer-events: none; }
.ed-focal [data-focal-reset] { justify-self: start; }
.dash-input-prefix { display: flex; align-items: center; border: 1px solid var(--line); border-radius: 12px; background: #fff; overflow: hidden; }
.dash-input-prefix em { padding: 0 2px 0 14px; color: var(--muted); font-style: normal; font-size: 14px; white-space: nowrap; }
.dash-input-prefix input { border: 0 !important; border-radius: 0 !important; flex: 1; min-width: 0; padding-left: 4px !important; }
.dash-input-prefix:focus-within { border-color: var(--green); }

/* Phone: modals become compact + fully scrollable so no step gets stuck below the fold. */
@media (max-width: 700px) {
  .dash-modal-backdrop { padding: 12px; align-items: start; }
  .pm-confirm-backdrop { align-items: center; }
  /* Sides stay tight on a phone to keep inputs wide, but the top and bottom
     need real breathing room — the heading and the submit button were sitting
     hard against the modal edge. */
  .dash-modal { padding: 24px 17px 26px; max-height: calc(100vh - 24px); max-height: calc(100dvh - 24px); border-radius: 18px; }
  .dash-modal-head h2 { font-size: 21px; }
  .dash-modal-form input, .dash-modal-form textarea, .dash-modal-form select { min-width: 0; max-width: 100%; }
  .dash-profile-setup { margin: 0; padding-bottom: 32px; scroll-margin-top: 92px; }
  .dash-profile-setup .dash-wizard { padding: 22px 18px; border-radius: 18px; }
  .dash-wizard-top { align-items: flex-start; margin-bottom: 22px; }
  .dash-wizard-top > span { max-width: 180px; font-size: 10.5px; line-height: 1.4; }
  .dash-wizard-exit { min-height: 44px; }
  .dash-wizard-heading { margin-bottom: 15px; }
  .dash-wizard-progress { margin-bottom: 22px; }
  .dash-wizard .dash-modal-form { gap: 16px; }
  .dash-wizard fieldset { gap: 14px; }
  .dash-wizard-lead { font-size: 14px; }
  .dash-wizard-nav { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .dash-wizard-nav .dash-btn { width: 100%; min-width: 0; margin-left: 0; }
  .dash-wizard-nav [data-wizard-back][hidden] + .dash-btn-primary { grid-column: 1 / -1; }
}
.dash-profile-state { position: relative; overflow: hidden; }
.dash-profile-state .dash-toggle-row { border: 0; padding: 0; position: relative; z-index: 2; }
.dash-profile-state.is-enabled { border-color: rgba(74,103,65,.4); }
/* No photograph behind this card any more. It sat directly under the switch and
   two rounds of gradients and halos still left the control hard to read — a
   decorative image competing with the only control on the card is a fight the
   control should never have to have. A flat brand wash instead. */
.dash-profile-state-art { display: none; }
.dash-profile-state { background: linear-gradient(120deg, #fbfaf7 0%, #f2f5ee 100%); }
.dash-profile-state.is-enabled { background: linear-gradient(120deg, #f4f8f0 0%, #e8f0e0 100%); }
/* Belt and braces: a white halo means the switch reads against ANY photo, not
   just this one — the hero image is admin-changeable. */
.dash-profile-state .dash-switch { box-shadow: 0 0 0 5px rgba(255,255,255,.95), 0 2px 10px rgba(17,19,15,.22); }
/* The switch is 27px tall by design; this extends only the TAP area to 45px
   without changing how it looks. Uses ::before — ::after is already the knob
   (see .dash-switch::after above); overriding it erases the knob entirely. */
.dash-profile-state .dash-switch::before { content: ""; position: absolute; inset: -9px; border-radius: 999px; }
@media (max-width: 720px) { .dash-profile-state-art { display: none; } }
@media (max-width: 640px) {
  .dash-type-picker { grid-template-columns: 1fr; }
}

/* -------------------------------------------------- gallery manager (editor.php) */
.ed-body { min-height: 100svh; display: flex; flex-direction: column; background: var(--paper, #f6f5f1); }
.ed-topbar { display: flex; align-items: center; gap: 14px; padding: 14px clamp(16px, 3vw, 30px) 10px; }
.ed-title { flex: 1; min-width: 0; }
.ed-title h1 { margin: 0; display: flex; align-items: center; gap: 9px; min-width: 0; font-size: clamp(17px, 2.4vw, 22px); letter-spacing: -.02em; }
/* Only the title text ellipsises — the Event badge stays visible on long titles. */
.ed-title-text { min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ed-title h1 .dash-event-badge { margin-left: 0; flex: 0 0 auto; }
.ed-title p { margin: 2px 0 0; color: var(--muted); font-size: 12.5px; font-weight: 600; }
/* 1600, not 1280: at 1920 the old cap wasted 320px each side and squeezed the
   design preview into an 822px column, so the desktop frame could never be more
   than two-thirds size. Share (640) and Settings (1000) cap themselves, and the
   photo grid just fits more per row, so only Design gains from the extra width. */
.ed-main { flex: 1; width: min(1600px, 100%); margin: 0 auto; padding: clamp(16px, 3vw, 30px); }
.ed-photos-col { display: grid; gap: 18px; min-width: 0; }
.ed-uploader { padding: 16px; }
.ed-drop { display: grid; justify-items: center; gap: 8px; padding: 34px 18px; border: 2px dashed rgba(74,103,65,.4); border-radius: 16px; background: rgba(74,103,65,.05); color: var(--ink, #1e241b); text-align: center; cursor: pointer; transition: border-color .15s, background .15s; }
.ed-drop .ic { width: 30px; height: 30px; color: var(--green); }
.ed-drop small { color: var(--muted); }
.ed-drop.is-drag, .ed-drop:hover { border-color: var(--green); background: rgba(74,103,65,.1); }
.ed-event .ed-drop { border-color: rgba(118,85,173,.4); background: rgba(118,85,173,.06); }
.ed-event .ed-drop .ic { color: #7655ad; }
.ed-event .ed-drop.is-drag, .ed-event .ed-drop:hover { border-color: #7655ad; background: rgba(118,85,173,.11); }
.ed-progress { margin-top: 14px; display: grid; gap: 8px; }
.ed-progress-head { display: flex; justify-content: space-between; gap: 12px; font-size: 13px; font-weight: 700; }
.ed-progress-head span:last-child { color: var(--muted); }
.ed-progress-errors { margin: 0; color: #a03d3d; font-size: 12.5px; font-weight: 600; }
.ed-photos-panel { min-height: 200px; }
.ed-grid { margin-top: 16px; display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 10px; }
.ed-photo { position: relative; margin: 0; border-radius: 12px; overflow: hidden; aspect-ratio: 1; background: #e8ece3; transition: opacity .35s, transform .35s; }
.ed-photo.is-new { opacity: 0; transform: scale(.94); }
.ed-photo img { width: 100%; height: 100%; object-fit: cover; display: block; }
.ed-photo-actions { position: absolute; inset: auto 8px 8px auto; display: flex; gap: 6px; opacity: 0; transition: opacity .15s; }
.ed-photo:hover .ed-photo-actions, .ed-photo:focus-within .ed-photo-actions { opacity: 1; }
@media (hover: none) { .ed-photo-actions { opacity: 1; } }
.ed-photo-actions button { width: 34px; height: 34px; display: grid; place-items: center; border: 0; border-radius: 10px; background: rgba(17,19,15,.72); color: #fff; cursor: pointer; }
.ed-photo-actions button:hover { background: rgba(17,19,15,.9); }
.ed-photo-actions button[data-portfolio].is-published { background: var(--green); }
.ed-photo-actions button[data-portfolio].is-published:hover { background: #3f7d2f; }
.ed-photo-actions .ic { width: 16px; height: 16px; }

/* Profile tab. The page itself is profile.php in a same-origin frame, so there
   is nothing here that styles the profile — only the frame around it and the
   modals its pencils open. An earlier version hand-copied the markup and every
   rule that "fixed" it made the preview disagree with the published page. */
.dash-pf-wrap { max-width: none; }
/* Editing is one named button beside the on/off switch, not pencils floating
   over the preview — you read what it does before you click it. */
/* Status and its controls stay together instead of being pushed to opposite
   ends of a full-width card. */
/* flex-start, NOT space-between: on a full-width card space-between threw the
   control ~900px from the words it belongs to, which is what made a switch
   there feel like decoration. The button now sits directly beside the status. */
.dash-profile-state-main { position: relative; z-index: 1; display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-start; gap: 22px; }
.dash-profile-state-copy { display: grid; gap: 3px; min-width: 0; flex: 0 1 auto; max-width: 46ch; }
.dash-profile-state-copy strong { font-size: 15px; }
.dash-profile-state-copy small { color: var(--muted); font-size: 13px; line-height: 1.5; overflow-wrap: anywhere; }
/* Owner's call: the actions sit at the right edge on desktop. The copy is
   capped at 46ch above, so the two never drift apart as far as they did when
   the whole row was space-between. */
.dash-profile-state-actions { display: flex; flex-wrap: wrap; gap: 10px; flex: 0 0 auto; }
@media (min-width: 701px) { .dash-profile-state-actions { margin-left: auto; } }
.dash-profile-state-actions .dash-btn { gap: 8px; }
.dash-profile-state-actions .ic { width: 15px; height: 15px; }

/* Says what it will DO, and looks like the consequence: green to publish,
   red-edged to take it down. */
.dash-pf-visibility { border: 1px solid var(--line); background: #fff; color: #42483f; }
.dash-pf-visibility:hover { border-color: rgba(17,19,15,.3); }
.dash-pf-visibility.on { border-color: rgba(178,59,59,.45); color: #a33636; }
.dash-pf-visibility.on:hover { background: #fdf4f4; border-color: #b23b3b; }
.dash-pf-visibility:not(.on) { border-color: rgba(74,103,65,.5); color: var(--green); }
.dash-pf-visibility:not(.on):hover { background: #f4f8f0; border-color: var(--green); }

@media (max-width: 700px) {
  .dash-profile-state-main { flex-direction: column; align-items: stretch; }
  .dash-profile-state-actions { flex-direction: column; }
  .dash-profile-state-actions .dash-btn { width: 100%; justify-content: center; }
}
.dash-pf-frame-wrap { border-radius: 16px; overflow: hidden; background: var(--paper); }
.dash-pf-frame { display: block; width: 100%; height: 900px; border: 0; }

.dash-pf-modal .dash-modal-form label { font-size: 12.5px; }
.dash-pf-modal .dash-modal-form textarea { resize: vertical; }
.dash-pf-modal-wide .dash-modal { width: min(940px, 100%); }

/* Photo left, the fields that describe you on the right. The photo is itself
   the control, so there is no separate "Profile photo" heading to read. */
.dash-pf-identity { display: grid; gap: 18px; align-items: start; }
/* Column sized to the button under the photo, not to the old 148px avatar —
   at 168px the button sat noticeably wider than the picture above it. */
@media (min-width: 660px) { .dash-pf-identity { grid-template-columns: 136px minmax(0, 1fr); gap: 24px; } }
.dash-pf-photo { display: grid; gap: 10px; justify-items: center; }
/* 96px is the placeholder avatar's own size, so it is never upscaled, and the
   column lines up with the fields beside it. */
.dash-pf-photo-btn { position: relative; display: block; width: 96px; max-width: 100%; aspect-ratio: 1; border-radius: 50%; overflow: hidden; cursor: pointer; background: #f0ece4; }
.dash-pf-photo-btn img { width: 100%; height: 100%; object-fit: cover; display: block; }
.dash-pf-photo-edit { position: absolute; inset: 0; display: grid; place-items: center; background: rgba(17,19,15,.45); color: #fff; opacity: 0; transition: opacity .15s ease; }
.dash-pf-photo-edit .ic { width: 22px; height: 22px; }
.dash-pf-photo-btn:hover .dash-pf-photo-edit, .dash-pf-photo-btn:focus-within .dash-pf-photo-edit { opacity: 1; }
/* Touch has no hover, so the affordance is always faintly there. */
@media (pointer: coarse) { .dash-pf-photo-edit { opacity: 1; background: rgba(17,19,15,.28); } }
/* A <label> styled as a button: state the centring rather than relying on
   .dash-btn's, or the text sits off to one side inside the box. */
.dash-pf-photo-choose { display: inline-flex; align-items: center; justify-content: center; text-align: center; width: 100%; cursor: pointer; }
.dash-pf-identity-fields { display: grid; gap: 14px; }
@media (min-width: 860px) { .dash-pf-identity-fields { grid-template-columns: 1fr 1fr; } }

/* The address lives above the box as a hint, not as an inline prefix that drew
   a grey seam through the field whenever it took focus. */
.dash-pf-hint { font-size: 12px; font-weight: 600; color: var(--muted); }
.dash-pf-hint b { color: #42483f; font-weight: 800; }
/* "Profile URL  pixmedium.com/handle" on one line. The address is allowed to
   shrink and ellipsise; if it wrapped, the input below would drop out of line
   with its neighbour — the misalignment this field had before. */
.dash-pf-url-label { display: flex; align-items: baseline; gap: 8px; min-width: 0; white-space: nowrap; }
.dash-pf-url-label .dash-pf-hint { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dash-pf-handle-status { font-size: 12px; font-weight: 700; }
.dash-pf-handle-status.is-free { color: var(--green); }
.dash-pf-handle-status.is-taken, .dash-pf-handle-status.is-bad { color: #b23b3b; }
.dash-pf-handle-status.is-busy { color: var(--muted); }
/* The header card is one edit, so its modal holds a lot of short fields — two
   up on anything wider than a phone, full width below. */
.dash-pf-grid { display: grid; gap: 14px; }
@media (min-width: 620px) { .dash-pf-grid { grid-template-columns: 1fr 1fr; } }
.dash-pf-photo-row { display: flex; align-items: flex-start; gap: 14px; padding: 14px; border: 1px solid var(--line); border-radius: 12px; background: #fff; }
.dash-pf-photo-row > img { width: 74px; height: 74px; flex: 0 0 auto; border-radius: 12px; object-fit: cover; background: #f0ece4; }
.dash-pf-photo-row strong { display: block; font-size: 13px; }
.dash-pf-photo-row small { display: block; margin: 3px 0 8px; color: var(--muted); font-size: 12px; line-height: 1.45; }
@media (max-width: 600px) {
  .dash-pf-frame-wrap { border-radius: 12px; }
  .dash-pf-photo-row { flex-direction: column; }
}

.dash-portfolio-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); gap: 12px; margin-top: 14px; }
.dash-portfolio-item img { cursor: default; } /* T13: tiles open the maximised viewer */
.dash-portfolio-item { position: relative; aspect-ratio: 1; border-radius: 12px; overflow: hidden; background: #f0ece4; }
.dash-portfolio-item img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* (T11: the old .dash-portfolio-actions arrow bar is gone — one × per tile.) */
.ed-cover-flag { position: absolute; top: 8px; left: 8px; padding: 3px 9px; border-radius: 999px; background: rgba(17,19,15,.75); color: #fff; font-size: 10.5px; font-weight: 800; letter-spacing: .05em; text-transform: uppercase; display: none; }
.ed-photo.is-cover .ed-cover-flag { display: inline-block; }
.ed-blocked-flag { position: absolute; top: 8px; left: 8px; padding: 3px 9px; border-radius: 999px; background: #b23b3b; color: #fff; font-size: 10.5px; font-weight: 800; letter-spacing: .04em; text-transform: uppercase; z-index: 2; }
.ed-photo.is-blocked img { opacity: .5; filter: grayscale(.35); }
.ed-photo.is-blocked .ed-cover-flag { display: none; }
.ed-photo.is-cover { outline: 2.5px solid var(--green); outline-offset: -2.5px; }
.ed-event .ed-photo.is-cover { outline-color: #7655ad; }
.ed-qr-wrap { display: grid; justify-items: center; gap: 10px; margin-bottom: 16px; text-align: center; }
.ed-qr-wrap img { border: 1px solid var(--line); border-radius: 14px; background: #fff; padding: 8px; }
.ed-qr-wrap p { margin: 0; color: var(--muted); font-size: 13px; line-height: 1.55; }
.ed-share-label { display: grid; gap: 6px; font-size: 12.5px; font-weight: 700; }
.ed-share-row { display: flex; gap: 8px; }
.ed-share-row input { flex: 1; min-width: 0; font-size: 12.5px; }
.ed-selections { margin-top: 16px; }
.ed-sel-list { display: grid; gap: 12px; }
.ed-sel { padding: 14px 16px; border: 1px solid var(--line); border-radius: 14px; background: #fff; }
.ed-sel-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; }
.ed-sel-actions { display: grid; gap: 6px; flex-shrink: 0; }
.ed-sel-actions .dash-btn { padding: 8px 14px; font-size: 12.5px; }
.ed-sel-who { display: grid; gap: 2px; min-width: 0; }
.ed-sel-who strong { font-size: 15px; display: inline-flex; align-items: center; gap: 8px; }
.ed-sel-kind { padding: 1px 8px; border-radius: 999px; font-size: 10.5px; font-weight: 800; letter-spacing: .03em; text-transform: uppercase; }
.ed-sel-kind-live { background: rgba(48,71,32,.12); color: var(--green); }
.ed-sel-kind-submitted { background: rgba(17,19,15,.08); color: var(--muted); }
.ed-sel-kind-ratings { background: rgba(201,138,54,.16); color: #8a5a1a; }
/* T16: each set shows its actual photos */
.ed-sel-thumbs { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 12px; }
.ed-sel-thumb { position: relative; width: 64px; height: 64px; border-radius: 10px; overflow: hidden; background: var(--paper); }
.ed-sel-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.ed-sel-thumb em { position: absolute; left: 0; right: 0; bottom: 0; padding: 2px 0 3px; background: rgba(12,11,8,.62); color: #ffd76a; font-style: normal; font-size: 10.5px; font-weight: 800; text-align: center; }
.ed-sel-thumb-more { display: grid; place-items: center; color: var(--muted); font-size: 12.5px; font-weight: 800; border: 1px dashed var(--line); background: none; }
.ed-sel-who a { font-size: 13px; color: var(--green); text-decoration: none; word-break: break-all; }
.ed-sel-who small { color: var(--muted); font-size: 12.5px; }
.ed-sel-note { margin: 10px 0 0; padding: 10px 12px; background: var(--paper); border-radius: 10px; font-size: 13.5px; color: #2a2d26; white-space: pre-wrap; }
.ed-grid.sel-filtering .ed-photo { opacity: .28; transition: opacity .2s ease; }
.ed-grid.sel-filtering .ed-photo.is-picked { opacity: 1; outline: 3px solid var(--green); outline-offset: -3px; }
.ed-share-send { margin-top: 12px; display: grid; gap: 6px; }
.ed-share-send .dash-btn { justify-content: center; }
.ed-share-hint { color: var(--muted); font-size: 12px; font-weight: 400; }
.ed-password-form { margin-top: 14px; display: grid; gap: 10px; }
.ed-password-form label { display: grid; gap: 6px; font-size: 12.5px; font-weight: 700; }
.ed-password-state { color: var(--muted); font-size: 12.5px; font-weight: 500; }
.ed-password-actions { display: flex; gap: 8px; flex-wrap: wrap; }
.ed-password-form small { color: var(--muted); font-weight: 500; }
.ed-danger { border-color: rgba(196,74,74,.3); }
.ed-delete-btn { color: #a03d3d; border-color: rgba(196,74,74,.4); }
.ed-delete-btn:hover { background: rgba(196,74,74,.08); }
.ed-event .ed-topbar .dash-btn-primary, .ed-event .ed-settings-form .dash-btn-primary, .ed-event .ed-password-form .dash-btn-primary { background: #7655ad; }

/* ---- Share + Settings views */
.ed-share-col { width: min(640px, 100%); display: grid; gap: 18px; }
/* One rhythm across every card grid (was 14 / 16 / 18 in three places), and
   stretch so cards sharing a row end level instead of ragged. The 1000px cap
   left a third of a 1440px screen empty — the editor's own .ed-main already
   caps the page at 1600px, so this can fill it. */
/* Columns, not a grid. These cards hold wildly unequal amounts (a settings card
   with six controls beside a two-line lock), so a row of grid tracks gave one
   tall card and three short ones — stretched, they were empty white boxes; left
   to their natural height, a ragged row. CSS columns FLOW instead: the short
   cards stack under one another and the browser balances the column heights, so
   the short ones fill the space beside the tall one. Two columns max — three
   made every card too narrow for its toggle rows.
   This also keeps it correct for the event editor, which has a different set of
   cards: nothing here names a card or counts them. */
.ed-settings-grid { column-count: 2; column-gap: 16px; }
.ed-settings-grid > * {
  /* A card must never be split down a column boundary. */
  break-inside: avoid;
  -webkit-column-break-inside: avoid;
  margin-bottom: 16px;
}
@media (max-width: 900px) { .ed-settings-grid { column-count: 1; } }

/* ---- Design view: controls column + scaled live preview */
.ed-design-layout { display: grid; grid-template-columns: 380px minmax(0, 1fr); gap: 18px; align-items: start; }
/* A DEFINITE height, not max-height. The stage below takes the leftover with
   flex:1, and that is the number fitPreview() scales the frame into — with
   max-height the panel stays content-sized, so the stage would size itself from
   the frame it is sizing and the two collapse each other (measured: scale fell
   to 0.19). Filling the viewport is also the point: the preview should be as
   large as the screen allows. 122px is the sticky offset, 12 more for air. */
.ed-design-preview { position: sticky; top: 122px; min-width: 0; display: flex; flex-direction: column; gap: 10px; height: calc(100svh - 134px); }
.ed-preview-head { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; margin-bottom: 10px; }
.ed-preview-head > strong { flex: 1 1 auto; min-width: 0; font-size: 13.5px; }
.ed-device-toggle { display: flex; gap: 2px; padding: 2px; border: 1px solid var(--line); border-radius: 11px; background: #fff; }
.ed-device-toggle button { min-height: 34px; padding: 6px 13px; border: 0; border-radius: 9px; background: none; color: var(--muted); font: inherit; font-size: 12.5px; font-weight: 700; cursor: pointer; }
.ed-device-toggle button.active { background: var(--ink, #11130f); color: #fff; }
.ed-preview-stage { flex: 1 1 auto; min-height: 0; display: grid; justify-items: center; align-content: center; padding: 14px; border: 1px solid var(--line); border-radius: 18px; background: #e9e6df; }
.ed-preview-frame-wrap { overflow: hidden; border-radius: 12px; box-shadow: 0 18px 44px rgba(17,19,15,.2); background: #fff; }
.ed-preview-frame-wrap iframe { display: block; border: 0; transform-origin: top left; background: #fff; }
/* Leads the preview column (it sits above the preview in the DOM). On wide
   screens the whole column is sticky, so it rides along; below 1080px the
   column goes static, and this pins itself under the sticky editor chrome
   instead — the height of .ed-chrome is what the 106px offset tracks. */
.ed-apply-bar { position: sticky; top: 106px; z-index: 6; margin: 0 0 12px; display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 10px; padding: 10px 10px 10px 18px; border-radius: 14px; background: var(--ink, #11130f); color: #fff; font-size: 13.5px; font-weight: 700; box-shadow: 0 14px 34px rgba(17,19,15,.3); }
.ed-apply-actions { display: flex; gap: 8px; }
.ed-apply-bar .dash-btn-light { background: rgba(255,255,255,.12); border-color: transparent; color: #fff; }
.ed-apply-bar .dash-btn-light:hover { background: rgba(255,255,255,.2); }
/* The sheet chrome and its trigger are phone-only; at desktop widths the
   preview is simply a column and neither exists. */
.ed-preview-close, .ed-preview-fab, .ed-preview-backdrop { display: none; }

/* ---- Design controls */
.ed-group-hint { display: block; color: var(--muted); font-size: 12px; font-weight: 500; }
.ed-mini-btn { min-height: 34px; padding: 6px 12px; font-size: 12px; }
.ed-swatch-custom { background: conic-gradient(#e66465, #f6d365, #9198e5, #e66465); }
.ed-custom-colours { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; padding-top: 4px; }
.ed-colour-row { display: inline-flex; align-items: center; gap: 8px; font-size: 12.5px; font-weight: 700; color: #42483f; }
.ed-colour-row input[type="color"] { width: 46px; height: 34px; padding: 2px; border: 1px solid var(--line); border-radius: 9px; background: #fff; cursor: pointer; }
.ed-contrast-warn { flex-basis: 100%; color: #a03d3d; font-size: 12px; font-weight: 600; }
.ed-range-row { display: flex; align-items: center; gap: 10px; }
.ed-range-row input[type="range"] { flex: 1; min-width: 0; accent-color: var(--green); }
.ed-range-val { min-width: 56px; text-align: right; color: var(--muted); font-size: 12px; font-weight: 700; font-variant-numeric: tabular-nums; }
.ed-font-opts label { gap: 9px; }
.ed-font-sample { display: grid; place-items: center; width: 26px; height: 26px; border-radius: 7px; background: var(--paper); font-size: 15px; line-height: 1; color: var(--ink); }
.ed-font-serif { font-family: Georgia, serif; }
.ed-font-editorial { font-family: 'Fraunces', Georgia, serif; font-weight: 440; }
.ed-font-elegant { font-family: 'Fraunces', Georgia, serif; font-style: italic; font-weight: 420; }
.ed-font-sans { font-family: Inter, Arial, sans-serif; font-weight: 700; }
.ed-font-display { font-family: 'Fraunces', Georgia, serif; font-weight: 750; }
.ed-font-caps { font-family: Inter, Arial, sans-serif; font-weight: 650; font-size: 11px; letter-spacing: .08em; text-transform: uppercase; }
.ed-font-typewriter { font-family: 'Courier New', Courier, monospace; font-weight: 700; }

/* ---- Activity view */
.ed-act-head { flex-wrap: wrap; gap: 10px; }
.ed-act-toggle { display: flex; gap: 2px; padding: 2px; border: 1px solid var(--line); border-radius: 11px; background: #fff; }
.ed-act-toggle button { min-height: 36px; padding: 7px 14px; border: 0; border-radius: 9px; background: none; color: var(--muted); font: inherit; font-size: 12.5px; font-weight: 700; cursor: pointer; }
.ed-act-toggle button.active { background: var(--green); color: #fff; }
.ed-act-stats { display: flex; flex-wrap: wrap; gap: 8px; margin: 12px 0 4px; }
.ed-act-chip { display: inline-flex; align-items: center; gap: 7px; padding: 8px 14px; border-radius: 999px; background: var(--paper); color: #42483f; font-size: 12.5px; font-weight: 700; }
.ed-act-chip .ic { width: 14px; height: 14px; color: var(--green); }
.ed-act-people { display: grid; gap: 10px; margin-top: 12px; }
.ed-person { border: 1px solid var(--line); border-radius: 14px; background: #fff; overflow: hidden; }
.ed-person-row { display: flex; align-items: center; gap: 12px; width: 100%; padding: 13px 16px; border: 0; background: none; font: inherit; text-align: left; cursor: pointer; }
.ed-person-row:hover { background: #fafaf7; }
.ed-person-chevron { width: 15px; height: 15px; flex: 0 0 auto; color: var(--muted); transition: transform .18s ease; }
.ed-person.is-open .ed-person-chevron { transform: rotate(90deg); }
.ed-person-who { flex: 1; min-width: 0; display: grid; gap: 2px; }
.ed-person-who strong { display: inline-flex; align-items: center; gap: 8px; font-size: 14.5px; }
.ed-person-who small { color: var(--muted); font-size: 12.5px; overflow-wrap: anywhere; }
.ed-person-count { display: inline-flex; align-items: center; gap: 6px; flex: 0 0 auto; color: var(--green); font-size: 13.5px; font-weight: 800; font-variant-numeric: tabular-nums; }
.ed-person-count .ic { width: 15px; height: 15px; }
.ed-person-body { padding: 0 16px 14px; border-top: 1px solid #f0ede5; }
.ed-person-body .ed-sel-thumbs { margin-top: 12px; }
.ed-person-actions { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 12px; }
.ed-person-actions .dash-btn { padding: 8px 14px; font-size: 12.5px; }
.ed-actph-row { display: grid; grid-template-columns: 64px 110px 130px minmax(0, 1fr) auto; gap: 12px; align-items: center; padding: 9px 4px; border-bottom: 1px solid #f0ede5; }
.ed-actph-row:last-child { border-bottom: 0; }
.ed-actph-head { padding-top: 14px; color: var(--muted); font-size: 11.5px; font-weight: 800; letter-spacing: .05em; text-transform: uppercase; border-bottom: 1px solid var(--line); }
.ed-actph-thumb { width: 64px; height: 64px; border-radius: 10px; overflow: hidden; background: var(--paper); }
.ed-actph-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.ed-actph-stat { display: inline-flex; align-items: center; gap: 6px; font-size: 13px; font-weight: 800; font-variant-numeric: tabular-nums; color: #42483f; }
.ed-actph-likes .ic { width: 14px; height: 14px; color: #c25b5b; }
.ed-actph-stars .ic { width: 14px; height: 14px; color: #c98a36; }
.ed-actph-none { color: var(--muted); font-weight: 600; }
.ed-actph-people { color: var(--muted); font-size: 12.5px; font-weight: 600; overflow-wrap: anywhere; }
.ed-photo.is-flash { outline: 3px solid var(--green); outline-offset: -3px; }

/* ---- Selection (culling), modelled on Google Photos: no Select/Done mode —
   ticking a photo's corner starts the selection, and the bar exists only while
   something is picked. Secondary actions sit under the ⋮ sheet so the row stays
   readable at 390px instead of wrapping into four lines of buttons. */
.ed-pick {
  position: absolute; top: 7px; left: 7px; z-index: 4; width: 26px; height: 26px;
  display: grid; place-items: center; padding: 0; border: 2px solid rgba(255,255,255,.95);
  border-radius: 50%; background: rgba(17,19,15,.34); color: transparent; cursor: pointer;
  opacity: 0; transition: opacity .12s, background .12s, border-color .12s;
  box-shadow: 0 1px 6px rgba(0,0,0,.4); -webkit-backdrop-filter: blur(2px); backdrop-filter: blur(2px);
}
.ed-pick .ic { width: 15px; height: 15px; }
/* Revealed on hover for a clean grid; permanent on touch, where there is no
   hover, and permanent for every tile once a selection is under way. */
.ed-photo:hover .ed-pick, .ed-photo:focus-within .ed-pick,
.ed-grid.has-selection .ed-pick { opacity: 1; }
@media (hover: none) { .ed-pick { opacity: 1; } }
.ed-photo.is-selected .ed-pick { opacity: 1; border-color: var(--green); background: var(--green); color: #fff; }
.ed-photo.is-selected { outline: 3px solid var(--green); outline-offset: -3px; }
.ed-photo.is-selected img { opacity: .74; }
/* While picking, the tile is a target, not a link to the viewer. */
.ed-grid.has-selection .ed-photo { cursor: pointer; }
.ed-grid.has-selection .ed-photo-actions { display: none; }
.ed-grid.has-selection .ed-cover-flag, .ed-grid.has-selection .ed-blocked-flag { display: none; }

.ed-selectbar { position: sticky; top: 108px; z-index: 6; display: flex; align-items: center; gap: 12px; margin-top: 14px; padding: 8px 10px 8px 8px; border-radius: 14px; background: var(--ink, #11130f); color: #fff; font-size: 14px; box-shadow: 0 10px 26px rgba(17,19,15,.22); }
.ed-selectbar > strong { flex: 1; min-width: 0; font-size: 14.5px; font-weight: 800; }
.ed-selectbar-actions { display: flex; align-items: center; gap: 6px; }
.ed-selectbar-x, .ed-selectbar-btn { display: inline-flex; align-items: center; justify-content: center; gap: 7px; min-height: 40px; padding: 0 12px; border: 0; border-radius: 11px; background: rgba(255,255,255,.1); color: #fff; font: inherit; font-size: 13.5px; font-weight: 700; cursor: pointer; }
.ed-selectbar-x { width: 40px; padding: 0; background: transparent; }
.ed-selectbar-x:hover, .ed-selectbar-btn:hover { background: rgba(255,255,255,.2); }
.ed-selectbar-x .ic, .ed-selectbar-btn .ic { width: 17px; height: 17px; }
.ed-selectbar-del { background: rgba(192,57,43,.32); color: #ffc9c0; }
.ed-selectbar-del:hover { background: rgba(192,57,43,.46); }
.ed-selectbar-more { width: 40px; padding: 0; }
@media (max-width: 560px) {
  /* Thumb reach beats a third stacked bar under the sticky editor chrome. */
  .ed-selectbar { position: fixed; top: auto; right: 12px; bottom: calc(12px + env(safe-area-inset-bottom)); left: 12px; z-index: 60; margin: 0; }
  .ed-selectbar-del span { display: none; }
  .ed-selectbar-del { width: 40px; padding: 0; }
}

@media (max-width: 1080px) {
  .ed-design-layout { grid-template-columns: 1fr; }

  /* Below the two-column breakpoint the preview stops being a column and
     becomes a bottom sheet on demand. Stacked, it cost a full screen of scroll
     between the controls and the thing they change; behind the eye button it
     costs one tap and gives the controls the whole display.
     The apply bar rides inside the sheet — so hiding the sheet also removes the
     bar's permanent 90px, and the tab/FAB dots are what advertise it instead. */
  /* A DEFINITE height, not max-height: the stage below takes the leftover with
     flex:1, which gives fitPreview() a stable number to fit the frame into. With
     a content-sized stage the two would chase each other. */
  .ed-design-preview {
    position: fixed; z-index: 60; inset: auto 0 0 0; display: flex; flex-direction: column; gap: 10px;
    height: min(86svh, 740px); padding: 12px 14px calc(14px + env(safe-area-inset-bottom));
    border-radius: 20px 20px 0 0; background: var(--paper, #f6f5f1);
    box-shadow: 0 -18px 50px rgba(17,19,15,.28);
    transform: translateY(101%); visibility: hidden; transition: transform .22s ease, visibility .22s;
  }
  .ed-design-preview.is-open { transform: none; visibility: visible; }
  .ed-preview-head { order: 1; flex: 0 0 auto; margin: 0; }
  .ed-preview-stage { order: 2; flex: 1 1 auto; min-height: 0; overflow: auto; }
  /* Actions to the foot of the sheet: once the preview is what you are looking
     at, "Apply" is the answer to it, not a heading above it. The label is
     dropped here — it wrapped to a second row and stole ~30px from the preview,
     and the dot you just tapped already said there were unsaved changes. */
  .ed-apply-bar { order: 3; flex: 0 0 auto; position: static; margin: 0; padding: 10px; }
  .ed-apply-bar > span:not(.ed-apply-actions) { display: none; }
  .ed-apply-actions { flex: 1; }
  .ed-apply-actions .dash-btn { flex: 1; justify-content: center; }
  .ed-preview-close { display: grid; place-items: center; width: 38px; height: 38px; margin-left: auto; border: 0; border-radius: 11px; background: rgba(17,19,15,.07); color: var(--ink); cursor: pointer; }
  .ed-preview-close .ic { width: 18px; height: 18px; }
  .ed-preview-backdrop { display: block; position: fixed; inset: 0; z-index: 55; background: rgba(17,19,15,.45); }

  .ed-preview-fab {
    display: inline-flex; align-items: center; gap: 8px; position: fixed; z-index: 50;
    right: 16px; bottom: calc(16px + env(safe-area-inset-bottom));
    min-height: 48px; padding: 0 18px; border: 0; border-radius: 999px;
    background: var(--ink, #11130f); color: #fff; font: inherit; font-size: 14px; font-weight: 700;
    box-shadow: 0 12px 30px rgba(17,19,15,.34); cursor: pointer;
  }
  .ed-preview-fab .ic { width: 19px; height: 19px; }
  .ed-event .ed-preview-fab { background: #7655ad; }
  /* Same amber marker as the tab: something is waiting to be applied in here. */
  .ed-preview-fab.is-dirty::after { content: ""; position: absolute; top: 6px; right: 6px; width: 10px; height: 10px; border-radius: 50%; background: #e2a52b; box-shadow: 0 0 0 2px var(--ink, #11130f); }
}
@media (max-width: 1080px) and (prefers-reduced-motion: reduce) {
  .ed-design-preview { transition: none; }
}
@media (max-width: 560px) {
  .ed-hide-narrow { display: none; }
  /* Icons only: five labelled tabs cannot fit at 390px, and a nav you have to
     scroll sideways hides the sections nobody has found yet. aria-label on each
     button keeps the accessible name. */
  .ed-nav { gap: 0; }
  .ed-nav-tab { flex: 1 1 0; min-width: 0; padding: 12px 4px; }
  .ed-nav-tab > span { display: none; }
  .ed-nav-tab .ic { width: 19px; height: 19px; }
  .ed-grid { grid-template-columns: repeat(auto-fill, minmax(110px, 1fr)); }
  .ed-topbar { padding-bottom: 6px; }
  .ed-actph-row { grid-template-columns: 52px auto auto minmax(0, 1fr); gap: 10px; }
  .ed-actph-row > :last-child { justify-self: end; }
  .ed-actph-thumb { width: 52px; height: 52px; }
  .ed-actph-people, .ed-actph-head span:nth-child(4), .ed-actph-head span:nth-child(5) { display: none; }
  .ed-preview-stage { padding: 8px; }
}

/* -------------------------------------------------- public pages (live) */
.gal-missing { min-height: 100svh; display: grid; place-items: center; align-content: center; gap: 12px; padding: 24px; text-align: center; }
.gal-missing h1 { margin: 10px 0 0; font-size: clamp(24px, 4vw, 34px); letter-spacing: -.02em; }
.gal-missing p { max-width: 420px; margin: 0 0 12px; color: var(--muted); line-height: 1.6; }
.gal-empty { padding: 60px 24px 80px; text-align: center; color: var(--galx-muted, var(--muted)); font-weight: 600; }
/* Paged grid footer. Usually the observer has already fetched the next batch by
   the time this scrolls into view, so the button is rarely seen — it is the
   no-observer fallback and the retry after a failed batch. */
.gal-more { display: grid; justify-items: center; gap: 10px; padding: 28px 24px 48px; }
.gal-more-status { margin: 0; color: var(--galx-muted, var(--muted)); font-size: 13.5px; font-weight: 600; }
.gal-gate-error { color: #ffb4b4; font-weight: 700; }
/* T12: sticky owner bar (mirrors the demo bar) — shown enabled OR disabled. */
.p3-ownerbar { position: sticky; top: 0; z-index: 40; display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 5px 12px; min-height: 38px; padding: 8px 16px; background: var(--ink, #1e241b); color: #f2ede3; text-align: center; font-size: 13px; font-weight: 700; }
.p3-ownerbar a { color: #cfe3c2; text-underline-offset: 2px; }
.p3-ownerbar.is-off { background: #241a33; color: #e7ddf6; }
.p3-ownerbar.is-off a { color: #cdb3f2; }
.p3-portfolio-empty { padding: 54px 30px; text-align: center; }
.p3-portfolio-empty h2 { margin: 0 0 10px; font-size: 22px; letter-spacing: -.02em; }
.p3-portfolio-empty p { max-width: 560px; margin: 0 auto; color: var(--muted); line-height: 1.65; }
.p3-socials a { display: grid; place-items: center; width: 44px; height: 44px; border: 1px solid var(--line); border-radius: 50%; background: #fff; color: var(--ink); }
.p3-socials a:hover { border-color: rgba(17,19,15,.3); }
.p3-socials a .ic { width: 17px; height: 17px; }

/* -------------------------------------------------- event guest page */
/* A brand-new wall has no photos, so the page is shorter than the viewport and
   the footer used to stop mid-screen with the paper-coloured html background
   showing under it. Column flex + a full-viewport floor pins it to the bottom.
   dvh over vh so a phone's collapsing toolbar doesn't leave a gap either. */
.ev-body { display: flex; flex-direction: column; min-height: 100vh; min-height: 100dvh; background: #17111f; color: #f2edf8; }
.ev-body .ev-main { flex: 1 0 auto; }
.ev-hero { position: relative; display: grid; justify-items: center; gap: 12px; padding: clamp(34px, 7vw, 70px) 20px clamp(22px, 4vw, 40px); text-align: center; background: radial-gradient(120% 130% at 50% -20%, #3a2a54 0%, #241a33 55%, #17111f 100%); }
/* Invite guests: a bare corner icon — no chrome, but still a 44px tap target */
.ev-share-fab { position: absolute; top: 14px; right: 14px; width: 44px; height: 44px; display: inline-flex; align-items: center; justify-content: center; border: 0; background: none; color: #d9c9f7; cursor: pointer; transition: color .18s; }
.ev-share-fab:hover { color: #fff; }
.ev-share-fab svg { width: 20px; height: 20px; }
.ev-brand { display: inline-flex; align-items: center; gap: 9px; margin-bottom: 6px; color: #f2edf8; font-weight: 800; font-size: 15px; text-decoration: none; }
.ev-brand b { color: #b592ec; }
.ev-eyebrow { margin: 0; display: flex; align-items: center; gap: 10px; color: #b592ec; font-size: 11px; font-weight: 850; letter-spacing: .18em; text-transform: uppercase; }
.ev-eyebrow::before, .ev-eyebrow::after { content: ""; width: 24px; height: 1px; background: currentColor; }
.ev-hero h1 { margin: 0; font-family: Fraunces, Georgia, serif; font-weight: 480; font-size: clamp(34px, 7vw, 58px); line-height: 1.04; letter-spacing: -.02em; }
.ev-sub { max-width: 480px; margin: 0; color: rgba(242,237,248,.66); font-size: 15px; line-height: 1.6; }
.ev-lifecycle { margin: 12px 0 0; font-size: 13px; font-weight: 600; color: rgba(242,237,248,.55); }
.ev-closed { margin: 16px 0 0; padding: 11px 20px; display: inline-block; border: 1px solid rgba(255,255,255,.2); border-radius: 999px; background: rgba(255,255,255,.06); color: rgba(242,237,248,.85); font-size: 14px; font-weight: 600; }
.ev-cta-row { display: flex; gap: 10px; justify-content: center; flex-wrap: wrap; }
.ev-upload-cta { margin-top: 10px; display: inline-flex; align-items: center; gap: 10px; min-height: 54px; padding: 0 15px; border-radius: 999px; background: #8e63d6; color: #fff; font-weight: 850; font-size: 15px; cursor: pointer; box-shadow: 0 18px 50px rgba(142,99,214,.35); transition: transform .18s, background .18s; }
.ev-upload-cta:hover { background: #7d52c6; transform: translateY(-1px); }
.ev-upload-cta .ic { width: 20px; height: 20px; }
.ev-cta-camera { background: rgba(142,99,214,.16); color: #d9c9f7; box-shadow: none; border: 1.5px solid rgba(190,160,240,.55); }
.ev-cta-camera:hover { background: rgba(142,99,214,.26); color: #fff; }
.ev-count { margin: 4px 0 0; color: rgba(242,237,248,.55); font-size: 13px; font-weight: 700; }
.ev-count b { color: #f2edf8; }
.ev-progress { width: min(420px, 92vw); margin-top: 10px; display: grid; gap: 8px; text-align: left; }
.ev-progress .dash-progress { background: rgba(255,255,255,.14); }
.ev-progress .dash-progress span { background: #b592ec; }
.ev-main { padding: clamp(14px, 3vw, 30px); }
.ev-grid { padding: 0; }
.ev-body .gal-photo { background: #241a33; }
.ev-like-count { font-size: 12px; font-weight: 800; font-style: normal; }
.ev-body .gal-empty { color: rgba(242,237,248,.6); }
.ev-footer { border-top: 1px solid rgba(255,255,255,.1); }
.ev-footer, .ev-footer p { color: rgba(242,237,248,.6); }
.ev-footer .brand { color: #f2edf8; }
/* These are the Online Safety Act discoverability links — a guest has to be
   able to actually hit them. inline-block padding lifts the target from ~15px
   to a usable size without changing how the line reads. */
.ev-footer-legal { font-size: 12px !important; font-style: normal !important; opacity: .75; line-height: 2; }
.ev-footer-legal a { color: inherit; text-decoration: none; display: inline-block; padding: 5px 2px; }
.ev-footer-legal a:hover { color: #fff; }

/* editor: favourite count badge on photo tiles */
.ed-like-flag { position: absolute; bottom: 8px; left: 8px; display: inline-flex; align-items: center; gap: 4px; padding: 3px 9px; border-radius: 999px; background: rgba(17,19,15,.72); color: #fff; font-size: 11px; font-weight: 800; }
.ed-like-flag .ic { width: 12px; height: 12px; color: #ff7d9c; }
/* T13: guest-report flag — visible from the very first report. */
.ed-report-flag { position: absolute; top: 8px; right: 8px; display: inline-flex; align-items: center; gap: 4px; padding: 3px 9px; border-radius: 999px; background: #b2843b; color: #fff; font-size: 11px; font-weight: 800; z-index: 2; }
.ed-report-flag .ic { width: 12px; height: 12px; }
.ed-rate-flag { position: absolute; bottom: 8px; right: 8px; display: inline-flex; align-items: center; gap: 4px; padding: 3px 9px; border-radius: 999px; background: rgba(17,19,15,.72); color: #fff; font-size: 11px; font-weight: 800; }
.ed-rate-flag .ic { width: 12px; height: 12px; color: #f5c542; }
.ev-dl-link { color: #b592ec; font-weight: 800; text-decoration: none; border-bottom: 1px solid rgba(181,146,236,.45); }
.ev-dl-link:hover { color: #cdb3f2; }

/* Phone ergonomics: 16px form text prevents Safari's focus zoom, and primary
   controls keep a genuine 44px target without changing the desktop rhythm. */
@media (max-width: 700px) {
  input:not([type]), input[type="text"], input[type="email"], input[type="password"], input[type="search"], input[type="url"], input[type="tel"], input[type="number"], input[type="date"], input[type="datetime-local"], input[type="file"], select, textarea { font-size: 16px !important; }
  .gal-toolbar .dash-btn { min-width: 44px; min-height: 44px; }
  .ed-photo-actions { right: 4px; bottom: 4px; gap: 4px; }
  .ed-photo-actions button { width: 44px; height: 44px; }
  .ev-count .ev-dl-link { min-height: 44px; display: inline-flex; align-items: center; }
  /* Both upload CTAs stay on one line on a phone: the row takes the full width
     and the two buttons share it, so neither drops below the fold. Shrinking the
     text is what buys the room — the 54px tap height is untouched. */
  .ev-cta-row { width: 100%; flex-wrap: nowrap; gap: 8px; }
  .ev-cta-row .ev-upload-cta { flex: 1 1 0; justify-content: center; min-width: 0; gap: 7px; padding: 0 10px; font-size: 14px; white-space: nowrap; }
  .ev-cta-row .ev-upload-cta .ic { flex: none; }
  /* Event timeline actions are the one-tap decisions in Settings — give them the
     full card width on a phone rather than a button floating at its text width. */
  .ed-settings-grid [data-close-uploads], .ed-settings-grid [data-start-now] { width: 100%; justify-content: center; }
}
/* Currency footnote under the pricing intro — checkout localises via Stripe
   Adaptive Pricing, but settlement is GBP, so say so before someone clicks. */
.pricing-currency-note { margin-top: 10px; font-size: 13.5px; color: var(--muted); }

/* --------------------------------------------------------------------------
   Light photo viewer (gallery appearance: viewer = light).
   Dark stays the default — a neutral dark surround judges tone most
   accurately — but high-key / light-and-airy brands can opt into this.
   Scoped to .gal-viewer-light, which only gallery.php ever puts on <body>,
   so the editor and dashboard viewers stay dark.
   Contrast targets AA: ink on near-white for text, and a visible border on
   every control (the dark theme leans on translucent white fills that vanish
   on a light ground).
   -------------------------------------------------------------------------- */
.gal-viewer-light .pm-viewer { background: #f7f6f2; }
.gal-viewer-light .pm-viewer-count { color: rgba(28,30,25,.66); }
/* `:not(.on):not(.pm-viewer-star)` is load-bearing, not tidiness. Every control
   that carries its own state colour — the liked heart, the star strip — is
   defined FURTHER UP this file at the same 0-2-0 weight, so a plain
   `.gal-viewer-light .pm-viewer-btn` beat them on source order alone: a liked
   heart rendered in plain dark ink on this theme, pixel-identical to an unliked
   one, so liking a photo looked like it had failed. Excluding the states here
   is the fix that cannot be undone by adding another state below. */
.gal-viewer-light .pm-viewer-btn:not(.on):not(.pm-viewer-star) {
  border-color: rgba(28,30,25,.18);
  background: rgba(255,255,255,.9);
  color: #1c1e19;
}
.gal-viewer-light .pm-viewer-btn:not(.on):not(.pm-viewer-star):hover { background: #fff; border-color: rgba(28,30,25,.34); }
/* The star strip is bare glyphs, not pills, and its unrated colour is white —
   invisible on this ground. `:not(.on)` so a rated star keeps its gold. */
.gal-viewer-light .pm-viewer-star:not(.on) { color: rgba(28,30,25,.32); }
.gal-viewer-light .pm-viewer-star:not(.on):hover { color: rgba(28,30,25,.62); }
.gal-viewer-light .pm-viewer-nav {
  background: rgba(255,255,255,.86);
  color: #1c1e19;
  box-shadow: 0 2px 10px rgba(17,19,15,.12);
}
.gal-viewer-light .pm-viewer-nav:hover { background: #fff; }
.gal-viewer-light .pm-viewer-ratingbar {
  background: #f7f6f2;
  border-top-color: rgba(28,30,25,.12);
}
.gal-viewer-light .pm-viewer-rating-label { color: rgba(28,30,25,.6); }
.gal-viewer-light .pm-viewer-report { border-color: rgba(176,42,42,.4); color: #a3271f; }
/* A white-ish photo on a white ground loses its edge — a hairline keeps the
   image readable as an object without adding a visible "frame". */
.gal-viewer-light .pm-viewer-swiper img { box-shadow: 0 0 0 1px rgba(28,30,25,.08); }
