/* ============================================
   Studio + Site — Joanna Aplin Fine Art
   Design: soft cream surfaces, teal accent,
   gallery-quality typography, generous whitespace
   ============================================ */

/* App headings: every weight resolves to the Bold file, so a heading can
   never fall back to Nexa Light. Public sites keep the real "Nexa" family. */
@font-face { font-family: "Nexa Display"; font-weight: 300; font-style: normal; font-display: swap; src: url("fonts/NexaTextDemo-Bold.woff2") format("woff2"); }
@font-face { font-family: "Nexa Display"; font-weight: 400; font-style: normal; font-display: swap; src: url("fonts/NexaTextDemo-Bold.woff2") format("woff2"); }
@font-face { font-family: "Nexa Display"; font-weight: 500; font-style: normal; font-display: swap; src: url("fonts/NexaTextDemo-Bold.woff2") format("woff2"); }
@font-face { font-family: "Nexa Display"; font-weight: 600; font-style: normal; font-display: swap; src: url("fonts/NexaTextDemo-Bold.woff2") format("woff2"); }
@font-face { font-family: "Nexa Display"; font-weight: 700; font-style: normal; font-display: swap; src: url("fonts/NexaTextDemo-Bold.woff2") format("woff2"); }
@font-face { font-family: "Nexa Display"; font-weight: 800; font-style: normal; font-display: swap; src: url("fonts/NexaTextDemo-Bold.woff2") format("woff2"); }

/* Nexa Text — self-hosted woff2 (same files joannaaplin.com uses). */
@font-face {
  font-family: "Nexa";
  font-weight: 300;
  font-style: normal;
  font-display: swap;
  src: url("fonts/NexaTextDemo-Light.woff2") format("woff2");
}
@font-face {
  font-family: "Nexa";
  font-weight: 400;
  font-style: normal;
  font-display: swap;
  src: url("fonts/NexaTextDemo-Light.woff2") format("woff2");
}
@font-face {
  font-family: "Nexa";
  font-weight: 500;
  font-style: normal;
  font-display: swap;
  src: url("fonts/NexaTextDemo-Bold.woff2") format("woff2");
}
@font-face {
  font-family: "Nexa";
  font-weight: 600;
  font-style: normal;
  font-display: swap;
  src: url("fonts/NexaTextDemo-Bold.woff2") format("woff2");
}
@font-face {
  font-family: "Nexa";
  font-weight: 700;
  font-style: normal;
  font-display: swap;
  src: url("fonts/NexaTextDemo-Bold.woff2") format("woff2");
}
@font-face {
  font-family: "Nexa";
  font-weight: 800;
  font-style: normal;
  font-display: swap;
  src: url("fonts/NexaTextDemo-Bold.woff2") format("woff2");
}

:root {
  /* Palette — light mode (soft cream + teal) */
  --bg:           #fcfaf7;
  --surface:      #F8F5EE;
  /* Brand marks: Light Black on light UI, Neo Pearl on dark UI. */
  --brand-ink:    #2B2F2D;
  --surface-2:    #F8F5EE;
  --surface-3:    #e6e2d8;
  --surface-elev: #fcfaf7;
  --border:       #e1ddd2;
  --border-soft:  #ece8dc;

  --ink:          #2B2F2D;
  --ink-soft:     #4a504c;
  --ink-mute:     #7a7e78;
  --ink-inverse:  #F8F5EE;

  --accent:       #933994;     /* dark fuchsia */
  --accent-soft:  rgba(147, 57, 148, 0.18);
  --accent-ink:   #F8F5EE;

  --green:        #228B22;
  --amber:        #FFD700;
  --rose:         #2B2F2D;
  --field-bg:     #F8F5EE;
  --bg-2:         #f1ece2;
  --surface-soft: #f2efe7;

  /* Type */
  --font-display: "General Sans", "Helvetica Neue", Arial, sans-serif;
  --font-ui:      "General Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;

  /* Scale */
  --text-xs:    11px;
  --text-sm:    13px;
  --text-base:  14.5px;
  --text-md:    16px;
  --text-lg:    20px;
  --text-xl:    28px;
  --text-2xl:   40px;
  --text-hero:  56px;

  /* Spacing */
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 24px;
  --space-6: 32px;
  --space-7: 48px;
  --space-8: 64px;

  --radius-sm: 4px;
  --radius-md: 10px;
  --radius-lg: 14px;
  --radius-xl: 20px;

  --shadow-sm: 0 1px 2px rgba(31, 36, 33, 0.04), 0 1px 1px rgba(31, 36, 33, 0.03);
  --shadow-md: 0 6px 20px rgba(31, 36, 33, 0.06), 0 2px 6px rgba(31, 36, 33, 0.04);
  --shadow-lg: 0 18px 40px rgba(31, 36, 33, 0.10);

  --transition: 180ms cubic-bezier(.2,.7,.2,1);
}

[data-theme="dark"] {
  /* Light Black (#2B2F2D) is the sidebar/surface. The page sits a shade
     darker so surfaces separate cleanly. */
  --bg:           #232726;
  --surface:      #2B2F2D;
  --brand-ink:    #F8F5EE;
  --surface-2:    #242424;
  --surface-3:    #303030;
  --surface-elev: #262626;
  --border:       #4d5453;
  --border-soft:  #3e4443;

  --ink:          #F8F5EE;
  --ink-soft:     #b9b6ac;
  --ink-mute:     #87867f;
  --ink-inverse:  #2B2F2D;

  /* Dark Fuchsia lightened so it holds up against the charcoal page. */
  --accent:       #C071C1;
  --accent-soft:  rgba(192, 113, 193, 0.22);
  --accent-ink:   #0e1a18;

  --green:        #228B22;
  --amber:        #FFD700;
  --rose:         #F8F5EE;
  --field-bg:     #343833;
  --bg-2:         #343833;
  --surface-soft: #242424;
}

/* ----- Reset ----- */
*, *::before, *::after { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
body {
  font-family: var(--font-ui);
  font-size: var(--text-base);
  color: var(--ink);
  background: var(--bg);
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}
button { font: inherit; color: inherit; cursor: pointer; }
input, select, textarea { font: inherit; color: inherit; }
img { max-width: 100%; display: block; }

/* ----- Shell ----- */
.shell {
  display: grid;
  grid-template-columns: 152px 1fr;
  min-height: 100vh;
  transition: grid-template-columns 220ms ease;
}
.shell.sidebar-collapsed {
  /* 64px = 12px padding + 40px nav-item pill + 12px padding — perfectly centers
     the icon column and gives the "F" wordmark room to render without clipping. */
  grid-template-columns: 64px 1fr;
}

/* ----- Sidebar ----- */
.sidebar {
  /* Brand red field in both expanded and collapsed states. */
  background: #EF4244;
  border-right: 0;
  padding: 22px 10px 22px;
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  position: sticky; top: 0; height: 100vh;
  overflow: hidden;
}

/* Sidebar header: brand mark + name, then artist sub-line */
.sidebar-head { display: flex; flex-direction: column; gap: 6px; overflow: visible; flex-shrink: 0; }

/* Sidebar collapse toggle — v43: lives in sidebar-foot as a ghost button */
/* Sidebar collapse toggle: show Open icon (arrow pointing left) when expanded,
   show Closed icon (arrow pointing right) when collapsed. */
.sidebar-toggle-closed { display: none; }
.shell.sidebar-collapsed .sidebar-toggle-open { display: none; }
.shell.sidebar-collapsed .sidebar-toggle-closed { display: inline-flex; }

.brand {
  display: flex; align-items: center; gap: 10px;
  overflow: visible;
  color: var(--accent);
  min-width: 0;
  /* Left padding matches .nav-item (12px) so the "Folio" wordmark aligns
     vertically with the icon column below. Collapse logic untouched. */
  padding: 0 2px 0 12px;
}
.brand-mark { display: flex; align-items: center; justify-content: center; flex-shrink: 0; }
.brand-mark svg { width: 30px; height: 30px; }
.brand-name {
  font-family: var(--font-display);
  font-size: 28px; font-weight: 600; line-height: 1.1;
  display: flex; align-items: center;
  min-height: 58px;
  color: var(--ink);
  white-space: nowrap;
  overflow: visible;
  text-overflow: ellipsis;
}
.brand-name-mini { display: none; }
.brand-wordmark {
  display: block;
  height: 52px;
  width: auto;
  fill: var(--brand-ink);
  margin: 0 0 0 -1px;
  overflow: visible;
}
.shell.sidebar-collapsed .brand-wordmark { display: none; }
.brand-brandmark {
  display: none;
  height: 34px;
  width: auto;
  fill: var(--brand-ink);
  margin: 0;
  overflow: visible;
}
.shell.sidebar-collapsed .brand-brandmark { display: block; height: 40px; }
.shell.sidebar-collapsed .brand { padding: 0; justify-content: center; }
.shell.sidebar-collapsed .brand-name { justify-content: center; width: 100%; }

.brand-sub {
  font-size: 11px;
  color: var(--ink-mute);
  letter-spacing: 0.02em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  padding: 0 2px;
}

.nav { display: flex; flex-direction: column; gap: 0; margin: auto 0; width: 100%; }
@media (min-width: 861px) {
  .nav {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    left: 12px;
    right: 12px;
    width: auto;
    margin: 0;
  }
}
/* Sidebar nav items: 16px icon at a fixed left position. When the rail
   collapses, padding stays the same so the icon never moves — only the
   label fades and gets clipped by the shrinking sidebar. */
.nav-item {
  text-align: left;
  background: transparent; border: 0;
  padding: 6px 10px;
  border-radius: var(--radius-md);
  color: var(--ink-soft);
  font-size: 13px;
  font-weight: 500;
  transition: background var(--transition), color var(--transition);
  display: flex; align-items: center;
  gap: 10px;
  white-space: nowrap;
  overflow: hidden;
  height: 34px;
  box-sizing: border-box;
  width: 100%;
  min-width: 0;
}
.nav-item .nav-icon {
  width: 16px; height: 16px;
  flex: 0 0 16px;
}
.nav-label {
  opacity: 1;
  transition: opacity 140ms ease;
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
}
.nav-icon { flex-shrink: 0; }
.nav-item:hover { background: var(--surface-2); color: var(--ink); }
.nav-item.is-active {
  background: var(--accent-soft);
  color: var(--accent);
  font-weight: 600;
}
.sidebar-foot { display: flex; flex-direction: column; gap: 0; margin-top: auto; width: 100%; padding-left: 2px; }
.shell.sidebar-collapsed .sidebar-foot { padding-left: 0; }
.sidebar .sidebar-foot .btn-ghost { padding-left: 10px; padding-right: 10px; }
.sidebar-foot .btn-ghost, .sidebar-foot .nav-item { height: 22px; padding-top: 2px; padding-bottom: 2px; }

/* Collapsed state — thin icon-only rail.
   Key idea (ElevenLabs-style): nav-item padding stays the same so the icon
   never moves. The sidebar width shrinks around the icon and the label
   fades + clips. Active pill is trimmed so it doesn't bleed past the rail. */
.shell.sidebar-collapsed .sidebar { padding: 22px 12px 22px; }

/* Red sidebar: Neo Pearl marks, icons and labels; Dark Fuchsia brandmark. */
.sidebar .brand-wordmark { fill: #F8F5EE; }
.sidebar .brand-brandmark { fill: #933994; }
/* The collapse icon draws its door on the left of its box, so nudge it right
   to optically centre with the other icons. */
.sidebar-toggle-icon { transform: translateX(2.5px); }
/* Second shape group in the mark takes Neo Pearl (CSS beats the inline attr). */
.sidebar .brand-brandmark path:nth-of-type(2) { fill: #F8F5EE; }
.sidebar .nav-item,
.sidebar .btn-ghost,
.sidebar .nav-icon,
.sidebar #theme-toggle {
  color: #F8F5EE;
}
.sidebar .nav-item svg,
.sidebar .btn-ghost svg { color: #F8F5EE; }
.sidebar .nav-item:hover,
.sidebar .btn-ghost:hover {
  background: rgba(248, 245, 238, 0.16);
  color: #F8F5EE;
}
.sidebar .nav-item.is-active {
  background: transparent;
  color: #F8F5EE;
  font-weight: 600;
}
.sidebar .btn-ghost.is-active {
  background: transparent;
  color: #F8F5EE;
  font-weight: 600;
}
/* Active nav swaps its outline icon for a solid one. Cut-out details
   (the plus, the magnifier, the site graphic) are painted in the sidebar
   colour so they read as knocked out of the solid shape. */
.sidebar { --nav-knockout: #EF4244; }
.nav-icon-solid { display: none; }
.nav-item.is-active .nav-icon-outline,
.sidebar .btn-ghost.is-active .nav-icon-outline { display: none; }
.nav-item.is-active .nav-icon-solid,
.sidebar .btn-ghost.is-active .nav-icon-solid { display: inline-flex; }
.nav-icon-solid .st1 { fill: var(--nav-knockout); }
/* Outline icons carry a 1.5 stroke that sits half outside the path, so the
   solid bodies get the same stroke to keep both states the same size. */
.nav-icon-solid [fill="currentColor"] {
  stroke: currentColor; stroke-width: 1.5;
  stroke-linecap: round; stroke-linejoin: round;
}
.sidebar .nav-item.is-active .nav-icon,
.sidebar .btn-ghost.is-active .nav-icon { color: #F8F5EE; }
.sidebar .btn-ghost.is-active .nav-icon,
.sidebar .btn-ghost.is-active svg { color: #F8F5EE; }
.shell.sidebar-collapsed .nav-item,
.shell.sidebar-collapsed .btn-ghost {
  width: 40px;
}
/* Brand padding stays identical in collapsed state so the F doesn't shift. */
.shell.sidebar-collapsed .brand-name-full { display: none; }
.shell.sidebar-collapsed .brand-name-mini { display: block; }
.shell.sidebar-collapsed .brand-sub { display: none; }
.shell.sidebar-collapsed .nav-label,
.shell.sidebar-collapsed .btn-ghost .nav-label,
.shell.sidebar-collapsed #theme-toggle .nav-label {
  opacity: 0;
  pointer-events: none;
  /* keep flex/width untouched so the icon's left position is stable */
}

.btn-ghost {
  background: transparent; border: 0;
  text-align: left;
  padding: 6px 12px;
  border-radius: var(--radius-md);
  color: var(--ink-mute);
  font-size: var(--text-xs);
  letter-spacing: 0.02em;
  display: flex; align-items: center; gap: 10px;
  height: 28px;
  box-sizing: border-box;
  width: 100%;
  white-space: nowrap;
  overflow: hidden;
}
.btn-ghost > .nav-icon,
.btn-ghost > .theme-icon {
  flex: 0 0 16px;
  width: 16px; height: 16px;
}

.btn-ghost:hover { color: var(--ink); background: var(--surface-2); }
.btn-ghost.is-active { color: var(--accent); background: var(--accent-soft); }

.theme-icon {
  font-size: 16px;
  width: 16px; height: 16px;
  display: inline-flex; align-items: center; justify-content: center;
  flex-shrink: 0;
  line-height: 1;
}
/* Theme toggle: show light icon in light mode, dark icon in dark mode.
   Uses !important to survive the mobile `.nav-icon { display: inline-flex }`
   override at ~line 5865 which would otherwise force both icons visible. */
.theme-icon-dark { display: none !important; }
:root[data-theme="dark"] .theme-icon-light { display: none !important; }
:root[data-theme="dark"] .theme-icon-dark { display: inline-flex !important; }
:root:not([data-theme="dark"]) .theme-icon-light { display: inline-flex !important; }
.pending-pill {
  font-size: var(--text-xs);
  padding: 6px 10px;
  background: var(--accent-soft);
  color: var(--accent);
  border-radius: 999px;
  text-align: center;
  font-weight: 500;
}

/* ----- Main ----- */
.main {
  min-width: 0;
  display: flex; flex-direction: column;
  padding-top: 76px; /* clearance for fixed auth bar */
}


/* Kicker still used inside section heads */
.kicker {
  font-size: var(--text-xs);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-mute);
}

/* Inline search pill — used in Artworks + Studio editor headers (v42) */
.search-pill {
  display: inline-flex; align-items: center; gap: var(--space-2);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 8px 14px;
  color: var(--ink-mute);
  min-width: 240px;
}
.search-pill svg { flex-shrink: 0; }
.search-pill input {
  border: 0;
  background: transparent;
  outline: none;
  color: var(--ink);
  font-size: var(--text-sm);
  width: 100%;
  padding: 0;
}
.search-pill input::placeholder { color: var(--ink-mute); }

.section-head-actions {
  display: flex; align-items: center; gap: var(--space-3); flex-wrap: wrap;
}
/* ----- Views ----- */
.view {
  padding: var(--space-4) var(--space-6) var(--space-6);
  max-width: 1320px;
  width: 100%;
  margin-inline: auto;
}

/* Library header inside Studio editor (kicker + search pill, v44) */
.library-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--space-3); flex-wrap: wrap;
  margin-bottom: var(--space-3);
}

/* ----- Common: section header ----- */
.section-head { margin-bottom: var(--space-4); }
.section-head-row { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; flex-wrap: wrap; }
.section-head-row > a.btn { flex-shrink: 0; align-self: flex-start; margin-top: 4px; }
.section-kicker {
  font-size: var(--text-xs);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-mute);
}
.section-title {
  font-family: var(--font-display);
  font-size: 36px;
  font-weight: 600;
  color: var(--ink);
  margin: 4px 0 0 0;
  line-height: 1.08;
  letter-spacing: -0.01em;
}
.section-sub {
  color: var(--ink-soft);
  margin-top: 6px;
  max-width: 60ch;
}

/* ----- Cards / panels ----- */
.panel {
  background: var(--surface);
  border: 1px solid var(--border-soft);
  border-radius: var(--radius-lg);
  padding: var(--space-5);
}
.panel-elev {
  background: var(--surface-elev);
  border: 1px solid var(--border-soft);
  border-radius: var(--radius-lg);
  padding: var(--space-5);
  box-shadow: var(--shadow-sm);
}

/* ----- KPIs ----- */
.kpi-row {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--space-4);
  margin-bottom: var(--space-6);
}
@media (max-width: 980px) {
  .kpi-row { grid-template-columns: repeat(2, 1fr); }
}
.kpi {
  background: var(--surface);
  border: 1px solid var(--border-soft);
  border-radius: var(--radius-md);
  padding: var(--space-4) var(--space-5);
  display: flex; flex-direction: column; gap: 6px;
}
.kpi-label {
  font-size: var(--text-xs);
  color: var(--ink-mute);
  letter-spacing: 0.04em;
}
.kpi-value {
  font-family: var(--font-ui);
  font-size: 34px;
  font-weight: 600;
  color: var(--ink);
  line-height: 1;
  letter-spacing: -0.01em;
}
.kpi-foot {
  font-size: var(--text-xs);
  color: var(--ink-mute);
}

/* ----- Buttons ----- */
.btn {
  display: inline-flex; align-items: center; justify-content: center;
  gap: 6px;
  padding: 10px 16px;
  border-radius: 999px;
  font-size: var(--text-sm);
  font-weight: 500;
  border: 1px solid transparent;
  background: var(--surface-2);
  color: var(--ink);
  /* App-wide button motion: radius snaps instantly to 0, scale + colors ease. */
  transition:
    transform 0.3s ease,
    background 0.3s ease,
    color 0.3s ease,
    border-color 0.3s ease;
  will-change: transform;
  cursor: pointer;
}
.btn:hover:not(:disabled) {
  border-radius: 0;
  transform: scale(1.06);
  background: transparent;
  color: var(--ink);
  border-color: var(--ink);
}
.btn-primary {
  background: var(--accent);
  color: var(--accent-ink);
  border-color: var(--accent);
}
.btn-primary:hover:not(:disabled) {
  background: transparent;
  color: var(--accent);
  border-color: var(--accent);
}

/* ----- Save Work — inherits app-wide hover; adds Saved success state ----- */
.btn-save-work { position: relative; }

/* Cancel button inside the crop modal sits on a permanently dark background.
   Force white hover treatment so border/text stay visible against the dark
   overlay regardless of the app's theme. The modal Save button uses
   .btn-save-work and inherits the app-wide Save Work treatment 1:1. */
.fc-overlay .btn-outline:hover:not(:disabled) {
  background: transparent;
  color: #fcfaf7;
  border-color: #fcfaf7;
}
/* Saved state — holds the hovered square + scale, swaps to black/white.
   box-sizing locked + flex centering guarantees zero geometry shift when
   the inner text swaps from "Save Work"/"Save Settings" to "Saved".
   Applied to any button using showSaveSuccess() — Save Work, Save Settings,
   and the Adjust Image modal's Save button (which also carries
   .btn-save-work for identical motion). */
/* One rule for every save button in the app, whatever else it's classed as —
   Save Work, Save Settings, the Adjust Image modal, the Alternative Text
   dialog. !important so a .btn-primary/.btn variant can never leave the pill
   green. */
.btn.is-saved,
.btn-save-work.is-saved,
.btn-save-settings.is-saved {
  /* Not !important: showSaveSuccess() sets an inline pill radius for a single
     frame as the starting point of the round-to-square ease in dialogs. */
  border-radius: 0;
  padding-left: 16px !important;
  padding-right: 16px !important;
  transform: scale(1.06);
  background: #000000 !important;
  border-color: #000000 !important;
  color: #fcfaf7 !important;
  opacity: 1 !important;
  cursor: default;
  box-sizing: border-box;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
}
/* The Adjust Image modal's footer is itself near-black, so give the pill a thin
   light edge there to keep it readable. */
.fc-overlay .btn.is-saved,
.fc-overlay .btn-save-work.is-saved {
  border-color: rgba(255, 255, 255, 0.35) !important;
}
/* Dialog-only: fade the "Saved" label in, matching the animated width. */
.modal-overlay .btn.is-saved .save-label,
.fc-overlay .btn.is-saved .save-label {
  animation: saveLabelIn 260ms cubic-bezier(0.22, 0.75, 0.16, 1) both;
}
@keyframes saveLabelIn {
  from { opacity: 0; transform: translateY(3px); }
  to   { opacity: 1; transform: none; }
}
.btn.is-saved .save-cloud,
.btn-save-work.is-saved .save-cloud,
.btn-save-settings.is-saved .save-cloud {
  animation: saveCheckDraw 0.45s ease-out 0.08s both;
  /* Explicit dimensions + flex-shrink: 0 prevents the SVG from collapsing to
     zero width inside a flex container (a known quirk in some browsers). */
  width: 18px;
  height: 18px;
  flex-shrink: 0;
  color: #fcfaf7;
  stroke: currentColor;
}
@keyframes saveCheckDraw {
  0%   { opacity: 0; transform: scale(0.55); }
  60%  { opacity: 1; transform: scale(1.15); }
  100% { opacity: 1; transform: scale(1); }
}
@media (prefers-reduced-motion: reduce) {
  .btn.is-saved .save-label,
  .btn-save-work,
  .btn.is-saved,
  .btn.is-saved .save-cloud,
  .btn-save-work.is-saved,
  .btn-save-work.is-saved .save-cloud,
  .btn-save-settings.is-saved,
  .btn-save-settings.is-saved .save-cloud { animation: none; transition: none; }
}
.btn-outline {
  background: transparent;
  border-color: var(--border);
  color: var(--ink);
}
.btn-outline:hover:not(:disabled) {
  background: transparent;
  border-color: var(--ink);
  color: var(--ink);
}
.btn-danger {
  background: var(--rose);
  border-color: var(--rose);
  color: var(--surface);
}
.btn-danger:hover:not(:disabled) {
  background: transparent;
  border-color: var(--rose);
  color: var(--rose);
}
.btn-sm { padding: 6px 12px; font-size: var(--text-xs); }

/* ----- Working concept hero (Dashboard) ----- */
.concept-grid {
  display: grid;
  grid-template-columns: 1.1fr 1fr;
  gap: var(--space-4);
  margin-bottom: var(--space-6);
}
@media (max-width: 980px) {
  .concept-grid { grid-template-columns: 1fr; }
}
.concept-card {
  background: var(--surface);
  border: 1px solid var(--border-soft);
  border-radius: var(--radius-lg);
  padding: var(--space-6);
  display: flex; flex-direction: column; gap: var(--space-4);
}
.concept-h {
  font-family: var(--font-display);
  font-size: 56px;
  font-weight: 600;
  line-height: 1.02;
  color: var(--ink);
  margin: 8px 0 0;
  letter-spacing: -0.015em;
}
@media (max-width: 980px) {
  .concept-h { font-size: 42px; }
}
.concept-sub {
  color: var(--ink-soft);
  font-size: 16px;
}
.concept-actions { display: flex; gap: var(--space-3); flex-wrap: wrap; margin-top: var(--space-2); }

.concept-right {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  align-self: start;
  min-width: 0;
}
.concept-stats {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--space-4);
  align-content: start;
}
.concept-stat {
  background: var(--surface);
  border: 1px solid var(--border-soft);
  border-radius: var(--radius-md);
  padding: var(--space-4) var(--space-5);
  display: flex; flex-direction: column; gap: 6px;
}
.concept-stat .kpi-value { font-size: 34px; }

/* ----- Charts (Works by gallery) ----- */
.bar-row {
  display: grid;
  grid-template-columns: 130px 1fr 40px;
  align-items: center;
  gap: var(--space-3);
  padding: 6px 0;
  font-size: var(--text-sm);
}
.bar-label { color: var(--ink-soft); }
.bar-track {
  height: 10px;
  background: var(--surface-3);
  border-radius: 999px;
  overflow: hidden;
}
.bar-fill {
  height: 100%;
  background: linear-gradient(90deg, var(--accent), color-mix(in oklab, var(--accent) 65%, var(--accent-soft)));
  border-radius: 999px;
}
.bar-value { text-align: right; color: var(--ink); font-variant-numeric: tabular-nums; }

/* ----- Activity feed ----- */
.activity-item {
  display: flex; justify-content: space-between; align-items: center;
  background: var(--surface);
  border: 1px solid var(--border-soft);
  border-radius: var(--radius-md);
  padding: var(--space-3) var(--space-4);
  font-size: var(--text-sm);
  margin-bottom: var(--space-2);
}
.activity-item:last-child { margin-bottom: 0; }
.activity-meta { color: var(--ink-mute); font-size: var(--text-xs); }

.two-col {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-4);
}
@media (max-width: 980px) { .two-col { grid-template-columns: 1fr; } }

/* ----- Filters (Artworks) ----- */
.filter-bar {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--space-3);
  margin-bottom: var(--space-5);
}
@media (max-width: 980px) { .filter-bar { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 560px) { .filter-bar { grid-template-columns: 1fr; } }

.field {
  display: flex; flex-direction: column; gap: 4px;
}
.field label {
  font-size: var(--text-xs);
  color: var(--ink-mute);
  letter-spacing: 0.04em;
}
.input, .select, .textarea {
  background: var(--field-bg);
  border: 1px solid transparent;
  border-radius: var(--radius-md);
  padding: 9px 12px;
  color: var(--ink);
  font-size: var(--text-sm);
  outline: 0;
  transition: border-color var(--transition), box-shadow var(--transition);
}

/* Custom chevron for selects (replaces native arrow that crowds right edge) */
.select {
  -webkit-appearance: none;
  -moz-appearance: none;
  appearance: none;
  padding-right: 32px;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%23556' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'><polyline points='6 9 12 15 18 9'/></svg>");
  background-repeat: no-repeat;
  background-position: right 12px center;
  background-size: 12px 12px;
}
[data-theme="dark"] .select {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%23F8F5EE' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'><polyline points='6 9 12 15 18 9'/></svg>");
}

/* Cap filter-bar select widths so they don't stretch the full column */
.filter-bar .select { max-width: 220px; width: 100%; }
.input:focus, .select:focus, .textarea:focus {
  border-color: transparent;
  box-shadow: 0 0 0 3px color-mix(in oklab, var(--accent) 22%, transparent);
}
[data-theme="dark"] .input::placeholder,
[data-theme="dark"] .textarea::placeholder { color: #8d918b; }
.textarea { resize: vertical; min-height: 96px; line-height: 1.5; }

/* Input prefix (e.g. $) — matches select option text rendering ($1.50) */
.input-prefix { position: relative; display: block; }
.input-prefix .input-prefix-symbol {
  position: absolute;
  left: 12px;
  top: 50%;
  transform: translateY(-50%);
  color: var(--ink);
  font-size: var(--text-sm);
  line-height: 1;
  pointer-events: none;
  font-variant-numeric: tabular-nums;
}
.input-prefix .input.has-prefix {
  /* 12px base padding + ~8px for the $ glyph, no extra gap */
  padding-left: 20px;
  width: 100%;
}

/* Counts/sort row */
.list-meta {
  display: flex; justify-content: space-between; align-items: center;
  margin-bottom: 40px;
  color: var(--ink-soft);
  font-size: var(--text-sm);
}
.list-meta .right { display: flex; gap: var(--space-3); align-items: center; }

/* ----- View toggle ----- */
.view-toggle {
  display: inline-flex !important;
  background: transparent;
  border: 0;
  border-radius: 6px;
  padding: 0;
  gap: 2px;
  align-items: center;
}
.vt-btn {
  display: inline-flex !important;
  align-items: center; gap: 6px;
  padding: 5px 10px;
  min-height: 28px;
  border: 0; background: transparent;
  font: inherit; font-size: 13px; font-weight: 500; color: #6b6557;
  border-radius: 6px;
  cursor: pointer;
  transition: background 140ms, color 140ms;
}
.vt-btn .vt-icon { flex: none; color: #8a8472; transition: color 140ms; }
.vt-btn:hover { background: rgba(0,0,0,0.04); color: #1f1d18; }
.vt-btn:hover .vt-icon { color: #4a4537; }
.vt-btn.is-active {
  background: transparent;
  color: #1f1d18;
  font-weight: 600;
}
.vt-btn.is-active .vt-icon { color: #1f6feb; }

[data-theme="dark"] .view-toggle { background: transparent; border: 0; }
[data-theme="dark"] .vt-btn { color: #a8a397; }
[data-theme="dark"] .vt-btn .vt-icon { color: #8a8472; }
[data-theme="dark"] .vt-btn:hover { background: rgba(255,255,255,0.05); color: #e8e4d6; }
[data-theme="dark"] .vt-btn:hover .vt-icon { color: #cfc9b8; }
[data-theme="dark"] .vt-btn.is-active { background: transparent; color: #f4f0e2; }
[data-theme="dark"] .vt-btn.is-active .vt-icon { color: #4a90ff; }

/* ----- Artwork list view ----- */
.art-list {
  display: flex; flex-direction: column;
  border: 1px solid var(--border-soft);
  border-radius: var(--radius-md);
  background: var(--bg);
}
.art-list-head, .art-row {
  display: grid;
  /* thumb | Title (capped so slack flows to Created/Gallery) | Created | Gallery | Medium | Dimensions | Visibility | Status | Price */
  grid-template-columns: 64px minmax(240px, 3fr) 80px 160px 170px 100px 76px 56px 76px;
  gap: var(--space-3);
  align-items: center;
  padding: 10px var(--space-4);
}
/* Push Visibility chip and Status dot to right side of their cells so they sit close to Price */
.art-list-head > div:nth-child(7),
.art-row > div:nth-child(7) { text-align: right; }
.art-row > div:nth-child(7) { display: flex; justify-content: flex-end; }
.al-status-col { text-align: right; }
.art-row > div.al-status-col { display: flex; justify-content: flex-end; }
/* STATUS header: center the text horizontally over the right-aligned status dot.
   Dot is right-aligned in a 60px column, so its center sits ~5px from the column's right edge.
   We center the header text and translate it right so its center matches the dot's center. */
.art-list-head > div.al-status-col {
  text-align: center;
  overflow: visible;
  /* (60px col / 2) - 5px (dot radius) = 25px shift right from column center to dot center */
  transform: translateX(25px);
}
.art-list-head {
  background: var(--surface-2);
  border-bottom: 1px solid var(--border-soft);
  font-size: var(--text-xs, 12px);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--ink-soft);
  padding-top: 12px; padding-bottom: 12px;
  /* Stick to top of viewport while scrolling so column titles stay visible */
  position: sticky;
  top: 0;
  z-index: 5;
  border-top-left-radius: var(--radius-md);
  border-top-right-radius: var(--radius-md);
}
.art-row:last-child {
  border-bottom-left-radius: var(--radius-md);
  border-bottom-right-radius: var(--radius-md);
  overflow: hidden;
}
.art-list-head .right { text-align: right; }
.art-row {
  border: 0; background: transparent;
  text-align: left; font: inherit; color: var(--ink);
  border-bottom: 1px solid var(--border-soft);
  cursor: pointer;
  transition: background var(--transition);
}
.art-row:last-child { border-bottom: 0; }
.art-row:hover { background: var(--surface); }
.art-row > div { font-size: var(--text-sm); color: var(--ink); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.art-row-thumb {
  width: 56px; height: 56px;
  flex: none;
}
.al-thumb {
  width: 56px; height: 56px;
  border-radius: var(--radius-sm, 6px);
  background: transparent;
  position: relative; overflow: hidden;
  display: flex; align-items: center; justify-content: center;
}
.al-thumb img { width: 100% !important; height: 100% !important; object-fit: cover !important; }
.al-thumb.placeholder { background: linear-gradient(160deg, var(--surface-2), var(--surface-3)); }
.al-thumb.placeholder::before {
  content: ""; position: absolute; inset: 5px;
  border: 1px solid var(--border); border-radius: 3px;
}
.al-ph-title {
  font-family: var(--font-display); font-style: italic;
  font-size: 9px; line-height: 1.1;
  color: var(--ink-soft);
  text-align: center; padding: 4px;
  position: relative;
  display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical;
  overflow: hidden;
}
.al-title {
  font-family: var(--font-display);
  font-size: var(--text-md, 15px); font-weight: 600;
  color: var(--ink); line-height: 1.2;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.al-sub { font-size: var(--text-xs, 12px); color: var(--ink-soft); margin-top: 2px; }
.art-row-price { text-align: right; font-weight: 600; }
.chip-inline {
  display: inline-block;
  font-size: 11px;
  padding: 2px 8px;
  border-radius: 999px;
  font-weight: 500;
  letter-spacing: 0.02em;
}

/* Mobile list card layout matching the reference mockup.

   Grid — 4 rows, 2 cols:
     Row 1: thumb | title            | price
     Row 2: thumb | gallery          | Public pill
     Row 3: thumb | dimensions       | status dot
     Row 4: thumb | medium           | .

   Actual grid: thumb spans all rows on the left, middle 1fr grows,
   right auto shrinks. */
@media (max-width: 720px) {
  .art-list-head { display: none !important; }

  .art-row {
    display: grid !important;
    grid-template-columns: 84px 1fr auto !important;
    /* Fixed heights for consistent line rhythm on both columns */
    /* Total = 25 + 20 + 20 + 20 = 85px content, plus 12px+12px padding
       = 109px card height. Thumb (84px) fits, meta lines sit tight under
       title and Medium row bottom aligns with thumb bottom. */
    grid-template-rows: 25px 20px 20px 20px !important;
    grid-template-areas:
      "thumb title right"
      "thumb gal   right"
      "thumb dim   right"
      "thumb med   right" !important;
    row-gap: 0 !important;
    column-gap: 12px !important;
    padding: 12px !important;
    align-items: center !important;
  }

  /* Reset base child rule that clipped everything */
  .art-row > div {
    white-space: normal !important;
    overflow: visible !important;
    text-overflow: clip !important;
    min-width: 0 !important;
  }

  .art-row-thumb {
    grid-area: thumb !important;
    width: 84px !important;
    height: 84px !important;
    align-self: start !important;
  }
  .art-row-thumb .al-thumb,
  .art-row-thumb .al-thumb img {
    width: 84px !important;
    height: 84px !important;
    border-radius: 6px !important;
  }

  /* Title — row 1 left. Allow the display serif to overflow the 17px row
     visually without stretching the meta rhythm. */
  .art-row-title {
    grid-area: title !important;
    align-self: center !important;
    overflow: visible !important;
  }
  .art-row-title .al-title {
    font-family: var(--font-display) !important;
    font-size: 17px !important;
    font-weight: 700 !important;
    line-height: 1.2 !important;
    color: var(--ink) !important;
    white-space: nowrap !important;
    overflow: hidden !important;
    text-overflow: ellipsis !important;
  }

  /* Show the stacked meta cells, one per line, in this order:
     child 4 = gallery  → gal
     child 6 = dimensions → dim
     child 5 = medium   → med
     child 3 = date/created → hidden */
  .art-row > div:nth-child(3) { display: none !important; }
  .art-row > div:nth-child(4),
  .art-row > div:nth-child(5),
  .art-row > div:nth-child(6) {
    display: block !important;
    font-size: 13px !important;
    color: var(--ink-soft) !important;
    line-height: 20px !important;
    height: 20px !important;
    text-align: left !important;
    font-weight: 400 !important;
    align-self: center !important;
    overflow: hidden !important;
    white-space: nowrap !important;
    text-overflow: ellipsis !important;
  }
  .art-row > div:nth-child(4) { grid-area: gal !important; }
  .art-row > div:nth-child(5) { grid-area: med !important; }
  .art-row > div:nth-child(6) { grid-area: dim !important; }

  /* No ::after meta line — we're using real cells now */
  .art-row::after { display: none !important; content: none !important; }

  /* Right column — all three items (price, status dot, chip) share the
     single "right" grid area which spans all 4 rows. We flip that area
     into a flex column with space-between so Price, Status, Public are
     evenly distributed vertically regardless of left-column meta height. */
  .art-row > div:nth-child(7),
  .art-row > div:nth-child(8),
  .art-row > div.al-status-col,
  .art-row-price {
    grid-area: right !important;
    justify-self: end !important;
  }

  /* Manually offset each item so they land at top / middle / bottom of the
     shared 4-row span (~68px tall). Grid ignores align-self between siblings
     in the same area, so we use transform/position to fake even spacing. */
  .art-row {
    position: relative;
  }
  .art-row .art-row-price {
    align-self: start !important;
    text-align: right !important;
    font-weight: 700 !important;
    font-size: 16px !important;
    white-space: nowrap !important;
  }
  .art-row > div.al-status-col,
  .art-row > div:nth-child(8) {
    align-self: center !important;
    display: inline-flex !important;
    align-items: center !important;
    justify-content: flex-end !important;
  }
  .art-row > div:nth-child(7) {
    align-self: end !important;
    display: inline-flex !important;
    align-items: center !important;
    overflow: visible !important;
  }
  .art-row > div:nth-child(7) .chip {
    display: inline-block !important;
    font-size: 10px !important;
    padding: 3px 10px !important;
    letter-spacing: 0.06em !important;
    text-transform: uppercase !important;
    border-radius: 999px !important;
    line-height: 1.4 !important;
  }
  .art-row .status-dot {
    width: 10px !important;
    height: 10px !important;
    border-radius: 999px !important;
    display: inline-block !important;
  }
}

/* ----- Artwork grid ----- */
.grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  grid-row-gap: 100px;
  grid-column-gap: 40px;
}

/* ----- Grid card (v94 redesign) ----- */
.grid-card {
  display: flex;
  flex-direction: column;
  gap: 12px;
  background: transparent;
  border: 0;
  padding: 0;
  cursor: pointer;
}
.grid-card-thumb {
  position: relative;
  overflow: hidden;
  border-radius: 0;
}
/* Disable card lift + thumb transform on grid cards only (must beat .card:hover) */
.card.grid-card { transition: none; }
.card.grid-card:hover,
.card.grid-card:focus,
.card.grid-card:focus-visible { transform: none !important; }
.card.grid-card .thumb { transition: none; }
.card.grid-card:hover .thumb { transform: none !important; }
.grid-card-thumb {
  width: 100%;
  aspect-ratio: 4/5;
}
.grid-card-thumb .thumb,
.grid-card-thumb img {
  width: 100%;
  height: 100%;
}
.grid-card-overlay {
  position: absolute;
  inset: 0;
  background: #000;
  color: #fcfaf7;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 10px;
  padding: 18px 20px;
  opacity: 0;
  pointer-events: none;
  transition: opacity 180ms ease;
}
.grid-card:hover .grid-card-overlay,
.grid-card:focus-visible .grid-card-overlay {
  opacity: 1;
}
.gco-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
  font-size: 13px;
  line-height: 1.3;
}
.gco-k {
  text-transform: uppercase;
  letter-spacing: 0.06em;
  font-size: 10px;
  color: rgba(255, 255, 255, 0.65);
  font-weight: 500;
}
.gco-v {
  color: #fcfaf7;
  font-weight: 500;
  text-align: right;
}
.gco-price { font-weight: 600; }
.gco-pill {
  display: inline-flex; align-items: center;
  padding: 4px 9px;
  border-radius: 999px;
  font-size: 9px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  font-weight: 600;
  white-space: nowrap;
  border: 1px solid rgba(248, 245, 238, 0.35);
}
/* Solid Light Black would vanish on the overlay, so Public reverses out. */
.gco-pill.is-public { background: #F8F5EE; border-color: #F8F5EE; color: #2B2F2D; }
.gco-pill.is-private { background: rgba(248, 245, 238, 0.08); }
.gco-status {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-weight: 500;
}
.gco-dot {
  width: 8px; height: 8px;
  border-radius: 50%;
  display: inline-block;
}
.gco-status.is-sold .gco-dot,
.gco-status.is-sold-paid .gco-dot { background: #EF4244; }
.gco-status.is-sold-unpaid .gco-dot { background: #FFD700; }
.gco-status.is-available .gco-dot { background: #0BDA51; }
.gco-status.is-private-collection .gco-dot { background: #933994; }
.gco-status.is-work-in-progress .gco-dot { background: #2F00FF; }

.grid-card-info {
  text-align: center;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.gci-title {
  font-weight: 600;
  font-size: 15px;
  color: var(--ink);
  line-height: 1.3;
}
.gci-meta {
  font-size: 13px;
  color: var(--ink-soft);
  line-height: 1.4;
}
.card {
  background: transparent;
  border: 0;
  text-align: left;
  padding: 0;
  cursor: pointer;
  display: flex; flex-direction: column;
  transition: transform var(--transition);
}
.card:hover { transform: translateY(-2px); }
.thumb {
  width: 100%; aspect-ratio: 4/5;
  position: relative; overflow: hidden;
  background: transparent;
  border: 0;
  border-radius: 0;
  display: flex; align-items: flex-end; justify-content: center;
  margin-bottom: var(--space-4);
  transition: transform var(--transition);
}
.card:hover .thumb { transform: none; }
.thumb img { width: 100% !important; height: 100% !important; object-fit: contain !important; object-position: center bottom !important; padding: 0; background: transparent; }

/* Light gallery-style placeholder (matches prototype) */
.thumb.placeholder {
  background: linear-gradient(160deg, var(--surface-2), var(--surface-3));
  padding: var(--space-4);
  text-align: center;
}
.thumb.placeholder::before {
  content: "";
  position: absolute; inset: 14px;
  border: 1px solid var(--border);
  border-radius: 4px;
  pointer-events: none;
}
.thumb.placeholder .placeholder-title {
  font-family: var(--font-display);
  font-style: italic;
  font-size: 17px;
  line-height: 1.25;
  color: var(--ink-soft);
  max-width: 78%;
  position: relative;
}

/* Card meta — centered, with consistent 12px detail size */
.card-head {
  display: flex; justify-content: center; align-items: flex-start; gap: var(--space-2);
  margin-bottom: 4px;
  text-align: center;
}
.card-title {
  font-family: var(--font-display);
  font-size: 15px;
  font-weight: 600;
  color: var(--ink);
  line-height: 1.25;
  letter-spacing: -0.005em;
  flex: 1;
  text-align: center;
}
.card-meta {
  font-size: 12px;
  color: var(--ink-mute);
  margin-top: 2px;
  display: flex; flex-direction: column; gap: 2px;
  text-align: center;
  align-items: center;
}
.card-foot {
  display: flex; justify-content: center; align-items: center; gap: 12px;
  margin-top: 8px;
  font-size: 12px;
  color: var(--ink);
  text-align: center;
}
.card-price { font-weight: 600; font-size: 12px; }

/* Status / visibility chips */
.chip {
  display: inline-flex; align-items: center; gap: 4px;
  font-size: 10.5px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding: 3px 8px;
  border-radius: 999px;
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--ink-soft);
  font-weight: 600;
  white-space: nowrap;
}
.chip.sold { background: var(--ink); color: var(--ink-inverse); border-color: var(--ink); }
.chip.available { background: var(--accent-soft); color: var(--accent); border-color: transparent; }
.chip.private {
  background: transparent;
  border-color: #2B2F2D;
  color: #2B2F2D;
}
.chip.public { background: #2B2F2D; border-color: #2B2F2D; color: #fcfaf7; }
/* Public / Private pills run tighter and smaller than the other chips. */
.chip.public, .chip.private { padding: 4px 9px; font-size: 9px; }
/* On the dark theme those two would sink into the page, so they flip to Neo Pearl. */
[data-theme="dark"] .chip.private { border-color: #F8F5EE; color: #F8F5EE; }
[data-theme="dark"] .chip.public { background: #F8F5EE; border-color: #F8F5EE; color: #2B2F2D; }

.thumb .chip-overlay {
  position: absolute; top: 10px; left: 10px;
  display: flex; gap: 6px;
}
.thumb .chip-overlay .chip {
  backdrop-filter: blur(6px);
  background: color-mix(in oklab, var(--surface) 90%, transparent);
}
.thumb .chip-overlay .chip.sold {
  background: color-mix(in oklab, var(--ink) 90%, transparent);
  color: var(--ink-inverse);
}

.thumb .private-flag {
  position: absolute; top: 10px; right: 10px;
  background: color-mix(in oklab, var(--amber) 92%, white);
  color: white;
  font-size: 10px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding: 3px 8px;
  border-radius: 999px;
  font-weight: 600;
}

/* ----- Studio editor (split view) ----- */
.editor-grid {
  display: grid;
  grid-template-columns: 1fr 1.05fr;
  gap: var(--space-5);
}
@media (max-width: 1100px) { .editor-grid { grid-template-columns: 1fr; } }

[data-theme="dark"] .editor-preview { background: transparent; }
.editor-preview {
  background: var(--surface-elev);
  border: 0;
  border-radius: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  min-height: 100%;
}
/* When an artwork is selected: the image slot grows, pushing title/meta to bottom */
.editor-preview > .editor-preview-slot {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
}
[data-theme="dark"] .editor-form,
[data-theme="dark"] .modal-card,
[data-theme="dark"] .share-modal,
[data-theme="dark"] .folio-import-modal .fi-card { background: #2B2F2D; }
.editor-form {
  background: var(--surface-elev);
  border: 1px solid var(--border-soft);
  border-radius: var(--radius-lg);
  padding: var(--space-5);
}
.editor-form-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--space-3);
  margin-bottom: var(--space-4);
  flex-wrap: wrap;
}
.editor-form-head .actions { display: flex; gap: 8px; flex-wrap: wrap; }

.preview-thumb {
  flex: 1 1 auto;
  min-height: 0;
  max-height: 650px;
  border-radius: 0;
  border: 0;
  background: transparent;
  display: flex; align-items: flex-end; justify-content: center;
  position: relative;
  margin-bottom: var(--space-4);
}
/* Fallback for the upload zone (no artwork selected) — keep aspect ratio there */
.editor-preview > .editor-preview-slot:has(.upload-zone) {
  flex: 0 0 auto;
  justify-content: flex-start;
}
.preview-thumb:not(:has(img))::before {
  content: ""; position: absolute; inset: 18px;
  border: 1px solid var(--border); border-radius: 4px;
}
.preview-thumb img { width: 100% !important; height: 100% !important; max-height: 650px; object-fit: contain !important; object-position: center bottom !important; padding: 0; background: transparent; border-radius: 0; }
.preview-thumb .placeholder-title {
  font-family: var(--font-display); font-style: italic;
  font-size: 22px; color: var(--ink-soft);
  text-align: center; max-width: 80%; position: relative;
}

.preview-title {
  font-family: var(--font-display);
  font-size: 30px; line-height: 1.15;
  font-weight: 600;
  margin: 4px 0 8px;
}
.preview-chips { display: flex; gap: 6px; flex-wrap: wrap; margin-bottom: var(--space-3); }
.preview-chips-spread { justify-content: space-between; align-items: center; gap: var(--space-2); }
.preview-chips-spread > * { flex: 0 0 auto; }
.preview-chips-spread > *:nth-child(2) { margin: 0 auto; }
.preview-meta {
  display: grid; grid-template-columns: 130px 1fr;
  row-gap: 6px; column-gap: 12px;
  font-size: var(--text-sm);
  margin-top: var(--space-3);
}
.preview-meta dt { color: var(--ink-mute); }
.preview-meta dd { margin: 0; color: var(--ink); }

/* Subtle hint text next to field labels */
.label-hint {
  color: var(--ink-mute);
  font-weight: 400;
  font-size: 0.85em;
  margin-left: 4px;
}

/* Private notes block in editor preview pane */
.preview-notes {
  background: var(--surface-2);
  border: 1px solid var(--border-soft);
  border-radius: 8px;
  padding: 10px 12px;
  margin-top: var(--space-2);
}
.preview-notes-label {
  font-size: var(--text-xs, 12px);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--ink-mute);
  margin-bottom: 4px;
}
.preview-notes p {
  margin: 0;
  font-size: var(--text-sm);
  color: var(--ink);
}

.form-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-3) var(--space-4);
}
.form-grid .full { grid-column: 1 / -1; }
@media (max-width: 600px) { .form-grid { grid-template-columns: 1fr; } }

.form-footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  margin-top: var(--space-6);
  padding-top: var(--space-4);
}
.form-footer .field-public-vis {
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.form-footer .field-public-vis > label:first-child {
  font-size: var(--text-xs);
  color: var(--muted);
  text-transform: none;
  letter-spacing: 0;
}
.form-footer-actions {
  display: flex;
  gap: var(--space-2);
  align-items: center;
}
@media (max-width: 600px) {
  .form-footer { flex-direction: column; align-items: stretch; }
  .form-footer-actions { justify-content: flex-end; }
}

.editor-empty {
  text-align: center;
  padding: var(--space-8) var(--space-5);
  color: var(--ink-mute);
}
.editor-empty .section-title { color: var(--ink-soft); }

/* Empty/index list inside editor */
.editor-list {
  max-height: 70vh; overflow-y: auto;
  padding-right: 4px;
}
.editor-list-item {
  display: grid; grid-template-columns: 60px 1fr auto;
  gap: var(--space-3); align-items: center;
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-md);
  cursor: pointer;
  border: 1px solid transparent;
}
.editor-list-item:hover { background: var(--surface-2); }
.editor-list-item.is-active { background: var(--accent-soft); border-color: transparent; }
.eli-status { display: inline-flex; align-items: center; gap: 8px; }
.editor-list-sentinel,
.editor-list-end {
  text-align: center;
  padding: var(--space-3) var(--space-2);
  font-size: 12px;
  letter-spacing: 0.02em;
}
.eli-thumb {
  width: 60px; height: 60px; border-radius: 0;
  background: transparent;
  border: 0;
  position: relative;
  overflow: hidden;
}
.eli-thumb img { width: 100% !important; height: 100% !important; object-fit: contain !important; object-position: center center !important; padding: 0; background: transparent; }
.eli-title {
  font-family: var(--font-display); font-size: 16px; font-weight: 600;
  color: var(--ink); line-height: 1.2;
}
.eli-sub { font-size: var(--text-xs); color: var(--ink-mute); margin-top: 2px; }

/* =====================================================================
   PUBLIC SITE — Aesthetic match for joannaaplin.com
   Self-contained; uses .public-frame as the scope so admin styling is
   never affected. All rules below are Public-Site only.
   ===================================================================== */

/* Shared Joanna font stack — used by all public-site UI and the public modal.
   Replace the Futura stack with `"Nexa"` once Jamie's Nexa woff2 files are
   wired up via @font-face. */
:root {
  --pub-nexa: "Nexa", sans-serif;
  --pub-garamond: "EB Garamond", Georgia, serif;
  --pub-red: #FF0000;
  --pub-rose: #cc3366;
  --pub-ink: #000000;
  --pub-ink-soft: #333333;
  --pub-bg: #fcfaf7;
}

.public-frame {
  background: var(--pub-bg);
  color: var(--pub-ink);
  border: 1px solid var(--border-soft);
  border-radius: var(--radius-xl);
  /* Allow position:sticky inside this frame to work. overflow:hidden
     ancestors prevent sticky positioning from pinning to viewport. */
  overflow: visible;
  box-shadow: var(--shadow-md);
  font-family: var(--pub-nexa);
}

/* ----- Header / nav (below hero on load, sticky once it hits the top) -----
   Joanna's pattern: the hero takes the full first viewport, then the header
   sits in document flow just below it. As you scroll, the header travels up
   with the page. When it reaches y=0 of the viewport, position:sticky pins
   it there for the remainder of the page. */
.public-nav {
  position: sticky;
  top: 0;
  z-index: 5;
  background: #fcfaf7;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 18px 48px; /* link itself adds 15px top/bottom, so total bar = ~66px */
  /* Shadow is only shown once the page has scrolled below the top, so the
     nav blends seamlessly into the page on initial load and only reveals
     itself as a sticky bar once it lifts off the page. */
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0);
  transition: box-shadow 0.25s ease;
}
.public-nav.is-stuck {
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.12);
}
/* In the admin Public Site preview tab, the fixed Folio auth bar (Sign out, etc.)
   covers the top ~44px of the viewport. Push the public sticky nav down so it
   pins below the auth bar instead of being hidden behind it. The standalone
   /public page (no auth bar) is unaffected. */
.public-frame--admin-preview .public-nav {
  top: 68px;
}
.public-nav .pn-brand {
  font-family: var(--pub-nexa);
  font-size: 16px;
  font-weight: 700;
  letter-spacing: 3px;
  word-spacing: 3px;
  text-transform: uppercase;
  color: #000;
  display: flex;
  align-items: center;
}
.public-nav nav {
  display: flex;
  gap: 24px; /* ~12px margin-inline on each side per Joanna's spec */
}
.public-nav nav a {
  position: relative;
  font-family: var(--pub-nexa);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 1.5px;
  text-transform: uppercase;
  color: #000;
  text-decoration: none;
  padding: 15px 0; /* Joanna: matches .elementor-item padding 15px 0 */
  transition: color 0.4s ease;
  cursor: pointer;
}
/* Subtle 1px underline. Matches joannaaplin.com's custom CSS exactly:
   transform-origin pinned to RIGHT, scaleX(0)↔scaleX(1), with a slow
   cubic-bezier(1, 0, 0, 1) easing over 0.7s. This curve sits idle at
   each end and races through the middle — a more elegant sweep than
   a plain ease. Hover-in grows from the right edge; hover-out
   collapses back toward the right edge (reads as left→right sweep-out). */
.public-nav nav a::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 4px;
  height: 1px;
  background: var(--pub-red);
  transform: scaleX(0);
  transform-origin: right center;
  transition: transform 0.7s cubic-bezier(1, 0, 0, 1);
}
.public-nav nav a:hover {
  color: var(--pub-red);
}
.public-nav nav a:hover::after {
  transform: scaleX(1);
}
.public-nav nav a.is-active {
  color: var(--pub-red);
}

/* ----- Hero (full-bleed image, title overlay in spaced caps) -----
   Sizes so hero + nav fill exactly one viewport on load. Nav total height
   = 18px container padding × 2 + 15px link padding × 2 + ~12px line-height
   ≈ 78px. Hero gets the remainder so the nav sits visible at the bottom
   of the fold on initial load. */
.public-hero {
  position: relative;
  min-height: calc(100vh - 78px);
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  background: #f5f5f5;
  overflow: hidden;
}
.public-hero .ph-image {
  position: absolute;
  inset: 0;
  background-size: 100%;       /* inline style overrides with zoom % */
  background-position: 50% 50%; /* inline style overrides */
  background-repeat: no-repeat;
  z-index: 0;
}
.public-hero .ph-overlay {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  /* background-color set inline based on overlay_color + intensity */
}
.public-hero .ph-inner {
  position: relative;
  z-index: 2;
  padding: 64px 24px;
  color: #000;
}
.public-hero .ph-kicker {
  display: none; /* Joanna's site has no kicker */
}
.public-hero h1 {
  /* Match joannaaplin.com exactly: Nexa Bold 70px, no CSS transform,
     no extra letter-spacing (literal spaces in markup), line-height 1. */
  font-family: var(--pub-nexa);
  font-size: clamp(36px, 7vw, 70px);
  font-weight: 700;
  letter-spacing: normal;
  text-transform: none;
  margin: 0 0 14px;
  color: #000;
  line-height: 1;
}
/* Hero text color toggle (Settings → Public Site). Light = white, dark = black.
   Defaults match "dark" (#000) for backwards compatibility on hero images that
   have plenty of contrast; the radio explicitly drives this class. */
.public-hero.ph-text-light h1,
.public-hero.ph-text-light .ph-sub {
  color: #fcfaf7;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.18);
}
.public-hero.ph-text-dark h1,
.public-hero.ph-text-dark .ph-sub {
  color: #000000;
  text-shadow: none;
}
/* Legacy spacer kept for backward compat with older renders. */
.public-hero h1 .ph-spacer { display: inline-block; width: 0.4em; }
/* Per-letter spans + word gap. We use letter-spacing instead of literal space
   characters because the demo Nexa font watermarks its space glyph. */
.public-hero h1 .ph-letter { display: inline-block; letter-spacing: 0.4em; }
.public-hero h1 .ph-letter:last-child { letter-spacing: 0; }
.public-hero h1 .ph-word-gap { display: inline-block; width: 0.9em; }
.public-hero .ph-sub {
  font-family: var(--pub-garamond);
  font-style: italic;
  font-size: clamp(18px, 2.2vw, 28px);
  color: #000;
  margin: 0 0 32px;
  font-weight: 400;
}
.public-hero p {
  font-family: var(--pub-garamond);
  font-size: 16px;
  color: var(--pub-ink-soft);
  max-width: 60ch;
  margin: 0 auto 24px;
  line-height: 1.6;
}
.public-hero .ph-actions { display: none; }

/* ----- Featured Image Picker (Settings → Public Site) ----- */
.featured-image-picker {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
  grid-auto-rows: max-content;
  align-items: start;
  gap: 16px;
  max-height: 560px;
  overflow-y: auto;
  padding: 14px;
  border: 1px solid var(--border-soft, #e2e8f0);
  border-radius: 8px;
  background: #fafafa;
}
.fip-tile {
  position: relative;
  display: block;
  width: 100%;
  border: 2px solid transparent;
  border-radius: 6px;
  overflow: hidden;
  cursor: pointer;
  padding: 0;
  background: #fcfaf7;
  transition: border-color 0.15s ease, transform 0.15s ease, box-shadow 0.15s ease;
  box-shadow: 0 1px 2px rgba(0,0,0,0.05);
}
.fip-tile .fip-thumb {
  width: 100%;
  aspect-ratio: 1 / 1;
  background: #f5f5f5;
  display: block;
  overflow: hidden;
}
.fip-tile .fip-thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.fip-tile .fip-caption {
  display: block;
  padding: 8px 10px;
  font-size: 12px;
  line-height: 1.3;
  color: #1e293b;
  text-align: left;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  border-top: 1px solid #eef2f7;
  background: #fcfaf7;
}
.fip-tile:hover {
  border-color: #94a3b8;
  transform: translateY(-1px);
  box-shadow: 0 4px 12px rgba(0,0,0,0.08);
}
.fip-tile.is-selected {
  border-color: var(--blue, #3b82f6);
  box-shadow: 0 0 0 2px rgba(59,130,246,0.18), 0 4px 12px rgba(0,0,0,0.08);
}
.fip-tile .fip-check {
  position: absolute;
  top: 8px;
  right: 8px;
  width: 24px;
  height: 24px;
  background: var(--blue, #3b82f6);
  color: #fcfaf7;
  border-radius: 50%;
  display: none;
  align-items: center;
  justify-content: center;
  font-size: 14px;
  font-weight: 700;
  line-height: 1;
  box-shadow: 0 1px 3px rgba(0,0,0,0.2);
}
.fip-tile.is-selected .fip-check { display: flex; }
.fip-empty {
  padding: 24px;
  text-align: center;
  color: #64748b;
  font-size: 14px;
}

/* ----- Featured Hero preview row (compact summary in Settings) ----- */
.featured-hero-preview {
  display: flex;
  gap: 16px;
  align-items: flex-start;
  padding: 14px;
  border: 1px solid var(--border-soft, #e2e8f0);
  border-radius: 8px;
  background: #fafafa;
}
.fhp-thumb {
  flex: 0 0 auto;
  width: 160px;
  height: 160px;
  border-radius: 6px;
  overflow: hidden;
  background: #f1f5f9;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px solid #e2e8f0;
}
.fhp-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.fhp-thumb.is-empty .fhp-empty-text {
  padding: 12px;
  text-align: center;
  font-size: 12px;
  color: #64748b;
  line-height: 1.4;
}
.fhp-thumb.is-empty small { font-size: 11px; color: #94a3b8; }
.fhp-meta {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-width: 0;
}
.fhp-title {
  font-size: 15px;
  font-weight: 600;
  color: #1e293b;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  min-height: 20px;
}
.fhp-actions { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 4px; }

/* ----- Featured Hero modal extensions ----- */
.modal-card.modal-card-lg {
  width: min(960px, 96vw);
  max-height: 88vh;
  display: flex;
  flex-direction: column;
}
.modal-card.modal-card-lg .modal-body {
  overflow-y: auto;
  flex: 1 1 auto;
  padding: 12px 20px 20px;
}
.modal-card.modal-card-lg .featured-image-picker {
  max-height: none;
  border: 0;
  padding: 0;
  background: transparent;
}
.modal-toolbar {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 20px;
  border-bottom: 1px solid var(--border-soft, #e2e8f0);
  background: #fcfaf7;
}
.modal-toolbar .input {
  flex: 1 1 auto;
  max-width: 380px;
}

/* ----- Hero Position Editor modal ----- */
.modal-card.modal-card-xl {
  width: min(1100px, 96vw);
  max-height: 92vh;
}
.modal-card .modal-foot {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 12px 20px;
  border-top: 1px solid var(--border-soft, #e2e8f0);
  background: #fcfaf7;
}
.hpe-stage {
  width: 100%;
  aspect-ratio: 16 / 9;
  max-height: 50vh;
  background: #000;
  border-radius: 8px;
  overflow: hidden;
  position: relative;
  user-select: none;
}
.hpe-frame {
  position: absolute;
  inset: 0;
  min-height: 0;            /* override .public-hero min-height: calc(100vh - 78px) */
  cursor: grab;
  touch-action: none;
}
.hpe-frame.is-dragging { cursor: grabbing; }
.hpe-frame .ph-image { pointer-events: none; }
.hpe-frame .ph-overlay { pointer-events: none; }
.hpe-frame .ph-inner { pointer-events: none; padding: 32px 24px; }
.hpe-frame .ph-inner h1 { font-size: clamp(24px, 4vw, 44px) !important; }
.hpe-frame .ph-sub { font-size: clamp(13px, 1.4vw, 17px) !important; }

.hpe-controls {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-top: 16px;
  padding: 14px 16px;
  background: #f8fafc;
  border: 1px solid #e2e8f0;
  border-radius: 8px;
}
.hpe-row {
  display: grid;
  grid-template-columns: 110px 1fr 56px;
  align-items: center;
  gap: 14px;
}
.hpe-row-label {
  font-size: 13px;
  color: #475569;
  font-weight: 500;
}
.hpe-row-val {
  font-size: 13px;
  color: #1e293b;
  text-align: right;
  font-variant-numeric: tabular-nums;
}
.hpe-row input[type="range"] { width: 100%; }

/* ----- Section wrapper (with vertical category label, Elementor-style) ----- */
.public-section {
  position: relative;
  padding: 72px 80px;
  background: #fcfaf7;
  border-top: 0;
  scroll-margin-top: 80px;
}
.public-frame .public-biography,
.public-frame .public-studio-shots { scroll-margin-top: 80px; }
/* Vertical category label — shown only on .public-cat-section. */
.public-section .ps-vlabel { display: none; }
.public-section.public-cat-section .ps-vlabel {
  /* Sticky vertical label: stays in view while scrolling through that
     category's tiles, then releases when its section ends. */
  display: block;
  position: sticky;
  top: 96px; /* sits just below the ~66px sticky nav */
  align-self: start; /* required for sticky inside the grid column */
  font-family: "Nexa", "Helvetica Neue", Arial, sans-serif;
  font-size: 15px;
  font-weight: 700;
  letter-spacing: 3px;
  color: #000;
  text-transform: uppercase;
  writing-mode: vertical-rl;
  transform: rotate(180deg);
  white-space: nowrap;
  pointer-events: none;
  z-index: 2;
  justify-self: center;
}
@media (max-width: 900px) and (min-width: 641px) {
  .public-section.public-cat-section .ps-vlabel { display: none; }
}
/* Phones keep the vertical category label (matches joannaaplin.com) but in a
   narrower rail and closer to the tiles. */
@media (max-width: 640px) {
  /* Not sticky on phones: the label marks the start of the category and then
     scrolls away, rather than riding alongside every tile. */
  .public-section.public-cat-section .ps-vlabel {
    display: block;
    position: static;
    font-size: 13px;
    letter-spacing: 2.5px;
  }
}
/* In admin Public Site preview, the public sticky nav itself sits 44px down
   (under the Folio auth bar), so the vertical category label must also be
   pushed down to clear it. */
.public-frame--admin-preview .public-section.public-cat-section .ps-vlabel {
  top: 164px;
}
.public-section-head {
  display: flex;
  justify-content: flex-end;
  align-items: baseline;
  gap: 16px;
  margin-bottom: 32px;
}
.public-section h2 {
  display: none; /* heading is replaced by the vertical label on Joanna's site */
}
.public-section .ps-meta {
  font-family: var(--pub-nexa);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 1.5px;
  text-transform: uppercase;
  color: var(--pub-ink-soft);
}

/* ----- Artist section (mirrors Joanna's bio block: text left, photo right)
   Pulls from settings.statement (multi-paragraph) and optional
   settings.artist_photo_url. Hidden entirely when statement is empty. */
/* Full-bleed like Joanna's site: section spans 100% width with 100px
   gutters on each side. Text column hugs the left gutter, photo hugs
   the right gutter. */
.public-frame .public-artist {
  display: grid;
  grid-template-columns: 60% 40%;
  gap: 0;
  align-items: center;
  padding: 80px 150px 140px;
  background: #fcfaf7;
}
@media (max-width: 1100px) {
  .public-frame .public-artist {
    padding: 80px 48px;
    gap: 48px;
  }
}
@media (max-width: 900px) {
  .public-frame .public-artist {
    grid-template-columns: 1fr;
    padding: 64px 24px;
    gap: 34px;
  }
}
.public-frame .public-artist .pa-text {
  font-family: var(--pub-garamond);
  font-size: 16px;
  line-height: 30px;
  color: #000000;
  justify-self: stretch;
  padding-right: 25px;
}
.public-frame .public-artist .pa-text p {
  margin: 0 0 1.4em;
}
.public-frame .public-artist .pa-text p:last-child {
  margin-bottom: 0;
  font-style: italic;
}
.public-frame .public-artist .pa-photo {
  justify-self: end;
}
.public-frame .public-artist .pa-photo img {
  width: 100%;
  max-width: 380px;
  height: auto;
  display: block;
}
.public-frame .public-artist .pa-photo-placeholder {
  width: 100%;
  max-width: 380px;
  aspect-ratio: 4 / 5;
  background: #f0f0f0;
  color: #999;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--pub-nexa);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 2px;
  text-transform: uppercase;
}
/* Stacked layout leads with the photo, then the statement (joannaaplin.com).
   Declared after the base rules so it wins on equal specificity. */
@media (max-width: 900px) {
  .public-frame .public-artist .pa-photo { order: -1; justify-self: stretch; }
  .public-frame .public-artist .pa-photo img,
  .public-frame .public-artist .pa-photo-placeholder { max-width: 100%; }
  .public-frame .public-artist .pa-text { padding-right: 0; }
}

/* =======================================================================
   Public Site — Biography section (mirrors joannaaplin.com/biography)
   Layout: photo left, content right. Same horizontal rhythm as the
   Artist section: 60% / 40% columns with 150px gutters. Section headings
   are Nexa bold uppercase — same scale as Joanna's. Body text inherits
   the EB Garamond 16px / 30px / #000 spec.
   ======================================================================= */
.public-frame .public-biography {
  display: grid;
  grid-template-columns: 40% 60%;
  gap: 0;
  align-items: start;
  padding: 80px 150px 140px;
  background: #fcfaf7;
}
@media (max-width: 1100px) {
  .public-frame .public-biography {
    padding: 80px 48px 120px;
    gap: 32px;
  }
}
@media (max-width: 900px) {
  .public-frame .public-biography {
    grid-template-columns: 1fr;
    padding: 64px 24px 96px;
    gap: 26px;
  }
}
.public-frame .public-biography .pb-photo {
  justify-self: start;
}
.public-frame .public-biography .pb-photo img {
  width: 85%;
  max-width: 85%;
  height: auto;
  display: block;
}
/* Full-width biography photo on stacked layouts (joannaaplin.com). Declared
   after the base .pb-photo rules so it wins on equal specificity. */
@media (max-width: 900px) {
  .public-frame .public-biography .pb-photo { justify-self: stretch; }
  .public-frame .public-biography .pb-photo img,
  .public-frame .public-biography .pb-photo-placeholder {
    width: 100%;
    max-width: 100%;
  }
}
.public-frame .public-biography .pb-photo-placeholder {
  width: 85%;
  max-width: 85%;
  aspect-ratio: 4 / 5;
  background: #f0f0f0;
  color: #999;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--pub-nexa);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 2px;
  text-transform: uppercase;
}
.public-frame .public-biography .pb-content {
  justify-self: stretch;
}
.public-frame .public-biography .pb-h {
  font-family: var(--pub-nexa);
  font-size: 15px;
  font-weight: 700;
  letter-spacing: 0.8px;
  text-transform: uppercase;
  color: #000000;
  margin: 0 0 5px;
}
.public-frame .public-biography .pb-h:not(:first-child) {
  margin-top: 40px;
}
.public-frame .public-biography .pb-body {
  font-family: var(--pub-garamond);
  font-size: 16px;
  line-height: 1.5;
  color: #000000;
}
.public-frame .public-biography .pb-body p {
  margin: 0;
}
.public-frame .public-biography .pb-body p + p {
  margin-top: 0;
}
/* Bio (and only bio) gets paragraph spacing. Education and Press are
   line-by-line lists with no inter-line gap beyond line-height. */
.public-frame .public-biography .pb-body.pb-bio p + p {
  margin-top: 1em;
}
.public-frame .public-biography .pb-body .pb-quote {
  font-style: italic;
  margin-top: 1em;
}
/* Press links — match the modal "Available for purchase at <Gallery>"
   styling: rose color, no underline at rest or hover, deeper rose on hover. */
.public-frame .public-biography .pb-press a,
.public-frame .public-biography .pb-body a {
  color: #cc3366;
  text-decoration: none;
  transition: color 0.3s ease-in-out;
}
.public-frame .public-biography .pb-press a:hover,
.public-frame .public-biography .pb-body a:hover {
  color: #a32a52;
  text-decoration: none;
}

/* ----- Category sections (joannaaplin.com style) — reuse .public-grid card styles ----- */
.public-frame .public-cat-stack { display: block; }
/* Match Joanna: 100px top, 100px right, 50px bottom; left is reduced because
   the sticky label rail lives in the outer gutter, closer to the viewport edge */
.public-frame .public-cat-section {
  padding: 100px 100px 140px 40px;
  position: relative;
  /* Two-column layout: narrow rail for the sticky vertical label, then content */
  display: grid;
  grid-template-columns: 24px 1fr;
  column-gap: 60px;
  align-items: start;
}
.public-frame .public-cat-section > .grid.public-grid,
.public-frame .public-cat-section > .pc-more-wrap { grid-column: 2; }
/* When the Load More button is still present, its 110px top margin already
   provides spacing — pull the bottom padding back to 50px so the button
   sits at a comfortable distance from the next category. */
.public-frame .public-cat-section:has(.pc-more-wrap) { padding-bottom: 50px; }
/* Last category keeps a full 160px bottom so it breathes into the Artist Quote section */
.public-frame .public-cat-section:last-of-type { padding-bottom: 160px; }
@media (max-width: 1100px) {
  .public-frame .public-cat-section { padding: 80px 56px 110px 32px; }
  .public-frame .public-cat-section:has(.pc-more-wrap) { padding-bottom: 40px; }
  .public-frame .public-cat-section:last-of-type { padding-bottom: 120px; }
}
@media (max-width: 640px) {
  /* joannaaplin.com centres the tiles in the viewport and lets the vertical
     label live in the left gutter. Mirror that by matching the right padding
     to (left padding + label rail + gap) so the content column lands dead
     centre: 6 + 20 + 10 = 36px. */
  .public-frame .public-cat-section {
    padding: 56px 36px 80px 6px;
    grid-template-columns: 20px 1fr;
    column-gap: 10px;
  }
  .public-frame .public-cat-section:has(.pc-more-wrap) { padding-bottom: 32px; }
  .public-frame .public-cat-section:last-of-type { padding-bottom: 88px; }
}
/* Grid gutters — split the difference (was 60/30, now 80/45) */
.public-frame .public-cat-section .grid.public-grid {
  gap: 80px 45px;
  padding: 0;
}
/* Captions: 15px, EB Garamond (sans-serif fallback chain to match joannaaplin.com) */
.public-frame .public-cat-section .grid.public-grid .card .card-title,
.public-frame .public-cat-section .grid.public-grid .card .card-meta {
  font-family: "EB Garamond", sans-serif;
  font-size: 15px;
}
/* The hidden HTML attribute must beat .card's display:flex */
.public-frame .public-cat-grid .pc-tile[hidden] { display: none !important; }
/* Load More — matches Joanna's reference (Nexa 12px, normal weight, 3px tracking) */
.public-frame .pc-more-wrap {
  display: flex;
  justify-content: center;
  margin-top: 110px; /* +50 above for separation from the grid */
}
.public-frame .pc-load-more {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-family: var(--pub-nexa, "Nexa", "Helvetica Neue", Arial, sans-serif);
  font-size: 12px;
  font-weight: 400;
  letter-spacing: 3px;
  text-transform: uppercase;
  color: var(--pub-ink, #111);
  background: transparent;
  border: 1px solid var(--pub-ink, #111);
  border-radius: 999px;
  padding: 12px 26px;
  cursor: pointer;
  will-change: transform;
  /* Same signature as every other Folio button: pill by default, square and
     slightly larger on hover. */
  transition:
    transform 0.3s ease,
    background-color 0.3s ease,
    color 0.3s ease,
    border-color 0.3s ease;
}
.public-frame .pc-load-more:hover {
  border-radius: 0;
  transform: scale(1.06);
  background: var(--pub-ink, #111);
  color: #fcfaf7;
}

/* ----- Works filter (All | Available | Previous) ----- */
/* Centered row above the first category section. Editorial, small,
   matches joannaaplin.com. Active item uses --pub-red, same as the
   active top-nav link. No underline — colour carries it. */
.public-frame .pc-works-filter {
  display: flex;
  justify-content: center;
  align-items: baseline;
  gap: 14px;
  padding: 60px 100px 0;
  font-family: var(--pub-garamond);
  font-size: 15px;
  color: #111;
}
.public-frame .pc-works-filter .pc-wf-item {
  background: transparent;
  border: 0;
  padding: 4px 2px;
  font: inherit;
  color: #111;
  cursor: pointer;
  letter-spacing: 0.01em;
  transition: color 0.15s ease;
}
.public-frame .pc-works-filter .pc-wf-item:hover {
  color: var(--pub-red, #FF0000);
}
.public-frame .pc-works-filter .pc-wf-item.is-active {
  color: var(--pub-red, #FF0000);
}
.public-frame .pc-works-filter .pc-wf-sep {
  color: #bbb;
  user-select: none;
  font-size: 13px;
}
@media (max-width: 760px) {
  .public-frame .pc-works-filter {
    padding: 40px 24px 0;
    gap: 10px;
    font-size: 14px;
    flex-wrap: wrap;
  }
}

/* ----- Artwork grid (4-col desktop, EB Garamond captions) ----- */
.public-frame .grid.public-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  /* row gap : column gap — split between original 40px and Joanna's 160px. */
  gap: 100px 60px;
  align-items: end;
  padding: 24px 0 56px;
}
@media (max-width: 1100px) {
  .public-frame .grid.public-grid { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 640px) {
  .public-frame .grid.public-grid { grid-template-columns: 1fr; }
  .public-section { padding: 48px 24px; }
  .public-section .ps-vlabel { display: none; }
}
.public-frame .grid.public-grid .card {
  background: transparent;
  border: 0;
  border-radius: 0;
  padding: 0;
  cursor: pointer;
  text-align: center;
  transform: none;
  transition: opacity 600ms ease;
}
/* Kill the global .card:hover translateY jitter for public tiles — gentle
   opacity fade only. */
.public-frame .grid.public-grid .card:hover,
.public-frame .grid.public-grid .card:focus,
.public-frame .grid.public-grid .card:focus-visible {
  transform: none !important;
  opacity: 0.7;
}
.public-frame .grid.public-grid .card .thumb,
.public-frame .grid.public-grid .card .preview-thumb {
  background: transparent;
  border: 0;
  border-radius: 0;
  box-shadow: none;
  aspect-ratio: auto;
  min-height: 0;
  padding: 0;
  margin-bottom: 14px;
}
.public-frame .grid.public-grid .card .thumb img,
.public-frame .grid.public-grid .card .preview-thumb img {
  width: 100%;
  height: auto;
  max-height: 360px;
  object-fit: contain;
  object-position: center bottom;
  background: transparent;
}
.public-frame .grid.public-grid .card .card-title {
  font-family: var(--pub-garamond);
  font-size: 16px;
  font-weight: 400;
  font-style: normal;
  line-height: 1;
  color: #000;
  margin: 0 0 4px;
  letter-spacing: 0;
  text-align: center;
}
.public-frame .grid.public-grid .card .card-meta,
.public-frame .grid.public-grid .card .card-year {
  font-family: var(--pub-garamond);
  font-size: 16px;
  font-style: normal;
  line-height: 1;
  color: var(--pub-ink-soft);
  border: 0;
  padding: 0;
  margin: 0 0 4px;
  justify-content: center;
  text-align: center;
}
.public-frame .grid.public-grid .card .card-meta { margin-bottom: 0; }
/* Hide the per-card status/price line on the Public Site grid —
   Joanna's design shows title + dims only. */
.public-frame .grid.public-grid .card .card-foot { display: none; }
.public-frame .grid.public-grid .card .card-price {
  font-family: var(--pub-nexa);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 1.5px;
  text-transform: uppercase;
  color: #000;
}

/* ----- Footer (black, centered, Roboto — mirrors joannaaplin.com) -----
   joannaaplin.com footer uses Roboto 12px body / 18px h4@600, all
   center-aligned, pure white on pure black. */
.public-footer {
  background: #000000;
  color: #fcfaf7;
  padding: 80px 80px 48px;
  font-family: "Roboto", "Helvetica Neue", Arial, sans-serif;
  text-align: center;
}
.public-footer-cols {
  display: grid;
  grid-template-columns: 1.4fr 1fr 1fr 1fr;
  gap: 40px;
  max-width: 1000px;
  margin: 0 auto;
  text-align: center;
}
@media (max-width: 900px) {
  .public-footer { padding: 64px 24px 32px; }
  .public-footer-cols { grid-template-columns: 1fr 1fr; gap: 40px; }
}
@media (max-width: 540px) {
  .public-footer-cols { grid-template-columns: 1fr; gap: 32px; }
}
.public-footer h4 {
  font-family: "Roboto", "Helvetica Neue", Arial, sans-serif;
  font-size: 18px;
  font-weight: 600;
  letter-spacing: normal;
  text-transform: none;
  margin: 0 0 14px;
  color: #fcfaf7;
  text-align: center;
}
.public-footer p,
.public-footer a,
.public-footer li {
  font-family: "Roboto", "Helvetica Neue", Arial, sans-serif;
  font-size: 12px;
  font-weight: 400;
  letter-spacing: normal;
  text-transform: none;
  color: #fcfaf7;
  text-decoration: none;
  line-height: 1.6;
  text-align: center;
}
.public-footer ul { list-style: none; padding: 0; margin: 0; text-align: center; line-height: 1.15; }
.public-footer li { padding: 0; line-height: 1.15; }
.public-footer ul li + li { margin-top: 0; }
.public-footer a:hover { color: #DB9C18; }
.public-footer .pf-brand {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-start;
  gap: 6px;
  text-align: center;
}
.public-footer .pf-logo {
  display: block;
  max-width: 180px;
  max-height: 90px;
  width: auto;
  height: auto;
  object-fit: contain;
  /* Force any dark/colored logo to render in white on the black footer. */
  filter: brightness(0) invert(1);
}
.public-footer .pf-brand-text {
  font-family: var(--pub-nexa);
  font-size: 12px;
  font-weight: 400;
  letter-spacing: normal;
  text-transform: none;
  color: #fcfaf7;
  text-align: center;
  margin-top: 4px;
}
.public-footer .pf-folio-link { display: inline-flex; align-items: center; vertical-align: middle; }
.public-footer .pf-folio-wordmark { height: 20px; width: auto; display: block; fill: #F8F5EE; overflow: visible; margin: 0 0 4px 2px; }
.public-footer .pf-brand-name {
  font-family: "Roboto", "Helvetica Neue", Arial, sans-serif;
  font-size: 12px;
  font-weight: 400;
  letter-spacing: normal;
  text-transform: uppercase;
  margin-bottom: 8px;
  text-align: center;
}
.public-footer .pf-copyright {
  opacity: 0.55;
  font-size: 11px;
  letter-spacing: normal;
  text-transform: none;
  margin: 8px 0 0;
  text-align: center;
}
.public-footer .pf-socials {
  display: flex;
  gap: 2px;
  margin-top: 8px;
  justify-content: center;
}
.public-footer .pf-socials a {
  color: #fcfaf7;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 2px;
}
.public-footer .pf-socials a:hover { color: #DB9C18; }
.public-footer .pf-socials svg { width: 20px; height: 20px; }
.public-footer .pf-base {
  margin: 72px auto 0;
  padding-top: 72px;
  border-top: 1px solid rgba(255, 255, 255, 0.18);
  font-size: 11px;
  letter-spacing: normal;
  opacity: 0.7;
  text-align: center;
  max-width: 1000px;
}
.public-footer .pf-base strong {
  font-weight: 700;
  opacity: 1;
}

/* ----- Modal ----- */
.modal { position: fixed; inset: 0; z-index: 50; display: flex; align-items: center; justify-content: center; }
.modal[hidden] { display: none; }
.modal-backdrop { position: absolute; inset: 0; background: rgba(20, 20, 20, 0.55); backdrop-filter: blur(2px); }
.modal-card {
  position: relative;
  background: var(--surface-elev);
  border: 1px solid var(--border-soft);
  border-radius: var(--radius-xl);
  max-width: 880px; width: calc(100% - 32px);
  max-height: calc(100vh - 32px);
  overflow-y: auto;
  box-shadow: var(--shadow-lg);
}
.modal-close {
  position: absolute; top: 12px; right: 12px;
  width: 36px; height: 36px;
  border-radius: 999px; border: 1px solid var(--border);
  background: var(--surface);
  font-size: 22px; line-height: 1;
  display: flex; align-items: center; justify-content: center;
  color: var(--ink-soft);
}
.modal-body { padding: var(--space-6); }
.modal-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-5);
}
@media (max-width: 760px) { .modal-grid { grid-template-columns: 1fr; } }

/* ----- Mobile sidebar collapse ----- */
@media (max-width: 820px) {
  .shell, .shell.sidebar-collapsed { grid-template-columns: 1fr; }
  .sidebar {
    position: static; height: auto;
    flex-direction: row; flex-wrap: wrap;
    align-items: center;
    padding: var(--space-3) var(--space-4);
    border-bottom: 1px solid var(--border-soft);
    border-right: 0;
    gap: var(--space-3);
    overflow: visible;
  }
  .sidebar-toggle { display: none; }
  .nav { flex-direction: row; flex-wrap: wrap; }
  .nav-item { padding: 6px 12px; font-size: 12px; }
  .nav-icon { display: none; }
  .sidebar-foot { margin-top: 0; flex-direction: row; align-items: center; gap: 8px; }
  .topbar { grid-template-columns: 1fr; padding: var(--space-3) var(--space-4); }
  .view { padding: var(--space-4); }
}

/* Visibility toggle (custom checkbox) */
.toggle {
  display: inline-flex; align-items: center; gap: 8px;
  cursor: pointer; user-select: none;
  position: relative;
}
.toggle input {
  position: absolute;
  width: 36px; height: 20px;
  margin: 0;
  opacity: 0;
  cursor: pointer;
  z-index: 2;
}
.toggle .track {
  width: 36px; height: 20px;
  border-radius: 999px;
  background: var(--surface-3);
  position: relative;
  transition: background var(--transition);
  pointer-events: none;
}
.toggle .track::after {
  content: "";
  position: absolute; top: 2px; left: 2px;
  width: 16px; height: 16px;
  border-radius: 999px;
  background: var(--surface-elev);
  box-shadow: 0 1px 3px rgba(0,0,0,0.18);
  transition: transform var(--transition);
}
.toggle input:checked + .track { background: var(--accent); }
.toggle input:checked + .track::after { transform: translateX(16px); }
.toggle .label { font-size: var(--text-sm); color: var(--ink); }

/* tiny helpers */
.hr { height: 1px; background: var(--border-soft); margin: var(--space-5) 0; border: 0; }
.muted { color: var(--ink-mute); }
.tabular { font-variant-numeric: tabular-nums; }
.row { display: flex; gap: var(--space-3); align-items: center; }
.gap-2 { gap: var(--space-2); }
.gap-3 { gap: var(--space-3); }
.flex-1 { flex: 1; }
.mb-3 { margin-bottom: var(--space-3); }
.mb-4 { margin-bottom: var(--space-4); }
.mt-3 { margin-top: var(--space-3); }
.mt-4 { margin-top: var(--space-4); }

/* Pricing tier table (in artwork modal) */
.tiers {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: var(--space-2);
  margin-top: var(--space-3);
}
.tier {
  background: var(--surface-2);
  border: 1px solid var(--border-soft);
  border-radius: var(--radius-md);
  padding: 10px 6px;
  text-align: center;
}
.tier.is-active { background: var(--accent-soft); border-color: var(--accent); }
.tier-rate { font-size: var(--text-xs); color: var(--ink-mute); }
.tier-amount { font-family: var(--font-display); font-size: 18px; font-weight: 600; color: var(--ink); margin-top: 2px; }
.tier-amount.is-active { color: var(--accent); }

/* ---------- Status dots (replaces SOLD/AVAILABLE chip overlays) ---------- */
.status-dot {
  display: inline-block;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  flex-shrink: 0;
  vertical-align: middle;
  background: var(--ink-mute);
}
.status-dot.sold,
.status-dot.sold-paid { background: #EF4244; }
.status-dot.sold-unpaid { background: #FFD700; }
.status-dot.available { background: #0BDA51; }
/* Private Collection = artist-held / not for sale. Plum reads as
   "reserved" without competing with sold-red or available-green. */
.status-dot.private-collection { background: #933994; }
/* Work In Progress = unfinished, set aside. A brighter, more saturated purple
   than the muted plum used for Private Collection, so the two stay distinct. */
.status-dot.work-in-progress { background: #2F00FF; }
/* Make bare status dots focusable for keyboard tooltip access without changing the cursor */
.status-dot[tabindex] { outline: none; }
.status-dot[tabindex]:focus-visible { box-shadow: 0 0 0 2px rgba(0,0,0,0.15); }

/* Custom instant tooltip on bare status dots (replaces native title delay).
   Wrapping the dot in .status-dot-tip allows us to render a styled label
   directly via ::after, showing on hover with no browser timer. */
.status-dot-tip {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.status-dot-tip::after {
  content: attr(data-tip);
  position: absolute;
  bottom: calc(100% + 8px);
  right: 0;
  /* Anchor to the right edge of the dot so the tooltip grows leftward.
     This avoids clipping when the dot sits at the far-right of its row. */
  background: #fcfaf7;
  color: #2B2F2D;
  font-size: 12px;
  font-weight: 400;
  white-space: nowrap;
  padding: 6px 10px;
  border-radius: 6px;
  border: 1px solid rgba(0,0,0,0.08);
  box-shadow: 0 4px 12px rgba(0,0,0,0.12);
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.08s ease-out;
  z-index: 1000;
}
.status-dot-tip:hover::after,
.status-dot-tip:focus-within::after {
  opacity: 1;
}
/* Containers that normally clip via overflow:hidden need to allow our tooltip to escape
   when a .status-dot-tip is hovered. Scoped tightly so list ellipsis still works elsewhere. */
.art-row > div.al-status-col,
.art-row > div.al-status-col * { overflow: visible !important; }
.card-foot,
.card-foot * { overflow: visible !important; }
.eli-status,
.eli-status * { overflow: visible !important; }

/* Note: the generic [data-tip] tooltip CSS was removed when we scoped tooltips
   to status dots only. If reintroducing tooltips elsewhere later, restore the
   .status-dot-tip pattern (wrap the target in a span with data-tip). */

/* Dot + price clustered together in card foot */
.price-with-status {
  display: inline-flex;
  align-items: center;
  gap: 8px;
}

/* Inline status with label (used in editor preview chips & public modal) */
.status-pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: var(--text-xs);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink);
  font-weight: 500;
  padding: 4px 0;
}

/* Center the dot AND its header in the list-view STATUS column */
.art-row > div:nth-child(6) {
  display: flex;
  align-items: center;
  justify-content: center;
}
.art-list-head > div:nth-child(6) {
  text-align: center;
}

/* ===== v36: Filters/Sort popover UI ===== */
.popover-wrap {
  position: relative;
  display: inline-block;
}
.icon-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 32px;
  padding: 0 8px;
  border: 1px solid transparent;
  background: transparent;
  color: var(--ink-soft, #555);
  border-radius: 6px;
  cursor: pointer;
  font-size: 13px;
  font-weight: 500;
  line-height: 1;
  transition: background 120ms ease, color 120ms ease, border-color 120ms ease;
}
.icon-btn:hover {
  background: var(--surface-soft, rgba(0,0,0,0.04));
  color: var(--ink, #1a1a1a);
}
.icon-btn svg {
  flex-shrink: 0;
  opacity: 0.7;
}
.icon-btn:hover svg { opacity: 1; }
.icon-btn.is-active {
  background: var(--surface-soft, rgba(0,0,0,0.05));
  color: var(--ink, #1a1a1a);
  border-color: transparent;
}
.icon-btn.is-active svg { opacity: 1; }
.icon-btn-square {
  width: 32px;
  padding: 0;
  justify-content: center;
}
.icon-btn-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 16px;
  height: 16px;
  padding: 0 5px;
  margin-left: 2px;
  border-radius: 8px;
  background: var(--ink, #1a1a1a);
  color: var(--surface, #fcfaf7);
  font-size: 10px;
  font-weight: 600;
  line-height: 1;
}

.popover {
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  z-index: 100;
  min-width: 260px;
  padding: 12px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 10px;
  box-shadow: 0 8px 24px rgba(0,0,0,0.10), 0 2px 6px rgba(0,0,0,0.06);
  display: flex;
  flex-direction: column;
  gap: 10px;
}
[data-theme="dark"] .popover {
  box-shadow: 0 8px 24px rgba(0,0,0,0.40), 0 2px 6px rgba(0,0,0,0.25);
}
.popover[hidden] { display: none; }

.popover-row {
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.popover-row .select {
  width: 100%;
  max-width: none;
}
.popover-label {
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-muted, #666);
}
.popover-foot {
  display: flex;
  justify-content: center;
  margin-top: 4px;
  padding-top: 8px;
  border-top: 1px solid var(--border);
}

.popover-sort {
  min-width: 200px;
  padding: 6px;
  gap: 0;
}
.popover-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  padding: 8px 10px;
  border: 0;
  background: transparent;
  color: var(--text);
  font: inherit;
  font-size: 13px;
  text-align: left;
  border-radius: 6px;
  cursor: pointer;
  transition: background 100ms ease;
}
.popover-item:hover {
  background: var(--surface-2, rgba(0,0,0,0.04));
}
[data-theme="dark"] .popover-item:hover {
  background: rgba(255,255,255,0.06);
}
.popover-item.is-active {
  color: var(--accent, #1f8a70);
  font-weight: 600;
}

/* ===== v37: Upload zone & image picker modal ===== */

/* Upload zone (replaces empty editor state) */
.upload-zone {
  display: block;
  width: 100%;
  margin-top: 0;
  padding: 0;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  cursor: pointer;
  transition: background 140ms ease, border-color 140ms ease;
  font-family: inherit;
  color: var(--ink);
  text-align: center;
}
.upload-zone:hover {
  background: var(--surface-3);
  border-color: var(--accent);
}
.upload-zone-inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 10px;
  aspect-ratio: 4 / 5;
  padding: 32px 24px;
  margin: 14px;
  border: 1.5px dashed var(--border);
  border-radius: var(--radius-md);
  background: linear-gradient(180deg, rgba(252,250,247,0.5), rgba(252,250,247,0.0));
}
[data-theme="dark"] .upload-zone { background: #242424; }
[data-theme="dark"] .upload-zone:hover { background: #2b2b2b; }
[data-theme="dark"] .upload-zone-inner { background: #2B2F2D; }
.upload-zone:hover .upload-zone-inner {
  border-color: var(--accent);
}
/* Drag-and-drop hover state on the editor preview slot */
.editor-preview-slot.is-drag .upload-zone-inner,
.editor-preview-slot.is-drag .preview-thumb {
  border-color: var(--accent);
  background: var(--accent-soft);
}
.editor-preview-slot.is-drag {
  outline: 2px dashed var(--accent);
  outline-offset: 4px;
  border-radius: var(--radius-md);
}
.editor-preview-slot.is-drag * {
  pointer-events: none;
}
/* Upload-in-progress: dim + show progress cursor */
.editor-preview-slot.is-uploading {
  opacity: 0.7;
  cursor: progress;
}
.editor-preview-slot.is-uploading::after {
  content: "Uploading\2026";
  position: absolute;
  top: 50%; left: 50%;
  transform: translate(-50%, -50%);
  padding: 6px 12px;
  background: var(--ink); color: var(--ink-inverse);
  font-size: 12px; font-weight: 500;
  border-radius: var(--radius-sm);
  pointer-events: none;
  z-index: 2;
}
.editor-preview-slot { position: relative; }
.upload-zone-plus {
  width: 56px;
  height: 56px;
  border-radius: 50%;
  background: var(--accent);
  color: var(--accent-ink);
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.upload-zone-label {
  font-family: var(--font-display);
  font-size: var(--text-lg);
  color: var(--ink);
  margin-top: 4px;
}
.upload-zone-sub {
  font-size: var(--text-sm);
}
.upload-zone.is-compact .upload-zone-inner {
  aspect-ratio: auto;
  padding: 22px;
}

/* Preview thumb wrapper (when image already exists) */
.preview-thumb-wrap {
  position: relative;
}
/* Overlay actions (Replace + Adjust) stacked in upper-right of image preview */
.preview-thumb-wrap .preview-overlay-actions {
  position: absolute;
  top: 10px;
  right: 10px;
  display: flex;
  flex-direction: column;
  gap: 6px;
  align-items: flex-end;
  opacity: 0;
  transition: opacity 140ms ease;
  pointer-events: none;
}
.preview-thumb-wrap .preview-overlay-actions .btn {
  background: var(--surface-elev);
  pointer-events: auto;
}
.preview-thumb-wrap:hover .preview-overlay-actions,
.preview-thumb-wrap:focus-within .preview-overlay-actions {
  opacity: 1;
}
@media (pointer: coarse) {
  .preview-thumb-wrap .preview-overlay-actions { opacity: 1; }
}
/* "Alt text" sits alongside Replace / Adjust. A small green dot appears once
   the artist has written alternative text, so a filled artwork is obvious at a
   glance without opening the dialog. */
.preview-thumb-wrap .preview-overlay-actions .preview-alt {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.preview-alt-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: #2f9e5f;
  flex: 0 0 auto;
}

/* ----- Alternative Text dialog ----- */
.alt-modal-row {
  display: flex;
  gap: 14px;
  align-items: flex-start;
  margin-bottom: 14px;
}
.alt-modal-thumb {
  flex: 0 0 96px;
  width: 96px;
  border-radius: 10px;
  overflow: hidden;
  background: var(--surface-elev);
}
.alt-modal-thumb img {
  display: block;
  width: 100%;
  height: auto;
}
.alt-modal-help {
  flex: 1 1 auto;
  margin: 0;
  font-size: 13px;
  line-height: 1.55;
}
.alt-modal-input {
  width: 100%;
  resize: vertical;
}
.alt-modal-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  flex-wrap: wrap;
  margin-top: 12px;
}
.alt-modal-count { font-size: 12px; }
.alt-modal-count.is-warn { color: #c2410c; }
.alt-modal-note {
  margin: 12px 0 0 0;
  font-size: 12px;
  line-height: 1.5;
}
@media (max-width: 560px) {
  .alt-modal-row { flex-direction: column; }
  .alt-modal-thumb { flex: 0 0 auto; width: 120px; }
  .alt-modal-foot { flex-direction: column; align-items: stretch; }
  .alt-modal-foot .ai-actions { display: flex; gap: 8px; }
  .alt-modal-foot .ai-actions .btn { flex: 1 1 0; }
}

/* Image-URL field collapsed UI */
.image-url-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}
.link-btn {
  background: transparent;
  border: 0;
  padding: 0;
  font: inherit;
  font-size: var(--text-sm);
  color: var(--accent);
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 3px;
}
.link-btn:hover { color: var(--ink); }

/* Modal overlay & card */
.modal-overlay {
  position: fixed;
  inset: 0;
  z-index: 200;
  background: rgba(31, 36, 33, 0.45);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  animation: jafa-fade 140ms ease;
}
@keyframes jafa-fade {
  from { opacity: 0; }
  to   { opacity: 1; }
}
.modal-card {
  background: var(--surface-elev);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  width: min(640px, 100%);
  max-height: calc(100vh - 48px);
  display: flex;
  flex-direction: column;
  box-shadow: 0 20px 60px rgba(0,0,0,0.18), 0 4px 12px rgba(0,0,0,0.08);
  overflow: hidden;
}
.modal-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 18px 20px 12px;
}
.modal-title {
  margin: 0;
  font-family: var(--font-display);
  font-size: var(--text-lg);
  color: var(--ink);
}
.modal-close {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  border: 0;
  background: transparent;
  color: var(--ink-soft);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.modal-close:hover {
  background: var(--surface-2);
  color: var(--ink);
}
.modal-tabs {
  display: flex;
  gap: 4px;
  padding: 0 20px;
  border-bottom: 1px solid var(--border);
}
.modal-tab {
  position: relative;
  background: transparent;
  border: 0;
  padding: 10px 14px 12px;
  font: inherit;
  font-size: var(--text-sm);
  color: var(--ink-soft);
  cursor: pointer;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
}
.modal-tab:hover { color: var(--ink); }
.modal-tab.is-active {
  color: var(--accent);
  border-bottom-color: var(--accent);
  font-weight: 600;
}
.modal-body {
  padding: 24px 20px 20px;
  overflow-y: auto;
}

/* Image-picker panels */
.ip-drop {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 14px;
  padding: 36px 24px;
  background: var(--surface);
  border: 1.5px dashed var(--border);
  border-radius: var(--radius-md);
  color: var(--ink-soft);
  transition: background 140ms ease, border-color 140ms ease;
}
.ip-drop.is-drag {
  background: var(--accent-soft);
  border-color: var(--accent);
}
.ip-drop-icon { color: var(--accent); }
.ip-drop-hint { margin: 0; font-size: var(--text-sm); }

.ip-cam {
  display: flex;
  flex-direction: column;
  align-items: stretch;
}
/* Camera preview frame — locks the shape via padding-bottom so the
   preview never changes size between the empty state, live stream, and
   captured poster (iOS Safari can override CSS `aspect-ratio` on a live
   <video>, so we drive the box from the wrapper). Default is 4:3 landscape
   (desktop webcams) — mobile overrides to 3:4 portrait below so the preview
   matches the rear camera's natural portrait framing when the phone is held
   vertically. This keeps the preview and the captured photo the same shape. */
.ip-cam-frame {
  position: relative;
  width: 100%;
  border-radius: var(--radius-md);
  overflow: hidden;
  background: var(--ink);
}
.ip-cam-frame::before {
  content: "";
  display: block;
  padding-bottom: 75%; /* 4:3 landscape default */
}
@media (max-width: 720px) {
  .ip-cam-frame::before {
    padding-bottom: 133.333%; /* 3:4 portrait — matches phone camera */
  }
  .ip-cam-frame {
    max-height: 60vh;
  }
  .ip-cam-frame > video {
    max-height: 60vh;
  }
}
.ip-cam-frame > video {
  position: absolute;
  top: 0; left: 0;
  width: 100%;
  height: 100%;
  background: var(--ink);
  /* `contain` = show the full stream (with letterboxing if needed) so the
     preview matches exactly what gets captured. `cover` would crop the top
     and bottom of a portrait stream to fit a landscape box — causing the
     preview and the captured photo to look completely different. */
  object-fit: contain;
  border-radius: var(--radius-md);
}
.ip-cam-msg {
  margin-top: 12px;
  font-size: var(--text-sm);
  text-align: center;
}

/* Camera button row — keep pills on one line, equal-width on mobile,
   respect the hidden attribute (btn's inline-flex was overriding it). */
.ip-cam .row .btn[hidden] { display: none !important; }
.ip-cam .row {
  flex-wrap: wrap;
  gap: 8px;
}
.ip-cam .row .btn {
  white-space: nowrap;
  padding: 10px 18px;
}
@media (max-width: 720px) {
  .ip-cam .row {
    justify-content: center !important;
    gap: 8px !important;
  }
  .ip-cam .row .btn {
    flex: 1 1 0;
    min-width: 0;
    padding: 10px 12px;
    font-size: 13px;
  }
}

.ip-link-preview {
  margin-top: 12px;
  display: flex;
  justify-content: center;
}
.ip-link-preview img {
  max-width: 100%;
  max-height: 280px;
  border-radius: var(--radius-md);
  border: 1px solid var(--border);
}

/* ----- Site Settings: tabbed layout ----- */
/* CRITICAL: width must be stable across tabs. Was `width: min-content`
   which made the panel shrink/grow to fit each tab's contents — the
   Artist vs Trash tabs were visibly different widths. Locked to 100%. */
.settings-panel {
  padding: 0;
  overflow: hidden;
  width: 100%;
  max-width: 100%;
  margin-left: 0;
  margin-right: auto;
  display: grid;
  grid-template-rows: auto 1fr;
}
.settings-panel-body {
  box-sizing: border-box;
  width: 100%;
  min-width: 0;
  overflow: hidden;
}
.settings-panel-body > * { min-width: 0; max-width: 100%; }
.settings-tabs {
  display: flex;
  gap: 4px;
  padding: 0 24px;
  border-bottom: 1px solid var(--border);
  background: var(--surface-2);
  flex-wrap: nowrap;
  white-space: nowrap;
}
.settings-tab { flex: 0 0 auto; }
.settings-tab {
  position: relative;
  background: transparent;
  border: 0;
  padding: 14px 14px 16px;
  font: inherit;
  font-size: 12px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-soft);
  cursor: pointer;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
}
.settings-tab:hover { color: var(--ink); }
.settings-tab.is-active {
  color: var(--accent);
  border-bottom-color: var(--accent);
  font-weight: 600;
}
.settings-panel-body {
  padding: 24px;
}
.settings-panel #settings-form > .row {
  padding: 0 24px 20px;
}

/* ----- Field width caps inside Settings -----
   Panel-body stays full-width for layout consistency, but inputs/textareas
   inside .field.full don't need to stretch the whole panel. Cap them to
   sensible reading widths. Galleries (.gallery-card .form-grid > .field)
   intentionally excluded — their 50% 2-col layout already looks right.

   Description copy under section titles is also capped so it never runs
   wider than the form it describes. Same 760px cap used in Public Site Setup. */
.settings-panel-body .section-title,
.settings-panel-body .section-title + .muted,
.settings-panel-body .section-kicker + .section-title + .muted,
.settings-panel-body > p.muted {
  max-width: 760px;
}
.settings-panel-body .field.full > .input,
.settings-panel-body .field.full > .select,
.settings-panel-body .field.full > .input-prefix {
  max-width: 520px;
}
.settings-panel-body .field.full > .textarea {
  max-width: 720px;
}
/* Short fields: artist name, tagline, category name */
.settings-panel-body .field.full > input[name="artist_name"],
.settings-panel-body .field.full > input[name="headline"],
.settings-panel-body .field.full > input[name^="category_name_"] {
  max-width: 340px;
}
/* Pricing tier grid: 2×2 tight, left-aligned. Override .form-grid's stretchy
   1fr 1fr columns so the four tiers sit next to each other with no dead
   middle space. Each cell is ~220px wide. */
.settings-panel-body [data-pricing-tiers] {
  grid-template-columns: 220px 220px;
  justify-content: start;
  column-gap: 16px;
  row-gap: 14px;
}
.settings-panel-body [data-pricing-tiers] .field .input-prefix {
  max-width: 220px;
}
.settings-panel-body [data-pricing-tiers] .field .input.has-prefix {
  width: 100%;
}

/* ----- Categories: flat rows (no collapsible folder) ----- */
.category-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
  max-width: 720px;
}
.category-row {
  display: grid;
  grid-template-columns: minmax(0, 340px) max-content;
  align-items: center;
  gap: 12px;
}
.category-row-field {
  position: relative;
  width: 100%;
}
.category-row-field .category-row-input {
  /* Reserve right-side room for the count badge */
  padding-right: 80px;
}
.category-row-field .category-row-count {
  position: absolute;
  right: 14px;
  top: 50%;
  transform: translateY(-50%);
  pointer-events: none;
  font-size: 12px;
  white-space: nowrap;
}
.category-row [data-action="delete-category"],
.gallery-card-footer [data-action="delete-gallery"] {
  /* Both Delete buttons share identical visual weight — natural btn-sm padding */
  padding: 6px 12px;
  font-size: var(--text-xs);
  font-weight: 500;
  justify-content: center;
  /* Hug content — never stretch to fill grid cell */
  justify-self: start;
  width: auto;
}
.category-row .category-row-input {
  width: 100%;
}
.category-row-count {
  font-size: 12px;
  letter-spacing: 0.04em;
  white-space: nowrap;
}
@media (max-width: 600px) {
  .category-row { grid-template-columns: 1fr auto; }
}

/* ----- Import/Export rows: cap width ----- */
.settings-panel-body .data-action-row {
  max-width: 720px;
}

/* ----- Trash list: medium width cap ----- */
.settings-panel-body #trash-list {
  max-width: 680px;
}

/* Galleries panel inside settings */
.gallery-cards {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.gallery-card {
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--bg);
  overflow: hidden;
}
.gallery-card-summary {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 16px;
  cursor: pointer;
  list-style: none;
  user-select: none;
}
.gallery-card-summary::-webkit-details-marker { display: none; }
.gallery-card-summary:hover { background: var(--surface-soft, rgba(0,0,0,0.02)); }
.gallery-card-chev {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 16px;
  font-size: 18px;
  line-height: 1;
  color: var(--muted);
  transition: transform 0.15s ease;
}
.gallery-card[open] .gallery-card-chev { transform: rotate(90deg); }
.gallery-card-title {
  flex: 1;
  font-weight: 600;
  color: var(--ink);
}
.gallery-count {
  color: var(--muted);
  font-size: var(--text-sm);
  white-space: nowrap;
}
.gallery-card-body {
  padding: 4px 16px 16px;
  border-top: 1px solid var(--border);
}
.gallery-card-footer {
  grid-column: 1 / -1;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 12px;
  flex-wrap: wrap;
  margin-top: 4px;
}
.gallery-default-label {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  cursor: pointer;
  margin: 0;
  line-height: 1;
  font-size: var(--text-sm);
}
.gallery-default-label input[type="radio"] {
  margin: 0;
  vertical-align: middle;
}

/* ============================================================
   Folio CSV Import
   ============================================================ */
.folio-import-modal {
  position: fixed; inset: 0; z-index: 9999;
  display: flex; align-items: center; justify-content: center;
  font-family: var(--font-sans, "General Sans", system-ui, sans-serif);
}
.folio-import-modal .fi-backdrop {
  position: absolute; inset: 0; background: rgba(15, 23, 25, 0.55);
  backdrop-filter: blur(2px);
}
.folio-import-modal .fi-card {
  position: relative; z-index: 1;
  width: min(760px, 94vw); max-height: 88vh;
  background: var(--surface-elev);
  color: var(--ink);
  border-radius: 14px; box-shadow: 0 30px 80px rgba(0,0,0,.25);
  display: flex; flex-direction: column; overflow: hidden;
}
.folio-import-modal .fi-head {
  display: flex; justify-content: space-between; align-items: center;
  padding: 18px 22px; border-bottom: 1px solid var(--border, #e6e2db);
}
.folio-import-modal .fi-head h2 { margin: 0; font-size: 18px; font-weight: 600; }
.folio-import-modal .fi-x {
  background: transparent; border: 0; font-size: 24px; cursor: pointer;
  color: var(--muted, #6b6b6b); padding: 0 8px; line-height: 1;
}
.folio-import-modal .fi-body {
  padding: 20px 22px; overflow: auto; flex: 1;
}
.folio-import-modal .fi-foot {
  display: flex; justify-content: flex-end; gap: 10px;
  padding: 14px 22px; border-top: 1px solid var(--border, #e6e2db);
  background: var(--surface-2, #faf8f4);
}
.folio-import-modal .fi-lead { margin: 0 0 14px; color: var(--muted, #555); }
.folio-import-modal .fi-muted { color: var(--muted, #6b6b6b); }
.folio-import-modal .fi-drop {
  display: block; border: 2px dashed var(--border, #d6d1c5);
  border-radius: 10px; padding: 36px 20px; text-align: center;
  cursor: pointer; transition: border-color .15s, background .15s;
}
.folio-import-modal .fi-drop:hover,
.folio-import-modal .fi-drop.is-dragover {
  border-color: var(--accent, #933994); background: var(--surface-2, #faf8f4);
}
.folio-import-modal .fi-drop.is-dragover {
  background: #eef5f1;
}
.folio-import-modal .fi-drop-inner strong { display: block; margin-bottom: 6px; }
.folio-import-modal .fi-details { margin-top: 18px; font-size: 13px; }
.folio-import-modal .fi-details summary { cursor: pointer; color: var(--muted); }
.folio-import-modal .fi-details code {
  background: var(--surface-2, #f0ece4); padding: 1px 5px; border-radius: 4px;
  font-size: 12px;
}
.folio-import-modal .fi-counts {
  display: flex; justify-content: space-between; gap: 10px;
  margin-bottom: 14px; font-size: 13px;
}
.folio-import-modal .fi-mapper {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px 18px; margin-bottom: 18px;
}
.folio-import-modal .fi-field { display: flex; flex-direction: column; gap: 4px; }
.folio-import-modal .fi-field label { font-size: 12px; color: var(--muted, #555); }
.folio-import-modal .fi-field select {
  padding: 7px 9px; border: 1px solid var(--border, #d6d1c5);
  border-radius: 7px; background: var(--surface, #fcfaf7); font-size: 13px;
}
.folio-import-modal .fi-req { color: #c44; }
.folio-import-modal .fi-preview h3 { margin: 8px 0; font-size: 13px; font-weight: 600; color: var(--muted); }
.folio-import-modal .fi-preview-table {
  border: 1px solid var(--border, #e6e2db); border-radius: 8px;
  overflow: auto; max-height: 220px;
}
.folio-import-modal .fi-preview-table table {
  width: 100%; border-collapse: collapse; font-size: 12px;
}
.folio-import-modal .fi-preview-table th,
.folio-import-modal .fi-preview-table td {
  padding: 6px 9px; border-bottom: 1px solid var(--border, #efeae1);
  text-align: left; white-space: nowrap;
}
.folio-import-modal .fi-preview-table th {
  background: var(--surface-2, #faf8f4); position: sticky; top: 0;
  font-weight: 600; color: var(--muted);
}
.folio-import-modal .fi-checkbox {
  display: flex; align-items: center; gap: 8px;
  margin-top: 14px; font-size: 13px; cursor: pointer;
}
.folio-import-modal .fi-bar {
  height: 8px; background: var(--surface-2, #efeae1); border-radius: 99px; overflow: hidden;
  margin-top: 14px;
}
.folio-import-modal .fi-bar-fill {
  height: 100%; width: 0%; background: var(--accent, #933994);
  transition: width .2s;
}
.folio-import-modal .fi-summary {
  list-style: none; padding: 0; margin: 12px 0; line-height: 1.9;
}
.folio-import-modal .fi-summary li.fi-err { color: #c44; }

/* ============================================================
   Unified Empty State (Catalog empty, Public Site off, etc.)
   ============================================================ */
.app-empty-state {
  width: 100%;
  margin: 32px 0 0;
  padding: 80px 32px;
  background: var(--surface);
  border: 1px solid var(--border-soft);
  border-radius: var(--radius-lg);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  box-sizing: border-box;
}
.app-empty-state .aes-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--ink-soft);
  margin-bottom: 18px;
  opacity: 0.7;
}
.app-empty-state .aes-icon svg { width: 56px; height: 56px; }
.app-empty-state .aes-title {
  font-family: var(--font-display);
  font-size: 24px;
  font-weight: 600;
  color: var(--ink);
  margin: 0 0 10px;
  line-height: 1.15;
  letter-spacing: -0.005em;
}
.app-empty-state .aes-body {
  font-family: var(--font-ui);
  font-size: 14px;
  line-height: 1.55;
  color: var(--ink-soft);
  margin: 0 0 24px;
  max-width: 520px;
}
.app-empty-state .aes-actions {
  display: flex;
  gap: 12px;
  justify-content: center;
  flex-wrap: wrap;
}
/* Footnote helper lines below the primary CTA in empty states.
   Used in the Public Site "not live" view to point new users to setup
   and to Joanna's example site. Subtle so the primary button stays loud. */
.app-empty-state .aes-footnote {
  font-family: var(--font-ui);
  font-size: 13px;
  line-height: 1.5;
  color: var(--ink-mute);
  margin: 18px 0 0;
  max-width: 520px;
}
.app-empty-state .aes-footnote + .aes-footnote {
  margin-top: 8px;
}
.app-empty-state .aes-link {
  color: var(--accent, #2F5D50);
  text-decoration: underline;
  text-underline-offset: 2px;
  font-weight: 500;
}
.app-empty-state .aes-link:hover {
  text-decoration: none;
}
.app-empty-state .aes-alt {
  margin: 28px 0 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
}
.app-empty-state .aes-alt-label {
  margin: 0;
  font-size: 13px;
  color: var(--ink-mute);
}

/* Legacy alias — keep so any stragglers still render */
.fi-empty-card { /* deprecated, use .app-empty-state */ }

/* ============================================================
   Unified Media Uploader — used across Settings for every
   single-image picker (Artist Photo, Biography Photo, Footer
   Logo, Quote Image, CTA Banner Image, CTA Icon, etc.)
   ============================================================ */
.media-uploader {
  display: flex;
  gap: 18px;
  align-items: flex-start;
  flex-wrap: wrap;
}
.media-uploader .mu-preview {
  width: 140px;
  height: 175px;
  background: var(--surface);
  border: 1px solid var(--border-soft);
  border-radius: 8px;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  position: relative;
}
.media-uploader.mu-square .mu-preview { width: 140px; height: 140px; }
.media-uploader.mu-wide   .mu-preview { width: 240px; height: 135px; }
.media-uploader.mu-icon   .mu-preview { width: 88px;  height: 88px; }
.media-uploader .mu-preview img {
  width: 100%; height: 100%;
  object-fit: cover;
  display: block;
}
.media-uploader .mu-preview .mu-empty {
  font-family: var(--font-ui);
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-mute);
}
.media-uploader .mu-controls {
  flex: 1 1 220px;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.media-uploader .mu-actions {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
}
.media-uploader .mu-hint {
  margin: 0;
  font-size: 12px;
  line-height: 1.5;
  color: var(--ink-mute);
}

/* Import/Export action rows in Settings */
.data-action-row {
  display: flex; justify-content: space-between; align-items: center;
  gap: 16px; padding: 16px 18px; margin-bottom: 12px;
  border: 1px solid var(--border, #e6e2db); border-radius: 10px;
  background: var(--surface, #fcfaf7);
}
.data-action-row .data-action-text { flex: 1; min-width: 0; }
.data-action-row h4 { margin: 0 0 4px; font-size: 14px; font-weight: 600; }
.data-action-row p { margin: 0; font-size: 13px; }

/* Trash list (Settings → Trash tab) */
.trash-list {
  list-style: none; padding: 0; margin: 0;
  display: flex; flex-direction: column; gap: 10px;
}
.trash-row {
  display: grid;
  grid-template-columns: 64px 1fr auto;
  align-items: center; gap: 14px;
  padding: 12px 14px;
  border: 1px solid var(--border, #e6e2db);
  border-radius: 10px;
  background: var(--surface, #fcfaf7);
}
.trash-thumb {
  width: 64px; height: 64px;
  border-radius: 6px; overflow: hidden;
  background: var(--surface-2, #f0ece4);
  display: flex; align-items: center; justify-content: center;
}
.trash-thumb img {
  width: 100%; height: 100%; object-fit: cover;
}
.trash-thumb-blank { color: var(--muted, #999); font-size: 18px; }
.trash-title { font-weight: 600; font-size: 14px; margin-bottom: 2px; }
.trash-sub { font-size: 12px; }
.trash-actions { display: flex; gap: 8px; }
@media (max-width: 600px) {
  .trash-row { grid-template-columns: 56px 1fr; }
  .trash-actions { grid-column: 1 / -1; justify-content: flex-end; }
}

/* ============================================================
   Share Views — Modal + Link Rows
   ============================================================ */
.share-modal-backdrop {
  position: fixed; inset: 0;
  background: rgba(0,0,0,0.42);
  display: flex; align-items: flex-start; justify-content: center;
  padding: 80px 24px 24px;
  z-index: 9000;
  overflow-y: auto;
  animation: shareFadeIn 140ms ease;
}
@keyframes shareFadeIn { from { opacity: 0; } to { opacity: 1; } }
.share-modal {
  width: 100%;
  max-width: 560px;
  background: var(--surface-elev);
  border: 1px solid var(--border-soft);
  border-radius: 14px;
  box-shadow: 0 24px 64px rgba(0,0,0,0.18), 0 4px 12px rgba(0,0,0,0.08);
  overflow: hidden;
}
.share-modal-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: 16px;
  padding: 20px 22px 14px;
  border-bottom: 1px solid var(--border-soft);
}
.share-modal-body {
  padding: 18px 22px 22px;
  max-height: calc(100vh - 200px);
  overflow-y: auto;
}
.share-summary {
  background: var(--surface-soft, #f6f4ef);
  border: 1px solid var(--border-soft);
  border-radius: 8px;
  padding: 10px 12px;
  font-size: 13px;
}
.share-summary-row { display: flex; gap: 10px; padding: 3px 0; }
.share-summary-row .sk { width: 60px; color: var(--ink-soft); }
.share-summary-row .sv { color: var(--ink); }
.share-modal .view-toggle { margin-left: -6px; }
.share-default-note { font-size: 10px; padding-left: 4px; }
.share-toggle {
  display: inline-flex; align-items: center; gap: 8px;
  margin-top: 12px;
  font-size: 13px;
  color: var(--ink);
  cursor: pointer;
  user-select: none;
}
.share-toggle input { width: 16px; height: 16px; accent-color: var(--accent); }
.share-quota {
  margin: 0 0 12px;
  font-size: 12px;
  line-height: 1.5;
}
.share-quota.is-maxed { color: var(--ink); }
.share-modal-actions {
  margin-top: 10px;
  display: flex; justify-content: flex-end;
}
.share-divider {
  height: 1px; background: var(--border-soft); margin: 22px 0 14px;
}
.share-link-row {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 12px 0;
  border-bottom: 1px solid var(--border-soft);
}
.share-link-row:last-child { border-bottom: none; }
.share-link-row.is-revoked .slr-main { opacity: 0.55; }
.slr-main { min-width: 0; flex: 1; }
.slr-name {
  font-size: 14px; font-weight: 600;
  color: var(--ink);
  display: flex; align-items: center; gap: 8px;
}
.slr-badge {
  font-size: 10px; font-weight: 600; letter-spacing: 0.06em;
  text-transform: uppercase;
  background: var(--surface-soft, #f0eee9);
  color: var(--ink-soft);
  border-radius: 4px;
  padding: 2px 6px;
}
.slr-meta {
  font-size: 12px; color: var(--ink-soft);
  display: flex; gap: 6px;
  margin-top: 2px;
}
.slr-url {
  font-size: 12px;
  margin-top: 4px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.slr-url a { color: var(--ink-soft); text-decoration: none; }
.slr-url a:hover { color: var(--ink); text-decoration: underline; }
.slr-actions { display: flex; gap: 6px; flex-shrink: 0; }

/* ===== AI: inline label-row button + modal ===== */
.field-label-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin-bottom: 4px;
  flex-wrap: wrap;
}
.field-label-row label { margin: 0; }
@media (max-width: 480px) {
  .field-label-row { gap: 6px; }
  .field-label-row label { flex: 1 1 auto; min-width: 0; }
  .field-label-row .btn-ai { flex-shrink: 0; }
}

.btn-ai {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 26px;
  padding: 0 10px;
  border-radius: 999px;
  background: linear-gradient(135deg, #6E59F2 0%, #B05CF2 100%);
  color: #fcfaf7;
  font-size: 12px;
  font-weight: 600;
  border: 0;
  cursor: pointer;
  white-space: nowrap;
  transition: transform 120ms ease, box-shadow 120ms ease, opacity 120ms ease;
  box-shadow: 0 1px 2px rgba(110, 89, 242, 0.25);
}
.btn-ai:hover:not(:disabled) {
  transform: translateY(-1px);
  box-shadow: 0 3px 10px rgba(110, 89, 242, 0.35);
}
.btn-ai:disabled {
  opacity: 0.45;
  cursor: not-allowed;
  background: var(--ink-mute, #888);
  box-shadow: none;
}
.btn-ai svg { flex-shrink: 0; }

/* AI modal options */
.ai-options {
  display: grid;
  gap: 14px;
  margin-bottom: 16px;
}
.ai-opt-row {
  display: grid;
  grid-template-columns: 80px 1fr;
  align-items: center;
  gap: 12px;
}
.ai-opt-label {
  font-size: 12px;
  font-weight: 600;
  color: var(--ink-soft);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.ai-seg {
  display: inline-flex;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 2px;
}
.ai-seg-btn {
  border: 0;
  background: transparent;
  padding: 6px 14px;
  font-size: 13px;
  border-radius: 999px;
  cursor: pointer;
  color: var(--ink-soft);
  transition: background 120ms ease, color 120ms ease;
}
.ai-seg-btn.is-active {
  background: var(--ink);
  color: var(--surface-elev, #fcfaf7);
}
.ai-opt-checkbox {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 13px;
  color: var(--ink);
  cursor: pointer;
}
.ai-output {
  width: 100%;
  min-height: 140px;
  padding: 12px 14px;
  border-radius: var(--radius-md, 10px);
  border: 1px solid var(--border);
  background: var(--surface);
  font-size: 14px;
  line-height: 1.55;
  color: var(--ink);
  font-family: inherit;
  resize: vertical;
}
.ai-output:focus { outline: 2px solid #6E59F2; outline-offset: 1px; }
.ai-output[data-state="loading"] {
  background: linear-gradient(90deg, var(--surface) 0%, rgba(110, 89, 242, 0.06) 50%, var(--surface) 100%);
  background-size: 200% 100%;
  animation: ai-shimmer 1.4s ease-in-out infinite;
  color: var(--ink-soft);
}
@keyframes ai-shimmer {
  0% { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}
.ai-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding-top: 14px;
}
.ai-usage {
  font-size: 12px;
  color: var(--ink-soft);
}
.ai-actions { display: flex; gap: 12px; }
.ai-error {
  margin-top: 10px;
  padding: 10px 12px;
  border-radius: 8px;
  background: rgba(255, 38, 0, 0.08);
  border: 1px solid rgba(255, 38, 0, 0.25);
  color: #B82200;
  font-size: 13px;
}

/* ----- AI Description history strip ----- */
.ai-history {
  margin-top: 12px;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.ai-history-label {
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-soft);
  font-weight: 600;
}
.ai-history-pills {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}
.ai-history-pill {
  font-size: 11px;
  padding: 4px 10px;
  border-radius: 999px;
  border: 1px solid var(--line-soft, #e4e1da);
  background: #fcfaf7;
  color: var(--ink, #2a2622);
  cursor: pointer;
  white-space: nowrap;
  max-width: 220px;
  overflow: hidden;
  text-overflow: ellipsis;
  transition: background 120ms ease, border-color 120ms ease, color 120ms ease;
}
.ai-history-pill:hover {
  background: #f5f2ec;
  border-color: #cfcabf;
}
.ai-history-pill.is-active {
  /* Warm amber to echo the ✨ AI theme and stand apart from the green action buttons */
  background: #F4D06F;
  color: #4A3500;
  border-color: #D9B040;
  font-weight: 600;
}
.ai-history-pill.is-active:hover {
  background: #F0C75A;
  border-color: #C99E2E;
}

/* ----- Toggle switch (iOS-style) ----- */
.toggle-switch {
  appearance: none;
  -webkit-appearance: none;
  width: 42px;
  height: 24px;
  background: var(--border);
  border-radius: 999px;
  position: relative;
  cursor: pointer;
  transition: background 180ms ease;
  flex-shrink: 0;
  margin: 0;
}
.toggle-switch::after {
  content: "";
  position: absolute;
  top: 2px; left: 2px;
  width: 20px; height: 20px;
  background: #fcfaf7;
  border-radius: 50%;
  box-shadow: 0 1px 3px rgba(0,0,0,0.15);
  transition: transform 180ms ease;
}
.toggle-switch:checked { background: var(--accent); }
.toggle-switch:checked::after { transform: translateX(18px); }
.toggle-switch:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.toggle-label { font-size: 14px; color: var(--ink); }
.toggle-label strong { font-weight: 600; }

/* =====================================================================
   PUBLIC SITE — Artwork Modal
   Tuned to mirror joannaaplin.com exactly. Self-contained: all rules are
   scoped to .modal-card.is-public so they cannot affect admin modals.

   Reference design tokens (from audit of joannaaplin.com, 2026-06-15):
     - Font system: Nexa (geometric sans) + EB Garamond (serif)
     - Accent: #FF0000 primary link, #cc3366 hover
     - Modal: full-page white takeover, no dark backdrop
     - Title: Nexa Bold 20px, letter-spacing 3.5px, UPPERCASE
     - Subtitle: EB Garamond 15px, color #333
     - Layout: 45/45 columns, mobile = column-reverse (image top)
   ===================================================================== */

/* Nexa is a paid custom font on joannaaplin.com. We approximate with a
   geometric-sans stack (Futura/Avenir/Nunito Sans fallback chain). */

.modal-card.is-public {
  background: #fcfaf7;
  border: 0;
  border-radius: 0;
  box-shadow: none;
  max-width: none;
  width: 100vw;
  max-height: 100vh;
  height: 100vh;
  overflow-y: auto;
  color: #000000;
}
.modal-card.is-public .modal-body {
  padding: 0;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
}
.modal-card.is-public .modal-close {
  position: fixed;
  top: 30px; right: 30px;
  width: 36px; height: 36px;
  border: 0;
  padding: 0;
  background: transparent;
  color: #000000;
  line-height: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: opacity 0.3s ease-in-out;
  z-index: 2;
  cursor: pointer;
}
.modal-card.is-public .modal-close svg {
  width: 28px;
  height: 28px;
  display: block;
}
.modal-card.is-public .modal-close:hover { opacity: 0.55; }

/* Hide the backdrop entirely — the modal IS the page on Joanna's site */
.modal:has(.modal-card.is-public) .modal-backdrop {
  background: #fcfaf7;
  backdrop-filter: none;
}

.pmod-grid {
  /* Fixed-width columns: image column always has the same on-screen width,
     and the image inside scales to fill it (width 100%, height auto). This
     gives consistent visual weight whether the work is portrait, landscape,
     or square. The text column is a fixed width with description scroll. */
  display: flex;
  flex-direction: row;
  align-items: center;
  justify-content: center;
  gap: 64px;
  width: 100%;
  max-width: 1100px;
  padding: clamp(20px, 3vh, 40px) clamp(20px, 3vw, 40px);
  box-sizing: border-box;
  margin: 0 auto;
}
.pmod-meta {
  flex: 0 0 360px;
  width: 360px;
  max-width: 360px;
  padding-left: 0;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  text-align: left;
  animation: pmod-fade-in-up 1.2s ease both;
}
.pmod-image {
  flex: 0 1 600px;
  width: 600px;
  max-width: 600px;
  padding: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  animation: pmod-fade-in 1.2s ease 0.2s both;
  opacity: 0;
}
@keyframes pmod-fade-in {
  0% { opacity: 0; }
  100% { opacity: 1; }
}
@keyframes pmod-fade-in-up {
  0% { opacity: 0; transform: translateY(24px); }
  100% { opacity: 1; transform: translateY(0); }
}

/* =========================================================
   Public Site — Parallax CTA Banner
   Fixed-attachment background image with centered icon + CTA.
   Sits between Studio Shots and the footer. Mobile fallback to
   scroll attachment (iOS/Android Safari don't honor `fixed`).
   ========================================================= */
.public-frame .public-cta-banner {
  position: relative;
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  background-color: #000;
  background-repeat: no-repeat;
  background-attachment: fixed;
  overflow: hidden;
  isolation: isolate;
}
.public-frame .public-cta-banner .pcb-overlay {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 1;
}
.public-frame .public-cta-banner .pcb-cta {
  position: relative;
  z-index: 2;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 22px;
  padding: 32px 24px;
  text-align: center;
  text-decoration: none;
  max-width: 720px;
}
.public-frame .public-cta-banner a.pcb-cta { text-decoration: none; }
.public-frame .public-cta-banner .pcb-icon {
  width: 56px;
  height: 56px;
  object-fit: contain;
  display: block;
  transition: transform 0.35s ease, filter 0.35s ease, background-color 0.35s ease;
  will-change: transform;
}
/* Raster icons (PNG/JPG): scale + subtle brightness lift on hover.
   Hover only fires when the cursor is directly over the icon, not the
   surrounding text/link area. */
.public-frame .public-cta-banner img.pcb-icon:hover {
  transform: scale(1.18);
  filter: brightness(1.15);
}
/* SVG icons rendered as masked spans — fillable and color-shiftable */
.public-frame .public-cta-banner .pcb-icon-svg {
  display: inline-block;
  width: 56px;
  height: 56px;
  background-color: var(--pcb-icon-color, #fcfaf7);
  -webkit-mask-repeat: no-repeat;
          mask-repeat: no-repeat;
  -webkit-mask-position: center;
          mask-position: center;
  -webkit-mask-size: contain;
          mask-size: contain;
  transition: transform 0.35s ease, background-color 0.35s ease;
}
.public-frame .public-cta-banner .pcb-icon-svg:hover {
  transform: scale(1.18);
  background-color: var(--pcb-icon-hover, var(--pub-red)) !important;
}
.public-frame .public-cta-banner .pcb-text {
  font-family: var(--pub-nexa, "Nexa", "Helvetica Neue", Arial, sans-serif);
  font-size: 28px;
  font-weight: 700;
  letter-spacing: 3.5px;
  text-transform: uppercase;
  line-height: 1.2;
}
@media (max-width: 900px) {
  .public-frame .public-cta-banner {
    background-attachment: scroll;
    background-size: cover !important;
  }
  .public-frame .public-cta-banner .pcb-text { font-size: 22px; letter-spacing: 2.5px; }
  .public-frame .public-cta-banner .pcb-icon { width: 44px; height: 44px; }
  .public-frame .public-cta-banner .pcb-icon-svg { width: 44px; height: 44px; }
}

/* =========================================================
   Public Site — scroll-triggered reveal animations
   Mirrors the modal entrance (1.2s ease). Initial state is
   hidden; .is-visible triggers the keyframe animation.
   ========================================================= */
.public-frame [data-reveal] { opacity: 0; will-change: opacity, transform; }
.public-frame [data-reveal="up"] { transform: translateY(24px); }
.public-frame [data-reveal].is-visible {
  animation: pmod-fade-in 1.2s ease both;
  opacity: 1;
}
.public-frame [data-reveal="up"].is-visible {
  animation: pmod-fade-in-up 1.2s ease both;
  opacity: 1;
  transform: translateY(0);
}
@media (prefers-reduced-motion: reduce) {
  .public-frame [data-reveal] { opacity: 1 !important; transform: none !important; animation: none !important; }
}

/* TITLE: Nexa Bold 20px, letter-spacing 3.5px, uppercase, color #000 */
.pmod-title {
  font-family: var(--pub-nexa);
  font-size: 20px;
  font-weight: 700;
  letter-spacing: 3.5px;
  text-transform: uppercase;
  color: #000000;
  margin: 0 0 24px 0;
  line-height: 1;
}

/* Condensed one-line spec (phones only — see the 720px block). */
.pmod-specline { display: none; }
.pmod-specline .pmod-sep { color: #bbbbbb; padding: 0 4px; }

/* SUBTITLE (medium, dimensions, year): EB Garamond 16px, color #000, line-height 1.5 */
.pmod-medium,
.pmod-dims,
.pmod-year {
  font-family: var(--pub-garamond);
  font-size: 16px;
  font-weight: 400;
  color: #000000;
  line-height: 1.5;
  margin: 0;
}

/* PRICE / STATUS: Nexa Bold 14px, letter-spacing 1.5px */
.pmod-price-block { margin-top: 22px; }
.pmod-price,
.pmod-status {
  font-family: var(--pub-nexa);
  font-size: 14px;
  font-weight: 700;
  letter-spacing: 1.5px;
  color: #000000;
}
.pmod-status { text-transform: uppercase; }

/* INQUIRY block */
.pmod-inquiry { margin-top: 26px; }
.pmod-inquiry-line {
  font-family: "EB Garamond", Georgia, serif;
  font-size: 16px;
  color: #000000;
  margin-bottom: 6px;
  line-height: 1.5;
}
/* Gallery link inside the inquiry line: same family/size as surrounding text,
   no underline, rose link color, deeper rose on hover. */
.pmod-inquiry-gallery {
  font-family: "EB Garamond", Georgia, serif;
  font-size: 16px;
  line-height: 1.5;
  color: #cc3366;
  text-decoration: none;
  transition: color 0.3s ease-in-out;
}
.pmod-inquiry-gallery:hover { color: #a32a52; }

/* SOCIAL ICONS: 22px, black default, #cc3366 hover, 10px right margin */
.pmod-share {
  display: flex;
  gap: 10px;
  margin-top: 30px;
}
.pmod-share a {
  color: #000000;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition: color 0.3s ease-in-out;
}
.pmod-share a:hover { color: #cc3366; }
.pmod-share svg { width: 22px; height: 22px; }

/* DESCRIPTION (optional, only if present): scrolls inside itself with a
   discrete scrollbar so long copy doesn't push title/meta off balance. */
.pmod-description {
  margin-top: 30px;
  padding-top: 20px;
  border-top: 1px solid #e5e5e5;
  font-family: "EB Garamond", Georgia, serif;
  font-size: 15px;
  line-height: 1.7;
  color: #333333;
  white-space: pre-line;
  width: 100%;
  max-height: 42vh;
  overflow-y: auto;
  padding-right: 12px;
  scrollbar-width: thin;
  scrollbar-color: rgba(0, 0, 0, 0.18) transparent;
}
.pmod-description::-webkit-scrollbar {
  width: 6px;
}
.pmod-description::-webkit-scrollbar-track {
  background: transparent;
}
.pmod-description::-webkit-scrollbar-thumb {
  background: rgba(0, 0, 0, 0.18);
  border-radius: 3px;
}
.pmod-description::-webkit-scrollbar-thumb:hover {
  background: rgba(0, 0, 0, 0.32);
}

/* IMAGE: fills the column width, height adapts to natural aspect.
   max-height ensures portrait works don't push the modal off-screen. */
.pmod-image img {
  width: 100%;
  max-width: 100%;
  height: auto;
  max-height: 88vh;
  margin: 0;
  padding: 0;
  object-fit: contain;
  display: block;
}
.pmod-image-placeholder {
  width: 100%;
  aspect-ratio: 4 / 5;
  background: #f5f5f5;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: "EB Garamond", Georgia, serif;
  font-size: 22px;
  color: #999999;
  padding: 24px;
  text-align: center;
}

/* MOBILE: column-reverse (image top, meta below), 90% widths */
@media (max-width: 767px) {
  .pmod-grid {
    flex-direction: column-reverse;
    padding: 80px 5%;
    gap: 32px;
  }
  .pmod-meta,
  .pmod-image {
    flex: 0 0 90%;
    max-width: 90%;
    padding-left: 5px;
  }
  .modal-card.is-public .modal-close {
    top: 20px; right: 20px;
  }
}

/* =========================================================
   Studio Shots — Settings manager (Public Site tab)
   ========================================================= */
.studio-shots-manager {
  margin-top: 4px;
}
.sshots-grid {
  display: grid;
  /* Cap at 5 columns so even rows are clean with 10 uploads */
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: 12px;
  margin-bottom: 10px;
  max-width: 900px;
}
@media (max-width: 900px) {
  .sshots-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}
@media (max-width: 640px) {
  .sshots-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
.sshot-tile {
  position: relative;
  aspect-ratio: 3 / 4;
  border-radius: 8px;
  overflow: hidden;
  background: var(--bg-soft, #f4f4f5);
  border: 1px solid var(--border-soft, #e5e7eb);
  cursor: grab;
  transition: transform 0.15s ease, box-shadow 0.15s ease, opacity 0.15s ease;
}
.sshot-tile:hover { box-shadow: 0 4px 14px rgba(0,0,0,0.08); }
.sshot-tile.is-dragging { opacity: 0.4; }
.sshot-tile.is-drop { outline: 2px dashed #2563eb; outline-offset: -3px; }
.sshot-tile .sshot-thumb { display:block; width:100%; height:100%; }
.sshot-tile .sshot-thumb img {
  width: 100%; height: 100%;
  object-fit: cover;
  display: block;
}
.sshot-tile .sshot-del {
  position: absolute; top: 6px; right: 6px;
  width: 24px; height: 24px;
  border-radius: 999px;
  background: rgba(0,0,0,0.72);
  color: #fcfaf7;
  border: 0;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  opacity: 0;
  transition: opacity 0.15s ease, background 0.15s ease;
}
.sshot-tile:hover .sshot-del { opacity: 1; }
.sshot-tile .sshot-del:hover { background: #dc2626; }
.sshot-add {
  aspect-ratio: 3 / 4;
  border-radius: 8px;
  border: 2px dashed var(--border-soft, #d1d5db);
  background: transparent;
  cursor: pointer;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 6px;
  color: #6b7280;
  font-family: "General Sans", "Inter", system-ui, sans-serif;
  font-size: 12px;
  transition: border-color 0.15s ease, color 0.15s ease, background 0.15s ease;
}
.sshot-add:hover { border-color: #2563eb; color: #2563eb; background: rgba(37, 99, 235, 0.04); }
.sshot-add-plus { font-size: 28px; line-height: 1; font-weight: 300; }
.sshots-count { font-size: 12px; margin: 0; }

/* =========================================================
   Universal Media Tile — used everywhere in Settings
   ========================================================= */
.media-tile {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-direction: column;
  gap: 8px;
  border: 2px dashed var(--border-soft, #d1d5db);
  border-radius: 12px;
  background: transparent;
  color: #6b7280;
  cursor: pointer;
  outline: none;
  transition: border-color 0.18s ease, background 0.18s ease, color 0.18s ease, box-shadow 0.18s ease;
  overflow: hidden;
}
.media-tile:focus-visible { box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.25); }
.media-tile.is-empty:hover,
.media-tile.is-empty:focus-visible,
.media-tile.is-dragover {
  border-color: #2563eb;
  background: rgba(37, 99, 235, 0.06);
  color: #2563eb;
}
.media-tile .mt-plus {
  font-size: 30px;
  line-height: 1;
  font-weight: 300;
}
.media-tile .mt-label {
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0.02em;
}
/* Filled state: solid neutral border, image fills tile */
.media-tile.is-filled {
  border: 1px solid var(--border, #e6e2db);
  background: var(--surface, #F8F5EE);
  cursor: pointer;
}
.media-tile.is-filled:hover { border-color: #2563eb; }
.media-tile img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
/* Variants */
.media-tile.mt-photo { width: 140px; height: 175px; }       /* portrait 4:5 */
.media-tile.mt-wide  { width: 240px; height: 135px; }       /* landscape 16:9 */
.media-tile.mt-icon  { width: 88px;  height: 88px;  }       /* square */
.media-tile.mt-logo  { width: 360px; height: 200px;         /* logo on dark-friendly bg, matches hero size */
  background: #0f1623;
}
.media-tile.mt-logo.is-empty {
  background: transparent;
}
.media-tile.mt-logo img {
  object-fit: contain;
  padding: 10px;
}
.media-tile.mt-hero  { width: 360px; height: 200px; }       /* hero picker */
.media-tile.mt-banner { width: 360px; height: 180px; }      /* parallax banner */
/* Remove (×) button — top-right corner of filled tile */
.media-tile .mt-remove {
  position: absolute;
  top: 6px; right: 6px;
  width: 26px; height: 26px;
  display: flex; align-items: center; justify-content: center;
  border: 0; border-radius: 50%;
  background: rgba(0, 0, 0, 0.55);
  color: #fcfaf7;
  cursor: pointer;
  opacity: 0;
  transition: opacity 0.15s ease, background 0.15s ease;
}
.media-tile.is-filled:hover .mt-remove,
.media-tile.is-filled:focus-within .mt-remove { opacity: 1; }
.media-tile .mt-remove:hover { background: #dc2626; }
/* Adjust position button — bottom-right pill */
.media-tile .mt-adjust {
  position: absolute;
  bottom: 8px; right: 8px;
  padding: 4px 10px;
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.02em;
  border: 0;
  border-radius: 999px;
  background: rgba(0, 0, 0, 0.65);
  color: #fcfaf7;
  cursor: pointer;
  opacity: 0;
  transition: opacity 0.15s ease;
}
.media-tile.is-filled:hover .mt-adjust,
.media-tile.is-filled:focus-within .mt-adjust { opacity: 1; }
.media-tile .mt-adjust:hover { background: #2563eb; }

/* Alternative text pill — bottom-left so it never collides with "Adjust position". */
.media-tile .mt-alt {
  position: absolute;
  bottom: 8px; left: 8px;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 4px 10px;
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.02em;
  border: 0;
  border-radius: 999px;
  background: rgba(0, 0, 0, 0.65);
  color: #fcfaf7;
  cursor: pointer;
  opacity: 0;
  transition: opacity 0.15s ease, background 0.15s ease;
}
.media-tile.is-filled:hover .mt-alt,
.media-tile.is-filled:focus-within .mt-alt { opacity: 1; }
.media-tile .mt-alt:hover { background: #2563eb; }
.mt-alt-dot {
  width: 6px; height: 6px;
  border-radius: 999px;
  background: #22c55e;
  flex: 0 0 auto;
}
/* A tile that already has alternative text keeps the pill faintly visible. */
.media-tile.is-filled .mt-alt.has-alt { opacity: 0.85; }

/* Studio shots get the same pill. */
.sshot-tile .sshot-alt {
  position: absolute;
  bottom: 6px; left: 6px;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 3px 9px;
  font-size: 11px;
  font-weight: 500;
  border: 0;
  border-radius: 999px;
  background: rgba(0, 0, 0, 0.72);
  color: #fcfaf7;
  cursor: pointer;
  opacity: 0;
  transition: opacity 0.15s ease, background 0.15s ease;
}
.sshot-tile:hover .sshot-alt,
.sshot-tile:focus-within .sshot-alt { opacity: 1; }
.sshot-tile .sshot-alt.has-alt { opacity: 0.85; }
.sshot-tile .sshot-alt:hover { background: #2563eb; }

/* Media-tile row — tile on the left, controls fill the rest on the right */
.media-tile-row {
  display: flex;
  align-items: flex-start;
  gap: 24px;
  flex-wrap: wrap;
}
.media-tile-row .mtr-controls {
  flex: 1 1 280px;
  min-width: 0;
  max-width: 720px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.media-tile-row .mtr-hint {
  margin: 0;
  font-size: 12px;
  color: var(--ink-mute);
  line-height: 1.5;
}

/* =========================================================
   Studio Shots — Public Site carousel
   ========================================================= */
.public-frame .public-studio-shots {
  width: 100%;
  margin: 0;
  padding: 0 0 12px 0;
  position: relative;
  overflow: hidden;
  background: #fcfaf7;
}
@media (min-width: 640px) {
  .public-frame .public-studio-shots { padding-bottom: 16px; }
}
@media (min-width: 1024px) {
  .public-frame .public-studio-shots { padding-bottom: 20px; }
}
.public-frame .public-studio-shots .pss-swiper {
  width: 100%;
  padding: 0;
}
.public-frame .pss-slide {
  aspect-ratio: 2 / 3;
  background: #f4f4f5;
  overflow: hidden;
}
.public-frame .pss-slide-inner {
  width: 100%;
  height: 100%;
}
.public-frame .pss-slide img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
/* Navigation arrows — outside the slide area, matching joannaaplin.com */
.public-frame .pss-nav {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  width: 44px;
  height: 44px;
  border-radius: 999px;
  background: transparent;
  border: 0;
  color: #fcfaf7;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  z-index: 5;
  transition: opacity 0.15s ease, transform 0.15s ease;
  opacity: 0.92;
  filter: drop-shadow(0 1px 3px rgba(0,0,0,0.35));
}
.public-frame .pss-nav:hover { opacity: 1; transform: translateY(-50%) scale(1.08); }
.public-frame .pss-prev { left: 16px; }
.public-frame .pss-next { right: 16px; }
.public-frame .pss-nav.swiper-button-disabled {
  opacity: 0.4;
  cursor: not-allowed;
}
@media (max-width: 640px) {
  .public-frame .pss-nav { width: 36px; height: 36px; }
  .public-frame .pss-prev { left: 8px; }
  .public-frame .pss-next { right: 8px; }
}

/* =========================================================
   Settings → Public Site → Social Links editor
   ========================================================= */
.social-links-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 14px 20px;
}
@media (max-width: 700px) {
  .social-links-grid { grid-template-columns: 1fr; }
}
.social-links-grid .field label {
  font-size: 13px;
  font-weight: 600;
  color: #1e293b;
  margin-bottom: 6px;
}
.social-links-grid .social-icon-inline {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
  color: #475569;
}
.social-links-grid .social-icon-inline svg { width: 18px; height: 18px; }
/* Social links input styling now handled by the shared .input class */

/* =========================================================
   Settings → Public Site → Footer Branding editor
   ========================================================= */
.footer-brand-editor {
  display: grid;
  grid-template-columns: minmax(220px, 320px) 1fr;
  gap: 24px;
  align-items: start;
}
@media (max-width: 760px) {
  .footer-brand-editor { grid-template-columns: 1fr; }
}
.fbe-logo-preview {
  background: #1f2329;
  border: 1px solid var(--border-soft);
  border-radius: 8px;
  height: 175px;
  width: 100%;
  max-width: 240px;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 16px;
  overflow: hidden;
}
.fbe-logo-preview.has-image { padding: 12px; }
.fbe-logo-preview img {
  max-width: 100%;
  max-height: 100%;
  width: auto;
  height: auto;
  object-fit: contain;
  filter: brightness(0) invert(1);
}
.fbe-logo-actions {
  display: flex;
  gap: 8px;
  margin-top: 10px;
  flex-wrap: wrap;
}
/* Footer-brand caption now uses shared .input class */

/* =========================================================
   Public Site — Image + Quote section (mirrors joannaaplin.com testimonial)
   Layout: ~40% quote block on a soft-gray background | ~60% photo, full-bleed.
   Typography per DevTools spec: EB Garamond 32px / 1.1em / #000.
   ========================================================= */
.public-frame .public-quote {
  display: grid;
  grid-template-columns: 1fr 1fr;
  align-items: stretch;
  background: #fcfaf7;
  scroll-margin-top: 80px;
  width: 100%;
  min-height: 50vh;
}
.public-frame .public-quote .pq-text {
  background: #f5f5f5;
  display: flex;
  align-items: center;
  padding: 96px 80px;
}
.public-frame .public-quote .pq-quote {
  margin: 0;
  font-family: "EB Garamond", Georgia, serif;
  font-size: 32px;
  font-weight: 400;
  line-height: 1.1;
  color: #000000;
  letter-spacing: 0;
  text-transform: none;
  font-style: normal;
}
.public-frame .public-quote .pq-image {
  position: relative;
  overflow: hidden;
  background-repeat: no-repeat;
  background-position: 50% 50%;
  background-size: 100%;
}
@media (max-width: 1100px) {
  .public-frame .public-quote .pq-text { padding: 80px 56px; }
  .public-frame .public-quote .pq-quote { font-size: 28px; }
}
@media (max-width: 900px) {
  .public-frame .public-quote {
    grid-template-columns: 1fr;
    min-height: 0;
  }
  .public-frame .public-quote .pq-text {
    padding: 72px 28px;
    order: 2;
  }
  /* background-size:100% left white space inside the image block, which read
     as a gap between the photo and the grey quote panel. Cover fills it. */
  /* The inline background-size (the zoom control) leaves white bands above and
     below the photo on narrow screens, which read as a gap before the grey
     quote panel. Force cover so the photo fills its block edge to edge. */
  .public-frame .public-quote .pq-image {
    order: 1;
    min-height: 46vh;
    background-size: cover !important;
  }
  .public-frame .public-quote .pq-quote { font-size: 26px; }
}

/* Quote Position Editor — preview stage mirrors the live 50/50 layout */
.qpe-stage {
  width: 100%;
  background: #fcfaf7;
  border-radius: 6px;
  overflow: hidden;
  border: 1px solid var(--border-soft);
  margin-bottom: 18px;
}
.qpe-preview {
  display: grid;
  grid-template-columns: 1fr 1fr;
  align-items: stretch;
}
.qpe-text-panel {
  background: #f5f5f5;
  display: flex;
  align-items: center;
  padding: 32px 28px;
  min-height: 280px;
}
.qpe-quote {
  margin: 0;
  font-family: "EB Garamond", Georgia, serif;
  font-size: 22px;
  line-height: 1.15;
  color: #000;
  font-weight: 400;
}
.qpe-image {
  background-repeat: no-repeat;
  background-position: 50% 50%;
  background-size: 100%;
  cursor: grab;
  touch-action: none;
  user-select: none;
  min-height: 280px;
  aspect-ratio: 4 / 3;
}
.qpe-image.is-dragging { cursor: grabbing; }
@media (max-width: 700px) {
  .qpe-preview { grid-template-columns: 1fr; }
  .qpe-text-panel { min-height: 160px; padding: 24px 20px; }
  .qpe-image { min-height: 220px; }
}

/* =========================================================
   Settings → Public Site → Image + Quote editor
   ========================================================= */
.quote-editor {
  display: grid;
  grid-template-columns: minmax(220px, 320px) 1fr;
  gap: 24px;
  align-items: start;
}
@media (max-width: 760px) {
  .quote-editor { grid-template-columns: 1fr; }
}
.qe-image-preview {
  background: var(--surface);
  border: 1px solid var(--border-soft);
  border-radius: 8px;
  width: 100%;
  max-width: 240px;
  height: 175px;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}
.qe-image-preview.has-image { background: #000; }
.qe-image-preview img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.qe-image-actions {
  display: flex;
  gap: 8px;
  margin-top: 10px;
  flex-wrap: wrap;
}
.qe-text textarea {
  width: 100%;
  padding: 10px 12px;
  border: 1px solid var(--border-soft);
  border-radius: 6px;
  font-size: 14px;
  font-family: "EB Garamond", Georgia, serif;
  line-height: 1.3;
  background: #fcfaf7;
  resize: vertical;
  min-height: 96px;
}
.qe-text textarea:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}

/* =========================================================
   Settings → Public Site → CTA Banner — Adjust Position editor
   ========================================================= */
.cpe-stage {
  position: relative;
  width: 100%;
  height: 360px;
  border-radius: 8px;
  overflow: hidden;
  background: #1a1a1a;
  margin-bottom: 18px;
  isolation: isolate;
}
.cpe-image {
  position: absolute;
  inset: 0;
  background-repeat: no-repeat;
  background-position: 50% 50%;
  background-size: 100%;
  cursor: grab;
  touch-action: none;
  user-select: none;
  z-index: 0;
}
.cpe-image.is-dragging { cursor: grabbing; }
.cpe-overlay {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 1;
}
.cpe-cta {
  position: absolute;
  inset: 0;
  z-index: 2;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 16px;
  pointer-events: none;
  padding: 24px;
  text-align: center;
}
.cpe-cta img {
  width: 48px;
  height: 48px;
  object-fit: contain;
  display: block;
}
.cpe-text {
  font-family: var(--pub-nexa, "Nexa", "Helvetica Neue", Arial, sans-serif);
  font-size: 22px;
  font-weight: 700;
  letter-spacing: 3px;
  text-transform: uppercase;
  line-height: 1.2;
}

/* =========================================================
   Settings → Public Site → CTA Banner editor
   ========================================================= */
.cta-banner-editor {
  display: flex;
  flex-direction: column;
  gap: 20px;
}
.cta-banner-row {
  display: grid;
  grid-template-columns: minmax(220px, 320px) 1fr;
  gap: 24px;
  align-items: start;
}
@media (max-width: 760px) {
  .cta-banner-row { grid-template-columns: 1fr; }
}
.cta-banner-preview {
  background: var(--surface);
  border: 1px solid var(--border-soft);
  border-radius: 8px;
  width: 100%;
  max-width: 240px;
  height: 175px;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}
.cta-banner-preview.has-image { background: #000; }
.cta-banner-preview img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.cta-banner-actions {
  display: flex;
  flex-direction: column;
  gap: 8px;
  align-items: flex-start;
}
.cta-banner-actions .btn { width: auto; }
.cta-banner-controls {
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.cta-banner-row-content {
  grid-template-columns: minmax(180px, 220px) 1fr;
}
@media (max-width: 760px) {
  .cta-banner-row-content { grid-template-columns: 1fr; }
}
.cta-banner-icon-block {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.cta-banner-icon-preview {
  width: 88px;
  height: 88px;
  background: var(--surface);
  border: 1px solid var(--border-soft);
  border-radius: 8px;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}
.cta-banner-icon-preview img {
  width: 70%;
  height: 70%;
  object-fit: contain;
  display: block;
}
.cta-banner-icon-actions {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
}
.cta-banner-text-block {
  display: flex;
  flex-direction: column;
  gap: 14px;
}
/* CTA banner text/link inputs now use shared .input class */

/* CTA Banner three-column row: icon | CTA Text | CTA Link | color stack */
.cta-tri-row {
  align-items: center;
}
.cta-tri-cols {
  flex: 1 1 0;
  min-width: 0;
  display: grid;
  /* CTA fields shrink (minmax 0 1fr), colour stack gets a fixed 180px lane */
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) 180px;
  gap: 24px;
  align-items: center;
}
.cta-tri-cols .field label {
  display: block;
  font-size: 12px;
  font-weight: 600;
  color: #475569;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  margin-bottom: 4px;
}
.cta-tri-cols .input { width: 100%; }
.cta-color-stack {
  display: flex;
  flex-direction: column;
  gap: 10px;
  align-self: end;
  padding-bottom: 2px;
}
.cta-color-row label {
  display: block;
  font-size: 11px;
  font-weight: 600;
  color: #475569;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  margin-bottom: 4px;
}
.cta-color-input {
  display: flex;
  align-items: center;
  gap: 8px;
}
.cta-color-input input[type="color"] {
  width: 42px;
  height: 32px;
  border: 1px solid var(--border-soft);
  border-radius: 6px;
  cursor: pointer;
  padding: 0;
  background: transparent;
}
.cta-color-input span { font-size: 12px; color: #64748b; font-variant-numeric: tabular-nums; }
@media (max-width: 900px) {
  .cta-tri-cols { grid-template-columns: 1fr; }
  .cta-color-stack { flex-direction: row; flex-wrap: wrap; }
}

/* =========================================================================
   Public Site tab — accordion sections
   ========================================================================= */
.ps-accordion {
  display: flex;
  flex-direction: column;
  gap: 0;
}
.ps-section {
  border-bottom: 1px solid var(--border-soft);
}
.ps-section:first-child {
  border-top: 1px solid var(--border-soft);
}
.ps-section-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  width: 100%;
  padding: 18px 4px;
  background: transparent;
  border: 0;
  cursor: pointer;
  text-align: left;
  font: inherit;
  color: var(--ink);
}
.ps-section-head:hover { background: rgba(0, 0, 0, 0.015); }
.ps-section-head:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
}
.ps-section-head-text {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}
.ps-section-num {
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--ink-mute, #6b7280);
}
.ps-section-title {
  font-family: var(--font-display);
  font-size: 18px;
  font-weight: 500;
  color: var(--ink);
  margin: 0;
  line-height: 1.2;
}
.ps-section-chev {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  color: var(--ink-mute, #6b7280);
  transition: transform 200ms ease;
}
.ps-section.is-open .ps-section-chev {
  transform: rotate(180deg);
}
.ps-section-body {
  display: none;
  padding: 6px 4px 24px;
}
.ps-section.is-open .ps-section-body { display: block; }
.ps-section-body > p.muted:first-child {
  margin-top: 0;
  margin-bottom: 14px;
}
.ps-section-body hr {
  display: none; /* legacy dividers no longer needed inside accordion sections */
}

/* Category-visibility list (Section 4) */
.cat-vis-list {
  display: flex;
  flex-direction: column;
  gap: 4px;
  max-width: 560px;
}
.cat-vis-row {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  gap: 16px;
  padding: 12px 14px;
  background: var(--surface-2, #f6f3ee);
  border-radius: 10px;
}
.cat-vis-name {
  font-size: 14px;
  color: var(--ink);
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.cat-vis-count {
  font-size: 12px;
  color: var(--ink-mute, #6b7280);
  margin-left: 8px;
  font-variant-numeric: tabular-nums;
}
.cat-vis-empty {
  padding: 16px;
  color: var(--ink-mute, #6b7280);
  font-size: 13px;
  background: var(--surface-2, #f6f3ee);
  border-radius: 10px;
}

/* ===== FolioCrop — full-screen 4-corner perspective crop modal ===== */
body.fc-open { overflow: hidden; }
.fc-overlay {
  position: fixed; inset: 0; z-index: 9999;
  background: rgba(0, 0, 0, 0.92);
  display: flex; flex-direction: column;
  animation: fcFadeIn 120ms ease-out;
}
@keyframes fcFadeIn { from { opacity: 0; } to { opacity: 1; } }
.fc-modal {
  background: #111;
  width: 100vw; height: 100vh;
  display: flex; flex-direction: column;
  overflow: hidden;
  color: #eee;
}
.fc-header {
  display: flex; align-items: center; justify-content: space-between;
  padding: 12px 20px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
  background: #0a0a0a;
  flex: 0 0 auto;
}
.fc-title { margin: 0; font-size: 15px; font-weight: 600; letter-spacing: 0.01em; color: #eee; }
.fc-header-actions { display: flex; align-items: center; gap: 10px; }
.fc-header-actions .fc-rotate {
  display: inline-flex; align-items: center; gap: 6px;
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid rgba(255, 255, 255, 0.15);
  color: #eee;
  padding: 6px 10px;
  border-radius: 6px;
  font-size: 13px;
  cursor: pointer;
  transition: background 120ms ease;
}
.fc-header-actions .fc-rotate:hover { background: rgba(255, 255, 255, 0.12); }
.fc-close {
  background: transparent; border: none; cursor: pointer;
  font-size: 28px; line-height: 1; padding: 0 4px;
  color: #bbb;
}
.fc-close:hover { color: #fcfaf7; }
.fc-body {
  flex: 1; min-height: 0;
  display: flex;
  padding: 0;
  position: relative;
}
.fc-stage {
  position: relative;
  background: #111;
  flex: 1; min-width: 0;
  overflow: hidden;
}
.fc-stage-inner {
  position: absolute; inset: 0;
  touch-action: none;
}
.fc-img {
  position: absolute;
  user-select: none; -webkit-user-drag: none;
  pointer-events: none;
}
.fc-overlay-svg {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  pointer-events: none;
}
.fc-poly {
  fill: rgba(255, 255, 255, 0.04);
  stroke: rgba(255, 255, 255, 0.95);
  stroke-width: 2;
  stroke-linejoin: round;
}
.fc-edge {
  stroke: rgba(255, 255, 255, 0.95);
  stroke-width: 2;
  pointer-events: none;
}
.fc-handle {
  fill: #fcfaf7;
  stroke: none;
  cursor: grab;
  pointer-events: auto;
  touch-action: none;
  transition: r 100ms ease, fill 100ms ease;
  filter: drop-shadow(0 1px 3px rgba(0, 0, 0, 0.6));
}
.fc-handle:hover { fill: #000; }
.fc-handle.is-active { fill: #000; cursor: grabbing; }
@media (pointer: coarse) {
  .fc-handle { r: 20; }
}
.fc-loading {
  position: absolute; inset: 0;
  display: flex; align-items: center; justify-content: center;
  background: rgba(0, 0, 0, 0.75);
  color: #fcfaf7; font-size: 14px; font-weight: 500;
  letter-spacing: 0.02em;
  z-index: 30;
}
.fc-loading[hidden] { display: none !important; }

/* Loupe (magnifier) — floats over the stage, opposite quadrant from active corner. */
.fc-loupe {
  position: absolute;
  width: 180px; height: 180px;
  border-radius: 50%;
  overflow: hidden;
  box-shadow: 0 4px 18px rgba(0, 0, 0, 0.6), 0 0 0 3px #fcfaf7, 0 0 0 5px rgba(0, 0, 0, 0.3);
  background: #111;
  pointer-events: none;
  z-index: 20;
}
.fc-loupe[hidden] { display: none; }
.fc-loupe-canvas { display: block; width: 100%; height: 100%; }
.fc-loupe-crosshair {
  position: absolute; left: 50%; top: 50%;
  width: 22px; height: 22px;
  margin: -11px 0 0 -11px;
  pointer-events: none;
}
.fc-loupe-crosshair::before,
.fc-loupe-crosshair::after {
  content: ""; position: absolute;
  background: #EF4244;
}
.fc-loupe-crosshair::before {
  left: 50%; top: 0; bottom: 0; width: 2px; margin-left: -1px;
}
.fc-loupe-crosshair::after {
  top: 50%; left: 0; right: 0; height: 2px; margin-top: -1px;
}

/* Preview pane — floats over the bottom-right of the stage. Pointer-events
   pass through so corners underneath it are still draggable. */
.fc-preview-pane {
  position: absolute;
  right: 20px; bottom: 20px;
  background: rgba(20, 20, 20, 0.85);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 10px;
  padding: 12px;
  display: flex; flex-direction: column;
  gap: 8px;
  max-width: 380px;
  z-index: 10;
  pointer-events: none;
}
.fc-preview-label {
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  font-weight: 600;
  color: #bbb;
}
.fc-preview-wrap {
  background: #1a1a1a;
  border-radius: 6px;
  padding: 6px;
  display: flex; align-items: center; justify-content: center;
  min-height: 100px;
}
.fc-preview-canvas {
  max-width: 100%; max-height: 340px;
  display: block;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.5);
}
.fc-hint {
  font-size: 13px;
  color: #aaa;
  margin: 0;
  flex: 1;
}
.fc-footer {
  display: flex; align-items: center; gap: 12px;
  padding: 14px 20px;
  border-top: 1px solid rgba(255, 255, 255, 0.08);
  background: #0a0a0a;
  flex: 0 0 auto;
}
.fc-footer .btn-outline {
  background: rgba(255, 255, 255, 0.06);
  border-color: rgba(255, 255, 255, 0.18);
  color: #eee;
}
.fc-footer .btn-outline:hover:not(:disabled) { background: rgba(255, 255, 255, 0.12); }
.fc-footer .btn-outline:disabled { opacity: 0.4; cursor: not-allowed; }
.fc-spacer { flex: 1; }

@media (max-width: 700px) {
  /* Hide the floating preview pane on mobile — it covers a crop corner handle
     no matter where we put it, and the user is looking at the source directly. */
  .fc-preview-pane { display: none !important; }
  .fc-hint { display: none; }
  .fc-loupe { width: 140px; height: 140px; }

  /* Footer buttons: prevent "Reset to Original" from wrapping across 3 lines
     while others sit on one line. Allow shrinking and wrap the whole row. */
  .fc-footer {
    flex-wrap: wrap !important;
    justify-content: center !important;
    padding: 10px 12px !important;
    padding-bottom: calc(10px + env(safe-area-inset-bottom, 0px)) !important;
    gap: 8px !important;
  }
  .fc-footer .btn {
    padding: 8px 12px !important;
    font-size: 12px !important;
    white-space: nowrap !important;
    flex: 0 0 auto !important;
  }
  .fc-spacer { display: none !important; }

  /* Hamburger must not overlap the crop modal header/title. */
  body.fc-open .mobile-hamburger { display: none !important; }

  /* Header title left-pad so nothing collides with close button. */
  .fc-header { padding-right: 44px !important; }
  .fc-title { font-size: 13px !important; padding-left: 4px !important; }

  /* Ensure stage has enough room and BR corner isn't hidden behind footer. */
  .fc-body { padding-bottom: 4px !important; }
}

/* Dimension gate — shown over the stage when L/W aren't yet entered. */
.fc-dim-gate {
  position: absolute; inset: 0;
  display: flex; align-items: center; justify-content: center;
  background: rgba(0, 0, 0, 0.78);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
  z-index: 40;
}
.fc-dim-gate[hidden] { display: none; }
.fc-dim-card {
  background: #161616;
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 12px;
  padding: 28px 28px 22px;
  width: min(420px, 92vw);
  text-align: center;
  box-shadow: 0 12px 40px rgba(0, 0, 0, 0.6);
}
.fc-dim-title { margin: 0 0 8px; font-size: 18px; font-weight: 600; color: #fcfaf7; letter-spacing: 0.01em; }
.fc-dim-sub { margin: 0 0 18px; font-size: 13px; color: #bbb; line-height: 1.45; }
.fc-dim-row {
  display: flex; align-items: flex-end; justify-content: center; gap: 10px;
  margin-bottom: 16px;
}
.fc-dim-field { display: flex; flex-direction: column; gap: 4px; flex: 1; max-width: 140px; }
.fc-dim-field span {
  font-size: 11px; color: #888; text-transform: uppercase;
  letter-spacing: 0.08em; font-weight: 600; text-align: left;
}
.fc-dim-input {
  background: #0a0a0a; color: #fcfaf7;
  border: 1px solid rgba(255, 255, 255, 0.18);
  border-radius: 6px; padding: 10px 12px;
  font-size: 16px; font-weight: 500;
  width: 100%; box-sizing: border-box;
  -moz-appearance: textfield;
}
.fc-dim-input::-webkit-outer-spin-button,
.fc-dim-input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.fc-dim-input:focus { outline: none; border-color: rgba(255, 255, 255, 0.45); }
.fc-dim-x { font-size: 18px; color: #666; padding-bottom: 10px; }
.fc-dim-continue { display: block; margin: 0 auto; }
.fc-dim-continue:disabled { opacity: 0.35; cursor: not-allowed; }
.fc-dim-hint { margin: 14px 0 0; font-size: 11px; color: #777; }

/* =========================================================
   Public Site \u2014 Setup tab
   ========================================================= */
.ps-subtabs {
  display: inline-flex;
  gap: 4px;
  padding: 4px;
  background: var(--bg-2, #f1ece2);
  border-radius: 999px;
  margin-bottom: 18px;
}
.ps-subtab {
  appearance: none;
  background: transparent;
  border: 0;
  font: inherit;
  font-size: 13px;
  font-weight: 600;
  padding: 8px 16px;
  border-radius: 999px;
  color: var(--ink-soft);
  cursor: pointer;
  letter-spacing: 0.01em;
}
.ps-subtab:hover { color: var(--ink); }
[data-theme="dark"] .ps-subtabs { background: #343833; }
[data-theme="dark"] .ps-subtab.is-active { background: #F8F5EE; color: #2B2F2D; }
.ps-subtab.is-active {
  background: var(--ink, #1a1d1b);
  color: var(--bg, #F8F5EE);
}

.ps-subpanel { min-width: 0; }

/* Public Site — Setup tab
   Uses the same accordion as Design (.ps-accordion / .ps-section / psSec()).
   Content inside each section body is width-capped to match the design system. */
.ps-setup { max-width: 760px; }
.ps-locked { opacity: 0.7; }
.ps-setup-note { margin: 12px 0 0; font-size: 13px; }

/* Last published meta */
.ps-setup-meta {
  display: flex;
  gap: 10px;
  align-items: center;
  margin-top: 16px;
  font-size: 13px;
}
.ps-setup-meta-label {
  color: var(--ink-mute, #8a8d86);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-size: 11px;
  font-weight: 600;
}
.ps-setup-meta-value {
  color: var(--ink, #1a1d1b);
  font-variant-numeric: tabular-nums;
}

.ps-pill-soft {
  display: inline-block;
  font-size: 10px;
  letter-spacing: 0.08em;
  padding: 2px 8px;
  border-radius: 999px;
  background: rgba(0,0,0,0.06);
  color: var(--ink-soft, #4a504c);
  text-transform: uppercase;
  font-weight: 600;
}

/* Publish toggle (Live / Draft pill style) */
.ps-publish-toggle {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  cursor: pointer;
  user-select: none;
  white-space: nowrap;
}
/* Inline variant: toggle sits beneath the section description, left-aligned */
.ps-publish-toggle-inline { margin-top: 4px; }
.ps-publish-toggle input[type="checkbox"] {
  appearance: none;
  width: 44px;
  height: 26px;
  border-radius: 999px;
  background: #d0d4cf;
  position: relative;
  cursor: pointer;
  transition: background 0.18s ease;
  margin: 0;
}
.ps-publish-toggle input[type="checkbox"]::after {
  content: "";
  position: absolute;
  top: 3px;
  left: 3px;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: #fcfaf7;
  box-shadow: 0 1px 2px rgba(0,0,0,0.18);
  transition: transform 0.18s ease;
}
.ps-publish-toggle input[type="checkbox"]:checked {
  background: var(--accent, #933994);
}
.ps-publish-toggle input[type="checkbox"]:checked::after {
  transform: translateX(18px);
}
.ps-publish-toggle input[type="checkbox"]:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}
.ps-publish-pill {
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.04em;
  color: var(--ink, #1a1d1b);
  min-width: 44px;
  text-align: left;
}

/* Slug field */
.ps-field-label {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-soft, #4a504c);
  display: block;
  margin: 18px 0 6px;
}
.ps-slug-field { margin-top: 10px; }
.ps-slug-input-row {
  display: flex;
  align-items: stretch;
  gap: 8px;
  flex-wrap: wrap;
}
.ps-slug-prefix,
.ps-slug-suffix {
  display: inline-flex;
  align-items: center;
  padding: 0 12px;
  background: var(--bg-2, #f1ece2);
  border: 1px solid var(--border, #e6e1d4);
  border-radius: 10px;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 13px;
  color: var(--ink-soft, #4a504c);
  white-space: nowrap;
}
.ps-slug-input {
  flex: 1 1 200px;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace !important;
  font-size: 14px;
  letter-spacing: 0.005em;
}
.ps-slug-status {
  margin-top: 8px;
  min-height: 20px;
  font-size: 13px;
}
.ps-slug-msg-hint { color: var(--ink-mute, #8a8d86); }
.ps-slug-msg-checking { color: var(--ink-soft, #4a504c); font-style: italic; }
.ps-slug-msg-ok { color: #2f7a4f; }
.ps-slug-msg-ok strong { font-weight: 700; }
.ps-slug-msg-error { color: #b3261e; }

/* URL list — no top border; just spacing from the slug field above */
.ps-url-list {
  display: grid;
  gap: 10px;
  margin-top: 18px;
}

/* Single-URL display (replaces the old primary/alias two-row block) */
.ps-url-display {
  margin-top: 18px;
}
.ps-url-eyebrow-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 6px;
  flex-wrap: wrap;
}
.ps-url-routing-note {
  font-size: 11.5px;
  color: var(--ink-mute, #8a8d86);
  font-style: italic;
}
.ps-url-row {
  display: grid;
  grid-template-columns: 130px 1fr;
  gap: 14px;
  align-items: center;
  padding: 10px 12px;
  background: var(--bg-2, #f7f4ef);
  border-radius: 10px;
}
.ps-url-rowhead {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.ps-url-eyebrow {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink, #1a1d1b);
}
.ps-url-tag {
  font-size: 11px;
  color: var(--ink-mute, #8a8d86);
  letter-spacing: 0.03em;
}
.ps-url-value-row {
  display: flex;
  align-items: center;
  gap: 10px;
  justify-content: space-between;
  flex-wrap: wrap;
  min-width: 0;
}
.ps-url-value {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 13px;
  color: var(--ink, #1a1d1b);
  background: var(--field-bg);
  border: 1px solid var(--border, #e6e1d4);
  padding: 6px 10px;
  border-radius: 8px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  flex: 1 1 200px;
  min-width: 0;
}
.ps-url-actions { display: flex; gap: 6px; flex-shrink: 0; }
.ps-url-actions .btn-sm {
  padding: 6px 12px;
  font-size: 12px;
  min-height: 32px;
}

/* Slug confirmation modal */
.slug-confirm-url {
  background: var(--bg-2, #f7f4ef);
  border: 1px solid var(--border, #e6e1d4);
  border-radius: 10px;
  padding: 14px 16px;
  text-align: center;
}
.slug-confirm-url code {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 15px;
  color: var(--ink, #1a1d1b);
  font-weight: 400;
  word-break: break-all;
}
.slug-confirm-url code strong {
  font-weight: 700;
}

/* Domain row */
.ps-domain-input-row {
  display: flex;
  gap: 8px;
  margin-top: 14px;
  flex-wrap: wrap;
}
.ps-domain-input-row .input { flex: 1 1 240px; }

/* Custom domain (Public Site > Step 2) */
.ps-domain-locked {
  display: flex; align-items: center; justify-content: space-between;
  gap: 14px; flex-wrap: wrap;
  margin-top: 14px; padding: 14px 16px;
  border: 1px solid var(--border-soft); border-radius: 12px;
  background: var(--surface-2, transparent);
}
.ps-domain-locked-copy { display: flex; flex-direction: column; gap: 2px; font-size: 13px; }
.ps-domain-loading { margin-top: 14px; font-size: 13px; }
.ps-domain-head {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  margin-top: 16px; margin-bottom: 10px;
}
.ps-domain-name { font-size: 14px; font-weight: 600; }
.ps-domain-pill {
  font-size: 11px; letter-spacing: 0.04em; text-transform: uppercase;
  padding: 4px 10px; border-radius: 999px;
  border: 1px solid var(--border-soft); color: var(--ink-soft);
}
.ps-domain-pill[data-status="active"] { border-color: #2f6b4f; color: #2f6b4f; }
.ps-domain-pill[data-status="error"]  { border-color: #a33a2a; color: #a33a2a; }
.ps-dns-table {
  margin-top: 14px; border: 1px solid var(--border-soft); border-radius: 12px; overflow: hidden;
}
.ps-dns-row {
  display: grid; grid-template-columns: 90px 150px minmax(0, 1fr);
  gap: 12px; align-items: center;
  padding: 12px 14px; border-top: 1px solid var(--border-soft);
}
.ps-dns-row:first-child { border-top: 0; }
.ps-dns-cell { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.ps-dns-cell code { font-size: 12.5px; word-break: break-all; }
.ps-dns-cell-value { flex-direction: row; align-items: center; gap: 10px; flex-wrap: wrap; }
.ps-dns-cell-value .ps-dns-label { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }
.ps-dns-label {
  font-size: 10.5px; letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--ink-mute, #8a8d86);
}
.ps-dns-note { grid-column: 1 / -1; font-size: 12px; margin-top: 2px; }
.ps-domain-actions { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 14px; }
.ps-domain-msg { margin-top: 10px; font-size: 12.5px; color: var(--ink-soft); }
.ps-domain-msg.is-error { color: #a33a2a; }

@media (max-width: 640px) {
  .ps-dns-row { grid-template-columns: 1fr; gap: 8px; }
}

/* Mobile */
@media (max-width: 640px) {
  .ps-url-row { grid-template-columns: 1fr; }
}

/* ===== Training tab (Site Settings) ===== */
.training-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
  gap: 16px;
}
.training-card {
  display: flex;
  flex-direction: column;
  border: 1px solid var(--border);
  /* Square: the video thumbnail fills the top edge, and no video anywhere in
     Folio has rounded corners. */
  border-radius: 0;
  background: var(--bg);
  overflow: hidden;
  cursor: pointer;
  transition: transform 0.3s ease, border-color 0.3s ease;
  will-change: transform;
}
.training-card:hover {
  transform: scale(1.02);
  border-color: var(--ink);
}
.training-thumb {
  position: relative;
  width: 100%;
  aspect-ratio: 16 / 9;
  background: linear-gradient(135deg, #2a2a2a 0%, #111 100%);
  display: flex;
  align-items: center;
  justify-content: center;
}
/* Thumbnail: the video's own frame at the one-second mark, so each card shows
   real footage without us maintaining eight separate still images. Only the
   file header is fetched, not the whole video. */
.training-thumb-vid {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  pointer-events: none;
}
.training-thumb-scrim {
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(0,0,0,0.35) 0%, rgba(0,0,0,0.12) 45%, rgba(0,0,0,0.42) 100%);
  transition: background 0.3s ease;
  pointer-events: none;
}
.training-card:hover .training-thumb-scrim {
  background: linear-gradient(180deg, rgba(0,0,0,0.22) 0%, rgba(0,0,0,0.04) 45%, rgba(0,0,0,0.3) 100%);
}
.training-play-icon {
  position: relative;
  z-index: 1;
  width: 48px;
  height: 48px;
  border-radius: 999px;
  background: rgba(0, 0, 0, 0.42);
  backdrop-filter: blur(2px);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition: background 0.3s ease;
}
.training-card:hover .training-play-icon {
  background: rgba(0, 0, 0, 0.6);
}
.training-play-icon svg {
  width: 22px;
  height: 22px;
  margin-left: 3px;
  fill: #fcfaf7;
}
.training-step-num {
  position: absolute;
  z-index: 1;
  top: 10px;
  left: 12px;
  font-family: "Nexa Display", "Helvetica Neue", Arial, sans-serif;
  color: rgba(255, 255, 255, 0.5);
  font-size: 12px;
  letter-spacing: 0.06em;
}
.training-body {
  padding: 14px 16px;
}
.training-title {
  font-size: 14px;
  font-weight: 500;
  color: var(--ink);
  margin-bottom: 4px;
}
.training-desc {
  font-size: 12px;
  line-height: 1.5;
  margin-bottom: 6px;
}
.training-status {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--ink-mute);
}


/* =========================================================
   Mobile Fixes (v-mobile-20260717) — Folio + Share View + Public
   Consolidated mobile pass. Targets ≤820px (tablet+phone) and
   ≤560px (phone). Adds hamburger drawer, tightens hero sizes,
   fixes demo pill overlap, share list row layout, pill dot.
   ========================================================= */

/* ---------- Hamburger button (mobile only) ---------- */
/* v-17: no circle, no border, no background, no shadow — just clean lines. */
.mobile-hamburger {
  display: none;
  position: fixed;
  top: 6px;
  right: 8px;
  left: auto;
  z-index: 10001;
  width: 40px;
  height: 40px;
  background: transparent;
  border: 0;
  border-radius: 0;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  color: var(--ink, #111);
  box-shadow: none;
  padding: 0;
}
.mobile-hamburger:hover { background: transparent; }
.mobile-hamburger svg { width: 24px; height: 24px; display: block; }

/* Mobile backdrop for drawer */
.mobile-drawer-backdrop {
  display: block;
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.62);
  z-index: 9998;
  opacity: 0;
  pointer-events: none;
  transition: opacity 160ms ease;
}

/* ---------- iOS Safari: prevent auto-zoom on input focus ----------
   Any input/select/textarea with font-size < 16px triggers iOS Safari to zoom
   in. It also fails to reset the viewport on blur, leaving the site scaled up
   with broken padding. Forcing 16px on mobile prevents this entirely. */
@media (max-width: 820px) {
  input,
  select,
  textarea,
  .input,
  .select,
  .textarea {
    font-size: 16px !important;
  }
  /* Preserve the visual size of small tags/labels that happen to use input elements */
  input[type="checkbox"],
  input[type="radio"] {
    font-size: inherit !important;
  }
}

/* ---------- Artist app: mobile drawer ≤820px ---------- */
@media (max-width: 820px) {
  /* Off-canvas sidebar drawer */
  .shell, .shell.sidebar-collapsed {
    grid-template-columns: 1fr;
  }
  .sidebar {
    position: fixed;
    top: 0;
    left: 0;
    /* Use dvh so iOS Safari's dynamic bottom bar doesn't cut off content;
       fall back to 100vh for browsers without dvh. */
    height: 100vh;
    height: 100dvh;
    width: 208px;
    max-width: 72vw;
    flex-direction: column;
    flex-wrap: nowrap;
    padding: var(--space-4) var(--space-3);
    /* The fixed top bar hides while the drawer is open, so the drawer shows
       its own wordmark and needs no clearance. */
    padding-top: var(--space-4);
    /* Extra bottom padding for iOS home indicator + tab bar clearance. */
    padding-bottom: calc(var(--space-4) + env(safe-area-inset-bottom, 0px) + 60px);
    border-right: 0;
    border-bottom: 0;
    gap: var(--space-4);
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    z-index: 9999;
    transform: translateX(-100%);
    transition: transform 150ms ease;
    box-shadow: 0 0 20px rgba(0, 0, 0, 0);
  }
  .shell.sidebar-mobile-open .sidebar {
    transform: translateX(0);
    box-shadow: 4px 0 24px rgba(0, 0, 0, 0.18);
  }
  .shell.sidebar-mobile-open .mobile-drawer-backdrop {
    opacity: 1;
    pointer-events: auto;
  }

  /* Restore column nav & icon labels inside the drawer */
  .nav {
    flex-direction: column; flex-wrap: nowrap; gap: 0;
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    left: var(--space-3);
    right: var(--space-3);
    width: auto;
    margin: 0;
  }
  .nav-item { padding: 5px 10px; height: 35px; font-size: 15px; justify-content: flex-start; gap: 11px; }
  .sidebar .nav-item .nav-icon,
  .sidebar .btn-ghost > .nav-icon,
  .sidebar .btn-ghost > .theme-icon { width: 18px; height: 18px; flex: 0 0 18px; }
  .sidebar .nav-item .nav-label { flex: 0 1 auto; }
  .sidebar .nav-badge { margin-left: 2px; }
  .nav-icon-outline { display: inline-flex; }
  .nav-icon-solid { display: none; }
  .nav-item.is-active .nav-icon-outline,
  .sidebar .btn-ghost.is-active .nav-icon-outline { display: none; }
  .nav-item.is-active .nav-icon-solid,
  .sidebar .btn-ghost.is-active .nav-icon-solid { display: inline-flex; }
  .sidebar-foot { margin-top: auto; flex-direction: column; align-items: stretch; gap: 0; }
  .sidebar-foot > button { justify-content: flex-start; padding: 2px 10px; height: 28px; font-size: 15px; gap: 11px; }
  .sidebar .sidebar-foot .btn-ghost,
  .sidebar .sidebar-foot .nav-item { height: 28px; padding-top: 2px; padding-bottom: 2px; }
  .sidebar-head { display: flex; padding: 0; }
  .sidebar-head .brand {
    padding: 0 0 0 12px;
    justify-content: flex-start;
    margin: 0;
  }
  .sidebar-head .brand-name {
    min-height: 0;
    width: auto;
    justify-content: flex-start;
    margin: 0;
    padding: 0;
  }
  .sidebar-head .brand-wordmark {
    height: 42px;
    width: 85px;
    flex: 0 0 85px;
    align-self: flex-start;
    margin: 0 0 0 -2px;
  }
  .folio-auth-bar { transition: opacity 420ms ease 140ms !important; }
  body.sidebar-mobile-open .folio-auth-bar {
    opacity: 0 !important;
    pointer-events: none !important;
    /* Snap away fast on open; the slow fade above only governs the return. */
    transition: opacity 100ms ease 0ms !important;
  }
  .mobile-hamburger { transition: color 200ms ease; }
  body.sidebar-mobile-open .mobile-hamburger { color: #F8F5EE; }
  .sidebar-toggle,
  #sidebar-toggle { display: none !important; }

  /* Show hamburger */
  .mobile-hamburger { display: inline-flex; }

  /* Auth bar: mobile — fixed at top. Logo left, sign in/out right,
     hamburger overlays far right. Border-bottom removed for cleaner look. */
  .folio-auth-bar {
    position: fixed !important;
    top: 0 !important;
    left: 0 !important;
    right: 0 !important;
    padding: 8px 56px 8px 16px !important; /* right space for hamburger overlay */
    justify-content: flex-end;
    gap: 8px;
    background: var(--surface, #fcfaf7);
    border-bottom: 0 !important;
    min-height: 48px;
    font-size: 12px;
    z-index: 9997;
  }

  /* Mobile Folio wordmark on the far-left of the auth bar. Injected by JS. */
  .folio-auth-bar .mobile-brand {
    margin-right: auto; /* pushes email/buttons to the right */
    display: inline-flex;
    align-items: center;
    line-height: 1;
  }
  .folio-auth-bar .mobile-brand svg { height: 30px; width: auto; fill: var(--brand-ink, #2B2F2D); display: block; }

  .folio-auth-bar .email { font-size: 11px; }
  .folio-auth-bar .btn {
    padding: 5px 10px;
    font-size: 11px;
    white-space: nowrap;
    flex-shrink: 0;
  }

  /* Push main content down to clear the fixed auth bar (~48px) */
  .shell { padding-top: 48px; }
  .main { min-width: 0; }
  .view { padding: var(--space-4) var(--space-3); }
  .topbar { padding: var(--space-3); }
  /* Hamburger on the right, aligned inside the auth bar */
  .mobile-hamburger { top: 4px; right: 6px; left: auto; width: 40px; height: 40px; z-index: 10001; }
}

/* ---------- Share view (v.html) mobile ---------- */
@media (max-width: 720px) {
  /* Grid cards on mobile: drop fixed 4/5 aspect that creates dead space when
     images are landscape or near-square. Let image dictate its own height. */
  .grid { grid-row-gap: 40px !important; }
  .grid-card-thumb {
    aspect-ratio: auto !important;
    max-height: 70vh;
  }
  .grid-card-thumb .thumb { height: auto !important; aspect-ratio: auto !important; }
  .grid-card-thumb img,
  .grid-card-thumb .thumb img {
    height: auto !important;
    max-height: 70vh;
    object-fit: contain !important;
  }
  .share-shell { padding: 16px 12px 60px; }
  .share-head {
    margin-top: 12px;
    margin-bottom: 20px;
    gap: 12px;
    flex-direction: column;
    align-items: flex-start;
  }
  /* Shrink oversized share view page title (was hero-sized, wrapped 5 lines) */
  .share-head .section-title,
  .share-head h1,
  .share-head h2 {
    font-size: clamp(20px, 5.5vw, 26px) !important;
    line-height: 1.2 !important;
    letter-spacing: 0 !important;
    margin: 0 !important;
  }
  .share-head .section-kicker {
    font-size: 11px !important;
    letter-spacing: 0.08em;
  }
  .share-meta-row { font-size: 12px; gap: 8px; }
  .share-meta-row .chip { font-size: 11px; padding: 3px 8px; }
}

/* Share view LIST row on mobile — scoped to .share-modal so it doesn't
   collide with the main catalog list mobile layout. */
@media (max-width: 720px) {
  .share-modal .art-row {
    grid-template-columns: 56px 1fr auto !important;
    grid-template-areas:
      "thumb title price"
      "thumb vis vis" !important;
    row-gap: 6px !important;
  }
  .share-modal .art-row-thumb { grid-area: thumb !important; }
  .share-modal .art-row-title { grid-area: title !important; }
  .share-modal .art-row-price { grid-area: price !important; }
  .share-modal .art-list .art-row > div:nth-child(3),
  .share-modal .art-list .art-row > div:nth-child(4),
  .share-modal .art-list .art-row > div:nth-child(5),
  .share-modal .art-list .art-row > div:nth-child(6) {
    display: none !important;
  }
  .share-modal .art-list .art-row > div:nth-child(7) {
    grid-area: vis !important;
    justify-content: flex-start !important;
    text-align: left !important;
    display: flex !important;
    align-items: center !important;
    gap: 8px !important;
  }
  .share-modal .art-list .art-row > div:nth-child(8) {
    display: none !important;
  }
  .share-modal .art-row .chip.chip-inline {
    font-size: 10px;
    padding: 2px 8px;
    line-height: 1.4;
  }
}

/* ---------- Visibility pill: green dot INSIDE, not floating outside ---------- */
.chip.chip-inline .status-dot,
.chip.public .status-dot,
.chip.private .status-dot {
  display: inline-block;
  width: 8px;
  height: 8px;
  border-radius: 999px;
  margin-right: 6px;
  vertical-align: middle;
}
/* When status dot appears standalone next to a pill, ensure gap consistent */
.al-status-col .status-dot { margin-left: 8px; }

/* ---------- Public site (public.html + public-frame preview) mobile ---------- */
/* Hamburger button — hidden on desktop, revealed below 820px. */
.public-nav .pn-burger { display: none; }
@media (max-width: 820px) {
  /* Nav collapses to brand + hamburger; links drop into a stacked panel. */
  .public-nav {
    padding: 20px 20px;
    flex-wrap: nowrap;
    gap: 12px;
  }
  .public-nav .pn-brand {
    font-size: 15px;
    letter-spacing: 3px;
    word-spacing: 3px;
    flex: 1 1 auto;
    min-width: 0;
  }
  .public-nav .pn-burger {
    display: flex;
    flex: 0 0 auto;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 6px;
    width: 34px;
    height: 26px;
    padding: 0;
    border: 0;
    background: transparent;
    cursor: pointer;
  }
  .public-nav .pn-burger span {
    display: block;
    width: 30px;
    height: 2px;
    background: var(--pub-red, #FF0000);
    transition: transform 0.3s ease, opacity 0.2s ease;
  }
  .public-nav.pn-open .pn-burger span:nth-child(1) { transform: translateY(8px) rotate(45deg); }
  .public-nav.pn-open .pn-burger span:nth-child(2) { opacity: 0; }
  .public-nav.pn-open .pn-burger span:nth-child(3) { transform: translateY(-8px) rotate(-45deg); }
  .public-nav nav {
    display: none;
    position: absolute;
    left: 0;
    right: 0;
    top: 100%;
    flex-direction: column;
    align-items: center;
    gap: 0;
    padding: 22px 16px 34px;
    background: #fcfaf7;
    box-shadow: 0 10px 18px rgba(0, 0, 0, 0.10);
  }
  .public-nav.pn-open nav { display: flex; }
  /* Menu bar sits at the very top of the page, above the hero image (the
     source order puts it after the hero for desktop). The sentinel stays
     directly beneath it so the drop shadow still only appears on scroll. */
  .public-frame {
    display: flex;
    flex-direction: column;
  }
  .public-frame > .public-nav { order: -3; }
  .public-frame > .public-nav-sentinel { order: -2; }
  .public-frame > .public-hero { order: -1; }
  .public-nav nav a {
    font-size: 12px;
    font-weight: 700;
    letter-spacing: 2.5px;
    color: #444444;
    padding: 15px 0;
    width: 100%;
    text-align: center;
  }
  .public-nav nav a::after { display: none; }
}

@media (max-width: 560px) {
  /* Hero name letter-spacing was breaking words on narrow phones */
  .public-hero h1 {
    font-size: clamp(24px, 8vw, 40px) !important;
    padding: 0 12px;
  }
  .public-hero h1 .ph-letter {
    letter-spacing: 0.18em !important;
  }
  .public-hero h1 .ph-word-gap {
    width: 0.5em !important;
  }
  .public-hero .ph-sub {
    font-size: clamp(14px, 3.6vw, 18px) !important;
  }
  .public-hero .ph-inner { padding: 32px 12px; }
  /* On mobile the ph-image uses background-size:100% which shrinks with viewport width
     leaving a grey band under the hero. Cover on narrow screens fills the hero. */
  .public-hero .ph-image { background-size: cover !important; }
  .public-hero { min-height: calc(100vh - 120px); }
}

/* Fix public-site work modal on mobile — image clip + missing close */
@media (max-width: 720px) {
  .public-frame .pmod-grid,
  .pmod-grid {
    flex-direction: column-reverse !important;
    padding: 60px 16px 40px !important;
    gap: 24px !important;
    box-sizing: border-box !important;
  }
  .public-frame .pmod-meta,
  .public-frame .pmod-image,
  .pmod-meta,
  .pmod-image {
    flex: 0 0 auto !important;
    width: 100% !important;
    max-width: 100% !important;
    /* the 767px rule adds 5px left padding, which threw the artwork 5px off
       centre inside the popup */
    padding-left: 0 !important;
  }
  .public-frame .pmod-close,
  .pmod-close {
    top: 16px !important;
    right: 16px !important;
    z-index: 10 !important;
  }
  /* Constrain the artwork so there is generous, equal white space on both
     sides (matches joannaaplin.com) and room above for the close button. */
  .public-frame .pmod-image img,
  .pmod-image img {
    max-height: 52vh !important;
    width: auto !important;
    max-width: 80% !important;
    margin: 0 auto !important;
  }
  /* The centred flex body clipped the top padding when the popup content was
     taller than the screen, so the close "X" landed on top of the artwork.
     Top-align on phones and give the image real breathing room. */
  .modal-card.is-public .modal-body { align-items: flex-start !important; }
  .public-frame .pmod-grid,
  .pmod-grid {
    padding: 92px 20px 56px !important;
    /* Auto margins centre the popup vertically when the artwork is short or
       landscape (no more crowding the close button, no more dead space at the
       bottom), yet collapse to zero for tall works so the top stays reachable
       instead of being clipped above the scroll area. */
    margin: auto !important;
  }
  .modal-card.is-public .modal-close { top: 26px !important; right: 22px !important; }
  /* Centre every line of the artwork details, matching joannaaplin.com. */
  .public-frame .pmod-meta,
  .pmod-meta {
    align-items: center !important;
    text-align: center !important;
    padding-left: 0 !important;
  }
  .pmod-share { justify-content: center !important; }
  .pmod-inquiry-btn { text-align: center !important; }
  .pmod-description { text-align: center !important; }
  /* Collapse year / medium / dimensions onto one divided line and tighten the
     vertical rhythm so tall portrait works fit without a scrollbar. */
  .pmod-year,
  .pmod-medium,
  .pmod-dims { display: none !important; }
  .pmod-specline {
    display: block !important;
    font-family: var(--pub-garamond);
    font-size: 15px;
    line-height: 1.5;
    color: #000000;
    margin: 0;
  }
  .pmod-title { margin-bottom: 14px !important; font-size: 18px !important; }
  .pmod-price-block { margin-top: 14px !important; }
  .pmod-inquiry { margin-top: 16px !important; }
  .pmod-share { margin-top: 20px !important; }
  .pmod-description {
    margin-top: 20px !important;
    padding-top: 16px !important;
    /* one scroll context only — no nested scrollbar inside the popup */
    max-height: none !important;
    overflow: visible !important;
  }
}

/* Kill any stray grey empty band on the standalone public page mobile */
@media (max-width: 820px) {
  .pub-shell .public-frame > *:empty { display: none; }
}

/* ---------- Signed-out landing (P4) — hero shrink on mobile ---------- */
@media (max-width: 560px) {
  .landing-hero h1,
  .signed-out-hero h1,
  .home-hero h1,
  .hero-title-lg,
  .concept-h {
    font-size: clamp(22px, 6.5vw, 30px) !important;
    line-height: 1.15 !important;
    letter-spacing: -0.01em !important;
  }
  .landing-hero p,
  .signed-out-hero p,
  .home-hero p,
  .concept-sub {
    font-size: clamp(13px, 3.6vw, 15px) !important;
    line-height: 1.4 !important;
  }
  /* Stack concept-grid actions vertically, tighten stat sizes */
  .concept-stat .kpi-value { font-size: 26px !important; }
}

/* ---------- Message 2 fixes (2026-07-17 v-6) ---------- */

/* Date Created (type=month) input on iOS renders text centered by default.
   Left-align to match all other fields in the Work Details form. */
@media (max-width: 820px) {
  input[type="month"],
  input[type="date"],
  input[type="datetime-local"],
  input[type="time"] {
    text-align: left !important;
    -webkit-appearance: none;
    appearance: none;
    /* iOS collapses empty date/month inputs when -webkit-appearance is
       removed. Enforce the same min-height as other .input controls so an
       empty Date Purchased/Date Created field renders at proper height. */
    min-height: 44px !important;
    box-sizing: border-box !important;
  }
  /* Some iOS versions center the pseudo-value; align via padding + text-align */
  input[type="month"]::-webkit-date-and-time-value,
  input[type="date"]::-webkit-date-and-time-value {
    text-align: left !important;
  }
}

/* Filters/Sort popover: on mobile, break out of the anchored positioning
   entirely and pin to viewport so the panel can span full width without
   being constrained by the toolbar button's position. */
@media (max-width: 720px) {
  .popover {
    position: fixed !important;
    top: auto !important;
    bottom: auto !important;
    left: 12px !important;
    right: 12px !important;
    width: auto !important;
    min-width: 0 !important;
    max-width: calc(100vw - 24px) !important;
    /* JS will set --popover-y with the button's bottom edge; fallback below toolbar */
    top: var(--popover-y, 180px) !important;
    max-height: calc(100vh - var(--popover-y, 180px) - 80px) !important;
    overflow-y: auto !important;
    -webkit-overflow-scrolling: touch;
  }
  .popover-row { min-width: 0; }
  .popover-row .select,
  .popover .select {
    width: 100% !important;
    max-width: 100% !important;
    min-width: 0 !important;
  }
  .popover-label {
    white-space: normal !important;
    overflow: visible !important;
    text-overflow: clip !important;
  }
  .popover-item {
    white-space: nowrap !important;
  }
}

/* =========================================================
   Site Settings — Mobile (v-18)
   All settings tabs (Public, Pricing, Categories, Galleries, Data,
   Training, Trash) previously overflowed the viewport horizontally.
   Root causes:
     • .settings-tabs used flex-wrap:nowrap + no scroll
     • .settings-panel used overflow:hidden clipping content
     • .settings-panel-body had 24px padding on both sides
     • [data-pricing-tiers] used fixed 220px × 220px columns
     • .form-grid columns didn't collapse until 600px
     • .gallery-card-footer used desktop-only two-column layout
   ========================================================= */
@media (max-width: 720px) {
  /* Tabs — horizontally scrollable strip */
  .settings-tabs {
    padding: 0 !important;
    overflow-x: auto !important;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
  }
  .settings-tabs::-webkit-scrollbar { display: none; }
  .settings-tab {
    padding: 12px 14px 14px !important;
    font-size: 11px !important;
  }

  /* Panel container — stop clipping, tighten padding */
  .settings-panel {
    overflow: visible !important;
    border-radius: var(--radius-md) !important;
  }
  .settings-panel-body {
    padding: 16px !important;
    overflow-x: hidden !important;
  }
  .settings-panel #settings-form > .row {
    padding: 0 16px 16px !important;
    flex-wrap: wrap;
    gap: 8px !important;
  }

  /* Section headings inside settings body — shrink slightly for narrow viewports */
  .settings-panel-body .section-title {
    font-size: 20px !important;
    line-height: 1.2 !important;
  }

  /* Field width caps aren't needed on mobile — let inputs fill the panel */
  .settings-panel-body .field.full > .input,
  .settings-panel-body .field.full > .select,
  .settings-panel-body .field.full > .input-prefix,
  .settings-panel-body .field.full > .textarea,
  .settings-panel-body .field.full > input {
    max-width: 100% !important;
    width: 100% !important;
  }

  /* Pricing tiers — stack to single column on mobile */
  .settings-panel-body [data-pricing-tiers] {
    grid-template-columns: 1fr !important;
    column-gap: 0 !important;
    row-gap: 12px !important;
  }
  .settings-panel-body [data-pricing-tiers] .field .input-prefix {
    max-width: 100% !important;
  }

  /* .form-grid — collapse to one column below 720 too (was 600) */
  .form-grid {
    grid-template-columns: 1fr !important;
    gap: 12px !important;
  }

  /* Categories rows */
  .category-row {
    grid-template-columns: 1fr auto !important;
    gap: 8px !important;
  }

  /* Gallery cards — tighter footer, stack body form */
  .gallery-card { border-radius: var(--radius-md) !important; }
  .gallery-card-summary { padding: 12px 14px !important; }
  .gallery-card-body { padding: 14px !important; }
  .gallery-card-footer {
    padding: 12px 14px !important;
    flex-wrap: wrap;
    gap: 8px !important;
  }

  /* Public Site accordion sections — more horizontal breathing room on mobile
     so chevrons, toggles, and slider values don't crowd the panel border. */
  .ps-section-head {
    padding: 14px 12px !important;
  }
  .ps-section-title {
    font-size: 18px !important;
  }
  .ps-section-body {
    padding: 6px 12px 20px !important;
  }
  .ps-accordion { padding: 0 !important; }
  /* Give the whole Public Site panel body an extra pad on mobile so the
     Setup/Design pill and section content don't touch the container edge. */
  .settings-panel-body > .section-kicker,
  .settings-panel-body > h3.section-title,
  .settings-panel-body > .ps-subtabs {
    padding-left: 4px !important;
    padding-right: 4px !important;
  }

  /* Section head titles above the panel ("Site Settings") — tighter margins */
  #view-settings .section-head { padding: 0 !important; }

  /* Training grid — single column with room to breathe */
  .training-grid {
    grid-template-columns: 1fr !important;
    gap: 14px !important;
  }

  /* Trash list caps removed */
  .settings-panel-body #trash-list { max-width: 100% !important; }
  .settings-panel-body .data-action-row { max-width: 100% !important; }

  /* Design tab — media tiles at fixed 360px were forcing the panel body
     wider than the 390px viewport (jumped from 364 → 416 when a section
     opens). Scale them to fit while keeping the intrinsic aspect ratio. */
  .settings-panel-body .media-tile.mt-hero,
  .settings-panel-body .media-tile.mt-logo,
  .settings-panel-body .media-tile.mt-banner {
    width: 100% !important;
    max-width: 100% !important;
    height: auto !important;
    aspect-ratio: 9 / 5;
  }
  .settings-panel-body .media-tile.mt-banner {
    aspect-ratio: 2 / 1;
  }
  .settings-panel-body .media-tile-row {
    gap: 14px !important;
  }
  .settings-panel-body .media-tile-row .mtr-controls {
    flex: 1 1 100% !important;
  }
  /* Belt & braces: nothing inside the accordion may overflow the panel */
  .settings-panel-body .ps-section-body,
  .settings-panel-body .ps-section-body > *,
  .settings-panel-body .ps-accordion,
  .settings-panel-body .ps-section {
    max-width: 100% !important;
    min-width: 0 !important;
    box-sizing: border-box;
  }
}

/* ============================================================
   ADMIN PANEL (#view-admin)
   Every rule below is scoped to #view-admin and every class is
   prefixed .admin- so nothing can reach another route. (A past
   bug had unscoped share-view .art-row rules hijack catalog
   rows — this section must never repeat it.)

   Structure, spacing and colour all come from the existing
   tokens. The metric tiles reuse .kpi / .kpi-row, and buttons
   reuse .btn / .btn-primary so the app-wide hover motion
   (radius snaps to 0, scale 1.06, colours ease) is inherited
   rather than redefined.
   ============================================================ */
#view-admin {
  /* Granted-access accent — matches the customer-facing comp badge in Billing. */
  --admin-comp:      #933994;
  --admin-comp-soft: rgba(147, 57, 148, 0.12);
  /* Users table columns, shared by the header row and every data row. */
  /* Artist / Email carries two lines of real text and was clipping full email
     addresses, so it takes the width freed by dropping the Over Limit pill. */
  /* Artist / Email is capped rather than elastic: left to grow it swallowed
     every spare pixel and pushed Plan, Status and Works far to the right.
     Spare width now collects in Joined, at the end of the row. */
  --admin-cols: minmax(240px, 268px) 104px 84px 140px 136px 76px 124px 76px minmax(100px, 1fr);
}
[data-theme="dark"] #view-admin {
  --admin-comp:      #c9a8da;
  --admin-comp-soft: rgba(201, 168, 218, 0.16);
}

/* ----- Metric tiles ----- */
#view-admin .admin-tier-pills {
  display: flex; flex-wrap: wrap; gap: 6px;
  margin: 2px 0 2px;
}
#view-admin .admin-tier-pill {
  display: inline-flex; align-items: baseline; gap: 5px;
  padding: 4px 10px;
  border-radius: 999px;
  background: var(--accent-soft);
  color: var(--accent);
  font-size: var(--text-xs);
  letter-spacing: 0.02em;
  white-space: nowrap;
}
#view-admin .admin-tier-pill b { font-size: var(--text-base); font-weight: 600; }

/* ----- Filters + search ----- */
#view-admin .admin-list-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--space-4); flex-wrap: wrap;
  margin-bottom: var(--space-2);
}
#view-admin .admin-filters { display: flex; flex-wrap: wrap; gap: 6px; }
#view-admin .admin-filter-pill {
  padding: 5px 12px;
  border-radius: 999px;
  border: 1px solid var(--border);
  background: var(--bg);
  color: var(--ink-soft);
  font: inherit;
  font-size: var(--text-xs);
  letter-spacing: 0.02em;
  white-space: nowrap;
  cursor: pointer;
  transition: background var(--transition), border-color var(--transition), color var(--transition);
}
#view-admin .admin-filter-pill:hover { border-color: var(--ink); color: var(--ink); }
#view-admin .admin-filter-pill.is-active {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--accent-ink);
  font-weight: 600;
}
#view-admin .admin-search { min-width: 260px; }
#view-admin .admin-count { font-size: var(--text-xs); margin: 0 0 var(--space-3); }

/* ----- Users table ----- */
#view-admin .admin-table-scroll { overflow-x: auto; }
#view-admin .admin-table {
  min-width: 1180px;
  display: flex; flex-direction: column;
  border: 1px solid var(--border-soft);
  border-radius: var(--radius-md);
  background: var(--bg);
}
#view-admin .admin-table-head,
#view-admin .admin-row {
  display: grid;
  grid-template-columns: var(--admin-cols);
  gap: var(--space-3);
  align-items: center;
  padding: 10px var(--space-4);
}
#view-admin .admin-table-head {
  background: var(--surface-2);
  border-bottom: 1px solid var(--border-soft);
  border-top-left-radius: var(--radius-md);
  border-top-right-radius: var(--radius-md);
  position: sticky; top: 0; z-index: 5;
}
#view-admin .admin-th {
  display: inline-flex; align-items: center; gap: 4px;
  border: 0; background: transparent;
  padding: 2px 0;
  font: inherit;
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--ink-soft);
  text-align: left;
  cursor: pointer;
  transition: color var(--transition);
}
#view-admin .admin-th:hover { color: var(--ink); }
#view-admin .admin-th.is-sorted { color: var(--accent); font-weight: 600; }
#view-admin .admin-th-arrow { font-size: 8px; line-height: 1; }

#view-admin .admin-row {
  border: 0; border-bottom: 1px solid var(--border-soft);
  background: transparent;
  font: inherit; color: var(--ink); text-align: left;
  cursor: pointer;
  transition: background var(--transition);
}
#view-admin .admin-row:last-child { border-bottom: 0; }
#view-admin .admin-row:hover { background: var(--surface); }
#view-admin .admin-row > div {
  min-width: 0;
  font-size: var(--text-sm);
  color: var(--ink);
}
#view-admin .admin-row-title {
  font-family: var(--font-display);
  font-size: var(--text-md);
  font-weight: 600;
  line-height: 1.2;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
#view-admin .admin-row-sub {
  font-size: var(--text-xs);
  color: var(--ink-soft);
  margin-top: 2px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
#view-admin .admin-cell-plan,
#view-admin .admin-cell-status { display: flex; flex-wrap: wrap; gap: 4px; align-items: center; }
/* Credits and MRR in the Users list: bold like a figure, but starting under
   their heading so the eye tracks straight down the column. */
#view-admin .admin-cell-figure { font-weight: 600; }
#view-admin .admin-cell-num { text-align: right; font-weight: 600; }
#view-admin .admin-cell-comp { line-height: 1.3; }

/* ----- Badges ----- */
#view-admin .admin-badge {
  display: inline-block;
  padding: 2px 8px;
  border-radius: 999px;
  border: 1px solid transparent;
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.02em;
  white-space: nowrap;
}
#view-admin .admin-badge-plan.admin-plan-free {
  background: var(--surface-2); color: var(--ink-soft); border-color: var(--border);
}
#view-admin .admin-badge-plan.admin-plan-studio {
  background: var(--accent-soft); color: var(--accent);
}
#view-admin .admin-badge-plan.admin-plan-pro {
  background: var(--accent); color: var(--accent-ink); border-color: var(--accent);
}
#view-admin .admin-badge-plan.admin-plan-gallery {
  background: var(--ink); color: var(--ink-inverse); border-color: var(--ink);
}
#view-admin .admin-badge-comp {
  background: var(--admin-comp-soft);
  color: var(--admin-comp);
  font-weight: 600;
}
#view-admin .admin-badge-comp.is-expiring {
  background: color-mix(in oklab, var(--amber) 16%, transparent);
  color: var(--amber);
}
#view-admin .admin-badge-warn {
  background: color-mix(in oklab, var(--rose) 14%, transparent);
  color: var(--rose);
  font-weight: 600;
}
#view-admin .admin-status { font-size: var(--text-xs); color: var(--ink-soft); }

/* ----- Usage: "12 / 50" plus a thin bar (amber at 80%, red at 100%) ----- */
#view-admin .admin-usage { min-width: 0; }
/* The usage bar fills its cell, so without this breathing room it runs
   right up to the next column's text and reads as crowding. */
#view-admin .admin-row > div > .admin-usage { padding-right: var(--space-4); }
#view-admin .admin-usage-text {
  font-size: var(--text-sm);
  color: var(--ink);
  white-space: nowrap;
}
#view-admin .admin-usage-text.is-near { color: var(--amber); }
#view-admin .admin-usage-text.is-over { color: var(--rose); font-weight: 600; }
#view-admin .admin-usage-bar {
  position: relative;
  height: 3px;
  margin-top: 5px;
  border-radius: 999px;
  background: var(--surface-3);
  overflow: hidden;
}
#view-admin .admin-usage-bar > span {
  position: absolute; inset: 0 auto 0 0;
  background: var(--accent);
  border-radius: 999px;
}
#view-admin .admin-usage-bar.is-near > span { background: var(--amber); }
#view-admin .admin-usage-bar.is-over > span { background: var(--rose); }
#view-admin .admin-usage-bar.is-unlimited { opacity: 0.4; }

/* ----- Messages ----- */
#view-admin .admin-empty {
  padding: var(--space-6) var(--space-4);
  text-align: center;
  color: var(--ink-mute);
  font-size: var(--text-sm);
}
#view-admin .admin-alert {
  padding: 10px 14px;
  margin-bottom: var(--space-4);
  border-radius: var(--radius-md);
  border: 1px solid color-mix(in oklab, var(--rose) 40%, var(--border));
  background: color-mix(in oklab, var(--rose) 8%, transparent);
  color: var(--rose);
  font-size: var(--text-sm);
}
#view-admin .admin-error {
  margin: 0 0 var(--space-3);
  color: var(--rose);
  font-size: var(--text-sm);
}

/* ----- User detail: single column, half width like Site Settings ----- */
#view-admin .admin-back {
  border: 0; background: transparent;
  padding: 0; margin-bottom: var(--space-4);
  font: inherit;
  font-size: var(--text-sm);
  color: var(--ink-soft);
  cursor: pointer;
  transition: color var(--transition);
}
#view-admin .admin-back:hover { color: var(--ink); }
/* Two columns on a wide screen: the account as it stands on the left, the
   controls and history on the right. On one column this stacked to well over
   two screens of scrolling with the whole right half of the page empty. */
#view-admin .admin-detail {
  width: 100%;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  align-items: start;
  gap: var(--space-4);
}
#view-admin .admin-detail-col {
  min-width: 0;
  display: flex; flex-direction: column;
  gap: var(--space-4);
}
#view-admin .admin-section { padding: var(--space-5); }
#view-admin .admin-detail-name {
  font-family: var(--font-display);
  font-size: 28px;
  font-weight: 600;
  color: var(--ink);
  margin: 4px 0 2px;
  line-height: 1.1;
}
#view-admin .admin-detail-email { margin: 0; color: var(--ink-soft); font-size: var(--text-sm); }
#view-admin .admin-detail-pills {
  display: flex; flex-wrap: wrap; gap: 6px; align-items: center;
  margin-top: var(--space-3);
}
#view-admin .admin-detail-joined { margin: var(--space-2) 0 0; font-size: var(--text-xs); }
#view-admin .admin-stripe-link { margin-top: var(--space-4); }
#view-admin .admin-section-title {
  font-family: var(--font-display);
  font-size: var(--text-lg);
  font-weight: 600;
  color: var(--ink);
  margin: 0 0 var(--space-3);
}

/* ----- Usage rows (detail) ----- */
#view-admin .admin-usage-row {
  display: grid;
  grid-template-columns: 150px minmax(0, 1fr);
  gap: var(--space-4);
  align-items: center;
  padding: 9px 0;
  border-bottom: 1px solid var(--border-soft);
}
#view-admin .admin-usage-row:last-of-type { border-bottom: 0; }
#view-admin .admin-usage-label { font-size: var(--text-sm); color: var(--ink-soft); }
#view-admin .admin-storage-note {
  margin: var(--space-3) 0 0;
  font-size: var(--text-xs);
}
#view-admin .admin-text-btn {
  border: 0; background: transparent;
  padding: 0; margin-left: 8px;
  font: inherit;
  font-size: var(--text-xs);
  color: var(--accent);
  text-decoration: underline;
  cursor: pointer;
}
#view-admin .admin-text-btn:hover { color: var(--ink); }
#view-admin .admin-text-btn:disabled { color: var(--ink-mute); cursor: default; text-decoration: none; }
#view-admin .admin-text-danger { color: var(--rose); margin-left: 0; }
#view-admin .admin-text-danger:hover { color: var(--rose); }

/* ----- Grants ----- */
#view-admin .admin-effect-lines {
  padding: 12px 14px;
  margin-bottom: var(--space-4);
  border-radius: var(--radius-md);
  background: var(--surface-2);
  font-size: var(--text-sm);
  line-height: 1.6;
}
#view-admin .admin-effect-key { color: var(--ink-soft); }
#view-admin .admin-reason { margin-bottom: var(--space-3); }
#view-admin .admin-label {
  display: block;
  font-size: var(--text-xs);
  letter-spacing: 0.04em;
  color: var(--ink-soft);
  margin-bottom: 5px;
}
#view-admin .admin-hint { margin: 5px 0 0; font-size: var(--text-xs); }
#view-admin .admin-grant-group {
  padding-top: var(--space-4);
  margin-top: var(--space-4);
  border-top: 1px solid var(--border-soft);
}
#view-admin .admin-group-title {
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-weight: 600;
  color: var(--ink-soft);
  margin: 0 0 var(--space-3);
}
#view-admin .admin-grant-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: var(--space-3);
}
#view-admin .admin-check {
  display: flex; align-items: center; gap: 8px;
  margin-top: var(--space-3);
  font-size: var(--text-sm);
  color: var(--ink-soft);
  cursor: pointer;
}
#view-admin .admin-actions {
  display: flex; align-items: center; gap: var(--space-4);
  flex-wrap: wrap;
  margin-top: var(--space-4);
}
#view-admin .admin-readout {
  display: flex; flex-wrap: wrap; gap: var(--space-4);
  font-size: var(--text-sm);
  color: var(--ink-soft);
  margin-bottom: var(--space-3);
}
#view-admin .admin-readout b { color: var(--ink); font-weight: 600; }
#view-admin .admin-quick-adds { display: flex; gap: 6px; margin-bottom: var(--space-3); }

/* Success state on admin save buttons — mirrors the app-wide Save Work
   confirmation (square, scaled, black, cloud check) and reuses its keyframes.
   Only transform/background/colour/border animate; radius snaps. */
#view-admin .admin-btn-save { position: relative; }
#view-admin .admin-btn-save.is-saved {
  border-radius: 0;
  transform: scale(1.06);
  background: #000000;
  border-color: #000000;
  color: #fcfaf7;
  cursor: default;
  box-sizing: border-box;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
}
#view-admin .admin-btn-save.is-saved .admin-save-cloud {
  animation: saveCheckDraw 0.45s ease-out 0.08s both;
  width: 18px;
  height: 18px;
  flex-shrink: 0;
  color: #fcfaf7;
  stroke: currentColor;
}
@media (prefers-reduced-motion: reduce) {
  #view-admin .admin-btn-save,
  #view-admin .admin-btn-save.is-saved,
  #view-admin .admin-btn-save.is-saved .admin-save-cloud { animation: none; transition: none; }
}

/* ----- Log tables: ledger, subscription history, admin activity ----- */
#view-admin .admin-log {
  border-top: 1px solid var(--border-soft);
}
#view-admin .admin-log-head,
#view-admin .admin-log-row {
  display: grid;
  grid-template-columns: 116px 96px minmax(0, 1fr) 88px;
  gap: var(--space-3);
  align-items: baseline;
  padding: 9px 0;
  border-bottom: 1px solid var(--border-soft);
  font-size: var(--text-sm);
}
#view-admin .admin-log-head.admin-log-row-3,
#view-admin .admin-log-row.admin-log-row-3 {
  grid-template-columns: 168px 132px minmax(0, 1fr);
}
/* Admin Activity: the last column is a free-text reason, not a number, so it
   gets the room instead of the fixed narrow width the ledger balance uses. */
#view-admin .admin-log-head.admin-log-row-audit,
#view-admin .admin-log-row.admin-log-row-audit {
  grid-template-columns: 160px 76px minmax(0, 1fr) minmax(0, 1.35fr);
}
#view-admin .admin-log-head {
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--ink-soft);
}
#view-admin .admin-log-row:last-child { border-bottom: 0; }
#view-admin .admin-log-row > div { min-width: 0; overflow-wrap: anywhere; }
#view-admin .admin-delta { font-weight: 600; }
#view-admin .admin-delta.is-positive { color: var(--accent); }
#view-admin .admin-delta.is-negative { color: var(--rose); }
#view-admin .admin-log + .admin-empty,
#view-admin .admin-log .admin-empty { border-bottom: 0; padding: var(--space-4) 0; text-align: left; }

/* ----- Mobile ----- */
@media (max-width: 1100px) {
  #view-admin .admin-detail { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 820px) {
  #view-admin .admin-list-head { align-items: stretch; flex-direction: column; }
  #view-admin .admin-search { min-width: 0; width: 100%; }
  #view-admin .admin-section { padding: var(--space-4); }
  #view-admin .admin-usage-row { grid-template-columns: 1fr; gap: 4px; }
  #view-admin .admin-detail-name { font-size: 24px; }
}
@media (max-width: 700px) {
  /* Log rows stack: the header no longer maps to the columns, so hide it. */
  #view-admin .admin-log-head { display: none; }
  #view-admin .admin-log-row,
  #view-admin .admin-log-row.admin-log-row-3 {
    grid-template-columns: 1fr;
    gap: 2px;
    padding: 12px 0;
  }
}

/* The sidebar nav rules set display:flex on foot nav buttons, which beats the
   hidden attribute's default display:none. Without this the Admin button would
   be visible to every signed-in artist, so it needs an explicit rule. Scoped to
   the one id so it cannot affect anything else. */
/* Same problem applies to every nav item that can be hidden by plan or role,
   not just Admin — Inquiries was showing to free-plan users because of it. */
#nav-admin[hidden],
.nav-item[hidden],
.nav-item-foot[hidden] { display: none !important; }

/* ---------------------------------------------------------------------------
   Work In Progress: locked Public Visibility toggle
   A work in progress is never published, so while that status is selected the
   toggle is switched off and disabled. Dim it so it reads as unavailable
   rather than broken, and sit a short explanation underneath.
   --------------------------------------------------------------------------- */
.toggle.is-locked { opacity: 0.5; cursor: not-allowed; }
.toggle.is-locked input { cursor: not-allowed; }
.field-note {
  margin: 6px 0 0;
  font-size: 12px;
  line-height: 1.4;
  color: var(--ink-mute);
}
.field-note[hidden] { display: none; }

/* =========================================================
   Public Site → Setup, Step 1: custom-domain confirmation
   and the Browser Tab (favicon + title) preview
   ========================================================= */
.ps-url-domain-note {
  margin-top: 14px;
  padding: 12px 14px;
  border: 1px solid color-mix(in oklab, var(--green) 45%, var(--border));
  background: color-mix(in oklab, var(--green) 10%, transparent);
  border-radius: 12px;
  display: flex;
  align-items: flex-start;
  gap: 12px;
  flex-wrap: wrap;
}
.ps-url-domain-note[hidden] { display: none; }
.ps-url-domain-pill {
  flex: 0 0 auto;
  font-size: 11px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  padding: 4px 10px;
  border-radius: 999px;
  border: 1px solid var(--green);
  color: var(--green);
  white-space: nowrap;
}
.ps-url-domain-copy {
  flex: 1 1 240px;
  min-width: 0;
  font-size: 13px;
  line-height: 1.55;
  color: var(--ink-soft, #4a4f4b);
}
.ps-url-domain-copy a { color: inherit; }
.ps-url-domain-copy code { font-size: 12px; }

.ps-tabid { margin-top: 22px; }
.media-tile.mt-icon img {
  object-fit: contain;
  padding: 8px;
}
.ps-tabchip {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  max-width: 320px;
  padding: 8px 12px;
  border: 1px solid var(--border, #e6e1d4);
  border-bottom: 0;
  border-radius: 10px 10px 0 0;
  background: var(--surface);
  box-shadow: 0 1px 0 var(--surface);
}
.ps-tabchip-ico {
  flex: 0 0 auto;
  width: 16px;
  height: 16px;
  display: flex;
  align-items: center;
  justify-content: center;
}
.ps-tabchip-ico img {
  width: 16px;
  height: 16px;
  object-fit: contain;
  display: block;
}
.ps-tabchip-dot {
  width: 12px;
  height: 12px;
  border-radius: 3px;
  background: var(--border, #e6e1d4);
  display: block;
}
.ps-tabchip-title {
  flex: 1 1 auto;
  min-width: 0;
  font-size: 12.5px;
  color: var(--ink, #1a1d1b);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.ps-tabchip-x {
  flex: 0 0 auto;
  font-size: 14px;
  line-height: 1;
  color: var(--ink-mute, #8a8d86);
}

/* =========================================================
   PUBLIC CONTACT FORM  (#contact)
   Sits between the CTA banner and the footer. Typography follows the
   Biography section: Nexa uppercase headings, EB Garamond body.
   ========================================================= */
.public-frame .public-contact {
  background: #fcfaf7;
  padding: 96px 150px 120px;
  scroll-margin-top: 80px;
}
@media (max-width: 1100px) {
  .public-frame .public-contact { padding: 72px 48px 96px; }
}
@media (max-width: 640px) {
  .public-frame .public-contact { padding: 56px 22px 80px; }
}
.public-frame .public-contact .pcf-inner {
  max-width: 980px;
  margin: 0 auto;
}
/* Big, airy, centred heading — light weight and wide tracking so it reads as
   a gallery title rather than a form label. */
.public-frame .public-contact .pcf-h {
  font-family: var(--pub-nexa);
  font-size: 46px;
  font-weight: 400;
  letter-spacing: 9px;
  text-transform: uppercase;
  text-align: center;
  color: #000000;
  line-height: 1.05;
  margin: 0 0 18px;
}
.public-frame .public-contact .pcf-intro {
  font-family: var(--pub-garamond);
  font-size: 17px;
  line-height: 1.55;
  text-align: center;
  color: #000000;
  max-width: 560px;
  margin: 0 auto 44px;
}
@media (max-width: 900px) {
  .public-frame .public-contact .pcf-h { font-size: 34px; letter-spacing: 6px; }
}
@media (max-width: 640px) {
  .public-frame .public-contact .pcf-h { font-size: 26px; letter-spacing: 4px; }
  .public-frame .public-contact .pcf-intro { font-size: 16px; margin-bottom: 32px; }
}
.public-frame .public-contact .pcf-form {
  display: flex;
  flex-direction: column;
  gap: 20px;
}
.public-frame .public-contact .pcf-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 20px;
}
@media (max-width: 640px) {
  .public-frame .public-contact .pcf-row { grid-template-columns: 1fr; }
}
.public-frame .public-contact .pcf-field {
  display: flex;
  flex-direction: column;
  gap: 7px;
}
.public-frame .public-contact .pcf-field > span {
  font-family: var(--pub-nexa);
  font-size: 13px;
  font-weight: 400;
  letter-spacing: 1.6px;
  text-transform: uppercase;
  color: #1a1a1a;
}
/* Red asterisk marking a required field, as in the reference layout. */
.public-frame .public-contact .pcf-req {
  color: #cc2222;
  margin-left: 3px;
  font-weight: 400;
}
.public-frame .public-contact .pcf-field > span em {
  font-style: normal;
  font-weight: 400;
  letter-spacing: 0.8px;
  color: #8a8a8a;
  margin-left: 5px;
}
.public-frame .public-contact .pcf-field input,
.public-frame .public-contact .pcf-field textarea {
  width: 100%;
  box-sizing: border-box;
  font-family: var(--pub-garamond);
  font-size: 17px;
  line-height: 1.5;
  color: #000000;
  background: #fcfaf7;
  border: 1px solid #A9A9A9;
  border-radius: 0;
  padding: 12px 14px;
  transition: border-color 0.25s ease-in-out;
  -webkit-appearance: none;
  appearance: none;
}
.public-frame .public-contact .pcf-field textarea {
  resize: vertical;
  min-height: 130px;
}
.public-frame .public-contact .pcf-field input:focus,
.public-frame .public-contact .pcf-field textarea:focus {
  outline: none;
  border-color: #000000;
}
/* "Regarding <artwork>" chip, shown when the visitor arrived from a piece. */
.public-frame .public-contact .pcf-about {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 11px 14px;
  border: 1px solid #000000;
  background: #FAFAFA;
}
.public-frame .public-contact .pcf-about-label {
  font-family: var(--pub-nexa);
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 1.4px;
  text-transform: uppercase;
  color: #8a8a8a;
  flex: 0 0 auto;
}
.public-frame .public-contact .pcf-about-title {
  font-family: var(--pub-garamond);
  font-size: 17px;
  color: #000000;
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.public-frame .public-contact .pcf-about-clear {
  flex: 0 0 auto;
  background: none;
  border: 0;
  cursor: pointer;
  font-size: 20px;
  line-height: 1;
  padding: 0 2px;
  color: #8a8a8a;
  transition: color 0.25s ease-in-out;
}
.public-frame .public-contact .pcf-about-clear:hover { color: #000000; }
/* display:flex above would otherwise defeat the hidden attribute, leaving an
   empty "Regarding" chip on screen when no artwork has been chosen. */
.public-frame .public-contact .pcf-about[hidden] { display: none; }
/* Honeypot: off-screen for bots, invisible and unfocusable for people. */
.public-frame .public-contact .pcf-hp {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}
/* Button sits hard right under the message box; any status text sits to its
   left so the two never collide. */
.public-frame .public-contact .pcf-actions {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 18px;
  flex-wrap: wrap;
  margin-top: 8px;
}
.public-frame .public-contact .pcf-actions .pcf-msg {
  order: -1;
  text-align: right;
}
@media (max-width: 640px) {
  .public-frame .public-contact .pcf-actions {
    justify-content: stretch;
    flex-direction: column-reverse;
    align-items: stretch;
  }
  .public-frame .public-contact .pcf-actions .pcf-submit { width: 100%; }
  .public-frame .public-contact .pcf-actions .pcf-msg { text-align: center; }
}
/* Send Inquiry carries the app-wide Folio button behaviour: a pill that snaps
   square, scales slightly and empties out on hover. Typography stays public-site
   Nexa so it belongs to the artist's page, not the admin. */
.public-frame .public-contact .pcf-submit {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-family: var(--pub-nexa);
  font-size: 12px;
  font-weight: 400;
  letter-spacing: 3px;
  text-transform: uppercase;
  color: #fcfaf7;
  background: #000000;
  border: 1px solid #000000;
  border-radius: 999px;
  padding: 12px 26px;
  cursor: pointer;
  will-change: transform;
  transition:
    transform 0.3s ease,
    background-color 0.3s ease,
    color 0.3s ease,
    border-color 0.3s ease;
}
.public-frame .public-contact .pcf-submit:hover:not(:disabled) {
  border-radius: 0;
  transform: scale(1.06);
  background: transparent;
  color: #000000;
  border-color: #000000;
}
.public-frame .public-contact .pcf-submit:disabled {
  opacity: 0.55;
  cursor: default;
}
.public-frame .public-contact .pcf-msg {
  font-family: var(--pub-garamond);
  font-size: 16px;
  line-height: 1.4;
}
.public-frame .public-contact .pcf-msg.is-ok { color: #1f7a4d; }
.public-frame .public-contact .pcf-msg.is-error { color: #cc3366; }

/* Inquire link inside the artwork popup. Deliberately not a button: it sits
   directly under the availability line and reads as body copy, black until
   hovered, then the popup's link colour. Keeps the popup quiet and typographic. */
.pmod-inquiry-btn {
  display: inline-block;
  margin: 0;
  padding: 0;
  font-family: "EB Garamond", Georgia, serif;
  font-size: 16px;
  line-height: 1.5;
  font-weight: 400;
  letter-spacing: 0;
  text-transform: none;
  text-decoration: none;
  text-align: left;
  color: #000000;
  background: none;
  border: 0;
  border-radius: 0;
  cursor: pointer;
  transition: color 0.3s ease-in-out;
}
.pmod-inquiry-btn:hover,
.pmod-inquiry-btn:focus-visible {
  color: #cc3366;
}

/* =========================================================
   INQUIRIES  (sidebar badge + Inquiries view)
   ========================================================= */
.nav-badge {
  flex: 0 0 auto;
  min-width: 18px;
  height: 18px;
  padding: 0 5px;
  border-radius: 999px;
  background: #933994;
  color: #F8F5EE;
  font-size: 10.5px;
  font-weight: 600;
  line-height: 18px;
  text-align: center;
  box-sizing: border-box;
}
/* Collapsed sidebar: the count becomes a small dot beside the icon. */
.shell.sidebar-collapsed .nav-badge {
  position: absolute;
  margin-left: 22px;
  margin-top: -10px;
  min-width: 8px;
  height: 8px;
  padding: 0;
  overflow: hidden;
  color: transparent;
}
.nav-item { position: relative; }

.inq-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
  margin-bottom: 16px;
}
.inq-filters { display: flex; gap: 6px; }
.inq-filter {
  background: transparent;
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 6px 14px;
  font-size: var(--text-sm);
  color: var(--ink-soft);
  cursor: pointer;
  transition: background var(--transition), color var(--transition), border-color var(--transition);
}
.inq-filter:hover { border-color: var(--accent); color: var(--ink); }
.inq-filter.is-active {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--accent-ink);
}
.inq-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 12px; }
.inq-row {
  display: flex;
  gap: 18px;
  align-items: flex-start;
  justify-content: space-between;
  padding: 16px 18px;
  background: var(--surface-elev);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
}
.inq-row.is-new { border-left: 3px solid var(--accent); }
.inq-main { flex: 1 1 auto; min-width: 0; }
.inq-head {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin-bottom: 3px;
}
.inq-name { font-size: var(--text-md); font-weight: 600; color: var(--ink); }
.inq-status {
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.5px;
  text-transform: uppercase;
  padding: 3px 9px;
  border-radius: 999px;
  background: var(--surface-2);
  color: var(--ink-mute);
}
.inq-status-new { background: var(--accent-soft); color: var(--accent); }
.inq-status-replied { background: color-mix(in oklab, var(--green) 16%, transparent); color: var(--green); }
.inq-date { font-size: var(--text-xs); }
.inq-contact { font-size: var(--text-sm); margin-bottom: 8px; }
.inq-contact a { color: var(--accent); text-decoration: none; }
.inq-contact a:hover { text-decoration: underline; }

/* The visitor's address doubles as a click-to-copy control. */
.inq-copy {
  appearance: none;
  border: 0;
  background: none;
  padding: 0;
  margin: 0;
  font: inherit;
  color: var(--accent);
  cursor: pointer;
  border-bottom: 1px dashed currentColor;
  transition: color .15s ease, border-color .15s ease;
}
.inq-copy:hover { border-bottom-style: solid; }
.inq-copy.is-copied {
  color: var(--text-muted, #6b7280);
  border-bottom-color: transparent;
  letter-spacing: .04em;
  text-transform: uppercase;
  font-size: var(--text-xs, 12px);
}
.inq-about {
  display: inline-flex;
  align-items: baseline;
  gap: 7px;
  font-size: var(--text-sm);
  color: var(--ink);
  background: var(--surface-2);
  border-radius: 6px;
  padding: 5px 10px;
  margin-bottom: 9px;
}
.inq-about span {
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.6px;
  text-transform: uppercase;
  color: var(--ink-mute);
}
.inq-message {
  margin: 0;
  font-size: var(--text-base);
  line-height: 1.55;
  color: var(--ink-soft);
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}
.inq-warn {
  margin-top: 9px;
  font-size: var(--text-xs);
  color: var(--amber);
}
.inq-actions {
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  gap: 7px;
  align-items: stretch;
}
.inq-actions .btn { white-space: nowrap; text-align: center; text-decoration: none; }
@media (max-width: 820px) {
  .inq-row { flex-direction: column; }
  .inq-actions { flex-direction: row; flex-wrap: wrap; width: 100%; }
}

/* Artwork tiles are links (each work has its own page) but must look exactly
   like the buttons they replaced. */
a.card.pc-tile {
  display: block;
  text-decoration: none;
  color: inherit;
  -webkit-tap-highlight-color: transparent;
}
a.card.pc-tile[hidden] { display: none !important; }


/* ===== Dark mode: toggles, date pickers and scrollbars ===== */

/* Off state reads as an unmistakable switch: Neo Pearl track, dark knob.
   On state keeps the fuchsia track with a Neo Pearl knob. */
[data-theme="dark"] .toggle .track,
[data-theme="dark"] .toggle-switch { background: #F8F5EE; }
[data-theme="dark"] .toggle .track::after,
[data-theme="dark"] .toggle-switch::after { background: #2B2F2D; }
[data-theme="dark"] .toggle input:checked + .track,
[data-theme="dark"] .toggle-switch:checked { background: var(--accent); }
[data-theme="dark"] .toggle input:checked + .track::after,
[data-theme="dark"] .toggle-switch:checked::after { background: #F8F5EE; }

/* Native calendar/clock buttons ship as dark glyphs; invert to Neo Pearl. */
[data-theme="dark"] input[type="date"]::-webkit-calendar-picker-indicator,
[data-theme="dark"] input[type="month"]::-webkit-calendar-picker-indicator,
[data-theme="dark"] input[type="datetime-local"]::-webkit-calendar-picker-indicator,
[data-theme="dark"] input[type="time"]::-webkit-calendar-picker-indicator {
  opacity: 0.95;
}
[data-theme="dark"] input[type="date"],
[data-theme="dark"] input[type="month"],
[data-theme="dark"] input[type="datetime-local"],
[data-theme="dark"] input[type="time"] { color-scheme: dark; }

[data-theme="dark"] * { scrollbar-color: rgba(248, 245, 238, 0.5) transparent; }
[data-theme="dark"] ::-webkit-scrollbar { width: 10px; height: 10px; }
[data-theme="dark"] ::-webkit-scrollbar-track { background: transparent; }
[data-theme="dark"] ::-webkit-scrollbar-thumb {
  background: rgba(248, 245, 238, 0.45);
  border-radius: 999px;
  border: 2px solid transparent;
  background-clip: content-box;
}
[data-theme="dark"] ::-webkit-scrollbar-thumb:hover { background: rgba(248, 245, 238, 0.7); background-clip: content-box; }


/* ---------- Mobile drawer wordmark: hard left alignment ----------
   Safari sizes an SVG with width:auto to its container and centres the
   artwork inside, so the wordmark drifted to the middle of the drawer.
   Fixed width plus !important so nothing upstream can re-centre it. */
@media (max-width: 820px) {
  .sidebar .sidebar-head,
  .sidebar .sidebar-head .brand,
  .sidebar .sidebar-head .brand-name {
    display: flex !important;
    flex-direction: row !important;
    justify-content: flex-start !important;
    align-items: center !important;
    width: auto !important;
    min-width: 0 !important;
    min-height: 0 !important;
    margin: 0 !important;
    padding: 0 !important;
    text-align: left !important;
  }
  .sidebar { align-items: stretch !important; }
  .sidebar .sidebar-head { padding-left: 10px !important; }
  .sidebar .sidebar-head .brand-wordmark {
    display: block !important;
    width: 85px !important;
    height: 42px !important;
    flex: 0 0 85px !important;
    align-self: center !important;
    margin: 0 !important;
  }
}

/* Headings use General Sans at its heaviest loaded weight (700). */
#view-admin .admin-detail-name,
#view-admin .admin-row-title,
#view-admin .admin-section-title,
.al-ph-title,
.al-title,
.app-empty-state .aes-title,
.art-row-title .al-title,
.brand-name,
.card-title,
.concept-h,
.eli-title,
.modal-title,
.preview-thumb .placeholder-title,
.preview-title,
.section-title,
.thumb.placeholder .placeholder-title,
.tier-amount,
.upload-zone-label {
  font-weight: 600 !important;
}

/* Presentation mode — hides Inquiries and Admin while screen recording.
   Toggled by visiting /#presentation and /#presentation-off. */
body.folio-presentation #nav-inquiries,
body.folio-presentation #nav-clients,
body.folio-presentation #nav-invoices,
body.folio-presentation #nav-admin,
body.folio-presentation #nav-inquiries-badge {
  display: none !important;
}
/* Contact Form section (Site Settings > Public Site > Design) is tied to the
   Inquiries feature, so it comes out of view during a demo too. */
body.folio-presentation .ps-section[data-ps-section="contact"] {
  display: none !important;
}

/* Account tab — inline email / password forms */
.account-form {
  margin: -4px 0 14px;
  padding: 16px 18px 18px;
  border: 1px solid var(--border);
  border-radius: 14px;
  background: var(--surface-3);
  max-width: 460px;
}
.account-form .field { margin-bottom: 12px; }
.account-form .acct-note { margin: 2px 0 14px; font-size: 13px; line-height: 1.45; }
.account-form-actions { display: flex; gap: 10px; flex-wrap: wrap; }
@media (max-width: 620px) {
  .account-form { max-width: 100%; }
  .account-form-actions .btn { flex: 1; }
}


/* ============================================================
   Invoices — list pills, line editor, and the printable document
   ============================================================ */
.inv-pill {
  display: inline-block;
  padding: 2px 9px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.02em;
  border: 1px solid var(--border);
  background: var(--surface-2);
  color: var(--ink-soft);
}
.inv-pill-sent { border-color: #cbb7cc; background: #f4ecf4; color: #6d2a6e; }
.inv-pill-paid { border-color: #bcd8c2; background: #edf6ef; color: #2f6b40; }
.inv-pill-void { text-decoration: line-through; }
.inv-pill-overdue { border-color: #f0b9ba; background: #fdeded; color: #a32b2d; }

.inv-lines-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin: 22px 0 10px;
  flex-wrap: wrap;
}
.inv-lines { display: flex; flex-direction: column; gap: 8px; }
.inv-line {
  display: grid;
  grid-template-columns: 1fr 68px 110px 100px 28px;
  gap: 8px;
  align-items: start;
}
.inv-line-desc { display: flex; flex-direction: column; gap: 6px; }
.inv-line-detail { font-size: 13px; }
.inv-line-amt {
  padding-top: 10px;
  text-align: right;
  font-variant-numeric: tabular-nums;
  color: var(--ink-soft);
}
.inv-line-del {
  margin-top: 6px;
  width: 28px;
  height: 28px;
  border-radius: 999px;
  border: 1px solid var(--border);
  background: var(--surface-2);
  color: var(--ink-mute);
  font-size: 16px;
  line-height: 1;
  cursor: pointer;
}
.inv-line-del:hover { color: var(--ink); border-color: var(--ink-mute); }
.inv-totals {
  margin: 14px 0 0;
  margin-left: auto;
  width: min(320px, 100%);
  display: flex;
  flex-direction: column;
  gap: 6px;
  font-size: 14px;
}
.inv-totals > div { display: flex; justify-content: space-between; gap: 16px; }
.inv-totals strong { font-variant-numeric: tabular-nums; }
.inv-total-row {
  border-top: 1px solid var(--border);
  padding-top: 8px;
  font-size: 16px;
}
.inv-work-results { margin-top: 12px; max-height: 46vh; overflow-y: auto; display: flex; flex-direction: column; gap: 4px; }
.inv-work-row {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  text-align: left;
  padding: 9px 10px;
  border: 1px solid transparent;
  border-radius: 10px;
  background: none;
  cursor: pointer;
  color: var(--ink);
}
.inv-work-row:hover { background: var(--surface-2); border-color: var(--border); }
.inv-work-title { font-weight: 600; }

@media (max-width: 720px) {
  .inv-line { grid-template-columns: 1fr 56px 92px; }
  .inv-line-amt { grid-column: 2 / 4; text-align: right; padding-top: 0; }
  .inv-line-del { grid-column: 3; justify-self: end; }
}

/* The printable invoice. Hidden on screen; on paper it is the only thing. */
#invoice-print { display: none; }
.inv-doc { color: #2B2F2D; font-size: 12pt; line-height: 1.5; }
.inv-doc-top { display: flex; justify-content: space-between; gap: 32px; margin-bottom: 30px; }
.inv-doc-biz { font-family: var(--font-display), sans-serif; font-size: 20pt; margin: 0 0 6px; }
.inv-doc-lines { margin: 0 0 3px; font-size: 10.5pt; }
.inv-doc-meta { text-align: right; white-space: nowrap; }
.inv-doc-word { font-family: var(--font-display), sans-serif; font-size: 22pt; letter-spacing: 0.04em; }
.inv-doc-num { font-size: 12pt; margin-bottom: 8px; }
.inv-doc-label {
  font-size: 8.5pt;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: #7a7e78;
  margin-bottom: 5px;
}
.inv-doc-billto { margin-bottom: 26px; }
.inv-doc-table { width: 100%; border-collapse: collapse; margin-bottom: 18px; }
.inv-doc-table th {
  text-align: left;
  font-size: 8.5pt;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: #7a7e78;
  border-bottom: 1px solid #2B2F2D;
  padding: 0 0 6px;
}
.inv-doc-table td { padding: 9px 0; border-bottom: 1px solid #e1ddd2; vertical-align: top; font-size: 11pt; }
.inv-doc-table .num { text-align: right; font-variant-numeric: tabular-nums; padding-left: 14px; }
.inv-doc-detail { font-size: 10pt; color: #4a504c; }
.inv-doc-sum { margin-left: auto; width: 260px; font-size: 11pt; }
.inv-doc-sum > div { display: flex; justify-content: space-between; padding: 4px 0; }
.inv-doc-grand { border-top: 1px solid #2B2F2D; margin-top: 4px; padding-top: 7px !important; font-size: 13pt; font-weight: 600; }
.inv-doc-paid { justify-content: flex-end !important; color: #2f6b40; font-weight: 600; }
.inv-doc-block { margin-top: 22px; }
.inv-doc-footer { margin-top: 28px; font-size: 10.5pt; color: #4a504c; }

@media print {
  body.folio-printing > *:not(#invoice-print) { display: none !important; }
  body.folio-printing #invoice-print { display: block !important; }
  body.folio-printing { background: #fff !important; }
  @page { margin: 18mm 16mm; }
}

/* Record Payment dialog — the checklist of works on a paid invoice. */
.inv-paid-work {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 7px 0;
  font-size: 14px;
  cursor: pointer;
}
.inv-paid-work input { margin-top: 3px; flex: 0 0 auto; }

/* Account tab: the seam between sign-in details and the subscription section. */
.acct-billing-divider {
  border-top: 1px solid var(--border);
  margin: 34px 0 26px;
  scroll-margin-top: 90px;
}

/* Invoice line photos. A work pulled from the catalog brings its picture with
   it, so the collector can see what they are paying for. */
.inv-line-desc { flex-direction: row; align-items: flex-start; gap: 8px; }
.inv-line-fields { display: flex; flex-direction: column; gap: 6px; flex: 1 1 auto; min-width: 0; }
.inv-line-thumb {
  flex: 0 0 auto;
  width: 42px;
  height: 42px;
  margin-top: 1px;
  border-radius: 6px;
  border: 1px solid var(--border);
  overflow: hidden;
  background: var(--surface-3);
}
.inv-line-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }

.inv-doc-item { display: flex; align-items: flex-start; gap: 12px; }
.inv-doc-thumb {
  flex: 0 0 auto;
  width: 58px;
  height: 58px;
  object-fit: cover;
  border-radius: 3px;
  border: 1px solid #e1ddd2;
  background: #f3f0e9;
}
@media print {
  .inv-doc-thumb { -webkit-print-color-adjust: exact; print-color-adjust: exact; }
}

/* Billing a piece in parts — deposit now, balance later. */
.inv-line-portion {
  grid-column: 1 / -1;
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  margin: 2px 0 4px 50px;
  font-size: 13px;
  color: var(--ink-soft);
}
.inv-line-portion label { font-size: 12px; letter-spacing: 0.02em; text-transform: uppercase; color: var(--ink-mute); }
.inv-line-portion-sel { width: auto; min-width: 150px; padding: 5px 8px; font-size: 13px; }
.inv-line-pct { width: 68px; padding: 5px 8px; font-size: 13px; }
.inv-line-portion .muted { font-size: 12px; }
@media (max-width: 720px) {
  .inv-line-portion { margin-left: 0; }
}

/* Pasted-link preview: stack the explanation under the picture. */
.ip-link-preview {
  flex-direction: column;
  align-items: center;
  gap: 8px;
}
.ip-link-note {
  font-size: 13px;
  line-height: 1.45;
  text-align: center;
  max-width: 460px;
}

/* Stacked editor (tablet + phone) — put the artwork image above the Work
   Details form, with the Library staying last. The preview column stops
   generating a box so its children can be ordered alongside the form. */
@media (max-width: 1100px) {
  .editor-grid { display: flex !important; flex-direction: column; }
  .editor-grid > .editor-preview { display: contents !important; }
  .editor-grid > .editor-preview > .editor-preview-slot { order: 1; }
  .editor-grid > .editor-form { order: 2; }
  .editor-grid > .editor-preview > .hr,
  .editor-grid > .editor-preview > .library-head,
  .editor-grid > .editor-preview > .editor-list { order: 3; }
}

/* Phone: the fixed sign-in bar sits above the pop-ups (z-index 9997), so a
   centred card could hide its own title and close button underneath it. Drop
   the card below the bar and let the overlay scroll. Uses dvh so Safari's
   collapsing address bar can't push the top edge off-screen. Deliberately
   does NOT touch .ip-cam-frame — the camera preview shape stays as-is. */
@media (max-width: 720px) {
  .modal-overlay {
    align-items: flex-start !important;
    padding: 72px 14px 20px !important;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
  }
  .modal-overlay > .modal-card {
    max-height: calc(100dvh - 92px);
  }
}

/* Phone: with a tall camera preview the pop-up scrolls, so pin the title row
   (and its close button) to the top and the camera buttons to the bottom of
   the scrolling area. Both stay in view at any scroll position, and the
   preview frame's shape is untouched. */
@media (max-width: 720px) {
  .modal-overlay > .modal-card > .modal-head {
    position: sticky;
    top: 0;
    z-index: 4;
    background: var(--surface-elev);
  }
  .modal-overlay > .modal-card > .modal-body { padding-bottom: 0 !important; }
  .modal-overlay .ip-cam .row {
    position: sticky;
    bottom: 0;
    z-index: 4;
    background: var(--surface-elev);
    padding: 10px 0 14px !important;
    margin-top: 6px;
  }
  .modal-overlay .ip-cam-msg { margin-top: 10px; }
}

/* Phone, camera tab only: the title row is dropped and the tabs move up
   alongside the close button, freeing that height for the viewfinder. The
   close button is pinned to the card's top-right so it stays reachable.
   The .ip-cam-frame shape is untouched. */
@media (max-width: 720px) {
  .modal-overlay > .modal-card.is-cam { position: relative; }
  .modal-overlay > .modal-card.is-cam > .modal-head {
    position: absolute;
    top: 2px;
    right: 6px;
    left: auto;
    padding: 0;
    background: transparent;
    z-index: 6;
  }
  .modal-overlay > .modal-card.is-cam > .modal-head .modal-title { display: none; }
  .modal-overlay > .modal-card.is-cam > .modal-tabs { padding: 2px 54px 0 16px; }
  .modal-overlay > .modal-card.is-cam > .modal-body { padding-top: 14px; }
}

/* The camera hint line only exists for errors now, so it takes no space when
   it has nothing to say. */
.ip-cam-msg:empty { display: none; margin: 0; }

/* Phone, camera tab: centre the close button against the tab labels by giving
   the close row and the tab row the same height and centring both. */
@media (max-width: 720px) {
  .modal-overlay > .modal-card.is-cam > .modal-head {
    top: 0;
    right: 4px;
    height: 44px;
    align-items: center;
  }
  .modal-overlay > .modal-card.is-cam > .modal-tabs {
    min-height: 44px;
    align-items: center;
    padding: 0 52px 0 16px;
  }
}

/* Phone fixes for the image picker:
   1. The close button was centring against the whole tab row, which includes
      the active tab's underline, so it read as sitting low. Nudge it up onto
      the label text itself.
   2. The camera tab zeroes the body's bottom padding for its pinned buttons —
      that must not leak into the Upload and Link panels, where the button
      needs normal breathing room underneath. */
@media (max-width: 720px) {
  .modal-overlay > .modal-card.is-cam > .modal-head .modal-close {
    transform: translateY(-7px);
  }
  .modal-overlay > .modal-card:not(.is-cam) > .modal-body {
    padding-bottom: 24px !important;
  }
}

/* ===== Admin: Room Library (Place It) — 2026-09-02 ===== */
#view-admin .admin-sections { margin-bottom: 22px; }

/* --- Room list --- */
#view-admin .room-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
  gap: 18px;
}
#view-admin .room-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 14px;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}
#view-admin .room-card.is-inactive { opacity: 0.6; }
#view-admin .room-card-thumb {
  position: relative;
  aspect-ratio: 4 / 3;
  background: var(--surface-3);
  flex: 0 0 auto;
  overflow: hidden;
}
/* Absolute, so a portrait photo's own height cannot stretch the card.
   In normal flow the image's intrinsic height wins over aspect-ratio and
   every card ends up a different height. */
#view-admin .room-card-thumb img {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover; display: block;
}
#view-admin .room-card-badge {
  position: absolute; top: 8px; left: 8px;
  background: rgba(43,47,45,0.82); color: #fff;
  font-size: var(--text-xs); padding: 3px 9px; border-radius: 999px;
}
#view-admin .room-card-body { padding: 12px 14px 4px; }
#view-admin .room-card-name { font-weight: 600; color: var(--ink); }
#view-admin .room-card-meta { font-size: var(--text-xs); margin-top: 2px; }
#view-admin .room-card-actions {
  display: flex; gap: 6px; flex-wrap: wrap;
  padding: 10px 14px 14px; margin-top: auto;
}
#view-admin .room-card-actions .btn {
  border-radius: 999px;
  flex: 1 1 0;
  min-width: 0;
  padding-inline: 8px;
}
#view-admin .room-danger { color: var(--red, #EF4244); }
#view-admin .room-empty {
  border: 1px dashed var(--border); border-radius: 14px;
  padding: 34px 26px; text-align: center; background: var(--surface);
}
#view-admin .room-empty p { margin: 0 0 6px; }
#view-admin .room-notice {
  background: var(--surface); border: 1px solid var(--border);
  border-left: 3px solid var(--accent);
  border-radius: 10px; padding: 10px 14px; margin-bottom: 16px;
  font-size: var(--text-sm); color: var(--ink);
}

/* --- Room editor --- */
#view-admin .room-editor {
  display: grid;
  grid-template-columns: minmax(0, 1.55fr) minmax(280px, 1fr);
  gap: 24px;
  align-items: start;
}
#view-admin .room-steps { margin-bottom: 12px; }
#view-admin .room-instruct {
  font-size: var(--text-sm); color: var(--ink-soft);
  margin: 0 0 12px; line-height: 1.5;
}
#view-admin .room-canvas {
  position: relative;
  border: 1px solid var(--border);
  border-radius: 12px;
  overflow: hidden;
  background: var(--surface-3);
  cursor: crosshair;
  touch-action: none;
  user-select: none;
}
#view-admin .room-canvas.is-preview { cursor: default; }
#view-admin .room-canvas img { width: 100%; display: block; }
#view-admin .room-overlay { position: absolute; inset: 0; pointer-events: none; }

#view-admin .room-pin {
  position: absolute; width: 22px; height: 22px;
  margin: -11px 0 0 -11px;
  border-radius: 50%;
  background: var(--accent); color: #fff;
  border: 2px solid #fff;
  box-shadow: 0 0 0 1px rgba(0,0,0,0.25);
  display: grid; place-items: center;
  font-size: 11px; font-weight: 700;
}
#view-admin .room-calib-line {
  position: absolute; inset: 0; width: 100%; height: 100%;
}
#view-admin .room-wall-box {
  position: absolute;
  border: 2px dashed var(--accent);
  background: rgba(147,57,148,0.12);
  border-radius: 2px;
}
#view-admin .room-wall-box.is-quiet {
  border-style: solid; border-color: rgba(147,57,148,0.45); background: transparent;
}
#view-admin .room-anchor {
  position: absolute; width: 18px; height: 18px;
  margin: -9px 0 0 -9px;
  border-radius: 50%;
  background: #fff; border: 3px solid var(--accent);
  box-shadow: 0 1px 4px rgba(0,0,0,0.3);
  pointer-events: auto; cursor: grab;
}
#view-admin .room-anchor.is-quiet { pointer-events: none; opacity: 0.7; }
#view-admin .room-ref-art {
  position: absolute;
  background: rgba(43,47,45,0.28);
  border: 1px solid rgba(255,255,255,0.55);
  box-shadow: 0 6px 16px rgba(0,0,0,0.28);
  display: grid; place-items: center;
}
#view-admin .room-ref-art span {
  font-size: var(--text-xs); color: #fff; font-weight: 600;
  text-shadow: 0 1px 3px rgba(0,0,0,0.6);
}

#view-admin .room-drop {
  display: block; border: 1px dashed var(--border);
  border-radius: 12px; background: var(--surface);
  padding: 52px 24px; text-align: center; cursor: pointer;
  transition: border-color 0.15s ease;
}
#view-admin .room-drop:hover { border-color: var(--accent); }
#view-admin .room-drop-inner { display: grid; gap: 6px; }
#view-admin .room-drop-inner strong { color: var(--ink); }
#view-admin .room-drop-inner span { font-size: var(--text-sm); }
#view-admin .room-file-input {
  position: absolute; width: 1px; height: 1px;
  opacity: 0; pointer-events: none;
}
#view-admin .room-replace { margin-top: 10px; border-radius: 999px; }
#view-admin .room-status {
  font-size: var(--text-sm); color: var(--ink-soft);
  margin: 12px 0 0; line-height: 1.5;
}
#view-admin .room-editor-side .admin-section { margin-bottom: 0; }

@media (max-width: 900px) {
  #view-admin .room-editor { grid-template-columns: 1fr; }
}

/* --- Room Library: foreground painting --- */
#view-admin .room-canvas.is-paint { cursor: crosshair; }
#view-admin .room-mask-holder,
#view-admin .room-preview-holder {
  position: absolute; inset: 0;
}
#view-admin .room-mask-holder canvas,
#view-admin .room-preview-holder canvas {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  display: block;
}
#view-admin .room-canvas.is-showing-preview .room-mask-holder { display: none; }
#view-admin .room-preview-holder { background: var(--surface-3); }
#view-admin .room-preview-wait {
  position: absolute; inset: 0;
  display: grid; place-items: center;
  font-size: var(--text-sm); color: var(--ink-mute);
}
#view-admin .room-brush-row { display: flex; gap: 6px; margin-bottom: 14px; }
#view-admin .room-brush-actions { display: flex; gap: 6px; margin: 4px 0 14px; }
#view-admin .room-brush-actions .btn { border-radius: 999px; }
#view-admin .room-range {
  width: 100%; accent-color: var(--accent);
  height: 26px; cursor: pointer;
}

/* ===== Place It — artist wall preview (2026-09-02) ===== */
/* --- Place It: full-window dark shell, matching the Adjust screen --- */
.pi-overlay {
  position: fixed; inset: 0; z-index: 9999;
  background: rgba(0, 0, 0, 0.92);
  display: flex; flex-direction: column;
  animation: fcFadeIn 120ms ease-out;
}
.pi-modal {
  background: #111;
  width: 100vw; height: 100dvh;
  display: flex; flex-direction: column;
  overflow: hidden;
  color: #eee;
}
.pi-header {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px;
  padding: 12px 20px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
  background: #0a0a0a;
  flex: 0 0 auto;
}
.pi-title {
  margin: 0; font-size: 15px; font-weight: 600;
  letter-spacing: 0.01em; color: #eee;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.pi-title .pi-work { font-weight: 400; color: #999; }
.pi-title .pi-work::before { content: "\2014"; margin-right: 8px; }
.pi-close {
  background: none; border: 0; color: #aaa;
  font-size: 26px; line-height: 1;
  width: 34px; height: 34px; border-radius: 8px;
  cursor: pointer; flex: 0 0 auto;
  transition: color 120ms ease, background 120ms ease;
}
.pi-close:hover { color: #fcfaf7; background: rgba(255, 255, 255, 0.08); }

.pi-body {
  flex: 1 1 auto; min-height: 0;
  display: flex; flex-direction: column;
  padding: 0;
}
.pi-stage {
  flex: 1 1 auto; min-height: 0;
  display: flex; flex-direction: column;
  align-items: center; justify-content: center;
  gap: 8px;
  padding: 16px 20px 8px;
}
.pi-canvas-wrap {
  position: relative;
  flex: 1 1 auto; min-height: 0;
  display: flex; align-items: center; justify-content: center;
  width: 100%;
  border: 0; border-radius: 0; background: transparent;
}
.pi-canvas-wrap canvas {
  display: block;
  width: auto; height: auto;
  max-width: 100%; max-height: 100%;
  border-radius: 4px;
  cursor: grab;
  touch-action: none;
  box-shadow: 0 2px 18px rgba(0, 0, 0, 0.5);
}
.pi-canvas-wrap canvas.is-dragging { cursor: grabbing; }
.pi-canvas-wrap.is-loading canvas { opacity: 0.35; }
.pi-wait {
  position: absolute; inset: 0;
  display: grid; place-items: center;
  font-size: var(--text-sm); color: #aaa;
}
.pi-hint { font-size: 12px; margin: 0; color: #8c8c8c; flex: 0 0 auto; }

/* Room type filter + thumbnail strip */
.pi-rooms {
  flex: 0 0 auto;
  display: grid; gap: 10px;
  padding: 10px 20px 14px;
  border-top: 1px solid rgba(255, 255, 255, 0.08);
}
.pi-types { display: flex; gap: 8px; overflow-x: auto; padding-bottom: 2px; }
.pi-type {
  flex: 0 0 auto;
  appearance: none; cursor: pointer;
  padding: 5px 13px;
  border-radius: 999px;
  border: 1px solid rgba(255, 255, 255, 0.18);
  background: rgba(255, 255, 255, 0.06);
  color: #ddd;
  font: inherit; font-size: 12px; font-weight: 500;
  white-space: nowrap;
  transition: background 120ms ease, border-color 120ms ease, color 120ms ease;
}
.pi-type:hover { background: rgba(255, 255, 255, 0.13); color: #fff; }
.pi-type.is-active {
  background: var(--accent); border-color: var(--accent); color: #fff;
}
.pi-room-strip {
  display: flex; gap: 8px;
  overflow-x: auto;
  padding-bottom: 4px;
  scrollbar-width: thin;
}
.pi-room {
  flex: 0 0 auto;
  width: 96px;
  border: 1px solid rgba(255, 255, 255, 0.14);
  border-radius: 8px;
  background: #1a1a1a;
  padding: 0;
  overflow: hidden;
  cursor: pointer;
  transition: border-color 120ms ease, box-shadow 120ms ease, opacity 120ms ease;
  opacity: 0.72;
}
.pi-room img { display: block; width: 100%; height: 62px; object-fit: cover; }
.pi-room:hover { opacity: 1; border-color: rgba(255, 255, 255, 0.4); }
.pi-room.is-active {
  opacity: 1;
  border-color: var(--accent);
  box-shadow: 0 0 0 2px var(--accent);
}

.pi-empty { padding: 40px 24px; max-width: 520px; margin: auto; text-align: center; }
.pi-empty p { margin: 0 0 10px; color: #ccc; }
.pi-empty p.muted { color: #999; font-size: var(--text-sm); }
.pi-error {
  margin: 0 20px 12px;
  color: #ff8c8e;
  font-size: var(--text-sm);
}

.pi-footer {
  display: flex; align-items: center; gap: 12px;
  padding: 12px 20px;
  border-top: 1px solid rgba(255, 255, 255, 0.08);
  background: #0a0a0a;
  flex: 0 0 auto;
}
.pi-foot-note { font-size: 13px; color: #8c8c8c; flex: 1 1 auto; }
.pi-overlay .btn-outline {
  background: rgba(255, 255, 255, 0.06);
  border-color: rgba(255, 255, 255, 0.18);
  color: #eee;
}
.pi-overlay .btn-outline:hover:not(:disabled) { background: rgba(255, 255, 255, 0.12); }

@media (max-width: 640px) {
  .pi-stage { padding: 10px 12px 6px; }
  .pi-rooms { padding: 8px 12px 12px; }
  .pi-footer { padding: 10px 12px; }
  .pi-foot-note { display: none; }
  .pi-room { width: 82px; }
  .pi-room img { height: 54px; }
}

/* --- Room Library: Point tool --- */
#view-admin .room-canvas.is-paint.is-pointing { cursor: crosshair; }
#view-admin .room-brush-row { flex-wrap: wrap; }
#view-admin .room-brush-actions .btn[disabled] { opacity: 0.45; cursor: default; }

/* --- Room Library: zoom (floating control, Google Maps style) --- */
#view-admin .room-stage-wrap { position: relative; }
#view-admin .room-viewport {
  position: relative;
  display: flex;
  overflow: hidden;
  overscroll-behavior: contain;
  border: 1px solid var(--border);
  border-radius: 12px;
  background: var(--surface-3);
  width: 100%;
}
#view-admin .room-viewport.is-zoomed { overflow: auto; }
#view-admin .room-viewport .room-canvas {
  border: 0; border-radius: 0;
  margin: auto;          /* centres a portrait photo, and scrolls correctly when zoomed */
  flex: 0 0 auto;
}
#view-admin .room-viewport .room-canvas img { width: 100%; height: 100%; display: block; }

#view-admin .room-zoom-ctl {
  position: absolute;
  right: 10px;
  bottom: 10px;
  display: flex;
  flex-direction: column;
  background: #fff;
  border: 1px solid var(--border);
  border-radius: 8px;
  box-shadow: 0 1px 4px rgba(43, 47, 45, 0.18);
  overflow: hidden;
  z-index: 4;
}
#view-admin .room-zoom-ctl button {
  appearance: none;
  border: 0;
  background: transparent;
  width: 28px;
  height: 26px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 14px;
  line-height: 1;
  color: var(--ink);
  cursor: pointer;
  padding: 0;
}
#view-admin .room-zoom-ctl button + button { border-top: 1px solid var(--border); }
#view-admin .room-zoom-ctl button:hover:not([disabled]) { background: var(--surface-2); }
#view-admin .room-zoom-ctl button[disabled] { color: var(--ink-mute); opacity: 0.4; cursor: default; }
#view-admin .room-zoom-fit {
  font-size: 9px !important;
  font-weight: 500;
  color: var(--ink-soft) !important;
  height: 22px !important;
  font-variant-numeric: tabular-nums;
}

/* --- Room Library: centre magnet guides --- */
#view-admin .room-guide-v,
#view-admin .room-guide-h {
  position: absolute;
  pointer-events: none;
  z-index: 3;
}
#view-admin .room-guide-v {
  width: 0;
  border-left: 1px dashed var(--accent);
  transform: translateX(-0.5px);
  opacity: 0.75;
}
#view-admin .room-guide-h {
  height: 0;
  border-top: 1px dashed var(--accent);
  transform: translateY(-0.5px);
  opacity: 0.75;
}
/* Keep the dot above the guide lines. */
#view-admin .room-anchor { z-index: 5; }
#view-admin .room-anchor.is-snapped {
  box-shadow: 0 1px 4px rgba(0,0,0,0.3), 0 0 0 4px rgba(147, 57, 148, 0.25);
}

/* Uploading a ready-made foreground PNG for a room, instead of marking it by hand. */
#view-admin .room-front-upload { position: relative; margin: 0 0 4px; }
#view-admin .room-drop-sm { padding: 18px 16px; text-align: left; }
#view-admin .room-drop-sm .room-drop-inner { gap: 4px; }
#view-admin .room-front-have {
  display: grid; gap: 6px; justify-items: start;
  border: 1px solid var(--border); border-radius: 12px;
  background: var(--surface-2); padding: 14px 16px;
}
#view-admin .room-front-have strong { color: var(--ink); }
#view-admin .room-front-have span {
  font-size: var(--text-sm); word-break: break-all; line-height: 1.35;
}
#view-admin .room-front-have .btn { margin-top: 2px; }
#view-admin .room-front-or {
  margin: 14px 0 8px; padding-top: 12px;
  border-top: 1px solid var(--border);
}

/* ----- Room Library: header spacing + type filters -----
   The Add A Room button used to sit tight against the first row of room
   photos. Give the header room to breathe, and drop the type filters into
   the gap so the button reads as part of the heading, not the grid. */
#view-admin .room-list-head {
  align-items: flex-start;
  margin-bottom: var(--space-4);
}
#view-admin .room-list-head .admin-count { margin-bottom: 0; }
#view-admin .room-filters { margin-bottom: var(--space-5); }
#view-admin .room-filters .admin-filter-pill {
  display: inline-flex;
  align-items: center;
  gap: 7px;
}
#view-admin .room-filter-n {
  display: inline-block;
  min-width: 18px;
  padding: 1px 5px;
  border-radius: 999px;
  background: var(--surface-3);
  color: var(--ink-mute);
  font-size: 11px;
  font-weight: 600;
  line-height: 1.45;
  text-align: center;
}
#view-admin .admin-filter-pill.is-active .room-filter-n {
  background: rgba(255, 255, 255, 0.22);
  color: var(--accent-ink);
}

/* ----- Room Library: which plan each room belongs to ----- */
#view-admin .room-head-counts { display: flex; flex-direction: column; gap: 3px; }
#view-admin .room-plan-split { opacity: 0.75; }
#view-admin .room-card-plan { margin-top: 6px; }
#view-admin .room-plan-tag {
  display: inline-block;
  padding: 2px 9px;
  border-radius: 999px;
  border: 1px solid var(--border);
  background: var(--surface-2);
  color: var(--ink-mute);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.02em;
}
#view-admin .room-plan-tag.is-free { border-color: var(--accent); color: var(--accent); }
#view-admin .room-plan-tag.is-studio { border-color: var(--ink-soft); color: var(--ink-soft); }

/* ----- Place It: rooms above the artist's plan -----
   Locked rooms stay in the strip on purpose. Seeing the rest of the library is
   the nudge; they simply cannot be opened, so there is nothing on screen for a
   screenshot to take. Kept quiet so it reads as a library to grow into rather
   than a paywall shouting on every visit. */
.pi-room.is-locked { position: relative; opacity: 0.4; cursor: default; }
.pi-room.is-locked:hover { opacity: 0.62; border-color: rgba(255, 255, 255, 0.28); }
.pi-room.is-locked img { filter: grayscale(0.55); }
.pi-room-lock {
  position: absolute;
  left: 50%; bottom: 5px;
  transform: translateX(-50%);
  padding: 1px 7px;
  border-radius: 999px;
  background: rgba(0, 0, 0, 0.72);
  color: #fff;
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.03em;
  white-space: nowrap;
  pointer-events: none;
}
.pi-locked-note {
  margin: 8px 0 0;
  font-size: 12px;
  color: #8c8c8c;
}
.pi-upgrade-link {
  border: 0;
  background: none;
  padding: 0;
  font: inherit;
  color: var(--accent);
  font-weight: 600;
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 2px;
}
.pi-upgrade-link:hover { color: #fff; }

/* ---------------------------------------------------------------------------
   Place It: the on-screen frame around the work.

   This is HTML sitting on top of the canvas rather than paint on the canvas,
   so the frame, the size chip and the grip guide the artist while they work
   but never appear in the downloaded picture.
--------------------------------------------------------------------------- */
.pi-art-box {
  position: absolute;
  pointer-events: none;
  border: 1.5px solid rgba(147, 57, 148, 0.9);
  border-radius: 2px;
  box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.35);
}
.pi-size-chip {
  position: absolute;
  left: 50%;
  bottom: calc(100% + 8px);
  transform: translateX(-50%);
  white-space: nowrap;
  background: var(--accent);
  color: #fff;
  font-size: 12px;
  font-weight: 500;
  line-height: 1;
  padding: 5px 9px;
  border-radius: 999px;
  box-shadow: 0 1px 6px rgba(0, 0, 0, 0.35);
}
.pi-grip {
  position: absolute;
  right: -9px;
  bottom: -9px;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: #fff;
  border: 2px solid var(--accent);
  box-shadow: 0 1px 5px rgba(0, 0, 0, 0.4);
  cursor: nwse-resize;
  pointer-events: auto;
  touch-action: none;
}
.pi-grip.is-sizing { transform: scale(1.15); }
.pi-canvas-wrap.is-loading .pi-art-box { display: none; }

.pi-reset-size {
  background: none;
  border: 0;
  padding: 0;
  margin-left: 4px;
  font: inherit;
  color: #cfa7d0;
  text-decoration: underline;
  cursor: pointer;
}
.pi-reset-size:hover { color: #fff; }

/* Place It -- Match The Room's Light.
   Sits under the size hint, quiet by default. The switch reads as a switch
   rather than a button so it is obvious it has an on and an off. */
.pi-light {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  gap: 6px 14px;
  margin: 6px 0 0;
}
.pi-light-btn {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  padding: 4px 4px 4px 0;
  border: 0;
  background: none;
  cursor: pointer;
  font: inherit;
  font-size: var(--text-sm);
  color: rgba(255, 255, 255, 0.92);
}
.pi-light-track {
  position: relative;
  display: inline-block;
  width: 34px;
  height: 19px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.22);
  transition: background 0.18s ease;
}
.pi-light-btn.is-on .pi-light-track { background: var(--accent); }
.pi-light-knob {
  position: absolute;
  top: 2.5px;
  left: 2.5px;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: #fff;
  transition: transform 0.18s ease;
}
.pi-light-btn.is-on .pi-light-knob { transform: translateX(15px); }
.pi-light-note {
  font-size: var(--text-xs);
  color: rgba(255, 255, 255, 0.55);
}
@media (max-width: 640px) {
  .pi-light { gap: 4px; }
  .pi-light-note { flex-basis: 100%; text-align: center; }
}

/* Add Another Work — deliberately outside the Work Details card so it reads as
   "start a new work", not as a control belonging to the work on screen. */
.editor-addanother {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  flex-wrap: wrap;
  margin-top: calc(var(--space-4) * -1);
}
.editor-addanother .muted { font-size: var(--text-sm); }
@media (max-width: 1100px) {
  .editor-grid > .editor-addanother { order: 3; }
  .editor-grid > .editor-preview > .hr,
  .editor-grid > .editor-preview > .library-head,
  .editor-grid > .editor-preview > .editor-list { order: 4; }
}

/* "This section is hidden" note inside Site Settings → Public Site */
.ps-hidden-note {
  background: var(--surface-3);
  border: 1px solid var(--border-soft);
  border-radius: var(--radius-md);
  padding: 10px 12px;
  margin-bottom: var(--space-4);
  font-size: var(--text-sm);
  color: var(--ink-mute);
}

/* Long artist names: each word is one unbreakable unit, so the hero name can
   wrap at a space but never mid-word. Paired with the fitHeroName() sizing. */
.public-hero h1 { overflow-wrap: normal; word-break: normal; }
.public-hero h1 .ph-word { display: inline-block; white-space: nowrap; }

/* ── Signed-out gate ───────────────────────────────────────────────────────
   Nothing in the app is visible until the artist signs in. The shell stays in
   the DOM so the app can still render into it, but it is hidden and a simple
   sign-in gate takes its place. */
body.folio-locked .shell { display: none !important; }
body.folio-locked #modal { display: none !important; }
body.folio-locked .fo-checklist { display: none !important; }
.folio-gate {
  position: fixed;
  inset: 0;
  z-index: 9000;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  background: var(--bg, #fcfaf7);
}
.folio-gate-card {
  width: 100%;
  max-width: 460px;
  text-align: center;
}
.folio-gate-mark svg { width: 96px; height: auto; fill: var(--ink, #2B2F2D); }
.folio-gate-card h1 {
  font-family: var(--font-display);
  font-size: clamp(24px, 4vw, 32px);
  font-weight: 600;
  line-height: 1.2;
  margin: 20px 0 10px;
  color: var(--ink, #2B2F2D);
}
.folio-gate-card p {
  margin: 0 0 24px;
  color: var(--ink-mute, #7a7e78);
  font-size: var(--text-sm);
  line-height: 1.6;
}
.folio-gate-actions {
  display: flex;
  gap: 10px;
  justify-content: center;
  flex-wrap: wrap;
}

/* ── Public Site screen header actions ─────────────────────────────────── */
.ps-head-actions { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }

/* ── Toggle pills read their own live state ────────────────────────────────
   The label text used to be baked in at render time, so switching a toggle
   left the wording stale until the page redrew. Both wordings now ship in the
   markup and CSS picks the right one straight off the checkbox. */
.ps-publish-toggle .ps-publish-pill .pill-on { display: none; }
.ps-publish-toggle .ps-publish-pill .pill-off { display: inline; }
.ps-publish-toggle input:checked + .ps-publish-pill .pill-on { display: inline; }
.ps-publish-toggle input:checked + .ps-publish-pill .pill-off { display: none; }

/* ── Printed invoice: "This invoice was made with folio." ──────────────── */
.inv-doc-madewith {
  margin-top: 34px;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  font-size: 9pt;
  color: #7a7e78;
}
.inv-doc-wordmark { width: 40px; height: auto; fill: #2B2F2D; }

/* ── Site Settings: unsaved-changes save bar ───────────────────────────────
   Slides up from the bottom of the screen only when something has changed, so
   long settings pages don't force a scroll to the very bottom to save. */
.settings-savebar {
  position: fixed;
  left: 152px;
  right: 0;
  bottom: 0;
  z-index: 90;
  padding: 12px 24px calc(12px + env(safe-area-inset-bottom, 0px));
  background: var(--surface);
  border-top: 1px solid var(--border);
  box-shadow: 0 -6px 20px rgba(43, 47, 45, 0.06);
  transform: translateY(120%);
  opacity: 0;
  pointer-events: none;
  transition: transform 220ms ease, opacity 220ms ease;
}
.settings-savebar.is-open { transform: translateY(0); opacity: 1; pointer-events: auto; }
.settings-savebar-inner {
  max-width: 1100px;
  margin: 0 auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
}
.settings-savebar-text { font-size: var(--text-sm); color: var(--ink-soft); }
.settings-savebar-actions { display: flex; gap: 8px; flex-shrink: 0; }
body:has(.shell.sidebar-collapsed) .settings-savebar { left: 64px; }
@media (max-width: 900px) {
  .settings-savebar { left: 0; padding: 10px 16px calc(10px + env(safe-area-inset-bottom, 0px)); }
  .settings-savebar-text { font-size: var(--text-xs); }
}
@media (prefers-reduced-motion: reduce) {
  .settings-savebar { transition: none; }
}

/* ── CTA Banner: quick-pick platform buttons ───────────────────────────── */
.cta-quickpick { margin: 4px 0 14px; }
.cta-quickpick-head { display: flex; flex-direction: column; gap: 2px; margin-bottom: 8px; }
.cta-quickpick-title { font-size: var(--text-sm); font-weight: 600; color: var(--ink); }
.cta-quickpick-note { font-size: var(--text-xs); color: var(--ink-mute); }
.cta-quickpick-row { display: flex; flex-wrap: wrap; gap: 8px; }
.cta-qp-btn {
  width: 38px; height: 38px;
  display: inline-flex; align-items: center; justify-content: center;
  padding: 0;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--surface);
  color: var(--ink-soft);
  cursor: pointer;
  transition: border-color 140ms ease, color 140ms ease, background 140ms ease;
}
.cta-qp-btn svg { width: 18px; height: 18px; display: block; }
.cta-qp-btn:hover { border-color: var(--accent); color: var(--accent); }
.cta-qp-btn.is-active { border-color: var(--accent); color: var(--accent); background: var(--surface-3); }

/* ── Invoice preview (Sample Invoice / Preview Invoice) ────────────────────
   Shows the same document the printer gets, on a white page against a soft
   grey desk, so artists can look before they print or send. */
.inv-preview-card { width: min(880px, 100%); display: flex; flex-direction: column; max-height: 92vh; }
.inv-preview-body { background: var(--surface-3); padding: 16px; overflow: auto; flex: 1 1 auto; }
.inv-preview-note { margin: 0 0 12px; font-size: var(--text-xs); }
.inv-preview-page {
  background: #ffffff;
  padding: 44px 48px;
  max-width: 760px;
  margin: 0 auto;
  box-shadow: 0 2px 14px rgba(43, 47, 45, 0.12);
}
.inv-preview-foot {
  display: flex; justify-content: flex-end; gap: 8px;
  padding: 14px 20px;
  border-top: 1px solid var(--border);
  background: var(--surface);
  flex: 0 0 auto;
}
@media screen and (max-width: 700px) {
  .inv-preview-body { padding: 10px; }
  .inv-preview-page { padding: 22px 20px; }
  .inv-preview-page .inv-doc { font-size: 10pt; }
  .inv-preview-page .inv-doc-top { flex-direction: column; gap: 14px; }
}

/* ── Add Another Work: sit under the Work Details card, not beside it ──────
   The editor is a two-column grid, so this button was landing in the top of
   the right-hand column on its own, floating in empty space. Pin the form and
   the button to the left column and let the artwork column span both rows. */
@media (min-width: 1101px) {
  .editor-grid > .editor-form { grid-column: 1; grid-row: 1; }
  .editor-grid > .editor-addanother { grid-column: 1; grid-row: 2; margin-top: 0; }
  .editor-grid > .editor-preview { grid-column: 2; grid-row: 1 / span 2; }
}

/* ── CTA icon: file-type hint under the tile ───────────────────────────── */
.cta-icon-col { display: flex; flex-direction: column; gap: 8px; align-items: flex-start; }
.cta-icon-hint { font-size: var(--text-xs); color: var(--ink-mute); max-width: 150px; line-height: 1.4; }

/* CTA link box when the button points at the artist's own inquiries form —
   there is no address to type, so the box is fixed and read-only. */
.cta-link-fixed { background: var(--surface-3); color: var(--ink-mute); cursor: default; }

/* Editor columns: the Library list makes the right column very tall. Without
   this the Work Details card stretched to match it, leaving a big empty gap
   under Save Work and pushing Add Another Work far down the page. */
@media (min-width: 1101px) {
  .editor-grid { align-items: start; }
  .editor-grid > .editor-form,
  .editor-grid > .editor-addanother { align-self: start; }
}

/* Add New Work sits beside the ADD WORK title, clear of the Work Details card,
   so it never reads as a control belonging to the work being edited. */
.section-head.editor-head {
  display: grid;
  grid-template-columns: 1fr 1.05fr;
  gap: var(--space-5);
  align-items: center;
}
.editor-head .section-kicker { grid-column: 1; grid-row: 1; justify-self: start; align-self: center; }
.editor-head .editor-addanother { grid-column: 1; grid-row: 1; justify-self: end; align-self: center; margin-top: 0; }
@media (max-width: 1100px) {
  .section-head.editor-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-3);
    flex-wrap: wrap;
  }
  .editor-head .editor-addanother { grid-column: auto; }
}

/* ── Full-screen writing sheet (phones) ───────────────────────────────────
   Tapping Description or Artist Notes on a phone opens this instead of
   squinting at four lines. Sits above the fixed sign-in bar (z-index 9997). */
body.fs-editor-lock { overflow: hidden; }
.fs-editor {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  height: 100dvh;
  z-index: 10050;
  display: flex;
  flex-direction: column;
  background: var(--surface);
  overscroll-behavior: contain;
  touch-action: none;
}
.fs-editor-bar {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: 10px 14px;
  border-bottom: 1px solid var(--border);
  background: var(--surface-2);
  padding-top: calc(10px + env(safe-area-inset-top, 0px));
}
.fs-editor-titles { flex: 1 1 auto; min-width: 0; text-align: center; }
.fs-editor-title {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 15px;
  color: var(--ink);
  line-height: 1.2;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.fs-editor-hint {
  font-size: var(--text-xs);
  color: var(--ink-mute);
  margin-top: 1px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.fs-editor-cancel,
.fs-editor-done {
  flex: 0 0 auto;
  border: 0;
  background: transparent;
  font-family: inherit;
  font-size: 15px;
  padding: 6px 4px;
  cursor: pointer;
  border-radius: var(--radius-md);
}
.fs-editor-cancel { color: var(--ink-mute); }
.fs-editor-done { color: var(--accent); font-weight: 600; }
.fs-editor-area {
  flex: 1 1 auto;
  width: 100%;
  border: 0;
  outline: none;
  resize: none;
  background: var(--surface);
  color: var(--ink);
  font-family: inherit;
  font-size: 16px;
  line-height: 1.6;
  padding: 16px 16px 8px;
  -webkit-appearance: none;
  overflow-y: auto;
  overscroll-behavior: contain;
  touch-action: pan-y;
  -webkit-overflow-scrolling: touch;
  min-height: 0;
}
.fs-editor-foot {
  flex: 0 0 auto;
  padding: 8px 16px calc(10px + env(safe-area-inset-bottom, 0px));
  border-top: 1px solid var(--border-soft);
  background: var(--surface-2);
}
.fs-editor-count { font-size: var(--text-xs); color: var(--ink-mute); }

/* ── Place It: room-light intensity slider ────────────────────────────────
   Replaces the old on/off switch. Full on could read as washed out and full
   off as pasted on, so the artist now dials in the amount that looks right. */
.pi-light-dial {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  transition: opacity 0.18s ease;
}
.pi-light-dial.is-off { opacity: 0.35; pointer-events: none; }
.pi-light-range {
  -webkit-appearance: none;
  appearance: none;
  width: 130px;
  height: 4px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.25);
  outline: none;
  cursor: pointer;
  flex: 0 0 auto;
}
.pi-light-range::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: var(--accent);
  border: 2px solid #fff;
  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.12);
  cursor: pointer;
}
.pi-light-range::-moz-range-thumb {
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: var(--accent);
  border: 2px solid #fff;
  cursor: pointer;
}
.pi-light-range:focus-visible { box-shadow: 0 0 0 3px rgba(147, 57, 148, 0.25); }
/* Fixed width and tabular figures so the row never shifts as the number
   changes -- that reflow was what made the slider feel like it was slipping. */
.pi-light-pct {
  font-size: var(--text-sm);
  color: rgba(255, 255, 255, 0.92);
  font-variant-numeric: tabular-nums;
  width: 42px;
  text-align: left;
  flex: 0 0 auto;
}
@media (max-width: 640px) {
  .pi-light-range { width: 100%; flex: 1 1 120px; }
  .pi-light-pct { min-width: 36px; }
}

/* The signed-in bar is pinned above the whole page, which left it covering the
   close button on the artwork pop-up. Drop it behind while a pop-up is open. */
body.folio-modal-open .folio-auth-bar { z-index: 40; }

/* Contact section as shown on the Public Site tab — a picture of the form, so
   the fields are visibly inactive rather than pretending to work. */
.public-frame .pcf-form--preview input,
.public-frame .pcf-form--preview textarea,
.public-frame .pcf-form--preview .pcf-submit {
  cursor: default;
  opacity: 0.75;
}
.public-frame .pcf-preview-note {
  margin: 14px 0 0;
  text-align: center;
  font-size: var(--text-xs);
  color: var(--ink-mute);
}

/* Same fix as above, but not dependent on which script opened the pop-up —
   inside the Folio app the preview opens its own copy. Whenever a pop-up is
   open anywhere, the signed-in bar steps behind it so the close button is
   reachable. */
body:not(:has(.shell)):has(#modal:not([hidden])) .folio-auth-bar { z-index: 40; }

/* Keep the contact sentence from dropping a single word onto its own line. */
.public-frame .public-contact .pcf-intro {
  text-wrap: balance;
  text-wrap: pretty;
}

/* Inside Folio, the Public Site tab's artwork pop-up stays in the preview area
   instead of covering the whole window, so the Folio menu and the signed-in
   bar remain visible behind it. Scoped to the app shell — on the artist's own
   live site the pop-up is still full screen, as it should be. */
body:has(.shell) .modal:has(.modal-card.is-public) {
  top: var(--pv-top, 70px);
  left: var(--pv-left, 152px);
  right: var(--pv-right, 0px);
  bottom: var(--pv-bottom, 0px);
}
/* The full-screen card sizes itself to the window, which would burst straight
   back out of the preview box. Inside the app it fills its container instead. */
body:has(.shell) .modal:has(.modal-card.is-public) .modal-card.is-public {
  width: 100%;
  height: 100%;
  max-height: 100%;
}
@media (max-width: 820px) {
  body:has(.shell) .modal:has(.modal-card.is-public) { top: 0; left: 0; right: 0; bottom: 0; }
}

/* The close button is pinned to the window in full-screen mode, which puts it
   outside the preview box. Inside the app it sits in the card's own corner. */
body:has(.shell) .modal:has(.modal-card.is-public) .modal-card.is-public .modal-close {
  position: absolute;
  top: 18px;
  right: 18px;
}

/* Switch on the left, strength on the right, on one line that never reflows. */
.pi-light { flex-wrap: nowrap; gap: 18px; }
.pi-light-text { white-space: nowrap; }
@media (max-width: 640px) {
  .pi-light { flex-wrap: wrap; gap: 8px 12px; justify-content: center; }
  .pi-light-range { width: 110px; }
}

/* The contact sentence reads as one line wherever it fits, rather than
   dropping "in touch." on its own. */
.public-frame .public-contact .pcf-intro {
  max-width: 820px;
  text-wrap: pretty;
}

/* Inside the Public Site preview the sticky nav sits below Folio's own signed-in
   bar, so anchors need to clear both, not just the nav. */
.public-frame--admin-preview [id] { scroll-margin-top: 150px; }

/* Sections skipped over during a nav jump appear without their entrance
   animation, so dozens of them don't animate at once mid-glide. */
.public-frame [data-reveal].reveal-instant {
  animation: none !important;
  transition: none !important;
  opacity: 1 !important;
  transform: none !important;
}
