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

:root {
  /* --- Pact24 brand book (RGB values lifted from ci.pdf):
     brand-red:   #ED1C24  (CMYK 0,100,100,0  · RGB 237,28,36)
     brand-gray:  #808285  (CMYK 0,0,0,60     · RGB 128,130,133)
     brand-black: #231F20  (CMYK 0,0,0,100    · RGB 35,31,32)
     Everything below derives from those three.
     --blue is kept as a token name for back-compat; semantically it is the
     brand accent (red). --red stays as a deeper destructive/danger color so
     "delete" / "offline" doesn't collide with brand-primary chrome.
  */
  --font: 'Geist', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  --font-mono: 'Geist Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
  --bg: #FAFAFA;
  --text: #231F20;
  --text-secondary: #808285;
  --border: rgba(35, 31, 32, 0.09);
  --white: #ffffff;
  --black: #231F20;
  /* brand-primary (accent) */
  --brand-red: #ED1C24;
  --brand-red-dark: #C40F17;
  --brand-red-soft: #FCE4E5;
  --brand-gray: #808285;
  --brand-black: #231F20;
  /* legacy token aliases — code across the app references --blue for the
     accent color, so we keep the name and point it at brand-red. */
  --blue: #ED1C24;
  --blue-soft: #FCE4E5;
  /* status colors — green and yellow are needed for "online" / "warning"
     UX but aren't in the two-color brand. Picked muted neutrals so they
     read calm next to the brand red. */
  --green: #2E8456;
  --green-soft: #E4F0EA;
  --yellow: #CA8A04;
  --red: #A8362E;
  --gray-50: #F6F6F6;
  --gray-100: #F0F0F0;
  --gray-200: #E6E6E7;
  --gray-300: #C8C9CB;
  --radius: 14px;
  --radius-sm: 10px;
  --radius-full: 9999px;
  --shadow: 0 1px 0 rgba(35,31,32,0.02), 0 1px 2px rgba(35,31,32,0.04);
  --shadow-md: 0 1px 0 rgba(35,31,32,0.02), 0 8px 24px -12px rgba(35,31,32,0.12);
  --transition: 0.22s cubic-bezier(0.2, 0.7, 0.2, 1);
}

html {
  font-family: var(--font);
  font-size: 15px;
  line-height: 1.5;
  color: var(--text);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

body {
  min-height: 100vh;
}

a {
  color: var(--blue);
  text-decoration: none;
  transition: opacity var(--transition);
}
a:hover { opacity: 0.75; }

/* ===== App shell (sidebar + main) ===== */
.app {
  display: grid;
  grid-template-columns: 232px 1fr;
  min-height: 100vh;
}

@media (max-width: 880px) {
  .app { grid-template-columns: 1fr; }
}

/* Off-canvas drawer scrim — only materialises at the mobile breakpoint. */
.nav-scrim { display: none; }
@media (max-width: 880px) {
  .nav-scrim {
    display: block;
    position: fixed;
    inset: 0;
    z-index: 45;
    background: rgba(11, 11, 14, 0.4);
    opacity: 0;
    pointer-events: none;
    transition: opacity 220ms ease;
  }
  .app.is-nav-open .nav-scrim {
    opacity: 1;
    pointer-events: auto;
  }
}

/* Prevent the page from scrolling behind an open drawer. Plain
   `overflow: hidden` on <body> is ignored by iOS Safari, so the controller
   pairs this class with position:fixed + a restored scroll offset. */
body.nav-locked {
  position: fixed;
  left: 0;
  right: 0;
  overflow: hidden;
}

/* ===== Sidebar ===== */
.sidebar {
  position: sticky;
  top: 0;
  height: 100vh;
  padding: 18px 14px 14px;
  background: var(--gray-100);
  border-right: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  gap: 4px;
  z-index: 50;
}

@media (max-width: 880px) {
  /* Slide the sidebar off-canvas; the hamburger in the topbar toggles it.
     `visibility: hidden` (flipped only after the slide-out finishes) keeps the
     off-screen nav out of the tab order and screen-reader tree while closed. */
  .sidebar {
    position: fixed;
    top: 0;
    left: 0;
    bottom: 0;
    width: 264px;
    max-width: 84vw;
    height: 100vh;
    height: 100dvh;
    overflow-y: auto;
    transform: translateX(-100%);
    visibility: hidden;
    transition: transform 240ms cubic-bezier(0.2, 0.7, 0.2, 1),
                visibility 0s linear 240ms;
    box-shadow: 0 18px 50px rgba(11, 11, 14, 0.22);
  }
  .app.is-nav-open .sidebar {
    transform: none;
    visibility: visible;
    /* Same slide curve as the closed state; only show immediately (no delay). */
    transition-delay: 0s, 0s;
  }
}

.brand {
  display: flex;
  align-items: center;
  padding: 6px 10px 16px;
  color: var(--text);
  margin-top: 2px;
}
.brand:hover { opacity: 1; }

.brand__logo {
  height: 28px;
  width: auto;
  display: block;
  object-fit: contain;
  /* The master PNG ships with the brand gray + brand red baked in;
     no additional tint needed. */
}

.nav-section {
  display: flex;
  flex-direction: column;
  gap: 1px;
}

.nav-item {
  position: relative;
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 8px 12px;
  border-radius: var(--radius-sm);
  color: var(--text);
  font-size: 13.5px;
  font-weight: 500;
  transition: background var(--transition), color var(--transition);
}
.nav-item:hover {
  background: rgba(11, 11, 14, 0.045);
  opacity: 1;
}
.nav-item__icon {
  width: 18px;
  height: 18px;
  color: var(--text-secondary);
  flex-shrink: 0;
  transition: color var(--transition);
}
.nav-item:hover .nav-item__icon { color: var(--text); }

.nav-item--active {
  background: var(--white);
  color: var(--text);
  box-shadow: 0 0 0 1px var(--border) inset, 0 1px 2px rgba(11, 11, 14, 0.03);
}
.nav-item--active .nav-item__icon { color: var(--blue); }
.nav-item--active::before {
  content: "";
  position: absolute;
  left: -14px;
  top: 50%;
  transform: translateY(-50%);
  width: 3px;
  height: 18px;
  border-radius: 0 3px 3px 0;
  background: var(--blue);
}

.nav-count {
  margin-left: auto;
  font-size: 11px;
  font-weight: 500;
  color: var(--text-secondary);
  padding: 1px 7px;
  border-radius: var(--radius-full);
  background: rgba(35, 31, 32, 0.05);
  line-height: 1.4;
}
.nav-item--active .nav-count {
  background: var(--blue-soft);
  color: var(--brand-red);
}

.sidebar__spacer { flex: 1; }

/* user-card details/menu */
.sidebar__user {
  position: relative;
  margin-top: 4px;
}
.sidebar__user[open] > summary {
  background: var(--gray-200);
}

.sidebar__user-summary {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 10px;
  border-radius: var(--radius-sm);
  background: rgba(11, 11, 14, 0.03);
  border: 1px solid var(--border);
  cursor: pointer;
  transition: background var(--transition);
  list-style: none;
}
.sidebar__user-summary::-webkit-details-marker { display: none; }
.sidebar__user-summary:hover { background: rgba(11, 11, 14, 0.06); }

.avatar {
  width: 30px;
  height: 30px;
  border-radius: 50%;
  background: linear-gradient(135deg, var(--blue), var(--brand-red-dark));
  color: var(--white);
  display: grid;
  place-items: center;
  font-weight: 600;
  font-size: 11px;
  letter-spacing: 0.02em;
  flex-shrink: 0;
}

.sidebar__user-info {
  flex: 1;
  min-width: 0;
  line-height: 1.25;
}
.sidebar__user-name {
  font-size: 12.5px;
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.sidebar__user-meta {
  font-size: 11px;
  color: var(--text-secondary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.sidebar__user-chevron {
  color: var(--text-secondary);
  flex-shrink: 0;
  transition: transform var(--transition);
}
.sidebar__user[open] .sidebar__user-chevron {
  transform: rotate(180deg);
}

.sidebar__user-menu {
  position: absolute;
  bottom: calc(100% + 6px);
  left: 0;
  right: 0;
  padding: 6px;
  background: var(--white);
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  box-shadow: var(--shadow-md);
  display: flex;
  flex-direction: column;
  gap: 2px;
  z-index: 100;
}

.sidebar__user-menu-section {
  padding: 8px 10px;
  border-bottom: 1px solid var(--border);
  margin-bottom: 4px;
}
.sidebar__user-menu-section:last-child {
  border-bottom: none;
  margin-bottom: 0;
}

.sidebar__user-menu-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 12px;
  font-size: 13px;
  color: var(--text);
  border-radius: 8px;
  transition: background var(--transition);
}
.sidebar__user-menu-item:hover {
  background: var(--gray-100);
  opacity: 1;
}
.sidebar__user-menu-item--danger { color: var(--red); }
.sidebar__user-menu-item--danger:hover {
  background: rgba(168, 54, 46, 0.08);
}

.sidebar__user-menu-item svg {
  color: var(--text-secondary);
  flex-shrink: 0;
}
.sidebar__user-menu-item--danger svg { color: var(--red); }

/* admin company switcher inside the user menu */
.sidebar__user-menu .company-session-switcher {
  flex-direction: column;
  align-items: stretch !important;
  gap: 6px !important;
}
.sidebar__user-menu .company-session-switcher label {
  font-size: 10.5px !important;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-secondary) !important;
}
.sidebar__user-menu .nav-company-select {
  width: 100%;
  font-size: 12.5px;
  padding: 6px 8px;
}

/* ===== Settings sub-nav: keep .nav-link for /settings/* tabs ===== */
.nav-link {
  color: var(--text-secondary);
  font-size: 13px;
  font-weight: 500;
  padding: 6px 14px;
  border-radius: var(--radius-full);
  transition: all var(--transition);
}
.nav-link:hover {
  color: var(--text);
  background: var(--gray-200);
  opacity: 1;
}
.nav-link--active {
  color: var(--text);
  background: var(--gray-200);
}
.nav-link--icon {
  padding: 6px 10px;
  display: inline-flex;
  align-items: center;
}

/* ===== Per-row "Akcje" dropdown on the Devices index ===== */
.row-actions-menu {
  position: relative;
  display: inline-block;
}
.row-actions-menu > summary {
  list-style: none;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 4px;
}
.row-actions-menu > summary::-webkit-details-marker { display: none; }
.row-actions-menu[open] > summary {
  color: var(--text);
  background: var(--gray-200);
}
.row-actions-menu__panel {
  position: absolute;
  right: 0;
  top: calc(100% + 6px);
  min-width: 220px;
  padding: 6px;
  background: var(--white);
  border-radius: var(--radius-sm);
  border: 1px solid var(--gray-200);
  box-shadow: var(--shadow-md);
  display: flex;
  flex-direction: column;
  gap: 2px;
  z-index: 100;
  text-align: left;
}
.row-actions-menu__item {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 8px 12px;
  font-size: 13px;
  color: var(--text);
  background: transparent;
  border: none;
  text-align: left;
  border-radius: 8px;
  cursor: pointer;
  transition: background var(--transition);
}
.row-actions-menu__item > svg { flex-shrink: 0; }
.row-actions-menu__item:hover:not(:disabled) {
  background: var(--gray-100);
  opacity: 1;
}
.row-actions-menu__item:disabled {
  color: var(--text-secondary);
  cursor: not-allowed;
  opacity: 0.6;
}
.row-actions-menu__item--danger {
  color: var(--red);
}
.row-actions-menu__item--danger:hover:not(:disabled) {
  background: rgba(168, 54, 46, 0.08);
  color: var(--red);
}
/* Touch devices need a ~44px tap target; the 13px/8px-padded items are ~33px,
   and the Akcje summary trigger (.btn--sm) is ~30px. */
@media (hover: none) and (pointer: coarse) {
  .row-actions-menu__item { min-height: 44px; }
  .row-actions-menu > summary { min-height: 44px; box-sizing: border-box; }
}

/* Inline icon-button cluster on campaigns table rows. Hidden by default;
   revealed on row hover or on keyboard focus inside the row. */
.row-actions-cluster {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  justify-content: flex-end;
  opacity: 0;
  transition: opacity var(--transition);
}
tr:hover .row-actions-cluster,
tr:focus-within .row-actions-cluster {
  opacity: 1;
}

/* Two-line table cell content: bold primary line + muted secondary line. */
.row-title {
  font-weight: 500;
  color: var(--text);
}
.row-sub {
  font-size: 12px;
  color: var(--text-secondary);
  margin-top: 2px;
}

/* Settings sub-nav (tabs under page header on /settings/* pages) */
.settings-tabs {
  display: flex;
  gap: 4px;
  margin-top: 16px;
  padding-bottom: 12px;
  border-bottom: 1px solid var(--gray-200);
}

/* ===== Locale toggle ===== */
.locale-toggle {
  font-size: 11px;
  font-weight: 600;
  padding: 4px 10px;
  border-radius: 6px;
  border: 1px solid var(--gray-300);
  color: var(--text-secondary);
  text-decoration: none;
  transition: all var(--transition);
  letter-spacing: 0.02em;
}
.locale-toggle:hover {
  background: var(--gray-100);
  color: var(--text);
  border-color: var(--gray-300);
  opacity: 1;
}

/* ===== Main Content ===== */
.main-content {
  max-width: 1200px;
  margin: 0 auto;
  padding: 32px 24px 64px;
}

/* Unauthenticated pages (login + password reset). Vertically stacks the
   brand logo, the form card, and any footer link with consistent gaps. */
.auth-shell {
  max-width: 440px;
  padding-top: 64px;
}

.auth-locale {
  display: flex;
  justify-content: flex-end;
  margin-bottom: 24px;
}

.auth-brand {
  display: flex;
  justify-content: center;
  margin-bottom: 28px;
}
.auth-brand:hover { opacity: 1; }
.auth-brand__logo {
  height: 48px;
  width: auto;
  display: block;
}

.auth-card-wrap {
  max-width: 400px;
  margin: 0 auto;
}

.auth-title {
  text-align: center;
  font-size: 22px;
  font-weight: 500;
  letter-spacing: -0.015em;
  margin-bottom: 24px;
}

/* Wraps the topbar + scrolling main content so they share the same column. */
.main-col {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

/* Sticky topbar with breadcrumb (left), search placeholder + help (right). */
.topbar {
  position: sticky;
  top: 0;
  z-index: 40;
  height: 60px;
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 0 48px;
  background: color-mix(in srgb, var(--bg) 80%, transparent);
  -webkit-backdrop-filter: saturate(140%) blur(14px);
  backdrop-filter: saturate(140%) blur(14px);
  border-bottom: 1px solid var(--border);
}
@media (max-width: 1100px) { .topbar { padding: 0 32px; } }
@media (max-width: 880px)  { .topbar { padding: 0 20px; } }

/* Hamburger lives in the topbar; only relevant once the sidebar goes drawer.
   Compound selector so `display: none` wins: a bare `.topbar__menu` ties on
   specificity with the later `.topbar__icon-btn { display: grid }` and would
   lose on source order, leaving the hamburger visible on desktop too. */
.topbar__icon-btn.topbar__menu { display: none; margin-right: 2px; }
@media (max-width: 880px) {
  .topbar__icon-btn.topbar__menu { display: inline-flex; }
}

/* Enlarge tap targets on touch devices to ~44px (WCAG 2.5.5) without
   disturbing the dense mouse-driven desktop layout. */
@media (hover: none) and (pointer: coarse) {
  .nav-item { min-height: 44px; padding-top: 11px; padding-bottom: 11px; }
  .topbar__icon-btn { width: 40px; height: 40px; }
  .table-action { width: 38px; height: 38px; }
  .sidebar__user-menu-item { min-height: 42px; }
  .tabs__tab { min-height: 44px; }
}

.crumb {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 13px;
  color: var(--text-secondary);
  min-width: 0;
}
.crumb__base    { color: var(--text-secondary); }
.crumb__sep     { color: var(--gray-300); display: inline-flex; flex-shrink: 0; }
.crumb__current { color: var(--text); font-weight: 500; }

.topbar__search {
  margin-left: auto;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
  width: 280px;
  height: 34px;
  padding: 0 12px;
  border-radius: var(--radius-full);
  background: var(--gray-50);
  border: 1px solid var(--border);
  color: var(--text-secondary);
  font-size: 13px;
  cursor: text;
  transition: border-color var(--transition), background var(--transition);
}
.topbar__search:hover { border-color: var(--gray-300); }
.topbar__search { font: inherit; text-align: left; }
.topbar__search > svg { flex-shrink: 0; }
.topbar__search-placeholder {
  flex: 1;
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.topbar__search kbd {
  margin-left: auto;
  font-family: var(--font-mono);
  font-size: 10.5px;
  padding: 1.5px 6px;
  border-radius: 5px;
  background: var(--white);
  border: 1px solid var(--border);
  color: var(--text-secondary);
  flex-shrink: 0;
}

.topbar__icon-btn {
  width: 34px;
  height: 34px;
  border-radius: var(--radius-full);
  color: var(--text-secondary);
  display: grid;
  place-items: center;
  transition: background var(--transition), color var(--transition);
  text-decoration: none;
  flex-shrink: 0;
}
.topbar__icon-btn:hover {
  background: rgba(35, 31, 32, 0.05);
  color: var(--text);
  opacity: 1;
}
/* Drop the dark UA focus ring on tap/click; keep a blue ring for keyboard users. */
.topbar__icon-btn:focus { outline: none; }
.topbar__icon-btn:focus-visible {
  outline: 2px solid var(--blue);
  outline-offset: 2px;
}

/* Notification bell — replaces the old mailto question icon in the
   topbar. The <details> shell is what makes click-to-toggle work
   without JS; the .topbar__bell-panel under it is absolutely
   positioned so it doesn't shift the topbar layout. */
.topbar__bell { position: relative; }
.topbar__bell-summary {
  list-style: none;
  cursor: pointer;
  position: relative;
}
.topbar__bell-summary::-webkit-details-marker,
.topbar__bell-summary::marker { display: none; }

.topbar__bell-badge {
  position: absolute;
  top: 2px;
  right: 2px;
  min-width: 16px;
  height: 16px;
  padding: 0 4px;
  border-radius: var(--radius-full);
  background: #ED1C24; /* same red as the dot indicator on player offline */
  color: #fff;
  font-size: 10px;
  font-weight: 600;
  line-height: 16px;
  text-align: center;
}
.topbar__bell-badge--hidden { display: none; }

.topbar__bell-panel {
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  width: 360px;
  max-width: calc(100vw - 24px);
  background: #fff;
  border: 1px solid var(--border);
  border-radius: 8px;
  box-shadow: 0 8px 24px rgba(0,0,0,0.08);
  z-index: 50;
  overflow: hidden;
}
.topbar__bell-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 10px 12px;
  border-bottom: 1px solid var(--border);
}
.topbar__bell-title {
  font-size: 13px;
  font-weight: 600;
  color: var(--text);
}
.topbar__bell-clear-btn,
.topbar__bell-clear-btn button {
  background: none;
  border: none;
  color: var(--text-secondary);
  font-size: 12px;
  cursor: pointer;
  padding: 0;
}
.topbar__bell-clear-btn:hover,
.topbar__bell-clear-btn button:hover { color: var(--text); }

.topbar__bell-list {
  max-height: 420px;
  overflow-y: auto;
}
.topbar__bell-empty {
  padding: 24px 12px;
  text-align: center;
  font-size: 13px;
  color: var(--text-secondary);
}

/* The row is a container <div> holding two sibling forms: the mark-read
   "main" button (icon + body) and the "remove" × button. The flex layout
   that used to live on the row itself now sits on the main button. */
.topbar__bell-row {
  display: flex;
  align-items: stretch;
  width: 100%;
  border-bottom: 1px solid var(--border);
}
.topbar__bell-row:hover { background: rgba(35,31,32,0.04); }
.topbar__bell-row--unread { background: rgba(237,28,36,0.04); }

.topbar__bell-row-main { flex: 1 1 auto; min-width: 0; display: flex; }
.topbar__bell-row-main button {
  display: flex;
  width: 100%;
  align-items: flex-start;
  gap: 10px;
  padding: 10px 12px;
  text-align: left;
  background: none;
  border: none;
  font: inherit;
  color: inherit;
  cursor: pointer;
  text-decoration: none;
}

.topbar__bell-row-remove { flex: 0 0 auto; display: flex; }
.topbar__bell-row-remove button {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0 10px;
  background: none;
  border: none;
  color: var(--text-secondary);
  cursor: pointer;
}
.topbar__bell-row-remove button:hover,
.topbar__bell-row-remove button:focus-visible { color: #ED1C24; }

.topbar__bell-row-icon { flex-shrink: 0; color: var(--text-secondary); margin-top: 2px; }
.topbar__bell-row-body { flex: 1; min-width: 0; }
.topbar__bell-row-title { font-size: 13px; font-weight: 500; color: var(--text); }
.topbar__bell-row-time  { font-size: 11px; color: var(--text-secondary); margin-top: 2px; }

@media (max-width: 880px) {
  .topbar__search { width: auto; flex: 1; }
  .topbar__search-placeholder { display: none; }
  .topbar__search kbd { display: none; }
}

/* Command palette (⌘K) — global search overlay. */
.cmdk {
  position: fixed;
  inset: 0;
  z-index: 9000;
  display: flex;
  justify-content: center;
  align-items: flex-start;
  padding: 12vh 16px 16px;
  animation: cmdk-fade 140ms ease-out;
}
.cmdk[hidden] { display: none; }
.cmdk__backdrop {
  position: absolute;
  inset: 0;
  background: rgba(35, 31, 32, 0.42);
  backdrop-filter: blur(2px);
}
.cmdk__panel {
  position: relative;
  width: min(640px, 100%);
  background: var(--white);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: 0 18px 48px rgba(0, 0, 0, 0.22);
  overflow: hidden;
  display: flex;
  flex-direction: column;
  max-height: 76vh;
}
.cmdk__input-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 14px;
  border-bottom: 1px solid var(--border);
  color: var(--text-secondary);
}
.cmdk__input {
  flex: 1;
  min-width: 0;
  border: 0;
  outline: 0;
  background: transparent;
  font: inherit;
  font-size: 15px;
  color: var(--text);
}
.cmdk__close {
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
  color: var(--text-secondary);
}
.cmdk__close kbd {
  font-family: var(--font-mono);
  font-size: 10.5px;
  padding: 1.5px 6px;
  border-radius: 5px;
  background: var(--gray-50);
  border: 1px solid var(--border);
  color: var(--text-secondary);
}
.cmdk__results {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: 6px 0;
}
.cmdk__group + .cmdk__group { border-top: 1px solid var(--border); }
.cmdk__group-label {
  padding: 10px 16px 4px;
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-secondary);
}
.cmdk__item {
  display: flex;
  align-items: baseline;
  gap: 10px;
  padding: 9px 16px;
  text-decoration: none;
  color: var(--text);
  font-size: 14px;
  transition: background var(--transition);
}
.cmdk__item:hover,
.cmdk__item[data-active] {
  background: var(--gray-50);
}
.cmdk__item-primary { font-weight: 500; }
.cmdk__item-secondary {
  margin-left: auto;
  color: var(--text-secondary);
  font-size: 12.5px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 55%;
}
.cmdk__empty {
  padding: 28px 16px;
  text-align: center;
  color: var(--text-secondary);
  font-size: 13px;
}
.cmdk__hint {
  padding: 8px 14px;
  border-top: 1px solid var(--border);
  font-size: 11.5px;
  color: var(--text-secondary);
  background: var(--gray-50);
}
body.cmdk-open { overflow: hidden; }

@keyframes cmdk-fade {
  from { opacity: 0; transform: translateY(-4px); }
  to   { opacity: 1; transform: none; }
}

/* Main content area below the topbar. */
.main {
  min-width: 0;
  padding: 36px 48px 80px;
  max-width: 1240px;
  width: 100%;
  animation: page-rise 480ms cubic-bezier(0.2, 0.7, 0.2, 1) both;
}

@media (max-width: 1100px) {
  .main { padding: 32px 32px 64px; }
}
@media (max-width: 880px) {
  .main { padding: 24px 20px 64px; }
}

@keyframes page-rise {
  from { opacity: 0; transform: translateY(6px); }
  to { opacity: 1; transform: none; }
}

/* ===== Typography ===== */
h1 {
  font-size: 32px;
  font-weight: 700;
  letter-spacing: -0.03em;
  margin-bottom: 8px;
}

h2 {
  font-size: 22px;
  font-weight: 600;
  letter-spacing: -0.02em;
  margin-top: 32px;
  margin-bottom: 12px;
}

h3 {
  font-size: 17px;
  font-weight: 600;
  letter-spacing: -0.01em;
  margin-bottom: 4px;
}

p { margin-bottom: 8px; }

small { font-size: 13px; color: var(--text-secondary); }

/* ===== Buttons ===== */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  font-family: var(--font);
  font-size: 14px;
  font-weight: 500;
  padding: 10px 24px;
  border-radius: var(--radius-full);
  border: none;
  cursor: pointer;
  transition: all var(--transition);
  text-decoration: none;
  line-height: 1;
}

.btn--primary {
  background: var(--black);
  color: var(--white);
}
.btn--primary:hover {
  background: #333;
  opacity: 1;
}

.btn--secondary {
  background: var(--gray-200);
  color: var(--text);
}
.btn--secondary:hover {
  background: var(--gray-300);
  opacity: 1;
}

.btn--blue {
  background: var(--blue);
  color: var(--white);
}
.btn--blue:hover {
  background: var(--brand-red-dark);
  opacity: 1;
}

.btn--ghost {
  background: var(--gray-50);
  color: var(--text);
  border: 1px solid var(--border);
}
.btn--ghost > svg { color: var(--text-secondary); }
.btn--ghost:hover {
  background: var(--white);
  border-color: var(--gray-300);
  color: var(--text);
  opacity: 1;
}

.btn--danger {
  color: var(--red);
  background: transparent;
}
.btn--danger:hover {
  background: #fff5f5;
  opacity: 1;
}

.btn--sm {
  font-size: 12px;
  padding: 6px 14px;
}

/* Turbo submit spinner — applied automatically by Turbo during submission */
form.turbo-submitting button[type="submit"],
form[aria-busy="true"] button[type="submit"] {
  position: relative;
  color: transparent !important;
  pointer-events: none;
}
form.turbo-submitting button[type="submit"]::after,
form[aria-busy="true"] button[type="submit"]::after {
  content: "";
  position: absolute;
  width: 16px;
  height: 16px;
  top: 50%;
  left: 50%;
  margin: -8px 0 0 -8px;
  border: 2px solid rgba(255, 255, 255, 0.3);
  border-top-color: white;
  border-radius: 50%;
  animation: spin 0.6s linear infinite;
}

@keyframes spin {
  to { transform: rotate(360deg); }
}

.btn__spinner {
  animation: spin 0.6s linear infinite;
  flex-shrink: 0;
}

.btn--disabled,
.btn:disabled,
.btn[aria-disabled="true"] {
  opacity: 0.6;
  cursor: not-allowed;
}

/* ===== Cards ===== */
.card {
  background: var(--white);
  border-radius: var(--radius);
  border: 1px solid var(--border);
  box-shadow: var(--shadow);
  padding: 20px;
  transition: box-shadow var(--transition);
}
.card:hover {
  box-shadow: var(--shadow-md);
}

.card--flat {
  box-shadow: none;
}
.card--flat:hover {
  box-shadow: none;
}

/* ===== Device Template Card (TV / Radio picker) ===== */
.device-template-card {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 12px;
  padding: 28px 20px;
  cursor: pointer;
  text-align: center;
  color: var(--text-secondary);
  transition: box-shadow var(--transition), border-color var(--transition), color var(--transition), transform var(--transition);
}
.device-template-card:hover {
  color: var(--text);
  border-color: var(--gray-300);
  transform: translateY(-1px);
}
.device-template-card__input {
  position: absolute;
  opacity: 0;
  pointer-events: none;
  width: 0;
  height: 0;
}
.device-template-card__icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 88px;
  height: 88px;
  border-radius: var(--radius);
  background: var(--gray-100);
  color: var(--text);
  transition: background var(--transition), color var(--transition);
}
.device-template-card:hover .device-template-card__icon {
  background: var(--gray-200);
}
.device-template-card__name {
  font-size: 17px;
  letter-spacing: -0.01em;
  color: var(--text);
}
.device-template-card:has(.device-template-card__input:checked) {
  border-color: var(--blue);
  box-shadow: 0 0 0 2px var(--blue) inset, var(--shadow-md);
  color: var(--text);
}
.device-template-card:has(.device-template-card__input:checked) .device-template-card__icon {
  background: var(--blue);
  color: var(--white);
}
.device-template-card__input:focus-visible + .device-template-card__icon {
  outline: 2px solid var(--blue);
  outline-offset: 3px;
}


/* ===== Grid ===== */
.grid {
  display: grid;
  gap: 16px;
}
.grid--2 { grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); }
.grid--3 { grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); }
.grid--4 { grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); }

/* ===== Tables ===== */
.table-wrap {
  background: var(--white);
  border-radius: var(--radius);
  border: 1px solid var(--border);
  box-shadow: var(--shadow);
  /* Was `overflow: hidden`. Switched so action-icon tooltips popping above
     the first row aren't clipped by the wrap's rounded boundary. Cells
     have no border-radius of their own, so the visual rounded corners
     stay intact. */
  overflow: visible;
}

/* On narrow screens the wide data tables can't fit; let the wrap scroll
   horizontally instead of pushing the whole page wider than the viewport.
   (Setting overflow-x to auto forces overflow-y to auto too — acceptable
   here since the hover tooltips that `overflow: visible` protected aren't
   used on touch devices.) */
@media (max-width: 880px) {
  .table-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }
  /* Size to content so genuinely wide tables scroll while narrow ones still
     fit the viewport (min-width:100% keeps them filling the wrap). */
  .table-wrap table { width: max-content; min-width: 100%; }
}

table {
  width: 100%;
  border-collapse: collapse;
}

th {
  text-align: left;
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: var(--text-secondary);
  padding: 12px 20px;
  border-bottom: 1px solid var(--border);
  background: var(--gray-50);
}

td {
  padding: 12px 16px;
  border-bottom: 1px solid var(--gray-200);
  font-size: 14px;
}

tr:last-child td {
  border-bottom: none;
}

tr:hover td {
  background: var(--gray-50);
}

/* ===== Device table (location editor + preview) =====
   Columnar device row: Urządzenie · Zegar · Aktywność · Specyfikacja · Akcje.
   Scoped to .dev-table so it can't bleed into other .table-wrap tables. */
.dev-table td { vertical-align: top; }

/* Urządzenie: status dot + kind icon + name, with description + state chips below. */
.dev-name { display: flex; align-items: flex-start; gap: 9px; font-weight: 600; }
.dev-name__icon { color: var(--text-secondary); display: inline-flex; flex-shrink: 0; margin-top: 1px; }
.dev-name__text { display: inline-flex; flex-direction: column; min-width: 0; }
/* Name never wraps -> the column grows naturally instead of stacking onto 2-3 lines. */
.dev-name__title { white-space: nowrap; }
.dev-name__desc { font-weight: 400; font-size: 0.85em; color: var(--text-secondary); margin-top: 1px; }
.dev-name__meta { margin-top: 5px; display: flex; flex-wrap: wrap; gap: 5px; }

/* Zegar: a single value; muted "—" when the kind doesn't report skew. */
.dev-col-clock { min-width: 64px; }
.dev-val { font-size: 0.9rem; color: var(--text); white-space: nowrap; }
.dev-val--muted { color: var(--text-secondary); }
.dev-val--ok { color: var(--green); font-weight: 500; }
.dev-val--warn { color: var(--yellow); font-weight: 500; }
.dev-val--danger { color: var(--red); font-weight: 500; }

/* Aktywność: ostatnio widziane (prominent) over zainstalowano (smaller, paler). */
.dev-col-when { min-width: 140px; }
.dev-activity { display: flex; flex-direction: column; gap: 2px; }
.dev-activity__seen { font-size: 0.9rem; color: var(--text); white-space: nowrap; }
.dev-activity__seen--danger { color: var(--red); font-weight: 500; }
/* Amber for a degraded-but-up state (e.g. a scale whose push is failing);
   matches the .clock-skew--warning text tone. */
.dev-activity__seen--warn { color: #7a5300; font-weight: 500; }
/* Compound selector so the muted placeholder ("—" / never-seen) wins the
   specificity tie against .dev-activity__seen's own colour (defined later). */
.dev-activity__seen.dev-val--muted { color: var(--text-secondary); }
.dev-activity__installed { font-size: 0.78rem; color: var(--text-secondary); white-space: nowrap; }
/* Secondary "why"/last-contact line under a failure reason. */
.dev-activity__why { font-size: 0.78rem; color: var(--text-secondary); white-space: nowrap; }

/* Specyfikacja: heterogeneous fields, each with a micro-label. It's the last data
   column, so width:100% lets it absorb the table's slack and keep Akcje pinned right. */
.dev-col-spec { min-width: 150px; width: 100%; }
.dev-fields { display: flex; flex-direction: column; gap: 8px; }
.dev-field { display: flex; flex-direction: column; gap: 1px; }
.dev-field__label { font-size: 10px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.06em; color: var(--text-secondary); }
.dev-field__value { font-size: 0.9rem; color: var(--text); line-height: 1.2; }

.dev-col-actions { width: 1%; white-space: nowrap; text-align: right; }

/* Neutral chip (same 4px shape as the clock-skew chips) for an "off" state. */
.clock-skew--muted { background: var(--gray-100); color: var(--text-secondary); }

/* ===== Priority Slider ===== */
input[type="number"].priority-slider__number {
  width: 48px;
  min-width: 48px;
  max-width: 48px;
  height: 32px;
  text-align: center;
  font-size: 16px;
  font-weight: 400;
  padding: 0 2px;
  border: 1px solid var(--gray-300);
  border-radius: 6px;
  font-family: var(--font);
  color: #000000;
  background: #ffffff;
  line-height: 32px;
  box-shadow: none;
  outline: none;
}
input[type="number"].priority-slider__number:focus {
  border-color: var(--gray-300);
  outline: none;
  box-shadow: none;
  color: #000000;
  background: #ffffff;
}
input[type="number"].priority-slider__number:active {
  outline: none;
  box-shadow: none;
}
/* Keep native stepper arrows visible */
input[type="number"].priority-slider__number::-webkit-inner-spin-button {
  -webkit-appearance: inner-spin-button;
  opacity: 1;
  height: 26px;
  cursor: pointer;
}

.priority-slider__header {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 6px;
}

.priority-slider__label {
  font-size: 14px;
  font-weight: 500;
}

.priority-slider__track-wrap {
  position: relative;
  height: 28px;
  display: flex;
  align-items: center;
}

.priority-slider__ramp-bg,
.priority-slider__ramp-fill {
  position: absolute;
  top: 50%;
  left: 0;
  right: 0;
  height: 14px;
  transform: translateY(-50%);
  border-radius: 3px;
  overflow: hidden;
  pointer-events: none;
}
.priority-slider__ramp-bg::before,
.priority-slider__ramp-fill::before {
  content: "";
  display: block;
  width: 100%;
  height: 100%;
  clip-path: polygon(0 90%, 100% 0, 100% 100%, 0 100%);
}
.priority-slider__ramp-bg::before {
  background: var(--gray-200);
}
.priority-slider__ramp-fill {
  z-index: 1;
  width: 50%;
}
.priority-slider__ramp-fill::before {
  background: var(--blue);
  opacity: 0.5;
}

.priority-slider__range {
  position: relative;
  width: 100%;
  -webkit-appearance: none;
  appearance: none;
  background: transparent;
  margin: 0;
  height: 28px;
  cursor: pointer;
  z-index: 2;
  outline: none;
  border: none;
}
.priority-slider__range:focus {
  outline: none;
  box-shadow: none;
}

.priority-slider__range::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: var(--white);
  border: 2px solid var(--blue);
  box-shadow: 0 1px 3px rgba(0,0,0,0.12);
  cursor: grab;
}
.priority-slider__range:active::-webkit-slider-thumb {
  cursor: grabbing;
  background: var(--gray-50);
}

.priority-slider__range::-moz-range-thumb {
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: var(--white);
  border: 2px solid var(--blue);
  box-shadow: 0 1px 3px rgba(0,0,0,0.12);
  cursor: grab;
}
.priority-slider__range::-moz-range-track {
  background: transparent;
  border: none;
}
.priority-slider__range:focus::-moz-range-thumb {
  outline: none;
  box-shadow: 0 1px 3px rgba(0,0,0,0.12);
}

.priority-slider__labels {
  display: flex;
  justify-content: space-between;
  font-size: 10px;
  color: var(--gray-300);
  margin-top: -2px;
  line-height: 1;
}

/* ===== Location Picker ===== */
.loc-toolbar {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 12px;
}

.search-wrap {
  position: relative;
  max-width: 300px;
  flex: 1;
}
.search-wrap__input {
  width: 100%;
  padding-right: 30px;
}
.search-wrap__clear {
  position: absolute;
  right: 6px;
  top: 50%;
  transform: translateY(-50%);
  width: 20px;
  height: 20px;
  border: none;
  background: var(--gray-200);
  border-radius: 50%;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--text-secondary);
  padding: 0;
  transition: all var(--transition);
}
.search-wrap__clear:hover {
  background: var(--gray-300);
  color: var(--text);
}

.loc-toolbar__search {
  max-width: 300px;
  font-family: var(--font);
  font-size: 13px;
  padding: 6px 10px;
  border: 1px solid var(--gray-300);
  border-radius: 6px;
  background: var(--white);
  color: var(--text);
  outline: none;
}
.loc-toolbar__search:focus {
  border-color: var(--blue);
}
.loc-toolbar__search::placeholder {
  color: var(--gray-300);
}

.loc-toolbar__actions {
  display: flex;
  gap: 8px;
}

.loc-toolbar__link {
  font-family: var(--font);
  font-size: 12px;
  font-weight: 500;
  color: var(--blue);
  background: none;
  border: none;
  cursor: pointer;
  padding: 4px 0;
  white-space: nowrap;
}
.loc-toolbar__link:hover {
  opacity: 0.7;
}

.loc-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  gap: 6px;
}

.loc-item {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 12px;
  border-radius: 4px;
  border: 1px solid var(--gray-200);
  cursor: pointer;
  transition: all var(--transition);
  background: var(--white);
}
.loc-item:hover {
  border-color: var(--gray-300);
  background: var(--gray-50);
}
.loc-item:has(.loc-item__check:checked) {
  background: rgba(237, 28, 36, 0.06);
  border-color: rgba(237, 28, 36, 0.25);
}
.loc-item:has(.loc-item__check:checked) .loc-item__name {
  color: var(--blue);
  font-weight: 500;
}

.loc-item__check {
  margin: 0;
  flex-shrink: 0;
}

.loc-item__name {
  font-size: 13px;
  font-weight: 400;
  color: var(--text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0;
}

/* ===== Device-kind scope cards (campaign form) ===== */
.scope-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 12px;
}
.scope-card {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 14px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--gray-200);
  cursor: pointer;
  transition: all var(--transition);
  background: var(--white);
}
.scope-card:hover {
  border-color: var(--gray-300);
  background: var(--gray-50);
}
.scope-card:has(input:checked) {
  background: rgba(237, 28, 36, 0.06);
  border-color: rgba(237, 28, 36, 0.25);
}
.scope-card__head {
  display: flex;
  align-items: center;
  gap: 8px;
}
.scope-card__icon {
  color: var(--text-secondary);
  flex-shrink: 0;
}
/* The shared DEVICE_SCOPE_ICONS svgs carry only a viewBox (no width/height) so
   each call site sizes them; the form's scope cards render them at 24px. */
.scope-card__icon svg {
  width: 24px;
  height: 24px;
}
.scope-card:has(input:checked) .scope-card__icon,
.scope-card:has(input:checked) .scope-card__title {
  color: var(--brand-red);
}
.scope-card__title {
  font-weight: 500;
  color: var(--text);
}
.scope-card__help {
  font-size: 13px;
  color: var(--text-secondary);
  margin: 0;
}
@media (max-width: 640px) {
  .scope-grid { grid-template-columns: 1fr; }
}

/* ===== Location filters (campaign form) ===== */
.loc-filters {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 12px 16px;
  margin-bottom: 16px;
  padding-bottom: 16px;
  border-bottom: 1px solid var(--border);
}

.loc-filters__field {
  min-width: 0;
}

.loc-filters__label {
  display: block;
  font-size: 11px;
  font-weight: 600;
  color: var(--text-secondary);
  text-transform: uppercase;
  letter-spacing: 0.4px;
  margin-bottom: 4px;
}

.loc-filters__hint {
  display: block;
  margin-top: 4px;
  font-size: 11px;
  color: var(--text-secondary);
  line-height: 1.4;
}

/* ===== Tag select ===== */
.tag-select {
  position: relative;
  width: 100%;
}

.tag-select__box {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px;
  min-height: 38px;
  padding: 4px 8px;
  border: 1px solid var(--gray-300);
  border-radius: 6px;
  background: var(--white);
  cursor: text;
  transition: border-color var(--transition);
}

.tag-select--open .tag-select__box {
  border-color: var(--blue);
}

.tag-select__pill {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 2px 4px 2px 8px;
  background: #3b8bd5;
  color: var(--white);
  border-radius: 4px;
  font-size: 13px;
  line-height: 1.4;
}

.tag-select__pill-label {
  white-space: nowrap;
}

.tag-select__pill-x {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
  border: none;
  background: rgba(255, 255, 255, 0.2);
  color: var(--white);
  border-radius: 3px;
  font-size: 14px;
  line-height: 1;
  cursor: pointer;
  padding: 0;
  font-family: inherit;
}

.tag-select__pill-x:hover {
  background: rgba(255, 255, 255, 0.4);
}

.tag-select__input {
  flex: 1 1 120px;
  min-width: 120px;
  border: none !important;
  outline: none !important;
  font-size: 13px;
  font-family: var(--font);
  background: transparent;
  padding: 4px 0;
  color: var(--text);
  max-width: none !important;
  width: auto !important;
}

.tag-select__input::placeholder {
  color: var(--gray-300);
}

.tag-select__dropdown {
  position: absolute;
  top: calc(100% + 2px);
  left: 0;
  right: 0;
  z-index: 50;
  margin: 0;
  padding: 4px 0;
  list-style: none;
  background: var(--white);
  border: 1px solid var(--gray-300);
  border-radius: 6px;
  box-shadow: 0 6px 16px rgba(0, 0, 0, 0.08);
  max-height: 240px;
  overflow-y: auto;
}

.tag-select__option {
  padding: 8px 14px;
  cursor: pointer;
  font-size: 13px;
  color: var(--text);
}

.tag-select__option:hover {
  background: rgba(237, 28, 36, 0.08);
}

.tag-select__empty {
  padding: 8px 14px;
  font-size: 13px;
  color: var(--text-secondary);
  cursor: default;
  list-style: none;
}

.tag-select__source {
  display: none;
}

/* ===== Forms ===== */
fieldset {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 20px;
  background: var(--white);
}

legend {
  font-size: 14px;
  font-weight: 600;
  color: var(--text);
  padding: 0 8px;
}

label {
  font-size: 14px;
  font-weight: 500;
  color: var(--text);
}

input[type="text"],
input[type="email"],
input[type="password"],
input[type="number"],
input[type="date"],
input[type="time"],
input[type="url"],
input[type="search"],
select,
textarea {
  width: 100%;
  max-width: 400px;
  font-family: var(--font);
  font-size: 15px;
  padding: 10px 14px;
  border: 1px solid var(--gray-300);
  border-radius: var(--radius-sm);
  background: var(--white);
  color: var(--text);
  transition: border-color var(--transition), box-shadow var(--transition);
  outline: none;
}

input:focus, select:focus, textarea:focus {
  border-color: var(--blue);
  box-shadow: 0 0 0 3px rgba(237, 28, 36, 0.15);
}

input[type="checkbox"] {
  width: 16px;
  height: 16px;
  accent-color: var(--blue);
  margin-right: 6px;
  vertical-align: middle;
}

input[type="radio"] {
  accent-color: var(--blue);
  margin-right: 6px;
}

input[type="file"] {
  font-family: var(--font);
  font-size: 14px;
}

input[type="submit"] {
  font-family: var(--font);
  font-size: 14px;
  font-weight: 500;
  padding: 10px 24px;
  border-radius: var(--radius-full);
  border: none;
  background: var(--black);
  color: var(--white);
  cursor: pointer;
  transition: all var(--transition);
}
input[type="submit"]:hover {
  background: #333;
}

/* ===== Flash messages ===== */
.flash {
  padding: 12px 20px;
  border-radius: var(--radius-sm);
  font-size: 14px;
  font-weight: 500;
  margin-bottom: 24px;
}

.flash--notice {
  background: #f0fdf4;
  color: #166534;
  border: 1px solid #bbf7d0;
}

.flash--alert {
  background: #fef2f2;
  color: #991b1b;
  border: 1px solid #fecaca;
}

/* ===== Status dots ===== */
.status-dot {
  display: inline-block;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  margin-right: 6px;
}
.status-dot--active { background: var(--green); }
.status-dot--pending { background: var(--yellow); }
.status-dot--draft { background: var(--gray-300); }
.status-dot--archived { background: var(--text-secondary); }

/* ===== Clock-skew badge (kiosk BIOS-battery health) ===== */
.clock-skew {
  display: inline-block;
  font-size: 0.8em;
  margin-top: 2px;
  padding: 1px 6px;
  border-radius: 4px;
  font-weight: 500;
}
.clock-skew--ok { background: #e6f4ea; color: #137333; }
.clock-skew--warning { background: #fef7e0; color: #7a5300; }
.clock-skew--danger { background: #fce8e6; color: #a50e0e; }

/* ===== Media grid ===== */
.media-card {
  background: var(--white);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 12px;
  text-align: center;
  transition: all var(--transition);
}
.media-card:hover {
  box-shadow: var(--shadow-md);
}

.media-card img {
  max-width: 100%;
  height: auto;
  border-radius: var(--radius-sm);
  margin-bottom: 8px;
}

/* ===== File upload zone ===== */
.file-upload-zone {
  text-align: center;
  padding: 8px 0 4px;
}

.file-upload-zone__input {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

.file-upload-zone__label {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 10px 28px;
  border: 1.5px solid var(--black);
  border-radius: var(--radius-full);
  background: var(--white);
  color: var(--black);
  font-family: inherit;
  font-size: 14px;
  font-weight: 500;
  cursor: pointer;
  transition: all var(--transition);
  -webkit-font-smoothing: antialiased;
}

.file-upload-zone__label + .file-upload-zone__label {
  margin-left: 8px;
}

.file-upload-zone__label:hover {
  background: var(--black);
  color: var(--white);
}

/* Keyboard focus ring for button-driven upload zones (device/location photo),
   whose hidden input is tabindex="-1". The .file-upload-zone__input:focus rule
   below still serves the campaigns form, where the input keeps a native label. */
.file-upload-zone__label:focus-visible {
  outline: none;
  border-color: var(--blue);
  box-shadow: 0 0 0 3px rgba(237, 28, 36, 0.15);
}

.file-upload-zone__label:hover .file-upload-zone__icon {
  color: var(--white);
}

.file-upload-zone__icon {
  display: flex;
  align-items: center;
  color: var(--black);
  transition: color var(--transition);
}

.file-upload-zone__text {
  line-height: 1;
}

.file-upload-zone__hint {
  margin-top: 10px;
  font-size: 13px;
  color: var(--text-secondary);
}

.file-upload-zone__input:focus + .file-upload-zone__label {
  border-color: var(--blue);
  box-shadow: 0 0 0 3px rgba(237, 28, 36, 0.15);
}

.file-upload-zone--dragover {
  background: rgba(237, 28, 36, 0.08);
  outline: 2px dashed var(--blue);
  outline-offset: -4px;
  border-radius: var(--radius-sm);
}

/* ===== Single-photo upload (location/device) ===== */
.photo-upload {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.photo-upload__preview {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  min-height: 220px;
  max-height: 360px;
  border: 1.5px dashed var(--gray-200);
  border-radius: var(--radius-sm);
  background: var(--gray-50);
  color: var(--text-secondary);
  font-size: 13px;
  overflow: hidden;
}

.photo-upload__remove {
  position: absolute;
  top: 8px;
  right: 8px;
  width: 32px;
  height: 32px;
  border-radius: 50%;
  border: 1px solid var(--gray-200);
  background: rgba(255, 255, 255, 0.92);
  color: var(--text-secondary);
  font-size: 20px;
  line-height: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  text-decoration: none;
  transition: all var(--transition);
}

.photo-upload__remove:hover {
  background: #fee2e2;
  color: var(--red);
  border-color: #fecaca;
}

.photo-upload__preview--filled {
  border-style: solid;
  background: var(--white);
  padding: 0;
}

.photo-upload__preview img {
  display: block;
  max-width: 100%;
  max-height: 360px;
  object-fit: contain;
}

.photo-upload__placeholder {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  padding: 24px;
  text-align: center;
}

.photo-upload__placeholder-icon {
  color: var(--text-secondary);
  opacity: 0.6;
}

/* ===== Upload previews ===== */
.upload-previews {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-top: 16px;
}

.upload-previews:empty {
  display: none;
}

.upload-card {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 12px;
  border: 1px solid var(--gray-200);
  border-radius: var(--radius-sm);
  background: var(--gray-50);
  transition: all var(--transition);
  position: relative;
}

.upload-card--completed {
  border-color: #bbf7d0;
  background: #f0fdf4;
}

.upload-card__thumb {
  width: 40px;
  height: 40px;
  border-radius: 8px;
  overflow: hidden;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--gray-200);
}

.upload-card__thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.upload-card__thumb--video {
  background: linear-gradient(135deg, #eff6ff, #dbeafe);
  color: #2563eb;
}

.upload-card__thumb--audio {
  background: linear-gradient(135deg, #faf5ff, #f3e8ff);
  color: #7c3aed;
}

.upload-card__info {
  flex: 1;
  min-width: 0;
}

.upload-card__name {
  font-size: 13px;
  font-weight: 500;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.upload-card__size {
  font-size: 11px;
  color: var(--text-secondary);
  margin-bottom: 4px;
}

.upload-card__progress-wrap {
  height: 4px;
  border-radius: 2px;
  background: var(--gray-200);
  overflow: hidden;
}

.upload-card__progress-bar {
  height: 100%;
  width: 0%;
  background: var(--blue);
  border-radius: 2px;
  transition: width 0.15s ease;
}

.upload-card--completed .upload-card__progress-bar {
  background: var(--green);
}

.upload-card__status {
  font-size: 11px;
  color: var(--text-secondary);
  margin-top: 2px;
}

.upload-card__status--error {
  color: var(--red);
}

.upload-card__remove {
  width: 24px;
  height: 24px;
  border-radius: 50%;
  border: none;
  background: transparent;
  color: var(--text-secondary);
  font-size: 16px;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  transition: all var(--transition);
  font-family: var(--font);
}

.upload-card__remove:hover {
  background: #fee2e2;
  color: var(--red);
}

/* ===== Toast ===== */
.toast {
  position: fixed;
  bottom: 24px;
  left: 50%;
  transform: translateX(-50%) translateY(20px);
  background: var(--black);
  color: var(--white);
  padding: 12px 24px;
  border-radius: var(--radius-full);
  font-size: 14px;
  font-weight: 500;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.2);
  z-index: 200;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.3s ease, transform 0.3s ease;
  -webkit-font-smoothing: antialiased;
}

.toast--visible {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
  pointer-events: auto;
}

/* ===== Location Map ===== */
.location-map {
  height: 360px;
  margin-top: 16px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  overflow: hidden;
  box-shadow: var(--shadow-md);
}

/* ===== Locations Overview Map ===== */
.location-overview-map__card {
  padding: 0;
  overflow: hidden;
}

.location-overview-map {
  width: 100%;
  height: 420px;
  background: var(--bg);
}

@media (max-width: 768px) {
  .location-overview-map { height: 280px; }
}

.map-info {
  font-family: 'Geist', system-ui, sans-serif;
  font-size: 13px;
  line-height: 1.45;
  color: var(--text, #231f20);
  padding: 2px 4px 4px;
  min-width: 180px;
}

.map-info__title {
  display: block;
  font-size: 14px;
  font-weight: 600;
  margin-bottom: 4px;
}

.map-info__address {
  color: var(--brand-gray);
  margin-bottom: 8px;
}

.map-info__link {
  display: inline-block;
  font-weight: 500;
  color: var(--brand-red);
  text-decoration: none;
}

.map-info__link:hover { text-decoration: underline; }

/* ===== File Manager ===== */
.fm__layout {
  display: grid;
  grid-template-columns: 220px 1fr;
  gap: 24px;
  min-height: 500px;
}

@media (max-width: 768px) {
  .fm__layout { grid-template-columns: 1fr; }
}

.fm__sidebar {
  display: flex;
  flex-direction: column;
  gap: 24px;
}

.fm__sidebar-section {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.fm__sidebar-title {
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-secondary);
  padding: 0 10px;
  margin-bottom: 4px;
}

.fm__sidebar-link {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 7px 10px;
  border-radius: 8px;
  font-size: 13px;
  font-weight: 500;
  color: var(--text);
  text-decoration: none;
  transition: background var(--transition);
}
.fm__sidebar-link:hover {
  background: var(--gray-100);
  opacity: 1;
}
.fm__sidebar-link--active {
  background: var(--gray-200);
}
.fm__sidebar-link svg {
  flex-shrink: 0;
  color: var(--text-secondary);
}
.fm__sidebar-link--active svg {
  color: var(--blue);
}

.fm__main {
  min-width: 0;
}

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

/* Bulk bar */
.fm__bulk-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 10px 16px;
  margin-bottom: 16px;
  background: var(--brand-red-soft);
  border: 1px solid var(--brand-red);
  border-radius: var(--radius-sm);
}
.fm__bulk-text {
  font-size: 13px;
  color: var(--brand-red-dark);
}

/* File card */
.fm__file-card {
  position: relative;
  background: var(--white);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
  transition: all var(--transition);
}
.fm__file-card:hover {
  box-shadow: var(--shadow-md);
  border-color: var(--gray-300);
  transform: translateY(-1px);
}

.fm__file-check {
  position: absolute;
  top: 8px;
  left: 8px;
  z-index: 2;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: rgba(255,255,255,0.9);
  backdrop-filter: blur(4px);
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 1px 3px rgba(0,0,0,0.15);
  opacity: 0;
  transition: opacity var(--transition);
}
.fm__file-card:hover .fm__file-check {
  opacity: 1;
}
.fm__file-check input {
  margin: 0;
  width: 14px;
  height: 14px;
}
/* Always show if checked */
.fm__file-check:has(input:checked) {
  opacity: 1;
}

.fm__file-thumb {
  width: 100%;
  aspect-ratio: 1;
  overflow: hidden;
  background: var(--gray-50);
}
.fm__file-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.fm__file-info {
  padding: 8px 10px;
}

.fm__file-name {
  font-size: 12px;
  font-weight: 500;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  cursor: text;
  padding: 2px 0;
  border-radius: 3px;
  transition: background var(--transition);
}
.fm__file-name:hover {
  background: var(--gray-100);
}

.fm__file-meta {
  display: grid;
  grid-template-columns: auto 1fr;
  column-gap: 8px;
  align-items: center;
  margin-top: 4px;
  font-size: 11px;
  color: var(--text-secondary);
}

.fm__file-meta__badge {
  align-self: center;
}

.fm__file-meta__values {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}

.fm__file-meta__values > span {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.fm__file-meta__status {
  margin-top: 2px;
}

.fm__file-actions {
  position: absolute;
  top: 8px;
  right: 8px;
  opacity: 0;
  transition: opacity var(--transition);
}
.fm__file-card:hover .fm__file-actions {
  opacity: 1;
}

/* Inline rename input */
.rename-input {
  font-family: var(--font);
  font-size: 12px;
  font-weight: 500;
  padding: 2px 4px;
  border: 1px solid var(--blue);
  border-radius: 4px;
  outline: none;
  width: 100%;
  box-shadow: 0 0 0 3px rgba(237, 28, 36, 0.15);
}

/* ===== Tabs ===== */
.tabs {
  display: flex;
  border-bottom: 1px solid var(--border);
  margin: -20px -20px 20px -20px;
  padding: 0 8px;
  gap: 0;
}

.tabs__tab {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 12px 18px;
  font-family: var(--font);
  font-size: 13px;
  font-weight: 500;
  color: var(--text-secondary);
  background: transparent;
  border: none;
  border-bottom: 2px solid transparent;
  border-radius: 8px 8px 0 0;
  cursor: pointer;
  transition: all var(--transition);
  -webkit-font-smoothing: antialiased;
  position: relative;
  bottom: -1px;
}

.tabs__tab:hover {
  color: var(--text);
  background: var(--gray-50);
}

.tabs__tab--active {
  color: var(--text);
  background: var(--white);
  border-bottom-color: var(--blue);
}

.tabs__tab--active:hover {
  background: var(--white);
}

.tabs__tab svg {
  opacity: 0.5;
}
.tabs__tab--active svg {
  opacity: 1;
  color: var(--blue);
}

.tabs__panel {
  transition: opacity 0.2s ease;
}

.tabs__panel--visible {
  opacity: 1;
}

.tabs__panel--hidden {
  display: none;
  opacity: 0;
}

/* ===== File Browser ===== */
.browser__toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 16px;
  flex-wrap: wrap;
}

.browser__breadcrumbs {
  display: flex;
  align-items: center;
  gap: 4px;
  font-size: 13px;
  min-width: 0;
  overflow-x: auto;
}

.browser__crumb {
  color: var(--text-secondary);
  text-decoration: none;
  white-space: nowrap;
  padding: 2px 6px;
  border-radius: 4px;
  transition: all var(--transition);
}
.browser__crumb:hover {
  background: var(--gray-100);
  color: var(--text);
  opacity: 1;
}
.browser__crumb--active {
  color: var(--text);
  font-weight: 500;
}

.browser__crumb-sep {
  color: var(--gray-300);
  font-size: 12px;
}

/* Browser grid */
.browser__grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
  gap: 10px;
}

.browser__folder-card-wrap {
  position: relative;
}

.fm__folder-check {
  position: absolute;
  top: 6px;
  left: 6px;
  z-index: 2;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: rgba(255,255,255,0.9);
  backdrop-filter: blur(4px);
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 1px 3px rgba(0,0,0,0.15);
  opacity: 0;
  transition: opacity var(--transition);
}
.browser__folder-card-wrap:hover .fm__folder-check {
  opacity: 1;
}
.fm__folder-check:has(input:checked) {
  opacity: 1;
}
.fm__folder-check input {
  margin: 0;
  width: 14px;
  height: 14px;
}

.browser__folder-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  padding: 16px 8px 12px;
  border-radius: var(--radius);
  border: 1px solid transparent;
  text-decoration: none;
  color: var(--text);
  transition: all var(--transition);
  text-align: center;
}
.browser__folder-card:hover {
  background: var(--gray-100);
  border-color: var(--gray-200);
  opacity: 1;
}

.browser__folder-icon {
  color: #5A7BB0;
}

.browser__folder-name {
  font-size: 12px;
  font-weight: 500;
  line-height: 1.3;
  word-break: break-word;
}

.browser__folder-count {
  font-size: 11px;
  color: var(--text-secondary);
}

/* Browser list */
.browser__list {
  display: flex;
  flex-direction: column;
}

.browser__list-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 10px;
  border-radius: 8px;
  transition: background var(--transition);
  text-decoration: none;
  color: var(--text);
  cursor: pointer;
}
.browser__list-row:hover {
  background: var(--gray-100);
  opacity: 1;
}

.browser__list-row--folder {
  font-weight: 500;
}

.browser__list-icon {
  flex-shrink: 0;
  width: 24px;
  display: flex;
  align-items: center;
  justify-content: center;
}
.browser__list-icon--folder {
  color: #5A7BB0;
}

.browser__list-name {
  flex: 1;
  font-size: 13px;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.browser__list-meta {
  font-size: 11px;
  color: var(--text-secondary);
  flex-shrink: 0;
}

.browser__list-check {
  flex-shrink: 0;
}

/* Browser empty */
.browser__empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 32px;
  color: var(--text-secondary);
  font-size: 13px;
}

/* ===== Selection Tray ===== */
.tray__list {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.tray__item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 10px;
  border-radius: 8px;
  background: var(--gray-50);
  transition: background var(--transition);
}
.tray__item:hover {
  background: var(--gray-100);
}

.tray__pos {
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: var(--gray-200);
  color: var(--text-secondary);
  font-size: 11px;
  font-weight: 600;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}

.tray__name {
  flex: 1;
  font-size: 13px;
  font-weight: 500;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.tray__actions {
  display: flex;
  gap: 2px;
  flex-shrink: 0;
  opacity: 0;
  transition: opacity var(--transition);
}
.tray__item:hover .tray__actions {
  opacity: 1;
}

.tray__btn {
  width: 24px;
  height: 24px;
  border: none;
  border-radius: 4px;
  background: transparent;
  color: var(--text-secondary);
  font-size: 10px;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: all var(--transition);
  font-family: var(--font);
}
.tray__btn:hover {
  background: var(--gray-200);
  color: var(--text);
}
.tray__btn--remove:hover {
  background: #fee2e2;
  color: var(--red);
}

/* ===== Badges ===== */
.badge {
  display: inline-block;
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.05em;
  padding: 2px 6px;
  border-radius: 4px;
  text-transform: uppercase;
  -webkit-font-smoothing: antialiased;
}
.badge--green  { background: #dcfce7; color: #166534; }
.badge--blue   { background: #dbeafe; color: #1e40af; }
.badge--purple { background: #f3e8ff; color: #6b21a8; }
.badge--gray   { background: #e5e7eb; color: #374151; }
.badge--red    { background: #fee2e2; color: #991b1b; }

.media-picker__badge {
  position: absolute;
  top: 8px;
  left: 8px;
  z-index: 1;
}

/* ===== Media preview (video) ===== */
.media-preview {
  position: relative;
  width: 100%;
  aspect-ratio: 1;
  overflow: hidden;
  border-radius: var(--radius-sm);
  background: #000;
}

.media-preview__video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.media-preview__overlay {
  position: absolute;
  bottom: 6px;
  right: 6px;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: rgba(0, 0, 0, 0.4);
  backdrop-filter: blur(4px);
  display: flex;
  align-items: center;
  justify-content: center;
}

.media-preview__duration {
  position: absolute;
  bottom: 6px;
  left: 6px;
  padding: 2px 6px;
  border-radius: 4px;
  background: rgba(0, 0, 0, 0.65);
  color: #fff;
  font-size: 11px;
  font-variant-numeric: tabular-nums;
  font-weight: 500;
  line-height: 1.2;
  letter-spacing: 0.02em;
}

/* ===== Media placeholders ===== */
.media-placeholder {
  width: 100%;
  aspect-ratio: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 6px;
  background: var(--gray-100);
  color: var(--text-secondary);
  border-radius: var(--radius-sm);
  font-size: 11px;
  font-weight: 500;
}

.media-placeholder--audio {
  background: linear-gradient(135deg, #faf5ff, #f3e8ff);
  color: #7c3aed;
}

.media-placeholder--video {
  background: linear-gradient(135deg, #eff6ff, #dbeafe);
  color: #2563eb;
}

/* Small fixed-size variant used by the campaign report row (helpers'
   medium_report_thumbnail dash fallback). Overrides the base 100%-of-
   container sizing with a 56x56 cell that matches .report-media__thumb. */
.media-placeholder--sm {
  width: 56px;
  height: 56px;
  aspect-ratio: unset;
  font-size: 18px;
  line-height: 1;
  gap: 0;
}

/* ===== Utilities ===== */
.flex { display: flex; }
.flex-wrap { flex-wrap: wrap; }
.items-center { align-items: center; }
.justify-between { justify-content: space-between; }
.gap-6 { gap: 6px; }
.gap-8 { gap: 8px; }
.gap-12 { gap: 12px; }
.gap-16 { gap: 16px; }
.gap-24 { gap: 24px; }
.mt-16 { margin-top: 16px; }
.mt-24 { margin-top: 24px; }
.mt-32 { margin-top: 32px; }
.mb-8 { margin-bottom: 8px; }
.mb-16 { margin-bottom: 16px; }
.mb-24 { margin-bottom: 24px; }
.text-right { text-align: right; }
.text-center { text-align: center; }
.text-secondary { color: var(--text-secondary); }
.text-sm { font-size: 13px; }

/* ===== Page header ===== */
.page-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 24px;
}
.page-header h1 { margin-bottom: 0; }

/* ===== Toolbar ===== */
.toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 24px;
  flex-wrap: wrap;
}
.toolbar__spacer { flex: 1; min-width: 0; }

/* Export CSV + grid/table toggle grouped at the far right, sitting close
   together (small gap) so they read as adjacent, neighbouring controls. */
.toolbar__actions {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-left: auto;
}

/* Left-aligned filter cluster: search box + (optional) category filter, parted
   by a subtle vertical divider. Wraps to full width on phones. */
.toolbar__filters {
  display: flex;
  align-items: center;
  gap: 12px;
  flex: 1 1 auto;
  min-width: 0;
  flex-wrap: wrap;
}
.toolbar__divider {
  flex: 0 0 auto;
  width: 1px;
  align-self: stretch;
  min-height: 24px;
  background: var(--border);
}
.loc-cat-filter {
  flex: 1 1 220px;
  min-width: 200px;
  max-width: 340px;
}

/* Live "showing X of Y" summary sitting just under the toolbar. */
.list-summary {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: -12px 0 18px;
  font-size: 13px;
  color: var(--text-secondary);
}
.list-summary__dot {
  flex: 0 0 auto;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--blue);
}

/* list-search (Stimulus) hides non-matching rows with this class instead of an
   inline display, so a row's own inline layout (e.g. the franchisee owner rows'
   display:flex) survives being re-shown. !important beats any inline display. */
.js-search-hidden { display: none !important; }

@media (max-width: 640px) {
  .toolbar__divider { display: none; }
  .toolbar__filters .search-wrap,
  .toolbar__filters .loc-cat-filter {
    flex: 1 1 100%;
    max-width: none;
  }
}

/* ===== Filter pills (Filtry / Sortuj on campaigns toolbar) ===== */
.filter-pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 12px;
  border-radius: var(--radius-full);
  border: 1px solid var(--border);
  background: var(--white);
  color: var(--text);
  font-size: 12.5px;
  font-weight: 500;
  white-space: nowrap;
  cursor: pointer;
  list-style: none;
  transition: border-color var(--transition), background var(--transition);
}
.filter-pill::-webkit-details-marker { display: none; }
.filter-pill > svg { color: var(--text-secondary); flex-shrink: 0; }
.filter-pill > strong { font-weight: 500; color: var(--text); }
.filter-pill:hover { border-color: var(--gray-300); }
.filter-pill--active,
.filter-pill-menu[open] > .filter-pill {
  background: var(--gray-50);
  border-color: var(--gray-300);
}
.filter-pill__badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 18px;
  height: 18px;
  padding: 0 5px;
  border-radius: var(--radius-full);
  background: var(--brand-red);
  color: var(--white);
  font-family: var(--font-mono);
  font-size: 10.5px;
  font-weight: 500;
  margin-left: 2px;
}

.filter-pill-menu {
  position: relative;
  display: inline-block;
}
.filter-pill-menu__panel {
  position: absolute;
  right: 0;
  top: calc(100% + 6px);
  min-width: 240px;
  padding: 12px;
  background: var(--white);
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  box-shadow: var(--shadow-md);
  z-index: 100;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.filter-pill-menu__panel--sort {
  min-width: 220px;
  padding: 6px;
  gap: 2px;
}

.filter-pill-menu__label {
  font-size: 10.5px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: var(--text-secondary);
  padding: 4px 8px 2px;
}

.filter-pill-menu__input {
  width: 100%;
  max-width: none;
  padding: 8px 10px;
  font-size: 13px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
}
.filter-pill-menu__input:focus {
  outline: none;
  border-color: var(--blue);
  box-shadow: 0 0 0 3px var(--brand-red-soft);
}

.filter-pill-menu__form {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.filter-pill-menu__actions {
  display: flex;
  gap: 8px;
  align-items: center;
  margin-top: 4px;
}

.filter-pill-menu__item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 7px 10px;
  font-size: 13px;
  color: var(--text);
  border-radius: 7px;
  transition: background var(--transition);
  text-decoration: none;
}
.filter-pill-menu__item:hover {
  background: var(--gray-100);
  opacity: 1;
}
.filter-pill-menu__item--active {
  color: var(--brand-red);
  font-weight: 500;
}
.filter-pill-menu__item--active svg { color: var(--brand-red); }

/* ===== Segmented Control ===== */
.segmented-control {
  display: inline-flex;
  background: var(--gray-200);
  border-radius: var(--radius-sm);
  padding: 3px;
  gap: 2px;
  margin-bottom: 24px;
}

.segmented-control__btn {
  font-family: var(--font);
  font-size: 13px;
  font-weight: 500;
  padding: 6px 14px;
  border-radius: 8px;
  color: var(--text-secondary);
  text-decoration: none;
  transition: all var(--transition);
  white-space: nowrap;
  -webkit-font-smoothing: antialiased;
}
.segmented-control__btn:hover {
  color: var(--text);
  opacity: 1;
}
.segmented-control__btn--active {
  background: var(--white);
  color: var(--text);
  box-shadow: 0 1px 3px rgba(0,0,0,0.08);
}
.segmented-control__btn--active:hover {
  opacity: 1;
}

/* ===== Segmented control — pill variant (campaigns index) =====
   Pill-shaped, hairline border, with inline monospace counts next to
   each label. Counts turn brand-red when the segment is active. */
.seg {
  display: inline-flex;
  padding: 3px;
  background: var(--gray-50);
  border: 1px solid var(--border);
  border-radius: var(--radius-full);
}

.seg__btn {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 5px 12px;
  border-radius: var(--radius-full);
  font-family: var(--font);
  font-size: 12.5px;
  font-weight: 500;
  color: var(--text-secondary);
  text-decoration: none;
  white-space: nowrap;
  transition: background var(--transition), color var(--transition);
  -webkit-font-smoothing: antialiased;
}
.seg__btn:hover {
  color: var(--text);
  opacity: 1;
}
.seg__btn--active {
  background: var(--white);
  color: var(--text);
  box-shadow: 0 1px 2px rgba(35, 31, 32, 0.06);
}
.seg__btn--active:hover {
  opacity: 1;
}

.seg__count {
  font-family: var(--font-mono);
  font-feature-settings: 'tnum';
  font-variant-numeric: tabular-nums;
  font-size: 10.5px;
  color: var(--text-secondary);
}
.seg__btn--active .seg__count {
  color: var(--brand-red);
}

/* The admin sub-nav packs many tabs into a single non-wrapping .seg pill. On a
   phone that pill is wider than the viewport, so scroll it horizontally inside
   this wrapper instead of widening the whole page (CLAUDE.md mobile rule). */
.subnav-scroll {
  max-width: 100%;
  margin-bottom: 24px;
}
@media (max-width: 880px) {
  .subnav-scroll {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
  }
}

/* ===== View Toggle ===== */
.view-toggle {
  display: inline-flex;
  background: var(--gray-200);
  border-radius: var(--radius-sm);
  padding: 3px;
  gap: 2px;
}

.view-toggle__btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 30px;
  border-radius: 7px;
  color: var(--text-secondary);
  transition: all var(--transition);
  text-decoration: none;
}
.view-toggle__btn:hover {
  color: var(--text);
  opacity: 1;
}
.view-toggle__btn--active {
  background: var(--white);
  color: var(--text);
  box-shadow: 0 1px 3px rgba(0,0,0,0.08);
}
.view-toggle__btn--active:hover {
  opacity: 1;
}

/* ===== Table avatar ===== */
.table-avatar {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  object-fit: cover;
  display: block;
  border: 1px solid var(--gray-200);
}

.table-avatar--empty {
  background: var(--gray-100);
  display: flex;
  align-items: center;
  justify-content: center;
}

.table-action {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  border-radius: 6px;
  transition: all var(--transition);
  text-decoration: none;
}
.table-action {
  color: var(--text-secondary);
}
.table-action:hover {
  background: var(--gray-100);
  color: var(--text);
  opacity: 1;
}
/* Edit is a non-destructive action — keep it neutral so it doesn't
   visually compete with the brand-red Delete next to it. */
.table-action--edit {
  color: var(--text-secondary);
}
.table-action--edit:hover {
  background: var(--gray-100);
  color: var(--text);
}
/* Delete is destructive — use the loud brand red so the warning signal
   is unambiguous (matches the old behavior before the rebrand swap
   accidentally made Edit red and Delete muted). */
.table-action--delete {
  color: var(--brand-red);
}
.table-action--delete:hover {
  background: var(--brand-red-soft);
  color: var(--brand-red-dark);
}
.table-action--start {
  color: var(--green);
}
.table-action--start:hover {
  background: rgba(46, 132, 86, 0.1);
}
.table-action--pause {
  color: var(--yellow);
}
.table-action--pause:hover {
  background: rgba(202, 138, 4, 0.12);
}

/* CSS-only tooltip on .table-action[data-tooltip]. Renders the attribute
   text as a small dark chip above the icon, with a tiny arrow. ~400 ms
   reveal delay so accidental flyovers don't trigger; hide is immediate. */
.table-action[data-tooltip],
.device-scope-icon[data-tooltip] {
  position: relative;
}
.table-action[data-tooltip]::after,
.table-action[data-tooltip]::before,
.device-scope-icon[data-tooltip]::after,
.device-scope-icon[data-tooltip]::before {
  position: absolute;
  left: 50%;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.18s ease 0s;
}
.table-action[data-tooltip]::after,
.device-scope-icon[data-tooltip]::after {
  content: attr(data-tooltip);
  bottom: calc(100% + 6px);
  transform: translateX(-50%);
  padding: 5px 9px;
  background: var(--text);
  color: var(--bg);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: -0.005em;
  white-space: nowrap;
  border-radius: 6px;
  box-shadow: var(--shadow-md);
  z-index: 100;
}
.table-action[data-tooltip]::before,
.device-scope-icon[data-tooltip]::before {
  content: "";
  bottom: calc(100% + 2px);
  transform: translateX(-50%);
  border: 4px solid transparent;
  border-top-color: var(--text);
}
.table-action[data-tooltip]:hover::after,
.table-action[data-tooltip]:hover::before,
.table-action[data-tooltip]:focus-visible::after,
.table-action[data-tooltip]:focus-visible::before,
.device-scope-icon[data-tooltip]:hover::after,
.device-scope-icon[data-tooltip]:hover::before,
.device-scope-icon[data-tooltip]:focus-visible::after,
.device-scope-icon[data-tooltip]:focus-visible::before {
  opacity: 1;
  transition-delay: 0.4s;
}

/* Single device-kind-scope icon shown in the campaigns list "Urządzenia"
   column. Sizes the shared 24px scope SVG down to row scale. */
.device-scope-icon {
  display: inline-flex;
  align-items: center;
  color: var(--text-secondary);
}
.device-scope-icon svg {
  width: 18px;
  height: 18px;
}

.btn--outline-success {
  background: transparent;
  color: var(--green);
  border: 1px solid var(--green);
}
.btn--outline-success:hover {
  background: rgba(46, 132, 86, 0.08);
  opacity: 1;
}

.btn--outline-warning {
  background: transparent;
  color: var(--yellow);
  border: 1px solid var(--yellow);
}
.btn--outline-warning:hover {
  background: rgba(255, 159, 10, 0.08);
  opacity: 1;
}

/* ===== Empty state ===== */
.empty-state {
  background: var(--white);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 60px 24px;
  text-align: center;
}

.empty-state__icon {
  font-size: 48px;
  margin-bottom: 16px;
  opacity: 0.3;
  line-height: 1;
}

.empty-state__text {
  color: var(--text-secondary);
  font-size: 16px;
  margin-bottom: 20px;
}

.empty-state__action {
  margin-bottom: 0;
}

/* ===== Sort chevron ===== */
.sort-chevron {
  vertical-align: middle;
  margin-left: 2px;
}

/* ===== Sort links ===== */
.sort-link {
  color: var(--text-secondary);
  text-decoration: none;
  font-size: 12px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  transition: color var(--transition);
}
.sort-link:hover {
  color: var(--text);
  opacity: 1;
}
.sort-link--active {
  color: var(--text);
}

/* ===== Pills ===== */
.pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 11.5px;
  font-weight: 400;
  padding: 3px 10px 3px 8px;
  border-radius: var(--radius-full);
  letter-spacing: 0;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}
.pill--green  { background: var(--green-soft); color: var(--green); }
.pill--yellow { background: #F6EEDA; color: #CA8A04; }
.pill--gray   { background: var(--gray-200); color: var(--text-secondary); }
.pill--red    { background: #F6E4E1; color: #A8362E; }
.pill--rose   { background: #F6E4E1; color: #A8362E; }
.pill--blue   { background: #E6ECF6; color: #2A5DB0; }

.pill .status-dot { margin-right: 0; }

.status-dot--scheduled { background: #2A5DB0; }
.status-dot--expired   { background: #A8362E; opacity: 0.8; }

/* ===== Stat cards ===== */
.stat-card {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 4px;
  padding: 20px;
  background: var(--white);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  text-decoration: none;
  color: var(--text);
  transition: all var(--transition);
  cursor: pointer;
}
.stat-card:hover {
  box-shadow: var(--shadow-md);
  border-color: var(--gray-300);
  transform: translateY(-1px);
  opacity: 1;
}

.stat-card__icon {
  width: 40px;
  height: 40px;
  border-radius: 10px;
  display: flex;
  align-items: center;
  justify-content: center;
  margin-bottom: 4px;
}
.stat-card--draft .stat-card__icon {
  background: rgba(237, 28, 36, 0.08);
  color: var(--blue);
}
.stat-card--active .stat-card__icon {
  background: rgba(46, 132, 86, 0.08);
  color: var(--green);
}
.stat-card--paused .stat-card__icon {
  background: rgba(255, 159, 10, 0.08);
  color: var(--yellow);
}
.stat-card--locations .stat-card__icon {
  background: rgba(237, 28, 36, 0.08);
  color: var(--blue);
}
.stat-card--online .stat-card__icon {
  background: rgba(46, 132, 86, 0.08);
  color: var(--green);
}
.stat-card--offline .stat-card__icon {
  background: rgba(255, 59, 48, 0.08);
  color: var(--red);
}

/* Per-device-kind icon tints. iOS system-palette picks (purple/cyan/orange)
   that don't collide with the existing semantic colours: blue=locations/
   drafts, green=online/active, red=offline, yellow=paused. */
.stat-card--device-player .stat-card__icon {
  background: rgba(175, 82, 222, 0.08);
  color: #af52de;
}
.stat-card--device-radio .stat-card__icon {
  background: rgba(90, 200, 250, 0.08);
  color: #5ac8fa;
}
.stat-card--device-receipt_screen .stat-card__icon {
  background: rgba(255, 149, 0, 0.08);
  color: #ff9500;
}

/* Inert stat cards have no link target — the dashboard's device-kind
   sections render as <div>, not <a>, because there's no global devices
   index page to navigate to. Cancels the hover lift + pointer cursor
   so the user doesn't expect a click target. Card chrome (padding,
   border, icon tint, typography) stays identical to the link cards. */
.stat-card--inert {
  cursor: default;
}
.stat-card--inert:hover {
  box-shadow: none;
  border-color: var(--border);
  transform: none;
}

.stat-card__value {
  font-size: 32px;
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: 1;
}

.stat-card__label {
  font-size: 13px;
  color: var(--text-secondary);
  font-weight: 500;
}

/* ===== Location card ===== */
.location-card {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.location-card__header {
  display: flex;
  align-items: flex-start;
  gap: 14px;
}

.location-card__icon {
  width: 40px;
  height: 40px;
  border-radius: var(--radius-sm);
  background: var(--gray-100);
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  font-size: 18px;
}

.location-card__devices {
  display: flex;
  flex-direction: column;
  gap: 0;
}

.device-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 10px 0;
  border-bottom: 1px solid var(--gray-200);
}
.device-row:last-child { border-bottom: none; }

/* ===== Campaign card ===== */
.campaign-card {
  display: flex;
  flex-direction: column;
  gap: 12px;
  height: 100%;
}

.campaign-card__actions {
  margin-top: auto;
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  padding-top: 8px;
}

.campaign-card__top {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
}

.campaign-card__meta {
  display: flex;
  gap: 16px;
  flex-wrap: wrap;
}

.campaign-card__meta-item {
  font-size: 13px;
  color: var(--text-secondary);
}
.campaign-card__meta-item strong {
  color: var(--text);
}

.campaign-card__locations {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
}

.location-tag {
  font-size: 11px;
  font-weight: 500;
  padding: 2px 8px;
  border-radius: var(--radius-full);
  background: var(--gray-100);
  color: var(--text-secondary);
  border: 1px solid var(--gray-200);
}

/* ===== Form sections ===== */
.form-section {
  margin-bottom: 40px;
}

.form-section__title {
  font-size: 20px;
  font-weight: 700;
  letter-spacing: -0.02em;
  margin-bottom: 6px;
}

.form-section__subtitle {
  font-size: 14px;
  color: var(--text-secondary);
  margin-bottom: 20px;
}

/* ===== Media picker ===== */
.media-picker {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
  gap: 12px;
}

.media-picker__item {
  position: relative;
  border-radius: var(--radius);
  overflow: hidden;
  border: 2px solid transparent;
  transition: all var(--transition);
  cursor: pointer;
  background: var(--white);
}

.media-picker__item:hover {
  box-shadow: var(--shadow-md);
}

.media-picker__item--selected {
  border-color: var(--blue);
  box-shadow: 0 0 0 3px rgba(237, 28, 36, 0.15);
}

.media-picker__thumb {
  width: 100%;
  aspect-ratio: 1;
  object-fit: cover;
  display: block;
  background: var(--gray-100);
}

.media-picker__placeholder {
  width: 100%;
  aspect-ratio: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--gray-100);
  color: var(--text-secondary);
  font-size: 12px;
}

.media-picker__check {
  position: absolute;
  top: 8px;
  right: 8px;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: rgba(255,255,255,0.9);
  backdrop-filter: blur(4px);
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 1px 3px rgba(0,0,0,0.15);
}

.media-picker__check input[type="checkbox"] {
  margin: 0;
  width: 14px;
  height: 14px;
}

.media-picker__label {
  padding: 8px 10px;
  font-size: 12px;
  color: var(--text-secondary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ===== Assigned media (edit view) ===== */
.assigned-media {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
  gap: 12px;
}

.assigned-media__item {
  position: relative;
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--white);
  border: 1px solid var(--border);
  transition: all var(--transition);
}
.assigned-media__item:hover { box-shadow: var(--shadow-md); }

.assigned-media__thumb {
  width: 100%;
  aspect-ratio: 1;
  object-fit: cover;
  display: block;
}

.assigned-media__info {
  padding: 8px 10px;
}

.assigned-media__thumb-wrap {
  position: relative;
}

.assigned-media__download {
  position: absolute;
  right: 6px;
  bottom: 6px;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: rgba(0, 0, 0, 0.55);
  color: white;
  display: flex;
  align-items: center;
  justify-content: center;
  text-decoration: none;
  opacity: 0;
  transition: opacity var(--transition), background var(--transition);
  z-index: 2;
}
.assigned-media__item:hover .assigned-media__download {
  opacity: 1;
}
.assigned-media__download:hover {
  background: rgba(0, 0, 0, 0.8);
}

.assigned-media__remove {
  position: absolute;
  top: 6px;
  right: 6px;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background: rgba(0,0,0,0.5);
  color: white;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 14px;
  text-decoration: none;
  opacity: 0;
  transition: opacity var(--transition);
  line-height: 1;
  z-index: 3;
}
.assigned-media__item:hover .assigned-media__remove {
  opacity: 1;
}
.assigned-media__remove:hover {
  background: var(--red);
  opacity: 1;
}

.status-dot {
  display: inline-block;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  margin-right: 8px;
  vertical-align: middle;
  flex-shrink: 0;
}
.status-dot--online  { background-color: #28a745; }
.status-dot--warning { background-color: #f0ad4e; }
.status-dot--offline { background-color: #dc3545; }

/* Per-kind device glyph cluster on the locations grid card + table. The glyph
   inherits its colour from .dev-glyph--<status>; the count badge sits over the
   icon's top-right corner and gets a matching coloured background per status
   (see the .dev-glyph--<status> .dev-glyph__count rules below). It can't use
   currentColor for the background because the badge sets its own white text
   colour, which currentColor would then resolve to — making it white-on-white. */
.dev-cluster { display: inline-flex; align-items: center; gap: 6px; }
.dev-glyph { position: relative; display: inline-flex; line-height: 0; }
.dev-glyph--healthy { color: #28a745; }
.dev-glyph--warning { color: #f0ad4e; }
.dev-glyph--offline { color: #dc3545; }
.dev-glyph__count {
  position: absolute;
  top: -5px;
  right: -7px;
  min-width: 14px;
  height: 14px;
  padding: 0 3px;
  border-radius: 999px;
  background: #6c757d;
  color: #fff;
  font-size: 10px;
  font-weight: 600;
  line-height: 14px;
  text-align: center;
}
.dev-glyph--healthy .dev-glyph__count { background: #28a745; }
.dev-glyph--warning .dev-glyph__count { background: #f0ad4e; }
.dev-glyph--offline .dev-glyph__count { background: #dc3545; }

.devices-filters {
  display: flex;
  flex-direction: column;
  gap: 12px;
  margin-bottom: 16px;
}
.devices-filters__row {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
}
.devices-filters__label {
  font-size: 0.85em;
  color: var(--text-secondary);
  min-width: 88px;
}
/* A single filter .seg (e.g. the kind row) is wider than a phone. Below the fine
   breakpoint, stack the label above the chips and let the chip group scroll
   horizontally rather than pushing the whole page wider than the viewport
   (CLAUDE.md mobile rule). Shared by the tenant /devices and admin devices list. */
@media (max-width: 640px) {
  .devices-filters__row {
    flex-direction: column;
    align-items: stretch;
    gap: 6px;
  }
  .devices-filters__row .seg {
    max-width: 100%;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
  }
}

.badge--default-always {
  display: inline-block;
  padding: 2px 8px;
  font-size: 0.75em;
  font-weight: 600;
  border-radius: 4px;
  background-color: #dbeafe;
  color: #1e40af;
}
.badge--default-fallback {
  display: inline-block;
  padding: 2px 8px;
  font-size: 0.75em;
  font-weight: 600;
  border-radius: 4px;
  background-color: #fef3c7;
  color: #92400e;
}

/* ===== Device preview ===== */
.preview-stage {
  position: relative;
  min-height: 80vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 24px;
  padding: 40px 20px;
  isolation: isolate;
}
.preview-stage::before {
  content: "";
  position: absolute;
  inset: 0;
  background: radial-gradient(ellipse at center, #1a1f2c 0%, #0a0d14 100%);
  filter: blur(40px);
  opacity: 0.55;
  z-index: -1;
}

.preview-device-name {
  margin: 0;
  font-size: 28px;
  font-weight: 600;
  color: var(--text);
  text-align: center;
}

.preview-tv {
  position: relative;
  width: min(80vw, 960px);
  aspect-ratio: 16 / 9;
}
/* Totem (portrait): flip the bezel to a vertical 9:16 frame, narrow it to fit
   the stage height, and move the speaker out of the now-tall right edge. */
.preview-tv--portrait {
  width: auto;
  height: min(70vh, 640px);
  aspect-ratio: 9 / 16;
}
.preview-tv--portrait .preview-speaker {
  right: auto;
  left: 12px;
}
.preview-tv__bezel {
  position: absolute;
  inset: 0;
  background: #0a0a0a;
  border-radius: 18px;
  padding: 14px;
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.4), inset 0 2px 6px rgba(255, 255, 255, 0.08);
}
.preview-tv__screen {
  position: absolute;
  inset: 14px;
  background: #000;
  border-radius: 6px;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  color: rgba(255, 255, 255, 0.65);
  font-size: 14px;
}
.preview-tv__screen img,
.preview-tv__screen video {
  width: 100%;
  height: 100%;
  object-fit: contain;
}

.preview-radio {
  width: min(60vw, 640px);
  aspect-ratio: 2 / 1;
  background: #0a0a0a;
  border-radius: 24px;
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.4);
}
.preview-radio__waveform {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 4px;
  width: 72%;
  height: 55%;
}

.preview-radio__bar {
  flex: 1 1 4px;
  max-width: 6px;
  min-width: 3px;
  height: 100%;
  background: var(--blue);
  transform-origin: center;
  transform: scaleY(0.9);
  opacity: 0.85;
  border-radius: 2px;
}

.preview-radio--playing .preview-radio__bar {
  animation: preview-radio-wave var(--duration, 1000ms) ease-in-out infinite;
  animation-delay: var(--delay, 0ms);
}

@keyframes preview-radio-wave {
  0%, 100% { transform: scaleY(0.9); }
  25%      { transform: scaleY(0.25); }
  50%      { transform: scaleY(1); }
  75%      { transform: scaleY(0.45); }
}

@media (prefers-reduced-motion: reduce) {
  .preview-radio--playing .preview-radio__bar {
    animation: none;
  }
  .sidebar,
  .app.is-nav-open .sidebar,
  .nav-scrim {
    transition: none;
  }
}

.preview-speaker {
  position: absolute;
  right: 16px;
  bottom: 16px;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  border: none;
  background: rgba(255, 255, 255, 0.15);
  color: white;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background var(--transition);
  backdrop-filter: blur(8px);
  z-index: 2;
}
.preview-speaker:hover { background: rgba(255, 255, 255, 0.28); }
.preview-speaker--unmuted { background: var(--blue); }

.preview-caption {
  text-align: center;
  color: var(--text);
}
.preview-location-name {
  font-size: 18px;
  font-weight: 500;
}
.preview-location-address {
  font-size: 14px;
  color: #3a3a3f;
}

.preview-empty {
  color: rgba(255, 255, 255, 0.65);
  font-size: 14px;
}

.preview-campaigns-wrap {
  margin-top: 4px;
  text-align: center;
  max-width: 540px;
}
.preview-campaigns-title {
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: #3a3a3f;
  margin-bottom: 6px;
}
.preview-campaigns {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 6px 8px;
  justify-content: center;
}
.preview-campaign {
  font-size: 13px;
  padding: 4px 10px;
  border-radius: var(--radius-full);
  background: rgba(255, 255, 255, 0.5);
  color: #3a3a3f;
  border: 1px solid rgba(0, 0, 0, 0.08);
  transition: background var(--transition), color var(--transition), border-color var(--transition);
}
.preview-campaign--active {
  background: var(--blue);
  color: white;
  border-color: var(--blue);
  font-weight: 500;
}

/* ===== Scale preview (tabbed, per display mode) ===== */
.scale-preview-tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-bottom: 16px;
}
.scale-preview-tab {
  font-size: 14px;
  padding: 6px 14px;
  border-radius: var(--radius-full);
  background: rgba(0, 0, 0, 0.04);
  color: var(--text-secondary, #555);
  border: 1px solid rgba(0, 0, 0, 0.08);
  cursor: pointer;
  transition: background var(--transition), color var(--transition), border-color var(--transition);
}
.scale-preview-tab--active {
  background: var(--blue);
  color: white;
  border-color: var(--blue);
  font-weight: 500;
}
.scale-preview-stage {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  max-width: 520px;
  margin: 0 auto;
  aspect-ratio: 16 / 10;
  background: radial-gradient(ellipse at center, #1a1f2c 0%, #0a0d14 100%);
  border-radius: var(--radius-sm);
  overflow: hidden;
}
.scale-preview-stage img {
  max-width: 100%;
  max-height: 100%;
  width: auto;
  height: auto;
  object-fit: contain;
}
.scale-preview-empty {
  color: #6b7280;
  font-size: 14px;
  padding: 24px;
  text-align: center;
}
.scale-preview-dims {
  text-align: center;
  margin: 8px 0 0;
}
.scale-preview-caption {
  text-align: center;
  margin: 4px 0 0;
  font-size: 15px;
  font-weight: 500;
  color: var(--blue);
}

.preview-close {
  position: absolute;
  top: 16px;
  right: 16px;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(255, 255, 255, 0.75);
  color: #1d1d1f;
  text-decoration: none;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.15);
  backdrop-filter: blur(8px);
  transition: background var(--transition), transform var(--transition);
  z-index: 3;
}
.preview-close:hover {
  background: rgba(255, 255, 255, 0.95);
  transform: scale(1.05);
}
.preview-audio-placeholder,
.preview-unknown {
  color: rgba(255, 255, 255, 0.85);
  font-size: 14px;
  padding: 24px;
  text-align: center;
}

/* ----- Cashregister kiosk preview ---------------------------------------
 * Sister to .preview-tv. Renders a mini-kiosk: TV stage on the left,
 * themed receipt pane on the right, operator-driven state controls below.
 * The pane reuses the live cashregister CSS (.receipt-lines, .receipt-line,
 * .receipt-running-total, .receipt-summary*) so the visual treatment stays
 * locked to production. Theme variables (--theme-bg/-fg/-accent,
 * --theme-summary-bg/-fg) are set by cashregister_preview_controller on
 * the root element.
 */
.preview-cashregister {
  --theme-bg: #ffffff;
  --theme-fg: #1f1f1f;
  --theme-accent: #0a6cff;
  --theme-summary-bg: #0a6cff;
  --theme-summary-fg: #ffffff;
  position: relative;
  width: min(95vw, 1200px);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 16px;
}

.preview-cashregister__chassis {
  position: relative;
  width: 100%;
  aspect-ratio: 16 / 9;
  display: flex;
  background: #0a0a0a;
  border-radius: 18px;
  padding: 14px;
  box-shadow:
    0 20px 60px rgba(0, 0, 0, 0.4),
    inset 0 2px 6px rgba(255, 255, 255, 0.08);
  overflow: hidden;
}

.preview-cashregister__tv {
  position: relative;
  background: #000;
  border-radius: 6px;
  overflow: hidden;
  flex-basis: calc(100% - var(--receipt-basis, 50%));
  flex-grow: 0;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: flex-basis 400ms ease;
}
/* Margin between TV and receipt only when the receipt pane is visible —
   in FULLSCREEN the receipt collapses to 0% and a constant right-margin
   would leave a stripe of bezel showing. */
.preview-cashregister:not([data-mode="fullscreen"]) .preview-cashregister__tv {
  margin-right: 6px;
}
.preview-cashregister__tv .preview-tv__screen {
  position: absolute;
  inset: 0;
  background: #000;
  border-radius: 6px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: rgba(255, 255, 255, 0.65);
  font-size: 14px;
  overflow: hidden;
}
.preview-cashregister__tv .preview-tv__screen img,
.preview-cashregister__tv .preview-tv__screen video {
  width: 100%;
  height: 100%;
  object-fit: contain;
}

.preview-cashregister__receipt {
  position: relative;
  background: var(--theme-bg);
  color: var(--theme-fg);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  border-radius: 6px;
  flex-basis: var(--receipt-basis, 50%);
  flex-grow: 0;
  flex-shrink: 0;
  transition: flex-basis 400ms ease;
}

/* State control bar — three pill buttons below the chassis. */
.preview-state-controls {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  justify-content: center;
}
.preview-state-btn {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 8px 16px;
  border-radius: var(--radius-full);
  border: 1px solid rgba(255, 255, 255, 0.18);
  background: rgba(255, 255, 255, 0.08);
  color: rgba(255, 255, 255, 0.85);
  font-size: 14px;
  font-weight: 500;
  cursor: pointer;
  backdrop-filter: blur(8px);
  transition: background var(--transition), color var(--transition), border-color var(--transition), transform var(--transition);
}
.preview-state-btn:hover {
  background: rgba(255, 255, 255, 0.16);
  color: #fff;
}
.preview-state-btn[aria-pressed="true"] {
  background: var(--blue);
  border-color: var(--blue);
  color: #fff;
  box-shadow: 0 6px 18px -8px rgba(10, 108, 255, 0.6);
}
.preview-state-btn__dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: currentColor;
  opacity: 0.7;
}
.preview-state-btn[aria-pressed="true"] .preview-state-btn__dot {
  opacity: 1;
}

/* ===== Cashregister (Ekran z paragonem) ===== */
/*
 * Theme palette is written by receipt_controller as CSS variables on the
 * --theme-* root. Defaults below match ReceiptTheme.fetch("standard") so a
 * theme-less mount still renders sensibly.
 */
.cashregister {
  --theme-bg: #ffffff;
  --theme-fg: #1f1f1f;
  --theme-accent: #0a6cff;
  --theme-summary-bg: #0a6cff;
  --theme-summary-fg: #ffffff;
  display: flex;
  position: relative;
  width: 100vw;
  height: 100vh;
  background: #000;
  font-family: var(--font);
  cursor: none;
}
.cashregister__tv {
  position: relative;
  background: #000;
  /* --receipt-basis is owned by receipt_controller: set inline on the
     .cashregister root (boot value 0% = FULLSCREEN), and toggled by the
     state machine on every mode change. A [data-mode="fullscreen"] CSS
     rule here can't override the variable because inline styles on the
     same element win on specificity. */
  flex-basis: calc(100% - var(--receipt-basis, 50%));
  flex-grow: 0;
  flex-shrink: 0;
  transition: flex-basis 400ms ease;
}
.cashregister__receipt {
  position: relative;
  background: var(--theme-bg);
  color: var(--theme-fg);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  flex-basis: var(--receipt-basis, 50%);
  flex-grow: 0;
  flex-shrink: 0;
  transition: flex-basis 400ms ease;
}
.receipt-lines {
  list-style: none;
  margin: 0;
  padding: 24px;
  flex: 1;
  /* Stays scrollable so receipt_controller.renderLines can pin the latest
     line into view via scrollTop = scrollHeight; the scrollbar gutter is
     hidden below so the customer never sees it. */
  overflow-y: auto;
  scrollbar-width: none; /* Firefox + standard */
  font-size: 1.25rem;
}
.receipt-lines::-webkit-scrollbar { /* Chromium / Iron */
  width: 0;
  height: 0;
}
.receipt-line {
  display: grid;
  grid-template-columns: auto 1fr auto;
  gap: 12px;
  padding: 6px 0;
  border-bottom: 1px solid color-mix(in srgb, var(--theme-fg) 12%, transparent);
}
.receipt-line__qty   { font-variant-numeric: tabular-nums; opacity: 0.7; }
.receipt-line__name  { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.receipt-line__total { font-variant-numeric: tabular-nums; font-weight: 600; }

/* Promo signals — applied when the pos-agent matcher flags a line. */
.receipt-line[data-promo="matched"] .receipt-line__qty {
  /* Left-edge accent so the customer scans which lines are "in the promo"
     at a glance even when the inline badge gets text-overflow-clipped. */
  box-shadow: -3px 0 0 0 color-mix(in srgb, var(--theme-accent, #1f7a3a) 75%, transparent);
}
.receipt-line__badge {
  display: inline-block;
  margin-left: 8px;
  padding: 1px 8px;
  border-radius: 999px;
  background: color-mix(in srgb, var(--theme-accent, #1f7a3a) 18%, var(--theme-bg, #fff));
  color: color-mix(in srgb, var(--theme-accent, #1f7a3a) 90%, var(--theme-fg, #111));
  font-size: 0.72em;
  font-weight: 700;
  letter-spacing: 0.02em;
  vertical-align: 0.1em;
  font-variant-numeric: normal;
}

/* Computed-promo breakdown (Opust / Cena końcowa) — shown live for a promo
   the POS only applies at the summary screen (min-receipt). Renders as a
   full-width block under the qty/name/total row; the regular total above it
   is struck through to signal it's superseded by the computed final price. */
.receipt-line__total--struck {
  text-decoration: line-through;
  opacity: 0.55;
  font-weight: 500;
}
.receipt-line__promo {
  grid-column: 1 / -1;
  margin-top: 4px;
  padding-left: 12px;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.receipt-line__promo-row {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  font-size: 0.92em;
}
.receipt-line__promo-label { opacity: 0.85; }
.receipt-line__promo-amount { font-variant-numeric: tabular-nums; }
.receipt-line__promo-row--discount {
  color: color-mix(in srgb, var(--theme-accent, #1f7a3a) 80%, var(--theme-fg, #111));
}
.receipt-line__promo-row--final { font-weight: 700; }

/* Hint banner ("Dodaj 1 szt., aby aktywować…") shown above the lines
   list during RECEIPT mode. Controller toggles data-visible. */
.receipt-promo-banner {
  display: none;
  align-items: center;
  gap: 10px;
  margin: 8px 24px 4px;
  padding: 10px 16px;
  border-radius: 8px;
  background: color-mix(in srgb, var(--theme-accent, #1f7a3a) 14%, var(--theme-bg, #fff));
  color: color-mix(in srgb, var(--theme-fg, #111) 85%, var(--theme-accent, #1f7a3a));
  font-size: 1.05rem;
  font-weight: 500;
  line-height: 1.3;
}
.receipt-promo-banner[data-visible="true"] { display: flex; }
.receipt-promo-banner__icon { font-size: 1.2em; flex-shrink: 0; }
.receipt-promo-banner__text { flex: 1; }

/* Running savings — sits below the "Razem" amount. Smaller than the
   running total but visually paired with it (same right-edge alignment,
   same tabular numerics). Hidden when no savings accrued. */
.receipt-running-savings {
  flex-shrink: 0;
  padding: 6px 24px 12px;
  background: color-mix(in srgb, var(--theme-bg) 92%, var(--theme-fg) 8%);
  font-size: 1.05rem;
  font-variant-numeric: tabular-nums;
  grid-template-columns: 1fr auto auto;
  gap: 6px;
  display: none;
  color: color-mix(in srgb, var(--theme-accent, #1f7a3a) 85%, var(--theme-fg, #111));
}
.receipt-running-savings[data-visible="true"] { display: grid; }
.receipt-running-savings__label { text-align: left; opacity: 0.85; font-weight: 600; }
.receipt-running-savings__amount { text-align: right; font-weight: 700; }
.receipt-running-savings__currency { opacity: 0.7; }

.receipt-running-total {
  flex-shrink: 0;
  padding: 12px 24px;
  border-top: 1px solid color-mix(in srgb, var(--theme-fg) 18%, transparent);
  background: color-mix(in srgb, var(--theme-bg) 92%, var(--theme-fg) 8%);
  font-size: 1.5rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  grid-template-columns: 1fr auto;
  gap: 16px;
  display: none;
}
.receipt-running-total[data-visible="true"] { display: grid; }
.receipt-running-total__label  { text-align: left;  opacity: 0.7; }
.receipt-running-total__amount { text-align: right; font-weight: 700; }

/* ---- SUMMARY: receipt-artefact card -------------------------------------
 *
 * The summary moment is a "printed receipt" sitting on a theme-coloured
 * field. Two type families do the work: a serif display face for the
 * warmth-words ("Dziękujemy", "Zapraszamy ponownie") and a monospace face
 * for the numerics so amounts column on the baseline. No web fonts are
 * loaded — kiosks run offline — so both stacks fall back to fonts
 * shipped on the Windows kiosk image (Cambria/Constantia, Consolas).
 *
 * Entry is a single orchestrated landing: backdrop → card → thanks → label
 * → total → rows (staggered) → welcome. Welcome lands at ~900ms — comfortably
 * inside any realistic summary_duration_seconds. The model validation floor
 * is 0.3s but that's only set by tests; field default is 30s.
 *
 * Anchored on the `[data-visible="true"]` flip — the controller already
 * drives that. Keyframes deliberately stay on transform + opacity only
 * (no `filter:blur`, no `letter-spacing` tween) to keep the entry on the
 * compositor and avoid paint/layout cost on entry-level kiosk GPUs.
 */
.receipt-summary {
  position: absolute;
  inset: 0;
  background:
    radial-gradient(ellipse at 50% 40%, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0.28) 78%),
    var(--theme-summary-bg);
  color: var(--theme-summary-fg);
  display: none;
  align-items: center;
  justify-content: center;
  padding: 32px;
  z-index: 5;
}
.receipt-summary[data-visible="true"] {
  display: flex;
  animation: receipt-backdrop-in 200ms ease-out both;
}

.receipt-summary__card {
  /* Paper palette is intentionally hard-coded, not theme-derived: every
     real receipt is printed on warm off-white stock regardless of the
     shop's brand colour, and the theme-summary-bg is still visible as
     the frame around the card. */
  --paper:       #fffdf4;
  --paper-edge:  #f3eedd;
  --ink:         #1a1612;
  --ink-soft:    #6a6258;
  --rule:        rgba(26, 22, 18, 0.16);
  --rule-strong: rgba(26, 22, 18, 0.42);

  --serif: "Cormorant Garamond", "Cormorant", "Hoefler Text", "Iowan Old Style",
           "Palatino Linotype", "Book Antiqua", Cambria, Constantia, Georgia, serif;
  --mono:  "JetBrains Mono", "IBM Plex Mono", "SF Mono", Menlo, Consolas,
           "DejaVu Sans Mono", "Courier New", monospace;

  width: min(560px, 92%);
  padding: 56px 56px 44px;
  border-radius: 10px;
  background-color: var(--paper);
  /* Faint paper grain — two offset dot patterns. Cheap and ships nowhere
     near the kiosk's GPU budget. */
  background-image:
    radial-gradient(rgba(26, 22, 18, 0.045) 1px, transparent 1.4px),
    radial-gradient(rgba(26, 22, 18, 0.025) 1px, transparent 1.4px),
    linear-gradient(180deg, var(--paper) 0%, var(--paper-edge) 100%);
  background-size: 7px 7px, 13px 13px, 100% 100%;
  background-position: 0 0, 3px 5px, 0 0;
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.85) inset,
    0 0 0 1px rgba(26, 22, 18, 0.05),
    0 28px 70px -22px rgba(0, 0, 0, 0.55),
    0 10px 28px -14px rgba(0, 0, 0, 0.45);

  color: var(--ink);
  font-family: var(--serif);
  display: flex;
  flex-direction: column;
  gap: 28px;
  text-align: center;
  position: relative;

  animation: receipt-card-in 380ms cubic-bezier(0.16, 0.84, 0.32, 1) 60ms both;
}

.receipt-summary__thanks {
  font-family: var(--serif);
  font-style: italic;
  font-weight: 500;
  font-size: clamp(2.6rem, 5.2vw, 3.6rem);
  line-height: 1;
  letter-spacing: -0.01em;
  color: var(--ink);
  animation: receipt-thanks-in 280ms cubic-bezier(0.2, 0.7, 0.3, 1) 200ms both;
}

.receipt-summary__total-block {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
}

/* Small-caps label flanked by rules — "— RAZEM —" editorial framing. */
.receipt-summary__label {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 14px;
  font-family: var(--serif);
  font-variant: small-caps;
  font-weight: 600;
  letter-spacing: 0.18em;
  font-size: 0.95rem;
  color: var(--ink-soft);
  text-transform: lowercase;
  animation: receipt-thanks-in 240ms ease-out 320ms both;
}
.receipt-summary__label::before,
.receipt-summary__label::after {
  content: "";
  flex: 0 0 auto;
  width: 56px;
  height: 0;
  border-top: 1px solid var(--rule-strong);
}

.receipt-summary__total {
  font-family: var(--mono);
  font-weight: 600;
  font-size: clamp(3.4rem, 7.6vw, 5rem);
  line-height: 1;
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
  color: var(--ink);
  display: inline-flex;
  align-items: baseline;
  justify-content: center;
  gap: 0.18em;
  animation: receipt-total-in 360ms cubic-bezier(0.16, 0.84, 0.32, 1) 400ms both;
}

/* Big "Oszczędziłeś X zł" highlight shown on the summary card between
   the totals rows and the goodbye line. Same monospace numeric stack
   as the total so amounts align visually, but smaller and tinted
   with the theme's accent so it reads as a feel-good moment rather
   than another row of bookkeeping. Hidden when no savings accrued —
   non-promo carts look exactly as they did before the matcher. */
.receipt-summary__savings {
  display: none;
  margin: 22px auto 0;
  padding: 14px 20px;
  border-radius: 12px;
  background: color-mix(in srgb, var(--theme-accent, #1f7a3a) 16%, var(--theme-bg, #fff));
  color: color-mix(in srgb, var(--theme-accent, #1f7a3a) 90%, var(--ink, #111));
  text-align: center;
  font-family: var(--mono);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  font-size: clamp(1.6rem, 3.2vw, 2.4rem);
  line-height: 1.1;
}
.receipt-summary__savings[data-visible="true"] { display: block; }
.receipt-summary__savings-label {
  display: block;
  font-family: var(--serif, serif);
  font-style: italic;
  font-weight: 500;
  font-size: 0.62em;
  letter-spacing: 0.02em;
  margin-bottom: 4px;
  opacity: 0.85;
}
.receipt-summary__savings-amount { font-weight: 700; }
.receipt-summary__savings-currency {
  font-family: var(--serif, serif);
  font-style: italic;
  font-weight: 500;
  font-size: 0.5em;
  margin-left: 0.18em;
  opacity: 0.75;
  transform: translateY(-0.4em);
  display: inline-block;
}
.receipt-summary__currency {
  font-family: var(--serif);
  font-style: italic;
  font-weight: 500;
  font-size: 0.36em;
  color: var(--ink-soft);
  letter-spacing: 0;
  transform: translateY(-0.55em);
}

.receipt-summary__rows {
  margin: 0;
  padding: 26px 0 0;
  border-top: 1.5px dashed var(--rule-strong);
  display: flex;
  flex-direction: column;
  gap: 14px;
  text-align: left;
}

/* Three-column grid: label · leader · value. The middle column is the
   only flex column (1fr); the leader pseudo-element lives there with a
   dotted border-bottom, so dots appear only in the gap between label
   and value by construction — no background-masking, no rectangles
   showing through on textured surfaces. */
.receipt-summary__row {
  display: grid;
  grid-template-columns: max-content 1fr max-content;
  align-items: baseline;
  font-size: 1.25rem;
  /* Per-row stagger driven by source order — payment-type row may be
     hidden at runtime; nth-child still lays the rhythm down because we
     count from the DOM, not the layout. */
  animation: receipt-row-in 240ms cubic-bezier(0.2, 0.7, 0.3, 1) both;
}
.receipt-summary__row:nth-child(1) { animation-delay: 540ms; }
.receipt-summary__row:nth-child(2) { animation-delay: 600ms; }
.receipt-summary__row:nth-child(3) { animation-delay: 660ms; }
.receipt-summary__row:nth-child(4) { animation-delay: 720ms; }

.receipt-summary__row::after {
  content: "";
  grid-column: 2;
  height: 2px;
  margin: 0 12px;
  /* radial-gradient produces a more visible dot pattern than
     border-bottom: dotted does at hairline thicknesses — Chromium packs
     border-dots tightly at 1.5px and the leader reads as a solid rule.
     This tiles dots at 8px intervals, matching the receipt-printer
     aesthetic we had before the rectangles issue. */
  background-image: radial-gradient(var(--rule-strong) 1px, transparent 1.4px);
  background-size: 8px 2px;
  background-repeat: repeat-x;
  align-self: center;
  transform: translateY(0.18em);
}

.receipt-summary__row dt {
  grid-column: 1;
  margin: 0;
  font-family: var(--serif);
  font-variant: small-caps;
  font-weight: 600;
  letter-spacing: 0.14em;
  font-size: 0.95rem;
  color: var(--ink-soft);
  white-space: nowrap;
}
.receipt-summary__row dd {
  grid-column: 3;
  margin: 0;
  font-family: var(--mono);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  font-size: 1.25rem;
  color: var(--ink);
}

.receipt-summary__welcome {
  padding-top: 22px;
  border-top: 1.5px dashed var(--rule-strong);
  font-family: var(--serif);
  font-style: italic;
  font-weight: 500;
  font-size: 1.5rem;
  color: var(--ink-soft);
  animation: receipt-welcome-in 260ms ease-out 820ms both;
}

@keyframes receipt-backdrop-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}
@keyframes receipt-card-in {
  from { opacity: 0; transform: translateY(28px) scale(0.97); }
  to   { opacity: 1; transform: translateY(0)    scale(1);    }
}
@keyframes receipt-thanks-in {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: translateY(0);   }
}
@keyframes receipt-total-in {
  from { opacity: 0; transform: scale(0.9); }
  to   { opacity: 1; transform: scale(1);   }
}
@keyframes receipt-row-in {
  from { opacity: 0; transform: translateX(-10px); }
  to   { opacity: 1; transform: translateX(0);     }
}
@keyframes receipt-welcome-in {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: translateY(0);   }
}

.pos-source-status {
  position: absolute;
  bottom: 12px;
  right: 12px;
  z-index: 4;
  font-size: 0.75rem;
  background: rgba(0, 0, 0, 0.55);
  color: #fff;
  padding: 4px 8px;
  border-radius: 4px;
  pointer-events: none;
  opacity: 0.7;
  transition: opacity 0.4s ease-out;
}
.pos-source-status[data-visible="false"] { opacity: 0; }
.pos-source-status[data-level="error"] { background: rgba(180, 30, 30, 0.85); opacity: 0.95; }
.pos-source-status[data-level="warn"]  { background: rgba(180, 130, 30, 0.85); opacity: 0.9; }
.pos-source-status[data-level="error"][data-visible="false"],
.pos-source-status[data-level="warn"][data-visible="false"] { opacity: 0; }

/* Themes — just decorations / filters; palette already lives in CSS vars. */
.cashregister.theme-mourning_grey,
.theme-mourning_grey { filter: grayscale(0.95); }

/* ============================================================
   Quiet Studio additions: dashboard hero, fleet panel, pills,
   monospace numeric helpers.
   ============================================================ */

/* Tabular numerics anywhere `.num` is applied. */
.num,
.stat-card__value {
  font-family: var(--font-mono);
  font-feature-settings: 'tnum';
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.01em;
}

/* ---- Dashboard hero ---- */
.page-hero {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 24px;
  margin-bottom: 32px;
}

.page-hero__main { min-width: 0; }

.page-hero__eyebrow {
  font-size: 12.5px;
  font-weight: 500;
  color: var(--text-secondary);
  text-transform: uppercase;
  letter-spacing: 0.08em;
}

.page-hero__title {
  margin: 8px 0 6px;
  font-size: 36px;
  font-weight: 300;        /* matches the brand wordmark's light weight */
  letter-spacing: -0.02em;
  line-height: 1.05;
  color: var(--text);
}
.page-hero__icon {
  color: var(--brand-red);
  vertical-align: -3px;
  margin-right: 10px;
}
.page-hero__title em {
  /* "24" in the brand logo is a colour change, not italic. We mirror
     that treatment for the user's name in the greeting. */
  font-style: normal;
  font-weight: 400;
  color: var(--brand-red);
}

.page-hero__sub {
  color: var(--text-secondary);
  font-size: 14px;
}

/* ---- Dashboard sections ---- */
.dash-section {
  margin-top: 40px;
}
.dash-section__title {
  font-size: 16px;
  font-weight: 600;
  letter-spacing: -0.005em;
  margin: 0 0 14px;
  color: var(--text);
}

/* Cover thumbnail of the location's uploaded photo on the show page. */
.location-photo {
  width: 100%;
  max-width: 480px;
  height: 200px;
  object-fit: cover;
  border-radius: 8px;
  margin-bottom: 16px;
}

/* Read-only key/value list, used on the location show page. */
.detail-list {
  margin: 0;
}
.detail-list__row {
  display: grid;
  grid-template-columns: 180px 1fr;
  gap: 16px;
  padding: 10px 0;
  border-bottom: 1px solid var(--border);
}
.detail-list__row:last-child {
  border-bottom: none;
}
.detail-list__row dt {
  font-size: 13px;
  font-weight: 500;
  color: var(--text-secondary);
}
.detail-list__row dd {
  margin: 0;
  font-size: 14px;
  color: var(--text);
}
@media (max-width: 640px) {
  .detail-list__row {
    grid-template-columns: 1fr;
    gap: 4px;
  }
}

/* Activity log: "Show older / Newest" keyset-pagination control under the table. */
.load-more {
  display: flex;
  justify-content: center;
  padding: 16px 0 4px;
}

/* Activity log: full field-level diff on the activity show page —
   field | before | after. Stacks to one column on a phone. */
.change-grid {
  margin-top: 16px;
  background: var(--white);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
}
.change-grid__row {
  display: grid;
  grid-template-columns: 200px 1fr 1fr;
  gap: 16px;
  padding: 10px 14px;
  border-bottom: 1px solid var(--border);
  align-items: baseline;
  font-size: 14px;
}
.change-grid__row:last-child {
  border-bottom: none;
}
.change-grid__row--head {
  background: var(--gray-50);
  font-size: 13px;
  font-weight: 500;
  color: var(--text-secondary);
}
.change-grid__field {
  font-weight: 500;
  color: var(--text-secondary);
}
.change-grid__old {
  color: var(--text-secondary);
  text-decoration: line-through;
  overflow-wrap: anywhere;
}
.change-grid__new {
  color: var(--text);
  overflow-wrap: anywhere;
}
@media (max-width: 640px) {
  .change-grid__row {
    grid-template-columns: 1fr;
    gap: 4px;
  }
  .change-grid__row--head {
    display: none;
  }
  .change-grid__old {
    text-decoration: none;
  }
  .change-grid__old::before {
    content: "− ";
  }
  .change-grid__new::before {
    content: "+ ";
  }
}

/* Plain stacked list of records (e.g. the campaigns assigned to a location on
   the show page). Each row separated by a hairline, last row borderless. */
.record-list {
  list-style: none;
  margin: 0;
  padding: 0;
}
.record-list__item {
  padding: 6px 0;
  border-bottom: 1px solid var(--border);
}
.record-list__item:last-child {
  border-bottom: none;
}
/* Empty-state line shown in place of the list when there are no records. */
.record-list__empty {
  margin: 0;
  font-size: 13px;
  color: var(--text-secondary);
}

/* Sub-heading above each fleet-version table on /locations management.
   Smaller than .dash-section__title so it sits as a third-level header
   inside a section grid cell. */
.fleet-table__title {
  font-size: 13px;
  font-weight: 600;
  color: var(--text);
  margin: 0 0 10px;
  letter-spacing: -0.005em;
}

/* Optional right-side "Otwórz urządzenia →" link next to a section title. */
.dash-section__header {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 14px;
}
.dash-section__header .dash-section__title {
  margin: 0;
}

.dash-section__link {
  font-size: 13px;
  font-weight: 500;
  color: var(--brand-red);
  text-decoration: none;
  white-space: nowrap;
  transition: opacity var(--transition);
}
.dash-section__link:hover {
  opacity: 0.7;
}

.dash-stats {
  /* tighter than .grid--3 default minmax — three even columns */
  grid-template-columns: repeat(3, 1fr);
}
@media (max-width: 880px) {
  .dash-stats { grid-template-columns: 1fr; }
}

/* ---- Campaigns stat cards (new chip-first layout) ----
   Replaces the icon-first .stat-card design for the three campaign tiles
   on the dashboard. Locations status block still uses .stat-card. */
.stat-row {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 14px;
}
@media (max-width: 880px) {
  .stat-row { grid-template-columns: 1fr; }
}

.stat {
  position: relative;
  overflow: hidden;
  display: block;
  padding: 20px 22px 18px;
  background: var(--white);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  color: inherit;
  text-decoration: none;
  transition: border-color var(--transition), transform var(--transition), box-shadow var(--transition);
}
.stat:hover {
  border-color: var(--gray-300);
  transform: translateY(-1px);
  box-shadow: var(--shadow-md);
  opacity: 1;
}

.stat__row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin-bottom: 14px;
}

.stat__label {
  font-size: 13px;
  font-weight: 500;
  color: var(--text);
  letter-spacing: -0.005em;
}

.stat__chip {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 2px 8px;
  border-radius: var(--radius-full);
  font-size: 11px;
  font-weight: 500;
  white-space: nowrap;
}
.stat__chip .dot {
  width: 5px;
  height: 5px;
  border-radius: 50%;
}

.stat--ok   .stat__chip { background: var(--green-soft); color: var(--green); }
.stat--ok   .stat__chip .dot {
  background: var(--green);
  box-shadow: 0 0 0 3px rgba(46, 132, 86, 0.18);
  animation: stat-pulse 2.4s ease-out infinite;
}
.stat--info .stat__chip { background: #E6ECF6; color: #2A5DB0; }
.stat--info .stat__chip .dot { background: #2A5DB0; }
.stat--warn .stat__chip { background: #F6EEDA; color: #CA8A04; }
.stat--warn .stat__chip .dot { background: #CA8A04; }
.stat--bad  .stat__chip { background: var(--brand-red-soft); color: var(--brand-red); }
.stat--bad  .stat__chip .dot { background: var(--brand-red); }

@keyframes stat-pulse {
  0%   { box-shadow: 0 0 0 0 rgba(46, 132, 86, 0.35); }
  70%  { box-shadow: 0 0 0 7px rgba(46, 132, 86, 0); }
  100% { box-shadow: 0 0 0 0 rgba(46, 132, 86, 0); }
}

.stat__value {
  font-family: var(--font-mono);
  font-feature-settings: 'tnum';
  font-variant-numeric: tabular-nums;
  font-size: 44px;
  font-weight: 500;
  line-height: 1;
  letter-spacing: -0.04em;
  color: var(--text);
}

.stat__delta {
  margin-top: 8px;
  font-size: 12.5px;
  color: var(--text-secondary);
  line-height: 1.45;
}
.stat__delta strong { color: var(--text); font-weight: 600; }

/* ---- Sieć urządzeń panel ---- */
.fleet-panel {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  background: var(--white);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
}
/* The device-fleet panel carries one card per device kind (5: players, totems,
   radios, cashregisters, scales). The modules panel reuses .fleet-panel but has
   its own card count, so the wider grid is scoped to the fleet variant only. */
.fleet-panel--devices { grid-template-columns: repeat(5, 1fr); }
@media (max-width: 1180px) {
  .fleet-panel { grid-template-columns: 1fr 1fr; }
  .fleet-panel--devices { grid-template-columns: repeat(3, 1fr); }
}
@media (max-width: 640px) {
  .fleet-panel,
  .fleet-panel--devices { grid-template-columns: 1fr; }
}

.fleet-cell {
  padding: 20px 22px;
  display: flex;
  flex-direction: column;
  gap: 12px;
  border-right: 1px solid var(--border);
}
.fleet-cell:last-child { border-right: none; }
@media (max-width: 880px) {
  .fleet-cell { border-right: none; border-bottom: 1px solid var(--border); }
  .fleet-cell:last-child { border-bottom: none; }
}

.fleet-cell__head {
  display: flex;
  align-items: center;
  gap: 10px;
  /* Reserve two lines so the bar below aligns across cells whether the
     kind name wraps (e.g. "Odtwarzacze TV") or fits on one line. */
  min-height: 39px;
}
.fleet-cell__icon {
  width: 30px;
  height: 30px;
  border-radius: 8px;
  display: grid;
  place-items: center;
  background: var(--gray-100);
  color: var(--text-secondary);
  flex-shrink: 0;
}
/* Harmonious per-kind tints — no rainbow. The activity-log chip (.type-chip)
   reuses the same per-kind colour as the icon square via the shared
   .fleet-cell--<kind> ancestor on the cell, so each tint pair lives in ONE place. */
.fleet-cell--player .fleet-cell__icon,
.fleet-cell--player .type-chip          { background: #ECF1EE; color: #2B6757; }
.fleet-cell--totem .fleet-cell__icon,
.fleet-cell--totem .type-chip           { background: #EDECF6; color: #4B3F8F; }
.fleet-cell--radio .fleet-cell__icon,
.fleet-cell--radio .type-chip           { background: #EEEAE0; color: #7A5C1F; }
.fleet-cell--receipt_screen .fleet-cell__icon,
.fleet-cell--receipt_screen .type-chip  { background: #E9EEF6; color: #2A5DB0; }
.fleet-cell--scale .fleet-cell__icon,
.fleet-cell--scale .type-chip           { background: #E4EFF1; color: #216C79; }
.fleet-cell--module .fleet-cell__icon   { background: #E6F2EF; color: #1F7A5C; }
.fleet-cell--pact24_server .fleet-cell__icon,
.fleet-cell--pact24_server .type-chip   { background: #EAEDF1; color: #475569; }

/* Activity log "Obiekt" cell: a type-tinted icon square + headline + a small
   type chip. Reuses .fleet-cell__icon and the .fleet-cell--<kind> tints above. */
.activity-resource {
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
}
.activity-resource__text {
  display: flex;
  flex-direction: column;
  gap: 3px;
  min-width: 0;
}
.activity-resource__text .row-title {
  max-width: 100%;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.type-chip {
  align-self: flex-start;
  display: inline-block;
  max-width: 100%;
  font-size: 11px;
  font-weight: 500;
  line-height: 1.35;
  padding: 1px 8px;
  border-radius: var(--radius-full);
  background: var(--gray-200);
  color: var(--text-secondary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.fleet-cell__name {
  font-size: 13.5px;
  font-weight: 600;
  letter-spacing: -0.005em;
  line-height: 1.3;
}
.fleet-cell__count {
  margin-left: auto;
  font-size: 12px;
  color: var(--text-secondary);
}

.fleet-cell__bar {
  height: 6px;
  border-radius: var(--radius-full);
  background: var(--gray-200);
  overflow: hidden;
  display: flex;
}
.fleet-cell__bar-fill {
  height: 100%;
  transition: width 800ms cubic-bezier(0.2, 0.7, 0.2, 1);
}
.fleet-cell__bar-fill--on  { background: var(--green); }
.fleet-cell__bar-fill--off { background: var(--red); }

.fleet-cell__legend {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 16px;
  font-size: 12px;
  color: var(--text-secondary);
}
.fleet-cell__legend .num { color: var(--text); font-weight: 500; }
.fleet-cell__legend-item {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  display: inline-block;
}
.dot--on  { background: var(--green); }
.dot--off { background: var(--red); }
.dot--muted { background: var(--gray-300); }

/* ---- Wsparcie Kasjera (Cashier Support) dashboard module card ---- */
/* The modules panel carries two cards (Promotions + Cashier Support); its own
   2-col grid mirrors .fleet-panel--devices' scoped column count. */
.fleet-panel--modules { grid-template-columns: repeat(2, minmax(0, 1fr)); }
@media (max-width: 640px) { .fleet-panel--modules { grid-template-columns: 1fr; } }

/* position: relative anchors the flow connector to this cell's left border;
   the harmonious muted-gold tint is its own identity next to Promotions' green. */
.fleet-cell--cashier_support { position: relative; }
.fleet-cell--cashier_support .fleet-cell__icon { position: relative; background: #F1EADB; color: #7A5C1F; }

/* Module-scope chips: this module covers Promotions + Loyalty. */
.ws-scope { display: flex; align-items: center; gap: 7px; margin-top: 2px; }
.ws-tag {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: 11px;
  font-weight: 500;
  color: #7A5C1F;
  background: #F4EEE0;
  border: 1px solid rgba(122, 92, 31, 0.16);
  padding: 3px 9px 3px 7px;
  border-radius: var(--radius-full);
}
.ws-tag svg { width: 11px; height: 11px; }
.ws-scope__plus { color: #7A5C1F; font-weight: 600; font-size: 12px; }

/* Flow connector capsule on the card's left border (promo data → overlay). */
.flow-link { position: absolute; top: 65px; left: 0; transform: translate(-50%, -50%); z-index: 3; pointer-events: none; }
.flow-link__cap {
  display: flex;
  align-items: center;
  gap: 4px;
  background: var(--white);
  border: 1px solid var(--border);
  border-radius: var(--radius-full);
  padding: 4px 7px;
  box-shadow: 0 4px 14px -6px rgba(35, 31, 32, 0.22);
}
.flow-link__rail { position: relative; width: 22px; height: 8px; }
.flow-link__rail svg { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; }
.flow-link__lane { stroke: var(--gray-200); stroke-width: 2; fill: none; }
.flow-link__lane--cut { stroke: #E0C3C0; }
.flow-link__flow {
  stroke: url(#cs-flowgrad);
  stroke-width: 2;
  fill: none;
  stroke-dasharray: 4 6;
  stroke-linecap: round;
  animation: flow-dash 1s linear infinite;
}
.flow-link__pk { fill: #7A5C1F; }
.flow-link__arrow { color: #7A5C1F; display: flex; }
.flow-link--broken .flow-link__cap { background: #FBF4F3; border-color: #F0D7D4; }
.flow-link--broken .flow-link__x { color: var(--brand-red); display: flex; }
@keyframes flow-dash { to { stroke-dashoffset: -20; } }
@media (max-width: 880px) { .flow-link { display: none; } }

/* Locked (not provisioned) upsell state. */
.fleet-cell--locked {
  background: repeating-linear-gradient(135deg, transparent, transparent 9px, rgba(35, 31, 32, 0.018) 9px, rgba(35, 31, 32, 0.018) 10px);
}
.fleet-cell--locked .lockwrap { display: flex; flex-direction: column; gap: 12px; filter: grayscale(1); opacity: 0.42; }
.fleet-cell--locked .fleet-cell__icon { background: var(--gray-100); color: var(--text-secondary); }
.lock-badge {
  position: absolute;
  right: -4px;
  bottom: -4px;
  width: 15px;
  height: 15px;
  border-radius: 50%;
  background: var(--text);
  color: var(--white);
  display: grid;
  place-items: center;
  box-shadow: 0 0 0 2px var(--white);
}
.locked-cta {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 2px;
  padding: 11px 13px;
  background: var(--white);
  border: 1px dashed #E7B9B6;
  border-radius: var(--radius-sm);
}
.locked-cta__txt { font-size: 12px; color: var(--text-secondary); line-height: 1.4; }
.locked-cta__txt b { color: var(--text); font-weight: 600; }
.locked-cta__btn {
  margin-left: auto;
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  font-weight: 600;
  color: var(--white);
  background: var(--brand-red);
  padding: 7px 13px;
  border-radius: var(--radius-full);
  text-decoration: none;
  box-shadow: 0 6px 16px -8px rgba(237, 28, 36, 0.6);
}
.locked-cta__btn:hover { background: var(--brand-red-dark); }

/* ---- Status pill variants (semantic aliases over the base .pill) ---- */
.pill--ok   { background: var(--green-soft); color: var(--green); }
.pill--ok .dot   { background: var(--green); }
.pill--info { background: #E6ECF6; color: #2A5DB0; }
.pill--info .dot { background: #2A5DB0; }
.pill--warn { background: #F6EEDA; color: #CA8A04; }
.pill--warn .dot { background: #CA8A04; }
.pill--bad  { background: #F6E4E1; color: #A8362E; }
.pill--bad .dot  { background: #A8362E; }
.pill--mute { background: var(--gray-200); color: var(--text-secondary); }
.pill--mute .dot { background: var(--text-secondary); }

/* ===== Campaign report media table — thumbnails =====
   Used by app/views/campaigns/report.html.erb (.report-media__preview-col
   on the first th/td) and by app/helpers/campaigns_helper.rb's
   medium_report_thumbnail helper. The dash fallback reuses
   .media-placeholder + .media-placeholder--sm for visual consistency
   with the rest of the app. */
.report-media__preview-col {
  width: 72px;
  padding-right: 8px;
}
.report-media__thumb {
  width: 56px;
  height: 56px;
  object-fit: cover;
  border-radius: 4px;
  display: block;
  background: var(--gray-100);
}


/* ============================================================
   KASA — redesigned customer receipt screen (design-lab preview)
   Reachable at /devices/:identifier/receipt_design. Fully namespaced
   under `.kasa` so it never collides with the live `.cashregister`
   layout or other app styles. Themed entirely via CSS variables that
   kasa_controller.js writes from the device's ReceiptTheme tokens.
   ============================================================ */
.kasa {
  /* font stacks: kiosks fall back to installed fonts; the lab loads
     web fonts (Fraunces / Bricolage Grotesque / Spline Sans Mono). */
  --k-display:"Fraunces", Cambria, Georgia, serif;
  --k-ui:"Bricolage Grotesque", system-ui, sans-serif;
  --k-mono:"Spline Sans Mono","JetBrains Mono", Consolas, monospace;
  --k-ease:cubic-bezier(0.16,0.84,0.32,1);
  /* token fallbacks (Lewiatan) — JS overrides per theme */
  --brand:#1f62b0; --brand-deep:#0e306c; --brand-bright:#2e7bd6; --brand-glow:#7fb2ee;
  --accent:#ffd200; --accent-light:#ffec4d; --accent-deep:#d6a400;
  --panel-a:#1f62b0; --panel-b:#123a82; --panel-c:#0e2a60; --panel-d:#08193c;
  --panel-glow:rgba(46,123,214,0.26);
  --ink:#14213d; --ink-soft:#5b6b86; --ink-faint:#9aa8be;
  --paper:#fbfbf6; --paper-warm:#eef2f8; --paper-edge:#e1e8f2; --card:#ffffff;
  --rule:rgba(20,33,61,0.10); --rule-strong:rgba(20,33,61,0.26);
  --brick:#d6402b; --coin-ink:#6b5400;
  /* warm "what you're losing" amber for the karta layout's regret window */
  --loss:#ff8a5b; --loss-deep:#e0542a;

  position:relative; display:flex; width:100%; height:100%;
  overflow:hidden; font-family:var(--k-ui);
  -webkit-font-smoothing:antialiased; text-rendering:optimizeLegibility;
}

/* ---- stage (left: media + communication) ---- */
.kasa-stage {
  position:relative; flex:1 1 auto; min-width:0;
  display:flex; flex-direction:column;
  background:
    radial-gradient(120% 90% at 18% 12%, var(--panel-a) 0%, transparent 55%),
    radial-gradient(130% 100% at 86% 92%, var(--panel-b) 0%, transparent 60%),
    linear-gradient(160deg, var(--panel-c) 0%, var(--panel-d) 100%);
  overflow:hidden; transition:flex-basis 480ms var(--k-ease);
}
.kasa-stage::before { content:""; position:absolute; inset:-20%;
  background-image:radial-gradient(rgba(255,255,255,0.05) 1px, transparent 1.4px);
  background-size:26px 26px; animation:kasa-drift 60s linear infinite; pointer-events:none; }
@keyframes kasa-drift { to { transform:translate(26px,26px);} }
/* The idle stage is intentionally brand-free — fullscreen shows ONLY the
   campaign image/video (no overlaid badge). */

.kasa-mediaframe { flex:1; display:grid; place-items:center; padding:0; min-height:0; transition:padding 480ms var(--k-ease); }
.kasa-media { position:relative; overflow:hidden; width:100%; height:100%; border-radius:0; box-shadow:none;
  transition:border-radius 480ms var(--k-ease), box-shadow 480ms var(--k-ease); }
.kasa-media__art { position:absolute; inset:0;
  background:
    radial-gradient(58% 78% at 72% 22%, var(--accent-light) 0%, transparent 58%),
    radial-gradient(80% 95% at 22% 88%, var(--brand-bright) 0%, transparent 62%),
    linear-gradient(135deg, var(--brand) 0%, var(--brand-deep) 100%);
  animation:kasa-kenburns 18s ease-in-out infinite alternate; }
@keyframes kasa-kenburns { from { transform:scale(1) translate(0,0);} to { transform:scale(1.12) translate(-2%,1%);} }
/* Live kiosk only: the kasa scene is a direct child of <body> in the
   cashregister layout, whereas the admin lab nests it inside .kasa-lab. So
   `body > .kasa` targets the kiosk alone — hide the cursor there (matches the
   legacy .cashregister) without hiding it in the operator preview. */
body > .kasa { cursor:none; }
/* Live kiosk only: stop the two full-stage infinite animations. The ken-burns
   __art layer sits behind opaque campaign media (never seen) and the drifting
   grain is imperceptible — but both keep the compositor busy 24/7 on weak kiosk
   GPUs. The small loyalty/pay flourishes stay; the admin lab keeps full motion. */
body > .kasa .kasa-media__art { animation:none; }
body > .kasa .kasa-stage::before { animation:none; }
/* Live kiosk only: the real campaign media (player_controller targets) fills
   .kasa-media on top of the animated __art backdrop. `contain` letterboxes
   onto the gradient so portrait/odd-ratio media still looks intentional. The
   lab keeps its static __art/__copy/__tag ad and renders none of these. */
.kasa-media__el { position:absolute; inset:0; width:100%; height:100%; object-fit:contain; z-index:1; }
/* No `display:flex` here: player_controller toggles inline display:block/none on
   this target, which would win over a flex rule. Centre via absolute positioning
   instead so it holds whatever display the controller sets. */
.kasa-media__nocontent { position:absolute; left:0; right:0; top:50%; transform:translateY(-50%); z-index:2; text-align:center;
  color:rgba(255,255,255,0.82); font-family:var(--k-ui); font-size:1.4rem; letter-spacing:0.02em; }
.kasa-media__offline { position:absolute; top:14px; right:14px; z-index:3; width:12px; height:12px; border-radius:50%;
  background:#ef4444; box-shadow:0 0 0 5px rgba(239,68,68,0.18); }
/* Lab-only demo photo filling the media frame (cover) behind the ad copy/tag.
   The live kiosk renders player img/video (.kasa-media__el) here instead. */
.kasa-media__photo { position:absolute; inset:0; width:100%; height:100%; object-fit:cover; z-index:0; }
.kasa-media__copy { position:absolute; left:0; right:0; bottom:0; padding:46px; color:#fff; text-align:left; z-index:2; }
/* Scrim under the headline so white copy stays legible over the photo. */
.kasa-media__copy::before { content:""; position:absolute; inset:-60px 0 0 0; z-index:-1;
  background:linear-gradient(to top, rgba(6,14,28,0.88) 8%, rgba(6,14,28,0.45) 50%, transparent); }
.kasa-media__copy .kicker { text-transform:uppercase; letter-spacing:0.32em; font-size:13px; opacity:0.8; margin-bottom:12px; }
.kasa-media__copy h2 { font-family:var(--k-display); font-weight:300; font-size:clamp(34px,4vw,62px); line-height:0.98; letter-spacing:-0.02em; }
.kasa-media__copy h2 em { font-style:italic; font-weight:500; color:var(--accent-light); }
.kasa-media__tag { position:absolute; top:26px; right:26px; font-family:var(--k-display); font-weight:700; font-size:30px; color:#14213d;
  background:var(--accent-light); padding:8px 16px; border-radius:14px; transform:rotate(4deg); box-shadow:0 10px 24px -8px rgba(0,0,0,0.5); }

.kasa-comm { flex-shrink:0; max-height:0; opacity:0; overflow:hidden;
  transition:max-height 480ms var(--k-ease), opacity 360ms var(--k-ease), padding 480ms var(--k-ease); }
.kasa-comm--top, .kasa-comm--bottom { padding:0 34px; }
/* Promo zone holds a STACK of promo cards (one per active promotion action).
   Scrolls if a basket triggers more than fit; on a kiosk the realistic count
   (a few) fits and the media frame above flexes smaller to make room. The cap
   is the viewport-relative 54vh (matching the serving .kasa-comm--bottom max),
   NOT max-height:100% — a percentage max-height doesn't resolve against the
   content-driven (indefinite-height) comm parent, so the scroll would never
   bound and overflowing cards would clip silently. */
.kasa-promos { display:flex; flex-direction:column; gap:10px; max-height:54vh; overflow-y:auto; scrollbar-width:none; }
.kasa-promos::-webkit-scrollbar { width:0; height:0; }

.kasa-loyalty { display:flex; align-items:center; gap:20px; padding:18px 22px; border-radius:20px;
  background:linear-gradient(180deg, rgba(255,255,255,0.10), rgba(255,255,255,0.04)); border:1px solid rgba(255,255,255,0.14); color:#eaf6ee; }
.kasa-loyalty__card { position:relative; width:96px; height:62px; flex-shrink:0; border-radius:11px; overflow:hidden;
  background:linear-gradient(135deg, var(--accent) 0%, var(--accent-deep) 100%); box-shadow:0 10px 22px -8px rgba(0,0,0,0.5), inset 0 1px 0 rgba(255,255,255,0.3); }
.kasa-loyalty__card::before { content:""; position:absolute; left:10px; top:14px; width:22px; height:16px; border-radius:3px; background:rgba(255,255,255,0.45); }
.kasa-loyalty__beam { position:absolute; inset:0; background:linear-gradient(100deg, transparent 40%, rgba(255,255,255,0.55) 50%, transparent 60%); transform:translateX(-120%); animation:kasa-beam 2.6s ease-in-out infinite; }
@keyframes kasa-beam { 0%,60% { transform:translateX(-120%);} 85%,100% { transform:translateX(120%);} }
.kasa-loyalty__body { flex:1; }
.kasa-loyalty__title { font-family:var(--k-display); font-style:italic; font-weight:500; font-size:24px; line-height:1.05; }
.kasa-loyalty__sub { font-size:15px; color:rgba(234,246,238,0.7); margin-top:3px; }
.kasa-loyalty__arrow { font-size:30px; color:var(--accent-light); animation:kasa-nudge 1.4s ease-in-out infinite; }
@keyframes kasa-nudge { 0%,100% { transform:translateX(0);} 50% { transform:translateX(6px);} }
.kasa-loyalty[data-state="welcome"] .kasa-loyalty__beam, .kasa-loyalty[data-state="welcome"] .kasa-loyalty__arrow { display:none; }

/* Compact card — sized so several stack in the promo zone without overflowing. */
.kasa-promo { display:flex; align-items:center; gap:15px; padding:13px 17px; border-radius:16px; flex-shrink:0;
  background:linear-gradient(180deg, rgba(246,206,94,0.18), rgba(246,206,94,0.07)); border:1px solid rgba(246,206,94,0.34); color:#fdf6e5; position:relative; overflow:hidden; }
.kasa-promo__icon { width:44px; height:44px; flex-shrink:0; display:grid; place-items:center; border-radius:13px;
  background:linear-gradient(160deg, var(--accent) 0%, var(--accent-deep) 100%); font-size:23px; box-shadow:0 8px 18px -10px rgba(0,0,0,0.6); }
.kasa-promo__body { flex:1; min-width:0; }
.kasa-promo__eyebrow { text-transform:uppercase; letter-spacing:0.16em; font-size:11px; color:var(--accent-light); margin-bottom:3px; }
.kasa-promo__title { font-family:var(--k-display); font-weight:500; font-size:18px; line-height:1.15; letter-spacing:-0.01em; }
.kasa-promo__title b { color:var(--accent-light); font-weight:700; }
.kasa-promo__note { font-size:12px; color:rgba(253,246,229,0.62); margin-top:4px; }
.kasa-meter { margin-top:8px; height:10px; border-radius:999px; background:rgba(0,0,0,0.28); overflow:hidden; }
.kasa-meter__fill { height:100%; border-radius:999px; width:0%; background:linear-gradient(90deg, var(--accent), var(--accent-light)); box-shadow:0 0 12px color-mix(in srgb, var(--accent) 60%, transparent); transition:width 640ms var(--k-ease); }
.kasa-meter__row { display:flex; justify-content:space-between; align-items:baseline; margin-top:5px; font-size:12px; color:rgba(253,246,229,0.75); }
.kasa-meter__row b { font-family:var(--k-mono); font-weight:700; color:#fff; }
/* Compact promo strip (multipack / weighted): product as the title, a single
   subrow (call-to-action / per-kg price + dots), and the savings pinned right as
   a price tag — fills the space the left-aligned content used to waste, ~⅓ shorter. */
.kasa-promo__icon .kasa-plus { width:24px; height:24px; }
.kasa-promo__icon .kasa-plus path { stroke:var(--brand-deep); stroke-width:2.6; stroke-linecap:round; fill:none; }
.kasa-promo--strip { gap:14px; padding:11px 15px 11px 14px; }
.kasa-promo--strip .kasa-promo__icon { width:42px; height:42px; }
.kasa-promo--strip .kasa-promo__title { font-size:16px; }
.kasa-promo__subrow { display:flex; align-items:center; gap:11px; margin-top:6px; flex-wrap:wrap; }
.kasa-promo__cta { font-size:12px; color:rgba(253,246,229,0.82); }
.kasa-promo__subrow .kasa-dots { margin-top:0; }
.kasa-promo__reward { flex-shrink:0; align-self:stretch; display:flex; flex-direction:column; align-items:flex-end; justify-content:center;
  position:relative; padding-left:15px; }
.kasa-promo__reward::before { content:""; position:absolute; left:0; top:14%; bottom:14%; width:1px;
  background:linear-gradient(180deg, transparent, rgba(255,255,255,0.22), transparent); }
.kasa-promo__reward-lead { text-transform:uppercase; letter-spacing:0.12em; font-size:10px; color:rgba(253,246,229,0.6); margin-bottom:2px; white-space:nowrap; }
.kasa-promo__reward-amt { font-family:var(--k-mono); font-weight:700; font-size:24px; line-height:0.95; letter-spacing:-0.02em; color:var(--accent-light); white-space:nowrap; }
.kasa-promo[data-done="true"] .kasa-promo__reward-lead { color:rgba(234,241,251,0.7); }
.kasa-promo[data-done="true"] .kasa-promo__reward-amt { color:var(--brand-glow); }
.kasa-dots { display:flex; gap:7px; margin-top:8px; }
.kasa-dots i { width:13px; height:13px; border-radius:50%; background:rgba(0,0,0,0.3); border:1.5px solid color-mix(in srgb, var(--accent-light) 50%, transparent); }
.kasa-dots i.on { background:var(--accent-light); border-color:var(--accent-light); box-shadow:0 0 10px color-mix(in srgb, var(--accent-light) 70%, transparent); }
.kasa-promo[data-done="true"] { background:linear-gradient(180deg, color-mix(in srgb, var(--brand-bright) 24%, transparent), color-mix(in srgb, var(--brand-bright) 10%, transparent)); border-color:color-mix(in srgb, var(--brand-glow) 55%, transparent); }
.kasa-promo[data-done="true"] .kasa-promo__icon { background:linear-gradient(160deg, var(--brand-bright), var(--brand)); }
.kasa-promo[data-done="true"] .kasa-promo__eyebrow, .kasa-promo[data-done="true"] .kasa-promo__title b { color:var(--brand-glow); }
.kasa-promo[data-done="true"] .kasa-meter__fill { background:linear-gradient(90deg, var(--brand-bright), var(--brand-glow)); }

/* ---- loyalty-card-gated promos ----
   A promo (or a card-only price) available ONLY with the customer's loyalty
   card. The "card flag" is a cobalt pill carrying a yellow mini-card glyph + the
   brand; card-gated cards also get an accent rail on the left edge. */
.kasa-cardflag { display:inline-flex; align-items:center; gap:7px; padding:3px 10px 3px 6px; border-radius:999px;
  background:linear-gradient(135deg, var(--brand-bright), var(--brand-deep)); color:#fff;
  font-family:var(--k-display); font-style:italic; font-weight:600; font-size:12.5px; letter-spacing:-0.01em; white-space:nowrap;
  box-shadow:0 4px 11px -5px rgba(0,0,0,0.6), inset 0 1px 0 rgba(255,255,255,0.22); }
.kasa-cardflag svg { width:23px; height:16px; flex-shrink:0; }
.kasa-cardflag .body { fill:var(--accent); } .kasa-cardflag .chip { fill:var(--brand-deep); } .kasa-cardflag .stripe { fill:var(--accent-deep); }
.kasa-promo__flagrow { margin-bottom:6px; }

/* variant (a): existing promo cards, gated — accent rail + the flag chip */
.kasa-promo--card { border-color:color-mix(in srgb, var(--accent) 50%, transparent); padding-left:21px;
  background:linear-gradient(180deg, rgba(246,206,94,0.22), rgba(246,206,94,0.08)); }
.kasa-promo--card::before, .kasa-promo--price::before { content:""; position:absolute; left:0; top:0; bottom:0; width:5px;
  background:linear-gradient(180deg, var(--accent-light), var(--accent-deep)); }

/* variant (b): card-only price — regular price struck → special card price */
.kasa-promo--price { align-items:stretch; padding:15px 18px 15px 21px;
  background:linear-gradient(165deg, color-mix(in srgb, var(--brand-bright) 30%, transparent), color-mix(in srgb, var(--brand-deep) 16%, transparent));
  border-color:color-mix(in srgb, var(--brand-glow) 45%, transparent); }
.kasa-promo--price .kasa-promo__icon { align-self:flex-start; background:linear-gradient(160deg, var(--brand-bright), var(--brand-deep)); color:#fff; }
.kasa-price { display:flex; align-items:center; gap:14px; margin-top:9px; flex-wrap:wrap; }
.kasa-price__was { font-family:var(--k-mono); font-size:18px; color:rgba(253,246,229,0.55); text-decoration:line-through; text-decoration-color:rgba(253,246,229,0.4); }
.kasa-price__arrow { color:var(--accent-light); font-size:18px; }
.kasa-price__now { display:inline-flex; align-items:baseline; gap:5px; padding:5px 14px; border-radius:13px;
  background:linear-gradient(135deg, var(--accent-light), var(--accent)); color:var(--brand-deep);
  box-shadow:0 8px 20px -8px color-mix(in srgb, var(--accent) 55%, transparent), inset 0 1px 0 rgba(255,255,255,0.5); }
.kasa-price__now b { font-family:var(--k-mono); font-weight:700; font-size:30px; line-height:1; letter-spacing:-0.02em; }
.kasa-price__now span { font-family:var(--k-mono); font-weight:700; font-size:15px; }
.kasa-price__save { font-size:12px; color:var(--accent-light); font-weight:600; align-self:center; }
.kasa-promo__note .scan { color:var(--accent-light); }

/* scene mode: idle vs serving.
   idle    → media fills the stage edge-to-edge (fullscreen, set on the base
             .kasa-media rule: full width/height, no radius/shadow).
   serving → the same media animates into a centred window on the left stage,
             framed to match the receipt panel's rounded cards (22px radius,
             themed accent hairline + deep shadow) so the two sides read as one
             cohesive scene. The mediaframe centres it (place-items:center);
             generous padding floats it clear of the loyalty/promo comm zones. */
.kasa[data-mode="serving"] .kasa-mediaframe { padding:30px 44px; }
/* The media fills the padded frame (keeps the base 100%×100% — do NOT switch to
   width/height:auto: the media's children are absolutely positioned, so an
   auto-sized box with aspect-ratio collapses to 0 and the window vanishes). The
   frame padding + the loyalty/promo zones above & below centre it on the stage;
   a light inner hairline + dark outer ring + deep shadow make it read as a
   deliberate framed screen on any media. */
.kasa[data-mode="serving"] .kasa-media {
  border-radius:22px;
  border:1px solid rgba(255,255,255,0.22);
  box-shadow:0 40px 80px -26px rgba(0,0,0,0.85), 0 0 0 1px rgba(0,0,0,0.28), inset 0 1px 0 rgba(255,255,255,0.20); }
.kasa[data-mode="serving"] .kasa-comm { max-height:240px; opacity:1; }
.kasa[data-mode="serving"] .kasa-comm--top { padding-top:80px; }
/* The promo zone may carry several cards — let it grow (up to ~half the stage,
   then scroll) so all active promotions show. It only takes the height its
   cards need, so a single promo keeps the media large; more promos shrink the
   media frame (flex:1 above) to fit. */
.kasa[data-mode="serving"] .kasa-comm--bottom { max-height:54vh; padding-top:6px; padding-bottom:22px; }

/* ---- receipt (right) ---- */
.kasa-receipt { position:relative; flex:0 0 0; max-width:720px; width:46%;
  display:flex; flex-direction:column;
  background:radial-gradient(rgba(32,32,26,0.030) 1px, transparent 1.5px), linear-gradient(180deg, var(--paper) 0%, var(--paper-warm) 100%);
  background-size:8px 8px, 100% 100%; color:var(--ink); box-shadow:-40px 0 80px -30px rgba(0,0,0,0.55);
  overflow:hidden; flex-basis:0; opacity:0; transition:flex-basis 480ms var(--k-ease), opacity 360ms var(--k-ease); }
.kasa[data-mode="serving"] .kasa-receipt { flex-basis:46%; opacity:1; }

.kasa-cart { flex-shrink:0; display:flex; align-items:center; gap:18px; padding:30px 38px 22px; border-bottom:1.5px solid var(--rule); position:relative; }
.kasa-cart__icon { position:relative; width:56px; height:56px; flex-shrink:0; display:grid; place-items:center; border-radius:16px; background:linear-gradient(160deg, var(--brand) 0%, var(--brand-deep) 100%); color:#fff; box-shadow:0 10px 22px -10px color-mix(in srgb, var(--brand) 70%, transparent), inset 0 1px 0 rgba(255,255,255,0.25); }
.kasa-cart__icon svg { width:30px; height:30px; }
.kasa-cart__count { display:flex; align-items:baseline; gap:10px; }
.kasa-cart__count b { font-family:var(--k-display); font-weight:600; font-size:46px; line-height:1; letter-spacing:-0.02em; font-variant-numeric:tabular-nums; }
.kasa-cart__count span { font-size:17px; color:var(--ink-soft); }
.kasa-cart__spacer { flex:1; }
.kasa-cart__loyalty { display:flex; flex-direction:column; align-items:flex-end; gap:6px; font-size:12px; color:var(--ink-faint); text-transform:uppercase; letter-spacing:0.18em; }
.kasa-cart__loyalty b { font-family:var(--k-display); font-size:18px; color:var(--brand); letter-spacing:0; text-transform:none; }
.kasa-cart__loyalty-caption { font-size:11px; color:var(--ink-faint); text-transform:uppercase; letter-spacing:0.18em; }

/* ---- brand logo (receipt header + summary card) ----
   Two render paths from devices/_kasa_logo:
   • --brand: the official Lewiatan logo (current brand mark) as a contained
     background image from --kasa-lewiatan-logo, sized by height with the
     artwork's intrinsic aspect ratio (450×146 ≈ 3.08:1). Transparent PNG, so
     drop-shadow follows the swoosh silhouette. Authentic colours — not tinted.
   • --word: themed text wordmark (leaf mark + brand name) for other themes —
     tinted entirely from theme tokens. */
.kasa-logo { display:inline-flex; align-items:center; gap:9px; line-height:1; }
.kasa-logo__mark { flex-shrink:0; overflow:visible; }
.kasa-logo__leaf { fill:var(--accent); }
.kasa-logo__vein { stroke:var(--brand-deep); stroke-width:2.2; stroke-linecap:round; }
.kasa-logo__word { font-family:var(--k-display); font-style:italic; font-weight:600; letter-spacing:-0.01em; color:var(--brand); white-space:nowrap; text-transform:none; }
.kasa-logo__art { display:block; flex-shrink:0; width:auto; aspect-ratio:450 / 146;
  background:var(--kasa-lewiatan-logo) center/contain no-repeat; }
.kasa-logo--receipt .kasa-logo__mark { width:25px; height:25px; }
.kasa-logo--receipt .kasa-logo__word { font-size:21px; }
.kasa-logo--receipt .kasa-logo__art { height:40px; }
.kasa-logo--summary { align-self:center; gap:13px; flex-shrink:0; animation:kasa-rise 460ms var(--k-ease) 60ms both; }
.kasa-logo--summary .kasa-logo__mark { width:42px; height:42px; }
.kasa-logo--summary .kasa-logo__word { font-size:clamp(28px,4.5vw,38px); }
.kasa-logo--summary .kasa-logo__art { height:clamp(40px,6vh,56px); filter:drop-shadow(0 8px 16px rgba(0,0,0,0.28)); }
.kasa-tick { animation:kasa-tick 420ms var(--k-ease); }
@keyframes kasa-tick { 0% { transform:scale(1);} 35% { transform:scale(1.18); color:var(--brand);} 100% { transform:scale(1);} }

.kasa-lines { list-style:none; margin:0; flex:1; overflow-y:auto; padding:14px 30px 8px; scrollbar-width:none; }
.kasa-lines::-webkit-scrollbar { width:0; height:0; }
.kasa-line { padding:18px 0 16px; border-bottom:1px solid var(--rule); animation:kasa-line-in 520ms var(--k-ease) both; }
.kasa-line:last-child { border-bottom:0; }
@keyframes kasa-line-in { 0% { opacity:0; transform:translateY(16px) scale(0.985);} 60% { opacity:1;} 100% { opacity:1; transform:none;} }
.kasa-line.fresh { position:relative; }
.kasa-line.fresh::after { content:""; position:absolute; inset:0 -30px; background:linear-gradient(90deg, transparent, color-mix(in srgb, var(--brand-bright) 16%, transparent), transparent); transform:translateX(-100%); animation:kasa-sweep 900ms var(--k-ease) 120ms; pointer-events:none; }
@keyframes kasa-sweep { to { transform:translateX(100%);} }
.kasa-line__head { display:grid; grid-template-columns:30px 1fr auto; align-items:baseline; gap:14px; }
.kasa-line__nr { font-family:var(--k-mono); font-size:14px; color:var(--ink-faint); font-variant-numeric:tabular-nums; }
.kasa-line__name { font-weight:600; font-size:20px; letter-spacing:-0.01em; color:var(--ink); display:flex; align-items:center; gap:10px; min-width:0; }
.kasa-line__name .txt { overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.kasa-line__badge { flex-shrink:0; display:inline-flex; align-items:center; gap:5px; padding:3px 10px 3px 8px; border-radius:999px; background:linear-gradient(180deg, var(--accent-light), var(--accent)); color:var(--brand-deep); font-size:12px; font-weight:700; letter-spacing:0.03em; text-transform:uppercase; box-shadow:0 4px 10px -4px color-mix(in srgb, var(--accent) 70%, transparent); }
.kasa-line__badge::before { content:"★"; font-size:11px; }
.kasa-line__total { font-family:var(--k-mono); font-weight:600; font-size:20px; font-variant-numeric:tabular-nums; white-space:nowrap; color:var(--ink); }
.kasa-line__total.struck { text-decoration:line-through; text-decoration-color:var(--ink-faint); color:var(--ink-faint); font-weight:500; font-size:17px; }
.kasa-line__sub { margin:9px 0 0 44px; display:flex; flex-direction:column; gap:5px; }
.kasa-line__row { display:grid; grid-template-columns:1fr auto; align-items:baseline; font-size:15px; color:var(--ink-soft); }
.kasa-line__row .v { font-family:var(--k-mono); font-variant-numeric:tabular-nums; }
.kasa-line__row.discount, .kasa-line__row.discount .v { color:var(--brick); font-weight:600; }
.kasa-line__row.final { color:var(--ink); font-weight:700; font-size:17px; padding-top:4px; }
.kasa-line__row.final .v { font-size:18px; }

.kasa-foot { flex-shrink:0; border-top:1.5px dashed var(--rule-strong); background:linear-gradient(180deg, rgba(255,255,255,0.5), color-mix(in srgb, var(--paper-warm) 70%, transparent)); padding:18px 38px 26px; display:none; flex-direction:column; gap:14px; }
.kasa-foot[data-visible="true"] { display:flex; }
.kasa-foot__pre { display:grid; grid-template-columns:1fr auto; align-items:baseline; font-size:17px; color:var(--ink-soft); }
.kasa-foot__pre[data-visible="false"] { display:none; }
.kasa-foot__pre .v { font-family:var(--k-mono); font-variant-numeric:tabular-nums; font-size:19px; }

.kasa-savings { display:none; align-items:center; gap:18px; padding:16px 18px; border-radius:18px;
  background:radial-gradient(120% 160% at 12% 0%, color-mix(in srgb, var(--accent-light) 22%, transparent), transparent 60%), linear-gradient(180deg, color-mix(in srgb, var(--brand) 10%, transparent), color-mix(in srgb, var(--brand) 5%, transparent));
  border:1px solid color-mix(in srgb, var(--brand) 22%, transparent); position:relative; overflow:hidden; }
.kasa-savings[data-visible="true"] { display:flex; animation:kasa-pop-in 520ms var(--k-ease); }
@keyframes kasa-pop-in { from { opacity:0; transform:translateY(10px) scale(0.97);} to { opacity:1; transform:none;} }
.kasa-wallet { position:relative; width:76px; height:70px; flex-shrink:0; }
.kasa-wallet svg { position:absolute; inset:0; width:100%; height:100%; overflow:visible; }
/* Wallet-glyph fills shared by .kasa-wallet and .kasa-card__savings .big-wallet
   (both render the _kasa_wallet partial). Scoped at .kasa so one rule retints
   every wallet on screen. */
.kasa .w-back   { fill:var(--brand-deep); }
.kasa .w-flap   { fill:var(--brand); }
.kasa .w-pocket { fill:color-mix(in srgb, var(--brand-deep) 76%, #000); }
.kasa .w-coin   { fill:var(--accent); }
.kasa .w-coin-in{ fill:var(--accent-deep); }
.kasa-wallet.bump { animation:kasa-wallet-bump 360ms var(--k-ease); }
@keyframes kasa-wallet-bump { 0% { transform:translateY(0);} 30% { transform:translateY(4px) scale(0.97,1.03);} 100% { transform:translateY(0);} }
.kasa-coin { position:absolute; left:50%; top:-34px; width:26px; height:26px; margin-left:-13px; border-radius:50%; background:radial-gradient(circle at 35% 30%, var(--accent-light), var(--accent) 60%, var(--accent-deep)); box-shadow:inset 0 -2px 3px rgba(0,0,0,0.25), 0 3px 6px rgba(0,0,0,0.25); display:grid; place-items:center; font-family:var(--k-display); font-weight:700; font-size:12px; color:var(--coin-ink); z-index:3; animation:kasa-coin-drop 760ms cubic-bezier(0.5,0,0.7,1) forwards; }
.kasa-coin::after { content:"zł"; }
@keyframes kasa-coin-drop { 0% { opacity:0; transform:translateY(-12px) scale(0.6) rotate(-20deg);} 25% { opacity:1;} 70% { opacity:1; transform:translateY(26px) scale(1) rotate(8deg);} 100% { opacity:0; transform:translateY(34px) scale(0.7) rotate(14deg);} }
.kasa-savings__body { flex:1; min-width:0; }
.kasa-savings__label { font-family:var(--k-display); font-style:italic; font-weight:500; font-size:19px; color:var(--brand-deep); letter-spacing:-0.01em; }
.kasa-savings__amount { font-family:var(--k-mono); font-weight:700; font-variant-numeric:tabular-nums; font-size:34px; line-height:1.05; color:var(--brand); letter-spacing:-0.01em; }
.kasa-savings__amount .cur { font-size:0.55em; color:var(--brand-deep); margin-left:4px; }

.kasa-pay { display:grid; grid-template-columns:1fr auto auto; align-items:center; gap:16px; margin-top:2px; padding:20px 26px; border-radius:20px;
  background:linear-gradient(165deg, var(--brand-bright) 0%, var(--brand) 45%, var(--brand-deep) 100%); color:#fff; box-shadow:0 18px 38px -16px color-mix(in srgb, var(--brand) 75%, transparent), inset 0 1px 0 rgba(255,255,255,0.25); position:relative; overflow:hidden; }
.kasa-pay::before { content:""; position:absolute; inset:0; background:linear-gradient(105deg, transparent 35%, rgba(255,255,255,0.22) 50%, transparent 65%); transform:translateX(-120%); animation:kasa-shine 4.2s ease-in-out infinite; }
@keyframes kasa-shine { 0%,55% { transform:translateX(-120%);} 80%,100% { transform:translateX(120%);} }
.kasa-pay__label { font-size:17px; font-weight:600; opacity:0.92; }
.kasa-pay__amount { font-family:var(--k-mono); font-weight:700; font-variant-numeric:tabular-nums; font-size:40px; line-height:1; letter-spacing:-0.02em; }
.kasa-pay__amount .cur { font-size:0.5em; opacity:0.85; margin-left:4px; }
.kasa-pay__arrow { width:44px; height:44px; display:grid; place-items:center; border-radius:50%; background:rgba(255,255,255,0.18); }
.kasa-pay__arrow svg { width:22px; height:22px; }

/* ---- summary ---- */
.kasa-summary { position:absolute; inset:0; z-index:30; display:none; align-items:center; justify-content:center; padding:24px; background:radial-gradient(80% 70% at 50% 30%, var(--panel-glow), transparent 70%), linear-gradient(160deg, var(--panel-c) 0%, var(--panel-d) 100%); }
.kasa-summary[data-visible="true"] { display:flex; animation:kasa-fade 280ms ease-out; }
@keyframes kasa-fade { from { opacity:0;} to { opacity:1;} }
.kasa-confetti { position:absolute; inset:0; overflow:hidden; pointer-events:none; }
.kasa-confetti-piece { position:absolute; top:-20px; width:10px; height:14px; opacity:0; animation:kasa-confetti-fall linear forwards; }
@keyframes kasa-confetti-fall { 0% { opacity:0; transform:translateY(-20px) rotate(0);} 10% { opacity:1;} 100% { opacity:0.9; transform:translateY(105vh) rotate(540deg);} }
/* margin:auto centres the card when it fits; when it's TALLER than the pane it
   top-pins (flex auto margins never overflow the start edge). kasa(_live)_controller.
   fitSummaryCard() then measures the natural height and sets the `scale` individual
   property so the WHOLE card — logo through the trailing welcome line — shrinks to
   fit with no clip. transform-origin:center top makes it shrink DOWN from that
   pinned top (a centre origin would scale about a point below the pane centre and
   push the bottom off-screen). `scale` is independent of the `transform` the
   kasa-card-in entry animation drives, so the two compose cleanly. */
.kasa-card { position:relative; margin:auto; transform-origin:center top; width:min(560px,94%); background:radial-gradient(rgba(32,32,26,0.035) 1px, transparent 1.5px), linear-gradient(180deg, var(--card), var(--paper-warm)); background-size:8px 8px, 100% 100%; border-radius:22px; padding:32px 48px 28px; text-align:center; box-shadow:0 40px 90px -30px rgba(0,0,0,0.7), inset 0 1px 0 rgba(255,255,255,0.8); display:flex; flex-direction:column; gap:16px; animation:kasa-card-in 520ms var(--k-ease) both; }
@keyframes kasa-card-in { from { opacity:0; transform:translateY(26px) scale(0.96);} to { opacity:1; transform:none;} }
.kasa-card::before { content:""; position:absolute; top:-9px; left:22px; right:22px; height:18px; background:radial-gradient(circle at 9px 9px, transparent 8px, var(--card) 8.5px) 0 0 / 18px 18px repeat-x; filter:drop-shadow(0 -3px 4px rgba(0,0,0,0.12)); }
.kasa-card__thanks { font-family:var(--k-display); font-style:italic; font-weight:500; font-size:clamp(40px,6vw,58px); line-height:0.96; letter-spacing:-0.02em; color:var(--ink); animation:kasa-rise 460ms var(--k-ease) 120ms both; }
.kasa-card__sub { font-size:14px; text-transform:uppercase; letter-spacing:0.28em; color:var(--ink-faint); animation:kasa-rise 460ms var(--k-ease) 200ms both; }
.kasa-card__savings { display:none; flex-direction:column; align-items:center; gap:10px; margin:4px auto; padding:26px 28px 22px; border-radius:20px; background:radial-gradient(120% 150% at 50% 0%, color-mix(in srgb, var(--accent-light) 30%, transparent), transparent 65%), linear-gradient(180deg, color-mix(in srgb, var(--brand) 12%, transparent), color-mix(in srgb, var(--brand) 6%, transparent)); border:1px solid color-mix(in srgb, var(--brand) 28%, transparent); position:relative; overflow:hidden; animation:kasa-rise 500ms var(--k-ease) 320ms both; }
.kasa-card__savings[data-visible="true"] { display:flex; }
.kasa-card__savings .big-wallet { position:relative; width:96px; height:88px; margin-bottom:4px; }
.kasa-card__savings .big-wallet svg { width:100%; height:100%; overflow:visible; }
.kasa-card__savings-label { font-family:var(--k-display); font-style:italic; font-weight:500; font-size:22px; color:var(--brand-deep); }
.kasa-card__savings-amount { font-family:var(--k-mono); font-weight:700; font-variant-numeric:tabular-nums; font-size:clamp(46px,8vw,64px); line-height:1; letter-spacing:-0.02em; color:var(--brand); }
.kasa-card__savings-amount .cur { font-size:0.45em; color:var(--brand-deep); margin-left:6px; }
.kasa-card__total-label { font-family:var(--k-display); font-variant:small-caps; letter-spacing:0.16em; font-size:15px; color:var(--ink-soft); }
.kasa-card__total { font-family:var(--k-mono); font-weight:700; font-variant-numeric:tabular-nums; font-size:clamp(54px,10vw,80px); line-height:1; letter-spacing:-0.03em; color:var(--ink); animation:kasa-rise 500ms var(--k-ease) 420ms both; }
.kasa-card__total .cur { font-size:0.36em; color:var(--ink-soft); margin-left:6px; }
.kasa-card__rows { display:flex; flex-direction:column; gap:12px; padding-top:20px; border-top:1.5px dashed var(--rule-strong); margin:0; }
.kasa-card__row { display:grid; grid-template-columns:max-content 1fr max-content; align-items:baseline; animation:kasa-rise 420ms var(--k-ease) both; }
.kasa-card__row:nth-child(1) { animation-delay:520ms; } .kasa-card__row:nth-child(2) { animation-delay:580ms; } .kasa-card__row:nth-child(3) { animation-delay:640ms; }
.kasa-card__row dt { font-family:var(--k-display); font-variant:small-caps; letter-spacing:0.12em; font-size:16px; color:var(--ink-soft); white-space:nowrap; margin:0; }
.kasa-card__row::after { content:""; grid-column:2; align-self:center; height:2px; margin:0 14px; background-image:radial-gradient(var(--rule-strong) 1px, transparent 1.4px); background-size:8px 2px; background-repeat:repeat-x; transform:translateY(0.2em); }
.kasa-card__row dd { font-family:var(--k-mono); font-weight:600; font-variant-numeric:tabular-nums; font-size:19px; color:var(--ink); margin:0; justify-self:end; }
.kasa-card__welcome { padding-top:18px; border-top:1.5px dashed var(--rule-strong); font-family:var(--k-display); font-style:italic; font-size:22px; color:var(--ink-soft); animation:kasa-rise 460ms var(--k-ease) 720ms both; }
@keyframes kasa-rise { from { opacity:0; transform:translateY(12px);} to { opacity:1; transform:none;} }

/* ============================================================
   KARTA LAYOUT — "Lewiatan z Kartą" (theme lewiatan_karta)
   The left column splits into three rows: a loyalty-card window (top), the
   campaign ad (middle, flex), and the promo stack (bottom). The promo stack is
   content-sized and the ad (flex:1) absorbs the rest, shrinking as promos pile
   up — so every card stays full-size and on-screen. The window swaps
   regret↔reward and a rich↔compact body; kasa(_live)_controller fills it via
   lib/kasa_karta.js. Scoped to the new classes so the shared `.kasa` themes are
   untouched.
   ============================================================ */
.kasa-zone { position:relative; min-height:0; overflow:hidden;
  transition:padding 560ms var(--k-ease), opacity 360ms var(--k-ease); }
/* Horizontal padding is 40px (was 30/34) as a safe inset: on a customer panel
   whose Windows scaling overhangs the left edge, the extra gutter keeps the
   loyalty-card column off the bezel. Belt-and-suspenders to the launcher
   --force-device-scale-factor fix; harmless on a correctly-scaled screen. */
.kasa-zone--loyalty { flex:0 0 auto; padding:20px 40px 4px; display:flex; align-items:flex-start; }
.kasa-zone--media   { flex:1 1 auto; min-height:0; padding:0; display:grid; place-items:stretch; }
/* Content-driven: the promo zone takes the height its cards need (flex:0 1 auto so
   it can still shrink under pressure); the ad zone above is flex:1 and absorbs the
   rest, shrinking as the stack grows. The inner stack is capped to the zone and
   scrolls only as a last resort, so a tall stack never clips below the screen. */
.kasa-zone--promos  { flex:0 1 auto; padding:8px 40px 20px; }
/* height:0 guarantees a full collapse when there are no promos (the inline 0%
   height an older build set used to do this); the ad zone reclaims the space. */
.kasa-zone--promos[data-empty="true"] { height:0; padding-top:0; padding-bottom:0; opacity:0; }
/* max-height:100% DOES bound the scroll here (unlike the classic .kasa-promos at
   the top of this file, which must use 54vh): this zone is a flex item in a
   fixed-height, overflow:hidden flex column, so its resolved height is definite
   and the percentage resolves against it. Cards scroll only as a last resort. */
.kasa-zone--promos .kasa-promos { height:auto; max-height:100%; overflow-y:auto; }
/* Idle (no customer): only the fullscreen ad — collapse the card + promo rows. */
.kasa[data-mode="idle"] .kasa-zone--loyalty,
.kasa[data-mode="idle"] .kasa-zone--promos { display:none; }
/* Serving: float the ad into a framed window so the three rows read as one scene. */
.kasa[data-mode="serving"] .kasa-stage--karta .kasa-zone--media { padding:6px 40px 12px; }
.kasa[data-mode="serving"] .kasa-stage--karta .kasa-media { border-radius:18px;
  border:1px solid rgba(255,255,255,0.18); box-shadow:0 30px 60px -28px rgba(0,0,0,0.8); }

/* ---- the loyalty-card window ---- */
.kasa-loyalty--karta { display:block; width:100%; max-height:100%; align-self:stretch;
  gap:0; padding:16px 22px; border-radius:22px; overflow:hidden;
  box-shadow:0 22px 46px -24px rgba(0,0,0,0.7), inset 0 1px 0 rgba(255,255,255,0.12);
  color:#eaf1fb; animation:kasa-zone-in 520ms var(--k-ease) both; }
@keyframes kasa-zone-in { from { opacity:0; transform:translateY(-10px);} to { opacity:1; transform:none;} }
.kasa-loyalty--karta .kasa-loyalty__head { display:flex; align-items:center; gap:11px; }
.kasa-loyalty--karta .kasa-loyalty__eyebrow { margin-left:auto; text-transform:uppercase; letter-spacing:0.16em;
  font-size:10px; font-weight:600; padding:5px 11px; border-radius:999px;
  color:#ffe9d8; background:rgba(255,138,91,0.16); border:1px solid rgba(255,138,91,0.4); }
.kasa-loyalty--karta .kasa-loyalty__eyebrow.on { color:#0e2a60;
  background:linear-gradient(135deg,var(--accent-light),var(--accent)); border-color:rgba(255,255,255,0.3); box-shadow:0 4px 12px -4px var(--accent-deep); }
.kasa-logo--loyalty .kasa-logo__art { height:30px; }

.kasa-loyalty--karta .kasa-loyalty__grid { display:grid; grid-template-columns:auto 1px 1fr; gap:18px; align-items:start; margin-top:13px; }
.kasa-loyalty--karta .kasa-loyalty__rule { align-self:stretch; background:linear-gradient(180deg, transparent, rgba(255,255,255,0.18), transparent); }
.kasa-loyalty--karta .kasa-loyalty__title { font-family:var(--k-display); font-weight:500; font-size:22px; line-height:1.08; letter-spacing:-0.01em; color:#fff; font-style:normal; }
.kasa-loyalty--karta[data-state="regret"] .kasa-loyalty__title { font-style:italic; }
.kasa-loyalty--karta .kasa-loyalty__title b { color:var(--accent-light); font-weight:700; font-style:normal; }
.kasa-loyalty--karta .kasa-loyalty__sub { font-size:13.5px; color:rgba(234,241,251,0.72); margin-top:8px; line-height:1.35; }
.kasa-loyalty--karta .kasa-loyalty__sub b { color:#fff; }

/* card visual */
.kasa-cardvis { position:relative; width:138px; flex-shrink:0; display:flex; flex-direction:column; gap:10px; align-items:center; }
.kasa-cardvis__plastic { position:relative; width:138px; height:88px; border-radius:13px; overflow:hidden;
  background:linear-gradient(135deg, var(--brand-bright) 0%, var(--brand-deep) 100%);
  box-shadow:0 16px 30px -12px rgba(0,0,0,0.6), inset 0 1px 0 rgba(255,255,255,0.25); }
.kasa-cardvis__plastic[data-on="true"] { background:linear-gradient(135deg, var(--brand) 0%, var(--brand-deep) 100%);
  box-shadow:0 16px 34px -10px rgba(46,123,214,0.6), inset 0 1px 0 rgba(255,255,255,0.3), 0 0 0 2px color-mix(in srgb,var(--accent) 60%,transparent); }
.kasa-cardvis__chip { position:absolute; left:13px; top:32px; width:25px; height:18px; border-radius:4px;
  background:linear-gradient(135deg,var(--accent-light),var(--accent-deep)); box-shadow:inset 0 0 0 1px rgba(0,0,0,0.15); }
.kasa-cardvis__brand { position:absolute; left:13px; top:9px; font-family:var(--k-display); font-style:italic; font-weight:600; font-size:14px; color:#fff; }
.kasa-cardvis__beam { position:absolute; inset:0; background:linear-gradient(100deg, transparent 40%, rgba(255,255,255,0.5) 50%, transparent 60%);
  transform:translateX(-120%); animation:kasa-karta-beam 2.6s ease-in-out infinite; }
@keyframes kasa-karta-beam { 0%,60% { transform:translateX(-120%);} 85%,100% { transform:translateX(120%);} }
.kasa-cardvis__check { position:absolute; right:-7px; top:-7px; width:30px; height:30px; border-radius:50%;
  background:linear-gradient(135deg,var(--accent-light),var(--accent)); color:var(--brand-deep); display:grid; place-items:center; font-size:16px; font-weight:800;
  box-shadow:0 6px 14px -4px var(--accent-deep); animation:kasa-stamp 520ms var(--k-ease) 160ms both; z-index:3; }
@keyframes kasa-stamp { 0% { opacity:0; transform:scale(0.2) rotate(-30deg);} 60% { transform:scale(1.18);} 100% { opacity:1; transform:scale(1) rotate(0);} }
.kasa-scan { display:inline-flex; align-items:center; gap:8px; font-size:13px; font-weight:600; color:#eaf1fb; }
.kasa-scan__ok { color:var(--accent-light); }
.kasa-scan__arrow { font-size:17px; color:var(--accent-light); animation:kasa-karta-nudge 1.4s ease-in-out infinite; }
@keyframes kasa-karta-nudge { 0%,100% { transform:translateY(0);} 50% { transform:translateY(4px);} }

/* elki tokens */
.elki-row { display:flex; align-items:center; gap:9px; margin-top:13px; flex-wrap:wrap; }
.elki { position:relative; width:40px; height:40px; border-radius:50%; flex-shrink:0; display:grid; place-items:center;
  background:radial-gradient(circle at 36% 30%, var(--accent-light), var(--accent) 58%, var(--accent-deep));
  box-shadow:inset 0 -2px 3px rgba(0,0,0,0.22), 0 6px 14px -6px rgba(214,164,0,0.7); }
.elki svg { width:22px; height:22px; }
.elki .blade { fill:var(--brand-deep); } .elki .vein { stroke:var(--accent-light); stroke-width:2.4; fill:none; stroke-linecap:round; }
.elki--ghost { background:rgba(255,255,255,0.06); box-shadow:inset 0 0 0 1.5px rgba(255,210,0,0.4); }
.elki--ghost .blade { fill:rgba(255,210,0,0.5); } .elki--ghost .vein { stroke:rgba(255,210,0,0.5); }
.elki--ghost::after { content:""; position:absolute; left:50%; top:-7px; bottom:-7px; width:2.5px; margin-left:-1px;
  background:var(--loss, #ff8a5b); transform:rotate(34deg); border-radius:2px; box-shadow:0 0 8px var(--loss, #ff8a5b); }
.elki-count { display:inline-flex; align-items:baseline; gap:6px; margin-left:4px; }
.elki-count b { font-family:var(--k-mono); font-weight:700; font-size:32px; line-height:1; letter-spacing:-0.02em; font-variant-numeric:tabular-nums; }
.elki-count span { font-size:13.5px; }
.kasa-loyalty--karta[data-state="regret"] .elki-count b { color:var(--loss, #ff8a5b); }
.kasa-loyalty--karta[data-state="reward"] .elki-count b { color:var(--accent-light); text-shadow:0 0 22px color-mix(in srgb,var(--accent) 55%,transparent); }

/* regret ledger */
.kasa-ledger { margin-top:12px; display:flex; flex-direction:column; gap:8px; }
.kasa-ledger__row { display:grid; grid-template-columns:30px 1fr auto; align-items:center; gap:11px; padding:10px 13px; border-radius:13px;
  background:rgba(255,138,91,0.08); border:1px solid rgba(255,138,91,0.2); }
.kasa-ledger__ico { width:30px; height:30px; display:grid; place-items:center; border-radius:9px; font-size:15px; background:rgba(255,138,91,0.16); }
.kasa-ledger__ico--leaf svg { width:17px; height:17px; }
.kasa-ledger__ico--leaf .blade { fill:var(--loss, #ff8a5b); } .kasa-ledger__ico--leaf .vein { stroke:none; }
.kasa-ledger__txt { font-size:13px; color:rgba(255,233,216,0.92); line-height:1.25; }
.kasa-ledger__txt .muted { opacity:0.7; }
.kasa-ledger__amt { font-family:var(--k-mono); font-weight:700; font-size:17px; color:var(--loss, #ff8a5b); white-space:nowrap; font-variant-numeric:tabular-nums; }
.kasa-ledger__amt .u { font-size:0.7em; } .kasa-ledger__amt .cur { font-size:0.62em; opacity:0.8; margin-left:2px; }

/* reward progress */
.kasa-reward { margin-top:12px; padding:13px 15px; border-radius:15px;
  background:radial-gradient(120% 150% at 12% 0%, color-mix(in srgb,var(--accent-light) 16%,transparent), transparent 60%), linear-gradient(180deg, rgba(255,255,255,0.07), rgba(255,255,255,0.03));
  border:1px solid rgba(255,236,77,0.28); }
.kasa-reward__top { display:flex; align-items:baseline; justify-content:space-between; gap:12px; }
.kasa-reward__lead { font-size:13px; color:rgba(234,241,251,0.85); }
.kasa-reward__lead b { color:var(--accent-light); font-weight:700; }
.kasa-reward__val { font-family:var(--k-mono); font-size:11.5px; color:rgba(234,241,251,0.6); }
.kasa-loyalty--karta .kasa-meter { margin-top:9px; height:10px; border-radius:999px; background:rgba(0,0,0,0.3); overflow:hidden; }
.kasa-loyalty--karta .kasa-meter__fill { height:100%; border-radius:999px; background:linear-gradient(90deg, var(--accent), var(--accent-light));
  box-shadow:0 0 14px color-mix(in srgb,var(--accent) 60%,transparent); transition:width 640ms var(--k-ease); }
.kasa-loyalty--karta .kasa-meter__row { display:flex; justify-content:space-between; align-items:baseline; margin-top:7px; font-size:12.5px; color:rgba(234,241,251,0.78); }
.kasa-loyalty--karta .kasa-meter__row b { font-family:var(--k-mono); font-weight:700; color:#fff; }

/* ---- summary medal (card-active checkout) ---- */
/* The transaction is paid: no progress meter, just a ceremonial gold medallion
   carrying the elki earned. Centered, full-width (no card/grid split). */
.kasa-loyalty--karta[data-size="summary"] { padding:18px 22px 20px; text-align:center; }
.kasa-medal { display:flex; flex-direction:column; align-items:center; }
.kasa-medal__lead { font-family:var(--k-display); font-style:italic; font-weight:500; font-size:23px; line-height:1.1;
  color:#fff; margin-top:14px; animation:kasa-zone-in 460ms var(--k-ease) both; }
.kasa-medal__stage { position:relative; width:172px; height:172px; margin:10px auto 2px; display:grid; place-items:center; }
.kasa-medal__rays { position:absolute; inset:0; border-radius:50%;
  background:conic-gradient(from 0deg, rgba(255,236,77,0) 0deg, rgba(255,236,77,0.22) 6deg, rgba(255,236,77,0) 12deg);
  -webkit-mask:radial-gradient(circle, transparent 54px, #000 56px, #000 84px, transparent 86px);
          mask:radial-gradient(circle, transparent 54px, #000 56px, #000 84px, transparent 86px);
  animation:kasa-medal-spin 20s linear infinite; }
@keyframes kasa-medal-spin { to { transform:rotate(360deg); } }
.kasa-medal__disc { position:relative; width:116px; height:116px; border-radius:50%; display:grid; place-items:center;
  background:radial-gradient(circle at 38% 28%, var(--accent-light), var(--accent) 56%, var(--accent-deep));
  box-shadow:inset 0 -4px 8px rgba(0,0,0,0.25), inset 0 2px 4px rgba(255,255,255,0.6), 0 16px 34px -10px rgba(214,164,0,0.8);
  animation:kasa-medal-pop 560ms var(--k-ease) 140ms both; }
.kasa-medal__disc::before { content:""; position:absolute; inset:9px; border-radius:50%; border:2px dashed rgba(110,84,0,0.45); }
@keyframes kasa-medal-pop { 0% { opacity:0; transform:scale(0.2) rotate(-24deg); } 60% { transform:scale(1.14); } 100% { opacity:1; transform:scale(1) rotate(0); } }
.kasa-medal__num { font-family:var(--k-mono); font-weight:700; font-size:52px; line-height:0.8; letter-spacing:-0.03em;
  color:var(--coin-ink, #6b5400); font-variant-numeric:tabular-nums; }
.kasa-medal__disc svg { position:absolute; top:9px; right:11px; width:28px; height:28px; }
.kasa-medal__disc svg .blade { fill:var(--coin-ink, #6b5400); }
.kasa-medal__disc svg .vein { stroke:#fff; stroke-width:2.2; fill:none; stroke-linecap:round; }
.kasa-medal__unit { font-family:var(--k-display); font-style:italic; font-weight:500; font-size:23px; color:var(--accent-light);
  text-shadow:0 0 22px color-mix(in srgb,var(--accent) 50%,transparent); margin-top:8px; }
.kasa-medal__done { display:inline-flex; align-items:center; gap:6px; margin-top:14px; font-size:12.5px; font-weight:600;
  color:#cdebd2; background:rgba(74,201,122,0.14); border:1px solid rgba(74,201,122,0.42); padding:6px 13px; border-radius:999px;
  animation:kasa-zone-in 460ms var(--k-ease) 220ms both; }
.kasa-medal--zero { padding:8px 0; }
.kasa-medal--zero .kasa-medal__lead { margin-bottom:4px; }
.kasa-medal__thanks { margin-top:8px; font-size:14px; color:rgba(234,241,251,0.82);
  animation:kasa-zone-in 460ms var(--k-ease) 160ms both; }

/* compact banner */
.kasa-loyalty--karta[data-size="compact"] { padding:13px 18px; }
.kasa-loyalty__compact { display:flex; align-items:center; gap:15px; }
.kasa-compact__card { position:relative; width:78px; height:50px; flex-shrink:0; border-radius:9px; overflow:hidden;
  background:linear-gradient(135deg,var(--brand-bright) 0%,var(--brand-deep) 100%); box-shadow:0 9px 18px -9px rgba(0,0,0,0.6), inset 0 1px 0 rgba(255,255,255,0.25); }
.kasa-compact__card .b { position:absolute; left:8px; top:6px; font-family:var(--k-display); font-style:italic; font-weight:600; font-size:10px; color:#fff; }
.kasa-compact__card .chip { position:absolute; left:8px; bottom:7px; width:16px; height:11px; border-radius:3px; background:linear-gradient(135deg,var(--accent-light),var(--accent-deep)); }
.kasa-compact__card .beam { position:absolute; inset:0; background:linear-gradient(100deg, transparent 40%, rgba(255,255,255,0.5) 50%, transparent 60%); transform:translateX(-120%); animation:kasa-karta-beam 2.6s ease-in-out infinite; }
.kasa-compact__card[data-on="true"] { background:linear-gradient(135deg,var(--brand) 0%,var(--brand-deep) 100%); box-shadow:0 9px 18px -8px rgba(46,123,214,0.6), 0 0 0 2px color-mix(in srgb,var(--accent) 60%,transparent); }
.kasa-compact__check { position:absolute; right:-6px; top:-6px; width:22px; height:22px; border-radius:50%; display:grid; place-items:center; font-size:12px; font-weight:800;
  background:linear-gradient(135deg,var(--accent-light),var(--accent)); color:var(--brand-deep); box-shadow:0 5px 12px -4px var(--accent-deep); z-index:2; }
.kasa-compact__body { flex:1; min-width:0; }
.kasa-compact__eyebrow { text-transform:uppercase; letter-spacing:0.16em; font-size:9.5px; font-weight:600; margin-bottom:4px;
  display:inline-block; padding:3px 9px; border-radius:999px; color:#ffe9d8; background:rgba(255,138,91,0.16); border:1px solid rgba(255,138,91,0.4); }
.kasa-compact__eyebrow.on { color:#0e2a60; background:linear-gradient(135deg,var(--accent-light),var(--accent)); border-color:rgba(255,255,255,0.3); }
.kasa-compact__title { font-family:var(--k-display); font-style:italic; font-weight:500; font-size:18px; line-height:1.12; color:#fff; }
.kasa-compact__title b { font-style:normal; font-weight:700; }
.kasa-loyalty--karta[data-state="regret"] .kasa-compact__title b { color:var(--loss, #ff8a5b); }
.kasa-loyalty--karta[data-state="reward"] .kasa-compact__title b { color:var(--accent-light); }
.kasa-compact__scan { display:inline-flex; align-items:center; gap:7px; flex-shrink:0; font-size:13px; font-weight:600; color:#eaf1fb; white-space:nowrap; }
.kasa-compact__scan .arr { font-size:18px; color:var(--accent-light); }
.kasa-compact__earned { display:inline-flex; align-items:center; gap:8px; flex-shrink:0; }
.kasa-compact__earned .elki { width:34px; height:34px; }
.kasa-compact__earned .elki svg { width:19px; height:19px; }
.kasa-compact__earned b { font-family:var(--k-mono); font-weight:700; font-size:24px; color:var(--accent-light); text-shadow:0 0 18px color-mix(in srgb,var(--accent) 55%,transparent); }

/* ============================================================
   COMPACT DENSITY — small kiosks (≤900 wide OR ≤700 tall; e.g. 800×600), used
   most visibly by "Lewiatan z Kartą".
   The base `.kasa` scale is tuned for the ≥1024×768 minimum. On an 800×600
   panel the fixed px sizes overflow: the receipt header clips its loyalty
   caption, the regret window's sub-copy is cut by overflow:hidden, and the
   card + ad + promo rows fight for the 600px column. This block recompresses
   paddings, type and the card visuals so the SAME scene fits the shorter
   viewport with nothing dropped. Activated by `.kasa--compact`, set from the
   kiosk-REPORTED screen resolution (Device#small_screen?) AND reconciled from
   the live viewport by kasa(_live)_controller — so it is correct on a real
   800×600 kiosk even before client_info has been reported. Scoped entirely to
   the marker class so the full layout is untouched. The `.kasa--tiny` block
   below layers a second, tighter pass on top of this for very short panels
   (≤540 tall, e.g. 800×480).
   ============================================================ */
.kasa--compact { font-size:15px; }

/* left: karta zones */
.kasa--compact .kasa-zone--loyalty { padding:10px 22px 2px; }
.kasa--compact .kasa-zone--promos  { padding:4px 22px 12px; }
.kasa[data-mode="serving"].kasa--compact .kasa-stage--karta .kasa-zone--media { padding:4px 22px 8px; }
.kasa--compact .kasa-loyalty--karta { padding:11px 15px; border-radius:16px; }
.kasa--compact .kasa-logo--loyalty .kasa-logo__art { height:24px; }
.kasa--compact .kasa-loyalty--karta .kasa-loyalty__eyebrow { font-size:9px; padding:4px 9px; }
.kasa--compact .kasa-loyalty--karta .kasa-loyalty__grid { gap:13px; margin-top:9px; }
.kasa--compact .kasa-loyalty--karta .kasa-loyalty__title { font-size:17px; }
.kasa--compact .kasa-loyalty--karta .kasa-loyalty__sub { font-size:12px; margin-top:5px; line-height:1.3; }
/* card visual */
.kasa--compact .kasa-cardvis { width:104px; gap:7px; }
.kasa--compact .kasa-cardvis__plastic { width:104px; height:66px; border-radius:11px; }
.kasa--compact .kasa-cardvis__chip { left:11px; top:24px; width:21px; height:15px; }
.kasa--compact .kasa-cardvis__brand { left:11px; top:8px; font-size:12px; }
.kasa--compact .kasa-cardvis__check { width:24px; height:24px; font-size:13px; }
.kasa--compact .kasa-scan { font-size:12px; }
/* elki tokens */
.kasa--compact .elki-row { gap:7px; margin-top:9px; }
.kasa--compact .elki { width:31px; height:31px; }
.kasa--compact .elki svg { width:17px; height:17px; }
.kasa--compact .elki-count b { font-size:24px; }
.kasa--compact .elki-count span { font-size:12px; }
/* regret ledger */
.kasa--compact .kasa-ledger { margin-top:9px; gap:6px; }
.kasa--compact .kasa-ledger__row { grid-template-columns:26px 1fr auto; gap:9px; padding:7px 10px; border-radius:11px; }
.kasa--compact .kasa-ledger__ico { width:26px; height:26px; font-size:13px; }
.kasa--compact .kasa-ledger__ico--leaf svg { width:15px; height:15px; }
.kasa--compact .kasa-ledger__txt { font-size:11.5px; line-height:1.2; }
.kasa--compact .kasa-ledger__amt { font-size:15px; }
/* reward progress */
.kasa--compact .kasa-reward { margin-top:9px; padding:10px 13px; }
.kasa--compact .kasa-reward__lead { font-size:12px; }
.kasa--compact .kasa-loyalty--karta .kasa-meter { margin-top:7px; height:8px; }
.kasa--compact .kasa-loyalty--karta .kasa-meter__row { margin-top:5px; font-size:11.5px; }
/* compact banner (promos piled up) */
.kasa--compact .kasa-loyalty--karta[data-size="compact"] { padding:10px 14px; }
.kasa--compact .kasa-loyalty__compact { gap:12px; }
.kasa--compact .kasa-compact__card { width:66px; height:42px; }
.kasa--compact .kasa-compact__title { font-size:16px; }
.kasa--compact .kasa-compact__earned b { font-size:21px; }
/* summary medal (card checkout) */
.kasa--compact .kasa-loyalty--karta[data-size="summary"] { padding:12px 18px 14px; }
.kasa--compact .kasa-medal__lead { font-size:19px; margin-top:8px; }
.kasa--compact .kasa-medal__stage { width:124px; height:124px; margin:6px auto 0; }
.kasa--compact .kasa-medal__disc { width:86px; height:86px; }
.kasa--compact .kasa-medal__num { font-size:38px; }
.kasa--compact .kasa-medal__disc svg { width:22px; height:22px; top:7px; right:8px; }
.kasa--compact .kasa-medal__unit { font-size:18px; margin-top:5px; }
.kasa--compact .kasa-medal__done { margin-top:9px; font-size:11.5px; padding:5px 11px; }
.kasa--compact .kasa-medal__rays { -webkit-mask:radial-gradient(circle, transparent 38px, #000 40px, #000 60px, transparent 62px); mask:radial-gradient(circle, transparent 38px, #000 40px, #000 60px, transparent 62px); }

/* promo cards */
.kasa--compact .kasa-promos { gap:7px; }
.kasa--compact .kasa-promo { gap:11px; padding:8px 12px; border-radius:13px; }
.kasa--compact .kasa-promo__icon { width:36px; height:36px; font-size:19px; border-radius:11px; }
.kasa--compact .kasa-promo__title { font-size:15px; }
.kasa--compact .kasa-promo--strip .kasa-promo__title { font-size:14px; }
.kasa--compact .kasa-promo__note { font-size:11px; margin-top:3px; }
.kasa--compact .kasa-promo__reward-amt { font-size:20px; }
.kasa--compact .kasa-price__now b { font-size:24px; }

/* right: receipt panel (shared by all .kasa themes) */
.kasa--compact .kasa-cart { gap:12px; padding:16px 22px 12px; }
.kasa--compact .kasa-cart__icon { width:42px; height:42px; border-radius:12px; }
.kasa--compact .kasa-cart__icon svg { width:23px; height:23px; }
.kasa--compact .kasa-cart__count b { font-size:32px; }
.kasa--compact .kasa-cart__count span { font-size:14px; }
.kasa--compact .kasa-cart__loyalty { gap:4px; }
.kasa--compact .kasa-cart__loyalty-caption { font-size:9px; letter-spacing:0.1em; }
.kasa--compact .kasa-logo--receipt .kasa-logo__art { height:30px; }
.kasa--compact .kasa-logo--receipt .kasa-logo__word { font-size:17px; }
.kasa--compact .kasa-lines { padding:9px 20px 6px; }
.kasa--compact .kasa-line { padding:11px 0 10px; }
.kasa--compact .kasa-line__head { grid-template-columns:24px 1fr auto; gap:10px; }
.kasa--compact .kasa-line__name { font-size:16px; }
.kasa--compact .kasa-line__total { font-size:16px; }
.kasa--compact .kasa-line__total.struck { font-size:14px; }
.kasa--compact .kasa-line__sub { margin:6px 0 0 34px; gap:4px; }
.kasa--compact .kasa-line__row { font-size:13px; }
.kasa--compact .kasa-line__row.final { font-size:14px; }
.kasa--compact .kasa-foot { padding:12px 22px 16px; gap:9px; }
.kasa--compact .kasa-foot__pre { font-size:14px; }
.kasa--compact .kasa-foot__pre .v { font-size:15px; }
.kasa--compact .kasa-savings { gap:12px; padding:11px 14px; border-radius:15px; }
.kasa--compact .kasa-wallet { width:50px; height:46px; }
.kasa--compact .kasa-savings__label { font-size:15px; }
.kasa--compact .kasa-savings__amount { font-size:25px; }
.kasa--compact .kasa-pay { gap:11px; padding:13px 18px; border-radius:16px; }
.kasa--compact .kasa-pay__label { font-size:14px; }
.kasa--compact .kasa-pay__amount { font-size:28px; }
.kasa--compact .kasa-pay__arrow { width:36px; height:36px; }
.kasa--compact .kasa-pay__arrow svg { width:18px; height:18px; }

/* summary card ("Dziękujemy") */
.kasa--compact .kasa-summary { padding:14px; }
.kasa--compact .kasa-card { width:min(440px,94%); padding:20px 30px 18px; gap:10px; border-radius:18px; }
.kasa--compact .kasa-card__thanks { font-size:clamp(30px,7vw,44px); }
.kasa--compact .kasa-card__sub { font-size:12px; letter-spacing:0.2em; }
.kasa--compact .kasa-card__savings { margin:2px auto; padding:16px 22px 14px; border-radius:16px; gap:7px; }
.kasa--compact .kasa-card__savings .big-wallet { width:64px; height:58px; }
.kasa--compact .kasa-card__savings-label { font-size:17px; }
.kasa--compact .kasa-card__savings-amount { font-size:clamp(34px,8vw,48px); }
.kasa--compact .kasa-card__total-label { font-size:13px; }
.kasa--compact .kasa-card__total { font-size:clamp(40px,11vw,60px); }
.kasa--compact .kasa-card__rows { gap:8px; padding-top:14px; }
.kasa--compact .kasa-card__row dt { font-size:13px; }
.kasa--compact .kasa-card__row dd { font-size:15px; }
.kasa--compact .kasa-card__welcome { padding-top:12px; font-size:17px; }
.kasa--compact .kasa-logo--summary .kasa-logo__art { height:clamp(32px,7vw,44px); }

/* ============================================================
   EXTRA-COMPACT DENSITY — very short kiosks (≤540 tall; e.g. 800×480). LAYERS
   on `.kasa--compact` (the live kiosk + lab apply both marks together), so it
   only needs to re-tighten what still overflows at 480 — every property it
   doesn't restate keeps its compact value. Each rule mirrors a `.kasa--compact`
   selector with `--tiny` swapped in: equal specificity, so it wins purely by
   coming later in the file (this block must stay AFTER the compact one). Set
   from Device#tiny_screen? and reconciled live by kasa(_live)_controller.
   ============================================================ */
.kasa--tiny { font-size:13.5px; }

/* left: karta zones */
.kasa--tiny .kasa-zone--loyalty { padding:7px 18px 2px; }
.kasa--tiny .kasa-zone--promos  { padding:3px 18px 8px; }
.kasa[data-mode="serving"].kasa--tiny .kasa-stage--karta .kasa-zone--media { padding:3px 18px 6px; }
.kasa--tiny .kasa-loyalty--karta { padding:8px 13px; border-radius:13px; }
.kasa--tiny .kasa-logo--loyalty .kasa-logo__art { height:20px; }
.kasa--tiny .kasa-loyalty--karta .kasa-loyalty__eyebrow { font-size:8px; padding:3px 7px; }
.kasa--tiny .kasa-loyalty--karta .kasa-loyalty__grid { gap:10px; margin-top:6px; }
.kasa--tiny .kasa-loyalty--karta .kasa-loyalty__title { font-size:15px; }
.kasa--tiny .kasa-loyalty--karta .kasa-loyalty__sub { font-size:11px; margin-top:3px; line-height:1.25; }
/* card visual */
.kasa--tiny .kasa-cardvis { width:88px; gap:5px; }
.kasa--tiny .kasa-cardvis__plastic { width:88px; height:56px; border-radius:9px; }
.kasa--tiny .kasa-cardvis__chip { left:9px; top:20px; width:18px; height:13px; }
.kasa--tiny .kasa-cardvis__brand { left:9px; top:7px; font-size:10px; }
.kasa--tiny .kasa-cardvis__check { width:20px; height:20px; font-size:11px; }
.kasa--tiny .kasa-scan { font-size:11px; }
/* elki tokens */
.kasa--tiny .elki-row { gap:5px; margin-top:6px; }
.kasa--tiny .elki { width:26px; height:26px; }
.kasa--tiny .elki svg { width:14px; height:14px; }
.kasa--tiny .elki-count b { font-size:20px; }
.kasa--tiny .elki-count span { font-size:11px; }
/* regret ledger */
.kasa--tiny .kasa-ledger { margin-top:6px; gap:4px; }
.kasa--tiny .kasa-ledger__row { grid-template-columns:22px 1fr auto; gap:7px; padding:5px 8px; border-radius:9px; }
.kasa--tiny .kasa-ledger__ico { width:22px; height:22px; font-size:11px; }
.kasa--tiny .kasa-ledger__ico--leaf svg { width:13px; height:13px; }
.kasa--tiny .kasa-ledger__txt { font-size:10.5px; line-height:1.2; }
.kasa--tiny .kasa-ledger__amt { font-size:13px; }
/* reward progress */
.kasa--tiny .kasa-reward { margin-top:6px; padding:8px 10px; }
.kasa--tiny .kasa-reward__lead { font-size:11px; }
.kasa--tiny .kasa-loyalty--karta .kasa-meter { margin-top:5px; height:7px; }
.kasa--tiny .kasa-loyalty--karta .kasa-meter__row { margin-top:4px; font-size:10.5px; }
/* compact banner (promos piled up) */
.kasa--tiny .kasa-loyalty--karta[data-size="compact"] { padding:8px 12px; }
.kasa--tiny .kasa-loyalty__compact { gap:9px; }
.kasa--tiny .kasa-compact__card { width:56px; height:36px; }
.kasa--tiny .kasa-compact__title { font-size:14px; }
.kasa--tiny .kasa-compact__earned b { font-size:18px; }
/* summary medal (card checkout) */
.kasa--tiny .kasa-loyalty--karta[data-size="summary"] { padding:10px 14px 11px; }
.kasa--tiny .kasa-medal__lead { font-size:16px; margin-top:6px; }
.kasa--tiny .kasa-medal__stage { width:100px; height:100px; margin:4px auto 0; }
.kasa--tiny .kasa-medal__disc { width:70px; height:70px; }
.kasa--tiny .kasa-medal__num { font-size:31px; }
.kasa--tiny .kasa-medal__disc svg { width:18px; height:18px; top:6px; right:7px; }
.kasa--tiny .kasa-medal__unit { font-size:15px; margin-top:4px; }
.kasa--tiny .kasa-medal__done { margin-top:7px; font-size:10.5px; padding:4px 9px; }
.kasa--tiny .kasa-medal__rays { -webkit-mask:radial-gradient(circle, transparent 31px, #000 33px, #000 50px, transparent 52px); mask:radial-gradient(circle, transparent 31px, #000 33px, #000 50px, transparent 52px); }

/* promo cards */
.kasa--tiny .kasa-promos { gap:5px; }
.kasa--tiny .kasa-promo { gap:9px; padding:6px 10px; border-radius:11px; }
.kasa--tiny .kasa-promo__icon { width:30px; height:30px; font-size:16px; border-radius:9px; }
.kasa--tiny .kasa-promo__title { font-size:13.5px; }
.kasa--tiny .kasa-promo--strip .kasa-promo__title { font-size:12.5px; }
.kasa--tiny .kasa-promo__note { font-size:10px; margin-top:2px; }
.kasa--tiny .kasa-promo__reward-amt { font-size:17px; }
.kasa--tiny .kasa-price__now b { font-size:20px; }

/* right: receipt panel (shared by all .kasa themes) */
.kasa--tiny .kasa-cart { gap:10px; padding:11px 18px 9px; }
.kasa--tiny .kasa-cart__icon { width:36px; height:36px; border-radius:10px; }
.kasa--tiny .kasa-cart__icon svg { width:20px; height:20px; }
.kasa--tiny .kasa-cart__count b { font-size:27px; }
.kasa--tiny .kasa-cart__count span { font-size:12px; }
.kasa--tiny .kasa-cart__loyalty-caption { font-size:8px; }
.kasa--tiny .kasa-logo--receipt .kasa-logo__art { height:25px; }
.kasa--tiny .kasa-logo--receipt .kasa-logo__word { font-size:15px; }
.kasa--tiny .kasa-lines { padding:6px 16px 4px; }
.kasa--tiny .kasa-line { padding:8px 0 7px; }
.kasa--tiny .kasa-line__head { grid-template-columns:20px 1fr auto; gap:8px; }
.kasa--tiny .kasa-line__name { font-size:14px; }
.kasa--tiny .kasa-line__total { font-size:14px; }
.kasa--tiny .kasa-line__total.struck { font-size:12.5px; }
.kasa--tiny .kasa-line__sub { margin:4px 0 0 28px; gap:3px; }
.kasa--tiny .kasa-line__row { font-size:12px; }
.kasa--tiny .kasa-line__row.final { font-size:12.5px; }
.kasa--tiny .kasa-foot { padding:9px 18px 11px; gap:6px; }
.kasa--tiny .kasa-foot__pre { font-size:12.5px; }
.kasa--tiny .kasa-foot__pre .v { font-size:13px; }
.kasa--tiny .kasa-savings { gap:9px; padding:8px 11px; border-radius:12px; }
.kasa--tiny .kasa-wallet { width:42px; height:39px; }
.kasa--tiny .kasa-savings__label { font-size:13px; }
.kasa--tiny .kasa-savings__amount { font-size:21px; }
.kasa--tiny .kasa-pay { gap:9px; padding:10px 14px; border-radius:13px; }
.kasa--tiny .kasa-pay__label { font-size:12.5px; }
.kasa--tiny .kasa-pay__amount { font-size:23px; }
.kasa--tiny .kasa-pay__arrow { width:30px; height:30px; }
.kasa--tiny .kasa-pay__arrow svg { width:15px; height:15px; }

/* summary card ("Dziękujemy") */
.kasa--tiny .kasa-summary { padding:10px; }
.kasa--tiny .kasa-card { width:min(380px,94%); padding:15px 24px 14px; gap:7px; border-radius:15px; }
.kasa--tiny .kasa-card__thanks { font-size:clamp(24px,6vw,36px); }
.kasa--tiny .kasa-card__sub { font-size:11px; letter-spacing:0.18em; }
.kasa--tiny .kasa-card__savings { margin:2px auto; padding:12px 18px 11px; border-radius:13px; gap:5px; }
.kasa--tiny .kasa-card__savings .big-wallet { width:52px; height:47px; }
.kasa--tiny .kasa-card__savings-label { font-size:14px; }
.kasa--tiny .kasa-card__savings-amount { font-size:clamp(28px,7vw,40px); }
.kasa--tiny .kasa-card__total-label { font-size:12px; }
.kasa--tiny .kasa-card__total { font-size:clamp(32px,9vw,48px); }
.kasa--tiny .kasa-card__rows { gap:6px; padding-top:10px; }
.kasa--tiny .kasa-card__row dt { font-size:12px; }
.kasa--tiny .kasa-card__row dd { font-size:13px; }
.kasa--tiny .kasa-card__welcome { padding-top:9px; font-size:14px; }
.kasa--tiny .kasa-logo--summary .kasa-logo__art { height:clamp(26px,6vw,36px); }

/* ---- lab chrome (operator-only) ---- */
.kasa-lab { position:relative; width:100vw; height:100vh; overflow:hidden; background:#0c0d0a; }
.kasa-lab__close { position:absolute; top:16px; right:18px; z-index:60; width:40px; height:40px; display:grid; place-items:center; border-radius:50%; background:rgba(0,0,0,0.55); color:#fff; text-decoration:none; }
/* flex-wrap + a viewport-bounded max-width keep every control reachable (and the
   page free of horizontal overflow) when the row is wider than a phone viewport. */
.kasa-dock { position:fixed; left:50%; bottom:18px; transform:translateX(-50%); z-index:60; display:flex; flex-wrap:wrap; justify-content:center; gap:8px; max-width:calc(100vw - 24px); padding:8px; border-radius:16px; background:rgba(12,13,10,0.82); backdrop-filter:blur(10px); box-shadow:0 12px 30px -10px rgba(0,0,0,0.6); }
.kasa-dock button { font-family:var(--k-ui); font-size:13px; font-weight:600; color:#f3f1e8; background:rgba(255,255,255,0.08); border:1px solid rgba(255,255,255,0.12); padding:9px 16px; border-radius:10px; cursor:pointer; }
.kasa-dock button:hover { background:rgba(255,255,255,0.16); }
.kasa-dock button.accent { background:var(--brand); border-color:var(--brand-bright); }
.kasa-dock__label { color:rgba(243,241,232,0.5); font-size:11px; align-self:center; padding:0 8px 0 4px; letter-spacing:0.04em; }
.kasa-dock__sep { width:1px; background:rgba(255,255,255,0.15); margin:4px 2px; }
/* Touch operators: the dock controls (density / theme / preview) need a ~44px
   tap target on coarse pointers — the default 13px/9px sizing is ~36px tall. */
@media (hover: none) and (pointer: coarse) {
  .kasa-dock button { min-height:44px; padding-top:11px; padding-bottom:11px; }
}

/* ============================================================
   Inventory ("Inwentarz") — fleet hardware & telemetry stats.
   Custom CSS/SVG charts (no chart library); reuses the dashboard
   palette + breakpoints (880 / 640). See app/views/inventory/.
   ============================================================ */

/* Small annotation next to a section header / under a chart */
.inv-note { font-size: 12.5px; color: var(--text-secondary); }
.inv-note--block { display: block; margin-top: 14px; max-width: 70ch; line-height: 1.5; }

.inv-empty {
  margin: 0;
  padding: 22px 0;
  color: var(--text-secondary);
  font-size: 13.5px;
}

/* ---- Horizontal bar list (resolutions, scale model/transport/state) ---- */
.inv-bars { list-style: none; margin: 18px 0 0; padding: 0; display: flex; flex-direction: column; gap: 12px; }
.inv-bar {
  display: grid;
  grid-template-columns: 140px 1fr 48px 56px;
  align-items: center;
  gap: 12px;
}
.inv-bar__label { font-size: 13px; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.inv-bar__track { position: relative; height: 10px; border-radius: 999px; background: var(--gray-100); overflow: hidden; }
.inv-bar__fill {
  position: absolute; inset: 0 auto 0 0;
  height: 100%;
  min-width: 3px;
  border-radius: 999px;
  background: var(--blue);
  transition: width 0.5s cubic-bezier(0.22, 1, 0.36, 1);
}
.inv-bar__value { font-size: 13.5px; font-weight: 600; text-align: right; font-variant-numeric: tabular-nums; }
.inv-bar__pct { font-size: 12.5px; color: var(--text-secondary); text-align: right; font-variant-numeric: tabular-nums; }

/* ---- Card grid for OS donuts + scale breakdowns ---- */
.inv-os-grid {
  margin-top: 18px;
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 16px;
}
.inv-card {
  border: 1px solid var(--border);
  border-radius: 14px;
  background: #fff;
  padding: 18px 20px 20px;
}
.inv-card__title { font-size: 13.5px; font-weight: 600; color: var(--text); margin-bottom: 6px; }

/* ---- SVG donut + legend ---- */
.inv-donut-wrap { display: flex; align-items: center; gap: 20px; flex-wrap: wrap; margin-top: 10px; }
.inv-donut { width: 120px; height: 120px; flex-shrink: 0; }
.inv-donut circle { transition: stroke-dasharray 0.6s cubic-bezier(0.22, 1, 0.36, 1); }
.inv-donut__center { font-size: 26px; font-weight: 600; fill: var(--text); font-variant-numeric: tabular-nums; }

.inv-legend { list-style: none; margin: 0; padding: 0; flex: 1 1 200px; min-width: 180px; display: flex; flex-direction: column; gap: 8px; }
.inv-legend__item { display: grid; grid-template-columns: 12px 1fr 40px 52px; align-items: center; gap: 10px; }
.inv-legend__dot { width: 12px; height: 12px; border-radius: 4px; }
.inv-legend__label { font-size: 13px; color: var(--text); }
.inv-legend__value { font-size: 13px; font-weight: 600; text-align: right; font-variant-numeric: tabular-nums; }
.inv-legend__pct { font-size: 12.5px; color: var(--text-secondary); text-align: right; font-variant-numeric: tabular-nums; }

@media (max-width: 880px) {
  .inv-os-grid { grid-template-columns: 1fr; }
}

@media (max-width: 640px) {
  .inv-bar { grid-template-columns: 110px 1fr 40px 48px; gap: 8px; }
  .inv-bar__label { font-size: 12px; }
  .inv-donut-wrap { gap: 14px; }
  .inv-donut { width: 104px; height: 104px; }
}

/* ===== Location editor / preview (tabbed) ===== */

/* The editor (6 tabs) and preview (up to 8) outgrow a phone width, so the tab
   strip scrolls horizontally rather than wrapping or pushing the page wide. */
.tabs--scroll {
  overflow-x: auto;
  flex-wrap: nowrap;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
}
.tabs--scroll::-webkit-scrollbar { display: none; }
.tabs--scroll .tabs__tab { flex: 0 0 auto; white-space: nowrap; }

/* First heading in a panel shouldn't inherit the big inter-section gap that
   dash-section / form-section carry when stacked down a page. */
.tabs__panel > .form-section__title:first-child,
.tabs__panel > .dash-section:first-child,
.tabs__panel > section:first-child { margin-top: 0; }

/* A divider between two groups inside one tab panel (device photos under the
   location photo; modules under the device table). */
.form-subsection {
  margin-top: 28px;
  padding-top: 24px;
  border-top: 1px solid var(--border);
}

/* Two-column field grid for the Dane tab; collapses on a phone. */
.form-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 2px 24px;
}
.form-grid > p { margin: 8px 0; }
.form-grid__wide { grid-column: 1 / -1; }
@media (max-width: 640px) {
  .form-grid { grid-template-columns: 1fr; }
}

.form-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 24px;
}

/* Map tab: an address echo bar above the map (the "repeated address"). */
.map-tab__address {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin-bottom: 4px;
  font-size: 14px;
}
.map-tab__address > svg { color: var(--brand-red); flex: 0 0 auto; }
.map-tab__address > span { flex: 1 1 200px; min-width: 0; }
.map-tab__address .btn { flex: 0 0 auto; }

/* ===== Instant photo widget (location + per-device) ===== */
.photo-single { max-width: 440px; }

.photo-tile {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--white);
}
.photo-tile--error { border-color: var(--brand-red); }

.photo-tile__frame {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  aspect-ratio: 4 / 3;
  overflow: hidden;
  border: 1.5px dashed var(--gray-200);
  border-radius: var(--radius-sm);
  background: var(--gray-50);
  color: var(--text-secondary);
}
.photo-tile__frame--filled { border-style: solid; background: var(--white); }
.photo-tile__frame img { width: 100%; height: 100%; object-fit: cover; display: block; }

.photo-tile__placeholder {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  font-size: 12px;
}

.photo-tile__spinner {
  display: none;
  position: absolute;
  top: 50%;
  left: 50%;
  width: 26px;
  height: 26px;
  margin: -13px 0 0 -13px;
  border: 3px solid rgba(35, 31, 32, 0.15);
  border-top-color: var(--brand-red);
  border-radius: 50%;
  animation: spin 0.7s linear infinite;
}
.photo-tile--busy .photo-tile__frame { opacity: 0.5; }
.photo-tile--busy .photo-tile__spinner { display: block; }

.photo-tile__meta { display: flex; flex-direction: column; gap: 2px; }
.photo-tile__title { font-size: 13px; font-weight: 600; line-height: 1.3; }
.photo-tile__subtitle { font-size: 12px; color: var(--text-secondary); }
.photo-tile__error { margin: 0; font-size: 12px; color: var(--brand-red); }
.photo-tile__actions { display: flex; flex-wrap: wrap; gap: 6px; }

/* ===== Read-only preview media + pills + module status (show page) ===== */
.preview-photo {
  display: block;
  max-width: 100%;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
}

.preview-photo-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
  gap: 14px;
  margin-top: 12px;
}
.preview-photo-grid__item { margin: 0; }
.preview-photo-grid__item img {
  display: block;
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
}
.preview-photo-grid__item figcaption {
  margin-top: 6px;
  font-size: 12px;
  color: var(--text-secondary);
}

.pill-row { display: flex; flex-wrap: wrap; gap: 8px; }

.module-status-list { display: flex; flex-direction: column; gap: 10px; }
.module-status {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 12px;
  padding: 12px 14px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--white);
}
.module-status__icon { display: flex; color: var(--text-secondary); }
.module-status__name { flex: 1 1 auto; font-weight: 600; }
/* Configure / activate buttons in the preview module list — sit at the row end,
   wrap below the name on narrow (phone) widths instead of overflowing. */
.module-status__actions { margin-left: auto; }

/* Per-device curation cards (preview): photo + categories in one place. */
.device-curation-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: 16px;
  margin-top: 12px;
}
.device-curation-card {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--white);
}
/* The photo tile drops its own chrome inside the card — the card is the frame. */
.device-curation-card .photo-tile {
  padding: 0;
  border: none;
  background: transparent;
}
.device-cat-fields {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding-top: 12px;
  border-top: 1px solid var(--border);
}
.device-cat-widget--busy {
  opacity: 0.5;
  pointer-events: none;
}
.device-cat-widget__error {
  display: none;
  margin: 8px 0 0;
  color: var(--danger, #c0392b);
  font-size: 0.85rem;
}
.device-cat-widget--error .device-cat-widget__error {
  display: block;
}
