:root {
  --brand: #8a5a34;
  --bg: #faf7f2;
}

body {
  background: var(--bg);
  font-family: 'Outfit', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  /* Defensive, app-wide: a single element that doesn't fit its container
     (the settings tabs row was one; there have been several others over
     time, see the mobile-overflow gotchas below) shouldn't be able to
     widen the whole document and force horizontal scroll/a stray white
     gutter down one side. Individual elements that need to scroll
     sideways on purpose (the filter row, filmstrip, filter presets) keep
     their own explicit `overflow-x: auto` and are unaffected by this. */
  overflow-x: hidden;
}

/* Guarantee the native [hidden] attribute always wins, even on elements
   whose class sets display:flex/inline-flex (e.g. .kkm-toolbar, .kkm-tabs). */
[hidden] {
  display: none !important;
}

.kkm-login-body {
  overflow-x: hidden;
}

.kkm-auth-shell {
  position: relative;
  z-index: 1;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}

.kkm-auth-card {
  width: 100%;
  max-width: 360px;
  text-align: center;
}

.kkm-login-logo {
  width: 84px;
  height: 84px;
  margin-bottom: 14px;
  filter: drop-shadow(0 0 24px rgba(255, 248, 220, 0.25));
}

.kkm-login-brand {
  margin: 0;
  font-size: 1.1rem;
  font-weight: 700;
  color: var(--kkm-text, #f3f4f1);
  letter-spacing: 0.02em;
}

.kkm-login-tagline {
  margin: 6px 0 22px;
  color: var(--kkm-text-muted, #98a19a);
  font-size: 0.95rem;
  font-style: italic;
}

.kkm-login-card {
  text-align: left;
  backdrop-filter: blur(6px);
  background: rgba(42, 45, 42, 0.85) !important;
}

.kkm-password-field {
  position: relative;
}

.kkm-password-field .uk-input {
  padding-right: 42px;
}

.kkm-password-toggle {
  position: absolute;
  top: 50%;
  right: 2px;
  transform: translateY(-50%);
  background: transparent;
  border: none;
  color: var(--kkm-text-muted, #98a19a);
  cursor: pointer;
  padding: 8px;
  display: flex;
  align-items: center;
  justify-content: center;
}

.kkm-password-toggle:hover {
  color: var(--kkm-text, #f3f4f1);
}

/* ---- Animated night sky ---- */
.kkm-night-sky {
  position: fixed;
  inset: 0;
  overflow: hidden;
  z-index: 0;
  background: linear-gradient(180deg, #0a0e26 0%, #141a3d 45%, #232a52 100%);
}

.kkm-stars {
  position: absolute;
  inset: -10% -10%;
  background-image: radial-gradient(1.5px 1.5px at 10% 20%, rgba(255, 255, 255, 0.9), transparent 60%),
    radial-gradient(1.5px 1.5px at 35% 65%, rgba(255, 255, 255, 0.75), transparent 60%),
    radial-gradient(1px 1px at 55% 15%, rgba(255, 255, 255, 0.8), transparent 60%),
    radial-gradient(2px 2px at 75% 45%, rgba(255, 255, 255, 0.6), transparent 60%),
    radial-gradient(1px 1px at 90% 75%, rgba(255, 255, 255, 0.9), transparent 60%),
    radial-gradient(1.5px 1.5px at 15% 85%, rgba(255, 255, 255, 0.5), transparent 60%),
    radial-gradient(1px 1px at 65% 90%, rgba(255, 255, 255, 0.8), transparent 60%),
    radial-gradient(2px 2px at 45% 35%, rgba(255, 255, 255, 0.65), transparent 60%);
  background-size: 320px 320px;
  background-repeat: repeat;
  animation: kkm-twinkle 2.2s ease-in-out infinite alternate;
}

@keyframes kkm-twinkle {
  from {
    opacity: 0.55;
  }
  to {
    opacity: 1;
  }
}

.kkm-moon {
  position: absolute;
  top: 9%;
  right: 10%;
  width: 100px;
  height: 100px;
  border-radius: 50%;
  background: radial-gradient(circle at 35% 35%, #fffdf2 0%, #f5eecb 55%, #e4d9a0 100%);
  box-shadow: 0 0 50px 12px rgba(255, 248, 220, 0.35), 0 0 130px 45px rgba(255, 248, 220, 0.15);
}

.kkm-moon::before,
.kkm-moon::after {
  content: '';
  position: absolute;
  border-radius: 50%;
  background: rgba(210, 195, 150, 0.35);
}

.kkm-moon::before {
  width: 20px;
  height: 20px;
  top: 25px;
  left: 20px;
}

.kkm-moon::after {
  width: 14px;
  height: 14px;
  top: 55px;
  left: 55px;
}

.kkm-cloud {
  position: absolute;
  background: rgba(255, 255, 255, 0.9);
  border-radius: 50px;
}

.kkm-cloud::before,
.kkm-cloud::after {
  content: '';
  position: absolute;
  background: inherit;
  border-radius: 50%;
}

@keyframes kkm-drift {
  from {
    transform: translateX(0);
  }
  to {
    transform: translateX(calc(100vw + 400px));
  }
}

.kkm-cloud-1 {
  width: 140px;
  height: 44px;
  top: 14%;
  left: -220px;
  opacity: 0.8;
  animation: kkm-drift 16s linear infinite;
}
.kkm-cloud-1::before {
  width: 70px;
  height: 70px;
  top: -36px;
  left: 18px;
}
.kkm-cloud-1::after {
  width: 50px;
  height: 50px;
  top: -24px;
  right: 20px;
}

.kkm-cloud-2 {
  width: 100px;
  height: 32px;
  top: 30%;
  left: -180px;
  opacity: 0.55;
  animation: kkm-drift 22s linear infinite;
  animation-delay: -6s;
}
.kkm-cloud-2::before {
  width: 50px;
  height: 50px;
  top: -25px;
  left: 12px;
}
.kkm-cloud-2::after {
  width: 36px;
  height: 36px;
  top: -16px;
  right: 14px;
}

.kkm-cloud-3 {
  width: 170px;
  height: 50px;
  top: 58%;
  left: -260px;
  opacity: 0.45;
  animation: kkm-drift 28s linear infinite;
  animation-delay: -12s;
}
.kkm-cloud-3::before {
  width: 85px;
  height: 85px;
  top: -42px;
  left: 25px;
}
.kkm-cloud-3::after {
  width: 60px;
  height: 60px;
  top: -28px;
  right: 25px;
}

.kkm-cloud-4 {
  width: 110px;
  height: 36px;
  top: 76%;
  left: -200px;
  opacity: 0.35;
  animation: kkm-drift 19s linear infinite;
  animation-delay: -3s;
}
.kkm-cloud-4::before {
  width: 55px;
  height: 55px;
  top: -28px;
  left: 14px;
}
.kkm-cloud-4::after {
  width: 40px;
  height: 40px;
  top: -18px;
  right: 16px;
}

@media (max-width: 600px) {
  .kkm-moon {
    width: 64px;
    height: 64px;
    top: 6%;
    right: 8%;
  }
}

@media (prefers-reduced-motion: reduce) {
  .kkm-stars,
  .kkm-cloud {
    animation: none;
  }
}

#gallery-title {
  display: flex;
  align-items: center;
  gap: 10px;
  color: var(--kkm-text, #f3f4f1);
}

/* Padding, not margin — the gallery page's outer container is body's first
   and only child with no sibling/border/padding above it, so a top MARGIN
   here collapses straight through body's own box and reveals the default
   white <html> background as a band above the (otherwise full-height,
   dark-backgrounded) body. Padding never collapses like this. Doesn't come
   up on Portfolio/Settings because their shell (`.kkm-shell`) is a flex
   container, and flex items never margin-collapse with their container. */
.kkm-gallery-container {
  padding-top: 20px;
  padding-bottom: 20px;
}

.kkm-photo-caption {
  font-size: 0.8rem;
  color: var(--kkm-text-muted, #98a19a);
  margin-top: 4px;
  word-break: break-word;
}

.kkm-editor-canvas-wrap {
  max-width: 100%;
  max-height: 60vh;
  overflow: hidden;
  background: #222;
}

.kkm-editor-canvas-wrap img {
  display: block;
  max-width: 100%;
}

/* Upload modal: image alone on the left; editing tools (rotate/perspective/
   filters/sliders) stacked above the name/tags/client fields on the right.
   `#crop-editor-view` and `#perspective-editor` (the two mode panels, only
   one ever visible — toggled the same as always via the `hidden` attribute,
   which the global `[hidden] { display: none !important }` rule above
   still wins over `display: contents` below) each contribute one item into
   the "image" area and one into the "tools" area rather than being laid
   out as their own boxes — `display: contents` lets a wrapper's children
   join the parent grid directly, which is what makes that split possible
   without restructuring how JS shows/hides each mode. */
.kkm-upload-editor-layout {
  display: grid;
  grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr);
  grid-template-areas:
    'image tools'
    'image fields';
  gap: 28px;
  align-items: start;
}

#crop-editor-view,
.kkm-perspective-editor,
#collage-editor-view {
  display: contents;
}

.kkm-upload-grid-image {
  grid-area: image;
}

.kkm-upload-grid-tools {
  grid-area: tools;
}

.kkm-upload-grid-fields {
  grid-area: fields;
}

.kkm-editor-tools {
  padding-top: 4px;
}

.kkm-editor-controls-row {
  display: flex;
  gap: 10px;
  margin: 14px 0;
}

.kkm-editor-sliders-row {
  display: flex;
  align-items: flex-end;
  gap: 20px;
  margin-bottom: 12px;
}

.kkm-filter-presets-row {
  display: flex;
  gap: 14px;
  margin: 14px 0;
  overflow-x: auto;
  padding-bottom: 4px;
}

.kkm-filter-preset-btn {
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
  color: var(--kkm-text-muted, #98a19a);
}

.kkm-filter-preset-thumb {
  display: block;
  width: 64px;
  height: 64px;
  border-radius: 10px;
  overflow: hidden;
  background: var(--kkm-card-bg, #2a2d2a);
  border: 2px solid var(--kkm-border, #383b38);
}

.kkm-filter-preset-thumb-img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.kkm-filter-preset-label {
  font-size: 0.78rem;
  font-weight: 600;
  white-space: nowrap;
}

.kkm-filter-preset-btn:hover .kkm-filter-preset-thumb {
  border-color: var(--kkm-accent, #3ecf8e);
}

.kkm-filter-preset-btn:hover .kkm-filter-preset-label {
  color: var(--kkm-text, #f3f4f1);
}

.kkm-filter-preset-btn.kkm-filter-preset-active .kkm-filter-preset-thumb {
  border-color: var(--kkm-accent, #3ecf8e);
  box-shadow: 0 0 0 1px var(--kkm-accent, #3ecf8e);
}

.kkm-filter-preset-btn.kkm-filter-preset-active .kkm-filter-preset-label {
  color: var(--kkm-text, #f3f4f1);
}

.kkm-editor-sliders-row .kkm-icon-btn {
  flex-shrink: 0;
}

.kkm-slider-field {
  flex: 1 1 0;
}

.kkm-slider-field label {
  display: block;
  font-size: 0.8rem;
  color: var(--kkm-text-muted, #98a19a);
  margin-bottom: 6px;
}

.kkm-slider-field input[type='range'] {
  width: 100%;
}

/* Collage builder: a square canvas of absolutely-positioned slots (rects
   computed by collage-layout.js from each photo's aspect ratio), each
   filled with that photo's cover-fit preview. Tap-tap-to-swap needs no
   drag-and-drop and works identically on touch — see upload.js. */
.kkm-collage-canvas-wrap {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.kkm-collage-canvas {
  position: relative;
  width: 100%;
  aspect-ratio: 1 / 1;
  background: var(--kkm-bg, #1b1e1c);
  border-radius: 10px;
  overflow: hidden;
}

.kkm-collage-slot {
  position: absolute;
  overflow: hidden;
  /* Every slot is draggable now, not just the selected one — tap-to-select
     and drag-to-reposition/swap are independent gestures (see upload.js),
     so this hints "grab to move" regardless of selection state. */
  cursor: grab;
  box-shadow: 0 0 0 2px var(--kkm-bg, #1b1e1c);
  /* Touch: this element owns the gesture (drag-to-reposition/swap) the
     moment a touch starts on it, so the browser must not also interpret
     it as a page-scroll/pinch-zoom gesture — see the 2026-09-02 mobile
     entry in CLAUDE.md for why `touch-action: none` alone (not just the
     pointerdown `preventDefault()` already in upload.js) is required. */
  touch-action: none;
  -webkit-user-select: none;
  user-select: none;
  /* Long-press on a touch device would otherwise pop a native "save/copy
     image" callout mid-drag. */
  -webkit-touch-callout: none;
}

.kkm-collage-slot img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  pointer-events: none;
  -webkit-user-drag: none;
  transition: transform 0.18s ease, opacity 0.18s ease;
}

.kkm-collage-slot-selected {
  box-shadow: 0 0 0 3px var(--kkm-accent, #3ecf8e);
  z-index: 1;
}

/* Live preview of "drop here to swap" while dragging a different photo
   over this slot — see the pointermove handler in upload.js. Dashed so it
   reads as a pending/proposed state, distinct from the solid accent ring
   on an actively tap-selected slot. The slot box itself stays put (it's
   still positioned/sized by the layout rect); only its *photo* shrinks and
   fades, previewing "this one is about to be swapped out." */
.kkm-collage-slot-drop-target {
  box-shadow: 0 0 0 3px var(--kkm-bg, #1b1e1c), 0 0 0 6px var(--kkm-accent, #3ecf8e);
  outline: 2px dashed var(--kkm-accent, #3ecf8e);
  outline-offset: -2px;
  z-index: 2;
}

.kkm-collage-slot-drop-target img {
  transform: scale(0.82);
  opacity: 0.45;
}

/* Toggled on <body> for the duration of any active collage-slot drag (see
   upload.js) — set globally rather than on the dragged/hovered slot alone
   so the cursor stays "grabbing" even if a fast mouse move momentarily
   outruns pointer capture and crosses over some other element. No visible
   effect on touch (no cursor there), which is fine — it's a mouse-only cue. */
body.kkm-collage-dragging,
body.kkm-collage-dragging .kkm-collage-slot {
  cursor: grabbing;
}

.kkm-collage-slot-remove {
  position: absolute;
  top: 6px;
  right: 6px;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  border: none;
  background: rgba(0, 0, 0, 0.55);
  color: #fff;
  font-size: 0.95rem;
  line-height: 1;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
}

.kkm-collage-slot-remove:hover {
  background: rgba(0, 0, 0, 0.8);
}

.kkm-collage-hint {
  margin: 0;
}

/* Tile-layout template picker — same pill-row shape as the filter presets
   strip elsewhere in this editor, just text-only labels instead of preview
   thumbnails (a layout applies to the whole set, not one photo, so there's
   no single "current photo" to render a thumbnail from). */
.kkm-collage-layout-picker {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin: 6px 0 14px;
}

.kkm-collage-layout-btn {
  flex-shrink: 0;
  background: var(--kkm-card-bg, #2a2d2a);
  border: 1px solid var(--kkm-border, #383b38);
  color: var(--kkm-text-muted, #98a19a);
  padding: 6px 14px;
  border-radius: 999px;
  font-size: 0.82rem;
  font-weight: 600;
  cursor: pointer;
}

.kkm-collage-layout-btn:hover {
  color: var(--kkm-text, #f3f4f1);
  border-color: var(--kkm-accent, #3ecf8e);
}

.kkm-collage-layout-active {
  background: var(--kkm-accent, #3ecf8e);
  border-color: var(--kkm-accent, #3ecf8e);
  color: #0e1410;
}

@media (max-width: 767px) {
  .kkm-upload-editor-layout {
    /* minmax(0, 1fr), not a bare 1fr — grid tracks default to a
       content-based minimum width, so a bare 1fr still won't shrink
       below whatever the widest child (e.g. the filter-preset strip)
       wants, and the modal overflows horizontally. Same root cause as
       the flexbox version of this bug documented elsewhere in this file
       (CLAUDE.md gotcha #5) — a different layout mode, identical fix. */
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas:
      'image'
      'tools'
      'fields';
  }
}

/* Batch-upload filmstrip — one thumbnail per photo in the current batch */
.kkm-filmstrip {
  display: flex;
  gap: 10px;
  overflow-x: auto;
  padding-top: 6px;
  padding-bottom: 10px;
  margin-bottom: 16px;
}

.kkm-filmstrip-item-wrap {
  position: relative;
  flex-shrink: 0;
}

.kkm-filmstrip-item {
  display: block;
  width: 56px;
  height: 56px;
  border-radius: 8px;
  overflow: hidden;
  border: 2px solid transparent;
  padding: 0;
  cursor: pointer;
  background: var(--kkm-card-bg, #2a2d2a);
}

.kkm-filmstrip-item img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.kkm-filmstrip-item.kkm-filmstrip-active {
  border-color: var(--kkm-accent, #3ecf8e);
}

.kkm-filmstrip-item.kkm-filmstrip-incomplete {
  border-color: #ff6b6b;
}

.kkm-filmstrip-incomplete-badge {
  position: absolute;
  bottom: -4px;
  right: -4px;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: #ff6b6b;
  color: #fff;
  border: 2px solid var(--kkm-card-bg, #2a2d2a);
  font-size: 10px;
  font-weight: 700;
  line-height: 16px;
  text-align: center;
}

.kkm-filmstrip-remove {
  position: absolute;
  top: -6px;
  right: -6px;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: #d9534f;
  color: #fff;
  border: 2px solid var(--kkm-card-bg, #2a2d2a);
  font-size: 11px;
  line-height: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  padding: 0;
}

/* Gallery mode: per-thumbnail swipe-order number, shown instead of the
   incomplete-badge (galleries have no per-item required fields, so nothing
   to flag incomplete). */
.kkm-filmstrip-order-badge {
  position: absolute;
  bottom: -4px;
  left: -4px;
  min-width: 16px;
  height: 16px;
  padding: 0 3px;
  border-radius: 8px;
  background: var(--kkm-accent, #3ecf8e);
  color: #0e1410;
  border: 2px solid var(--kkm-card-bg, #2a2d2a);
  font-size: 10px;
  font-weight: 700;
  line-height: 12px;
  text-align: center;
}

/* Gallery mode: press-and-drag a thumbnail to reorder it. touch-action:none
   stops the browser's own touch-scroll from fighting the drag the instant a
   touch starts on the thumbnail — same reasoning as the collage slot drag. */
.kkm-filmstrip-draggable {
  cursor: grab;
  touch-action: none;
  -webkit-user-select: none;
  user-select: none;
}

body.kkm-filmstrip-dragging,
body.kkm-filmstrip-dragging .kkm-filmstrip-draggable {
  cursor: grabbing;
}

/* While dragging: the original collapses (a floating ghost follows the
   pointer instead) and a dashed placeholder marks the slot it will drop into. */
.kkm-filmstrip-dragging-item {
  width: 0;
  margin-right: -10px; /* cancels the flex gap the collapsed item would leave */
  overflow: hidden;
  opacity: 0;
}

.kkm-filmstrip-placeholder {
  flex-shrink: 0;
  box-sizing: border-box;
  width: 56px;
  height: 56px;
  border-radius: 8px;
  border: 2px dashed var(--kkm-accent, #3ecf8e);
  background: rgba(62, 207, 142, 0.1);
  animation: kkm-placeholder-pulse 1s ease-in-out infinite;
}

@keyframes kkm-placeholder-pulse {
  0%, 100% { background: rgba(62, 207, 142, 0.06); }
  50% { background: rgba(62, 207, 142, 0.18); }
}

.kkm-filmstrip-ghost {
  position: fixed;
  z-index: 5500;
  width: 64px;
  height: 64px;
  margin: -32px 0 0 -32px; /* centered on the pointer */
  border-radius: 10px;
  overflow: hidden;
  border: 2px solid var(--kkm-accent, #3ecf8e);
  box-shadow: 0 10px 26px rgba(0, 0, 0, 0.5);
  transform: rotate(4deg) scale(1.08);
  opacity: 0.95;
  pointer-events: none;
}

.kkm-filmstrip-ghost img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* After a drop: the moved thumbnail blinks a few times so you can see where it landed. */
.kkm-filmstrip-just-moved .kkm-filmstrip-item {
  animation: kkm-filmstrip-blink 0.45s ease-in-out 3;
}

@keyframes kkm-filmstrip-blink {
  0%, 100% { opacity: 1; box-shadow: 0 0 0 0 rgba(62, 207, 142, 0); }
  50% { opacity: 0.25; box-shadow: 0 0 0 4px rgba(62, 207, 142, 0.9); }
}

@media (prefers-reduced-motion: reduce) {
  .kkm-filmstrip-placeholder,
  .kkm-filmstrip-just-moved .kkm-filmstrip-item {
    animation: none;
  }
  .kkm-filmstrip-just-moved .kkm-filmstrip-item {
    box-shadow: 0 0 0 3px var(--kkm-accent, #3ecf8e);
  }
}

.kkm-filmstrip-hint {
  margin: -8px 0 12px;
}

/* A dashed "+" tile at the end of the filmstrip, same size as a thumbnail —
   putting "add more" right next to the photos themselves, instead of only
   in the modal footer where it's easy to miss (especially below the fold
   on a phone). */
.kkm-filmstrip-add-tile {
  flex-shrink: 0;
  width: 56px;
  height: 56px;
  border-radius: 8px;
  border: 2px dashed var(--kkm-border);
  background: transparent;
  color: var(--kkm-text);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  opacity: 0.75;
}

.kkm-filmstrip-add-tile:hover {
  opacity: 1;
  border-color: var(--kkm-accent, #3ecf8e);
  color: var(--kkm-accent, #3ecf8e);
}

/* Gallery upload mode: the shared name/categories/tags/client fields apply
   to every image in the set, not just whichever one the filmstrip currently
   shows — this note sits above them as a reminder. */
.kkm-gallery-fields-note {
  margin: 0 0 12px;
  padding: 8px 12px;
  border-radius: 8px;
  background: rgba(62, 207, 142, 0.1);
  border: 1px solid rgba(62, 207, 142, 0.3);
  color: var(--kkm-text-muted);
  font-size: 0.8rem;
}

.kkm-saved-indicator {
  color: var(--kkm-accent, #3ecf8e);
  font-size: 0.8rem;
  margin-left: 10px;
}

/* Perspective correction: draggable-corner stage */
.kkm-perspective-stage {
  position: relative;
  max-width: 100%;
  user-select: none;
  touch-action: none;
  background: #222;
}

.kkm-perspective-stage img {
  display: block;
  width: 100%;
  height: auto;
  pointer-events: none;
}

.kkm-perspective-outline {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
}

.kkm-perspective-outline polygon {
  fill: rgba(62, 207, 142, 0.15);
  stroke: var(--kkm-accent, #3ecf8e);
  stroke-width: 2;
  vector-effect: non-scaling-stroke;
}

.kkm-perspective-handle {
  position: absolute;
  width: 22px;
  height: 22px;
  margin-left: -11px;
  margin-top: -11px;
  border-radius: 50%;
  background: var(--kkm-accent, #3ecf8e);
  border: 2px solid #0e1410;
  cursor: grab;
  touch-action: none;
}

/* Invisible 48px hit area (the dot itself stays 22px) — a fingertip can't
   reliably land on 22px, especially on a corner. */
.kkm-perspective-handle::before {
  content: '';
  position: absolute;
  inset: -14px;
  border-radius: 50%;
}

.kkm-perspective-handle:active {
  cursor: grabbing;
}

.kkm-perspective-actions {
  display: flex;
  gap: 10px;
  margin-top: 14px;
}

.kkm-links-table td {
  vertical-align: middle;
}

/* Settings page tabs — Material-style segmented control with sliding indicator.
   max-width + overflow-x is a safety net (mobile-first: this row has no
   business ever being wider than its container) on top of the mobile
   compacting below — with 3 tabs including the long "Before/After" label,
   the compacted sizes fit on every phone width tested, but this still
   holds even if that stops being true on some narrower device rather than
   forcing the whole page into horizontal scroll again (see the body-level
   overflow-x:hidden note above — that was this exact bug). */
.kkm-tabs {
  position: relative;
  display: inline-flex;
  gap: 2px;
  padding: 4px;
  background: var(--kkm-card-bg);
  border: 1px solid var(--kkm-border);
  border-radius: 14px;
  max-width: 100%;
  overflow-x: auto;
}

.kkm-tab-indicator {
  position: absolute;
  top: 4px;
  bottom: 4px;
  left: 4px;
  width: 0;
  border-radius: 10px;
  background: var(--kkm-accent);
  transition: transform 0.28s cubic-bezier(0.4, 0, 0.2, 1), width 0.28s cubic-bezier(0.4, 0, 0.2, 1);
  z-index: 0;
}

.kkm-tab {
  position: relative;
  z-index: 1;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  flex-shrink: 0;
  background: transparent;
  border: none;
  color: var(--kkm-text-muted);
  padding: 9px 18px;
  border-radius: 10px;
  cursor: pointer;
  font-size: 0.9rem;
  font-weight: 600;
  transition: color 0.2s ease;
  white-space: nowrap;
}

.kkm-tab:hover {
  color: var(--kkm-text);
}

.kkm-tab.kkm-tab-active {
  color: #0e1410;
}

.kkm-tab-count {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 20px;
  height: 20px;
  padding: 0 6px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.08);
  color: var(--kkm-text-muted);
  font-size: 0.72rem;
  font-weight: 700;
  transition: background 0.2s ease, color 0.2s ease;
}

.kkm-tab.kkm-tab-active .kkm-tab-count {
  background: rgba(14, 20, 16, 0.18);
  color: #0e1410;
}

/* Action bar: tabs on the left, contextual selection actions on the right */
.kkm-action-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 12px;
  margin-bottom: 20px;
}

.kkm-action-bar .kkm-toolbar {
  margin-bottom: 0;
}

/* Sortable links table headers */
.kkm-sortable {
  cursor: pointer;
  user-select: none;
  white-space: nowrap;
}

.kkm-sortable:hover {
  color: var(--kkm-text);
}

.kkm-sort-arrow {
  display: inline-block;
  width: 0.8em;
  opacity: 0.6;
}

.kkm-links-th-check {
  width: 32px;
}

/* Responsive (stacked-card) links table */
@media (max-width: 700px) {
  .kkm-responsive-table thead {
    display: none;
  }

  .kkm-responsive-table,
  .kkm-responsive-table tbody,
  .kkm-responsive-table tr,
  .kkm-responsive-table td {
    display: block;
    width: 100%;
  }

  .kkm-responsive-table tr {
    box-sizing: border-box;
    margin-bottom: 12px;
    border: 1px solid var(--kkm-border);
    border-radius: 10px;
    padding: 10px 12px;
  }

  .kkm-responsive-table td {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 6px 12px;
    padding: 6px 0;
    border: none !important;
    text-align: right;
    white-space: normal;
  }

  .kkm-responsive-table td > a,
  .kkm-responsive-table td > span {
    min-width: 0;
    overflow-wrap: anywhere;
  }

  .kkm-responsive-table td[data-label='Actions'] {
    justify-content: flex-end;
  }

  .kkm-responsive-table td[data-label]::before {
    content: attr(data-label);
    font-weight: 600;
    color: var(--kkm-text-muted);
    text-align: left;
  }

  .kkm-responsive-table td.kkm-td-check {
    justify-content: flex-start;
  }

  .kkm-responsive-table td.kkm-td-check::before {
    content: 'Select';
    font-weight: 600;
    color: var(--kkm-text-muted);
  }
}

.kkm-empty {
  color: #888;
  padding: 2rem 0;
  text-align: center;
}

/* Public gallery loading spinner — real percentage, not indeterminate */
.kkm-gallery-loader {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 12px;
  padding: 60px 0;
  position: relative;
}

.kkm-gallery-loader-ring {
  width: 64px;
  height: 64px;
  transform: rotate(-90deg);
}

.kkm-gallery-loader-track,
.kkm-gallery-loader-fill {
  fill: none;
  stroke-width: 6;
}

.kkm-gallery-loader-track {
  stroke: var(--kkm-border, #383b38);
}

.kkm-gallery-loader-fill {
  stroke: var(--kkm-accent, #3ecf8e);
  stroke-linecap: round;
  stroke-dasharray: 213.6;
  stroke-dashoffset: 213.6;
  transition: stroke-dashoffset 0.2s ease;
}

.kkm-gallery-loader-pct {
  color: var(--kkm-text-muted, #98a19a);
  font-size: 0.9rem;
  font-weight: 600;
}

/* Same ring+percentage, repurposed as a blocking overlay on top of the
   upload modal while a save is in flight — replaces a small status-text
   line at the bottom of the fields column that was too easy to miss.
   `position: fixed` (not `absolute`) is deliberate: the modal dialog can be
   taller than the viewport and scroll internally (long field list on a
   small phone screen), and an `absolute` overlay anchors to that full
   scrollable box, not the visible viewport — so its centered content sits
   at the midpoint of content the user may have scrolled well past,
   forcing them to scroll back to the top of the modal just to see it.
   `position: fixed` alone isn't enough, though: `.uk-modal-dialog` carries
   a lingering `transform: matrix(1,0,0,1,0,0)` from UIkit's own show/hide
   transition machinery (an identity matrix — visually a no-op, but a
   non-`none` transform value still establishes a CSS containing block for
   `position: fixed` descendants regardless of whether it visibly does
   anything). That silently turned `fixed` right back into `absolute`
   relative to the dialog. Confirmed empirically by walking the ancestor
   chain's computed `transform` in a real browser, not by reading the CSS —
   the fix that actually works is in the markup (`settings.html`): this
   element lives as a *sibling* of `.uk-modal-dialog`, a direct child of
   `#upload-modal` (the outer `.uk-modal` container, which UIkit gives
   `position: fixed; inset: 0` and no transform of its own), so it's never
   inside the transformed dialog's containing block in the first place. */
.kkm-save-progress-overlay {
  position: fixed;
  inset: 0;
  z-index: 1020;
  background: rgba(14, 16, 13, 0.94);
  padding: 0;
}

.kkm-save-progress-label {
  color: var(--kkm-text, #f3f4f1);
  font-size: 0.95rem;
  font-weight: 600;
}

/* ===== Dark app shell (public feed + upload/links pages) ===== */

body.kkm-dark {
  --kkm-bg: #1b1e1c;
  --kkm-sidebar-bg: #141613;
  --kkm-card-bg: #2a2d2a;
  --kkm-accent: #3ecf8e;
  --kkm-text: #f3f4f1;
  --kkm-text-muted: #98a19a;
  --kkm-border: #383b38;

  background: var(--kkm-bg);
  color: var(--kkm-text);
  min-height: 100vh;
}

body.kkm-dark a {
  color: var(--kkm-text);
}

.kkm-shell {
  display: flex;
  min-height: 100vh;
  align-items: flex-start;
}

.kkm-sidebar {
  width: 240px;
  flex-shrink: 0;
  background: var(--kkm-sidebar-bg);
  height: 100vh;
  padding: 20px 14px;
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  position: sticky;
  top: 0;
  transition: width 0.15s ease;
  overflow: hidden;
}

.kkm-sidebar.kkm-collapsed {
  width: 76px;
}

.kkm-sidebar-toggle {
  background: transparent;
  border: none;
  color: var(--kkm-text-muted);
  cursor: pointer;
  padding: 8px;
  margin-bottom: 20px;
  align-self: flex-start;
  border-radius: 8px;
}

.kkm-sidebar-toggle:hover {
  background: rgba(255, 255, 255, 0.05);
  color: var(--kkm-text);
}

.kkm-sidebar.kkm-collapsed .kkm-sidebar-toggle {
  align-self: center;
  width: 44px;
  height: 44px;
  padding: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}

.kkm-sidebar-brand {
  display: flex;
  align-items: center;
  gap: 10px;
  font-weight: 700;
  font-size: 0.85rem;
  line-height: 1.25;
  color: var(--kkm-text) !important;
  margin-bottom: 24px;
  letter-spacing: 0.01em;
  text-decoration: none;
  padding: 0 12px;
  white-space: normal;
  word-break: break-word;
}

.kkm-sidebar-logo {
  width: 28px;
  height: 28px;
  flex-shrink: 0;
}

.kkm-sidebar.kkm-collapsed .kkm-sidebar-brand {
  flex-direction: column;
  justify-content: flex-start;
  gap: 4px;
  padding: 0;
  text-align: center;
}

.kkm-sidebar.kkm-collapsed .kkm-sidebar-logo {
  width: 22px;
  height: 22px;
}

.kkm-sidebar.kkm-collapsed .kkm-sidebar-brand .kkm-sidebar-label {
  display: block;
  font-size: 0.5rem;
  line-height: 1.2;
  white-space: normal;
  word-break: break-word;
}

.kkm-sidebar-nav {
  list-style: none;
  margin: 0;
  padding: 0;
}

.kkm-sidebar-nav li + li {
  margin-top: 4px;
}

.kkm-sidebar-nav a,
.kkm-sidebar-footer a,
.kkm-sidebar-footer button {
  width: 100%;
  background: transparent;
  border: none;
  cursor: pointer;
  font: inherit;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 12px;
  border-radius: 8px;
  color: var(--kkm-text-muted) !important;
  text-decoration: none;
  font-size: 0.95rem;
  white-space: nowrap;
  overflow: hidden;
}

.kkm-sidebar.kkm-collapsed .kkm-sidebar-nav a,
.kkm-sidebar.kkm-collapsed .kkm-sidebar-footer a,
.kkm-sidebar.kkm-collapsed .kkm-sidebar-footer button {
  width: 44px;
  height: 44px;
  margin: 0 auto;
  padding: 0;
  justify-content: center;
}

.kkm-sidebar-nav a:hover,
.kkm-sidebar-footer a:hover,
.kkm-sidebar-footer button:hover {
  background: rgba(255, 255, 255, 0.05);
  color: var(--kkm-text) !important;
}

.kkm-sidebar-nav a.kkm-active,
.kkm-sidebar-footer a.kkm-active {
  background: rgba(62, 207, 142, 0.15);
  color: var(--kkm-accent) !important;
  font-weight: 600;
}

.kkm-sidebar-label {
  overflow: hidden;
  text-overflow: ellipsis;
}

.kkm-sidebar.kkm-collapsed .kkm-sidebar-label {
  display: none;
}

.kkm-sidebar-footer {
  margin-top: auto;
  padding-top: 12px;
  border-top: 1px solid var(--kkm-border);
  flex-shrink: 0;
}

.kkm-main {
  flex: 1;
  min-width: 0;
  padding: 28px 32px 60px;
}

.kkm-topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 12px;
  margin-bottom: 20px;
}

.kkm-topbar h2 {
  display: flex;
  align-items: center;
  gap: 10px;
}

.kkm-title-logo {
  width: 28px;
  height: 28px;
  flex-shrink: 0;
}

.kkm-topbar h2 {
  margin: 0;
}

.kkm-topbar .kkm-toolbar {
  margin-bottom: 0;
}

body.kkm-dark .uk-input,
body.kkm-dark .uk-textarea,
body.kkm-dark .uk-select {
  background: var(--kkm-card-bg);
  border: 1px solid var(--kkm-border);
  color: var(--kkm-text);
}

/* A <select>'s dropdown popup is a separate browser-rendered surface that
   doesn't inherit the color/background above — without this, unselected
   options render in a light color against the browser's default white
   popup background (see .kkm-search-scope option for the same issue). */
body.kkm-dark .uk-select option {
  background: var(--kkm-card-bg);
  color: var(--kkm-text);
}

body.kkm-dark .uk-input::placeholder {
  color: var(--kkm-text-muted);
}

body.kkm-dark .uk-button-default {
  background: var(--kkm-card-bg);
  border: 1px solid var(--kkm-border);
  color: var(--kkm-text);
}

body.kkm-dark .uk-button-primary {
  background: var(--kkm-accent);
  border-color: var(--kkm-accent);
  color: #0e1410;
}

body.kkm-dark .uk-card-default {
  background: var(--kkm-card-bg);
  color: var(--kkm-text);
  border: 1px solid var(--kkm-border);
}

body.kkm-dark .uk-card-title {
  color: var(--kkm-text);
}

body.kkm-dark h1,
body.kkm-dark h2,
body.kkm-dark h3,
body.kkm-dark h4,
body.kkm-dark h5,
body.kkm-dark h6,
body.kkm-dark label {
  color: var(--kkm-text);
}

body.kkm-dark .uk-checkbox {
  background: var(--kkm-card-bg);
  border-color: var(--kkm-border);
}

body.kkm-dark .uk-checkbox:checked,
body.kkm-dark .uk-checkbox:indeterminate {
  background-color: var(--kkm-accent);
  border-color: var(--kkm-accent);
}

body.kkm-dark .uk-radio {
  background: var(--kkm-card-bg);
  border-color: var(--kkm-border);
}

body.kkm-dark .uk-radio:checked {
  background-color: var(--kkm-accent);
  border-color: var(--kkm-accent);
}

.kkm-link-scope-options {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.kkm-radio-option {
  display: flex;
  align-items: center;
  gap: 8px;
  cursor: pointer;
  font-weight: 400;
}

.kkm-radio-option .uk-radio {
  flex-shrink: 0;
  margin: 0;
}

.kkm-expired-text {
  color: #e5484d;
  font-weight: 600;
  font-size: 0.85rem;
}

.kkm-analytics-total {
  font-size: 1.4rem;
  font-weight: 700;
  color: var(--kkm-text, #f3f4f1);
  margin: 4px 0 0;
}

.kkm-analytics-chart {
  margin-top: 16px;
}

.kkm-analytics-svg {
  width: 100%;
  height: 120px;
  display: block;
}

.kkm-analytics-axis {
  display: flex;
  justify-content: space-between;
  font-size: 0.75rem;
  color: var(--kkm-text-muted, #98a19a);
  margin-top: 4px;
}

.kkm-ba-toolbar {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 14px;
  margin-bottom: 18px;
}

.kkm-ba-select-toggle {
  position: absolute;
  top: 10px;
  left: 10px;
  z-index: 1;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  border: 2px solid rgba(255, 255, 255, 0.8);
  background: rgba(0, 0, 0, 0.35);
  color: transparent;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}

.kkm-ba-select-toggle.kkm-selected {
  background: var(--kkm-accent);
  border-color: var(--kkm-accent);
  color: #0e1410;
}

.kkm-ba-picker-row {
  display: flex;
  gap: 16px;
  flex-wrap: wrap;
}

.kkm-ba-picker {
  flex: 1 1 260px;
  min-width: 0;
}

.kkm-ba-picker-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 6px;
  margin-top: 8px;
  max-height: 260px;
  overflow-y: auto;
}

.kkm-ba-picker-thumb {
  padding: 0;
  border: 2px solid transparent;
  border-radius: 6px;
  overflow: hidden;
  cursor: pointer;
  background: none;
  aspect-ratio: 1;
  line-height: 0;
}

.kkm-ba-picker-thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.kkm-ba-picker-thumb-selected {
  border-color: var(--kkm-accent);
}

.kkm-ba-list {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(460px, 1fr));
  gap: 24px;
}

.kkm-ba-item {
  background: var(--kkm-card-bg);
  border-radius: 10px;
  overflow: hidden;
}

.kkm-ba-frame {
  position: relative;
  aspect-ratio: 4 / 3;
  overflow: hidden;
  cursor: ew-resize;
  touch-action: none;
  --kkm-ba-x: 50%;
}

.kkm-ba-img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  user-select: none;
  -webkit-user-drag: none;
}

.kkm-ba-before {
  clip-path: inset(0 calc(100% - var(--kkm-ba-x)) 0 0);
}

.kkm-ba-handle {
  position: absolute;
  top: 0;
  bottom: 0;
  left: var(--kkm-ba-x);
  width: 3px;
  background: #fff;
  transform: translateX(-50%);
  pointer-events: none;
}

.kkm-ba-handle span,
.kkm-ba-handle svg {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 32px;
  height: 32px;
  background: #fff;
  border-radius: 50%;
  padding: 6px;
  box-sizing: border-box;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.4);
}

.kkm-ba-tag {
  position: absolute;
  top: 10px;
  background: rgba(0, 0, 0, 0.55);
  color: #fff;
  font-size: 0.72rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  padding: 3px 9px;
  border-radius: 999px;
  pointer-events: none;
}

.kkm-ba-tag-before {
  left: 10px;
}

.kkm-ba-tag-after {
  right: 10px;
}

.kkm-ba-item-footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 10px 12px;
  color: var(--kkm-text);
  font-size: 0.85rem;
}

.kkm-live-badge {
  display: inline-block;
  background: var(--kkm-accent);
  color: #0e1410;
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  padding: 1px 6px;
  border-radius: 10px;
  vertical-align: middle;
}

.kkm-select-all-toggle {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-shrink: 0;
  white-space: nowrap;
  color: var(--kkm-text-muted, #98a19a);
  font-size: 0.85rem;
  cursor: pointer;
  padding: 0 4px;
}

.kkm-select-all-toggle .uk-checkbox {
  margin: 0;
  flex-shrink: 0;
}

.kkm-select-all-bar {
  margin-bottom: 14px;
}

.kkm-share-url {
  background: var(--kkm-card-bg);
  border: 1px solid var(--kkm-border);
  border-radius: 6px;
  padding: 10px 12px;
  color: var(--kkm-text);
  word-break: break-all;
  font-size: 0.85rem;
}

.kkm-share-actions {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
}

.kkm-share-actions .uk-button {
  display: flex;
  align-items: center;
  gap: 8px;
}

.kkm-qr-section {
  margin-top: 16px;
  padding-top: 16px;
  border-top: 1px solid var(--kkm-border);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
}

.kkm-qr-wrap {
  background: #fff;
  padding: 10px;
  border-radius: 8px;
  line-height: 0;
}

.kkm-qr-section .kkm-share-actions {
  justify-content: center;
}

.kkm-inline-input {
  display: inline-block;
  width: auto;
  height: 30px;
  padding: 0 8px;
  margin: 0 2px;
  font-size: 0.85rem;
}

.kkm-inline-input-sm {
  width: 64px;
}

.kkm-pill-row {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 20px;
}

.kkm-pill {
  background: var(--kkm-card-bg);
  border: 1px solid var(--kkm-border);
  color: var(--kkm-text-muted);
  border-radius: 999px;
  padding: 7px 16px;
  font-size: 0.85rem;
  cursor: pointer;
}

.kkm-pill:hover {
  color: var(--kkm-text);
}

.kkm-pill.kkm-pill-active {
  background: var(--kkm-accent);
  border-color: var(--kkm-accent);
  color: #0e1410;
  font-weight: 600;
}

.kkm-toolbar {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 14px;
  margin-bottom: 18px;
  color: var(--kkm-text-muted);
  font-size: 0.9rem;
}

/* Pinterest-style masonry via native CSS multi-column layout instead of
   UIkit's JS masonry component — no re-layout-on-image-load timing to get
   right, the browser reflows columns automatically as lazy images load. */
/* JS-driven masonry (public/js/masonry.js): the grid holds N
   `.kkm-masonry-col` flex children, each a vertical stack of item wrappers.
   CSS column-count was tried here first but Chrome's column-balance
   algorithm reliably dumps every item into the first column (leaving the
   rest empty) whenever there are few — or few very tall — items relative to
   the column count, which is exactly the common case for a small shared
   gallery or a narrow tag-filtered result. That can't be fixed by tuning
   column-count/column-fill, so layout is done in JS instead. */
.kkm-masonry-grid {
  display: flex;
  align-items: flex-start;
  gap: 12px;
}

.kkm-masonry-col {
  flex: 1 1 0;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.kkm-card {
  position: relative;
  border-radius: 10px;
  overflow: hidden;
  background: var(--kkm-card-bg);
  cursor: zoom-in;
  transition: box-shadow 0.25s ease, transform 0.25s ease;
}

.kkm-card:hover {
  box-shadow: 0 10px 28px rgba(0, 0, 0, 0.35);
  transform: translateY(-2px);
}

.kkm-card img {
  width: 100%;
  display: block;
  aspect-ratio: auto;
}

.kkm-card-zoom-hint {
  position: absolute;
  top: 50%;
  left: 50%;
  z-index: 2;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  background: rgba(0, 0, 0, 0.45);
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0;
  pointer-events: none;
  transform: translate(-50%, -50%) scale(0.8);
  transition: opacity 0.25s ease, transform 0.25s ease;
}

.kkm-card:hover .kkm-card-zoom-hint {
  opacity: 1;
  transform: translate(-50%, -50%) scale(1);
}

/* Public gallery only: no hover on touch devices, so the zoom cue has to
   be visible by default rather than hover-gated like the admin grids'
   centered .kkm-card-zoom-hint. Bottom-right corner keeps it out of the
   way of the photo name in .kkm-card-overlay-text. */
.kkm-gallery-zoom-hint {
  position: absolute;
  bottom: 10px;
  right: 10px;
  z-index: 2;
  width: 32px;
  height: 32px;
  border-radius: 50%;
  background: rgba(0, 0, 0, 0.55);
  display: flex;
  align-items: center;
  justify-content: center;
  pointer-events: none;
}

.kkm-gallery-zoom-hint svg {
  width: 18px;
  height: 18px;
}

.kkm-card-zoom-hint svg {
  width: 20px;
  height: 20px;
}

.kkm-card-checkbox {
  position: absolute;
  top: 10px;
  left: 10px;
  transform: scale(1.3);
  z-index: 2;
}

.kkm-card-badges {
  position: absolute;
  top: 10px;
  right: 10px;
  z-index: 2;
  display: flex;
  flex-direction: column;
  gap: 4px;
  align-items: flex-end;
  max-width: 65%;
}

.kkm-card-badge {
  background: rgba(20, 22, 19, 0.75);
  color: #fff;
  font-size: 0.7rem;
  padding: 3px 9px;
  border-radius: 999px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Small icon-only variant, stacked above the date pill in the same
   top-right .kkm-card-badges column — flags a Gallery-mode photo without
   competing for the bottom-corner space the title/actions overlay and the
   public zoom-hint already use. */
.kkm-card-badge-gallery {
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: rgba(20, 22, 19, 0.75);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
}

.kkm-card-overlay {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 2;
  padding: 22px 10px 10px;
  background: linear-gradient(to top, rgba(0, 0, 0, 0.75), transparent);
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 8px;
}

.kkm-card-overlay-text {
  min-width: 0;
}

.kkm-card-overlay-title {
  color: #fff;
  font-size: 0.85rem;
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.kkm-card-overlay-sub {
  color: rgba(255, 255, 255, 0.7);
  font-size: 0.75rem;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.kkm-card-download {
  flex-shrink: 0;
  color: #fff !important;
  background: rgba(255, 255, 255, 0.15);
  border-radius: 50%;
  width: 28px;
  height: 28px;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* Gallery-mode card overlay: a horizontal scroll-snap track of every image
   plus dots, layered on top of the plain cover <img> that's always present
   underneath (and stays in normal flow so masonry keeps measuring it, not
   this overlay). Both pieces start `hidden` and are only revealed once
   gallery-swipe.js's async fetch confirms there's more than one image — see
   gallery-swipe.js. z-index sits below the select-toggle/card-badges/
   zoom-hint/card-overlay chrome above (all bumped to z-index: 2) so that
   existing chrome stays visible/clickable over a swiped-to image exactly
   like it already is over the plain cover image. The "this is a gallery"
   cue itself lives as a small icon badge inside .kkm-card-badges (built by
   each page's own card markup), not as a separate element here — that
   avoids fighting the title/actions overlay or the date badge for corner
   space. */
.kkm-gallery-swipe-track {
  position: absolute;
  inset: 0;
  z-index: 1;
  display: flex;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  -webkit-overflow-scrolling: touch;
}

/* Each item is 92% wide, not 100% — leaves a sliver of the next image
   peeking in from the right edge as the "swipe for more" affordance, same
   idea as the mobile lightbox's vertical scroll-snap list. */
.kkm-gallery-swipe-track img {
  flex: 0 0 92%;
  scroll-snap-align: start;
  width: 92%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* Sits just above the always-visible title/actions bar (.kkm-card-overlay),
   not down inside it — bottom: 8px would land the dots directly behind the
   title text. z-index: 3 (one above the overlay's 2) so they stay visible
   over its gradient background regardless of DOM order. */
.kkm-gallery-dots {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 38px;
  z-index: 3;
  display: flex;
  justify-content: center;
  gap: 5px;
  pointer-events: none;
}

.kkm-gallery-dot {
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.5);
  transition: background 0.15s ease, transform 0.15s ease;
}

.kkm-gallery-dot-active {
  background: #fff;
  transform: scale(1.3);
}

/* Clearable text inputs */
.kkm-clearable-input {
  position: relative;
}

.kkm-clearable-input > input {
  width: 100%;
  padding-right: 32px;
}

/* Search field with an embedded "search in: tags/client" scope select —
   one shared pill-shaped box (border/bg live on the wrapper), select and
   input both borderless/transparent inside it so they read as one field,
   not two stacked controls. */
.kkm-search-with-scope {
  display: flex;
  align-items: stretch;
  background: var(--kkm-card-bg);
  border: 1px solid var(--kkm-border);
  border-radius: 6px;
  transition: border-color 0.15s ease;
}

.kkm-search-with-scope:focus-within {
  border-color: var(--kkm-accent);
}

.kkm-search-scope {
  flex-shrink: 0;
  width: auto;
  max-width: 76px;
  border: none;
  border-right: 1px solid var(--kkm-border);
  background: transparent;
  color: var(--kkm-text-muted);
  font-size: 0.78rem;
  font-weight: 600;
  padding: 0 4px 0 10px;
  margin: 0;
  border-radius: 6px 0 0 6px;
  cursor: pointer;
}

/* The closed <select> box picks up the styling above, but its dropdown
   popup is a separate, browser-rendered surface that doesn't inherit it —
   without this it defaults to a white popup, and since `color` above is a
   light gray, unselected options render as near-invisible light-on-white. */
.kkm-search-scope option {
  background: var(--kkm-card-bg, #2a2d2a);
  color: var(--kkm-text, #f3f4f1);
}

.kkm-search-scope:focus {
  outline: none;
  color: var(--kkm-text);
}

.kkm-search-with-scope > input.uk-input {
  flex: 1 1 auto;
  min-width: 0;
  border: none !important;
  background: transparent !important;
  border-radius: 0 6px 6px 0 !important;
}

.kkm-search-with-scope > input.uk-input:focus {
  box-shadow: none;
}

@media (max-width: 767px) {
  .kkm-search-scope {
    max-width: 62px;
    font-size: 0.72rem;
    padding-left: 8px;
  }
}

.kkm-input-clear {
  position: absolute;
  top: 50%;
  right: 6px;
  transform: translateY(-50%);
  width: 22px;
  height: 22px;
  border-radius: 50%;
  border: none;
  background: transparent;
  color: var(--kkm-text-muted);
  display: none;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  padding: 0;
}

.kkm-clearable-input.kkm-has-value .kkm-input-clear {
  display: flex;
}

.kkm-input-clear:hover {
  color: var(--kkm-text);
  background: rgba(255, 255, 255, 0.1);
}

/* Tag chip input */
.kkm-tag-chip-wrap .kkm-input-clear {
  top: 8px;
  transform: none;
}

.kkm-tag-chip-box {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  box-sizing: border-box;
  width: 100%;
  min-height: 38px;
  padding: 6px 32px 6px 10px;
  line-height: normal;
  cursor: text;
  background: var(--kkm-card-bg);
  border: 1px solid var(--kkm-border);
  border-radius: 4px;
  color: var(--kkm-text);
}

.kkm-tag-chip {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  background: var(--kkm-accent);
  color: #0e1410;
  border-radius: 999px;
  padding: 2px 4px 2px 10px;
  line-height: 1.4;
  font-size: 0.82rem;
  font-weight: 600;
  white-space: nowrap;
}

.kkm-tag-chip-remove {
  background: rgba(0, 0, 0, 0.15);
  border: none;
  color: inherit;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  font-size: 0.85rem;
  line-height: 1;
  padding: 0;
}

.kkm-tag-chip-remove:hover {
  background: rgba(0, 0, 0, 0.3);
}

.kkm-tag-chip-entry {
  flex: 1 1 80px;
  min-width: 80px;
  border: none;
  background: transparent;
  color: var(--kkm-text);
  font: inherit;
  outline: none;
  padding: 4px 2px;
}

.kkm-tag-chip-entry::placeholder {
  color: var(--kkm-text-muted);
}

/* Tag suggestion dropdown */
.kkm-tag-suggest {
  position: absolute;
  top: calc(100% + 4px);
  left: 0;
  right: 0;
  z-index: 10;
  background: var(--kkm-card-bg);
  border: 1px solid var(--kkm-border);
  border-radius: 8px;
  max-height: 200px;
  overflow-y: auto;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.35);
  padding: 4px;
}

.kkm-tag-suggest-item {
  display: block;
  width: 100%;
  text-align: left;
  background: transparent;
  border: none;
  color: var(--kkm-text);
  padding: 8px 10px;
  border-radius: 6px;
  font-size: 0.9rem;
  cursor: pointer;
}

.kkm-tag-suggest-item:hover,
.kkm-tag-suggest-item.kkm-tag-suggest-active {
  background: rgba(62, 207, 142, 0.15);
  color: var(--kkm-accent);
}

/* Category multi-select dropdown */
.kkm-category-select {
  position: relative;
}

.kkm-category-trigger {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  box-sizing: border-box;
  width: 100%;
  min-height: 38px;
  padding: 6px 10px;
  line-height: normal;
  background: var(--kkm-card-bg);
  border: 1px solid var(--kkm-border);
  border-radius: 4px;
  color: var(--kkm-text);
  cursor: pointer;
}

.kkm-category-trigger:focus-visible {
  outline: 2px solid var(--kkm-accent);
  outline-offset: 1px;
}

.kkm-category-placeholder {
  color: var(--kkm-text-muted);
  font-size: 0.95rem;
}

.kkm-category-caret {
  margin-left: auto;
  color: var(--kkm-text-muted);
  flex-shrink: 0;
}

.kkm-category-dropdown {
  position: absolute;
  top: calc(100% + 4px);
  left: 0;
  right: 0;
  z-index: 10;
  background: var(--kkm-card-bg);
  border: 1px solid var(--kkm-border);
  border-radius: 8px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.35);
  padding: 8px;
}

.kkm-category-search {
  width: 100%;
  box-sizing: border-box;
  background: var(--kkm-bg);
  border: 1px solid var(--kkm-border);
  border-radius: 6px;
  color: var(--kkm-text);
  padding: 7px 10px;
  font: inherit;
  margin-bottom: 6px;
}

.kkm-category-search::placeholder {
  color: var(--kkm-text-muted);
}

.kkm-category-options {
  max-height: 200px;
  overflow-y: auto;
}

.kkm-category-option {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  text-align: left;
  background: transparent;
  border: none;
  color: var(--kkm-text);
  padding: 8px 10px;
  border-radius: 6px;
  font-size: 0.9rem;
  cursor: pointer;
}

.kkm-category-dropdown:focus {
  outline: none;
}

.kkm-category-option-active,
.kkm-category-option:hover {
  background: rgba(255, 255, 255, 0.06);
}

.kkm-category-option-active {
  box-shadow: inset 0 0 0 1px var(--kkm-accent);
}

.kkm-category-hint {
  margin-top: 6px;
  padding-top: 6px;
  border-top: 1px solid var(--kkm-border);
  color: var(--kkm-text-muted);
  font-size: 0.72rem;
  line-height: 1.4;
}

.kkm-category-option-check {
  width: 16px;
  height: 16px;
  flex-shrink: 0;
  border: 1px solid var(--kkm-border);
  border-radius: 4px;
  position: relative;
}

.kkm-category-option-selected .kkm-category-option-check {
  background: var(--kkm-accent);
  border-color: var(--kkm-accent);
}

.kkm-category-option-selected .kkm-category-option-check::after {
  content: '';
  position: absolute;
  left: 4px;
  top: 1px;
  width: 4px;
  height: 8px;
  border: solid #0e1410;
  border-width: 0 2px 2px 0;
  transform: rotate(45deg);
}

.kkm-category-empty {
  padding: 10px;
  color: var(--kkm-text-muted);
  font-size: 0.85rem;
  text-align: center;
}

.kkm-tag-popular {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 8px;
}

.kkm-tag-popular .kkm-pill {
  padding: 4px 12px;
  font-size: 0.78rem;
}







/* Filter row */
.kkm-filter-row-wrap {
  position: relative;
  margin-bottom: 18px;
}

.kkm-filter-scroll-hint {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 40px;
  display: flex;
  align-items: center;
  pointer-events: none;
  color: var(--kkm-text-muted);
  opacity: 0;
  transition: opacity 0.15s ease;
  z-index: 1;
}

.kkm-filter-scroll-hint-left {
  left: 0;
  justify-content: flex-start;
  background: linear-gradient(to right, var(--kkm-bg) 45%, transparent);
}

.kkm-filter-scroll-hint-right {
  right: 0;
  justify-content: flex-end;
  background: linear-gradient(to left, var(--kkm-bg) 45%, transparent);
}

.kkm-filter-row-wrap.kkm-can-scroll-left .kkm-filter-scroll-hint-left,
.kkm-filter-row-wrap.kkm-can-scroll-right .kkm-filter-scroll-hint-right {
  opacity: 1;
}

.kkm-filter-row {
  display: flex;
  flex-wrap: nowrap;
  align-items: center;
  gap: 10px;
  overflow-x: auto;
  scrollbar-width: none;
  -ms-overflow-style: none;
}

.kkm-filter-row::-webkit-scrollbar {
  display: none;
}

.kkm-filter-row .kkm-clearable-input,
.kkm-filter-row .uk-select {
  flex: 1 0 160px;
}

.kkm-filter-row .kkm-filter-query {
  flex: 2 0 220px;
}

/* Round icon buttons */
.kkm-icon-btn {
  flex-shrink: 0;
  width: 38px;
  height: 38px;
  border-radius: 50%;
  border: 1px solid var(--kkm-border);
  background: var(--kkm-card-bg);
  color: var(--kkm-text-muted);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  padding: 0;
}

.kkm-icon-btn:hover {
  color: var(--kkm-text);
}

.kkm-links-actions {
  display: flex;
  gap: 6px;
  align-items: center;
}

.kkm-links-actions .kkm-icon-btn {
  width: 30px;
  height: 30px;
}

.kkm-icon-btn-danger:hover {
  color: #e5484d;
  border-color: #e5484d;
}

/* Active/inactive link toggle */
.kkm-switch {
  position: relative;
  display: inline-block;
  width: 38px;
  height: 21px;
  cursor: pointer;
}

.kkm-switch-input {
  position: absolute;
  inset: 0;
  opacity: 0;
  margin: 0;
  cursor: pointer;
}

.kkm-switch-track {
  position: absolute;
  inset: 0;
  background: var(--kkm-border);
  border-radius: 999px;
  transition: background 0.2s ease;
}

.kkm-switch-thumb {
  position: absolute;
  top: 2px;
  left: 2px;
  width: 17px;
  height: 17px;
  border-radius: 50%;
  background: #fff;
  transition: transform 0.2s ease;
}

.kkm-switch-input:checked + .kkm-switch-track {
  background: var(--kkm-accent);
}

.kkm-switch-input:checked + .kkm-switch-track .kkm-switch-thumb {
  transform: translateX(17px);
}

.kkm-switch-input:focus-visible + .kkm-switch-track {
  outline: 2px solid var(--kkm-accent);
  outline-offset: 2px;
}

.kkm-fab {
  flex-shrink: 0;
  width: 46px;
  height: 46px;
  border-radius: 50%;
  border: none;
  background: var(--kkm-accent);
  color: #0e1410;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}

.kkm-fab:disabled {
  background: var(--kkm-card-bg);
  color: var(--kkm-text-muted);
  cursor: not-allowed;
}

/* Round icon button that expands into a labeled pill on hover (same idea as
   the upload FAB) — used for Share, Delete, and Log out actions. */
.kkm-pill-btn {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  height: 38px;
  border: 1px solid var(--kkm-border);
  border-radius: 19px;
  background: var(--kkm-card-bg);
  color: var(--kkm-text-muted);
  cursor: pointer;
  padding: 0;
  overflow: hidden;
  transition: color 0.2s ease, box-shadow 0.2s ease, background 0.2s ease, border-color 0.2s ease;
}

.kkm-pill-btn:hover,
.kkm-pill-btn:focus-visible {
  color: var(--kkm-text);
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.3);
}

.kkm-pill-btn:disabled {
  cursor: not-allowed;
  opacity: 0.5;
  box-shadow: none;
}

.kkm-pill-btn-icon {
  flex-shrink: 0;
  width: 38px;
  height: 38px;
  display: flex;
  align-items: center;
  justify-content: center;
}

.kkm-pill-btn-label {
  display: inline-block;
  max-width: 0;
  opacity: 0;
  overflow: hidden;
  white-space: nowrap;
  font-weight: 600;
  font-size: 0.85rem;
  padding-right: 0;
  transition: max-width 0.25s ease, opacity 0.2s ease, padding-right 0.25s ease;
}

.kkm-pill-btn:hover .kkm-pill-btn-label,
.kkm-pill-btn:focus-visible .kkm-pill-btn-label {
  max-width: 120px;
  opacity: 1;
  padding-right: 18px;
}

.kkm-pill-btn-lg {
  height: 46px;
  border-radius: 23px;
}

.kkm-pill-btn-lg .kkm-pill-btn-icon {
  width: 46px;
  height: 46px;
}

.kkm-pill-btn-accent {
  border: none;
  background: var(--kkm-accent);
  color: #0e1410;
}

.kkm-pill-btn-accent:hover,
.kkm-pill-btn-accent:focus-visible {
  color: #0e1410;
}

.kkm-pill-btn-accent:disabled {
  background: var(--kkm-card-bg);
  color: var(--kkm-text-muted);
}

.kkm-pill-btn-danger {
  color: #ff8a80;
}

.kkm-pill-btn-danger:hover,
.kkm-pill-btn-danger:focus-visible {
  background: rgba(255, 82, 82, 0.12);
  border-color: rgba(255, 82, 82, 0.4);
  color: #ff8a80;
}

/* Tick-select toggle on cards. Sits right at the corner of a card whose
   own default cursor is `zoom-in` (clicking anywhere else opens the
   lightbox) — a 26px circle alone is an unforgivingly small, precise
   target to land a click on before it falls through to that zoom-in
   behavior instead. The ::before below extends the actual clickable/
   hoverable area well past the visible circle without changing how it
   looks, so a near-miss still registers as a select-toggle click (and
   shows the pointer cursor) rather than opening the photo full-screen. */
.kkm-select-toggle {
  position: absolute;
  top: 10px;
  left: 10px;
  z-index: 2;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  border: 2px solid rgba(255, 255, 255, 0.75);
  background: rgba(0, 0, 0, 0.35);
  color: transparent;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  padding: 0;
}

.kkm-select-toggle::before {
  content: '';
  position: absolute;
  inset: -10px;
}

.kkm-select-toggle.kkm-selected {
  background: var(--kkm-accent);
  border-color: var(--kkm-accent);
  color: #0e1410;
}

.kkm-card-actions {
  display: flex;
  gap: 6px;
  flex-shrink: 0;
}

.kkm-card-action {
  flex-shrink: 0;
  color: #fff !important;
  background: rgba(255, 255, 255, 0.15);
  border: none;
  border-radius: 50%;
  width: 28px;
  height: 28px;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}

.kkm-card-action:hover {
  background: rgba(255, 255, 255, 0.3);
}

/* Upload FAB (Material-style extended button) */
.kkm-upload-fab {
  position: fixed;
  right: 32px;
  bottom: 32px;
  z-index: 500;
  display: inline-flex;
  align-items: center;
  height: 56px;
  border: none;
  border-radius: 28px;
  background: var(--kkm-accent);
  color: #0e1410;
  cursor: pointer;
  padding: 0;
  overflow: hidden;
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.35);
}

.kkm-upload-fab-icon {
  flex-shrink: 0;
  width: 56px;
  height: 56px;
  display: flex;
  align-items: center;
  justify-content: center;
}

.kkm-upload-fab-label {
  display: inline-block;
  max-width: 0;
  opacity: 0;
  overflow: hidden;
  white-space: nowrap;
  font-weight: 600;
  font-size: 0.95rem;
  padding-right: 0;
  transition: max-width 0.25s ease, opacity 0.2s ease, padding-right 0.25s ease;
}

.kkm-upload-fab:hover .kkm-upload-fab-label,
.kkm-upload-fab:focus-visible .kkm-upload-fab-label {
  max-width: 160px;
  opacity: 1;
  padding-right: 22px;
}

/* Speed-dial: the toggle above is unchanged (still fixed bottom-right); this
   options list pops up directly above it with the same right edge. */
.kkm-fab-options {
  position: fixed;
  right: 32px;
  bottom: 100px;
  z-index: 500;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 10px;
}

.kkm-fab-option {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  height: 44px;
  padding-right: 18px;
  border: none;
  border-radius: 22px;
  background: var(--kkm-card-bg);
  color: var(--kkm-text);
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.35);
  cursor: pointer;
  font-size: 0.85rem;
  font-weight: 600;
  white-space: nowrap;
}

.kkm-fab-option:hover {
  background: var(--kkm-border);
}

.kkm-fab-option-icon {
  flex-shrink: 0;
  width: 44px;
  height: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: var(--kkm-accent);
  color: #0e1410;
}

@media (max-width: 767px) {
  .kkm-upload-fab {
    right: 20px;
    bottom: 20px;
  }

  .kkm-fab-options {
    right: 20px;
    bottom: 88px;
  }
}

/* Multi-image editor nav */

.kkm-editor-nav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 12px;
  color: var(--kkm-text-muted);
  font-size: 0.9rem;
}

body.kkm-dark .uk-modal-dialog {
  background: var(--kkm-card-bg);
  color: var(--kkm-text);
}

body.kkm-dark .uk-modal-header,
body.kkm-dark .uk-modal-footer {
  background: var(--kkm-card-bg);
  border-color: var(--kkm-border);
}

.kkm-upload-footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 10px;
}

.kkm-upload-footer-right {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}

.kkm-confirm-actions {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
  margin-top: 20px;
}

/* Toasts — pill-shaped, colored by status, explicit close button */
#kkm-toast-container {
  position: fixed;
  top: 16px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 6000;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  pointer-events: none;
}

.kkm-toast {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 10px 9px 16px;
  border-radius: 999px;
  font-size: 0.85rem;
  font-weight: 600;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.35);
  opacity: 0;
  transform: translateY(-14px);
  transition: opacity 0.2s ease, transform 0.2s ease;
  pointer-events: auto;
  max-width: min(90vw, 420px);
}

.kkm-toast-visible {
  opacity: 1;
  transform: translateY(0);
}

.kkm-toast-success {
  background: var(--kkm-accent, #3ecf8e);
  color: #0e1410;
}

.kkm-toast-danger {
  background: #ef4444;
  color: #fff;
}

.kkm-toast-warning {
  background: #f5b400;
  color: #2b2200;
}

.kkm-toast-message {
  white-space: normal;
  word-break: break-word;
}

.kkm-toast-close {
  flex-shrink: 0;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  border: none;
  background: rgba(0, 0, 0, 0.15);
  color: inherit;
  font-size: 1.1rem;
  line-height: 1;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
}

/* Range sliders (brightness/contrast) — cross-browser dark theming */
body.kkm-dark input[type='range'] {
  -webkit-appearance: none;
  appearance: none;
  width: 100%;
  height: 4px;
  border-radius: 999px;
  background: var(--kkm-border);
  outline: none;
  cursor: pointer;
}

body.kkm-dark input[type='range']::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: var(--kkm-accent);
  border: 2px solid var(--kkm-card-bg);
  box-shadow: 0 0 0 1px var(--kkm-accent);
  margin-top: -6px;
}

body.kkm-dark input[type='range']::-webkit-slider-runnable-track {
  height: 4px;
  border-radius: 999px;
  background: var(--kkm-border);
}

body.kkm-dark input[type='range']::-moz-range-thumb {
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: var(--kkm-accent);
  border: 2px solid var(--kkm-card-bg);
  box-shadow: 0 0 0 1px var(--kkm-accent);
}

body.kkm-dark input[type='range']::-moz-range-track {
  height: 4px;
  border-radius: 999px;
  background: var(--kkm-border);
}

/* Modal close (×) button — default UIkit styling is near-invisible on dark */
body.kkm-dark .uk-modal-close-default {
  color: var(--kkm-text-muted);
  background: var(--kkm-card-bg);
  border: 1px solid var(--kkm-border);
  border-radius: 50%;
  width: 30px;
  height: 30px;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
}

body.kkm-dark .uk-modal-close-default:hover {
  color: var(--kkm-text);
  background: rgba(255, 255, 255, 0.08);
}

/* Upload progress bar — accent green instead of UIkit's default blue */
body.kkm-dark progress.uk-progress {
  height: 10px;
  border-radius: 999px;
  background: var(--kkm-border);
}

body.kkm-dark progress.uk-progress::-webkit-progress-bar {
  background: var(--kkm-border);
  border-radius: 999px;
}

body.kkm-dark progress.uk-progress::-webkit-progress-value {
  background: var(--kkm-accent);
  border-radius: 999px;
}

body.kkm-dark progress.uk-progress::-moz-progress-bar {
  background: var(--kkm-accent);
  border-radius: 999px;
}

body.kkm-dark .uk-table {
  color: var(--kkm-text);
}

body.kkm-dark .uk-table-divider > tr > td,
body.kkm-dark .uk-table-divider > :not(:first-child) > tr > td,
body.kkm-dark .uk-table th {
  border-top: 1px solid var(--kkm-border);
  color: var(--kkm-text);
}

.kkm-mobile-menu-btn {
  display: none;
}

.kkm-sidebar-backdrop {
  display: none;
}

@keyframes kkm-sheet-up {
  from {
    transform: translateY(100%);
  }
  to {
    transform: translateY(0);
  }
}

@media (max-width: 767px) {
  .kkm-mobile-menu-btn {
    display: flex;
    flex-shrink: 0;
    order: -1;
    width: 36px;
    height: 36px;
    border-radius: 50%;
    align-items: center;
    justify-content: center;
    background: var(--kkm-sidebar-bg);
    color: var(--kkm-text);
    border: 1px solid var(--kkm-border);
  }

  /* Same top row on every page: hamburger left, title centered, a single
     icon-button right. Settings' topbar already has just those 3 direct
     children so it lays out this way automatically; Portfolio's topbar also
     carries a "N selected + Share" toolbar, which would otherwise wrap onto
     its own line pinned to the left instead of forming a clean second row —
     order/flex-basis pushes it below as its own centered row instead. */
  .kkm-topbar h2 {
    order: 1;
    flex: 1 1 auto;
    justify-content: center;
    text-align: center;
  }

  .kkm-topbar > #topbar-logout-btn {
    order: 2;
  }

  .kkm-topbar > .kkm-toolbar {
    order: 3;
    flex-basis: 100%;
    justify-content: center;
  }

  /* The public gallery page has no sidebar/hamburger to balance against,
     but the title should still read as centered on a phone rather than
     pinned to the left, matching the rest of the app. */
  #gallery-title {
    justify-content: center;
    text-align: center;
  }

  .kkm-sidebar-backdrop.kkm-visible {
    display: block;
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.5);
    z-index: 999;
  }

  .kkm-shell {
    flex-direction: column;
    align-items: stretch;
  }

  .kkm-sidebar {
    position: fixed;
    top: 0;
    left: 0;
    bottom: 0;
    width: 240px;
    z-index: 1000;
    transform: translateX(-100%);
    transition: transform 0.2s ease;
    /* Defensive: guarantee the sidebar itself scrolls if its content is
       ever taller than the viewport, regardless of whether the inner
       flex/min-height/overflow chain on .kkm-sidebar-tags-scroll is
       working as intended — content should never silently spill past
       the bottom edge unreachable. */
    overflow-y: auto;
  }

  .kkm-sidebar:not(.kkm-collapsed) {
    transform: translateX(0);
  }

  .kkm-sidebar.kkm-collapsed .kkm-sidebar-label {
    display: inline;
  }

  .kkm-sidebar.kkm-collapsed .kkm-sidebar-brand,
  .kkm-sidebar.kkm-collapsed .kkm-sidebar-nav a,
  .kkm-sidebar.kkm-collapsed .kkm-sidebar-footer a,
  .kkm-sidebar.kkm-collapsed .kkm-sidebar-footer button {
    justify-content: flex-start;
  }

  .kkm-main {
    padding: 16px;
  }

  /* Compact enough that all 3 tabs (including the longest label,
     "Before/After") fit in one row without needing the overflow-x:auto
     scroll fallback above on any phone width actually tested — that
     fallback still catches anything narrower. */
  .kkm-tab {
    padding: 7px 10px;
    gap: 5px;
    font-size: 0.78rem;
  }

  .kkm-tab-count {
    min-width: 18px;
    height: 18px;
    padding: 0 5px;
    font-size: 0.68rem;
  }

  /* The 3 buttons (Rotate/Rotate/Fix Perspective) use UIkit's default
     button padding, generous enough that "Fix Perspective" wraps to two
     lines in a 3-across row on a phone-width column — same fix shape as
     the tabs above, just smaller padding/font instead of a scroll
     fallback, since these three always need to stay visible together. */
  .kkm-editor-controls-row .uk-button {
    flex: 1 1 0;
    padding: 8px 6px;
    font-size: 0.8rem;
  }

  /* Filters wrap onto rows instead of scrolling sideways (search on its own
     full-width row, the two dates side by side, then sort + clear) — the
     usual mobile pattern; nothing is hidden off-screen. */
  .kkm-filter-row {
    flex-wrap: wrap;
    overflow-x: visible;
    gap: 8px;
  }

  .kkm-filter-row .kkm-filter-query {
    flex: 1 1 100%;
  }

  .kkm-filter-row .kkm-clearable-input {
    flex: 1 1 calc(50% - 4px);
    min-width: 0;
  }

  .kkm-filter-row .uk-select {
    flex: 1 1 0;
    min-width: 0;
  }

  .kkm-filter-scroll-hint {
    display: none;
  }

  /* Bottom-sheet modals */
  .uk-modal.uk-open {
    display: flex !important;
    align-items: flex-end !important;
    justify-content: center !important;
    padding: 0 !important;
  }

  .uk-modal-dialog,
  .uk-modal-container .uk-modal-dialog {
    width: 100% !important;
    max-width: 100% !important;
    margin: 0 !important;
    border-radius: 16px 16px 0 0 !important;
    max-height: 88vh;
    overflow-x: hidden;
    overflow-y: auto;
    animation: kkm-sheet-up 0.25s ease-out;
  }

  /* Cropper.js sizes its internal canvas off the source image's natural
     pixel width unless explicitly capped — on a phone photo that's often
     far wider than the viewport, which forced the whole bottom sheet to
     scroll horizontally. */
  .kkm-editor-canvas-wrap {
    max-width: 100%;
    overflow: hidden;
  }

  /* The perspective stage must NOT clip: its corner handles sit exactly on
     the stage edge, so overflow:hidden cut three of the four down to an
     unreachable quarter-dot. The padding gives the handles room inside the
     dialog instead. */
  .kkm-perspective-stage {
    max-width: 100%;
    overflow: visible;
  }

  .kkm-perspective-editor .kkm-upload-grid-image {
    padding: 18px;
    box-sizing: border-box;
  }

  .kkm-editor-canvas-wrap img,
  .kkm-perspective-stage img,
  .cropper-container {
    max-width: 100% !important;
  }
}

/* Custom fullscreen lightbox (zoom + pan + arrow nav) */
.kkm-lightbox {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.94);
  display: none;
  z-index: 2000;
  touch-action: none;
}

.kkm-lightbox.kkm-open {
  display: block;
}

.kkm-lightbox-stage {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}

.kkm-lightbox-img {
  max-width: 92vw;
  max-height: 85vh;
  object-fit: contain;
  user-select: none;
  transition: transform 0.05s linear;
}

.kkm-lightbox-close,
.kkm-lightbox-prev,
.kkm-lightbox-next {
  position: absolute;
  background: rgba(255, 255, 255, 0.12);
  border: none;
  color: #fff;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  z-index: 2001;
}

.kkm-lightbox-close:hover,
.kkm-lightbox-prev:hover,
.kkm-lightbox-next:hover {
  background: rgba(255, 255, 255, 0.25);
}

.kkm-lightbox-close {
  top: 16px;
  right: 16px;
}

.kkm-lightbox-prev {
  top: 50%;
  left: 16px;
  transform: translateY(-50%);
}

.kkm-lightbox-next {
  top: 50%;
  right: 16px;
  transform: translateY(-50%);
}

/* Name/tags text is intentionally never shown in fullscreen — dots are the
   only overlay on the image itself. imgEl.alt (set in lightbox.js) still
   carries the name for accessibility even though this is visually hidden. */
.kkm-lightbox-caption {
  display: none;
}

/* A "Gallery" photo's own dots, reusing the same visual language as the
   masonry card's dots (`.kkm-gallery-dot`) so a viewer recognizes it as
   the same affordance in both places. The row itself is a shrink-to-fit
   pill (width: fit-content + margin: 0 auto, not justify-content: center
   on a full-width bar) with its own semi-opaque background, so the dots
   stay legible sitting directly on top of a photo of *any* color —
   without a backdrop, white dots on a light/white product photo would
   simply disappear. */
.kkm-lightbox-dots {
  position: absolute;
  bottom: 20px;
  left: 0;
  right: 0;
  width: fit-content;
  margin: 0 auto;
  z-index: 2001;
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 7px 12px;
  border-radius: 999px;
  background: rgba(0, 0, 0, 0.45);
}

.kkm-lightbox-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.4);
  cursor: pointer;
  transition: background 0.15s ease, transform 0.15s ease;
}

.kkm-lightbox-dot:hover {
  background: rgba(255, 255, 255, 0.7);
}

.kkm-lightbox-dot-active {
  background: #fff;
  transform: scale(1.3);
}

/* Desktop single-image mode's horizontal drag/pan is handled on
   .kkm-lightbox-img directly (see lightbox.js) — a "Gallery" photo there
   just swaps that one <img>'s src via Next/Prev/dots, no extra track
   markup needed. The mobile scroll-list needs a real nested horizontal
   carousel, though: the *outer* list already owns vertical swipe (between
   top-level photos), so browsing a gallery's own images needs its own
   horizontal scroll-snap area, `touch-action: pan-x` so the two axes route
   to the right container instead of fighting each other. */
.kkm-lightbox-gallery-track {
  position: absolute;
  inset: 0;
  display: flex;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  touch-action: pan-x;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
}

.kkm-lightbox-gallery-track::-webkit-scrollbar {
  display: none;
}

/* Selector deliberately 3 levels deep (not just `.kkm-lightbox-gallery-track
   img`) to out-specificity the pre-existing `.kkm-lightbox-scroll-item img`
   rule below (sized for the single, non-nested cover image every OTHER
   mobile slide uses). Specificity alone isn't enough, though: that rule's
   `max-width: 92vw; max-height: 85vh` are a *different* property from this
   rule's `width`/`height`, so winning the `width`/`height` battle doesn't
   stop the other rule's `max-width`/`max-height` from still applying and
   capping the box anyway (max-width/max-height always constrain width/
   height, regardless of which rule "wins" on those separate properties) —
   they have to be explicitly reset to `none` here too, or every gallery
   sub-image renders at 92vw×85vh *of the whole slide* instead of filling
   it, leaving the rest of the vertical slide's height empty. */
.kkm-lightbox-scroll-item .kkm-lightbox-gallery-track img {
  flex: 0 0 100%;
  scroll-snap-align: start;
  scroll-snap-stop: always;
  width: 100%;
  height: 100%;
  max-width: none;
  max-height: none;
  object-fit: contain;
  user-select: none;
}

@media (max-width: 600px) {
  .kkm-lightbox-prev,
  .kkm-lightbox-next {
    width: 36px;
    height: 36px;
  }
}

/* Mobile lightbox: vertical scroll-snap through images instead of arrows */
.kkm-lightbox-scroll {
  display: none;
  position: absolute;
  inset: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  scroll-snap-type: y mandatory;
  touch-action: pan-y;
  -webkit-overflow-scrolling: touch;
}

.kkm-lightbox-scroll-item {
  height: 100%;
  scroll-snap-align: start;
  scroll-snap-stop: always;
  display: flex;
  align-items: center;
  justify-content: center;
  position: relative;
}

.kkm-lightbox-scroll-item img {
  max-width: 92vw;
  max-height: 85vh;
  object-fit: contain;
  user-select: none;
  transition: transform 0.2s ease;
}

.kkm-lightbox-scroll-item img.kkm-zoomed {
  transform: scale(2);
}

.kkm-lightbox.kkm-mode-scroll .kkm-lightbox-stage,
.kkm-lightbox.kkm-mode-scroll .kkm-lightbox-prev,
.kkm-lightbox.kkm-mode-scroll .kkm-lightbox-next,
.kkm-lightbox.kkm-mode-scroll > .kkm-lightbox-dots {
  display: none;
}

.kkm-lightbox.kkm-mode-scroll .kkm-lightbox-scroll {
  display: block;
}

/* Non-dismissable "site updated" warning shown before an automatic refresh */
#kkm-refresh-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.75);
  z-index: 5000;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 16px;
}

.kkm-refresh-box {
  background: var(--kkm-card-bg, #2a2d2a);
  color: var(--kkm-text, #f3f4f1);
  border: 1px solid var(--kkm-border, #383b38);
  border-radius: 12px;
  padding: 28px 32px;
  text-align: center;
  max-width: 320px;
  box-shadow: 0 10px 40px rgba(0, 0, 0, 0.4);
}

.kkm-refresh-box p {
  margin: 6px 0;
}

.kkm-refresh-box #kkm-refresh-now-btn {
  margin-top: 12px;
}

.kkm-refresh-box #kkm-refresh-skip-btn {
  margin-top: 8px;
}

/* Mobile-first pass on surfaces added this session — none of these had
   been checked on a narrow viewport before. */
@media (max-width: 600px) {
  /* minmax(460px, 1fr) forces horizontal overflow below ~460px; drop to a
     single full-width column instead. */
  .kkm-ba-list {
    grid-template-columns: 1fr;
  }

  /* A fixed 4-column picker grid is cramped on a phone-width modal —
     3 leaves each thumbnail a usable tap target. */
  .kkm-ba-picker-grid {
    grid-template-columns: repeat(3, 1fr);
  }

  .kkm-ba-picker-row {
    flex-direction: column;
  }

  /* The expiry radio group's "Expires after [N] days" rows need to wrap
     onto two lines rather than compress the number input down to
     illegibility. */
  .kkm-radio-option {
    align-items: flex-start;
  }

  .kkm-radio-option span {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 4px;
  }
}

#kkm-refresh-count {
  font-weight: 700;
  color: var(--kkm-accent, #3ecf8e);
}

/* Create-link modal: Keep Updating toggle sits beside "Create link" */
.kkm-create-row {
  display: flex;
  align-items: center;
  gap: 18px;
  flex-wrap: wrap;
}

.kkm-keep-updating {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  cursor: pointer;
  user-select: none;
}

.kkm-keep-updating.kkm-disabled {
  opacity: 0.45;
  cursor: not-allowed;
}

.kkm-keep-updating-note {
  margin: 8px 0 0;
}

/* Bottom navigation (mobile): Portfolio + Settings replace the sidebar drawer.
   Fixed to the viewport bottom, icon over label. Below UIkit modals (1010)
   and toasts/lightbox so those still cover it. */
.kkm-bottom-nav {
  display: none;
}

@media (max-width: 767px) {
  .kkm-sidebar,
  .kkm-sidebar-backdrop,
  .kkm-sidebar-backdrop.kkm-visible {
    display: none !important;
  }

  .kkm-bottom-nav {
    display: flex;
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 900;
    background: var(--kkm-sidebar-bg);
    border-top: 1px solid var(--kkm-border);
    padding-bottom: env(safe-area-inset-bottom);
  }

  .kkm-bottom-nav a {
    flex: 1 1 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 3px;
    height: 58px;
    color: var(--kkm-text-muted);
    text-decoration: none;
    font-size: 0.72rem;
    font-weight: 500;
  }

  .kkm-bottom-nav a.kkm-active {
    color: var(--kkm-accent);
  }

  /* Room so the last row of content and the upload FAB clear the nav. */
  .kkm-main {
    padding-bottom: calc(82px + env(safe-area-inset-bottom));
  }

  .kkm-upload-fab {
    bottom: calc(76px + env(safe-area-inset-bottom));
  }

  .kkm-fab-options {
    bottom: calc(144px + env(safe-area-inset-bottom));
  }

  /* The hamburger is gone; this spacer keeps the title visually centered
     against the single icon button on the right. */
  .kkm-topbar::before {
    content: '';
    order: -1;
    width: 36px;
    height: 36px;
    flex-shrink: 0;
  }
}

/* Settings -> Photos: management table (deliberately not the Portfolio's
   masonry cards, so the two pages never look alike). */
.kkm-sortable-photos {
  cursor: pointer;
  user-select: none;
  white-space: nowrap;
}

.kkm-sortable-photos:hover {
  color: var(--kkm-text);
}

.kkm-photos-th-check {
  width: 32px;
}

.kkm-photos-th-thumb {
  width: 72px;
}

.kkm-photos-table td {
  vertical-align: middle;
}

.kkm-td-thumb img {
  display: block;
  width: 56px;
  height: 56px;
  object-fit: cover;
  border-radius: 8px;
  background: var(--kkm-card-bg);
}

.kkm-photo-name {
  font-weight: 500;
  overflow-wrap: anywhere;
}

.kkm-photo-meta-mobile {
  display: none;
}

.kkm-photos-table tr.kkm-row-selected {
  background: rgba(62, 207, 142, 0.09);
}

.kkm-photos-table .kkm-td-actions .kkm-links-actions {
  justify-content: flex-end;
}

.kkm-photos-table .kkm-td-actions .kkm-icon-btn {
  width: 32px;
  height: 32px;
}

@media (max-width: 700px) {
  /* Compact list rows rather than stacked cards: [check][thumb][name+meta][actions] */
  .kkm-photos-table thead,
  .kkm-photos-table .kkm-td-client,
  .kkm-photos-table .kkm-td-date {
    display: none;
  }

  .kkm-photos-table,
  .kkm-photos-table tbody {
    display: block;
    width: 100%;
  }

  .kkm-photos-table tr {
    display: grid;
    grid-template-columns: auto 52px minmax(0, 1fr) auto;
    align-items: center;
    gap: 10px;
    box-sizing: border-box;
    padding: 8px 6px;
    border-bottom: 1px solid var(--kkm-border);
  }

  .kkm-photos-table td {
    display: block;
    padding: 0;
    border: none !important;
    min-width: 0;
  }

  .kkm-td-thumb img {
    width: 52px;
    height: 52px;
  }

  .kkm-photo-meta-mobile {
    display: block;
    color: var(--kkm-text-muted);
    font-size: 0.78rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  .kkm-photos-table .kkm-td-actions .kkm-links-actions {
    gap: 4px;
  }

  .kkm-photos-table .kkm-td-actions .kkm-icon-btn {
    width: 30px;
    height: 30px;
  }
}

.kkm-td-thumb a {
  cursor: zoom-in;
}

/* Send Folio auth views (sign in / sign up / verify / reset) */
.kkm-auth-links {
  margin: 14px 0 0;
  text-align: center;
  font-size: 0.85rem;
  color: var(--kkm-text-muted);
}

.kkm-auth-links a {
  color: var(--kkm-accent);
}

.kkm-auth-note {
  margin: 0 0 12px;
  font-size: 0.88rem;
  color: var(--kkm-text-muted);
}

.kkm-auth-note strong {
  color: var(--kkm-text);
  overflow-wrap: anywhere;
}

.kkm-auth-legal {
  margin: 14px 0 0;
  font-size: 0.72rem;
  color: var(--kkm-text-muted);
  text-align: center;
}

.kkm-otp-input {
  text-align: center;
  letter-spacing: 6px;
  font-size: 1.3rem;
}

.kkm-auth-view[hidden] {
  display: none !important;
}

/* Account access banner + frozen state (see public/js/access.js) */
.kkm-access-banner {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 6px 12px;
  padding: 10px 14px;
  margin-bottom: 16px;
  border-radius: 10px;
  font-size: 0.88rem;
  line-height: 1.4;
}

.kkm-access-trial {
  background: rgba(62, 207, 142, 0.12);
  border: 1px solid rgba(62, 207, 142, 0.35);
}

.kkm-access-frozen {
  background: rgba(229, 72, 77, 0.14);
  border: 1px solid rgba(229, 72, 77, 0.45);
}

.kkm-access-cta {
  margin-left: auto;
  padding: 4px 14px;
  border-radius: 999px;
  background: var(--kkm-accent);
  color: #0e1410;
  font-weight: 600;
  text-decoration: none;
}

.kkm-access-dismiss {
  background: none;
  border: none;
  color: var(--kkm-text-muted);
  font-size: 1.2rem;
  cursor: pointer;
  padding: 0 4px;
}

body.kkm-frozen [data-needs-active] {
  display: none !important;
}

/* Settings -> Billing */
.kkm-billing {
  display: grid;
  gap: 16px;
  max-width: 560px;
}

.kkm-billing-card {
  background: var(--kkm-card-bg);
  border: 1px solid var(--kkm-border);
  border-radius: 12px;
  padding: 18px 20px;
}

.kkm-billing-card h3 {
  margin: 0 0 8px;
  font-size: 1.05rem;
}

.kkm-billing-price {
  margin: 4px 0;
  font-size: 1.4rem;
}

.kkm-billing-price span {
  font-size: 0.9rem;
  color: var(--kkm-text-muted);
}

.kkm-billing-pill {
  display: inline-block;
  padding: 2px 10px;
  border-radius: 999px;
  font-size: 0.78rem;
  font-weight: 600;
  background: rgba(62, 207, 142, 0.18);
  color: var(--kkm-accent);
}

.kkm-billing-pill.kkm-billing-pill-bad {
  background: rgba(229, 72, 77, 0.2);
  color: #ff8a8d;
}

.kkm-billing-table td,
.kkm-billing-table th {
  padding: 8px 4px;
}

/* Mobile: four tabs don't fit with labels, so only the ACTIVE tab keeps its label
   (the others are icon + count) — all four stay visible, no sideways scrolling. */
@media (max-width: 767px) {
  .kkm-tabs .kkm-tab:not(.kkm-tab-active) > span:nth-child(2) {
    display: none;
  }
}

/* Settings -> Account */
.kkm-logo-row {
  display: flex;
  gap: 16px;
  align-items: flex-start;
  flex-wrap: wrap;
}

.kkm-logo-preview {
  width: 96px;
  height: 96px;
  object-fit: contain;
  background: #101312;
  border: 1px solid var(--kkm-border);
  border-radius: 12px;
  padding: 8px;
  flex-shrink: 0;
}

.kkm-logo-note {
  margin: 0 0 10px;
}

.kkm-cat-editor {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin: 10px 0;
}

.kkm-cat-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 6px 4px 12px;
  border-radius: 999px;
  background: rgba(62, 207, 142, 0.14);
  border: 1px solid rgba(62, 207, 142, 0.4);
  font-size: 0.85rem;
}

.kkm-cat-chip button {
  background: none;
  border: none;
  color: inherit;
  cursor: pointer;
  font-size: 1.05rem;
  line-height: 1;
  padding: 0 4px;
}

.kkm-cat-add {
  display: flex;
  gap: 8px;
}

.kkm-meter {
  height: 10px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.08);
  overflow: hidden;
  margin: 6px 0;
}

.kkm-meter-fill {
  height: 100%;
  width: 0;
  background: var(--kkm-accent, #3ecf8e);
  transition: width 0.3s ease;
}

.kkm-meter-fill.kkm-meter-warn {
  background: #f0a63c;
}

.kkm-meter-fill.kkm-meter-full {
  background: #e5484d;
}

.kkm-export-status {
  margin-top: 14px;
}

.kkm-export-row {
  padding: 10px 12px;
  margin-top: 8px;
  border: 1px solid var(--kkm-border);
  border-radius: 10px;
  font-size: 0.88rem;
}

.kkm-export-row.kkm-export-bad {
  border-color: rgba(229, 72, 77, 0.5);
  color: #ff8a8d;
}

.kkm-export-links {
  margin: 8px 0 0;
  padding-left: 18px;
}

.kkm-sidebar-legal { font-size: 11px; opacity: 0.55; padding: 8px 14px 0; white-space: nowrap; }
.kkm-sidebar-legal a { color: inherit; }
@media (min-width: 768px) { .kkm-sidebar.kkm-collapsed .kkm-sidebar-legal { display: none; } }
