/* ══════════════════════════════════════════════════════════════════════════
   Specialty Items — specialty-items.html + js/specialty-items.js.

   The cards, grid, stepper, status box and skeletons are css/catalog.css's
   `ss-` components, loaded first, so a specialty item looks like everything
   else the shop sells. This file adds only what that page doesn't have:
   sections (one per seller), the admin-mode controls, and the edit dialog.

   Colors are the site tokens plus the few fixed hues catalog.css already
   uses for the same meanings — #2e6b3f for "on", #b42318 for errors and
   destructive actions, #565150 slate for "switched off" — so one state never
   wears two colors across the two pages.
   ══════════════════════════════════════════════════════════════════════════ */

/* ── Hero: the Admin mode toggle (admins only) ── */
.sp-hero-tools { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; margin-top: 1.75rem; }
.sp-admin {
  display: inline-flex; align-items: center; gap: 0.45rem;
  padding: 0.35rem 0.75rem;
  border: 1px solid var(--border); border-radius: 999px; cursor: pointer;
  font-size: 0.74rem; font-weight: 700; letter-spacing: 0.04em;
  color: var(--text-muted); background: var(--card); user-select: none;
  transition: border-color 0.15s, color 0.15s, background 0.15s;
}
.sp-admin:hover { border-color: var(--accent); color: var(--text); }
.sp-admin input { margin: 0; accent-color: var(--accent); }
.sp-admin.is-on { border-color: var(--accent); color: var(--accent); background: var(--accent-dim); }

/* ── Admin bar, above the sections while admin mode is on ── */
.sp-admin-bar {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 0.75rem 1.25rem;
  margin-bottom: 2rem; padding: 0.85rem 1rem;
  background: #eef4fb; border: 1px dashed #90b4dc; border-radius: 8px;
}
.sp-admin-bar-note { margin: 0; font-size: 0.84rem; line-height: 1.5; color: var(--text); max-width: 640px; }
.sp-admin-bar-note strong { color: #0d4f99; }

/* ── Sections: one per seller ── */
.sp-section + .sp-section { margin-top: 3.25rem; }
.sp-section-head {
  display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between; gap: 0.75rem 1.5rem;
  margin-bottom: 1.25rem; padding-bottom: 0.75rem; border-bottom: 1px solid var(--border);
}
.sp-section-titles { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.35rem 0.85rem; min-width: 0; }
.sp-section-title {
  margin: 0; font-family: var(--ff-display); font-size: clamp(1.4rem, 2.6vw, 1.9rem);
  line-height: 1.15; color: var(--text); overflow-wrap: anywhere;
}
.sp-section-count { font-size: 0.78rem; color: var(--text-muted); white-space: nowrap; }
.sp-section-tools { display: flex; flex-wrap: wrap; align-items: center; gap: 0.4rem; }
.sp-section-tools .btn-admin { padding: 0.4rem 0.85rem; font-size: 0.7rem; }

/* An empty seller — admin-only; the customer view never carries one. */
.sp-section-empty {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 0.75rem 1.25rem;
  padding: 1.5rem 1.25rem; border: 1px dashed var(--border); border-radius: 8px; background: var(--surface);
}
.sp-section-empty p { margin: 0; font-size: 0.88rem; color: var(--text-muted); max-width: 520px; }

/* Small secondary buttons for admin actions: quiet until hovered, so a row of
   them reads as tools beside the content rather than competing with it. */
.sp-tool {
  font: inherit; font-size: 0.72rem; font-weight: 700; letter-spacing: 0.02em;
  padding: 0.3rem 0.65rem; border-radius: 999px; cursor: pointer;
  border: 1px solid var(--border); background: var(--card); color: var(--text-muted);
  white-space: nowrap; transition: border-color 0.15s, color 0.15s, background 0.15s;
}
.sp-tool:hover { border-color: #1565c0; color: #1565c0; }
.sp-tool--danger:hover { border-color: #b42318; color: #b42318; }
.sp-tool[disabled] { opacity: 0.4; cursor: default; pointer-events: none; }
/* Share is for everyone, so it hovers in the site's accent, not the admin blue. */
.sp-share:hover { border-color: var(--accent); color: var(--accent); }

/* Above a one-seller page (a deep link): the way back to everything. */
.sp-crumb { margin: 0 0 1rem; font-size: 0.84rem; font-weight: 700; }
.sp-crumb a { color: var(--text-muted); text-decoration: none; }
.sp-crumb a:hover { color: var(--accent); text-decoration: underline; }

/* ── Cards ── */
/* No detail page to read the rest on, so the description gets three lines
   instead of the catalog title's two, and keeps the line breaks the admin
   typed. The full text rides on the title attribute for a hover. */
.sp-card-desc {
  margin: 0.25rem 0 0; font-size: 0.8rem; line-height: 1.45; color: var(--text-muted);
  white-space: pre-line; overflow-wrap: anywhere;
  display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden;
}
/* The sale's dates — the deadline on a customer's card, "goes on sale…" or
   "ended…" on an admin's. Plain text color, not --text-dim: on a fundraiser
   the end date is the reason to order today, and it has to be read. */
.sp-card-when {
  margin: 0.35rem 0 0; font-size: 0.74rem; font-weight: 700; line-height: 1.4; color: var(--text);
}

/* The foot is price on top, then the size picker on its own row, then
   stepper + button. On a two-up phone card (~140px of foot) the button drops
   under the stepper instead of squeezing. */
.sp-card .ss-card-foot { align-items: center; }
.sp-buy { flex: 1 1 100%; display: flex; flex-wrap: wrap; align-items: stretch; gap: 0.4rem; }
.sp-buy .ss-qty button { min-height: 2rem; }
.sp-buy .btn { flex: 1 1 auto; justify-content: center; padding: 0.5rem 0.75rem; }
.sp-size {
  flex: 1 1 100%; min-width: 0; font: inherit; font-size: 0.84rem; font-weight: 600; color: var(--text);
  padding: 0.42rem 0.55rem; border: 1.5px solid var(--border); border-radius: 6px;
  background: var(--card); cursor: pointer;
}
.sp-size:focus { outline: none; border-color: var(--accent); }
/* Add was pressed with no size picked. Error red, the same as the note below. */
.sp-size.is-missing { border-color: #b42318; background: #fdeceb; }
/* iOS Safari zooms the page into any control under 16px, select included. */
@media (pointer: coarse) { .sp-size { font-size: 1rem; } }

/* The photo is a button that opens the viewer. It fills the image box so the
   catalog's `.ss-card-img img` sizing still applies to the picture inside. */
.sp-zoom {
  position: relative; display: block; width: 100%; height: 100%;
  padding: 0; border: 0; background: none; cursor: zoom-in; font: inherit;
}
.sp-zoom:focus-visible { outline: 2px solid var(--accent); outline-offset: -4px; border-radius: 4px; }
.sp-zoom-badge {
  position: absolute; right: 0.45rem; bottom: 0.45rem;
  display: flex; align-items: center; justify-content: center;
  width: 1.7rem; height: 1.7rem; border-radius: 50%;
  color: var(--text); background: rgba(255, 255, 255, 0.92);
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.18); transition: color 0.15s, transform 0.15s;
}
.sp-zoom:hover .sp-zoom-badge { color: var(--accent); transform: scale(1.08); }

/* "Hidden" over a switched-off item's photo. Slate, like the catalog's
   switched-off badge — not red, which means "sold out" on the other page. */
.sp-off-tag {
  position: absolute; right: 0.45rem; top: 0.45rem; z-index: 2;
  font-size: 0.62rem; font-weight: 800; letter-spacing: 0.04em;
  color: #fff; background: #565150; border-radius: 5px; padding: 0.1rem 0.4rem;
}
/* "Scheduled" is the admin's blue — nothing's wrong, it's waiting on a date. */
.sp-off-tag--soon { background: #2a5d8f; }

/* The admin strip under a card. Tinted the same blue as the admin bar so it
   reads as "controls only you can see", never as part of the listing. */
.sp-card-admin {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 0.4rem 0.5rem;
  padding: 0.5rem 0.85rem; background: #eef4fb; border-top: 1px dashed #90b4dc;
}
.sp-card-admin-btns { display: inline-flex; gap: 0.3rem; }

/* The Enabled switch. A real checkbox underneath (keyboard, screen readers,
   the change event the script listens for), drawn as a track and knob. */
.sp-switch {
  position: relative; display: inline-flex; align-items: center; gap: 0.4rem;
  cursor: pointer; user-select: none;
}
.sp-switch input {
  position: absolute; opacity: 0; width: 1px; height: 1px; margin: 0; pointer-events: none;
}
.sp-switch-track {
  position: relative; flex-shrink: 0; width: 30px; height: 17px; border-radius: 999px;
  background: #8f8985; transition: background 0.15s;
}
.sp-switch-track::after {
  content: ''; position: absolute; top: 2px; left: 2px; width: 13px; height: 13px;
  border-radius: 50%; background: #fff; box-shadow: 0 1px 2px rgba(0, 0, 0, 0.25);
  transition: transform 0.15s;
}
.sp-switch input:checked + .sp-switch-track { background: #2e6b3f; }
.sp-switch input:checked + .sp-switch-track::after { transform: translateX(13px); }
.sp-switch input:focus-visible + .sp-switch-track { outline: 2px solid var(--accent); outline-offset: 2px; }
.sp-switch input:disabled + .sp-switch-track { opacity: 0.5; }
.sp-switch-text { font-size: 0.72rem; font-weight: 700; color: var(--text); }

@media (prefers-reduced-motion: reduce) {
  .sp-switch-track, .sp-switch-track::after { transition: none; }
}

/* ══ The dialog — add/edit an item, add/rename a seller ══════════════════
   Above the fixed site header (z-index 1000) and below sdAlert/sdConfirm
   (99999), which have to be able to open OVER it to report a failed save. */
html.sp-modal-open { overflow: hidden; }
.sp-modal {
  position: fixed; inset: 0; z-index: 2000;
  display: flex; align-items: center; justify-content: center;
  padding: 1rem; background: rgba(30, 27, 24, 0.55);
  overflow-y: auto; overscroll-behavior: contain;
}
.sp-modal-card {
  width: 100%; max-width: 560px; max-height: calc(100vh - 2rem); overflow-y: auto;
  margin: auto; background: var(--card); border: 1px solid var(--border); border-radius: 12px;
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.25); padding: 1.35rem 1.5rem 1.5rem;
}
.sp-modal-head { display: flex; align-items: center; justify-content: space-between; gap: 1rem; margin-bottom: 1.1rem; }
.sp-modal-head h3 { margin: 0; font-family: var(--ff-display); font-size: 1.35rem; color: var(--text); }
.sp-modal-x {
  width: 2rem; height: 2rem; flex-shrink: 0; border: none; border-radius: 50%; cursor: pointer;
  background: transparent; color: var(--text-muted); font-size: 1.4rem; line-height: 1;
}
.sp-modal-x:hover { background: var(--surface-2); color: var(--accent); }

.sp-form { margin: 0; }
.sp-field { display: flex; flex-direction: column; gap: 0.35rem; margin-bottom: 1rem; min-width: 0; }
.sp-field-label {
  display: flex; align-items: baseline; justify-content: space-between; gap: 0.5rem;
  font-size: 0.64rem; font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase; color: var(--text-dim);
}
.sp-field-count { font-weight: 600; letter-spacing: 0; text-transform: none; font-variant-numeric: tabular-nums; }
.sp-field-hint { font-size: 0.76rem; line-height: 1.45; color: var(--text-muted); margin: 0; }
/* 1rem, not smaller: iOS Safari zooms the whole page into any field whose
   text is under 16px, and doesn't zoom back out when the dialog closes. */
.sp-field input[type="text"], .sp-field input[type="datetime-local"], .sp-field textarea, .sp-field select {
  width: 100%; font: inherit; font-size: 1rem; color: var(--text);
  padding: 0.55rem 0.7rem; border: 1.5px solid var(--border); border-radius: 6px; background: var(--surface);
  transition: border-color 0.15s, background 0.15s;
}
.sp-field textarea { resize: vertical; min-height: 4.5rem; line-height: 1.45; }
.sp-field input[type="text"]:focus, .sp-field input[type="datetime-local"]:focus,
.sp-field textarea:focus, .sp-field select:focus {
  outline: none; border-color: var(--accent); background: var(--white);
}

/* The sale window: Starts and Ends side by side, stacking by themselves once
   the dialog is too narrow for two date-and-time boxes. */
.sp-when { display: grid; grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr)); gap: 0.6rem 1rem; }
.sp-when-cell { display: flex; flex-direction: column; gap: 0.25rem; min-width: 0; }
.sp-when-sub { font-size: 0.78rem; font-weight: 700; color: var(--text); }
.sp-when-input { display: flex; align-items: center; gap: 0.4rem; }
.sp-when-input input { min-width: 0; flex: 1 1 auto; }
.sp-when-clear {
  flex-shrink: 0; padding: 0.3rem 0.2rem; border: none; background: none; cursor: pointer;
  font: inherit; font-size: 0.78rem; font-weight: 700; color: var(--accent); text-decoration: underline;
}
.sp-when-clear:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 3px; }
.sp-field-row { display: grid; grid-template-columns: 9.5rem minmax(0, 1fr); gap: 0 1rem; }
.sp-money { position: relative; display: block; }
.sp-money > span {
  position: absolute; left: 0.7rem; top: 50%; transform: translateY(-50%);
  font-size: 1rem; color: var(--text-muted); pointer-events: none;
}
.sp-money input[type="text"] { padding-left: 1.5rem; font-variant-numeric: tabular-nums; }

.sp-photo { display: flex; align-items: center; gap: 1rem; margin-bottom: 1.15rem; }
.sp-photo-preview {
  flex-shrink: 0; width: 108px; aspect-ratio: 1 / 1.12; overflow: hidden;
  display: flex; align-items: center; justify-content: center;
  background: var(--white); border: 1px solid var(--border); border-radius: 8px;
}
.sp-photo-preview img { width: 100%; height: 100%; object-fit: contain; padding: 0.35rem; }
.sp-photo-preview .ss-noimg { text-align: center; padding: 0 0.4rem; }
.sp-photo-side { display: flex; flex-direction: column; align-items: flex-start; gap: 0.5rem; min-width: 0; }
.sp-photo-pick:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.sp-check {
  display: flex; align-items: flex-start; gap: 0.6rem; margin: 0.25rem 0 1rem; cursor: pointer;
  font-size: 0.85rem; line-height: 1.45; color: var(--text-muted);
}
.sp-check input { margin: 0.2rem 0 0; accent-color: #2e6b3f; flex-shrink: 0; }
.sp-check strong { color: var(--text); }

/* Sizes, as tickable chips. Real checkboxes underneath, the same way the
   Enabled switch is drawn; ticked wears the switch's "on" green. */
.sp-chips { display: flex; flex-wrap: wrap; gap: 0.35rem; }
.sp-chip { position: relative; cursor: pointer; user-select: none; }
.sp-chip input { position: absolute; opacity: 0; width: 1px; height: 1px; margin: 0; pointer-events: none; }
.sp-chip span {
  display: inline-block; padding: 0.3rem 0.65rem; border-radius: 999px;
  border: 1.5px solid var(--border); background: var(--surface); color: var(--text-muted);
  font-size: 0.78rem; font-weight: 700; white-space: nowrap;
  transition: border-color 0.15s, background 0.15s, color 0.15s;
}
.sp-chip:hover span { border-color: #2e6b3f; color: var(--text); }
.sp-chip input:checked + span { border-color: #2e6b3f; background: #2e6b3f; color: #fff; }
.sp-chip input:focus-visible + span { outline: 2px solid var(--accent); outline-offset: 2px; }

/* A price box per ticked 2XL+ size, two or three to a row. */
.sp-plus-rows { display: grid; grid-template-columns: repeat(auto-fill, minmax(8.5rem, 1fr)); gap: 0.5rem 0.85rem; }
.sp-plus-row { display: flex; align-items: center; gap: 0.5rem; min-width: 0; }
.sp-plus-size { flex: 0 0 2.4rem; font-size: 0.8rem; font-weight: 700; color: var(--text); }
.sp-plus-row .sp-money { flex: 1 1 auto; min-width: 0; }

.sp-form-error {
  margin: 0 0 1rem; padding: 0.55rem 0.75rem; border-radius: 6px;
  font-size: 0.82rem; line-height: 1.45; color: #b42318; background: #fdeceb;
}
.sp-form-actions { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 0.6rem; }

/* ══ The photo viewer ════════════════════════════════════════════════════
   Full screen, dark, the photo on its own white ground (a cut-out dark shirt
   would vanish into the backdrop otherwise). Same layer as the edit dialog —
   the two never open together. The photo's size is set by the script; see
   layoutViewer() for why it isn't max-width/max-height. */
.sp-viewer {
  position: fixed; inset: 0; z-index: 2000;
  display: grid; grid-template-rows: minmax(0, 1fr) auto;
  background: rgba(22, 19, 17, 0.95); color: #fff;
}
.sp-viewer-stage {
  position: relative; display: flex; min-height: 0; overflow: hidden;
  padding: 3.75rem 1rem 1rem; overscroll-behavior: contain;
}
.sp-viewer-stage img {
  flex: none; margin: auto; max-width: none; max-height: none;
  background: #fff; border-radius: 8px; cursor: zoom-in;
  user-select: none; -webkit-user-drag: none; -webkit-touch-callout: none;
  opacity: 0; transition: opacity 0.15s;
}
.sp-viewer.is-ready .sp-viewer-stage img { opacity: 1; }
.sp-viewer.is-zoomed .sp-viewer-stage { overflow: auto; padding: 0; }
.sp-viewer.is-zoomed .sp-viewer-stage img { border-radius: 0; cursor: zoom-out; }
.sp-viewer-stage.is-dragging, .sp-viewer-stage.is-dragging img { cursor: grabbing; }
.sp-viewer-err { margin: auto; max-width: 22rem; text-align: center; color: rgba(255, 255, 255, 0.8); }

.sp-viewer-x {
  position: absolute; top: max(0.6rem, env(safe-area-inset-top)); right: 0.6rem; z-index: 2;
  width: 2.75rem; height: 2.75rem; border: none; border-radius: 50%; cursor: pointer;
  background: rgba(0, 0, 0, 0.55); color: #fff; font-size: 1.7rem; line-height: 1;
}
.sp-viewer-x:hover { background: rgba(0, 0, 0, 0.8); }
.sp-viewer-x:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }

.sp-viewer-cap {
  max-height: 38vh; overflow-y: auto;
  padding: 0.85rem 1.25rem calc(1rem + env(safe-area-inset-bottom));
  border-top: 1px solid rgba(255, 255, 255, 0.12);
}
.sp-viewer-cap > * { max-width: 680px; margin-left: auto; margin-right: auto; }
.sp-viewer-title {
  display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 0.25rem 1rem;
  margin-top: 0; margin-bottom: 0.25rem; font-size: 1.05rem;
}
.sp-viewer-price { font-weight: 700; font-variant-numeric: tabular-nums; }
.sp-viewer-meta { margin-top: 0; margin-bottom: 0.2rem; font-size: 0.84rem; color: rgba(255, 255, 255, 0.75); }
.sp-viewer-desc {
  margin-top: 0.5rem; margin-bottom: 0; font-size: 0.88rem; line-height: 1.5;
  color: rgba(255, 255, 255, 0.88); white-space: pre-line; overflow-wrap: anywhere;
}
.sp-viewer-hint { margin-top: 0.6rem; margin-bottom: 0; font-size: 0.76rem; color: rgba(255, 255, 255, 0.6); }

/* Zoomed, the caption steps aside for the photo and this one line says how
   to get around — and back. */
.sp-viewer-zoomhint {
  display: none; position: absolute; left: 50%; bottom: calc(1rem + env(safe-area-inset-bottom)); z-index: 2;
  transform: translateX(-50%); margin: 0; padding: 0.35rem 0.85rem; border-radius: 999px;
  background: rgba(0, 0, 0, 0.6); color: #fff; font-size: 0.75rem; white-space: nowrap; pointer-events: none;
}
.sp-viewer.is-zoomed .sp-viewer-cap { display: none; }
.sp-viewer.is-zoomed .sp-viewer-zoomhint { display: block; }

@media (prefers-reduced-motion: reduce) {
  .sp-viewer-stage img, .sp-zoom-badge { transition: none; }
}

/* ── Narrow ── */
@media (max-width: 640px) {
  .sp-section + .sp-section { margin-top: 2.5rem; }
  .sp-section-head { align-items: flex-start; }
  .sp-admin-bar .btn-admin { width: 100%; justify-content: center; }
}
@media (max-width: 520px) {
  .sp-field-row { grid-template-columns: minmax(0, 1fr); }
  .sp-modal { padding: 0.5rem; align-items: flex-start; }
  .sp-modal-card { padding: 1.1rem 1rem 1.25rem; max-height: calc(100vh - 1rem); }
  .sp-photo-preview { width: 88px; }
  .sp-form-actions .btn { flex: 1 1 auto; justify-content: center; }
  /* A two-up card is ~150px wide: the admin strip stacks the switch over its
     two buttons rather than clipping one off the right edge. */
  .sp-card-admin { padding: 0.45rem 0.6rem; }
}
