/* ── Stitch Widget CSS ─────────────────────────────────────────────────
   All styles use --st-* custom properties for theming.
   Host pages set these via URL params from the SDK.
   ──────────────────────────────────────────────────────────────────── */

:root {
  /* ── Brand / Primary ── Stitch terracotta */
  --st-color-primary:        #b05030;
  --st-color-primary-hover:  #8d4026;
  --st-color-primary-light:  rgba(176, 80, 48, 0.09);

  /* ── Backgrounds ── warm off-whites */
  --st-color-bg:             #faf7f4;
  --st-color-surface:        #f2ede7;
  --st-color-surface-hover:  #ede6de;

  /* ── Form fields ── the fill every .st-input/select/textarea takes.
     Its own token rather than a raw --st-color-surface reference so a host
     can retune fields without also moving cards and buttons, and so the
     default tracks whatever palette that host already set. `.st-card` is
     --st-color-bg, the same as `body`, so a field filled with bg is its
     container's colour on every widget page — in a card and on bare body
     alike. Don't point these back at --st-color-bg. */
  --st-color-field:          var(--st-color-surface);
  --st-color-field-hover:    var(--st-color-surface-hover);

  /* ── Borders ── warm stone */
  --st-color-border:         #ddd7d0;
  --st-color-card-border:    transparent;

  /* ── Text ── warm near-blacks */
  --st-color-text:           #1c1917;
  /* Muted is contrast-gated: it must clear WCAG AA (4.5:1) against every
     surface it lands on — bg, surface, and surface-hover. The previous
     #78716c cleared none of them (4.49 / 4.12 / 3.88); this clears all
     three (5.45 / 5.00 / 4.70) and stays clearly muted against
     --st-color-text, which sits at 16.39:1. Don't lighten it back. */
  --st-color-text-muted:     #6b645e;

  /* ── Disabled ── */
  --st-color-disabled-bg:     #e9e3d7;
  --st-color-disabled-border: #d2cabb;
  --st-color-disabled-text:   #5f584d;

  /* ── Semantic states ── */
  --st-color-error:          #c0392b;
  --st-color-error-light:    rgba(192, 57, 43, 0.09);
  --st-color-success:        #2d7a4f;
  --st-color-success-light:  rgba(45, 122, 79, 0.09);
  --st-color-warning:        #b45309;
  --st-color-warning-light:  rgba(180, 83, 9, 0.09);

  /* ── Typography ── */
  --st-font-family:          'Inter', system-ui, -apple-system, sans-serif;
  --st-font-family-heading:  'Inter', system-ui, -apple-system, sans-serif;

  /* ── Shape ── */
  --st-radius:               10px;
  --st-radius-sm:            7px;
  --st-radius-pill:          999px;

  /* ── Spacing ── */
  --st-spacing:              16px;

  /* ── Shadows ── warm-tinted */
  --st-shadow-sm:            0 1px 3px rgba(28, 25, 23, 0.07), 0 1px 2px rgba(28, 25, 23, 0.04);
  --st-shadow:               0 4px 14px rgba(28, 25, 23, 0.10), 0 2px 4px rgba(28, 25, 23, 0.05);
  --st-shadow-lg:            0 12px 36px rgba(28, 25, 23, 0.15), 0 4px 8px rgba(28, 25, 23, 0.07);
  --st-card-shadow:          none;

  /* ── Focus ring ── */
  --st-ring-color:           rgba(176, 80, 48, 0.28);

  /* ── Motion ── */
  --st-transition:           150ms ease;

  /* ── Layout ── */
  --st-max-width:            none;

  /* ── Scrollbars ──
     The widget's scroll containers (#category-tree, the mobile filter sheet,
     modals) paint a *native* track, and the browser has no idea the host put
     us in a dark theme: this file declares no `prefers-color-scheme` block, so
     dark mode is entirely custom properties and `color-scheme` stays `normal`.
     Left alone the track renders the UA default — a near-white strip, cool
     against the warm bg in light mode and starkly wrong in dark. Their own
     tokens rather than raw references, following --st-color-field above, so a
     host can retune the scrollbar without moving borders and backgrounds with
     it; both track the host's palette (including its `-dark` pair) for free,
     since the theme script sets the tokens these point at. */
  --st-scrollbar-thumb:      var(--st-color-border);
  --st-scrollbar-track:      var(--st-color-bg);

  /* Inherited, so this single declaration reaches every scroll container in
     the widget — the ones above and any added later. Deliberately *not*
     paired with a ::-webkit-scrollbar block: defining that pseudo-element
     switches WebKit to classic always-visible scrollbars, which would take
     layout width out of the host's page on macOS where the default is an
     overlay. Safari below 18.2 keeps the native track, which is today's
     behaviour rather than a regression. */
  scrollbar-color: var(--st-scrollbar-thumb) var(--st-scrollbar-track);
}

/* ── Reset ─────────────────────────────────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

html {
  overflow: hidden;   /* suppress iframe scrollbars; height reported via postMessage */
}

body {
  font-family: var(--st-font-family);
  background: var(--st-color-bg);
  color: var(--st-color-text);
  font-size: 14px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  max-width: var(--st-max-width);
  margin-inline: auto;
}

/* ── Headings ──────────────────────────────────────────────────────── */
.st-heading    { font-size: 0.75rem; font-weight: 700; margin-bottom: 0; color: var(--st-color-text-muted); text-transform: uppercase; letter-spacing: 0.09em; }
.st-heading-sm { font-size: 0.9rem;  font-weight: 600; margin-bottom: 8px;  color: var(--st-color-text); }
/* Modifier of .st-heading: keeps its weight, muted colour and uppercase,
   only enlarging it and adding the gap beneath. */
.st-heading--section { font-size: 0.9rem; margin-bottom: 8px; }
.st-heading--card    { font-size: 1rem; }
.st-heading-md { font-size: 1rem;    font-weight: 600; margin: 0 0 6px;     color: var(--st-color-text); }
.st-heading-lg { font-size: 1.1rem;  font-weight: 600; margin: 0 0 6px;     color: var(--st-color-text); }

/* ── Buttons ───────────────────────────────────────────────────────── */
.st-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 8px 16px;
  border: 1px solid var(--st-color-border);
  border-radius: var(--st-radius-sm);
  background: var(--st-color-surface);
  color: var(--st-color-text);
  font-size: 0.85rem;
  font-weight: 500;
  font-family: inherit;
  cursor: pointer;
  text-decoration: none;
  white-space: nowrap;
  outline: none;
  transition: background var(--st-transition), border-color var(--st-transition),
              box-shadow var(--st-transition), transform var(--st-transition);
}
.st-btn:hover:not(:disabled)   { background: var(--st-color-surface-hover); }
.st-btn:active:not(:disabled)  { transform: translateY(1px); }
.st-btn:focus-visible          { box-shadow: 0 0 0 3px var(--st-ring-color); }
.st-btn:disabled               {
  background: var(--st-color-disabled-bg);
  border-color: var(--st-color-disabled-border);
  color: var(--st-color-disabled-text);
  box-shadow: none;
  cursor: not-allowed;
}

.st-btn-primary {
  background: var(--st-color-primary);
  color: #fff;
  border-color: var(--st-color-primary);
  box-shadow: 0 1px 4px rgba(176, 80, 48, 0.20);
}
.st-btn-primary:hover:not(:disabled) {
  background: var(--st-color-primary-hover);
  border-color: var(--st-color-primary-hover);
  box-shadow: 0 3px 10px rgba(176, 80, 48, 0.32);
}
.st-btn-primary:focus-visible {
  box-shadow: 0 0 0 3px var(--st-ring-color), 0 1px 4px rgba(176, 80, 48, 0.20);
}

.st-btn-outline {
  background: transparent;
  border-color: var(--st-color-border);
  color: var(--st-color-text);
}
.st-btn-outline:hover:not(:disabled) {
  background: var(--st-color-surface);
  border-color: var(--st-color-text-muted);
}

.st-btn-secondary {
  background: var(--st-color-primary-light);
  border-color: var(--st-color-primary);
  color: var(--st-color-primary);
  font-weight: 500;
}
.st-btn-secondary:hover:not(:disabled) {
  background: var(--st-color-primary-light);
  filter: brightness(0.94);
  border-color: var(--st-color-primary-hover);
  color: var(--st-color-primary-hover);
}
.st-btn-secondary:focus-visible {
  box-shadow: 0 0 0 3px var(--st-ring-color);
}

.st-btn-block { width: 100%; }
.st-btn-sm    { padding: 5px 12px; font-size: 0.82rem; height: 32px; }

.st-btn-link {
  display: inline-flex;
  align-items: center;
  background: none;
  border: none;
  color: var(--st-color-primary);
  font-size: 0.82rem;
  font-family: inherit;
  cursor: pointer;
  padding: 0;
  outline: none;
  text-decoration: none;
  transition: color var(--st-transition);
}
.st-btn-link:hover         { text-decoration: underline; }
.st-btn-link:focus-visible { outline: 2px solid var(--st-ring-color); border-radius: 2px; }

.st-link {
  color: var(--st-color-primary);
  cursor: pointer;
  text-decoration: underline;
  transition: color var(--st-transition);
}
.st-link:hover { color: var(--st-color-primary-hover); }

/* ── Cards ─────────────────────────────────────────────────────────── */
.st-card {
  background: var(--st-color-bg);
  border: 1px solid var(--st-color-card-border);
  border-radius: var(--st-radius);
  padding: var(--st-spacing);
  box-shadow: var(--st-card-shadow);
}

.st-card--highlight {
  border-color: var(--st-color-primary);
  background: var(--st-color-primary-light);
}

/* Weekly schedule calendar */
.st-cal {
  display: block;
  margin-top: 10px;
  overflow-x: auto;
  overflow-y: hidden;
  -webkit-overflow-scrolling: touch;
}
.st-cal-grid {
  display: grid;
  grid-template-columns: 72px repeat(var(--st-cal-days, 7), minmax(112px, 1fr));
  min-width: max-content;
  border: 1px solid var(--st-color-border);
  border-radius: var(--st-radius-sm);
  overflow: hidden;
}
.st-cal-empty {
  display: block;
  text-align: center;
  font-size: 0.66rem;
  color: var(--st-color-text-muted);
  padding-top: 8px;
}
.st-cal-item__title {
  display: block;
  font-size: 0.72rem;
  font-weight: 500;
  color: var(--st-color-text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: normal;
}
.st-cal-item__time {
  display: block;
  font-size: 0.65rem;
  color: var(--st-color-text-muted);
}

/* Transposed calendar variant (days vertical, time horizontal) */
.st-cal-grid--transposed {
  --st-cal-day-col: 74px;
  --st-cal-room-col: 84px;
  grid-template-columns: var(--st-cal-day-col) var(--st-cal-room-col) minmax(420px, 1fr);
}
.st-cal-head--day {
  text-align: left;
  position: sticky;
  left: 0;
  z-index: 5;
}
.st-cal-head--room {
  text-align: left;
  border-left: 1px solid var(--st-color-border);
  position: sticky;
  left: var(--st-cal-day-col);
  z-index: 4;
}
.st-cal-time-head {
  display: grid;
  grid-template-columns: repeat(var(--st-cal-hours), minmax(68px, 1fr));
  min-width: max-content;
  border-left: 1px solid var(--st-color-border);
  border-bottom: 1px solid var(--st-color-border);
  background: var(--st-color-surface);
}
.st-cal-time-slot {
  font-size: 0.65rem;
  font-weight: 600;
  color: var(--st-color-text-muted);
  text-align: center;
  padding: 6px 4px;
  border-left: 1px solid var(--st-color-border);
  line-height: 1.2;
}
.st-cal-time-slot:first-child {
  border-left: none;
}
.st-cal-day-label {
  font-size: 0.68rem;
  font-weight: 700;
  color: var(--st-color-text-muted);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  border-bottom: 1px solid var(--st-color-border);
  background: var(--st-color-surface);
  padding: 8px 6px;
  vertical-align: top;
  position: sticky;
  left: 0;
  z-index: 4;
}
.st-cal-room-label {
  font-size: 0.64rem;
  font-weight: 600;
  color: var(--st-color-text-muted);
  background: var(--st-color-surface);
  border-left: 1px solid var(--st-color-border);
  border-right: 1px solid var(--st-color-border);
  border-bottom: 1px solid var(--st-color-border);
  padding: 8px 6px;
  line-height: 1.2;
  position: sticky;
  left: var(--st-cal-day-col);
  z-index: 3;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.st-cal-room-track {
  position: relative;
  min-width: max-content;
  background: var(--st-color-bg);
  border-bottom: 1px solid var(--st-color-border);
  overflow: hidden;
}
.st-cal-day-hour-grid {
  position: absolute;
  inset: 0;
  display: grid;
  grid-template-columns: repeat(var(--st-cal-hours), minmax(68px, 1fr));
  pointer-events: none;
}
.st-cal-day-hour {
  border-left: 1px solid var(--st-color-border);
}
.st-cal-day-hour:first-child {
  border-left: none;
}
.st-cal-block {
  position: absolute;
  box-sizing: border-box;
  margin: 0;
  padding: 4px 5px;
  left: 0;
  top: 0;
  width: 100%;
  min-height: 18px;
  border-radius: var(--st-radius-sm);
  border: 1px solid color-mix(in srgb, var(--st-color-primary) 20%, transparent);
  background: color-mix(in srgb, var(--st-color-primary) 12%, var(--st-color-bg) 88%);
  z-index: 1;
  overflow: hidden;
}
.st-cal-block--h {
  z-index: 2;
}
.st-cal-block--h .st-cal-item__title {
  overflow: visible;
  text-overflow: clip;
  white-space: normal;
  overflow-wrap: anywhere;
  word-break: break-word;
  line-height: 1.15;
}
.st-cal-block--h .st-cal-item__time {
  white-space: nowrap;
}
.st-cal-empty--overlay {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
}

/* Inverted calendar layout (days + rooms horizontal, time vertical) */
.st-cal--by-day {
  overflow-x: visible;
}
.st-cal-days {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(430px, 100%), 1fr));
  gap: 10px;
  align-items: start;
}
.st-cal-day-panel {
  border: 1px solid var(--st-color-border);
  border-radius: var(--st-radius-sm);
  overflow-x: auto;
  overflow-y: hidden;
  background: var(--st-color-bg);
  -webkit-overflow-scrolling: touch;
}
.st-cal-day-title {
  font-size: 0.68rem;
  font-weight: 700;
  color: var(--st-color-text-muted);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  background: var(--st-color-surface);
  border-bottom: 1px solid var(--st-color-border);
  padding: 7px 8px;
}
.st-cal-day-shell {
  display: grid;
  grid-template-columns: 56px minmax(0, 1fr);
  grid-template-rows: auto auto;
}
.st-cal-corner {
  background: var(--st-color-surface);
  border-right: 1px solid var(--st-color-border);
  border-bottom: 1px solid var(--st-color-border);
}
.st-cal-room-heads {
  display: grid;
  grid-template-columns: repeat(var(--st-cal-rooms), minmax(96px, 1fr));
  min-width: max-content;
  border-bottom: 1px solid var(--st-color-border);
  background: var(--st-color-surface);
}
.st-cal-room-head {
  font-size: 0.62rem;
  font-weight: 600;
  color: var(--st-color-text-muted);
  padding: 7px 6px;
  border-left: 1px solid var(--st-color-border);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.st-cal-room-head:first-child {
  border-left: none;
}
.st-cal-time-col {
  border-right: 1px solid var(--st-color-border);
  background: var(--st-color-surface);
}
.st-cal-time-slot-v {
  height: var(--st-cal-hour-height, 44px);
  font-size: 0.62rem;
  font-weight: 600;
  color: var(--st-color-text-muted);
  text-align: right;
  padding: 4px 6px 0 4px;
  border-top: 1px solid var(--st-color-border);
  line-height: 1.1;
}
.st-cal-time-slot-v:first-child {
  border-top: none;
}
.st-cal-room-tracks {
  display: grid;
  grid-template-columns: repeat(var(--st-cal-rooms), minmax(96px, 1fr));
  min-width: max-content;
}
.st-cal-track-col {
  position: relative;
  border-left: 1px solid var(--st-color-border);
  background: var(--st-color-bg);
  overflow: hidden;
}
.st-cal-track-col:first-child {
  border-left: none;
}
.st-cal-hour-grid-v {
  position: absolute;
  inset: 0;
  display: grid;
  grid-template-rows: repeat(var(--st-cal-hours), var(--st-cal-hour-height, 44px));
  pointer-events: none;
}
.st-cal-hour-line {
  border-top: 1px solid var(--st-color-border);
}
.st-cal-hour-line:first-child {
  border-top: none;
}
.st-cal-block--v {
  z-index: 2;
}
.st-cal-block--v .st-cal-item__title {
  overflow: visible;
  text-overflow: clip;
  white-space: normal;
  overflow-wrap: anywhere;
  word-break: break-word;
  line-height: 1.15;
}
.st-cal-block--v .st-cal-item__time {
  white-space: nowrap;
}

@media (max-width: 1040px) {
  .st-cal-days {
    grid-template-columns: repeat(auto-fit, minmax(min(360px, 100%), 1fr));
  }
}

@media (max-width: 760px) {
  .st-cal-days {
    grid-template-columns: 1fr;
  }
  .st-cal-day-shell {
    grid-template-columns: 50px minmax(0, 1fr);
  }
  .st-cal-room-heads,
  .st-cal-room-tracks {
    grid-template-columns: repeat(var(--st-cal-rooms), minmax(88px, 1fr));
  }
  .st-cal-time-slot-v {
    font-size: 0.58rem;
    padding: 5px 2px;
  }
  .st-cal-day-title,
  .st-cal-room-head {
    font-size: 0.56rem;
    padding: 6px 4px;
  }

}

@media (max-width: 479px) {
  .st-cal-day-shell {
    grid-template-columns: 46px minmax(0, 1fr);
  }
  .st-cal-room-heads,
  .st-cal-room-tracks {
    grid-template-columns: repeat(var(--st-cal-rooms), minmax(78px, 1fr));
  }
}

/* ── Forms ──────────────────────────────────────────────────────────── */
.st-form-group { margin-bottom: 14px; }
.st-label {
  display: block;
  font-size: 0.8rem;
  font-weight: 600;
  margin-bottom: 5px;
  color: var(--st-color-text);
  letter-spacing: 0.01em;
}
.st-input {
  width: 100%;
  padding: 9px 12px;
  border: 1.5px solid var(--st-color-border);
  border-radius: var(--st-radius-sm);
  background: var(--st-color-field);
  color: var(--st-color-text);
  font-size: 0.875rem;
  font-family: inherit;
  line-height: 1.5;
  outline: none;
  transition: border-color var(--st-transition), box-shadow var(--st-transition),
              background var(--st-transition);
}
.st-input::placeholder          { color: var(--st-color-text-muted); opacity: 0.7; }
.st-input:hover:not(:focus)     { border-color: var(--st-color-text-muted); background: var(--st-color-field-hover); }
.st-input:focus                 { border-color: var(--st-color-primary); box-shadow: 0 0 0 3px var(--st-ring-color); }
.st-input[type="number"]::-webkit-outer-spin-button,
.st-input[type="number"]::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.st-input[type="number"] { -moz-appearance: textfield; appearance: textfield; }
.st-form-hint { font-size: 0.75rem; color: var(--st-color-text-muted); margin-top: 5px; line-height: 1.4; }

/* ── Spinner ───────────────────────────────────────────────────────── */
.st-loading { text-align: center; padding: 48px 16px; }
.st-spinner {
  display: inline-block;
  width: 26px; height: 26px;
  border: 2.5px solid var(--st-color-border);
  border-top-color: var(--st-color-primary);
  border-radius: 50%;
  animation: st-spin 0.65s linear infinite;
}
@keyframes st-spin { to { transform: rotate(360deg); } }

/* ── Empty state ───────────────────────────────────────────────────── */
.st-empty {
  text-align: center;
  padding: 56px 16px;
  color: var(--st-color-text-muted);
}
.st-empty svg { opacity: 0.3; }
.st-empty p   { margin-top: 14px; font-size: 0.9rem; }

/* ── Tag chips ─────────────────────────────────────────────────────── */
.st-tag {
  display: inline-flex;
  align-items: center;
  padding: 2px 9px;
  border-radius: var(--st-radius-pill);
  font-size: 0.73rem;
  font-weight: 600;
  letter-spacing: 0.01em;
  background: color-mix(in srgb, var(--tag-color, var(--st-color-primary)) 14%, transparent);
  color: var(--tag-color, var(--st-color-primary));
}

.st-tag-btn {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 8px 18px;
  border: 1px solid var(--st-color-border);
  border-radius: var(--st-radius-pill);
  font-size: 0.9375rem;
  font-weight: 500;
  letter-spacing: 0.03em;
  background: var(--st-color-bg);
  color: var(--st-color-text);
  cursor: pointer;
  outline: none;
  transition: all var(--st-transition);
}
.st-tag-btn:hover {
  background: var(--st-color-text);
  color: var(--st-color-bg);
  border-color: var(--st-color-text);
}
.st-tag-btn:focus-visible { box-shadow: 0 0 0 3px var(--st-ring-color); }
.st-tag-btn.active {
  background: var(--st-color-text);
  border-color: var(--st-color-text);
  color: var(--st-color-bg);
  font-weight: 600;
}

/* Vertical checklist variant — used inside .st-tag-row */
.st-tag-row {
  display: flex;
  align-items: center;
  border-radius: var(--st-radius-sm);
  transition: background var(--st-transition);
  width: 100%;
}
.st-tag-row:hover { background: var(--st-color-surface); }
.st-tag-row .st-tag-btn {
  flex: 1;
  min-width: 0;
  padding: 6px 10px;
  border: none;
  border-radius: var(--st-radius-sm);
  background: transparent;
  font-size: 0.9rem;
  font-weight: 500;
  letter-spacing: 0;
  gap: 8px;
}
.st-tag-row .st-tag-btn:hover {
  background: var(--st-color-surface);
  border: none;
  color: var(--st-color-text);
}
.st-tag-row .st-tag-btn.active {
  background: transparent;
  border: none;
  color: var(--tag-color, var(--st-color-primary));
}
.st-tag-row .st-tag-btn:focus-visible { box-shadow: 0 0 0 2px var(--st-ring-color) inset; }
/* Checkbox indicator */
.st-tag-check {
  width: 14px;
  height: 14px;
  flex-shrink: 0;
  border-radius: 3px;
  border: 1.5px solid var(--st-color-border);
  background: transparent;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition: background var(--st-transition), border-color var(--st-transition);
}
.st-tag-btn.active .st-tag-check {
  background: var(--tag-color, var(--st-color-primary));
  border-color: var(--tag-color, var(--st-color-primary));
}
.st-tag-btn.active .st-tag-check::after {
  content: '';
  display: block;
  width: 4px;
  height: 7px;
  border: 1.5px solid #fff;
  border-top: none;
  border-left: none;
  transform: rotate(45deg) translate(-1px, -1px);
}
.st-tag-name {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  text-align: left;
}

/* ── Gallery layout (sidebar + main) ──────────────────────────────── */
.st-gallery-layout {
  display: flex;
  flex-direction: row;
  gap: 20px;
  align-items: flex-start;
  min-height: 0;
  padding: 0 var(--st-spacing) var(--st-spacing);
}

.st-btn-clear-tags {
  white-space: nowrap;
  font-size: 0.8rem;
  color: var(--st-color-text-muted);
}
.st-btn-clear-tags:hover { color: var(--st-color-error); }

.st-filter-status {
  font-size: 0.8rem;
  color: var(--st-color-text-muted);
  margin-top: 6px;
}

/* Segmented "Match any / Match by category / Match all" control, shown once
   2+ tags are selected — mirrors the dashboard's own tag-match toggle. */
.st-match-toggle {
  display: flex;
  align-items: center;
  gap: 2px;
  margin-top: 10px;
  margin-bottom: 10px;
  padding: 2px;
  border: 1px solid var(--st-color-border);
  border-radius: var(--st-radius-pill);
  /* The track needs its own fill: the buttons are transparent and the sidebar
     it sits in has no background of its own, so without this the control is
     the page background with only a hairline border to find it by. */
  background: var(--st-color-surface);
}
.st-match-toggle button {
  flex: 1;
  padding: 5px 8px;
  border: none;
  border-radius: var(--st-radius-pill);
  background: transparent;
  color: var(--st-color-text-muted);
  font-size: 0.75rem;
  font-weight: 500;
  cursor: pointer;
  transition: all var(--st-transition);
}
.st-match-toggle button:hover { color: var(--st-color-text); }
.st-match-toggle button.active {
  background: var(--st-color-text);
  color: var(--st-color-bg);
  font-weight: 600;
}

/* The sidebar tree rules below (and the lightbox block further down) are used
   by BOTH the Jinja photo-gallery widget and the React inventory-gallery
   bundle, which links this stylesheet. scripts/dead_classes.py cannot see the
   React half — its extractor matches `class="..."` and `className =`
   assignment, while minified React emits `className:"..."` as an object
   property — so a sweep for rules nothing applies will read these as dead.
   They are not; check widget-src/src/widgets/inventory-gallery/ before
   deleting any of them. */

/* Top-level container for the gallery sidebar's filter tree — tag categories
   and, in the photo gallery, a Locations branch beside them. Children stretch
   full width so .st-tree-row/.st-tag-row rows get an edge-to-edge hover
   background rather than shrink-wrapping. */
.st-sidebar-group {
  display: flex;
  flex-direction: column;
  gap: 1px;
}

.st-sidebar-chevron {
  background: none;
  border: none;
  cursor: pointer;
  padding: 4px;
  color: var(--st-color-text-muted);
  transition: transform var(--st-transition);
  display: flex;
  align-items: center;
}
.st-sidebar-chevron.open { transform: rotate(180deg); }
.st-sidebar-chevron:hover { color: var(--st-color-text); }

/* Tree row — shared by category headers and the Locations branch header: a
   plain hoverable row (chevron + label + count), not a rounded pill, so
   headers read as tree structure rather than selectable filter chips
   (actual selectable tags stay .st-tag-row/.st-tag-btn). */
.st-tree-row {
  display: flex;
  align-items: center;
  gap: 6px;
  width: 100%;
  padding: 6px 8px;
  border: none;
  background: none;
  border-radius: var(--st-radius-sm);
  font-size: 0.8125rem;
  font-weight: 600;
  color: var(--st-color-text);
  text-align: left;
  cursor: pointer;
  transition: background 150ms ease;
}
.st-tree-row:hover {
  background: var(--st-color-surface);
}

.st-tag-count {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  font-size: 0.7rem;
  font-weight: 500;
  color: var(--st-color-text-muted);
  background: var(--st-color-surface);
  border: 1px solid var(--st-color-border);
  border-radius: 999px;
  padding: 1px 7px;
  margin-left: auto;
  line-height: 1.5;
  white-space: nowrap;
  flex-shrink: 0;
}
.st-tag-count--sub {
  background: transparent;
  border-color: transparent;
  opacity: 0.65;
  margin-left: 0;
}

.st-sidebar-children {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding-left: 16px;
  margin-top: 2px;
  overflow: hidden;
  /* Deliberately no max-height on the open state. This used to be capped at
     500px so the collapse had a finite value to animate between (`auto` is
     not interpolable), but nesting compounds the cap — every level puts its
     children in another capped container — so a branch holding a few
     tag-bearing children clipped silently. Any cap large enough to never clip
     also makes the animation mostly invisible travel: the content vanishes
     only in the last fraction of the transition, so it reads as lag then a
     snap. Height is therefore not animated at all; the opacity fade carries
     the transition, and the tree is correct at any depth. */
  transition: opacity 0.2s ease;
}
.st-sidebar-children.st-collapsed {
  max-height: 0;
  opacity: 0;
  margin-top: 0;
}

.st-gallery-main {
  flex: 1;
  min-width: 0;
}

/* ── Gallery grid ──────────────────────────────────────────────────── */
.st-gallery {
  columns: 2;
  gap: 16px;
  padding: 4px 0;
}
@media (min-width: 640px) {
  /* Target column width rather than a fixed count, so a wide embed/screen
     gains more columns instead of stretching them arbitrarily wide. 300px
     rather than the 220px this used to be: at 220 a 1200px-wide embed fitted
     five ~227px columns, which is a contact sheet rather than a gallery. */
  .st-gallery { columns: 300px; }
}

.st-gallery-item {
  break-inside: avoid;
  margin-bottom: 16px;
  position: relative;
  overflow: hidden;
  border-radius: 8px;
  cursor: pointer;
  background: var(--st-color-surface);
}
.st-gallery-item:focus-visible {
  outline: 2px solid var(--st-color-primary);
  outline-offset: 2px;
}
.st-gallery-item img {
  width: 100%;
  height: auto;
  display: block;
  transition: transform 0.45s cubic-bezier(0.16, 1, 0.3, 1), opacity 0.35s ease;
}
.st-gallery-item:hover img {
  transform: scale(1.04);
}

/* The crawlable pages wrap each thumbnail in a link to that photo's own page.
   Block, or the anchor would be an inline box the scaled image overflows. */
.st-gallery-media-link {
  display: block;
}

/* Tag + caption overlay on hover */
.st-gallery-item-tags {
  position: absolute;
  inset: 0;
  background: linear-gradient(to top, rgba(20,15,8,0.86) 0%, rgba(20,15,8,0.45) 38%, transparent 72%);
  display: flex;
  /* align-content, not just align-items: with flex-wrap on, align-items only
     places a pill within its own line, and the default align-content spreads
     the lines over the whole tile — so one row of tags sat at the bottom while
     two rows sat at the middle and the bottom. The strip is anchored to the
     bottom edge whatever it wraps to. */
  align-content: flex-end;
  align-items: flex-end;
  flex-wrap: wrap;
  gap: 4px;
  padding: 10px 8px 8px;
  opacity: 0;
  transition: opacity 0.28s ease;
  /* inset:0 means this covers the whole tile, and an invisible element still
     takes clicks — so without this it swallows every click aimed at the
     thumbnail beneath it, including the link the crawlable pages wrap it in.
     Same none/auto pair .st-gallery-select-btn already uses. */
  pointer-events: none;
}
/* Only a pill that is actually a link takes clicks back. In the embed React
   renders these as <span>, so clicks there keep bubbling to the tile and
   opening the lightbox. */
.st-gallery-tag-pill[href] { pointer-events: auto; }
.st-gallery-item:hover .st-gallery-item-tags { opacity: 1; }
.st-gallery-tag-pill {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: 0.65rem;
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  padding: 3px 8px;
  border-radius: var(--st-radius-pill);
  /* Both templates already pass the tag's own colour as --tag-color and
     nothing read it, so every pill was white-on-translucent-white: unreadable
     over a pale photo, and near-invisible in the .st-tag-links row on the
     page background. The colour is always darkened before white text goes on
     it, because a tag colour is arbitrary — a pale yellow is as likely as a
     navy. The flat declaration above is the fallback for a browser with no
     color-mix. */
  background: rgba(18,14,9,0.86);
  background: color-mix(in srgb, var(--tag-color, #6b5a44) 32%, rgba(14,11,7,0.92));
  color: #fff;
  box-shadow: 0 1px 3px rgba(0,0,0,0.35);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
  white-space: nowrap;
}

/* Picker mode — select overlay */
.st-gallery-item-select-overlay {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(0, 0, 0, 0);
  transition: background 0.22s ease;
}
.st-gallery-item:hover .st-gallery-item-select-overlay {
  background: rgba(0, 0, 0, 0.38);
}
.st-gallery-select-btn {
  opacity: 0;
  transform: translateY(6px);
  transition: opacity 0.22s ease, transform 0.22s ease;
  background: var(--st-color-primary);
  color: #fff;
  border: none;
  border-radius: var(--st-radius-sm);
  padding: 7px 18px;
  font-size: 0.8rem;
  font-weight: 600;
  cursor: pointer;
  pointer-events: none;
}
.st-gallery-item:hover .st-gallery-select-btn {
  opacity: 1;
  transform: translateY(0);
  pointer-events: auto;
}

/* Skeleton loading */
.st-gallery-skeleton { pointer-events: none; }

.st-skeleton-item {
  break-inside: avoid;
  margin-bottom: 16px;
  border-radius: 8px;
  overflow: hidden;
  background: var(--st-color-surface);
}
.st-skeleton-item:nth-child(3n+1) { height: 200px; }
.st-skeleton-item:nth-child(3n+2) { height: 270px; }
.st-skeleton-item:nth-child(3n)   { height: 230px; }
.st-skeleton-shimmer {
  width: 100%;
  height: 100%;
  background: linear-gradient(90deg, var(--st-color-surface) 25%, var(--st-color-surface-hover) 50%, var(--st-color-surface) 75%);
  background-size: 200% 100%;
  animation: st-shimmer 1.5s infinite;
}
@keyframes st-shimmer {
  0%   { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}

/* Load more */
.st-load-more {
  display: flex;
  justify-content: center;
  padding: 24px 0 8px;
}

/* ── Pagination ────────────────────────────────────────────────────── */
.st-pagination {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 12px;
  padding: 20px 0 8px;
}

/* The "Page 2 of 7" label between the Prev/Next links on the crawlable
   gallery page. Muted so the links stay the emphasis. */
.st-pagination-status {
  color: var(--st-color-text-muted);
  font-size: 0.9rem;
}

/* ── Crawlable gallery / tag pages ─────────────────────────────────── */
/* Server-rendered only (widget/public_gallery.html); the React gallery never
   renders these. */
.st-subheading {
  color: var(--st-color-text-muted);
  font-size: 0.95rem;
  margin: 4px 0 16px;
}

.st-breadcrumb {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  color: var(--st-color-text-muted);
  font-size: 0.85rem;
  margin-bottom: 4px;
}

/* Separator between crumbs, drawn rather than typed so the text stays
   copy-pasteable. */
.st-breadcrumb-item + .st-breadcrumb-item::before {
  content: "/";
  margin-right: 6px;
  opacity: 0.6;
}

.st-tag-links {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  padding: 24px 0 8px;
  border-top: 1px solid var(--st-color-border);
  margin-top: 24px;
}

/* The section heading sits on its own row above the pills. */
.st-tag-links .st-subheading {
  flex-basis: 100%;
  margin: 0;
}

/* ── Albums ─────────────────────────────────────────────────────────────────
   The album-cover grid the gallery opens on in album mode, the album section
   at the top of the crawlable index, and the "More albums" nav on an album
   page. One set of rules for the Jinja partial (_album_grid.html) and the
   React AlbumGrid, which must paint identical markup. A real grid rather than
   the photo grid's CSS columns: every card is the same shape, so masonry
   would buy nothing and would reorder the operator's album order. */
.st-album-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 16px;
  margin: 0;
  padding: 4px 0;
  list-style: none;
}
.st-album-item {
  min-width: 0;
}
@media (min-width: 640px) {
  .st-album-grid { grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); }
}
.st-album-card {
  display: flex;
  flex-direction: column;
  gap: 6px;
  width: 100%;
  min-width: 0;
  padding: 0;
  border: 0;
  border-radius: 8px;
  background: transparent;
  color: var(--st-color-text);
  font: inherit;
  text-align: left;
  text-decoration: none;
  cursor: pointer;
}
.st-album-card:focus-visible {
  outline: 2px solid var(--st-color-primary);
  outline-offset: 2px;
}
.st-album-cover {
  display: block;
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  border-radius: 8px;
  background: var(--st-color-surface);
  transition: transform 0.45s cubic-bezier(0.16, 1, 0.3, 1);
}
.st-album-card:hover .st-album-cover {
  transform: scale(1.02);
}
/* An album with nothing visible to show for itself still gets a tile of the
   same shape, so the grid does not jump when its first photo lands. */
.st-album-cover-empty {
  border: 1px dashed var(--st-color-border);
}
.st-album-name {
  font-weight: 600;
  font-size: 0.95rem;
  line-height: 1.3;
  overflow-wrap: anywhere;
}
.st-album-count {
  font-size: 0.8rem;
  color: var(--st-color-text-muted);
}
.st-album-links {
  padding: 24px 0 8px;
  border-top: 1px solid var(--st-color-border);
  margin-top: 24px;
}
.st-album-links .st-subheading {
  margin: 0 0 8px;
}
/* The row above the photos once a visitor has opened an album in the embed:
   a back control, the name, and the description on its own line. */
.st-album-header {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 8px 12px;
  margin: 0 0 12px;
}
.st-album-header .st-heading-sm {
  margin: 0;
}
.st-album-header .st-album-description {
  flex-basis: 100%;
  margin: 0;
  color: var(--st-color-text-muted);
  font-size: 0.9rem;
}
.st-album-back {
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--st-color-primary);
  font: inherit;
  font-size: 0.9rem;
  cursor: pointer;
}
.st-album-back:hover {
  text-decoration: underline;
}

/* A linked pill in the grid or the related-tags row. The span form is
   styled by .st-gallery-tag-pill already — including its own text colour —
   so this only removes the underline. */
a.st-gallery-tag-pill {
  text-decoration: none;
}

a.st-gallery-tag-pill:hover {
  text-decoration: underline;
}

/* ── Crawlable single-photo page ───────────────────────────────────── */
/* widget/public_photo.html only, organized the same as the widget's own
   lightbox (image, tags, caption, meta+actions) rather than a report-style
   list of fields.

   A guessed vh percentage here (88, then 94) kept coming up short — every
   fixed number is either too small on a tall monitor or leaves the image
   fighting the info block for room on a short one. `.st-photo-page` instead
   makes the root a column exactly one viewport tall, gives the info block
   its natural height, and lets the figure claim *everything left over* via
   flex-grow — filling the actual remaining space on whatever screen this
   renders on, rather than a fraction of it decided in advance. */
/* height, not min-height: a minimum lets the column grow past one viewport
   whenever content (the image's own intrinsic size, before flex-shrink gets
   a say) wants more room than that, which defeats the whole layout — the
   figure never actually gets forced to shrink back down, because flex-grow
   only ever hands out *extra* space in a container that's free to grow.
   Fixing the column at exactly one viewport tall is what makes shrinking the
   figure to fit non-optional. */
.st-photo-page {
  height: 100vh;
  display: flex;
  flex-direction: column;
}

.st-photo-figure {
  margin: 0 0 12px;
  display: flex;
  justify-content: center;
  /* On a viewport much taller than the image needs to be (a landscape photo
     is width-bound long before it reaches a tall figure's full height), this
     is what keeps the image centered in the leftover room rather than stuck
     against the top with a gap between it and the info block below. */
  align-items: center;
  /* flex-basis: 0%, not auto — an auto basis makes the browser size the item
     from its content first (the image's own intrinsic pixel size, which is
     enormous) and only then grow/shrink it, and a percentage max-height
     inside a flex-basis:auto item is a circular dependency browsers resolve
     by falling back to that intrinsic size — silently ignoring the
     max-height and handing the image far more room than actually remains.
     Starting from zero sidesteps the circularity outright. */
  flex: 1 1 0%;
  /* Belt-and-suspenders: also overrides the flex default of
     min-height:auto, which alone would already refuse to shrink the figure
     below the image's intrinsic size. */
  min-height: 0;
}

/* A ceiling on the figure's own box, not a forced fixed-aspect one: filling
   width AND height (as this once did) pillarboxes or letterboxes any photo
   whose own aspect ratio does not match the box's — which is every photo not
   shaped exactly like the figure. A real upload is already several
   megapixels, so capping to the figure's resolved size and leaving the image
   to size itself already fills whichever dimension binds first, no gap on
   either side. */
.st-photo-image {
  display: block;
  max-width: 100%;
  max-height: 100%;
  width: auto;
  height: auto;
  border-radius: 8px;
  background: var(--st-color-surface);
  object-fit: contain;
}

.st-photo-info {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  text-align: center;
  margin: 0 0 32px;
}

.st-photo-heading {
  font-size: 1.3rem;
  font-weight: 600;
  color: var(--st-color-text);
  margin: 0;
}

.st-photo-tags {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
  justify-content: center;
}

/* The location plus the Share button, on one line — the meta+actions row the
   lightbox itself renders. */
.st-photo-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 14px;
  align-items: center;
  justify-content: center;
  color: var(--st-color-text-muted);
  font-size: 0.85rem;
}

.st-photo-share {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
  font: inherit;
  font-size: 0.85rem;
  color: var(--st-color-primary);
  text-decoration: underline;
  text-underline-offset: 3px;
}

.st-photo-share-icon {
  flex-shrink: 0;
}

/* ── Lightbox ──────────────────────────────────────────────────────── */
/* Also built by the React inventory-gallery's ItemLightbox — see the note
   above .st-sidebar-group. */
.st-lightbox {
  position: fixed;
  inset: 0;
  z-index: 1000;
  display: flex;
  align-items: center;
  justify-content: center;
}
.st-lightbox-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.88);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
}
.st-lightbox-content {
  position: relative;
  max-width: 96vw;
  max-height: 96vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  animation: st-lightbox-in 0.18s ease;
}
@keyframes st-lightbox-in {
  from { opacity: 0; transform: scale(0.96); }
  to   { opacity: 1; transform: scale(1); }
}
.st-lightbox-content img {
  max-width: 100%;
  max-height: 88vh;
  object-fit: contain;
  border-radius: var(--st-radius);
  box-shadow: var(--st-shadow-lg);
}
.st-lightbox-close {
  position: absolute;
  top: -14px;
  right: -14px;
  width: 34px; height: 34px;
  border-radius: 50%;
  border: none;
  background: var(--st-color-bg);
  color: var(--st-color-text);
  font-size: 18px;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1;
  box-shadow: var(--st-shadow);
  transition: background var(--st-transition);
}
.st-lightbox-close:hover { background: var(--st-color-surface-hover); }
.st-lightbox-media {
  position: relative;
  display: flex;
  max-width: 100%;
}
.st-lightbox-nav {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  width: 40px; height: 40px;
  border-radius: 50%;
  border: none;
  background: rgba(0, 0, 0, 0.45);
  color: #fff;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1;
  transition: background var(--st-transition);
}
.st-lightbox-nav:hover { background: rgba(0, 0, 0, 0.65); }
.st-lightbox-prev { left: 8px; }
.st-lightbox-next { right: 8px; }
.st-lightbox-info {
  margin-top: 14px;
  color: #fff;
  font-size: 0.83rem;
  text-align: center;
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  justify-content: center;
  opacity: 0.9;
}
.st-lightbox-caption {
  width: 100%;
  color: #fff;
  font-size: 0.9rem;
  line-height: 1.5;
  opacity: 1;
}
.st-lightbox-tags { display: flex; gap: 4px; flex-wrap: wrap; justify-content: center; }
.st-lightbox-meta { display: flex; gap: 12px; color: rgba(255,255,255,0.65); align-items: center; }
/* Link to the photo's own page. Over the lightbox's dark scrim, so it takes a
   light colour rather than the theme's link colour, matching the meta row it
   sits in — the SDK's own lightbox styles this identically inline. */
.st-lightbox-permalink {
  color: rgba(255,255,255,0.8);
  text-decoration: underline;
  text-underline-offset: 3px;
}
/* The Share button beside it is a <button>, not an <a>, so it needs the reset
   the anchor gets for free. */
.st-lightbox-share {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
  font: inherit;
  font-size: 0.83rem;
}
@keyframes st-spin { to { transform: rotate(90deg); } }
@keyframes st-lb-in {
  from { opacity: 0; transform: scale(0.97); }
  to   { opacity: 1; transform: scale(1); }
}
.st-loc-search { max-width: 200px; }

/* Cap sidebar tag/category lists so a deep or wide tree scrolls inside the
   sidebar instead of growing the page unbounded (desktop only — the mobile
   bottom-sheet already has its own height cap on the whole sidebar). */
@media (min-width: 640px) {
  #category-tree {
    max-height: 340px;
    overflow-y: auto;
  }
  /* Visitor-collapsed sidebar. Media-scoped on purpose: an unscoped hide would
     sit in the same cascade as the `display: block !important` the mobile
     bottom-sheet rule carries below, and lose to it. Hidden rather than
     unmounted so LocationFilter keeps its own search text and show-all count
     across a collapse. */
  .st-filters-collapsed .st-tags-col {
    display: none;
  }
}
.st-tags-col {
  width: 260px;
  flex-shrink: 0;
}
/* Names shrink to whatever room is left in the row (after checkbox/icon/
   chevron/count) rather than a fixed max-width, so a name is only ever
   truncated when it actually doesn't fit — including at deeper, more
   indented tree levels where less horizontal room is available. */
.st-tags-col .st-tag-name {
  overflow: hidden;
  text-overflow: ellipsis;
}

.st-mobile-tag-backdrop,
#mobile-filter-backdrop {
  display: none;
  position: fixed;
  inset: 0;
  z-index: 199;
  background: rgba(0, 0, 0, 0);
  transition: background 240ms ease;
}
.st-mobile-tag-backdrop.st-sheet-open,
#mobile-filter-backdrop.st-sheet-open {
  display: block;
  background: rgba(0, 0, 0, 0.45);
}

/* Gallery filter button bar — the sidebar's show control. Rendered on mobile
   (where the sidebar is a bottom sheet) and on desktop once a visitor has
   collapsed it. */
.st-gallery-filter-bar {
  display: block;
  padding: 0 0 10px;
}

/* Tag section header actions — "Clear all" and "Hide" travel together on the
   right of the space-between header. */
.st-tag-header-actions {
  display: flex;
  align-items: center;
  gap: 8px;
}
.st-btn-hide-filters {
  display: inline-flex;
  align-items: center;
  gap: 3px;
}

/* Tag section header row */
.st-tag-section-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding-bottom: 6px;
  border-bottom: 1px solid var(--st-color-border);
  margin-bottom: 8px;
}
.st-tag-section-header .st-heading-sm {
  font-size: 0.7rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--st-color-text-muted);
  margin-bottom: 0;
}
.st-input-sm  { padding: 5px 10px; font-size: 0.82rem; height: 32px; flex: 1; min-width: 60px; }

/* ── Auth widget ───────────────────────────────────────────────────── */
.st-auth-container {
  width: 100%;
  max-width: 420px;
  margin: 24px auto;
  padding: 0 var(--st-spacing);
}
.st-auth-tabs {
  display: flex;
  border-bottom: 2px solid var(--st-color-border);
  margin-bottom: 22px;
}
.st-auth-tab {
  flex: 1;
  padding: 10px 8px;
  text-align: center;
  border: none;
  background: none;
  font-size: 0.875rem;
  font-weight: 500;
  font-family: inherit;
  color: var(--st-color-text-muted);
  cursor: pointer;
  border-bottom: 2.5px solid transparent;
  margin-bottom: -2px;
  outline: none;
  transition: color var(--st-transition), border-color var(--st-transition);
}
.st-auth-tab.active             { color: var(--st-color-primary); border-bottom-color: var(--st-color-primary); }
.st-auth-tab:hover:not(.active) { color: var(--st-color-text); }
.st-auth-tab:focus-visible      { outline: 2px solid var(--st-ring-color); outline-offset: 2px; border-radius: 3px; }

.st-auth-panel { margin-bottom: 16px; }

.st-auth-message {
  padding: 9px 13px;
  border-radius: var(--st-radius-sm);
  font-size: 0.8rem;
  margin-top: 12px;
  line-height: 1.45;
}
.st-auth-message.st-error {
  background: var(--st-color-error-light);
  color: var(--st-color-error);
  border: 1px solid color-mix(in srgb, var(--st-color-error) 22%, transparent);
}
.st-auth-message.st-success {
  background: var(--st-color-success-light);
  color: var(--st-color-success);
  border: 1px solid color-mix(in srgb, var(--st-color-success) 22%, transparent);
}

.st-auth-divider {
  text-align: center;
  margin: 20px 0;
  position: relative;
}
.st-auth-divider::before {
  content: '';
  position: absolute;
  left: 0; right: 0; top: 50%;
  border-top: 1px solid var(--st-color-border);
}
.st-auth-divider span {
  position: relative;
  background: var(--st-color-bg);
  padding: 0 12px;
  font-size: 0.72rem;
  color: var(--st-color-text-muted);
  text-transform: uppercase;
  letter-spacing: 0.07em;
  font-weight: 600;
}

.st-oauth-buttons { display: flex; flex-direction: column; gap: 8px; }

.st-btn-oauth {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 10px 16px;
  border: 1.5px solid var(--st-color-border);
  border-radius: var(--st-radius-sm);
  background: var(--st-color-bg);
  color: var(--st-color-text);
  font-size: 0.875rem;
  font-weight: 500;
  font-family: inherit;
  cursor: pointer;
  width: 100%;
  outline: none;
  transition: background var(--st-transition), border-color var(--st-transition), box-shadow var(--st-transition);
}
.st-btn-oauth:hover         { background: var(--st-color-surface); border-color: var(--st-color-text-muted); }
.st-btn-oauth:focus-visible { box-shadow: 0 0 0 3px var(--st-ring-color); }

/* ── Events ──────────────────────────────────────────────────────────── */
.st-event-card {
  position: relative;
  overflow: hidden;
  box-shadow: inset 0 0 0 1px var(--st-color-border), var(--st-shadow-sm);
  transition: box-shadow var(--st-transition), transform var(--st-transition);
}
.st-event-card:hover {
  box-shadow: inset 0 0 0 1px var(--st-color-border), var(--st-shadow);
  transform: translateY(0);
}

.st-modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.5);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 100;
  padding: var(--st-spacing);
  backdrop-filter: blur(3px);
  -webkit-backdrop-filter: blur(3px);
  animation: st-fade-in 0.15s ease;
}
@keyframes st-fade-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}
.st-modal-content {
  max-width: 480px;
  width: 100%;
  max-height: 80vh;
  overflow-y: auto;
  animation: st-slide-up 0.2s ease;
}
@keyframes st-slide-up {
  from { opacity: 0; transform: translateY(14px) scale(0.98); }
  to   { opacity: 1; transform: translateY(0) scale(1); }
}
/* ── Notices ────────────────────────────────────────────────────── */
/* Built by stNotice() in widget/base.html, the themed replacement for
   window.alert — which blocks the host page's scripts and can be suppressed
   by the browser, in which case the message is never delivered at all. */
.st-notice-region {
  position: fixed;
  inset: auto 0 var(--st-spacing) 0;
  z-index: 200;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  padding: 0 var(--st-spacing);
  pointer-events: none;
}
.st-notice {
  pointer-events: auto;
  display: flex;
  align-items: center;
  gap: 12px;
  max-width: 420px;
  padding: 10px 12px;
  border: 1px solid var(--st-color-border);
  border-radius: var(--st-radius);
  background: var(--st-color-surface);
  color: var(--st-color-text);
  font-size: 0.85rem;
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.18);
}
.st-notice-error {
  border-color: var(--st-color-error);
  background: var(--st-color-error-light);
  color: var(--st-color-error);
}
.st-notice-dismiss {
  flex-shrink: 0;
  border: 0;
  background: none;
  color: inherit;
  font-size: 1.1rem;
  line-height: 1;
  cursor: pointer;
  padding: 0 2px;
  border-radius: var(--st-radius-sm);
}
.st-notice-dismiss:focus-visible {
  outline: 2px solid var(--st-color-primary);
  outline-offset: 2px;
}

/* ── Confirmation dialog ────────────────────────────────────────── */
/* Built by stConfirm() in widget/base.html, the themed replacement for
   window.confirm — which renders in the browser's chrome rather than the
   host's theme, and which a host page can suppress entirely. */
.st-confirm { max-width: 400px; }
.st-confirm-title { margin-bottom: 8px; }
.st-confirm-body  { margin-bottom: var(--st-spacing); }
.st-confirm-actions {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
}

/* ── Registration form ──────────────────────────────────────────── */
.st-reg-type-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
  margin-bottom: 16px;
}
.st-reg-type-btn {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  padding: 16px 12px;
  border: 2px solid var(--st-color-border);
  border-radius: var(--st-radius);
  background: var(--st-color-bg);
  cursor: pointer;
  text-align: center;
  font-size: 0.875rem;
  transition: border-color var(--st-transition), background var(--st-transition);
}
.st-reg-type-btn.active {
  border-color: var(--st-color-primary);
  background: var(--st-color-surface);
}
.st-reg-type-btn:hover:not(.active) {
  border-color: var(--st-color-text-muted);
}
.st-form-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
}
.st-form-section-heading {
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--st-color-text-muted);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  margin: 14px 0 8px;
  padding-bottom: 6px;
  border-bottom: 1px solid var(--st-color-border);
}
.st-fee-summary {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 10px 14px;
  background: var(--st-color-surface);
  border-radius: var(--st-radius);
  border: 1px solid var(--st-color-border);
  font-size: 0.9rem;
}
/* ── End registration form ─────────────────────────────────────── */

.st-badge {
  display: inline-block;
  padding: 2px 9px;
  border-radius: var(--st-radius-pill);
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.02em;
}
.st-badge-confirmed  { background: #d1e7dd; color: #0a4428; }
.st-badge-class      { background: #e0eaff; color: #1a3a6d; }

.st-textarea {
  resize: vertical;
  min-height: 72px;
}

/* ── Tag color dot (inside chip) ───────────────────────────────────── */
.st-tag-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  display: inline-block;
  flex-shrink: 0;
  opacity: 0.85;
  /* Colour arrives as an inline --tag-color, matching .st-tag above. Call
     sites that still set `background:` inline keep working — inline wins. */
  background: var(--tag-color, var(--st-color-primary));
}

/* ── Contact form widget ───────────────────────────────────────────── */

/* Honeypot — off-screen and invisible, preserving document flow */
.st-honeypot {
  position: absolute;
  left: -9999px;
  opacity: 0;
  height: 0;
  overflow: hidden;
  pointer-events: none;
  tab-index: -1;
}

/* Required asterisk */
.st-contact-required {
  color: var(--st-color-error);
  margin-left: 1px;
}

/* Inline field error */
.st-contact-field-error {
  display: none;
  font-size: 0.75rem;
  color: var(--st-color-error);
  margin-top: 4px;
  line-height: 1.4;
}
.st-form-group.st-has-error .st-input,
.st-form-group.st-has-error select.st-input,
.st-form-group.st-has-error textarea.st-input {
  border-color: var(--st-color-error);
  box-shadow: 0 0 0 3px var(--st-color-error-light);
}
.st-form-group.st-has-error .st-contact-field-error {
  display: block;
}

/* Radio group layout */
.st-contact-radio-group {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 20px;
  padding: 6px 0;
}
.st-contact-radio-option {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 0.875rem;
  color: var(--st-color-text);
  cursor: pointer;
}
.st-contact-radio-option input[type="radio"],
.st-contact-radio-option input[type="checkbox"] {
  accent-color: var(--st-color-primary);
  width: 15px;
  height: 15px;
  cursor: pointer;
}

.st-file-input-wrapper {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
/* Hide the native input visually but keep it accessible */
.st-file-input {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}
/* Styled label acts as the button — inherits all --st-* theme tokens */
.st-file-btn {
  width: fit-content;
  user-select: none;
}
.st-file-input:focus-visible + .st-file-btn {
  box-shadow: 0 0 0 3px var(--st-ring-color);
}
.st-file-list {
  list-style: none;
  margin: 0;
  padding: 0;
  font-size: 0.8rem;
  color: var(--st-color-text-muted);
  line-height: 1.6;
}

/* Status message below submit button */
.st-contact-status {
  padding: 9px 13px;
  border-radius: var(--st-radius-sm);
  font-size: 0.82rem;
  line-height: 1.45;
  margin-top: 10px;
}
.st-contact-status--error {
  background: var(--st-color-error-light);
  color: var(--st-color-error);
  border: 1px solid color-mix(in srgb, var(--st-color-error) 22%, transparent);
}
.st-contact-status--success {
  background: var(--st-color-success-light);
  color: var(--st-color-success);
  border: 1px solid color-mix(in srgb, var(--st-color-success) 22%, transparent);
}

/* Loading skeleton, shown until the field config arrives. Same shimmer as
   .st-content-skeleton; --tall stands in for the message textarea. */
.st-contact-skeleton {
  height: 38px;
  background: var(--st-color-surface);
  border-radius: var(--st-radius);
  margin-bottom: 14px;
  width: 60%;
  animation: st-shimmer 1.4s ease-in-out infinite;
}
.st-contact-skeleton--wide { width: 100%; }
.st-contact-skeleton--tall { height: 96px; width: 100%; }

/* ── End contact form widget ───────────────────────────────────────── */

/* ── Content widget (public view) ───────────────────────────────────── */

.st-content-block {
  margin-bottom: calc(var(--st-spacing) * 2);
  padding-bottom: calc(var(--st-spacing) * 2);
  border-bottom: 1px solid var(--st-color-border);
}

.st-content-block:last-child {
  border-bottom: none;
  margin-bottom: 0;
  padding-bottom: 0;
}

.st-content-title {
  font-size: 1.35rem;
  font-weight: 700;
  color: var(--st-color-text);
  margin: 0 0 calc(var(--st-spacing) * 0.75) 0;
  line-height: 1.3;
}

.st-content-body {
  font-size: 0.95rem;
  line-height: 1.7;
  color: var(--st-color-text);
}

.st-content-body p {
  margin: 0 0 0.85em 0;
}

.st-content-body p:last-child {
  margin-bottom: 0;
}

.st-content-body h2 {
  font-size: 1.1rem;
  font-weight: 600;
  margin: 1.25em 0 0.4em;
}

.st-content-body h3 {
  font-size: 1rem;
  font-weight: 600;
  margin: 1em 0 0.3em;
}

.st-content-body ul,
.st-content-body ol {
  padding-left: 1.5em;
  margin: 0 0 0.85em 0;
}

.st-content-body li {
  margin-bottom: 0.25em;
}

.st-content-body a {
  color: var(--st-color-primary);
  text-decoration: underline;
}

.st-content-body a:hover {
  color: var(--st-color-primary-hover);
}

.st-content-body blockquote {
  border-left: 3px solid var(--st-color-primary);
  margin: 1em 0;
  padding: 0.5em 0 0.5em 1em;
  color: var(--st-color-text-muted);
  font-style: italic;
}

/* Loading skeleton for content widget */
.st-content-skeleton {
  height: 14px;
  background: var(--st-color-surface);
  border-radius: var(--st-radius);
  margin-bottom: 10px;
  width: 60%;
  animation: st-shimmer 1.4s ease-in-out infinite;
}

.st-content-skeleton--title {
  height: 22px;
  width: 45%;
  margin-bottom: 14px;
}

.st-content-skeleton--wide {
  width: 90%;
}

/* ── End content widget ──────────────────────────────────────────────── */

/* ── Tables ────────────────────────────────────────────────────────── */
/* The account widget's five panels are the only tables in the widget layer.
   These rules have to stay above the phone-size block below, which overrides
   the same cell padding and font-size at equal specificity — put them after it
   and they win the cascade, which is how .st-table ended up styled only under
   480px in the first place.

   No `display` here on purpose: the account JS reveals a loaded table with
   `style.display = ""`, which falls back to whatever the stylesheet says. */
.st-table-wrap {
  /* Widgets render inside an iframe the embedder sizes, so a wide table has to
     scroll in place rather than push the frame wider. */
  overflow-x: auto;
}

.st-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.875rem;
  color: var(--st-color-text);
}

.st-table th,
.st-table td {
  padding: 10px 12px;
  text-align: left;
  vertical-align: top;
  border-bottom: 1px solid var(--st-color-border);
}

.st-table th {
  background: var(--st-color-surface);
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: var(--st-color-text-muted);
  white-space: nowrap;
}

.st-table tbody tr:last-child td { border-bottom: none; }

/* ── Responsive: phone-sized iframe (< 480px) ───────────────────────── */
@media (max-width: 479px) {
  /* Tighten global spacing */
  :root {
    --st-spacing: 12px;
  }

  /* Stack form fields full-width */
  .st-form-row {
    flex-direction: column;
  }
  .st-form-row > * {
    width: 100% !important;
  }

  /* Reduce table horizontal padding so columns don't overflow */
  .st-table th,
  .st-table td {
    padding-left: 8px;
    padding-right: 8px;
    font-size: 0.8rem;
  }

  /* Pagination: tighten button gap */
  .st-pagination { gap: 6px; }

  /* Buttons: ensure min tap target */
  .st-btn {
    min-height: 40px;
    padding: 8px 14px;
  }

  /* Cards: strip border/radius/shadow so content fills full width */
  .st-card {
    padding: 14px;
    border: none;
    border-radius: 0;
    box-shadow: none;
  }
}

/* ══════════════════════════════════════════════════════════════════════
   Base rules, and they must stay above the mobile @media block that
   follows: that block holds the narrow-viewport overrides for several
   of them, so a base rule placed after it would win when it shouldn't.
   Some rules here also rely on source order to beat an equal-specificity
   base rule defined earlier in the file (noted individually), so they
   cannot simply move up either.

   Until this commit the file did not parse: `.st-mobile-tag-bar` below
   was missing its closing brace, which under CSS nesting swallowed the
   34 selectors after it as descendants of a `display: none` rule, and
   left the enclosing @media unterminated at EOF. Keep the braces
   balanced — `npx postcss` or any parser will catch it.
   ══════════════════════════════════════════════════════════════════ */

/* ── Widget shell ──────────────────────────────────────────────────── */
.st-widget-root { padding: var(--st-spacing); }
.st-result-icon { font-size: 2.5rem; line-height: 1; margin-bottom: 12px; }
.st-modal-close { font-size: 1.4rem; line-height: 1; padding: 0 4px; }
.st-card--flush { padding: 0; }

/* Must follow .st-modal-content (same specificity, so source order wins). */
.st-modal-content--tall { max-height: 90vh; }
.st-modal-content--wide { max-width: 560px; }

/* ── Badges: remaining variants ────────────────────────────────────── */
.st-badge-primary { background: var(--st-color-primary);       color: #fff; }
.st-badge-success { background: var(--st-color-success-light); color: var(--st-color-success); }
.st-badge-muted   { background: var(--st-color-surface);       color: var(--st-color-text-muted); }

/* ── Destructive outline button ────────────────────────────────────── */
.st-btn-danger { color: var(--st-color-error); border-color: var(--st-color-error); }
.st-btn-danger:hover:not(:disabled) { background: var(--st-color-error-light); border-color: var(--st-color-error); }

/* A label that stacks its own control beneath it (gift/checkout forms).
   Spacing composes via .st-mb-* rather than being baked in. */
.st-stacked-label { display: block; }

/* ── Gift message quote ────────────────────────────────────────────── */
.st-gift-message {
  font-style: italic;
  margin: 10px 0;
  padding: 10px;
  border-left: 2px solid var(--st-color-border);
}

/* ── Choice label (radio/checkbox row) ─────────────────────────────── */
.st-choice-label { display: flex; align-items: center; gap: 4px; cursor: pointer; }
.st-choice-icon  { font-size: 1.6rem; }

/* Small inline glyphs that sit beside text. */
.st-tag-icon     { vertical-align: -1px; }
.st-oauth-icon   { margin-right: 6px; vertical-align: middle; }
.st-review-avatar { width: 32px; height: 32px; border-radius: 50%; }
.st-loc-show-more { padding: 4px 0; }

/* ── Reviews ───────────────────────────────────────────────────────────
   Deliberately its own layout rather than reusing .st-gallery. That class is
   the photo masonry grid, and its rules are written for thumbnails: no inner
   padding (an image fills its box), a hover scale on the img, and a mobile
   override forcing `columns: 3`. Applied to a review, those give text pressed
   flat against the card edge and, on a phone, three ~100px-wide columns of
   roughly twelve characters per line. Column width here is a length, so the
   browser fits as many columns as the embed can actually afford — one on a
   phone — instead of a fixed count. */
.st-review-list {
  columns: 280px;
  gap: 16px;
  padding: 4px 0;
}
.st-review-card {
  break-inside: avoid;
  margin-bottom: 16px;
  padding: 14px 16px;
  border-radius: var(--st-radius);
  background: var(--st-color-surface);
}
.st-review-name { font-weight: 600; }
/* Stars carry the brand colour rather than body text: they are the one part of
   a review read at a glance, and a host already themes --st-color-primary. */
.st-review-stars {
  color: var(--st-color-primary);
  letter-spacing: 0.08em;
  margin: 6px 0 8px;
}
.st-review-comment { color: var(--st-color-text-muted); }
/* Attribution: a manual review's own label, or "Google" for an imported
   one. Resolved server-side by app.reviews.public_attribution. */
.st-review-source {
  margin: 0;
  font-size: 0.8125rem;
  color: var(--st-color-text-muted);
}

/* Loading skeleton — mirrors the card rhythm above, not the gallery's. */
.st-review-skeleton { pointer-events: none; }
.st-review-skeleton-item {
  break-inside: avoid;
  margin-bottom: 16px;
  border-radius: var(--st-radius);
  overflow: hidden;
  background: var(--st-color-surface);
}
.st-review-skeleton-item:nth-child(3n+1) { height: 132px; }
.st-review-skeleton-item:nth-child(3n+2) { height: 108px; }
.st-review-skeleton-item:nth-child(3n)   { height: 156px; }

/* ── Order summary rows ────────────────────────────────────────────── */
.st-summary-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-size: 0.85rem;
  color: var(--st-color-text-muted);
}
.st-summary-row--total {
  border-top: 1px solid var(--st-color-border);
  margin-top: 10px;
  padding-top: 10px;
  font-size: inherit;
  font-weight: 600;
  color: var(--st-color-text);
}

/* ── Account: stat cards ───────────────────────────────────────────── */
.st-stat-card        { padding: 12px 20px; text-align: center; min-width: 90px; }
.st-stat-card__value { font-size: 1.4rem; font-weight: 700; }
.st-stat-row         { display: flex; gap: 12px; flex-wrap: wrap; }
.st-card-title       { font-weight: 600; font-size: 1rem; }
.st-perk-list        { margin: 8px 0 0 16px; padding: 0; }
.st-account-loading  { min-height: 200px; }
.st-session-expired  { text-align: center; padding: 40px 16px; }
.st-account-photo {
  width: 100%;
  aspect-ratio: 1;
  object-fit: cover;
  border-radius: var(--st-radius);
}
.st-account-photo--empty {
  display: flex;
  align-items: center;
  justify-content: center;
  object-fit: initial;
  background: var(--st-color-surface);
  color: var(--st-color-text-muted);
}
.st-gallery-item__body { padding: 8px 4px; }
.st-gallery-item__name { font-weight: 600; font-size: 0.9rem; }

/* ── Responsive tab strip ──────────────────────────────────────────── */
.st-responsive-tabs { display: flex; flex-wrap: wrap; gap: 6px; }

/* ── Inventory: point-of-sale layout ───────────────────────────────── */
.st-pos-layout       { display: flex; gap: 16px; flex-wrap: wrap; align-items: flex-start; }
.st-pos-main         { flex: 1; min-width: 280px; }
.st-pos-side         { width: 360px; flex-shrink: 0; }
.st-pos-gallery-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(130px, 1fr)); gap: 10px; }
.st-pos-cart-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 12px 16px;
  border-bottom: 1px solid var(--st-color-border);
  flex-shrink: 0;
}
.st-pos-cart-total {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 10px 16px;
  border-top: 2px solid var(--st-color-border);
  font-weight: 600;
}
.st-pos-cart-actions {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 0 16px 16px;
  border-top: 1px solid var(--st-color-border);
}
.st-pos-cart-row {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  padding: 10px 16px;
  border-bottom: 1px solid var(--st-color-border);
}
.st-pos-cart-row__body { flex: 1; min-width: 0; }
.st-pos-cart-row__name { font-size: 0.9rem; font-weight: 500; line-height: 1.3; word-break: break-word; }
.st-pos-cart-row__meta { display: flex; align-items: center; gap: 6px; margin-top: 5px; flex-wrap: wrap; }
.st-pos-qty        { display: flex; align-items: center; gap: 3px; flex-shrink: 0; }
.st-pos-qty__value { min-width: 18px; text-align: center; font-size: 0.9rem; }
/* Descendant override rather than .st-btn-icon, whose `padding: … !important`
   would grow the cart row. Same idiom as `.st-tag-row .st-tag-btn` above. */
.st-pos-qty .st-btn { padding: 1px 6px; min-height: 0; height: auto; }
.st-pos-price-input { width: 56px; padding: 2px 4px; font-size: 0.8rem; text-align: right; }
.st-pos-auth-frame-wrap  { margin-top: 12px; width: 100%; max-width: 520px; margin-inline: auto; }
.st-pos-auth-frame       { width: 100%; border: none; min-height: 560px; border-radius: 10px; background: transparent; }
.st-pos-filter-row       { display: flex; flex-wrap: wrap; gap: 6px; }
.st-pos-empty            { padding: 24px 0; font-size: 0.875rem; }
.st-pos-loading          { padding: 20px 0; }
.st-pos-cart-empty       { padding: 24px 16px; }
.st-pos-cart-total__label { font-weight: 600; font-size: 0.9rem; }
.st-pos-cart-total__value { font-weight: 700; font-size: 1rem; }
.st-pos-link             { word-break: break-all; font-size: 0.8rem; }
.st-pos-line-total       { font-size: 0.8rem; margin-left: 2px; }
.st-pos-cart-row__dot    { margin-top: 5px; }
.st-pos-cart-row__head   { display: flex; justify-content: space-between; align-items: flex-start; gap: 6px; }
.st-pos-cart-row__status { font-size: 0.72rem; flex: 1; min-width: 50px; }
.st-pos-remove-btn       { padding: 1px 5px; }

/* ── POS: gallery product card ─────────────────────────────────────── */
.st-pos-card {
  border: 1px solid var(--st-color-border);
  border-radius: 8px;
  overflow: hidden;
  background: var(--st-color-bg);
  cursor: pointer;
  transition: box-shadow 0.15s, border-color 0.15s;
}
/* Was two JS mouseenter/mouseleave listeners setting style.boxShadow. */
.st-pos-card:hover { box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12); }
.st-pos-card--disabled { cursor: default; opacity: 0.5; }
.st-pos-card--disabled:hover { box-shadow: none; }
.st-pos-card__media  { position: relative; }
.st-pos-card__img    { width: 100%; aspect-ratio: 1 / 1; object-fit: cover; display: block; }
.st-pos-card__badge {
  position: absolute;
  top: 6px;
  left: 6px;
  background: var(--st-color-primary);
  color: #fff;
  font-size: 0.65rem;
  font-weight: 700;
  padding: 2px 7px;
  border-radius: var(--st-radius-pill);
  pointer-events: none;
}
.st-pos-card__body  { padding: 6px 8px; }
.st-pos-card__name  { font-size: 0.8rem; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; margin-bottom: 2px; }
.st-pos-card__price { font-size: 0.85rem; font-weight: 700; color: var(--st-color-primary); }
.st-pos-card__tags  { margin-top: 4px; display: flex; flex-wrap: wrap; gap: 3px; }
.st-pos-card__stock { font-size: 0.7rem; margin-top: 3px; }
.st-pos-chip {
  font-size: 0.65rem;
  padding: 1px 6px;
  border-radius: var(--st-radius-pill);
  background: color-mix(in srgb, var(--chip-color, var(--st-color-border)) 13%, transparent);
  color: var(--chip-color, var(--st-color-text));
  border: 1px solid color-mix(in srgb, var(--chip-color, var(--st-color-border)) 27%, transparent);
}

/* ── POS: gallery tag filter chip ──────────────────────────────────── */
.st-pos-tag-chip {
  border: 1px solid var(--st-color-border);
  border-radius: var(--st-radius-pill);
  padding: 3px 12px;
  font-size: 0.78rem;
  cursor: pointer;
  background: transparent;
  color: var(--st-color-text-muted);
  transition: background 0.15s, border-color 0.15s, color 0.15s;
}
.st-pos-tag-chip.is-active {
  background: var(--chip-color, var(--st-color-primary));
  border-color: var(--chip-color, var(--st-color-primary));
  color: #fff;
}

/* ── POS: stock-status picker modal ────────────────────────────────── */
.st-pos-status-modal {
  position: fixed;
  inset: 0;
  z-index: 9000;
  background: rgba(0, 0, 0, 0.4);
  display: flex;
  align-items: center;
  justify-content: center;
}
.st-pos-status-box {
  background: var(--st-color-bg);
  border-radius: var(--st-radius);
  padding: 20px;
  width: min(360px, calc(100vw - 32px));
  box-shadow: var(--st-shadow-lg);
}
.st-pos-status-title { font-size: 0.95rem; margin-bottom: 8px; }
.st-pos-status-btn   { width: 100%; margin-bottom: 6px; display: flex; justify-content: space-between; align-items: center; }
.st-tag-dot--spaced  { margin-right: 6px; }
.st-divider-top      { border-top: 1px solid var(--st-color-border); padding-top: 12px; }

/* ── Membership tier cards ─────────────────────────────────────────── */
.st-tier-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 16px; }
/* Flex column so the CTA always sits at the bottom of the card. */
.st-tier-card        { display: flex; flex-direction: column; background: var(--st-color-surface); }
.st-tier-card__name  { font-size: 1rem; font-weight: 600; margin: 0 0 4px; line-height: 1.3; }
.st-tier-card__desc  { margin: 0 0 10px; }
.st-tier-card__rule  { border: none; border-top: 1px solid var(--st-color-border); margin: 10px 0 14px; }
.st-tier-card__price { font-size: 1.75rem; font-weight: 700; color: var(--st-color-primary); line-height: 1; margin: 0; }
.st-tier-card__interval { margin: 3px 0 0; }
.st-tier-card__fee   { margin: 2px 0 0; }
.st-tier-perks       { margin: 14px 0 0; padding: 0; list-style: none; flex: 1; }
.st-tier-perks li    { display: flex; align-items: flex-start; gap: 7px; padding: 3px 0; }
.st-tier-perks__check { color: var(--st-color-primary); flex-shrink: 0; font-size: 0.8rem; line-height: 1.55; font-weight: 700; }
.st-tier-card__spacer { flex: 1; }
.st-tier-card__action { margin-top: 18px; }
.st-card--inset      { padding: 12px; background: var(--st-color-surface); }
.st-badge-success--solid { background: var(--st-color-success); color: #fff; }

.st-pos-error {
  padding: 8px;
  border-radius: var(--st-radius-sm);
  background: var(--st-color-error-light);
  color: var(--st-color-error);
}
.st-pos-toast {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  z-index: 9999;
  padding: 12px 24px;
  border-radius: var(--st-radius);
  background: var(--st-color-success);
  color: #fff;
  font-size: 0.875rem;
  text-align: center;
  box-shadow: var(--st-shadow);
}

/* ── Public inventory item page ────────────────────────────────────── */
.st-inv-public             { max-width: 640px; margin: 0 auto; }
.st-inv-public-card        { padding: 24px; }
.st-inv-public-media       { margin-bottom: 20px; text-align: center; }
.st-inv-public-image       { max-width: 100%; max-height: 360px; border-radius: 8px; object-fit: contain; }
/* The item's remaining photos, below the primary one. Scrolls sideways in
   its own container rather than wrapping, so a long set never grows the card. */
.st-inv-public-thumbs      { display: flex; gap: 8px; overflow-x: auto; margin-top: 8px; padding-bottom: 4px; }
.st-inv-public-thumb       { height: 72px; width: auto; border-radius: 6px; object-fit: cover; flex: 0 0 auto; }
/* Must follow .st-heading (same specificity): the <h1> carries both, and
   .st-heading's 0.75rem would otherwise win. */
.st-inv-public-title       { font-size: 1.5rem; margin-bottom: 8px; }
.st-inv-public-price       { font-size: 1.75rem; font-weight: 700; color: var(--st-color-primary); margin-bottom: 16px; }
.st-inv-public-description { margin-bottom: 20px; line-height: 1.6; }
.st-inv-public-tags        { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 16px; }
.st-inv-public-status      { margin-bottom: 20px; }
.st-inv-public-meta        { margin-top: 20px; font-size: 0.75rem; color: var(--st-color-text-muted); }
/* Overrides .st-btn's inline-flex, so it must follow it in source order. */
.st-inv-public-cta         { display: inline-block; margin-top: 8px; }
/* Data-driven colour arrives as an inline --chip-color, the same idiom
   .st-tag and .st-gallery-item-caption-status already use. */
.st-inv-public-chip {
  display: inline-block;
  padding: 2px 10px;
  border-radius: var(--st-radius-pill);
  font-size: 0.8rem;
  font-weight: 600;
  background: color-mix(in srgb, var(--chip-color, var(--st-color-border)) 13%, transparent);
  color: var(--chip-color, var(--st-color-text));
  border: 1px solid var(--chip-color, var(--st-color-border));
}

/* ── Secure upload page ────────────────────────────────────────────
   Relocated verbatim from widget/secure_upload.html's <style> block.
   ──────────────────────────────────────────────────────────────── */
.su-shell {
  max-width: 920px;
  margin: 32px auto;
  display: grid;
  grid-template-columns: minmax(0, 1.3fr) minmax(280px, 0.7fr);
  gap: 20px;
  padding: 0 12px 24px;
}
.su-hero {
  padding: 22px;
  border-radius: 18px;
  border: 1px solid var(--st-color-border);
  background:
    radial-gradient(circle at top left, rgba(26, 122, 110, 0.14), transparent 42%),
    linear-gradient(135deg, rgba(255,255,255,0.8), rgba(242,237,231,0.95));
  box-shadow: var(--st-shadow);
}
.su-kicker {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 6px 10px;
  border-radius: 999px;
  background: rgba(26, 122, 110, 0.1);
  color: var(--st-color-primary);
  font-size: 0.76rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.su-title {
  font-size: clamp(1.7rem, 3vw, 2.5rem);
  line-height: 1.05;
  font-weight: 700;
  margin: 16px 0 10px;
  font-family: var(--st-font-family-heading);
}
.su-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 12px;
  margin-top: 18px;
}
.su-stat {
  padding: 14px;
  border-radius: 14px;
  background: rgba(250, 247, 244, 0.9);
  border: 1px solid rgba(221, 215, 208, 0.85);
}
.su-stat strong {
  display: block;
  font-size: 1rem;
  margin-bottom: 2px;
}
.su-panel {
  padding: 18px;
  border-radius: 18px;
  border: 1px solid var(--st-color-border);
  background: var(--st-color-bg);
  box-shadow: var(--st-shadow-sm);
  max-height: calc(100vh - 80px);
  overflow-y: auto;
}
.su-dropzone {
  margin-top: 14px;
  padding: 26px 18px;
  border: 1.5px dashed var(--st-color-border);
  border-radius: 16px;
  background: linear-gradient(180deg, rgba(242,237,231,0.4), rgba(250,247,244,0.95));
  text-align: center;
  transition: border-color var(--st-transition), transform var(--st-transition), background var(--st-transition);
}
.su-dropzone.is-dragging {
  border-color: var(--st-color-primary);
  background: rgba(26, 122, 110, 0.08);
  transform: translateY(-1px);
}
.su-file-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-top: 14px;
}
.su-file-row {
  padding: 12px;
  border-radius: 14px;
  border: 1px solid var(--st-color-border);
  background: var(--st-color-surface);
}
.su-file-meta {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}
.su-file-name {
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.su-status-pill {
  display: inline-flex;
  align-items: center;
  padding: 4px 8px;
  border-radius: 999px;
  font-size: 0.74rem;
  font-weight: 600;
  background: rgba(120, 113, 108, 0.12);
  color: var(--st-color-text-muted);
}
.su-status-pill.is-success { background: var(--st-color-success-light); color: var(--st-color-success); }
.su-status-pill.is-error { background: var(--st-color-error-light); color: var(--st-color-error); }
.su-status-pill.is-active { background: var(--st-color-primary-light); color: var(--st-color-primary); }
.su-progress {
  width: 100%;
  height: 10px;
  border-radius: 999px;
  background: rgba(120, 113, 108, 0.16);
  overflow: hidden;
  margin-top: 10px;
}
.su-progress > span {
  display: block;
  height: 100%;
  width: 0%;
  background: linear-gradient(90deg, var(--st-color-primary), #2fa28f);
  transition: width 180ms ease;
}
.su-log {
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-top: 14px;
}
.su-log li {
  padding: 10px 12px;
  border-radius: 12px;
  background: var(--st-color-surface);
  border: 1px solid var(--st-color-border);
  font-size: 0.85rem;
}
.su-log small {
  display: block;
  color: var(--st-color-text-muted);
  margin-top: 2px;
}
.su-alert {
  padding: 12px 14px;
  border-radius: 14px;
  border: 1px solid var(--st-color-border);
  background: var(--st-color-surface);
  margin-top: 14px;
}
.su-alert.is-error {
  border-color: rgba(192, 57, 43, 0.2);
  background: var(--st-color-error-light);
  color: var(--st-color-error);
}
.su-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-top: 14px;
}
.su-hidden { display: none !important; }
@media (max-width: 840px) {
  .su-shell { grid-template-columns: 1fr; }
  .su-grid { grid-template-columns: 1fr; }
}

/* ── Sessions: payment-method toggle and registration list ─────────
   Relocated verbatim from widget/sessions.html's <style> block.
   ──────────────────────────────────────────────────────────────── */
.st-pm-toggle {
  display: flex;
  gap: 8px;
  margin-top: 6px;
}
.st-pm-option {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 7px 16px;
  border-radius: 999px;
  border: 1.5px solid var(--st-color-border);
  background: transparent;
  color: var(--st-color-text);
  font-size: 0.8125rem;
  font-weight: 500;
  cursor: pointer;
  transition: border-color 0.15s, background 0.15s, color 0.15s;
  user-select: none;
}
.st-pm-option input[type="radio"] {
  position: absolute;
  opacity: 0;
  pointer-events: none;
  width: 0;
  height: 0;
}
.st-pm-option:hover {
  border-color: var(--st-color-primary);
  color: var(--st-color-primary);
}
.st-pm-option:has(input:checked) {
  background: var(--st-color-primary);
  border-color: var(--st-color-primary);
  color: #fff;
}
.st-day-section + .st-day-section {
  margin-top: 10px;
}
.st-day-section__title {
  font-size: 0.75rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--st-color-text-muted);
  margin-bottom: 4px;
}
.st-class-item {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 8px;
  border-radius: var(--st-radius-sm);
  margin-bottom: 4px;
  cursor: pointer;
}
.st-class-item:hover {
  background: var(--st-color-surface);
}
.st-class-item__body {
  display: flex;
  flex-direction: column;
  flex: 1;
  line-height: 1.3;
}
.st-class-item__title {
  font-size: 0.8125rem;
  font-weight: 500;
}
.st-studio-badge {
  font-size: 0.7rem;
  font-weight: 500;
  padding: 2px 8px;
  border-radius: 999px;
  border: 1px solid var(--st-color-border);
  white-space: nowrap;
}
.st-tl-cal {
  display: grid;
  grid-template-columns: 56px repeat(var(--st-tl-days), minmax(140px, 1fr));
  border: 1px solid var(--st-color-border);
  border-radius: var(--st-radius-sm);
  overflow: hidden;
  margin-bottom: 8px;
  min-width: max-content;
}
.st-tl-corner,
.st-tl-head {
  background: var(--st-color-surface);
  border-bottom: 1px solid var(--st-color-border);
  padding: 6px;
  font-size: 0.7rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--st-color-text-muted);
  text-align: center;
}
.st-tl-hour-label {
  font-size: 0.65rem;
  font-weight: 600;
  color: var(--st-color-text-muted);
  padding: 6px 6px 0;
  border-top: 1px solid var(--st-color-border);
  background: var(--st-color-surface);
  white-space: nowrap;
}
.st-tl-cell {
  border-top: 1px solid var(--st-color-border);
  border-left: 1px solid var(--st-color-border);
  padding: 4px;
  min-height: 40px;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.st-tl-card {
  padding: 4px 6px;
  border-radius: var(--st-radius-sm);
  border: 1px solid var(--st-color-border);
  border-left-width: 3px;
}
.st-tl-card__time {
  display: block;
  font-size: 0.65rem;
  font-weight: 600;
  color: var(--st-color-text-muted);
}
.st-tl-card__title {
  display: block;
  font-size: 0.78rem;
  font-weight: 500;
}
.st-tl-card__studio {
  display: block;
  font-size: 0.65rem;
  color: var(--st-color-text-muted);
}

/* ── Appointment booking widget ─────────────────────────────────────
   Composed from .st-card (the service tiles) and .st-day-section (the
   per-day slot groups); only what those cannot express lives here. */

.st-appt-service {
  display: flex;
  flex-direction: column;
  gap: 4px;
  text-align: left;
  width: 100%;
  cursor: pointer;
  font: inherit;
  color: inherit;
  border: 1px solid var(--st-color-border);
  transition: box-shadow var(--st-transition), border-color var(--st-transition);
}
.st-appt-service:hover {
  border-color: var(--st-color-primary);
  box-shadow: var(--st-shadow-sm);
}
.st-appt-service__name {
  font-size: 1rem;
  font-weight: 600;
  line-height: 1.3;
}
.st-appt-service__meta {
  font-size: 0.85rem;
  color: var(--st-color-primary);
  font-weight: 500;
}
.st-appt-service__desc {
  font-size: 0.85rem;
  color: var(--st-color-text-muted);
  line-height: 1.5;
}

.st-appt-summary {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 12px 14px;
}

.st-appt-nav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}

/* A width rather than a column count, so the grid fits the embed it is
   given instead of forcing three ~100px columns onto a phone — the defect
   the reviews list inherited from .st-gallery. */
.st-slot-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(104px, 1fr));
  gap: 6px;
}

.st-slot-btn {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1px;
  /* 44px tall: a slot button is the widget's primary tap target, and this
     is the minimum comfortable touch size. */
  min-height: 44px;
  justify-content: center;
  padding: 6px 8px;
  border: 1px solid var(--st-color-border);
  border-radius: var(--st-radius-sm);
  background: var(--st-color-surface);
  color: inherit;
  font: inherit;
  cursor: pointer;
  transition: background var(--st-transition), border-color var(--st-transition);
}
.st-slot-btn:hover {
  border-color: var(--st-color-primary);
  background: var(--st-color-surface-hover);
}
.st-slot-btn__time {
  font-size: 0.9rem;
  font-weight: 600;
  white-space: nowrap;
}
.st-slot-btn__staff {
  font-size: 0.7rem;
  color: var(--st-color-text-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 100%;
}

/* ══════════════════════════════════════════════════════════════════
   Utility layer — deliberately LAST so a utility always beats the
   component class it is composed with. It used to sit near the top,
   where `.st-form-group` (margin-bottom) and `.st-auth-tabs` silently
   beat a `.st-mb-*` written beside them and the utility did nothing.
   Anything added here must stay below every component rule.
   ══════════════════════════════════════════════════════════════ */
/* ── Utility classes ───────────────────────────────────────────────── */
.st-hidden           { display: none !important; }
/* Present for a crawler and a screen reader, invisible to a sighted user —
   unlike .st-hidden's display:none, which both would skip too. Same
   clip-to-nothing technique as .st-file-input, generalised. */
.st-sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}
.st-text-center      { text-align: center; }
.st-text-sm          { font-size: 0.85rem; }
.st-text-muted       { color: var(--st-color-text-muted); }
.st-flex             { display: flex; }
.st-gap-1            { gap: 4px; }
.st-gap-2            { gap: 8px; }
.st-gap-3            { gap: 12px; }
.st-justify-between  { justify-content: space-between; }
.st-justify-center   { justify-content: center; }
.st-align-center     { align-items: center; }
.st-mt-1 { margin-top: 4px; }
.st-mt-2 { margin-top: 10px; }
.st-mt-3 { margin-top: 18px; }
.st-mb-1 { margin-bottom: 4px; }
.st-mb-2 { margin-bottom: 10px; }
.st-mb-0 { margin-bottom: 0; }
.st-mb-3 { margin-bottom: 18px; }
.st-mx-2 { margin-inline: 8px; }
.st-w-full           { width: 100%; }
.st-m-0              { margin: 0; }
.st-shrink-0         { flex-shrink: 0; }
.st-text-xs          { font-size: 0.75rem; }
.st-font-semibold    { font-weight: 600; }
.st-font-bold        { font-weight: 700; }
.st-text-error       { color: var(--st-color-error); }
.st-text-primary     { color: var(--st-color-primary); }
.st-text-success     { color: var(--st-color-success); }

/* ── Mobile: tag sidebar becomes a bottom sheet ─────────────────────── */
@media (max-width: 639px) {

  /* Desktop tag sidebar hidden — becomes a bottom sheet */
  .st-tags-col {
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
    z-index: 200;
    width: 100%;
    max-height: 75vh;
    overflow-y: auto;
    background: var(--st-color-bg);
    border-top: 1px solid var(--st-color-border);
    border-radius: 16px 16px 0 0;
    padding: 12px var(--st-spacing) max(20px, env(safe-area-inset-bottom, 20px));
    transform: translateY(100%);
    transition: transform 280ms cubic-bezier(0.32, 0.72, 0, 1);
    box-shadow: 0 -8px 32px rgba(28, 25, 23, 0.16);
  }

  /* Drag handle */
  .st-tags-col::before {
    content: '';
    display: block;
    width: 36px;
    height: 4px;
    background: var(--st-color-border);
    border-radius: 2px;
    margin: 0 auto 14px;
  }

  .st-tags-col.st-sheet-open {
    transform: translateY(0);
  }

  /* ── Gallery: single-column layout, filter sidebar becomes bottom sheet ─ */
  .st-gallery-layout {
    flex-direction: column;
    gap: 0;
    padding-inline: 0;
  }

  /* Hide sidebar — JS shows it as a sheet */
  .st-tags-col#tag-sidebar {
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
    z-index: 200;
    width: 100%;
    max-height: 80vh;
    overflow-y: auto;
    background: var(--st-color-bg);
    border-top: 1px solid var(--st-color-border);
    border-radius: 16px 16px 0 0;
    padding: 12px var(--st-spacing) max(20px, env(safe-area-inset-bottom, 20px));
    transform: translateY(100%);
    transition: transform 280ms cubic-bezier(0.32, 0.72, 0, 1);
    box-shadow: 0 -8px 32px rgba(28, 25, 23, 0.16);
    display: block !important; /* override inline display:none — transform hides it */
  }

  /* Drag handle for gallery filter sheet */
  .st-tags-col#tag-sidebar::before {
    content: '';
    display: block;
    width: 36px;
    height: 4px;
    background: var(--st-color-border);
    border-radius: 2px;
    margin: 0 auto 14px;
  }

  .st-tags-col#tag-sidebar.st-sheet-open {
    transform: translateY(0);
  }

  .st-gallery-main {
    width: 100%;
  }

  /* Mobile filter button bar */
  .st-gallery-filter-bar {
    padding: 10px var(--st-spacing) 4px;
  }

  /* Gallery: 2-col on mobile. The count comes from the base rule; this only
     tightens the gap, so no breakpoint sets columns in two places. */
  .st-gallery {
    gap: 8px;
  }

  /* ── Prevent iOS Safari zoom on input focus (requires font-size ≥ 16px) */
  .st-input,
  .st-input-sm,
  select.st-input,
  textarea.st-input {
    font-size: 16px !important;
  }

  /* ── Tag picker: larger touch targets ───────────────────────────── */

  /* Each tag row: min 48px tall, more padding */
  .st-tag-row {
    min-height: 48px;
  }
  .st-tag-row .st-tag-btn {
    padding: 12px 10px;
    font-size: 1rem;
    gap: 12px;
  }

  /* Bigger checkbox */
  .st-tag-check {
    width: 22px;
    height: 22px;
    border-radius: 5px;
    flex-shrink: 0;
  }
  .st-tag-btn.active .st-tag-check::after {
    width: 6px;
    height: 10px;
  }

  /* ── Inventory modal: full-width, taller on mobile ───────────── */
  .st-modal-overlay {
    padding: 0;
    align-items: flex-end !important;
  }
  .st-modal-content {
    max-width: 100% !important;
    width: 100% !important;
    max-height: 92vh !important;
    border-radius: 16px 16px 0 0;
    padding-bottom: max(16px, env(safe-area-inset-bottom, 16px));
  }

  /* Public inventory item page */
  .st-inv-public-card {
    overflow-wrap: anywhere;
  }

  .st-inv-public-image {
    width: 100%;
    height: auto;
  }

  @media (max-width: 639px) {
    .st-inv-public {
      padding: 12px !important;
    }

    .st-inv-public-card {
      padding: 16px !important;
    }

    .st-inv-public-title {
      font-size: 1.25rem !important;
    }

    .st-inv-public-price {
      font-size: 1.5rem !important;
    }

    .st-inv-public-cta {
      width: 100%;
      text-align: center;
      min-height: 44px;
    }
  }
}
