/* ==================================================================
   BUSINESS DASHBOARD STYLES
   Matches the Guide palette (rust / evergreen / cream). Loaded ONLY
   on /dashboard/* pages. Keeps the marketing site's CSS untouched.
   ================================================================== */

:root {
  --ink: #241f1a;
  --paper: #f3ece0;
  --card: #fffaf1;
  --rail: #0e3b2c;
  --rail-deep: #0a2d21;
  --ember: #d96c2c;
  --line: #d6c9b2;
  --muted: #5a4f3d;
  --shadow: 0 10px 30px rgba(20, 50, 38, .13);
  --verified: #3f6e44;
  --danger: #a85a22;
}

* { box-sizing: border-box; margin: 0; padding: 0; }
html { -webkit-text-size-adjust: 100%; }
body {
  font-family: 'Spline Sans', -apple-system, BlinkMacSystemFont, sans-serif;
  font-size: 1rem;
  background: var(--paper);
  color: var(--ink);
  line-height: 1.6;
  min-height: 100vh;
}
h1, h2, h3 { font-family: 'Fraunces', Georgia, serif; line-height: 1.15; font-weight: 800; }
a { color: var(--rail); }

.nl-nav {
  background: var(--rail-deep); color: var(--paper);
  padding: 0.9rem 1.25rem;
  display: flex; align-items: center; gap: 1rem; flex-wrap: wrap;
}
/* Brand matches site .brand exactly: Fraunces 900, cream "Northlander"
   + gold "Guide", SVG train mark in a rusty-brown disc. Consistent
   across the site + dashboard so the shell reads as one product. */
.nl-nav .nl-brand { font-family: 'Fraunces', serif; font-weight: 900; font-size: 1.18rem; text-decoration: none; color: #f3ece0; letter-spacing: -0.01em; display: flex; align-items: center; gap: 0; }
.nl-nav .nl-brand span { color: #dca33c; font-style: normal; }
.nl-nav .nl-brand .brand-mark { display: flex; flex-shrink: 0; line-height: 0; margin-right: 0.5rem; }
.nl-nav .nl-brand .brand-mark svg { display: block; }
.nl-nav .nl-nav-links { display: flex; gap: 0.9rem; flex-wrap: wrap; flex: 1; }
/* Login-page variant: no nav links, so Back to site should sit
   right-justified against the userEmail/signout area. */
.nl-nav .nl-nav-links.is-solo { justify-content: flex-end; }
.nl-nav .nl-nav-links a { color: var(--paper); opacity: 0.82; text-decoration: none; font-size: 0.95rem; }
.nl-nav .nl-nav-links a:hover, .nl-nav .nl-nav-links a.active { opacity: 1; text-decoration: underline; }
.nl-nav .nl-nav-user { font-size: 0.85rem; opacity: 0.75; }
.nl-nav .nl-nav-signout { background: transparent; border: 1px solid rgba(255,255,255,0.3); color: var(--paper); padding: 0.35rem 0.75rem; border-radius: 4px; cursor: pointer; font-size: 0.85rem; }
.nl-nav .nl-nav-signout:hover { background: rgba(255,255,255,0.1); }

.nl-page {
  max-width: 900px; margin: 0 auto; padding: 2rem 1.25rem 4rem;
}
/* Listings page runs wider so the form + live-preview sidebar can
   sit side-by-side on desktop. Falls back to the normal 900px on
   narrow viewports via the grid stacking below. */
.nl-page.nl-page-listings { max-width: 1240px; }
.nl-edit-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 380px;
  gap: 2rem;
  align-items: start;
}
.nl-edit-grid > .nl-card { margin-bottom: 0; }
@media (max-width: 960px) {
  .nl-edit-grid { grid-template-columns: 1fr; gap: 1.5rem; }
}

/* Live preview sidebar. Sticks to the top on desktop so the owner
   sees their changes reflected as they type. On mobile it stacks
   below the form (not sticky, since the form is long). */
.nl-edit-preview { min-width: 0; }
.nl-preview-sticky {
  position: sticky; top: 5rem;
}
@media (max-width: 960px) {
  .nl-preview-sticky { position: static; }
}
.nl-preview-panel {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 1.15rem 1.15rem 1.3rem;
  box-shadow: var(--shadow);
}
.nl-preview-label {
  display: inline-flex; align-items: center; gap: .4rem;
  font-size: .72rem; font-weight: 700;
  letter-spacing: .08em; text-transform: uppercase;
  color: var(--ember);
  padding: .3rem .6rem;
  background: rgba(217, 108, 44, 0.10);
  border-radius: 999px;
}
.nl-preview-context {
  margin: .55rem 0 1rem;
  font-size: .82rem; color: var(--muted);
  line-height: 1.4;
}
.nl-preview-tiernote {
  margin-top: .9rem; padding: .6rem .7rem;
  background: rgba(217, 108, 44, 0.06);
  border-left: 3px solid var(--ember);
  border-radius: 4px;
  font-size: .78rem; color: var(--ink); line-height: 1.45;
}

/* The preview card visually mirrors the public stop-page card
   (sp-lcard). Colours and shape are close approximations; not
   pixel-identical to avoid coupling the dashboard bundle to
   stop-page.css. */
.nl-preview-card {
  background: #f6efe2; /* poster-ivory */
  border: 1px solid #d9c9a8;
  border-radius: 6px;
  overflow: hidden;
  font-family: 'Spline Sans', system-ui, sans-serif;
  color: #2d2820;
}
.nl-preview-photo {
  aspect-ratio: 16 / 9;
  background: #e6d9bd center/cover no-repeat;
  border-bottom: 1px solid rgba(0,0,0,.06);
  display: flex; align-items: center; justify-content: center;
  color: #a1957a; font-size: .82rem; font-style: italic;
}
.nl-preview-photo.is-empty { background: repeating-linear-gradient(45deg, #ede2c6, #ede2c6 8px, #e6d9bd 8px, #e6d9bd 16px); }
/* Gallery nav overlay: hidden when only one photo, floats on top of
   the photo bottom-right when 2+ so owners can preview each photo
   without leaving the dashboard. Cycles via the wired arrow buttons
   which bump photoIdx and call render(). */
.nl-preview-photo-wrap { position: relative; }
.nl-preview-gallery-nav {
  position: absolute; bottom: .5rem; right: .5rem;
  display: flex; align-items: center; gap: .3rem;
  background: rgba(20, 15, 10, .55);
  color: #f3ece0;
  border-radius: 999px;
  padding: .15rem .3rem;
  font-size: .78rem;
  backdrop-filter: blur(3px);
}
.nl-preview-gallery-btn {
  background: transparent; border: 0; color: inherit;
  width: 1.6rem; height: 1.6rem;
  display: inline-flex; align-items: center; justify-content: center;
  cursor: pointer; border-radius: 50%;
  transition: background .12s ease;
}
.nl-preview-gallery-btn:hover { background: rgba(255,255,255,.15); }
.nl-preview-gallery-btn i { font-size: 1rem; }
.nl-preview-gallery-counter {
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  padding: 0 .2rem;
}
.nl-preview-body { padding: .8rem .9rem 1rem; }
.nl-preview-top {
  display: flex; align-items: center; justify-content: space-between;
  gap: .6rem; margin-bottom: .5rem;
}
.nl-preview-pills {
  display: inline-flex; align-items: center; gap: .35rem; flex-wrap: wrap;
}
.nl-preview-tag {
  display: inline-block; padding: .2rem .55rem;
  font-size: .68rem; font-weight: 700; letter-spacing: .06em;
  text-transform: uppercase;
  background: rgba(125, 58, 30, .08);
  color: #7d3a1e;
  border-radius: 999px;
}
.nl-preview-featured {
  display: inline-flex; align-items: center; gap: .25rem;
  padding: .2rem .55rem; font-size: .68rem; font-weight: 700;
  letter-spacing: .06em; text-transform: uppercase;
  background: #d9a53c; color: #2d2820;
  border-radius: 999px;
}
.nl-preview-featured i { font-size: .8rem; }
.nl-preview-rating {
  display: inline-flex; align-items: center; gap: .25rem;
  padding: .2rem .55rem; font-size: .78rem; font-weight: 700;
  background: rgba(0,0,0,.08); color: #2d2820;
  border-radius: 999px;
}
.nl-preview-rating.nl-preview-rating-new {
  background: rgba(63, 110, 68, 0.14); color: #3f6e44;
  font-size: .68rem; letter-spacing: .06em; text-transform: uppercase;
}
.nl-preview-discount {
  display: flex; align-items: center; gap: .4rem;
  margin: 0 0 .55rem;
  padding: .4rem .55rem;
  background: rgba(63, 110, 68, 0.10);
  color: #2f5a37; border-radius: 4px;
  font-size: .82rem; line-height: 1.35;
}
.nl-preview-discount i { color: #3f6e44; }
.nl-preview-name {
  font-family: 'Fraunces', Georgia, serif;
  font-weight: 600; font-size: 1.15rem; line-height: 1.2;
  margin: 0 0 .55rem;
  display: flex; align-items: center; gap: .5rem; flex-wrap: wrap;
}
.nl-preview-verified {
  display: inline-flex; align-items: center; gap: .25rem;
  padding: .2rem .5rem; font-size: .68rem; font-weight: 700;
  letter-spacing: .06em; text-transform: uppercase;
  background: rgba(63, 110, 68, 0.14); color: #3f6e44;
  border-radius: 999px;
}
.nl-preview-verified i { font-size: .78rem; }
.nl-preview-info { display: flex; flex-direction: column; gap: .3rem; }
.nl-preview-info-row {
  display: grid; grid-template-columns: 4.5rem 1fr; gap: .4rem;
  font-size: .82rem; line-height: 1.35;
}
.nl-preview-info-label {
  font-size: .68rem; font-weight: 700; letter-spacing: .06em;
  text-transform: uppercase; color: #7a6f5d;
  padding-top: .1rem;
}
.nl-preview-info-value { color: #2d2820; word-break: break-word; }
.nl-page h1 { font-size: 2rem; margin-bottom: 0.5rem; }
.nl-page .nl-lede { color: var(--muted); margin-bottom: 2rem; }

.nl-card {
  background: var(--card); border: 1px solid var(--line); border-radius: 8px;
  padding: 1.5rem; margin-bottom: 1.25rem; box-shadow: var(--shadow);
}
.nl-card h2 { font-size: 1.3rem; margin-bottom: 0.75rem; }

/* Account recovery card. Collapsed by default so it does not compete
   with the primary login form for attention; opens to reveal the two
   recovery paths (spam check + email support). */
.nl-recovery { padding: 0; }
.nl-recovery summary {
  cursor: pointer; padding: 1rem 1.5rem;
  color: var(--ink); font-size: 0.95rem;
  list-style: none; display: flex; align-items: center; justify-content: space-between; gap: 1rem;
  transition: background 0.15s ease;
}
.nl-recovery summary::-webkit-details-marker { display: none; }
.nl-recovery summary::after {
  content: '+'; color: var(--rail); font-size: 1.4rem; line-height: 1;
  flex: none; transition: transform 0.2s ease;
}
.nl-recovery details[open] summary { background: rgba(0, 0, 0, 0.02); }
.nl-recovery details[open] summary::after { content: '\2212'; }
.nl-recovery summary:hover { background: rgba(0, 0, 0, 0.03); }
.nl-recovery-body {
  padding: 0 1.5rem 1.4rem; border-top: 1px solid var(--line);
  padding-top: 1rem;
}
.nl-recovery-body p { margin: 0 0 0.7rem; color: var(--ink); font-size: 0.92rem; line-height: 1.55; }
.nl-recovery-body ul { margin: 0.2rem 0 1rem; padding-left: 1.4rem; color: var(--ink); font-size: 0.92rem; line-height: 1.6; }
.nl-recovery-body ul li { margin-bottom: 0.2rem; }
.nl-recovery-body .nl-btn { display: inline-flex; align-items: center; gap: 0.4rem; text-decoration: none; }
/* Recovery form. Sits inside the collapsible, matches the login-form
   field styles so both feel like part of the same auth surface. */
.nl-recover-form { margin: 0.8rem 0 1rem; }
.nl-recover-form .nl-field { margin-bottom: 0.8rem; }
.nl-recover-form .nl-two-col { display: grid; grid-template-columns: 1fr 1fr; gap: 0.7rem; }
.nl-recover-form .nl-two-col label { display: block; font-weight: 600; font-size: 0.9rem; margin-bottom: 0.35rem; color: var(--ink); }
.nl-recover-form .nl-two-col input { width: 100%; padding: 0.6rem 0.75rem; border: 1px solid var(--line); border-radius: 4px; font: inherit; background: #fff; color: var(--ink); }
@media (max-width: 480px) { .nl-recover-form .nl-two-col { grid-template-columns: 1fr; } }
.nl-recover-form .nl-btn { display: inline-block; margin-top: 0.3rem; }
.nl-recover-msg { margin: 0.7rem 0 0; font-size: 0.88rem; color: var(--muted); min-height: 1.3em; line-height: 1.5; }
.nl-recover-msg.is-ok { color: #2d5a35; font-weight: 600; }
.nl-recover-msg.is-err { color: var(--danger, #a1341f); }
.nl-recover-fallback { margin-top: 1.2rem; padding-top: 1rem; border-top: 1px dashed var(--line); font-size: 0.85rem; line-height: 1.55; }

/* Post-claim recovery setup card. Sits at the top of the listings
   page for owners who have not set a backup email yet. Gold-tinted
   background so it reads as "a friendly nudge, do this once" rather
   than an error. */
/* Warm welcome card shown above the required backup-email card
   for first-time owners. Same paper background as .nl-card but
   with a rusty ember accent + orientation checklist so the moment
   feels like a "you're in" rather than "here's your first chore." */
.nl-welcome-card {
  background: var(--card);
  border-left: 4px solid var(--ember, #d96c2c);
  position: relative;
}
.nl-welcome-card h2 {
  font-family: 'Fraunces', Georgia, serif;
  margin-top: .25rem; color: var(--ink);
}
.nl-welcome-kicker {
  font-size: .68rem; font-weight: 700; letter-spacing: .16em;
  text-transform: uppercase; color: var(--ember, #d96c2c);
  margin-bottom: .35rem;
}
.nl-welcome-list {
  list-style: none; padding: 0; margin: 0;
  display: flex; flex-direction: column; gap: .55rem;
}
.nl-welcome-list li {
  display: flex; align-items: flex-start; gap: .65rem;
  font-size: .92rem; line-height: 1.4; color: var(--ink);
}
.nl-welcome-list li i {
  font-size: 1.1rem; color: var(--ember, #d96c2c);
  margin-top: .1rem; flex: none;
}

.nl-recovery-setup { background: #fff8ea; border-color: rgba(220, 163, 60, 0.5); position: relative; }
.nl-recovery-setup h2 { color: var(--ink); font-family: 'Fraunces', Georgia, serif; margin-top: 0; }
/* "Required" pill at top-right so it reads as gated on first glance. */
.nl-recovery-required-badge {
  position: absolute; top: 1rem; right: 1rem;
  background: var(--rail, #0a2d21); color: #f3ece0;
  font-size: 0.68rem; font-weight: 700; letter-spacing: 0.16em;
  text-transform: uppercase; padding: 0.3rem 0.65rem; border-radius: 3px;
}
/* Old .nl-recovery-warning removed 2026-07-25 in favour of the
   softer .nl-recovery-tip below. The blunt alert-style box read as
   scary for a brand-new owner; the tip block explains the same
   trade-off in warmer copy. */
/* Inline "same email as sign-in" notice — informational only. The
   acknowledgment sits below and is always required regardless of
   which email they chose. */
.nl-recovery-inline-warn {
  background: rgba(217, 108, 44, 0.08); border-left: 3px solid #d96c2c;
  padding: 0.7rem 0.9rem; margin: 0.4rem 0 0.4rem; border-radius: 4px;
  font-size: 0.9rem; line-height: 1.5; color: var(--ink);
}
.nl-recovery-inline-warn strong { color: #a1341f; }
/* Softer "save both somewhere safe" nudge. Warm amber tint, no
   scary vocabulary. Explains the trade-off subtly through the
   "no manual recovery" line rather than shouting it. */
.nl-recovery-tip {
  background: rgba(220, 163, 60, 0.10);
  border-left: 3px solid var(--ember, #d96c2c);
  padding: 0.85rem 1rem;
  margin: 1rem 0 1.2rem;
  border-radius: 4px;
  color: var(--ink);
  font-size: 0.92rem;
  line-height: 1.6;
}
.nl-recovery-tip strong { color: var(--rail, #0a2d21); }
/* Acknowledgment checkbox row — always shown, always required. */
.nl-recovery-ack {
  display: flex; align-items: flex-start; gap: 0.55rem;
  margin: 0.8rem 0 1rem; padding: 0.65rem 0.85rem;
  background: rgba(0, 0, 0, 0.03); border-radius: 4px;
  font-size: 0.92rem; line-height: 1.5; color: var(--ink); cursor: pointer;
}
.nl-recovery-ack input[type="checkbox"] {
  flex: none; margin-top: 0.2rem; width: 16px; height: 16px; cursor: pointer;
}

.nl-field { margin-bottom: 1rem; }
.nl-field label { display: block; font-weight: 600; font-size: 0.9rem; margin-bottom: 0.35rem; color: var(--ink); }
.nl-field input, .nl-field textarea, .nl-field select {
  width: 100%; padding: 0.6rem 0.75rem; border: 1px solid var(--line); border-radius: 4px;
  font: inherit; background: #fff; color: var(--ink);
}
.nl-field input:focus, .nl-field textarea:focus { outline: 2px solid var(--rail); outline-offset: -1px; }
.nl-field input[disabled], .nl-field textarea[disabled] { background: var(--paper); color: var(--muted); cursor: not-allowed; }
.nl-field textarea { min-height: 6rem; resize: vertical; font-family: inherit; }
.nl-field .nl-help { font-size: 0.82rem; color: var(--muted); margin-top: 0.35rem; }
.nl-field-inline { display: flex; align-items: center; gap: 0.5rem; }
.nl-field-inline input[type="checkbox"] { width: auto; }

/* Character counter shown below capped text fields. Colour ramps
   as the writer approaches the cap; the inline upsell only shows
   for Free/Onboard when they've written more than their tier
   allows but the next tier would fit it. */
.nl-char-count {
  display: flex; justify-content: space-between; align-items: baseline; gap: .5rem;
  font-size: .78rem; color: var(--muted); margin-top: .3rem;
  font-variant-numeric: tabular-nums;
}
.nl-char-count.is-warn { color: #8a6b1c; }
.nl-char-count.is-over { color: var(--danger); font-weight: 600; }
.nl-char-upsell {
  margin: .35rem 0 0; font-size: .82rem;
  padding: .55rem .7rem; border-radius: 4px;
  background: rgba(217, 108, 44, 0.10);
  border-left: 3px solid var(--ember);
  color: var(--ink);
}
.nl-char-upsell a { color: var(--ember); font-weight: 600; }

/* Seven-day hours picker. One row per day; each row is:
   [day label] [Open? checkbox] [from time] [-] [to time].
   When "Open?" is unchecked the times dim and read "Closed". */
.nl-hours-grid { display: flex; flex-direction: column; gap: .45rem; }
.nl-hours-row {
  display: grid;
  grid-template-columns: 6.5rem auto 1fr auto 1fr;
  align-items: center;
  gap: .55rem;
  padding: .35rem .5rem;
  border-radius: 4px;
  background: rgba(217, 108, 44, 0.04);
}
.nl-hours-day { font-weight: 600; font-size: .9rem; color: var(--ink); }
.nl-hours-toggle {
  display: inline-flex; align-items: center; gap: .35rem;
  font-size: .82rem; color: var(--muted);
}
.nl-hours-toggle input { width: auto !important; margin: 0; }
.nl-hours-row input[type="time"] {
  width: 100% !important;
  padding: .4rem .5rem !important;
  font-family: inherit; font-size: .9rem;
}
.nl-hours-dash { color: var(--muted); text-align: center; }
.nl-hours-row.is-closed input[type="time"] {
  opacity: .35; pointer-events: none;
}
.nl-hours-row.is-closed .nl-hours-closed-label {
  grid-column: 3 / -1;
  color: var(--muted); font-style: italic; font-size: .9rem;
}
.nl-hours-row.is-closed .nl-hours-dash,
.nl-hours-row.is-closed input[type="time"] { display: none; }
.nl-hours-row:not(.is-closed) .nl-hours-closed-label { display: none; }
.nl-hours-legacy {
  margin-top: .6rem;
  padding: .6rem .75rem;
  background: rgba(220, 163, 60, 0.12);
  border-left: 3px solid #b98a2c;
  border-radius: 4px;
  font-size: .82rem; color: var(--ink);
}
.nl-hours-legacy strong { display: block; margin-bottom: .2rem; }
@media (max-width: 480px) {
  .nl-hours-row {
    grid-template-columns: 5.5rem 1fr auto 1fr;
    gap: .3rem .35rem;
  }
  .nl-hours-toggle {
    grid-column: 1 / -1;
    justify-self: start;
    padding-left: .25rem;
  }
  .nl-hours-row.is-closed .nl-hours-closed-label { grid-column: 2 / -1; }
}

.nl-btn {
  display: inline-block; padding: 0.7rem 1.4rem;
  background: var(--rail); color: var(--paper); border: 0; border-radius: 4px;
  font: inherit; font-weight: 600; cursor: pointer; text-decoration: none;
}
.nl-btn:hover { background: var(--rail-deep); }
.nl-btn.nl-btn-secondary { background: transparent; color: var(--rail); border: 1px solid var(--rail); }
.nl-btn.nl-btn-secondary:hover { background: var(--rail); color: var(--paper); }
.nl-btn.nl-btn-danger { background: var(--danger); }
.nl-btn.nl-btn-danger:hover { background: #8b3f16; }
.nl-btn.nl-busy { opacity: 0.5; pointer-events: none; }
.nl-btn[disabled] { opacity: 0.5; cursor: not-allowed; }

.nl-badge {
  display: inline-flex; align-items: center; gap: 0.35rem;
  padding: 0.2rem 0.55rem; border-radius: 999px;
  font-size: 0.8rem; font-weight: 600;
}
.nl-badge.nl-badge-verified { background: rgba(63, 110, 68, 0.12); color: var(--verified); }
.nl-badge.nl-badge-pending { background: rgba(220, 163, 60, 0.14); color: #8a6b1c; }
.nl-badge.nl-badge-tier { background: rgba(217, 108, 44, 0.14); color: var(--ember); text-transform: capitalize; }

.nl-photo-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 0.75rem; margin-top: 1rem; }
.nl-photo-tile { position: relative; border-radius: 6px; overflow: hidden; border: 1px solid var(--line); background: var(--paper); aspect-ratio: 4 / 3; cursor: grab; }
.nl-photo-tile:active { cursor: grabbing; }
.nl-photo-tile.nl-photo-dragging { opacity: 0.4; }
.nl-photo-tile.nl-photo-drop-target { outline: 3px dashed var(--rail); outline-offset: -3px; }
.nl-photo-tile img { width: 100%; height: 100%; object-fit: cover; display: block; pointer-events: none; }
.nl-photo-tile .nl-photo-drag { position: absolute; top: 6px; left: 6px; background: rgba(0,0,0,0.6); color: white; border-radius: 4px; padding: 2px 6px; font-size: 14px; line-height: 1; pointer-events: none; user-select: none; }
.nl-photo-tile .nl-photo-del { position: absolute; top: 6px; right: 6px; background: rgba(0,0,0,0.6); color: white; border: 0; border-radius: 999px; width: 26px; height: 26px; font-size: 14px; cursor: pointer; line-height: 26px; padding: 0; }
.nl-photo-tile .nl-photo-del:hover { background: rgba(0,0,0,0.85); }
.nl-photo-tile.nl-photo-empty { display: flex; align-items: center; justify-content: center; color: var(--muted); border-style: dashed; cursor: pointer; text-align: center; padding: 1rem; font-size: 0.85rem; }

.nl-claim-row {
  display: flex; justify-content: space-between; align-items: center; gap: 1rem;
  padding: 1rem; border: 1px solid var(--line); border-radius: 4px; background: var(--card);
  margin-bottom: 0.75rem;
}
.nl-claim-row .nl-claim-info strong { display: block; }
.nl-claim-row .nl-claim-info small { color: var(--muted); }
.nl-claim-row .nl-claim-info .nl-claim-email { display: block; margin-top: 0.15rem; }
.nl-claim-row .nl-claim-actions { display: flex; gap: 0.5rem; }

.nl-toast {
  position: fixed; bottom: 24px; left: 50%; transform: translateX(-50%) translateY(120%);
  padding: 0.9rem 1.4rem; border-radius: 6px;
  background: var(--rail-deep); color: var(--paper);
  box-shadow: var(--shadow); z-index: 9999; opacity: 0; transition: opacity 0.2s, transform 0.2s;
  max-width: 90vw; text-align: center; font-size: 0.95rem;
}
.nl-toast.nl-toast-visible { opacity: 1; transform: translateX(-50%) translateY(0); }
.nl-toast.nl-toast-error { background: var(--danger); }
.nl-toast.nl-toast-success { background: var(--verified); }

.nl-empty { color: var(--muted); text-align: center; padding: 3rem 1rem; font-style: italic; }
.nl-loading { color: var(--muted); text-align: center; padding: 3rem 1rem; }

@media (max-width: 640px) {
  .nl-nav { padding: 0.75rem 1rem; }
  .nl-page { padding: 1.5rem 1rem 3rem; }
  .nl-card { padding: 1rem; }
}

/* ==================================================================
   Bottom upgrade CTA (Free-tier only). Rust left rule + list of
   locked features + rust "Start a 14-day trial" button. Companion
   to the small dismissible nudge at the top of the page.
   ================================================================== */
.nl-upgrade-cta {
  border-left: 4px solid var(--ember);
  background: linear-gradient(180deg, #fffaf1 0%, #fdf5e5 100%);
  margin-top: 1.6rem;
}
.nl-upgrade-cta .nl-upgrade-kicker {
  font-size: .68rem; font-weight: 700; color: var(--ember);
  text-transform: uppercase; letter-spacing: .18em; margin: 0 0 .5rem;
}
.nl-upgrade-cta h3 {
  font-family: 'Fraunces', Georgia, serif; font-size: 1.35rem;
  font-weight: 600; margin: 0 0 .8rem; color: var(--ink);
}
.nl-upgrade-list {
  list-style: none; padding: 0; margin: 0 0 1.2rem;
  color: var(--ink); font-size: .95rem; line-height: 1.65;
}
.nl-upgrade-list li {
  padding: .35rem 0 .35rem 1.6rem; position: relative;
}
.nl-upgrade-list li::before {
  content: '\2713'; position: absolute; left: 0; top: .35rem;
  color: var(--verified); font-weight: 700; font-size: 1rem;
}
.nl-upgrade-list li strong { color: var(--ink); }
.nl-upgrade-list li em { color: var(--ember); font-style: italic; }
.nl-upgrade-actions {
  display: flex; gap: .8rem; align-items: center; flex-wrap: wrap;
}
.nl-upgrade-fine {
  color: var(--muted); font-size: .82rem;
}

/* Pending photo tile: dashed gold outline + 60% opacity so it reads
   as "in review" without looking broken. No drag, no delete affordance;
   an admin approves or rejects via the review-edit page. */
.nl-photo-tile.nl-photo-tile-pending {
  position: relative; opacity: .78;
  outline: 2px dashed var(--ember); outline-offset: -2px;
  cursor: default;
}
.nl-photo-tile.nl-photo-tile-pending img { filter: saturate(.85); }
.nl-photo-pending-badge {
  position: absolute; left: 6px; bottom: 6px;
  background: rgba(217,166,72,.95); color: #2d2820;
  font-size: .68rem; font-weight: 700; letter-spacing: .1em;
  text-transform: uppercase; padding: 3px 8px; border-radius: 3px;
  pointer-events: none;
}

/* Website URL field with locked "https://" visual prefix so owners
   only type the domain. Server side (api/dashboard-listing.js
   normalizeWebsite) prepends the scheme on save. Matches the
   .ef-url-group pattern on the public submit form. */
.nl-url-group {
  display: flex; align-items: stretch;
  background: var(--paper, #f6efe2);
  border: 1.5px solid var(--line); border-radius: 4px;
  overflow: hidden;
  transition: border-color .15s ease;
}
.nl-url-group:focus-within { border-color: var(--poster-crimson, #8e3d22); }
.nl-url-prefix {
  padding: .65rem .55rem .65rem .8rem;
  color: var(--muted, #7a6f5d);
  font-size: .92rem;
  background: rgba(125, 58, 30, 0.05);
  border-right: 1px solid var(--line);
  user-select: none;
  white-space: nowrap;
  display: flex; align-items: center;
}
.nl-url-group input {
  flex: 1 1 auto; min-width: 0;
  border: 0 !important; padding: .65rem .8rem !important;
  background: transparent !important;
  font-family: inherit; font-size: .95rem;
  color: var(--ink);
}
.nl-url-group input:focus { outline: none !important; border: 0 !important; }

/* Request-a-change modal (Locked fields section). Native <dialog>
   so we get the browser's focus trap + Escape-closes + backdrop
   for free. Styled to match the dashboard palette. */
.nl-modal {
  border: 0;
  padding: 0;
  background: transparent;
  max-width: 520px;
  width: calc(100% - 32px);
}
.nl-modal::backdrop {
  background: rgba(10, 45, 33, 0.42);
  backdrop-filter: blur(2px);
}
.nl-modal-form {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 1.6rem 1.6rem 1.2rem;
  position: relative;
  box-shadow: 0 24px 60px rgba(10, 45, 33, .3);
}
.nl-modal-form h3 {
  font-family: 'Fraunces', Georgia, serif;
  font-weight: 700;
  font-size: 1.4rem;
  margin: 0 0 .5rem;
  color: var(--ink);
}
.nl-modal-form textarea {
  width: 100%;
  min-height: 140px;
  padding: .7rem .85rem;
  border: 1.5px solid var(--line);
  border-radius: 4px;
  font-family: inherit;
  font-size: .95rem;
  line-height: 1.55;
  color: var(--ink);
  background: var(--paper);
  resize: vertical;
}
.nl-modal-form textarea:focus {
  outline: none;
  border-color: var(--rail);
}
.nl-modal-close {
  position: absolute;
  top: .75rem; right: .85rem;
  background: transparent;
  border: 0;
  font-size: 1.4rem;
  line-height: 1;
  color: var(--muted);
  cursor: pointer;
  padding: .25rem .5rem;
  border-radius: 3px;
}
.nl-modal-close:hover { color: var(--ink); background: rgba(0,0,0,.05); }
.nl-modal-actions {
  display: flex; gap: .6rem; justify-content: flex-end;
  margin-top: 1rem;
  flex-wrap: wrap;
}

/* Tabs above the preview panes. Toggles Card <> Detail view. */
.nl-preview-tabs {
  display: flex;
  gap: .3rem;
  margin: .8rem 0 .9rem;
  padding: .25rem;
  background: rgba(217, 108, 44, 0.06);
  border-radius: 6px;
}
.nl-preview-tab {
  flex: 1; padding: .45rem .5rem;
  background: transparent; border: 0;
  font: inherit; font-size: .82rem; font-weight: 600;
  color: var(--muted);
  border-radius: 4px; cursor: pointer;
  transition: background .12s ease, color .12s ease;
}
.nl-preview-tab:hover { color: var(--ink); }
.nl-preview-tab.is-active {
  background: var(--card); color: var(--ember);
  box-shadow: 0 1px 3px rgba(0,0,0,.06);
}
.nl-preview-pane[hidden] { display: none; }

/* Detail-view pane. Mirrors the public site's detail modal shape. */
.nl-preview-detail {
  background: #f6efe2; /* poster-ivory */
  border: 1px solid #d9c9a8;
  border-radius: 6px;
  overflow: hidden;
  font-family: 'Spline Sans', system-ui, sans-serif;
  color: #2d2820;
}
.nl-preview-detail-hero {
  aspect-ratio: 16 / 9;
  background: #e6d9bd center/cover no-repeat;
  border-bottom: 1px solid rgba(0,0,0,.06);
  display: flex; align-items: center; justify-content: center;
  color: #a1957a; font-size: .82rem; font-style: italic;
}
.nl-preview-detail-hero.is-empty {
  background: repeating-linear-gradient(45deg, #ede2c6, #ede2c6 8px, #e6d9bd 8px, #e6d9bd 16px);
}
.nl-preview-detail-discount {
  display: flex; align-items: center; gap: .4rem;
  padding: .5rem .75rem;
  background: rgba(63, 110, 68, 0.10);
  color: #2f5a37;
  font-size: .82rem; line-height: 1.35;
}
.nl-preview-detail-discount i { color: #3f6e44; }
.nl-preview-detail-body { padding: .8rem .9rem 1rem; }
.nl-preview-detail-toprow {
  display: flex; align-items: center; justify-content: space-between;
  gap: .6rem; margin: 0 0 .5rem;
}
.nl-preview-detail-name {
  font-family: 'Fraunces', Georgia, serif;
  font-weight: 600; font-size: 1.15rem; line-height: 1.2;
  margin: 0 0 .5rem;
}
.nl-preview-detail-desc {
  font-size: .88rem; line-height: 1.5;
  color: var(--ink); margin: 0 0 .7rem;
}
.nl-preview-detail-desc.is-placeholder { color: #a1957a; font-style: italic; }
.nl-preview-detail-info { display: flex; flex-direction: column; gap: .3rem; }
