@font-face {
  font-family: "Fraunces";
  font-style: normal;
  font-weight: 300 900;
  font-display: swap;
  src: url(fonts/Fraunces-normal-latin-ext.woff2) format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+2020, U+20A0-20AB, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Fraunces";
  font-style: normal;
  font-weight: 300 900;
  font-display: swap;
  src: url(fonts/Fraunces-normal-latin.woff2) format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Schibsted Grotesk";
  font-style: normal;
  font-weight: 400 900;
  font-display: swap;
  src: url(fonts/SchibstedGrotesk-normal-latin-ext.woff2) format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+2020, U+20A0-20AB, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Schibsted Grotesk";
  font-style: normal;
  font-weight: 400 900;
  font-display: swap;
  src: url(fonts/SchibstedGrotesk-normal-latin.woff2) format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

html { font-size: 100%; }

:root {
  /* Tło i powierzchnie */
  --bg: #EAE7F1;
  --surface: #FFFFFF;
  --surface-2: #F5F3F9;
  --ink: #1D053C;
  --ink-deep: #12022A;

  /* Tekst */
  --text-1: var(--ink);
  --text-2: #4A3A5E;
  --ink-2: var(--text-2);
  --mut: #6E5D80;
  --on-dark: #F3F2F7;
  --on-dark-2: rgba(243, 242, 247, .9);

  /* Marka Zeelandii — bakłażan i żółty z zeelandia.pl */
  --brand: #1D053C;            /* 18,4:1 na bieli — kolor marki, tekstu i akcji drugiego planu */
  --brand-deep: #12022A;
  --brand-soft: #EBEAF1;       /* ich szarość z --bs-secondary */
  --brand-text: #1D053C;
  --grad-brand:
    radial-gradient(120% 140% at 88% -20%, rgba(255, 228, 2, .20), transparent 56%),
    linear-gradient(158deg, #2E0B5C, var(--brand-deep) 78%);

  /* Żółty — kolor akcji i sygnału, zawsze pod ciemnym tekstem (14,3:1) */
  --accent: #FFE402;
  --accent-soft: #FFF6C2;
  --on-accent: #1D053C;
  --warn: #7A5E00;             /* 6,1:1 na bieli */
  --low: #8A6B00;
  --accent-on-dark: #FFE402;

  /* Dostępność — jedyny kolor spoza marki, bo zielona kropka „dostępny" to konwencja */
  --ok: #146B4E;               /* 6,5:1 na bieli */
  --ok-soft: #E3F1EB;

  /* Błąd */
  --danger: #B3261E;
  --danger-soft: #FBE7E5;

  /* Linie */
  --line-soft: #EAE8F0;
  --line: #DFDCE8;
  --line-mid: #C3BDD1;
  --line-strong: #8579A0;
  --switch-off: #9990AB;

  /* Typografia */
  --t-11: .6875rem;
  --t-12: .75rem;
  --t-13: .8125rem;
  --t-15: .9375rem;
  --t-17: 1.0625rem;
  --t-20: 1.25rem;
  --t-24: 1.5rem;
  --t-28: 1.75rem;
  --t-36: 2.25rem;
  --font-ui: "Schibsted Grotesk", "Segoe UI", system-ui, -apple-system, sans-serif;
  --font-display: "Fraunces", Georgia, serif;
  --lh-display: 1.1;
  --lh-tight: 1.25;
  --lh-body: 1.5;
  --ls-display: -.02em;
  --ls-eyebrow: .08em;

  /* Siatka 4 px */
  --s-1: 4px;
  --s-2: 8px;
  --s-3: 12px;
  --s-4: 16px;
  --s-5: 20px;
  --s-6: 24px;
  --s-7: 32px;
  --s-8: 40px;
  --s-9: 48px;
  --gutter: var(--s-4);

  /* Promienie */
  --r-1: 8px;
  --r-2: 12px;
  --r-3: 16px;
  --r-4: 20px;
  --r-5: 28px;
  --r-pill: 999px;

  /* Elewacja */
  /* Kreska sama nie oddzielała białej karty od jasnego tła — stąd wrażenie,
     że wszystko się zlewa. Cień jest w tonie marki, nie neutralnie szary. */
  --hairline:
    inset 0 0 0 1px var(--line-soft),
    0 1px 2px rgba(29, 5, 60, .05),
    0 6px 16px rgba(29, 5, 60, .05);
  --sh-1: 0 1px 2px rgba(29, 5, 60, .07), 0 4px 14px rgba(29, 5, 60, .06);
  --sh-2: 0 2px 6px rgba(29, 5, 60, .09), 0 16px 38px rgba(29, 5, 60, .12);
  --sh-3: 0 -2px 8px rgba(29, 5, 60, .07), 0 -20px 60px rgba(29, 5, 60, .18);

  /* Ruch */
  --dur-1: 120ms;
  --dur-2: 220ms;
  --dur-3: 360ms;
  --ease-out: cubic-bezier(.2, .7, .2, 1);
  --ease-in: cubic-bezier(.4, 0, 1, 1);
  --ease-spring: cubic-bezier(.3, 1.4, .4, 1);

  /* Cele dotyku */
  --hit: 48px;
  --hit-row: 44px;
  --btn-h: 52px;
  --nav-h: 64px;
  --orb: 56px;

  --focus-ring: 0 0 0 3px var(--brand);
  --sat: env(safe-area-inset-top, 0px);
  --sab: env(safe-area-inset-bottom, 0px);
}

* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }

html, body { margin: 0; height: 100%; overscroll-behavior-y: none; }

body {
  background: var(--bg);
  color: var(--text-1);
  font-family: var(--font-ui);
  font-size: var(--t-15);
  line-height: var(--lh-body);
  -webkit-font-smoothing: antialiased;
  font-optical-sizing: auto;
}

button, input, select, textarea { font: inherit; color: inherit; }
button { border: 0; background: none; padding: 0; cursor: pointer; }
a { color: inherit; text-decoration: none; }
ul, ol { margin: 0; padding: 0; list-style: none; }
dl, dd { margin: 0; }
h1, h2, h3, p { margin: 0; }
img, svg { display: block; }

button, [data-act], .chip, .prod, .opt { touch-action: manipulation; }
.stepper button, .chip, .tab { user-select: none; -webkit-user-select: none; -webkit-touch-callout: none; }

:focus-visible { outline: none; box-shadow: var(--focus-ring); border-radius: var(--r-1); }

.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* Wagę niosą wszystkie kwoty. */
.tnum { font-weight: 600; }

/* Cyfry tabularne wyłącznie tam, gdzie treść jest czysto liczbowa. Schibsted
   Grotesk w wariancie tabularnym rozsuwa też przecinek i kropkę na szerokość
   cyfry, więc z „138,60 zł" robi się „138 , 60 zł", a z e-maila „zlotyklos . pl".
   Kolumny kwot trzyma równo wyrównanie do prawej, nie krój. */
.stepper .st-ile,
.ean,
.blik-input { font-variant-numeric: tabular-nums; }

.eyebrow {
  font-size: var(--t-11); font-weight: 700;
  letter-spacing: var(--ls-eyebrow); text-transform: uppercase;
  line-height: 1.2;
}

/* ---------- Rama aplikacji ---------- */

#app {
  position: fixed; inset: 0;
  display: flex; flex-direction: column;
  max-width: 560px; margin-inline: auto;
  background: var(--bg);
  overflow: hidden;
}

.widoki { flex: 1; position: relative; min-height: 0; }

.view {
  position: absolute; inset: 0;
  overflow-y: auto; overflow-x: hidden;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
  scrollbar-width: none;
}
.view::-webkit-scrollbar { display: none; }
.view[hidden] { display: none; }


@keyframes rise { from { opacity: 0; transform: translateY(14px) scale(.985); } to { opacity: 1; transform: none; } }

.pad { padding-inline: var(--gutter); }
.stack > * + * { margin-top: var(--s-3); }
.spacer-nav { height: var(--s-6); }
.spacer-sheet { height: var(--s-5); }


.offline {
  flex: none;
  padding: var(--s-2) var(--gutter);
  text-align: center;
  font-size: var(--t-12); font-weight: 600;
  background: var(--accent-soft); color: var(--warn);
}
.offline[data-ton="online"] { background: var(--brand-soft); color: var(--brand-text); }
.offline[hidden] { display: none; }

/* ---------- Atrapa telefonu na tablecie ---------- */
/* Tylko do 1039 px; szerzej wchodzi układ desktopowy na dole pliku. */

@media (min-width: 620px) and (max-width: 1039.98px) {
  body {
    background:
      radial-gradient(90% 80% at 80% 0%, rgba(255, 228, 2, .13), transparent 60%),
      var(--ink-deep);
  }
  #app {
    inset: 24px auto; left: 50%;
    transform: translateX(-50%);
    width: 420px; height: calc(100% - 48px);
    border-radius: 42px;
    box-shadow: 0 40px 120px rgba(0, 0, 0, .5), 0 0 0 10px #0E170F, 0 0 0 11px #2C3A2E;
  }
}

/* ---------- Nagłówki ---------- */

/* Belka konta jest paskiem aplikacji, nie wierszem treści: własne tło,
   kreska pod spodem i przyklejenie do góry przy przewijaniu. Bez tego
   awatar, nazwa i dzwonek unosiły się nad szarym tłem bez związku. */
.hello {
  position: sticky; top: 0; z-index: 40;
  display: flex; align-items: center; gap: var(--s-2);
  padding: calc(var(--sat) + var(--s-2)) var(--s-3) var(--s-2) var(--gutter);
  background: var(--surface);
  box-shadow: 0 1px 0 var(--line-soft);
}
.hello-konto {
  flex: 1; min-width: 0;
  display: flex; align-items: center; gap: var(--s-3);
  min-height: var(--hit); padding: 0; text-align: left;
  border-radius: var(--r-2);
}
.hello-konto:active { background: var(--bg); }
.avatar {
  width: 38px; height: 38px; flex: none;
  border-radius: var(--r-pill); overflow: hidden;
  display: grid; place-items: center;
  background: var(--brand-deep); color: var(--on-dark);
  font-size: var(--t-13); font-weight: 700; letter-spacing: .04em;
}
.avatar img { width: 100%; height: 100%; }
.hello .who { flex: 1; min-width: 0; }
.hello .who small {
  display: block; color: var(--mut); font-size: var(--t-12); line-height: 1.3;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.hello .who strong {
  display: block; font-size: var(--t-15); font-weight: 700; line-height: 1.25;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

.topbar {
  display: flex; align-items: center; gap: var(--s-3);
  padding: calc(var(--sat) + var(--s-3)) var(--gutter) var(--s-2);
}
.h1-page {
  flex: 1;
  font-family: var(--font-display); font-size: var(--t-24); font-weight: 600;
  letter-spacing: var(--ls-display); line-height: 1.15;
}

/* Dzwonek w belce jest ikoną, nie uniesionym kółkiem — biały krążek na białym
   pasku był cieniem bez powodu. Cień zostaje tam, gdzie dzwonek stoi na tle
   treści (pasek tytułu katalogu i zamówień). */
.bell {
  position: relative; flex: none;
  width: var(--hit); height: var(--hit);
  border-radius: var(--r-pill);
  display: grid; place-items: center;
  background: var(--surface); box-shadow: var(--sh-1);
  color: var(--text-2);
}
.hello .bell { background: none; box-shadow: none; color: var(--brand-deep); }
.hello .bell:active { background: var(--bg); }
.bell .dot {
  position: absolute; top: 11px; right: 12px;
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--accent); box-shadow: 0 0 0 2px var(--surface);
  animation: pop var(--dur-2) var(--ease-spring);
}
@keyframes pop { from { transform: scale(.4); } to { transform: scale(1); } }

.plist + .shead { margin-top: var(--s-6); }
.shead {
  display: flex; align-items: baseline; gap: var(--s-2);
  margin: var(--s-6) var(--gutter) var(--s-3);
}
.shead h2 {
  font-family: var(--font-display); font-size: var(--t-17);
  font-weight: 600; color: var(--text-1); letter-spacing: -.01em;
}
.shead .link, .shead-info { margin-left: auto; }
.shead-info { font-size: var(--t-12); color: var(--mut); }

.link {
  min-height: var(--hit-row); padding: 10px 12px; margin: -10px -12px;
  font-size: var(--t-13); font-weight: 600; color: var(--brand);
}
.link-danger { color: var(--danger); }
.link-sledz { display: block; margin: 2px -12px -10px; font-weight: 700; text-decoration: underline; }
.link-center { display: block; width: 100%; text-align: center; margin-top: var(--s-2); }

/* ---------- Karta „W drodze" ---------- */

/* Jedyna karta na starcie opisująca rzecz dziejącą się teraz — dostaje listwę
   marki, żeby nie ginęła w rzędzie białych kart. Żółć zostaje zarezerwowana
   dla presji czasu (cutoff, nieopłacona faktura). */
.card-w-drodze {
  position: relative; overflow: hidden;
  margin: var(--s-1) var(--gutter) var(--s-3);
  padding: var(--s-3) var(--s-4) var(--s-3) var(--s-5);
  border-radius: var(--r-4);
  background: var(--surface);
  box-shadow: var(--hairline);
  cursor: pointer;
  transition: transform var(--dur-1) var(--ease-out);
}
.card-w-drodze::before {
  content: ""; position: absolute; left: 0; top: 0; bottom: 0;
  width: 5px; background: var(--brand);
}
.card-w-drodze:active { transform: scale(.99); }
.wd-head { display: flex; align-items: center; gap: var(--s-2); }
.wd-head .eyebrow { color: var(--mut); }
.wd-head .pill { margin-left: auto; }
/* Kropka przy statusie pulsuje, dopóki zamówienie jest w toku. */
.wd-head .pill::before {
  content: ""; width: 7px; height: 7px; margin-right: 6px;
  border-radius: 50%; background: currentColor;
  animation: tetno 2s var(--ease-out) infinite;
}
.wd-head .pill { display: inline-flex; align-items: center; }
@keyframes tetno { 0%, 100% { opacity: 1; } 50% { opacity: .25; } }
@media (prefers-reduced-motion: reduce) { .wd-head .pill::before { animation: none; } }
.wd-nr {
  font-family: var(--font-display); font-size: var(--t-20); font-weight: 600;
  letter-spacing: var(--ls-display); margin-top: var(--s-1);
}
.wd-sub { font-size: var(--t-13); color: var(--text-2); margin-top: 2px; line-height: 1.35; }
.wd-stopka {
  display: flex; align-items: center; gap: var(--s-3);
  margin-top: var(--s-2); font-size: var(--t-13); color: var(--mut);
}
.wd-stopka .btn { margin-left: auto; width: auto; }

/* ---------- Hero „Ponów" ---------- */

.reorder {
  position: relative; overflow: hidden;
  margin: 0 var(--gutter);
  padding: var(--s-3) var(--s-4) var(--s-4);
  border-radius: var(--r-4);
  color: var(--on-dark);
  background: var(--grad-brand);
  box-shadow: var(--sh-2);
}
.reorder::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background-image: radial-gradient(rgba(255, 255, 255, .13) 1px, transparent 1px);
  background-size: 13px 13px; opacity: .34;
}
.reorder .lab { color: var(--on-dark-2); position: relative; }
.reorder .sum {
  position: relative;
  margin-top: var(--s-1);
  font-family: var(--font-display); font-size: var(--t-20); font-weight: 600;
  letter-spacing: var(--ls-display);
}
.reorder .sum-brutto { position: relative; font-size: var(--t-12); color: rgba(239, 233, 216, .8); }
.thumbs { position: relative; display: flex; gap: var(--s-2); margin: var(--s-2) 0 var(--s-3); }
.thumbs .ilu { opacity: .92; }
.thumbs .more {
  width: 40px; height: 40px; border-radius: var(--r-2);
  display: grid; place-items: center;
  font-size: var(--t-12); font-weight: 700;
  background: var(--bg); color: var(--brand-deep);
}
.reorder .btn { position: relative; }

/* ---------- Przyciski ---------- */

.btn {
  display: flex; align-items: center; justify-content: center; gap: var(--s-2);
  width: 100%; min-height: var(--btn-h);
  padding: 0 var(--s-4);
  border-radius: var(--r-2);
  font-size: var(--t-15); font-weight: 700; letter-spacing: -.01em;
  transition: transform var(--dur-1) var(--ease-out), background var(--dur-1) var(--ease-out);
}
.btn:active { transform: scale(.975); }
.btn + .btn { margin-top: var(--s-2); }

/* Trzy wagi i nic więcej. Żółty to akcja główna, oberżyna wypełniona to akcja
   druga, obrys to akcja poboczna. Wcześniej przyciski obok siebie miały różne
   grubości obrysu i różne tła, przez co „Ponów" czytał się jak wyłączony. */
.btn-akcja, .btn-jasny { background: var(--accent); color: var(--on-accent); }
.btn-akcja:active, .btn-jasny:active { background: #F2D800; }

.btn-marka, .btn-brand { background: var(--brand); color: var(--on-dark); }
.btn-marka:active, .btn-brand:active { background: var(--brand-deep); }

.btn-ghost, .btn-line {
  background: var(--surface); color: var(--brand-deep);
  box-shadow: inset 0 0 0 1.5px var(--line-mid);
}
.btn-ghost:active, .btn-line:active { background: var(--bg); box-shadow: inset 0 0 0 1.5px var(--line-strong); }

.btn-danger { background: var(--danger-soft); color: var(--danger); }
.btn-sm { min-height: var(--hit-row); width: auto; font-size: var(--t-13); padding: 0 var(--s-4); }
.btn[disabled] { background: var(--brand-soft); color: var(--mut); box-shadow: none; pointer-events: none; }

/* Rząd przycisków: równe szerokości i wspólny odstęp — reguła dla .acts
   stoi niżej, przy karcie zamówienia. */
.konto-stopka, .empty-akcje { gap: var(--s-3); }
.foot-rzad { display: flex; gap: var(--s-3); align-items: center; }
.foot-rzad .btn { margin-top: 0; }
.foot-rzad .btn:last-child { flex: 1; }
.foot-info { text-align: center; font-size: var(--t-13); color: var(--mut); }

.spin {
  width: 16px; height: 16px; border-radius: 50%;
  border: 2px solid rgba(29, 5, 60, .22); border-top-color: var(--brand-deep);
  animation: spin .7s linear infinite;
}
.spin.duzy { width: 28px; height: 28px; border-width: 3px; }
@keyframes spin { to { transform: rotate(360deg); } }

/* ---------- Limit i cutoff ---------- */

.limit-chip {
  display: block; width: calc(100% - 2 * var(--gutter));
  margin: var(--s-3) var(--gutter) 0;
  padding: var(--s-3) var(--s-4);
  border-radius: var(--r-3);
  background: var(--surface); box-shadow: var(--hairline);
  text-align: left;
}
.limit-tekst { font-size: var(--t-13); color: var(--text-2); }
.limit-tekst b { color: var(--brand); }
/* ---------- Pasek limitu w koszyku ---------- */

.limit-pasek {
  margin: var(--s-4) var(--gutter) var(--s-4);
  padding: var(--s-4);
  border-radius: var(--r-3);
  background: var(--surface); box-shadow: var(--hairline);
}
.lp-head { display: flex; align-items: baseline; gap: var(--s-3); }
.lp-lab { flex: 1; font-size: var(--t-13); color: var(--mut); }
.lp-kwota { font-size: var(--t-13); font-weight: 500; color: var(--mut); }
.lp-kwota b { font-size: var(--t-15); font-weight: 700; color: var(--brand-deep); }
.limit-pasek.nad .lp-kwota b { color: var(--danger); }
.limit-pasek.nad .lp-kwota { color: var(--danger); }

.lp-tor {
  position: relative; height: 10px; margin-top: var(--s-3);
  border-radius: var(--r-pill);
  background: var(--brand-soft); overflow: hidden;
}
/* Segmenty wyjeżdżają z lewej przy pierwszym rysowaniu — pasek, który od razu
   stoi pełny, nie mówi nic o proporcji; rosnący mówi. */
.lp-tor i {
  position: absolute; top: 0; bottom: 0;
  transform-origin: left center;
  animation: rozsun 560ms var(--ease-out) both;
}
.lp-koszyk { animation-delay: 160ms; }
@keyframes rozsun { from { transform: scaleX(0); } to { transform: scaleX(1); } }
/* Szerokość wjeżdża animacją, bo pasek zmienia się przy każdej zmianie ilości
   — skok bez ruchu czyta się jak przeładowanie widoku. */
.lp-zajete { left: 0; background: var(--brand); transition: width var(--dur-3) var(--ease-out); }
.lp-koszyk { background: var(--accent); transition: left var(--dur-3) var(--ease-out), width var(--dur-3) var(--ease-out); }
.limit-pasek.nad .lp-koszyk { background: var(--danger); }
@media (prefers-reduced-motion: reduce) {
  .lp-zajete, .lp-koszyk { transition: none; animation: none; }
}

.lp-legenda {
  display: flex; flex-wrap: wrap; gap: var(--s-1) var(--s-4);
  margin-top: var(--s-3);
  font-size: var(--t-12); color: var(--mut);
}
.lp-legenda span { display: inline-flex; align-items: center; gap: 6px; white-space: nowrap; }
.lp-kropka { width: 9px; height: 9px; border-radius: 3px; flex: none; }
.lp-k-zajete { background: var(--brand); }
.lp-k-koszyk { background: var(--accent); }
.lp-k-wolne { background: var(--brand-soft); box-shadow: inset 0 0 0 1px var(--line-mid); }

.lp-nota {
  display: flex; align-items: flex-start; gap: var(--s-2);
  margin-top: var(--s-3); padding-top: var(--s-3);
  border-top: 1px solid var(--line-soft);
  font-size: var(--t-13); color: var(--danger); line-height: 1.4;
}
.lp-nota b { font-weight: 700; }

.progress {
  display: block; height: 6px; margin-top: var(--s-2);
  border-radius: 3px; background: var(--line-mid); overflow: hidden;
}
.progress i {
  display: block; height: 100%; border-radius: 3px;
  background: var(--brand);
  transition: width var(--dur-3) var(--ease-out);
}

.cutoff {
  display: flex; align-items: flex-start; gap: var(--s-3);
  margin: var(--s-3) var(--gutter) 0;
  padding: var(--s-3) var(--s-4);
  border-radius: var(--r-2);
  background: var(--surface);
  box-shadow: var(--sh-1);
  border-left: 3px solid var(--accent);
  color: var(--text-2);
  font-size: var(--t-13);
}
.cutoff .ico, .cutoff b { color: var(--warn); }
.cutoff.soon { background: var(--danger-soft); border-left-color: var(--danger); }
.cutoff.soon .ico, .cutoff.soon b { color: var(--danger); }

/* ---------- Wyszukiwarka ---------- */

.search {
  position: relative;
  display: flex; align-items: center; gap: var(--s-3);
  margin: var(--s-3) var(--gutter) 0;
  padding: 0 var(--s-1) 0 var(--s-4);
  min-height: var(--btn-h);
  border-radius: var(--r-3);
  background: var(--surface); box-shadow: var(--hairline);
  color: var(--mut);
  transition: box-shadow var(--dur-1) var(--ease-out);
}
/* Obramowanie bierze na siebie pole, nie sam input. Domyślny pierścień fokusu
   rysował się wokół inputa, czyli ciemną ramkę w środku białej karty — to była
   ta „czarna ramka" pojawiająca się przy pisaniu. */
.search:focus-within { box-shadow: inset 0 0 0 2px var(--brand); }
.search input {
  flex: 1; min-width: 0; border: 0; outline: 0; background: none;
  font-size: 16px; color: var(--text-1);
  -webkit-appearance: none;
}
.search input:focus-visible { box-shadow: none; }
.search input::-webkit-search-cancel-button { display: none; }
.search input::placeholder { color: var(--mut); }
.search .scan {
  width: var(--hit); height: var(--hit); flex: none;
  border-radius: var(--r-2);
  display: grid; place-items: center;
  background: var(--brand-soft); color: var(--brand-deep);
}
.search .qclear {
  width: var(--hit-row); height: var(--hit-row); flex: none;
  display: grid; place-items: center; color: var(--mut);
}

/* ---------- Karta zgody na powiadomienia ---------- */

.karta-zgoda {
  display: flex; align-items: flex-start; gap: var(--s-3);
  margin: 0 var(--gutter) var(--s-4);
  padding: var(--s-4);
  border-radius: var(--r-3);
  background: var(--brand); color: var(--on-dark);
}
.karta-zgoda.odmowa { background: var(--danger-soft); color: var(--danger); }
.kz-ic { flex: none; color: var(--accent); }
.karta-zgoda.odmowa .kz-ic { color: var(--danger); }
.kz-body { flex: 1; min-width: 0; }
.kz-body strong { display: block; font-size: var(--t-15); font-weight: 700; }
.kz-body span { display: block; margin-top: 2px; font-size: var(--t-13); line-height: 1.4; color: var(--on-dark-2); }
.karta-zgoda.odmowa .kz-body span { color: var(--danger); opacity: .85; }
.karta-zgoda .btn { flex: none; align-self: center; }
.karta-zgoda.odmowa { margin-bottom: var(--s-3); }
.kroki-zgoda { margin-bottom: var(--s-3); }
.kroki-zgoda .krok { background: var(--surface); }
.kroki-zgoda .krok-nr { background: var(--danger); }
.kroki-zgoda .krok-ic { color: var(--danger); }

/* ---------- Aktywne promocje ---------- */

.shead-licznik {
  min-width: 20px; height: 20px; padding: 0 6px;
  border-radius: var(--r-pill);
  display: inline-grid; place-items: center;
  background: var(--accent); color: var(--on-accent);
  font-size: var(--t-11); font-weight: 800;
}

.promo-lista {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(268px, 1fr)); gap: var(--s-3);
  margin: var(--s-3) var(--gutter) 0;
}
.promo-karta {
  position: relative; overflow: hidden;
  display: flex; flex-direction: column;
  border-radius: var(--r-3);
  background: var(--surface); box-shadow: var(--hairline);
}
/* Żółta listwa oznacza promocję; czerwona, że kończy się w tym tygodniu. */
.promo-karta::before {
  content: ""; position: absolute; left: 0; top: 0; bottom: 0;
  width: 4px; background: var(--accent);
}
.promo-karta.pilna::before { background: var(--danger); }

.pk-tlo {
  display: flex; align-items: flex-start; gap: var(--s-3);
  padding: var(--s-3) var(--s-3) var(--s-2) var(--s-4);
  text-align: left; width: 100%;
}
.pk-tlo:active { background: var(--bg); }
.pk-body { flex: 1; min-width: 0; }
.pk-sku { display: block; color: var(--mut); }
.pk-nazwa {
  display: block; margin-top: 1px;
  font-size: var(--t-15); font-weight: 700; line-height: var(--lh-tight); color: var(--text-1);
}
.pk-powod {
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
  margin-top: 2px; font-size: var(--t-12); color: var(--mut); line-height: 1.35;
}
.pk-rabat {
  flex: none;
  padding: 3px 8px; border-radius: var(--r-1);
  background: var(--accent); color: var(--on-accent);
  font-size: var(--t-13); font-weight: 800; letter-spacing: -.01em;
}
.promo-karta.pilna .pk-rabat { background: var(--danger); color: #fff; }

.pk-dol {
  display: flex; align-items: center; gap: var(--s-3);
  padding: 0 var(--s-3) var(--s-2) var(--s-4);
}
.pk-ceny { flex: 1; min-width: 0; display: flex; align-items: baseline; gap: var(--s-2); flex-wrap: wrap; }
.pk-ceny b { font-family: var(--font-display); font-size: var(--t-20); font-weight: 600; }
.pk-ceny s { font-size: var(--t-13); color: var(--mut); }
.pk-ceny small { font-size: var(--t-12); color: var(--mut); }
.pk-dol .btn { flex: none; }
.pk-w-koszyku {
  flex: none; display: inline-flex; align-items: center; gap: 6px;
  padding: 0 var(--s-3); min-height: var(--hit-row);
  border-radius: var(--r-2);
  background: var(--brand-soft); color: var(--brand);
  font-size: var(--t-13); font-weight: 700;
}

.pk-termin {
  padding: var(--s-2) var(--s-3) var(--s-3) var(--s-4);
  border-top: 1px solid var(--line-soft);
  font-size: var(--t-12); color: var(--mut);
}
.promo-karta.pilna .pk-termin { color: var(--danger); font-weight: 600; }

/* ---------- Podpowiedzi wyszukiwarki ---------- */

.podp {
  position: absolute; left: var(--gutter); right: var(--gutter); z-index: 60;
  margin-top: 6px;
  border-radius: var(--r-3);
  background: var(--surface); box-shadow: var(--sh-2);
  overflow: hidden;
  animation: podpWejdz 180ms var(--ease-out);
}
.podp[hidden] { display: none; }
@keyframes podpWejdz { from { opacity: 0; transform: translateY(-6px); } }
@media (prefers-reduced-motion: reduce) { .podp { animation: none; } }

.podp-poz {
  display: flex; align-items: center; gap: var(--s-3);
  width: 100%; min-height: 56px; padding: var(--s-2) var(--s-3);
  text-align: left;
}
.podp-poz + .podp-poz, .podp-lista li + li .podp-poz { box-shadow: inset 0 1px 0 var(--line-soft); }
.podp-lista li + li .podp-poz { box-shadow: inset 0 1px 0 var(--line-soft); }
.podp-poz:hover, .podp-poz:active { background: var(--bg); }
.podp-body { flex: 1; min-width: 0; }
.podp-sku { display: block; font-size: var(--t-11); font-weight: 700; letter-spacing: .04em; color: var(--mut); }
.podp-nazwa {
  display: block; font-size: var(--t-15); font-weight: 600; color: var(--text-1);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.podp mark { background: var(--accent-soft); color: inherit; border-radius: 3px; padding: 0 1px; }
.podp-cena { flex: none; font-family: var(--font-display); font-size: var(--t-15); font-weight: 600; }
.podp-pusto { padding: var(--s-4); font-size: var(--t-13); color: var(--mut); line-height: 1.45; }

.sticky-head {
  position: sticky; top: 0; z-index: 40;
  background: var(--bg);
  padding-bottom: var(--s-1);
}
.sticky-head .search { margin-top: 0; }
.sticky-head + .plist + .shead { margin-top: var(--s-6); }
.shead { margin-top: var(--s-3); }

/* ---------- Kategorie ---------- */

/* Kategorie zawijają się do siatki zamiast jechać w bok. Poziome przewijanie
   chowa połowę pozycji za krawędzią, a na telefonie nikt tam nie zagląda —
   w siatce widać wszystkie dziewięć bez gestu. */
.rail {
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--s-2);
  margin-top: var(--s-4);
  padding: 0 var(--gutter);
}
/* Na telefonie kategorie to kafle w siatce trzech kolumn i nic się nie zmienia:
   opakowanie znika z układu, a wyjście do katalogu jest w pasku zakładek. */
.pas-kategorie { display: contents; }
.rail-caly { display: none; }
.cat {
  width: auto; min-width: 0;
  display: flex; flex-direction: column; align-items: center; gap: 6px;
  min-height: 82px; padding: var(--s-3) var(--s-2);
  border-radius: var(--r-3);
  background: var(--surface); box-shadow: var(--hairline);
  text-align: center;
  transition: transform var(--dur-1) var(--ease-out), box-shadow var(--dur-1) var(--ease-out);
}
.cat:active { transform: scale(.96); box-shadow: inset 0 0 0 1.5px var(--line-mid); }
.cat .tile {
  width: 30px; height: 30px; flex: none;
  display: grid; place-items: center;
  background: none; box-shadow: none;
  color: var(--brand);
}
.cat span {
  display: block; margin: 0; min-height: 0;
  font-size: var(--t-12); font-weight: 600; line-height: 1.2; color: var(--text-2);
}

/* ---------- Chipy ---------- */

.chips {
  display: flex; gap: var(--s-3);
  margin-top: var(--s-4);
  padding: 2px var(--gutter);
  overflow-x: auto; scrollbar-width: none;
  scroll-padding-inline: var(--gutter);
  -webkit-mask-image: linear-gradient(90deg, #000 calc(100% - 32px), transparent);
  mask-image: linear-gradient(90deg, #000 calc(100% - 32px), transparent);
}
.chips::-webkit-scrollbar { display: none; }
.chip {
  flex: none;
  display: inline-flex; align-items: center; gap: var(--s-1);
  min-height: var(--hit-row); padding: 0 var(--s-4);
  border-radius: var(--r-pill);
  font-size: 14px; font-weight: 600; color: var(--text-2);
  background: var(--surface); box-shadow: var(--hairline);
  white-space: nowrap;
  transition: background var(--dur-1) var(--ease-out), color var(--dur-1) var(--ease-out), transform var(--dur-1);
}
.chip:active { transform: scale(.95); }
.chip[aria-pressed="true"] { background: var(--brand-deep); color: var(--on-dark); box-shadow: none; }
.chip.mini { min-height: 32px; padding: 0 var(--s-3); font-size: var(--t-12); }
.chip-sort { margin-left: auto; }

/* ---------- Ilustracje ---------- */

.ilu { flex: none; display: block; border-radius: var(--r-1); }
.ilu-hero {
  width: calc(100% - 2 * var(--gutter)); height: 120px;
  margin: var(--s-2) var(--gutter) 0;
  border-radius: var(--r-4);
}
.ilu use { stroke: var(--stroke); }
.ilu-s use, .ilu-r use { stroke-width: 1.25; }
.ilu-m use { stroke-width: 1.5; }
.ilu-l use { stroke-width: 1.6; }
.ilu-hero use { stroke-width: 1.9; }
.ilu .mono {
  font-family: var(--font-display); font-weight: 600; letter-spacing: .04em;
  text-anchor: end; fill: var(--ink); fill-opacity: .55;
}

.mono-kolo {
  width: var(--hit); height: var(--hit); flex: none;
  border-radius: var(--r-pill);
  display: grid; place-items: center;
  background: var(--brand-soft); color: var(--brand-deep);
  font-size: var(--t-13); font-weight: 700; letter-spacing: .04em;
}
.mono-kolo.duzy { width: 62px; height: 62px; font-size: var(--t-20); font-family: var(--font-display); }

/* ---------- Wiersz produktu ---------- */

.plist { margin: 0 var(--gutter); }
/* Karty potrzebują odstępu większego niż wewnętrzny padding, inaczej czyta
   się je jak jeden blok z kreskami. */
.plist > li + li { margin-top: var(--s-4); }

.prod > article {
  position: relative;
  display: flex; gap: var(--s-3);
  padding: var(--s-3) var(--s-3) var(--s-2);
  border-radius: var(--r-4);
  background: var(--surface);
  box-shadow: var(--hairline);
  transition: transform var(--dur-1) var(--ease-out);
}
.prod:active > article { transform: scale(.99); }
.prod .body { flex: 1; min-width: 0; padding-right: 56px; }
.prod .sku { color: var(--mut); display: flex; align-items: center; gap: var(--s-1); }
.prod .ulub-znak { color: var(--accent); }
.prod h3 { margin: 2px 0 0; }
.prod-name {
  font-size: var(--t-15); font-weight: 700; line-height: var(--lh-tight);
  text-align: left; color: var(--text-1);
}
.prod-name::after { content: ""; position: absolute; inset: 0; border-radius: var(--r-4); }
.prod .typ { font-size: var(--t-13); color: var(--mut); line-height: 1.3; margin-top: 1px;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
/* Cena, opakowanie i przelicznik trzymają się jednej linii — przy 320 px
   rozpadały się na trzy wiersze i karta rosła o 40 px na każdej pozycji. */
.prod .meta {
  display: flex; align-items: baseline; gap: 6px; flex-wrap: wrap;
  margin-top: var(--s-1);
}
.prod .meta .pack, .prod .meta .perkg { white-space: nowrap; }
.prod .cena {
  font-family: var(--font-display); font-size: var(--t-17); font-weight: 600;
}
.prod .perkg { font-size: var(--t-12); color: var(--mut); }
.prod .pack { font-size: var(--t-12); font-weight: 500; color: var(--mut); }
.prod .meta { row-gap: 1px; }
.prod .hist { font-size: var(--t-12); color: var(--mut); }

.stock {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: var(--t-12); font-weight: 600; margin-top: var(--s-1);
}
.stock i { width: 9px; height: 9px; border-radius: 50%; flex: none; }
.stock.ok { color: var(--ok); } .stock.ok i { background: var(--ok); }
.stock.low { color: var(--warn); } .stock.low i { background: var(--low); }
.stock.no { color: var(--danger); } .stock.no i { background: var(--danger); }
.stock.pad { display: flex; margin: var(--s-2) var(--gutter) 0; }

.qadd {
  position: absolute; right: var(--s-3); bottom: var(--s-3);
  width: var(--hit); height: var(--hit);
  border-radius: var(--r-2);
  display: grid; place-items: center;
  background: var(--accent); color: var(--on-accent);
  transition: transform var(--dur-1) var(--ease-out);
}
.qadd:active { transform: scale(.9); }
.qadd.obs { background: var(--brand-soft); color: var(--brand); }
.prod .stepper { position: absolute; right: var(--s-3); bottom: var(--s-3); }

/* ---------- Stepper ---------- */

.stepper {
  display: inline-flex; align-items: center;
  height: var(--hit-row);
  border-radius: var(--r-2);
  background: var(--surface);
  box-shadow: inset 0 0 0 1.5px var(--line-strong);
  overflow: hidden;
}
.stepper button {
  width: var(--hit-row); height: var(--hit-row);
  display: grid; place-items: center;
  font-family: var(--font-display); font-size: var(--t-17); font-weight: 600;
  color: var(--brand-deep);
  transition: background var(--dur-1) var(--ease-out), transform var(--dur-1);
}
.stepper button:active { transform: scale(.86); background: var(--brand-soft); }
.stepper .st-ile {
  width: 52px; height: var(--hit-row);
  border: 0; outline: 0; background: none;
  text-align: center;
  font-size: 16px; font-weight: 700;
  font-variant-numeric: tabular-nums;
  appearance: textfield;
  -moz-appearance: textfield;
}
.stepper .st-ile::-webkit-outer-spin-button,
.stepper .st-ile::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }

/* ---------- Koszyk ---------- */

.cart-wrap { display: flex; flex-direction: column; min-height: 100%; }

.citem {
  display: flex; gap: var(--s-3);
  padding: var(--s-3);
  border-radius: var(--r-3);
  background: var(--surface); box-shadow: var(--hairline);
  overflow: hidden;
  transition: height var(--dur-2) var(--ease-out), opacity var(--dur-2) var(--ease-out),
              margin var(--dur-2) var(--ease-out), padding var(--dur-2) var(--ease-out);
}
.citem.out { height: 0 !important; opacity: 0; margin-top: 0 !important; padding-block: 0; }
.citem.klikalna { cursor: pointer; }
.citem .body { flex: 1; min-width: 0; }
.citem h3 { font-size: var(--t-15); font-weight: 700; line-height: var(--lh-tight); }
.citem .sub { font-size: var(--t-13); color: var(--mut); margin-top: 1px; }
.linia-ilosc { display: flex; align-items: center; gap: var(--s-3); margin-top: var(--s-2); }
.linia-ilosc .kwota {
  margin-left: auto;
  font-family: var(--font-display); font-size: var(--t-17); font-weight: 600;
}
.ilosc-stala { font-size: var(--t-13); color: var(--mut); }
.packrow { display: flex; align-items: center; gap: var(--s-2); margin-top: var(--s-2); flex-wrap: wrap; }
.warstwa-info { font-size: var(--t-12); color: var(--brand); font-weight: 600; }

.citem.in { animation: rise var(--dur-2) var(--ease-out) both; }

.cart-foot {
  position: sticky; bottom: 0; z-index: 30;
  margin-top: auto;
  display: flex; align-items: center; gap: var(--s-3);
  padding: var(--s-3) var(--gutter) var(--s-4);
  background: var(--bg);
  box-shadow: 0 -1px 0 var(--line-soft), 0 -12px 24px -12px rgba(29, 38, 31, .16);
}
.cf-kwoty { display: flex; flex-direction: column; min-width: 0; }
.cf-netto { font-size: var(--t-13); color: var(--mut); }
.cf-netto b { font-family: var(--font-display); font-size: var(--t-20); font-weight: 600; color: var(--text-1); }
.cf-brutto { font-size: var(--t-12); color: var(--mut); }
.cf-min { font-size: var(--t-12); font-weight: 600; }
.cf-min.ok { color: var(--brand-text); }
.cf-min.bad { color: var(--danger); }
.cart-foot .btn { width: auto; min-width: 148px; margin-left: auto; }

/* ---------- Sumy i notki ---------- */

.totals {
  margin: var(--s-3) var(--gutter) 0;
  padding: var(--s-4);
  border-radius: var(--r-4);
  background: var(--surface); box-shadow: var(--hairline);
}
.totals .row { display: flex; justify-content: space-between; align-items: baseline; font-size: var(--t-15); color: var(--text-2); }
.totals .row + .row { margin-top: var(--s-2); }
.totals .row.grand {
  margin-top: var(--s-3); padding-top: var(--s-3);
  border-top: 1px solid var(--line-soft);
  color: var(--text-1);
}
.totals .row.grand span:last-child { font-family: var(--font-display); font-size: var(--t-17); font-weight: 600; }
.prog { margin-top: var(--s-3); font-size: var(--t-12); color: var(--mut); }
.prog b { color: var(--text-1); }

.note {
  display: flex; gap: var(--s-3); align-items: flex-start;
  margin: var(--s-3) var(--gutter) 0;
  padding: var(--s-3) var(--s-4);
  border-radius: var(--r-3);
  font-size: var(--t-13); line-height: 1.4;
}
.note .ico { flex: none; margin-top: 1px; }
.note.ok { background: var(--brand-soft); color: var(--brand-text); }
.note.warn { background: var(--accent-soft); color: var(--warn); }
.note.bad { background: var(--danger-soft); color: var(--danger); }
.note.tight { margin-inline: 0; }
.note b { font-weight: 700; }
.note .link { color: inherit; text-decoration: underline; }
.nota-platnosc { align-items: center; }
.nota-platnosc .np-tresc { flex: 1; cursor: pointer; }
.nota-platnosc .btn { flex: none; background: var(--brand); color: var(--on-dark); }

/* ---------- Opcje ---------- */

.opts {
  margin: 0 var(--gutter);
  border-radius: var(--r-4);
  background: var(--surface); box-shadow: var(--hairline);
  overflow: hidden;
}
.opt {
  display: flex; align-items: center; gap: var(--s-3);
  width: 100%; min-height: 64px;
  padding: var(--s-3) var(--s-4);
  text-align: left;
  transition: background var(--dur-1) var(--ease-out);
}
.opt:active { background: var(--surface-2); }
.opt + .opt { box-shadow: inset 0 1px 0 var(--line-soft); }
.opt .ic {
  width: 40px; height: 40px; flex: none;
  border-radius: var(--r-1);
  display: grid; place-items: center;
  background: var(--surface-2); color: var(--brand-deep);
}
.opt .ic.num { font-family: var(--font-display); font-size: var(--t-15); font-weight: 600; }
.opt .body { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.opt-h { font-size: var(--t-15); font-weight: 700; }
.opt-p { font-size: var(--t-12); color: var(--mut); line-height: 1.35; margin-top: 1px; }
.opt .kiedy { font-size: var(--t-11); color: var(--mut); margin-top: var(--s-1); }
.opt .tick {
  width: 24px; height: 24px; flex: none; border-radius: 50%;
  box-shadow: inset 0 0 0 2px var(--line-strong);
  display: grid; place-items: center;
  transition: background var(--dur-1) var(--ease-out), box-shadow var(--dur-1) var(--ease-out);
}
.opt[aria-checked="true"] .tick { background: var(--brand); box-shadow: none; }
.opt[aria-checked="true"] .tick::after {
  content: ""; width: 10px; height: 5px;
  border-left: 2px solid #fff; border-bottom: 2px solid #fff;
  transform: rotate(-45deg) translate(1px, -1px);
  animation: tick var(--dur-2) var(--ease-spring);
}
@keyframes tick { from { transform: rotate(-45deg) translate(1px, -1px) scale(0); } }
.opt[aria-disabled="true"] { opacity: .58; }
.opt[aria-disabled="true"] .tick { visibility: hidden; }
.opt.opiekun { gap: var(--s-3); }
.ikona-akcja {
  width: var(--hit); height: var(--hit); flex: none;
  border-radius: var(--r-pill);
  display: grid; place-items: center;
  background: var(--surface-2); color: var(--brand-deep);
}
.powiadomienie.nowe .ic { background: var(--accent-soft); color: var(--warn); }

/* ---------- Pigułki i statusy ---------- */

.pill {
  font-size: var(--t-11); font-weight: 700; letter-spacing: .03em;
  padding: 4px 9px; border-radius: var(--r-pill);
  white-space: nowrap;
}
.pill.ok { background: var(--brand-soft); color: var(--brand-text); }
.pill.send { background: var(--brand-deep); color: var(--on-dark); }
.pill.neutral { background: var(--surface-2); color: var(--text-2); box-shadow: inset 0 0 0 1px var(--line); }
.pill.warn { background: var(--accent-soft); color: var(--warn); }
.pill.mut { background: var(--surface-2); color: var(--mut); text-decoration: line-through; }

/* ---------- Zamówienia ---------- */

.order {
  margin: 0 var(--gutter) var(--s-3);
  padding: var(--s-4);
  border-radius: var(--r-4);
  background: var(--surface); box-shadow: var(--hairline);
}
.order.swieza { animation: podswietl 1.4s var(--ease-out); }
@keyframes podswietl { from { background: var(--brand-soft); } to { background: var(--surface); } }
.order .head { display: flex; align-items: center; gap: var(--s-2); cursor: pointer; }
.order .head h3 { font-family: var(--font-display); font-size: var(--t-17); font-weight: 600; }
.order .head .when { margin-left: auto; font-size: var(--t-12); color: var(--mut); }
.order .kanal { color: var(--mut); margin-top: 2px; }
.mini-rzad { display: flex; gap: 6px; margin-top: var(--s-3); cursor: pointer; }
.mini-wiecej {
  width: 32px; height: 32px; border-radius: var(--r-1);
  display: grid; place-items: center;
  background: var(--surface-2); color: var(--mut);
  font-size: var(--t-11); font-weight: 700;
}
.order-sum {
  display: flex; align-items: baseline; justify-content: space-between;
  margin-top: var(--s-3); font-size: var(--t-13); color: var(--mut);
}
.order-sum .kwoty { text-align: right; }
.order-sum .kwoty b { font-family: var(--font-display); font-size: var(--t-17); font-weight: 600; color: var(--text-1); }
.order-sum .kwoty small { display: block; font-size: var(--t-12); color: var(--mut); }
/* Równa szerokość i ta sama wysokość co przyciski główne — dwa przyciski
   obok siebie o różnych rozmiarach czytają się jak różne poziomy ważności. */
.acts { display: flex; gap: var(--s-3); margin-top: var(--s-4); }
.acts .btn { flex: 1 1 0; min-width: 0; min-height: var(--btn-h); margin-top: 0; padding-inline: var(--s-3); }

/* ---------- Oś realizacji ---------- */

.track { display: flex; align-items: flex-start; margin: var(--s-4) 0 var(--s-2); }
.track .node { display: flex; flex-direction: column; align-items: center; gap: 6px; flex: none; width: 60px; }
.track .node i {
  width: 12px; height: 12px; border-radius: 50%;
  background: var(--line-mid);
  display: grid; place-items: center; color: #fff;
}
.track .node i .ico { width: 10px; height: 10px; }
.track .node.done i { background: var(--brand); }
.track .node.now i {
  width: 13px; height: 13px; background: var(--brand);
  box-shadow: 0 0 0 4px var(--brand-soft);
  animation: pop var(--dur-2) var(--ease-spring);
}
.track .node span { font-size: var(--t-11); color: var(--mut); text-align: center; line-height: 1.2; }
.track .node.now span { font-weight: 700; color: var(--text-1); }
.track .bar { flex: 1; height: 2px; background: var(--line-mid); margin-top: 5px; }
.track .bar.done { background: var(--brand); }

/* ---------- Arkusz ---------- */

.scrim {
  position: absolute; inset: 0; z-index: 70;
  background: rgba(16, 24, 18, .5);
  -webkit-backdrop-filter: blur(2px);
  backdrop-filter: blur(2px);
  opacity: 0;
  transition: opacity var(--dur-2) var(--ease-out);
  border: 0;
}
.scrim[data-open="true"] { opacity: 1; }
.scrim[hidden] { display: none; }

.sheet {
  position: absolute; left: 0; right: 0; bottom: 0; z-index: 71;
  max-height: 92%;
  display: flex; flex-direction: column;
  /* Przycięcie do własnej ramki: bez tego treść dłuższa niż arkusz wylewa się
     poza zaokrąglenie — na telefonie ucieka za ekran, w oknie desktopowym
     rysuje się na przyciemnieniu i łapie kliknięcia poza kartą. */
  overflow: hidden;
  background: var(--bg);
  border-radius: var(--r-5) var(--r-5) 0 0;
  box-shadow: var(--sh-3);
  transform: translateY(101%);
  transition: transform var(--dur-3) cubic-bezier(.32, .72, 0, 1);
}
.sheet[data-open="true"] { transform: translateY(0); }
.sheet[data-open="false"] { transition-duration: var(--dur-2); transition-timing-function: var(--ease-in); }
.sheet[hidden] { display: none; }
.sheet .pane { display: flex; flex-direction: column; min-height: 0; flex: 1; }

.sheet-head {
  position: relative; flex: none;
  height: 44px;
  touch-action: none;
}
.sheet-head .grip {
  position: absolute; left: 50%; top: 10px;
  width: 44px; height: 4px; margin-left: -22px;
  border-radius: 2px; background: var(--line);
}
.sheet-head .x {
  position: absolute; top: 6px; right: 10px;
  width: var(--hit); height: var(--hit);
  display: grid; place-items: center;
  color: var(--text-2);
}
.sheet-head .x::before {
  content: ""; position: absolute; inset: 4px;
  border-radius: 50%; background: var(--surface); box-shadow: var(--sh-1);
}
.sheet-head .x .ico { position: relative; }
.sheet-head .wstecz {
  position: absolute; top: 6px; left: var(--s-3);
  min-height: var(--hit); display: flex; align-items: center; gap: var(--s-1);
  padding-right: var(--s-3);
  font-size: var(--t-13); font-weight: 600; color: var(--brand);
}

.sheet .scrollable {
  flex: 1; overflow-y: auto; min-height: 0;
  overscroll-behavior: contain; touch-action: pan-y;
  scrollbar-width: none;
}
.sheet .scrollable::-webkit-scrollbar { display: none; }
.sheet .foot {
  flex: none;
  padding: var(--s-3) var(--gutter) calc(var(--s-3) + var(--sab));
  background: linear-gradient(rgba(244, 238, 226, 0), var(--bg) 35%);
}

/* Zawartość arkusza wchodzi kaskadą jak zakładka. Wyjątek to szybkie
   zamawianie — tam panel przerysowuje się przy każdym znaku i ruch
   zamieniłby się w migotanie. */
.sheet .pane:not([data-id="szybkie"]) .scrollable > * { animation: rise 260ms var(--ease-out) both; }
.sheet .pane:not([data-id="szybkie"]) .scrollable > *:nth-child(2) { animation-delay: 45ms; }
.sheet .pane:not([data-id="szybkie"]) .scrollable > *:nth-child(3) { animation-delay: 85ms; }
.sheet .pane:not([data-id="szybkie"]) .scrollable > *:nth-child(4) { animation-delay: 120ms; }
.sheet .pane:not([data-id="szybkie"]) .scrollable > *:nth-child(n+5) { animation-delay: 150ms; }
@media (prefers-reduced-motion: reduce) {
  .sheet .pane .scrollable > * { animation: none; }
}

/* Kafel zakładki potwierdza przełączenie — bez tego jedyną informacją
   o zmianie jest kolor napisu. */
.tab .ico.pyk { animation: pykIkona 340ms var(--ease-spring); }
@keyframes pykIkona {
  0% { transform: scale(.82); }
  60% { transform: scale(1.12); }
  100% { transform: scale(1); }
}
@media (prefers-reduced-motion: reduce) { .tab .ico.pyk { animation: none; } }

.pane.in-right { animation: wjedzPrawo var(--dur-3) var(--ease-out); }
.pane.in-left { animation: wjedzLewo var(--dur-3) var(--ease-out); }
.pane.out-left { position: absolute; inset: 0; animation: wyjdzLewo var(--dur-3) var(--ease-out) forwards; }
.pane.out-right { position: absolute; inset: 0; animation: wyjdzPrawo var(--dur-3) var(--ease-out) forwards; }
@keyframes wjedzPrawo { from { transform: translateX(100%); } }
@keyframes wjedzLewo { from { transform: translateX(-28%); opacity: .4; } }
@keyframes wyjdzLewo { to { transform: translateX(-28%); opacity: 0; } }
@keyframes wyjdzPrawo { to { transform: translateX(100%); opacity: 0; } }

.sheet-naglowek { padding-top: var(--s-1); }
.sheet-title {
  font-family: var(--font-display); font-size: var(--t-24); font-weight: 600;
  letter-spacing: var(--ls-display); line-height: 1.15;
  outline: none;
}
/* Tytuł dostaje fokus przy otwarciu arkusza, żeby czytnik ekranu przeczytał,
   co się otworzyło. To fokus z kodu, nie z klawiatury — obwódka wokół
   nagłówka jest tu artefaktem, nie wskazówką. */
.sheet-title:focus, .sheet-title:focus-visible { box-shadow: none; }
.sheet-sub { font-size: var(--t-13); color: var(--mut); margin-top: 2px; }
.fakt-linia { font-size: var(--t-13); color: var(--text-2); margin-top: var(--s-2); }
.fakt-linia .link { margin-left: var(--s-1); }

.pozycje-skladane { margin-top: var(--s-2); }
.pozycje-skladane summary {
  min-height: var(--hit-row); display: flex; align-items: center;
  font-size: var(--t-13); font-weight: 600; color: var(--brand);
  cursor: pointer;
}
.pozycje-skladane ul { padding-bottom: var(--s-2); }
.pozycje-skladane li {
  display: flex; justify-content: space-between; gap: var(--s-3);
  font-size: var(--t-13); color: var(--text-2);
  padding: 4px 0;
}

/* ---------- Produkt ---------- */

.prod-naglowek { display: flex; align-items: flex-start; gap: var(--s-3); margin-top: var(--s-3); }
.prod-naglowek > div { flex: 1; min-width: 0; }
.prod-naglowek .eyebrow { color: var(--mut); }
.serce {
  width: var(--hit); height: var(--hit); flex: none;
  border-radius: var(--r-pill);
  display: grid; place-items: center;
  background: var(--surface); box-shadow: var(--sh-1);
  color: var(--brand-deep);
  transition: transform var(--dur-2) var(--ease-spring);
}
.serce:active { transform: scale(.94); }
.serce.on { color: var(--accent); }
.serce.on .ico { fill: var(--accent); }

.pricebox {
  margin: var(--s-4) var(--gutter) 0;
  padding: var(--s-4);
  border-radius: var(--r-4);
  background: var(--surface); box-shadow: var(--hairline);
}
.pricebox .big {
  font-family: var(--font-display); font-size: var(--t-28); font-weight: 600;
  letter-spacing: var(--ls-display); margin-bottom: var(--s-3);
}
.pricebox .netto-lab {
  font-family: var(--font-ui); font-size: var(--t-12); font-weight: 600;
  letter-spacing: .06em; text-transform: uppercase; color: var(--mut);
  margin-left: 6px;
}
.rowline { display: flex; justify-content: space-between; gap: var(--s-3); font-size: var(--t-13); color: var(--text-2); }
.rowline + .rowline { margin-top: var(--s-2); }
.rowline.mocna span:last-child { color: var(--text-1); font-weight: 700; }
.cennik { margin-top: var(--s-3); padding-top: var(--s-3); border-top: 1px solid var(--line-soft); }
.przekreslona { text-decoration: line-through; color: var(--mut); }
.cennik .twoja { color: var(--brand-deep); font-weight: 600; }
.cennik .pill { margin-left: 6px; }
.rowline.wzrost span:last-child { color: var(--danger); }
.rowline.spadek span:last-child { color: var(--brand); }
.rowline.promo-linia span:last-child { color: var(--brand); }
.pod-pricebox { margin: var(--s-2) var(--gutter) 0; font-size: var(--t-12); color: var(--mut); }

.lead { font-size: var(--t-15); line-height: 1.45; color: var(--text-2); margin-top: var(--s-4); }

.card {
  margin: 0 var(--gutter);
  padding: var(--s-4);
  border-radius: var(--r-4);
  background: var(--surface); box-shadow: var(--hairline);
}
.card.pola { display: flex; flex-direction: column; gap: var(--s-2); }
.card textarea, .card input {
  width: 100%; border: 0; outline: 0;
  background: var(--surface-2);
  border-radius: var(--r-2);
  padding: var(--s-3) var(--s-4);
  min-height: var(--hit);
  font-size: 16px; color: var(--text-1);
  resize: none;
}
.card textarea::placeholder, .card input::placeholder { color: var(--mut); font-size: var(--t-15); }

.kv { display: flex; justify-content: space-between; gap: var(--s-4); font-size: var(--t-15); min-height: 28px; align-items: baseline; }
.kv + .kv { margin-top: var(--s-2); }
.kv dt { color: var(--mut); flex: none; }
.kv dd { text-align: right; font-weight: 600; text-wrap: balance; }
.kv dd small { display: block; font-weight: 400; font-size: var(--t-12); color: var(--mut); }
.kv dd.zielone, .tnum.zielone { color: var(--brand); }
/* Pasek podsumowuje trzy kwoty nad sobą, a nie wiersz pod nim — bez odstępu
   od dołu czytał się jak podkreślenie „Terminu płatności". */
.kv-list .progress { margin-top: var(--s-3); margin-bottom: var(--s-3); }
.kv .switch { align-self: center; }
.ean { letter-spacing: .04em; }

.alergeny { display: flex; flex-wrap: wrap; gap: var(--s-2); }
.chip-alergen {
  padding: 5px 11px; border-radius: var(--r-pill);
  border: 1.5px solid var(--danger); color: var(--danger); background: var(--danger-soft);
  font-size: var(--t-13); font-weight: 700;
}
.moze-zawierac { margin-top: var(--s-3); font-size: var(--t-13); color: var(--mut); }
.brak-alergenow { display: flex; align-items: center; gap: var(--s-2); font-size: var(--t-13); color: var(--ok); }

.docs {
  margin: 0 var(--gutter);
  border-radius: var(--r-4);
  background: var(--surface); box-shadow: var(--hairline);
  overflow: hidden;
}
.doc {
  display: flex; align-items: center; gap: var(--s-3);
  width: 100%; min-height: 64px;
  padding: var(--s-3) var(--s-4);
  text-align: left; color: var(--mut);
}
.doc:active { background: var(--surface-2); }
.doc + .doc { box-shadow: inset 0 1px 0 var(--line-soft); }
.doc .ic {
  width: 40px; height: 40px; flex: none;
  border-radius: var(--r-1);
  display: grid; place-items: center;
  background: var(--danger-soft); color: var(--danger);
}
.doc .body { flex: 1; min-width: 0; }
.doc-nazwa { display: block; font-size: var(--t-15); font-weight: 600; color: var(--text-1); }
.doc-meta { display: block; font-size: var(--t-12); color: var(--mut); }

.ostatnio { font-size: var(--t-12); color: var(--mut); margin-bottom: var(--s-2); text-align: center; }
.foot .foot-rzad .stepper { flex: none; }
.foot .foot-rzad .btn { flex: 1; }

/* ---------- Mapa ---------- */

.map {
  position: relative; height: 208px;
  margin: var(--s-2) var(--gutter) 0;
  border-radius: var(--r-4);
  overflow: hidden;
  background: var(--surface-2);
  box-shadow: var(--hairline);
  z-index: 0;
}
.map-msg {
  position: absolute; inset: 0;
  display: grid; place-items: center;
  padding: 0 34px; text-align: center;
  font-size: var(--t-13); color: var(--mut);
}
.map-skel { background: linear-gradient(100deg, var(--surface-2) 30%, var(--line-soft) 50%, var(--surface-2) 70%); background-size: 200% 100%; animation: shimmer 1.4s linear infinite; }
@keyframes shimmer { to { background-position: -200% 0; } }
.map .leaflet-container { background: #E8EDE2; font: inherit; }
.map .leaflet-control-attribution {
  font-size: var(--t-11); background: rgba(255, 255, 255, .88); color: var(--mut); padding: 1px 5px;
}
.map .leaflet-control-attribution a { color: var(--mut); }

.mpin-hit { display: grid; place-items: center; width: 44px; height: 44px; position: relative; }
.mpin {
  width: 28px; height: 36px;
  fill: var(--surface);
  filter: drop-shadow(0 3px 5px rgba(29, 38, 31, .28));
  transition: fill var(--dur-2) var(--ease-out);
}
.mpin.on { fill: var(--brand); }
.mpin-nr {
  font-family: var(--font-display); font-size: 13px; font-weight: 600;
  text-anchor: middle; dominant-baseline: middle;
  fill: var(--brand-deep);
}
.mpin.on .mpin-nr { fill: var(--on-dark); }
.mhere {
  display: block; width: 14px; height: 14px; border-radius: 50%;
  background: var(--brand);
  box-shadow: 0 0 0 2px #fff, 0 0 0 3px rgba(29, 5, 60, .30);
}

/* ---------- Potwierdzenie ---------- */

.potwierdzenie { text-align: center; padding: var(--s-4) var(--s-6) 0; }
.ring {
  width: 64px; height: 64px; margin: 0 auto var(--s-4);
  border-radius: 50%;
  display: grid; place-items: center;
  background: var(--brand-deep); color: var(--on-dark);
  box-shadow: 0 12px 30px rgba(29, 5, 60, .28);
  animation: pop var(--dur-3) var(--ease-spring);
}
.ring.czeka { background: var(--surface-2); color: var(--mut); box-shadow: var(--hairline); }
.ring-check { width: 36px; height: 36px; fill: none; stroke: var(--on-dark); stroke-width: 4; stroke-linecap: round; stroke-linejoin: round; }
.ring-check path { stroke-dasharray: 48; stroke-dashoffset: 48; animation: rysuj 420ms var(--ease-out) 120ms forwards; }
@keyframes rysuj { to { stroke-dashoffset: 0; } }
.pot-nr { font-family: var(--font-display); font-size: var(--t-28); font-weight: 600; margin-top: var(--s-2); }
.pot-kwota { font-size: var(--t-15); color: var(--mut); }
.pot-opis { font-size: var(--t-13); color: var(--mut); margin-top: var(--s-2); }
.pot-karta { margin-top: var(--s-5); text-align: left; }
.pot-stopka { margin-top: var(--s-4); font-size: var(--t-12); color: var(--mut); }
.pot-stopka a { color: var(--brand); font-weight: 600; }

/* ---------- ING Pay ---------- */

.metody { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s-3); margin: 0 var(--gutter); }
.metoda {
  min-height: 56px;
  display: flex; align-items: center; gap: var(--s-2);
  padding: 0 var(--s-4);
  border-radius: var(--r-2);
  background: var(--surface); box-shadow: var(--hairline);
  font-size: var(--t-13); font-weight: 600; color: var(--text-2);
}
.metoda.on { box-shadow: inset 0 0 0 2px var(--brand); color: var(--brand-deep); }
.blik-box { margin-top: var(--s-4); }
.blik-label { display: block; font-size: var(--t-13); color: var(--mut); margin-bottom: var(--s-2); }
.blik-input {
  width: 100%; border: 0; outline: 0;
  background: var(--surface); box-shadow: var(--hairline);
  border-radius: var(--r-2);
  padding: var(--s-3) var(--s-4); min-height: var(--btn-h);
  font-family: var(--font-display); font-size: var(--t-24); font-weight: 600;
  letter-spacing: .2em; text-align: center;
}
.metoda-info { margin-top: var(--s-4); font-size: var(--t-13); color: var(--mut); }
.platnosc-czeka { display: flex; flex-direction: column; align-items: center; gap: var(--s-4); padding: var(--s-8) var(--s-6); }
.platnosc-czeka p { font-size: var(--t-15); color: var(--text-2); text-align: center; }

/* ---------- Dokument ---------- */

.doc-podglad {
  margin: var(--s-2) var(--gutter) 0;
  border-radius: var(--r-3);
  background: var(--surface); box-shadow: var(--sh-1);
  overflow: hidden;
}
.doc-pasek { background: var(--brand-deep); color: var(--on-dark); font-size: var(--t-12); font-weight: 600; padding: var(--s-2) var(--s-4); }
.doc-tresc { padding: var(--s-5) var(--s-4); }
.doc-tresc h3 { font-family: var(--font-display); font-size: var(--t-20); font-weight: 600; }
.doc-sku { font-size: var(--t-13); color: var(--mut); margin-top: var(--s-1); }
.doc-tresc p { font-size: var(--t-13); color: var(--text-2); margin-top: var(--s-3); line-height: 1.5; }
.doc-stopka { font-size: var(--t-11) !important; color: var(--mut) !important; margin-top: var(--s-5) !important; }

/* ---------- Przełącznik ---------- */

.switch {
  width: var(--hit); height: 28px; flex: none;
  border-radius: var(--r-pill);
  background: var(--switch-off);
  position: relative;
  transition: background var(--dur-2) var(--ease-out);
}
.switch::after {
  content: ""; position: absolute; top: 3px; left: 3px;
  width: 22px; height: 22px; border-radius: 50%;
  background: #fff; box-shadow: var(--sh-1);
  transition: transform var(--dur-2) var(--ease-out);
}
.switch[aria-checked="true"] { background: var(--brand); }
.switch[aria-checked="true"]::after { transform: translateX(20px); }

/* ---------- Promo ---------- */

.promo {
  position: relative;
  display: flex; gap: var(--s-3); align-items: flex-start;
  margin: 0 var(--gutter);
  padding: var(--s-4);
  border-radius: var(--r-4);
  background: var(--surface); box-shadow: var(--hairline);
}
.promo .tag {
  display: inline-block; margin-bottom: var(--s-1);
  padding: 3px 8px; border-radius: var(--r-1);
  background: var(--brand-soft); color: var(--brand-deep);
}
.promo h3 { margin-bottom: 3px; }
/* Notka handlowa, nie artykuł — trzy wiersze i koniec. Bez tego zajmowała
   na telefonie pół ekranu między zamówieniem a limitem. */
.promo p {
  display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden;
}
.promo .prod-name { font-size: var(--t-15); font-weight: 700; line-height: var(--lh-tight); }
.promo p { font-size: var(--t-13); color: var(--mut); line-height: 1.4; }


/* ---------- Pusty stan ---------- */

.empty { text-align: center; padding: var(--s-9) var(--s-7); color: var(--mut); }
.empty .ico { margin: 0 auto; color: var(--line-strong); }
.empty h3 { margin: var(--s-3) 0 var(--s-1); font-size: var(--t-17); font-family: var(--font-display); font-weight: 600; color: var(--text-1); }
.empty p { font-size: var(--t-13); line-height: 1.45; }
.empty .btn { margin-top: var(--s-4); }
.empty-akcje { margin-top: var(--s-5); display: flex; flex-direction: column; gap: var(--s-2); }
.empty-akcje .btn { margin-top: 0; }

.nota-mala { margin: var(--s-2) var(--gutter) 0; font-size: var(--t-12); color: var(--mut); }
.konto-head { align-items: center; gap: var(--s-4); }
.konto-stopka { margin-top: var(--s-5); display: flex; flex-direction: column; gap: var(--s-2); }
.konto-stopka .btn { margin-top: 0; }
.adres-nazwa { font-size: var(--t-15); font-weight: 700; }
.adres-linia { font-size: var(--t-13); color: var(--mut); }

/* ---------- Pasek zakładek ---------- */

.tabbar {
  position: relative; z-index: 45; flex: none;
  /* auto-flow zamiast repeat(5): gdyby do paska trafił dodatkowy element,
     rząd się ściśnie, a nie zawinie do drugiej linii. */
  display: grid; grid-auto-flow: column; grid-auto-columns: 1fr;
  padding-bottom: var(--sab);
  background: var(--surface);
  box-shadow: 0 -1px 0 var(--line-soft), 0 -10px 30px rgba(29, 38, 31, .05);
}
.tab {
  position: relative;
  height: var(--nav-h);
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 3px;
  font-size: var(--t-12); font-weight: 600; color: var(--mut);
}
.tab .ico { display: grid; place-items: center; width: 40px; height: 26px; border-radius: var(--r-pill); transition: background var(--dur-1) var(--ease-out); }
.tab .lab { font-size: 11.5px; font-weight: 700; }
.tab[aria-current="page"] { color: var(--brand-deep); }
.tab[aria-current="page"] .ico { background: var(--brand-soft); }
.tab .badge {
  position: absolute; top: 6px; left: calc(50% + 6px);
  min-width: 18px; height: 18px; padding: 0 5px;
  border-radius: var(--r-pill);
  background: var(--accent); color: var(--on-accent);
  font-size: var(--t-11); font-weight: 800;
  display: grid; place-items: center;
  box-shadow: 0 0 0 2px var(--surface);
  font-variant-numeric: tabular-nums;
}
.tab .badge[hidden] { display: none; }
.tab .badge.pop { animation: popBadge var(--dur-2) var(--ease-spring); }
@keyframes popBadge { 0% { transform: scale(.4); } 60% { transform: scale(1.22); } 100% { transform: scale(1); } }

/* Skaner jest piątym kaflem, nie pływającą kulą. Kula wchodziła na treść nad
   paskiem, jej podpis zderzał się z sąsiednimi, a na iPhonie właził jeszcze
   w pasek gestu. Wyróżnia go tło kafla, nie wyniesienie z rzędu. */
.tab-scan .orb {
  width: 40px; height: 26px;
  border-radius: var(--r-pill);
  display: grid; place-items: center;
  /* Żółty, nie oberżyna: oberżynowa pigułka oznacza zakładkę bieżącą, więc
     skaner w tym samym kolorze czytałby się jak aktywna karta. */
  background: var(--accent); color: var(--on-accent);
  transition: transform var(--dur-1) var(--ease-out);
}
.tab-scan:active .orb { transform: scale(.92); }
.tab-scan .lab { color: var(--brand-deep); }

.rail-brand, .rail-stopka, .topweb { display: none; }

/* Znak klienta — kłos w kole marki. Firma dostaje swój znak, osoba zostaje
   przy inicjałach; inaczej awatar konta i awatar profilu byłyby tym samym. */
.avatar img, .kto-avatar img, .rk-avatar img { width: 100%; height: 100%; }
.avatar, .kto-avatar, .rk-avatar { padding: 0; overflow: hidden; background: none; }
.znak-firmy { flex: none; width: 56px; height: 56px; border-radius: var(--r-pill); }

/* ---------- Formularze profilu i adresu ---------- */

.formularz { display: grid; gap: var(--s-4); margin-top: var(--s-2); }
.pole { display: block; }
.pole-lab {
  display: block; margin-bottom: 6px;
  font-size: var(--t-12); font-weight: 700; color: var(--mut);
  letter-spacing: .01em;
}
.pole-input {
  width: 100%; min-height: var(--btn-h);
  padding: 0 var(--s-4);
  border: 0; outline: 0;
  border-radius: var(--r-2);
  background: var(--surface); box-shadow: var(--hairline);
  font-size: 16px; font-weight: 600; color: var(--text-1);
}
.pole-input:focus-visible { box-shadow: inset 0 0 0 2px var(--brand); }
.pole-nota { font-size: var(--t-12); color: var(--mut); line-height: 1.45; }
.link-inline { color: var(--brand); font-weight: 700; text-decoration: underline; }
.opt-strzalka { flex: none; color: var(--mut); transform: rotate(180deg); }
.rachunek { font-variant-numeric: tabular-nums; letter-spacing: .02em; }

/* Nagłówek arkusza konta jako przycisk do profilu firmy. */
.konto-head-btn { display: flex; width: 100%; text-align: left; align-items: center; gap: var(--s-4); }
.konto-head-btn:active { background: var(--bg); }
.kh-body { flex: 1; min-width: 0; }
.kh-body .sheet-title { display: block; }
.kh-body .sheet-sub { display: block; }
.kh-edytuj {
  flex: none; align-self: flex-start; margin-top: 2px;
  display: inline-flex; align-items: center; gap: 6px;
  min-height: 32px; padding: 0 var(--s-3);
  border-radius: var(--r-pill);
  background: var(--brand-soft); color: var(--brand);
  font-size: var(--t-12); font-weight: 700;
}
.hello-strzalka { flex: none; color: var(--mut); transform: rotate(180deg); }
.link-inline-btn { display: inline; min-height: 0; padding: 0; margin: 0; text-decoration: underline; }

.karta-profil {
  display: flex; align-items: center; gap: var(--s-3);
  width: calc(100% - 2 * var(--gutter)); margin: 0 var(--gutter) var(--s-2);
  padding: var(--s-3) var(--s-4);
  border-radius: var(--r-4); text-align: left;
  background: var(--surface); box-shadow: var(--hairline);
}
.kp-body { flex: 1; min-width: 0; }
.kp-body strong { display: block; font-size: var(--t-17); font-weight: 700; }
.kp-body span { display: block; font-size: var(--t-13); color: var(--mut); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.kp-edytuj {
  flex: none; display: inline-flex; align-items: center; gap: 6px;
  padding: 0 var(--s-3); min-height: var(--hit-row);
  border-radius: var(--r-pill);
  background: var(--brand-soft); color: var(--brand);
  font-size: var(--t-13); font-weight: 700;
}

/* ---------- Szybkie zamawianie ---------- */

.sz-lista { margin: var(--s-2) var(--gutter) 0; display: grid; gap: var(--s-2); }
.sz-wiersz {
  display: grid; align-items: center; gap: var(--s-2) var(--s-3);
  grid-template-columns: auto minmax(0, 1fr) auto auto;
  padding: var(--s-3);
  border-radius: var(--r-3);
  background: var(--surface); box-shadow: var(--hairline);
}
.sz-pola { display: flex; gap: var(--s-2); }
.sz-kod { width: 168px; text-transform: uppercase; }
.sz-ile { width: 74px; text-align: center; }
.sz-opis { min-width: 0; font-size: var(--t-13); line-height: 1.35; }
.sz-opis strong { display: block; font-size: var(--t-15); font-weight: 700; }
.sz-opis span { color: var(--mut); }
.sz-pusty { color: var(--mut); }
.sz-blad { display: inline-flex; align-items: center; gap: 6px; color: var(--danger); font-weight: 600; }
.sz-suma { font-family: var(--font-display); font-size: var(--t-17); font-weight: 600; white-space: nowrap; }
.sz-usun { width: var(--hit-row); height: var(--hit-row); display: grid; place-items: center; color: var(--mut); border-radius: var(--r-1); }
.sz-usun:hover { color: var(--danger); background: var(--danger-soft); }
.sz-wiersz[data-status="zly"] { box-shadow: inset 0 0 0 1.5px var(--danger); }
.sz-wiersz[data-status="ostrzezenie"] { box-shadow: inset 0 0 0 1.5px var(--line-mid); }
.sz-akcje { margin-top: var(--s-3); }
.sz-foot { display: flex; align-items: center; gap: var(--s-4); }
.sz-podsumowanie { flex: 1; min-width: 0; font-size: var(--t-13); color: var(--mut); }
.sz-podsumowanie b { font-family: var(--font-display); font-size: var(--t-20); font-weight: 600; color: var(--text-1); }
.sz-podsumowanie small { display: block; font-size: var(--t-12); }
.sz-foot .btn { flex: none; width: auto; padding-inline: var(--s-6); }

@media (max-width: 519px) {
  .sz-wiersz { grid-template-columns: minmax(0, 1fr) auto; }
  .sz-pola { grid-column: 1 / -1; }
  .sz-kod { flex: 1; width: auto; }
}

/* ---------- Zaproszenie do instalacji ---------- */

.instal {
  position: absolute; z-index: 88;
  left: var(--s-3); right: var(--s-3); bottom: calc(var(--nav-h) + var(--sab) + var(--s-3));
  opacity: 0; transform: translateY(16px);
  transition: opacity var(--dur-2) var(--ease-out), transform var(--dur-3) var(--ease-out);
  pointer-events: none;
}
.instal[data-open="true"] { opacity: 1; transform: none; pointer-events: auto; }
.instal:empty { display: none; }
/* Arkusz przykrywa kartę instalacji, nie odwrotnie. */
body.sheet-open .instal { display: none; }

.instal-karta {
  position: relative;
  padding: var(--s-5) var(--s-5) var(--s-4);
  border-radius: var(--r-4);
  background: var(--grad-brand); color: var(--on-dark);
  box-shadow: 0 18px 50px rgba(18, 2, 42, .45);
}
.instal-x {
  position: absolute; top: var(--s-2); right: var(--s-2);
  width: var(--hit); height: var(--hit);
  display: grid; place-items: center;
  color: var(--on-dark-2);
}
.instal-eyebrow {
  font-size: var(--t-11); font-weight: 700;
  letter-spacing: var(--ls-eyebrow); text-transform: uppercase;
  color: var(--accent);
}
.instal-h {
  margin-top: var(--s-1); padding-right: var(--s-7);
  font-family: var(--font-display); font-size: var(--t-20); font-weight: 600;
  letter-spacing: var(--ls-display); line-height: 1.15;
}
.instal-p { margin-top: var(--s-2); font-size: var(--t-13); line-height: 1.45; color: var(--on-dark-2); }

.instal-kroki { margin-top: var(--s-4); display: grid; gap: var(--s-2); }
/* Bez gap na li — węzły tekstu są tu osobnymi elementami flex i odstęp
   rozpychałby zdanie wokół pogrubień. */
.instal-kroki li {
  display: flex; align-items: center;
  font-size: var(--t-13); color: var(--on-dark-2);
}
.instal-kroki b { margin: 0 .25em; }
.instal-kroki b { color: var(--on-dark); font-weight: 700; }
.instal-ic, .instal-nr {
  flex: none; width: 34px; height: 34px; margin-right: var(--s-3);
  border-radius: var(--r-1);
  display: grid; place-items: center;
  background: rgba(243, 242, 247, .12); color: var(--accent);
}
.instal-nr { font-size: var(--t-13); font-weight: 800; }

.instal-qr {
  width: 150px; height: 150px; margin: var(--s-4) auto 0;
  padding: var(--s-3);
  border-radius: var(--r-2); background: #fff;
}
.instal-adres {
  margin-top: var(--s-2); text-align: center;
  font-size: var(--t-12); font-weight: 600; letter-spacing: .02em; color: var(--on-dark-2);
}

.instal-akcje { margin-top: var(--s-4); display: flex; gap: var(--s-2); }
.instal-akcje .btn { flex: 1; }
.instal-akcje .btn-ghost {
  background: transparent; color: var(--on-dark);
  box-shadow: inset 0 0 0 1.5px rgba(243, 242, 247, .28);
}

/* ---------- Arkusz „Jak zamawiać" ---------- */

.kroki { margin: var(--s-2) var(--gutter) 0; }
.krok {
  position: relative;
  display: flex; align-items: flex-start; gap: var(--s-3);
  padding: var(--s-4);
  border-radius: var(--r-3);
  background: var(--surface); box-shadow: var(--hairline);
}
.krok + .krok { margin-top: var(--s-3); }
/* Pionowa nitka łącząca kroki — pokazuje, że to sekwencja, nie lista. */
.krok + .krok::before {
  content: ""; position: absolute; left: 30px; top: calc(-1 * var(--s-3));
  width: 2px; height: var(--s-3); background: var(--line);
}
.krok-nr {
  flex: none; width: 24px; height: 24px; margin-top: 2px;
  border-radius: 50%;
  display: grid; place-items: center;
  background: var(--brand); color: var(--on-dark);
  font-size: var(--t-12); font-weight: 800;
}
.krok-ic { flex: none; color: var(--brand); margin-top: 1px; }
.krok-body { min-width: 0; }
.krok-body strong { display: block; font-size: var(--t-15); font-weight: 700; }
.krok-body span { display: block; margin-top: 2px; font-size: var(--t-13); color: var(--mut); line-height: 1.45; }

/* ---------- Toast ---------- */

/* Powiadomienie zjeżdża zza krawędzi z lekkim odbiciem i chowa się szybciej,
   niż wchodzi — wejście ma przyciągnąć wzrok, wyjście nie ma go zatrzymywać.
   Skala idzie razem z przesunięciem, żeby ruch miał głębię, a nie był samym
   przesuwaniem prostokąta. */
.toast {
  position: absolute; left: var(--s-3); right: var(--s-3);
  top: calc(var(--sat) + 10px);
  z-index: 90;
  display: flex; align-items: center; gap: var(--s-3);
  padding: var(--s-3) var(--s-4);
  border-radius: var(--r-3);
  background: var(--ink); color: var(--on-dark);
  font-size: var(--t-15);
  box-shadow: 0 10px 30px rgba(18, 2, 42, .35), var(--sh-2);
  transform: translate3d(0, calc(-100% - var(--s-4)), 0) scale(.96);
  opacity: 0;
  pointer-events: none;
  transition:
    opacity 160ms var(--ease-in),
    transform 220ms var(--ease-in);
}
.toast[data-open="true"] {
  opacity: 1; transform: translate3d(0, 0, 0) scale(1); pointer-events: auto;
  transition:
    opacity 180ms var(--ease-out),
    transform 420ms var(--ease-spring);
}
@media (prefers-reduced-motion: reduce) {
  .toast, .toast[data-open="true"] { transition: opacity 120ms linear; transform: none; }
}
/* Powiadomienie w aplikacji ma tę samą treść co systemowe: tytuł i opis.
   Sam tytuł mówił o połowę mniej niż to, co wpada na pasek systemu. */
.toast-ic {
  flex: none; display: grid; place-items: center;
  width: 30px; height: 30px; border-radius: var(--r-1);
  background: rgba(243, 242, 247, .12); color: var(--accent);
}
.toast .toast-tekst { flex: 1; min-width: 0; line-height: 1.3; }
.toast .toast-tekst b { display: block; font-size: var(--t-15); font-weight: 700; }
.toast .toast-tekst small {
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
  margin-top: 2px; font-size: var(--t-12); color: var(--on-dark-2);
}
.toast[data-dwie="true"] { align-items: flex-start; }
.toast[data-dwie="true"] .toast-akcja { align-self: center; }
.toast[data-ton="warn"] .ico { color: var(--accent-on-dark); }
.toast[data-ton="err"] .ico { color: #E88F8A; }
.toast[data-ton="ok"] .ico { color: #7FCB98; }
.toast-akcja {
  flex: none; min-height: var(--hit-row); padding: 0 var(--s-3);
  color: var(--accent-on-dark); font-weight: 700; font-size: var(--t-13);
}

/* ---------- Lot do koszyka ---------- */

.fly {
  position: fixed; z-index: 100;
  width: 40px; height: 40px; border-radius: var(--r-2);
  background: var(--brand-soft);
  box-shadow: var(--sh-1);
  pointer-events: none;
}

/* ---------- Skaner ---------- */

.scanner {
  position: absolute; inset: 0; z-index: 86;
  background: var(--ink);
  display: flex; flex-direction: column;
  opacity: 0; transform: scale(1.03);
  transition: opacity var(--dur-2) var(--ease-out), transform var(--dur-2) var(--ease-out);
}
.scanner[data-open="true"] { opacity: 1; transform: none; }
.scanner[hidden] { display: none; }
.scanner video { flex: 1; width: 100%; object-fit: cover; }
.scanner .frame {
  position: absolute; left: 12%; right: 12%; top: 30%;
  aspect-ratio: 1.6;
  border-radius: var(--r-5);
  box-shadow: 0 0 0 100vmax rgba(8, 14, 10, .56);
  outline: 2px solid rgba(240, 235, 221, .85); outline-offset: -2px;
  transition: outline-color var(--dur-1), transform var(--dur-1);
}
.scanner .frame::after {
  content: ""; position: absolute; left: 6%; right: 6%; top: 50%; height: 2px;
  background: linear-gradient(90deg, transparent, #5CBB7E, transparent);
  animation: sweep 2.1s cubic-bezier(.45, 0, .55, 1) infinite;
}
.scanner .frame.hit { outline-color: #5CBB7E; outline-width: 3px; transform: scale(.97); }
.scanner .frame.hit::after { animation-play-state: paused; background: #5CBB7E; }
@keyframes sweep { 0%, 100% { transform: translateY(-46px); } 50% { transform: translateY(46px); } }
.scanner .hint {
  position: absolute; left: 0; right: 0; bottom: calc(96px + var(--sab));
  text-align: center; color: var(--on-dark); font-size: var(--t-13);
  padding: 0 30px; line-height: 1.4;
}
.scanner .close {
  position: absolute; top: calc(var(--sat) + 36px); right: var(--s-4);
  width: var(--hit); height: var(--hit); border-radius: var(--r-pill);
  background: rgba(240, 235, 221, .16); color: var(--on-dark);
  display: grid; place-items: center;
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
}
.scan-anuluj {
  position: absolute; left: var(--s-4); right: var(--s-4);
  bottom: calc(var(--s-6) + var(--sab));
  min-height: var(--btn-h);
  border-radius: var(--r-2);
  background: rgba(240, 235, 221, .14); color: var(--on-dark);
  font-size: var(--t-15); font-weight: 700;
}

/* ---------- Logowanie ---------- */

.login {
  position: absolute; inset: 0; z-index: 90;
  /* Formularz przy dolnej krawędzi — tam sięga kciuk. Pusta przestrzeń nad nim
     jest celowa, to pole dla logo i nagłówka. */
  display: flex; flex-direction: column; justify-content: flex-end;
  padding: 0 var(--s-6) calc(var(--s-7) + var(--sab));
  color: var(--on-dark);
  background: var(--grad-brand);
  overflow: hidden;
  transition: opacity var(--dur-3) cubic-bezier(.4, 0, .6, 1), transform var(--dur-3) var(--ease-out);
}
.login[hidden] { display: none; }
html.sesja .login { display: none; }
.login.leaving { opacity: 0; transform: scale(1.03); }

.brand {
  position: absolute; top: calc(var(--sat) + 46px); left: var(--s-6);
  display: flex; flex-direction: column; gap: 6px;
}
/* Jeden plik logo dla obu teł — na ciemnym wybielany filtrem, bez drugiego pobrania. */
.logo-bialy { width: 190px; height: auto; filter: brightness(0) invert(1); }
.brand .tag {
  font-size: var(--t-12); font-weight: 700; letter-spacing: .14em; text-transform: uppercase;
  color: var(--accent);
  padding-left: 2px;
}

.login h1 {
  font-family: var(--font-display); font-size: var(--t-36); font-weight: 600;
  line-height: 1.06; letter-spacing: -.03em;
  margin-bottom: var(--s-3);
}
.login-lead { font-size: var(--t-15); color: var(--on-dark-2); line-height: 1.45; margin-bottom: var(--s-6); max-width: 32ch; }

.field {
  display: flex; align-items: center; gap: var(--s-3);
  min-height: var(--btn-h); padding: 0 var(--s-4);
  border-radius: var(--r-3);
  background: rgba(255, 255, 255, .1);
  box-shadow: inset 0 0 0 1.5px rgba(238, 232, 215, .45);
  margin-bottom: var(--s-3);
}
.field:focus-within { box-shadow: inset 0 0 0 1.5px #F4EEDE; }
.field input {
  flex: 1; min-width: 0; border: 0; outline: 0; background: none;
  color: #F2ECDC; font-size: 16px;
}
.field input::placeholder { color: rgba(238, 232, 215, .85); }

/* Maskowanie hasła krojem systemowym. Subset Schibsted Grotesk deklaruje zakres
   U+2000–206F, ale nie ma w nim glifu kropki maskującej, więc Safari na iOS
   rysował pustą ramkę zamiast każdego znaku hasła. */
input[type="password"] {
  font-family: system-ui, -apple-system, "Segoe UI Variable", "Segoe UI", sans-serif;
  letter-spacing: .12em;
}

.kto { display: none; text-align: center; margin-bottom: var(--s-6); }
.kto-avatar {
  width: 56px; height: 56px; margin: 0 auto var(--s-3);
  border-radius: var(--r-pill);
  display: grid; place-items: center;
  background: var(--brand); color: #F4EEE2;
  font-size: var(--t-20); font-weight: 700; letter-spacing: .04em;
}
.kto strong { display: block; font-size: var(--t-17); font-weight: 700; }
.kto-mail { font-size: var(--t-13); color: rgba(238, 232, 215, .74); }

.login.skrot .kto { display: block; }
.login.skrot .login-lead,
.login.skrot .field,
.login.skrot h1 { display: none; }
.login.skrot .etykieta-pelna { display: none; }
.login:not(.skrot) .etykieta-skrot { display: none; }
.etykieta-skrot { display: flex; align-items: center; gap: var(--s-2); }
.login:not(.skrot) #inneKonto { display: none; }

/* Numer telefonu i inne dane kontaktowe nigdy nie łamią się w środku —
   „+48 601 / 220 145" w dwóch wierszach czyta się jak dwa różne numery. */
a[href^="tel:"], .nr-telefonu { white-space: nowrap; }

.login-linki { margin-top: var(--s-4); text-align: center; }
.link-login {
  min-height: var(--hit); padding: 0 var(--s-3);
  font-size: 14px; color: rgba(238, 232, 215, .82); font-weight: 600;
}
.login-opiekun { margin-top: var(--s-1); font-size: var(--t-13); color: rgba(238, 232, 215, .62); line-height: 1.4; }
.login-opiekun a { color: rgba(238, 232, 215, .9); font-weight: 600; }

@media (max-height: 760px) {
  .logo-bialy { width: 158px; }
  .login h1 { font-size: var(--t-28); }
}

/* ---------- Preferencje systemowe ---------- */

@media (prefers-reduced-motion: reduce) {
  .sheet, .scrim, .toast, .login, .scanner { transition-property: opacity; transition-duration: 160ms; }
  .sheet { transform: none !important; }
  .sheet:not([data-open="true"]) { opacity: 0; }
  .btn:active, .prod:active > article, .cat:active .tile, .chip:active { transform: none; }
  * { animation-duration: .01ms !important; animation-iteration-count: 1 !important; }
}

@media (prefers-contrast: more) {
  :root { --mut: #4C5750; --line: #C9BFA6; --line-strong: #6B6350; }
  .prod > article, .card, .order, .citem, .opts, .docs { box-shadow: inset 0 0 0 1px var(--line-strong); }
}

@media (forced-colors: active) {
  .btn, .chip, .opt .tick, .switch, .stepper, .search, .field, .card, .prod > article, .citem, .order { border: 1px solid ButtonText; }
  .opt[aria-checked="true"] .tick, .switch[aria-checked="true"], .progress i, .track .node.done i { background: Highlight; forced-color-adjust: none; }
  .tab[aria-current="page"] { outline: 2px solid Highlight; outline-offset: -3px; }
}

::view-transition-old(root), ::view-transition-new(root) { animation-duration: var(--dur-1); }

/* ---------- Zdjęcia produktów ---------- */

.foto {
  position: relative; flex: none; display: block; overflow: hidden;
  border-radius: var(--r-1);
}
.foto img { width: 100%; height: 100%; object-fit: cover; display: block; }
.foto-s { width: 32px; height: 32px; }
.foto-r { width: 40px; height: 40px; }
.foto-m { width: 54px; height: 54px; }
.foto-l { width: 66px; height: 66px; }
.foto-hero {
  width: calc(100% - 2 * var(--gutter)); height: 148px;
  margin: var(--s-2) var(--gutter) 0;
  border-radius: var(--r-4);
}
/* Jasne kadry (chleb, krem) zlewałyby się z białą kartą — cienki wewnętrzny
   pierścień w kolorze marki domyka krawędź bez rysowania ramki obok zdjęcia. */
.foto::after {
  content: ""; position: absolute; inset: 0; border-radius: inherit;
  box-shadow: inset 0 0 0 1px rgba(29, 5, 60, .10);
  pointer-events: none;
}
.thumbs .foto { border-radius: var(--r-2); }
/* ---------- Ekran wejścia ---------- */

#splash {
  position: fixed; inset: 0; z-index: 200;
  display: flex;
  flex-direction: column; align-items: center; justify-content: center; gap: var(--s-6);
  padding: var(--s-8);
  background: var(--grad-brand);
  /* Zapas na wypadek, gdyby moduł się nie wczytał: po 6 s ekran schodzi sam,
     żeby zamiast aplikacji nie zostało samo logo. Kod zdejmuje go wcześniej. */
  animation: splashZapas 380ms var(--ease-out) 6s forwards;
}
@keyframes splashZapas { to { opacity: 0; visibility: hidden; } }

.sp-znak {
  display: flex; flex-direction: column; align-items: center; gap: var(--s-2);
  animation: splashZnak 620ms var(--ease-out) both;
}
#splash img { width: min(210px, 62vw); height: auto; filter: brightness(0) invert(1); }
.sp-tag {
  font-size: var(--t-12); font-weight: 700;
  letter-spacing: .34em; text-transform: uppercase; text-indent: .34em;
  color: var(--accent);
  animation: splashTag 700ms var(--ease-out) 220ms both;
}
@keyframes splashZnak {
  from { opacity: 0; transform: translateY(10px) scale(.97); }
}
@keyframes splashTag {
  from { opacity: 0; letter-spacing: .12em; }
}

.splash-pasek {
  display: block; width: 132px; height: 3px; border-radius: 2px;
  background: rgba(243, 242, 247, .2); overflow: hidden;
  animation: splashTag 500ms var(--ease-out) 380ms both;
}
.splash-pasek i {
  display: block; width: 40%; height: 100%; border-radius: 2px;
  background: var(--accent);
  animation: splashSuw 1.1s var(--ease-out) infinite;
}
@keyframes splashSuw {
  0% { transform: translateX(-100%); }
  100% { transform: translateX(330%); }
}

.sp-nota {
  position: absolute; left: 0; right: 0; bottom: calc(var(--sab) + var(--s-6));
  text-align: center;
  font-size: var(--t-11); font-weight: 600;
  letter-spacing: .18em; text-transform: uppercase;
  color: rgba(243, 242, 247, .38);
  animation: splashTag 600ms var(--ease-out) 520ms both;
}

/* Wyjście: ekran odjeżdża lekko do przodu i gaśnie, treść wchodzi pod spodem. */
#splash.znika {
  opacity: 0; transform: scale(1.04);
  transition: opacity 340ms var(--ease-in), transform 420ms var(--ease-out);
  pointer-events: none;
}

@media (prefers-reduced-motion: reduce) {
  .sp-znak, .sp-tag, .splash-pasek, .sp-nota { animation: none; }
  .splash-pasek i { animation: none; width: 100%; }
  #splash.znika { transform: none; transition: opacity 200ms linear; }
}

/* ---------- Szkielet na czas pobierania ---------- */

.szkielet { padding: var(--s-4) var(--gutter) 0; display: block; }
.sk {
  display: block; border-radius: var(--r-3);
  background:
    linear-gradient(100deg, var(--surface) 38%, var(--brand-soft) 50%, var(--surface) 62%)
    0 0 / 300% 100%;
  animation: polysk 1.25s linear infinite;
}
@keyframes polysk { to { background-position: -200% 0; } }

.sk-pas { display: flex; gap: var(--s-3); margin-bottom: var(--s-4); }
.sk-kafel { flex: 1; height: 58px; }
.sk-hero { height: 168px; border-radius: var(--r-4); margin-bottom: var(--s-4); }
.sk-chipy { margin-bottom: var(--s-5); }
.sk-chip { flex: 1; height: 32px; border-radius: var(--r-pill); }
.sk-tytul { width: 42%; height: 18px; border-radius: var(--r-1); margin-bottom: var(--s-3); }
.sk-wiersz { height: 74px; margin-bottom: var(--s-4); }

/* Szkielet znika razem z animacjami — przy wyłączonym ruchu zostaje sam
   spokojny kształt, bez pulsowania. */
@media (prefers-reduced-motion: reduce) {
  .sk { animation: none; background: var(--surface); }
}

/* ---------- Wejście zawartości zakładki ---------- */

/* Grupy i pasy pulpitu są przezroczyste dla układu, dopóki nie wejdzie
   układ webowy — na telefonie bloki lecą jeden pod drugim jak zawsze. */
.kol, .pas { display: contents; }

.view.entering > *, .kol > *, .pas > * { animation: rise 260ms var(--ease-out) both; }
.view.entering > *:nth-child(1) { animation-delay: 0ms; }
.view.entering > *:nth-child(2) { animation-delay: 45ms; }
.view.entering > *:nth-child(3) { animation-delay: 90ms; }
.view.entering > *:nth-child(4) { animation-delay: 135ms; }
.view.entering > *:nth-child(5) { animation-delay: 175ms; }
.view.entering > *:nth-child(6) { animation-delay: 210ms; }
.view.entering > *:nth-child(7) { animation-delay: 240ms; }
.view.entering > *:nth-child(n+8) { animation-delay: 265ms; }

/* Wejście listy po przełączeniu zakładki — krótsze, bez opóźnień kaskady */
.view.wchodzi > * { animation: rise 200ms var(--ease-out) both; }

/* Pozycje list wchodzą własną kaskadą. Bez tego cała lista pojawia się jako
   jeden blok i ruch kończy się, zanim oko zdąży za nim pójść. */
.view.entering .plist > li,
.view.wchodzi .plist > li { animation: rise 240ms var(--ease-out) both; }
.view.entering .plist > li:nth-child(2), .view.wchodzi .plist > li:nth-child(2) { animation-delay: 45ms; }
.view.entering .plist > li:nth-child(3), .view.wchodzi .plist > li:nth-child(3) { animation-delay: 85ms; }
.view.entering .plist > li:nth-child(4), .view.wchodzi .plist > li:nth-child(4) { animation-delay: 120ms; }
.view.entering .plist > li:nth-child(5), .view.wchodzi .plist > li:nth-child(5) { animation-delay: 150ms; }
.view.entering .plist > li:nth-child(n+6), .view.wchodzi .plist > li:nth-child(n+6) { animation-delay: 175ms; }

/* Potwierdzenie dodania na samym wierszu — pierścień w kolorze akcji gaśnie
   w 700 ms. Przy liście dwudziestu pozycji sam licznik w pasku nie mówi,
   która trafiła do koszyka. */
.prod.dodano > article { animation: mrugniecie 700ms var(--ease-out); }
@keyframes mrugniecie {
  0% { box-shadow: var(--hairline), 0 0 0 0 var(--accent); }
  22% { box-shadow: var(--hairline), 0 0 0 3px var(--accent); }
  100% { box-shadow: var(--hairline), 0 0 0 0 rgba(255, 228, 2, 0); }
}
@media (prefers-reduced-motion: reduce) {
  .view.entering .plist > li, .view.wchodzi .plist > li,
  .prod.dodano > article { animation: none; }
}

/* ================================================================
   Układ desktopowy — osobny, nie przeskalowany telefon (≥ 1040 px)

   Do 1039 px aplikacja zostaje telefonem (na tablecie w atrapie
   urządzenia). Powyżej: pasek zakładek staje się bocznym menu,
   arkusze wyśrodkowanymi oknami, katalog dwiema kolumnami.
   ================================================================ */

@media (min-width: 1040px) {
  :root {
    --gutter: 28px;
  }

  /* Aplikacja wypełnia okno — żadnej ramki ani pasów po bokach.
     Szerokość biorą kolumny katalogu, nie sztuczny limit kontenera. */
  body { background: var(--bg); }

  #app {
    inset: 0; max-width: none; height: 100%;
    display: grid;
    grid-template-columns: clamp(232px, 18vw, 300px) minmax(0, 1fr);
    grid-template-rows: auto auto minmax(0, 1fr);
    grid-template-areas:
      "siec  siec"
      "menu  tresc";
    border-radius: 0;
  }

  .offline { grid-area: siec; }
  .widoki { grid-area: tresc; }
  .tabbar { grid-area: menu; }

  /* ---------- Boczne menu ---------- */

  /* Menu bez ozdób: pasek marki, lista pozycji, konto przy dolnej krawędzi.
     Aktywna pozycja oznaczona listwą i wagą pisma, nie wypełnionym prostokątem
     — wypełnienie przykuwa oko do nawigacji, a pracuje się w treści. */
  .tabbar {
    display: flex; flex-direction: column; align-items: stretch;
    gap: 1px;
    padding: 0 var(--s-3) var(--s-4);
    background: var(--surface);
    box-shadow: 1px 0 0 var(--line-soft);
    overflow-y: auto;
  }

  .rail-brand {
    display: flex; align-items: center;
    height: 62px; margin: 0 calc(-1 * var(--s-3)) var(--s-4);
    padding: 0 var(--s-4);
    box-shadow: 0 1px 0 var(--line-soft);
  }
  .rail-brand img { width: 132px; height: auto; }

  .tab {
    position: relative;
    flex-direction: row; justify-content: flex-start; gap: var(--s-3);
    height: auto; min-height: 38px;
    padding: 0 var(--s-3);
    border-radius: var(--r-1);
    color: var(--text-2);
    transition: background var(--dur-1) var(--ease-out), color var(--dur-1) var(--ease-out);
  }
  .tab:hover { background: var(--bg); color: var(--brand-deep); }
  .tab .ico { width: 20px; height: 20px; background: none; }
  .tab .ico svg { width: 19px; height: 19px; }
  .tab[aria-current="page"] .ico { background: none; }
  .tab .lab { font-size: var(--t-13); font-weight: 600; }
  .tab[aria-current="page"] { background: var(--brand-soft); color: var(--brand-deep); }
  .tab[aria-current="page"] .lab { font-weight: 700; }
  .tab[aria-current="page"]::before {
    content: ""; position: absolute; left: calc(-1 * var(--s-3)); top: 6px; bottom: 6px;
    width: 3px; border-radius: 0 2px 2px 0; background: var(--brand);
  }
  .tab .badge { position: static; margin-left: auto; box-shadow: none; }

  /* Koszyk mieszka w pasku górnym — w nawigacji byłby drugim wejściem. */
  .tab[data-tab="koszyk"] { display: none; }

  /* Skaner zostaje w menu tylko na urządzeniu dotykowym; przy klawiaturze
     jego rolę pełni „Szybkie zamawianie" w pasku górnym. */
  .tab-scan {
    position: relative; order: 5;
    display: inline-flex; flex-direction: row; align-items: center; justify-content: center; gap: var(--s-2);
    height: auto; min-height: var(--btn-h);
    margin-top: var(--s-7); padding: 0 var(--s-4);
    border-radius: var(--r-2);
    background: var(--accent); color: var(--on-accent);
    font-size: var(--t-15); font-weight: 700;
  }
  .tab-scan:hover { background: var(--accent); color: var(--on-accent); filter: brightness(.95); }
  .tab-scan .orb { width: 20px; height: 20px; margin: 0; background: none; color: inherit; box-shadow: none; }
  .tab-scan .lab { margin: 0; font-size: var(--t-15); font-weight: 700; }

  /* Etykieta grupy — bez niej cztery zakładki, przycisk akcji i linki stopki
     czytają się jak jedna długa lista. */


  .rail-stopka {
    display: block; order: 10;
    margin-top: auto; padding-top: var(--s-5);
    border-top: 1px solid var(--line-soft);
  }
  .rail-link {
    display: flex; align-items: center; gap: var(--s-2);
    width: 100%; text-align: left;
    min-height: 38px; padding: 0 var(--s-3);
    border-radius: var(--r-1);
    font-size: var(--t-13); font-weight: 600; color: var(--mut);
  }
  .rail-link:hover { background: var(--surface-2); color: var(--brand-deep); }
  .rail-link svg { flex: none; }

  /* Konto na dole menu — wzorzec z paneli administracyjnych: tożsamość siedzi
     przy krawędzi, nie w nawigacji. */
  .rail-konto {
    display: flex; align-items: center; gap: var(--s-3);
    width: 100%; margin-top: var(--s-4); padding: var(--s-2) var(--s-3);
    border-radius: var(--r-2); text-align: left;
    background: var(--surface-2); color: var(--text-2);
  }
  .rail-konto:hover { background: var(--brand-soft); color: var(--brand-deep); }
  .rk-avatar {
    flex: none; width: 34px; height: 34px;
    border-radius: var(--r-pill);
    display: grid; place-items: center;
    background: var(--brand); color: var(--on-dark);
    font-size: var(--t-11); font-weight: 800; letter-spacing: .04em;
  }
  .rk-body { flex: 1; min-width: 0; }
  .rk-body strong { display: block; font-size: var(--t-13); font-weight: 700; color: var(--text-1);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .rk-body span { display: block; font-size: var(--t-11); color: var(--mut);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .rail-nota {
    margin-top: var(--s-3); padding: 0 var(--s-3);
    font-size: var(--t-11); color: var(--mut); line-height: 1.4;
  }

  /* ---------- Kolumna treści ---------- */

  /* Pasek przewijania z powrotem widoczny — na myszy to jedyny sygnał,
     że pod krawędzią jest jeszcze treść. */
  .view { padding-bottom: var(--s-8); scrollbar-width: thin; scrollbar-color: var(--line-mid) var(--bg); }
  .view::-webkit-scrollbar { display: block; width: 12px; }
  .view::-webkit-scrollbar-thumb { background: var(--line-mid); border: 4px solid var(--bg); border-radius: 99px; }
  .view::-webkit-scrollbar-track { background: var(--bg); }

  /* Kolumna robocza dla widoków jednokolumnowych — karta zamówienia rozciągnięta
     na 1600 px jest nieczytelna, oko gubi początek wiersza. Katalog zostaje
     płynny, bo tam siatka sama wypełnia każdą szerokość. */
  .view:not([data-tab="katalog"]) { padding-inline: max(0px, (100% - 1180px) / 2); }

  .topbar, .hello { padding-top: var(--s-6); padding-bottom: var(--s-4); }
  .h1-page { font-size: var(--t-36); }
  .spacer-nav { height: var(--s-4); }

  /* Katalog skaluje się sam: tyle kolumn, ile zmieści się kart o sensownej
     szerokości. Bez progów na konkretne rozdzielczości. */
  .plist {
    display: grid; grid-template-columns: repeat(auto-fill, minmax(288px, 1fr));
    gap: var(--s-4);
    align-items: start;
  }
  .plist > li + li { margin-top: 0; }

  /* Karta produktu staje się pionowa: zdjęcie u góry dostaje wreszcie miejsce,
     a nazwa nie walczy o szerokość ze stepperem. */
  .plist { align-items: stretch; }
  .plist > .prod { display: flex; }
  .prod > article {
    flex-direction: column; gap: var(--s-3);
    width: 100%; padding: var(--s-3);
    box-shadow: var(--hairline), var(--sh-1);
  }
  .prod:hover > article { box-shadow: inset 0 0 0 1px var(--line-mid), var(--sh-2); }
  .prod .foto, .prod .ilu { width: 100%; height: 160px; border-radius: var(--r-3); }
  .prod .body { width: 100%; padding: 0 var(--s-1); }
  .prod .typ { -webkit-line-clamp: 2; min-height: 2.6em; }
  .prod .qadd, .prod .stepper {
    position: static; align-self: flex-end; margin-top: auto;
  }

  .card, .citem, .order { cursor: default; }
  .card-w-drodze:hover, .order:hover { box-shadow: var(--hairline), var(--sh-2); }

  /* ---------- Arkusze jako okna ---------- */

  .sheet {
    left: 50%; right: auto; bottom: auto; top: 50%;
    width: min(680px, calc(100% - 96px));
    max-height: min(84%, 860px);
    border-radius: var(--r-5);
    transform: translate(-50%, -46%) scale(.97);
    opacity: 0;
    transition: transform var(--dur-3) var(--ease-out), opacity var(--dur-2) var(--ease-out);
  }
  .sheet[data-open="true"] { transform: translate(-50%, -50%) scale(1); opacity: 1; }
  .sheet[data-open="false"] { transform: translate(-50%, -48%) scale(.98); opacity: 0; }
  .sheet-head .grip { display: none; }
  .sheet .foot { padding-bottom: var(--s-4); border-radius: 0 0 var(--r-5) var(--r-5); }

  /* Pod paskiem, nie na nim: pasek ma 62 px, a toast siadał na 52 px, więc
     wchodził na niego dziesięcioma pikselami i stykał się z przyciskiem
     koszyka. Oba mają to samo tło (--ink), więc zlewały się w jedną plamę.
     Jasna obwódka daje toastowi własną krawędź nad ciemnym przyciskiem. */
  .toast {
    left: auto; right: var(--s-6); width: min(420px, 34vw);
    top: calc(var(--sat) + 62px + var(--s-3));
    box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .14), 0 10px 30px rgba(18, 2, 42, .35), var(--sh-2);
  }

  /* Karta instalacji w rogu — na desktopie nie ma paska zakładek, nad którym
     miałaby siedzieć, a QR nie powinien zasłaniać treści. */
  /* Gdyby ktoś wywołał kartę z menu — siada nad treścią po lewej, z dala od
     kolumny roboczej, którą wcześniej przykrywała w całości. */
  .instal { left: var(--s-6); right: auto; bottom: var(--s-6); width: 320px; }

  /* Filtry mają dość miejsca, żeby się zawinąć — poziome przewijanie
     na myszy chowa połowę kategorii poza krawędzią. */
  .chips {
    flex-wrap: wrap; overflow: visible;
    -webkit-mask-image: none; mask-image: none;
  }

  /* Sam plus nie mówi, co zrobi. Przy kursorze jest miejsce na słowo. */
  .prod .qadd {
    display: inline-flex; align-items: center; justify-content: center; gap: var(--s-2);
    width: auto; padding: 0 var(--s-4);
  }
  .prod .qadd::after { content: "Dodaj"; font-size: var(--t-13); font-weight: 700; }
  .prod .qadd.obs::after { content: "Powiadom"; }

  /* ---------- Logowanie ---------- */

  .login { justify-content: center; align-items: center; padding: var(--s-8); }
  .login > * { width: 100%; max-width: 440px; }
  .login h1 { font-size: var(--t-36); }
}

/* Duży monitor: więcej powietrza i wyższe zdjęcia, liczba kolumn wynika
   z auto-fill powyżej. */
@media (min-width: 1600px) {
  :root { --gutter: 36px; }
  .prod .foto, .prod .ilu { height: 160px; }
}


/* Skaner ma sens tam, gdzie aparat jest pod ręką. Przy samej myszy zostaje
   szybkie zamawianie po kodzie — wzorzec „quick order pad" z B2B: kod, ilość,
   cena kontraktowa przy wierszu, koszyk bez wchodzenia na kartę produktu. */
@media (min-width: 1040px) and (pointer: fine) and (hover: hover) {
  .tab-scan { display: none; }
}
@media (min-width: 1040px) and (pointer: coarse) {
  .tab-scan { order: 5; }
}

/* Mysz zamiast palca: wszędzie, gdzie jest kursor, pokaż że element klika. */
@media (hover: hover) and (pointer: fine) {
  .prod, .card-w-drodze, .order, .chip, .opt, .kat-kafel { cursor: pointer; }
  .btn:hover { filter: brightness(.96); }
  .link:hover { text-decoration: underline; }
}

/* ================================================================
   Warstwa webowa (≥ 1040 px)

   Telefon i desktop to dwa różne narzędzia. Na telefonie liczy się kciuk:
   duże cele dotyku, jedna kolumna, karty. Przy biurku liczy się gęstość
   informacji i mysz: pasek akcji na górze, nawigacja z boku, mniejsze
   promienie, ciaśniejsza typografia, listy zamiast kart.
   ================================================================ */

@media (min-width: 1040px) {
  :root {
    /* Cele dotyku schodzą do rozmiarów dla myszy — 48 px pod kursorem to
       marnowana przestrzeń, nie dostępność. */
    --hit: 36px;
    --hit-row: 34px;
    --btn-h: 40px;
    --gutter: 28px;

    /* Promienie telefonu (20–28 px) na monitorze wyglądają jak zabawka. */
    --r-2: 8px;
    --r-3: 10px;
    --r-4: 12px;
    --r-5: 16px;
  }

  body { font-size: var(--t-13); }

  #app {
    grid-template-rows: auto auto minmax(0, 1fr);
    grid-template-areas:
      "siec  siec"
      "menu  gora"
      "menu  tresc";
  }

  /* ---------- Górny pasek akcji ---------- */

  /* Szukanie to główna czynność w aplikacji zamówieniowej, więc dostaje
     najwięcej miejsca w pasku i największy stopień pisma na tym ekranie. */
  .topweb {
    grid-area: gora;
    display: flex; align-items: center; gap: var(--s-3);
    height: 62px; padding: 0 var(--gutter);
    background: var(--surface);
    box-shadow: 0 1px 0 var(--line-soft);
  }
  /* Akcje odsunięte od szukania i zamknięte w jedną grupę z przegrodą —
     inaczej trzy przyciski o różnej wadze rozjeżdżają się po pasku. */
  .topweb .tw-akcja { margin-left: auto; }
  .topweb .tw-ikona {
    margin-left: var(--s-2);
    position: relative;
  }
  .topweb .tw-ikona::before {
    content: ""; position: absolute; left: calc(-1 * var(--s-2) - 1px); top: 10px; bottom: 10px;
    width: 1px; background: var(--line-soft);
  }

  .tw-pole {
    /* Pole rozciągnięte na całą wolną szerokość wygląda jak pusta płyta,
       a znacznik skrótu ucieka kilkaset pikseli od kursora. */
    flex: 1 1 auto; min-width: 0; max-width: 560px;
    display: flex; align-items: center; gap: var(--s-3);
    height: 42px; padding: 0 var(--s-4);
    border-radius: var(--r-2);
    background: var(--bg); color: var(--mut);
    box-shadow: inset 0 0 0 1px var(--line);
    transition: box-shadow var(--dur-1) var(--ease-out), background var(--dur-1) var(--ease-out);
  }
  .tw-pole:hover { box-shadow: inset 0 0 0 1px var(--line-mid); }
  .tw-pole:focus-within { box-shadow: inset 0 0 0 2px var(--brand); background: var(--surface); }
  .tw-pole svg { width: 19px; height: 19px; }
  .tw-pole input {
    flex: 1; min-width: 0; border: 0; outline: 0; background: none;
    font-size: var(--t-15); font-weight: 500; color: var(--text-1);
  }
  .tw-pole input::placeholder { color: var(--mut); font-weight: 400; }
  .tw-pole input::-webkit-search-cancel-button { display: none; }
  .tw-skrot {
    flex: none; padding: 1px 6px;
    border-radius: 5px;
    background: var(--surface); box-shadow: inset 0 0 0 1px var(--line);
    font-family: var(--font-ui); font-size: var(--t-11); font-weight: 700; color: var(--mut);
  }
  .tw-pole:focus-within .tw-skrot { visibility: hidden; }

  /* W pasku górnym lista wisi pod polem, nie pod całą belką. */
  .topweb { position: relative; }
  .podp { left: var(--gutter); right: auto; width: min(560px, calc(100% - 2 * var(--gutter))); top: 100%; margin-top: 0; }

  .tw-akcja {
    flex: none;
    display: inline-flex; align-items: center; gap: var(--s-2);
    height: 42px; padding: 0 var(--s-4);
    border-radius: var(--r-2);
    background: none; color: var(--brand-deep);
    box-shadow: inset 0 0 0 1px var(--line-mid);
    font-size: var(--t-13); font-weight: 600;
  }
  .tw-akcja:hover { background: var(--bg); box-shadow: inset 0 0 0 1px var(--line-strong); }

  .tw-ikona {
    position: relative; flex: none;
    width: 42px; height: 42px;
    display: grid; place-items: center;
    border-radius: var(--r-2);
    color: var(--text-2);
  }
  .tw-ikona:hover { background: var(--bg); color: var(--brand-deep); }
  .tw-kropka {
    position: absolute; top: 10px; right: 10px;
    width: 8px; height: 8px; border-radius: 50%;
    background: var(--accent); box-shadow: 0 0 0 2px var(--surface);
  }
  .tw-kropka[hidden] { display: none; }

  /* Koszyk z kwotą — zamawiający pilnuje progu darmowej dostawy i limitu
     kredytowego, więc sama liczba pozycji nic by mu nie dała. */
  .tw-koszyk {
    flex: none;
    display: inline-flex; align-items: center; gap: var(--s-3);
    height: 42px; padding: 0 var(--s-4) 0 var(--s-3);
    margin-left: var(--s-1);
    border-radius: var(--r-2);
    background: var(--brand); color: var(--on-dark);
    text-align: left;
  }
  .tw-koszyk:hover { background: var(--brand-deep); }
  .tw-koszyk svg { flex: none; }
  .twk-info { display: block; line-height: 1.15; }
  .twk-info b { display: block; font-size: var(--t-13); font-weight: 700; }
  .twk-info small { display: block; font-size: var(--t-11); color: var(--on-dark-2); }

  /* Dzwonek i wyszukiwarka są w pasku górnym — w treści byłyby duplikatem.
     Pole w pasku jest jednocześnie filtrem katalogu, więc katalog nie ma
     drugiego. Jedna aplikacja, jedno miejsce na szukanie. */
  .widoki .bell,
  .view[data-tab="start"] .search,
  .view[data-tab="katalog"] .search { display: none; }
  .view[data-tab="katalog"] .chips { margin-top: var(--s-2); }

  /* ---------- Gęstość treści ---------- */

  .h1-page { font-size: var(--t-28); }
  .topbar { padding-top: var(--s-5); padding-bottom: var(--s-3); }
  /* Powitanie z awatarem to element ekranu logowania, nie panelu roboczego —
     firma i osoba stoją w menu, powtarzanie ich nad treścią nic nie wnosi.
     Odstęp po nim przejmuje sam widok. */
  .hello { display: none; }
  .view[data-tab="start"] { padding-top: var(--s-5); }
  .shead h2 { font-size: var(--t-15); }
  .card, .opts, .kv-list { padding: var(--s-3) var(--s-4); }
  .kv { font-size: var(--t-13); min-height: 24px; }
  .btn { min-height: var(--btn-h); font-size: var(--t-13); }
  .btn-sm { min-height: 32px; }
  .chip { min-height: 32px; padding: 0 var(--s-3); font-size: var(--t-13); }

  /* ---------- Pulpit: rząd wskaźników ---------- */

  .view[data-tab="katalog"] { padding-inline: 0; }

  /* Pulpit w pasmach na całą szerokość: stan konta, bieżące zamówienia,
     kategorie, promocje, listy pozycji. Wcześniej było to dwie kolumny
     z kolumną roboczą przy prawej krawędzi — i przy każdym zestawie danych
     jedna z nich kończyła się wyżej, zostawiając kilkaset pikseli pustego
     pola obok treści. Wysokości dwóch kolumn nie da się pogodzić, bo zależą
     od liczby promocji i od tego, czy jest zamówienie w drodze. Pasma nie
     mają tego problemu: każdy blok zajmuje tyle, ile potrzebuje. */
  .view[data-tab="start"]:not([hidden]) {
    display: block;
    padding-inline: var(--gutter);
  }
  /* Gutter przeszedł na widok, więc bloki w środku nie dokładają własnego.
     Zerujemy sam margines — padding zostaje, bo w tej grupie tylko .rail
     trzyma gutter paddingiem. Karta .promo ma własne 16 px i wyzerowanie ich
     wypychało tekst notki sezonowej na krawędź, podczas gdy sąsiednie karty
     w tym samym rzędzie miały 16–20 px. */
  .view[data-tab="start"] .rail,
  .view[data-tab="start"] .shead,
  .view[data-tab="start"] .promo,
  .view[data-tab="start"] .promo-lista,
  .view[data-tab="start"] .plist,
  .view[data-tab="start"] .pas { margin-inline: 0; }
  .view[data-tab="start"] .rail { padding-inline: 0; }

  /* Rytm pionowy pulpitu: 24 px między pasmami, 12 px od nagłówka do jego
     treści. Wcześniej wszędzie było 12 px, więc nagłówek sekcji stał
     w równej odległości od pasma nad sobą i od własnej listy — czytał się
     jak podpis pod poprzednim blokiem. */
  .view[data-tab="start"] .shead { margin-top: var(--s-6); }

  /* auto-fit, nie auto-fill: przy czterech promocjach w pięciu torach
     auto-fill zostawiał pusty tor i pasmo kończyło się 330 px przed
     krawędzią, choć pasmo nad nim i pod nim szło na pełną szerokość.
     Górna granica toru musi zostać na 1fr — przy stałej (np. 400px) tory
     nie rozciągają się na resztę i pasmo znów kończy się w połowie. */
  .view[data-tab="start"] .promo-lista {
    grid-template-columns: repeat(auto-fit, minmax(268px, 1fr));
  }

  /* Pas stanu stoi w kodzie za zamówieniami, a na pulpicie ma być pierwszy —
     stąd flex z order zamiast zmiany kolejności w szablonie (na telefonie
     kolejność jest odwrotna i poprawna). */
  .kol-stan { display: flex; flex-direction: column; }
  .kol-przegladanie, .kol-listy { display: block; }

  .pas { display: flex; align-items: stretch; gap: var(--s-4); }
  .pas:empty { display: none; }
  .pas > * { flex: 1 1 0; min-width: 0; width: auto; margin: 0 0 var(--s-4); }

  /* Bieżące zamówienia jako rząd równych kart. W pionowej kolumnie roboczej
     wyglądały lepiej, ale to ona generowała pustkę obok treści.
     Karty w rzędzie mają wspólną wysokość, więc stopka najkrótszej z nich
     idzie do dolnej krawędzi zamiast zostawiać pod sobą 78 px pustki. */
  /* Przy 1040 px trzy karty w rzędzie dostają po 240 px i stopka „9 pozycji ·
     2897,01 zł brutto + Domów" wychodzi poza kartę. Zamiast ściskać — zawijamy:
     karta ma 320 px minimum i schodzi do drugiego rzędu, kiedy zabraknie
     miejsca. */
  .pas-zamowienia { gap: var(--s-4); flex-wrap: wrap; }
  .pas-zamowienia > * { flex: 1 1 320px; }
  .wd-stopka { flex-wrap: wrap; row-gap: var(--s-2); }
  /* 24 px do pasma kategoriów pod spodem — tyle, co między pozostałymi
     pasmami. Reguła musi być bardziej szczegółowa niż `.pas > *`, która
     ustawia 16 px dla wszystkich pasów. */
  .view[data-tab="start"] .pas-zamowienia > * { margin-bottom: var(--s-6); }
  /* Jedna wartość wcięcia dla wszystkich trzech kart w rzędzie. Notka
     sezonowa miała 12 px przy 16 px sąsiadów, a karta „W drodze" trzyma
     20 px po lewej, bo tam stoi listwa statusu. */
  .pas-zamowienia > * { padding: var(--s-4); }
  .pas-zamowienia > .card-w-drodze { display: flex; flex-direction: column; padding-left: var(--s-5); }
  .pas-zamowienia > .card-w-drodze .wd-stopka { margin-top: auto; padding-top: var(--s-3); }

  /* Stan konta jako jeden pas z przegrodami, nie trzy osobne karty. Trzy
     równe kafle to układ, który sam się prosi o czwarty i piąty; pasek czyta
     się jednym spojrzeniem i zajmuje połowę wysokości. */
  .pas-wskazniki {
    order: -1;
    margin: 0 0 var(--s-6); padding: 0; gap: 0;
    border-radius: var(--r-3);
    background: var(--surface); box-shadow: var(--hairline);
  }
  /* Bez overflow: hidden na pasie — to zeruje jego automatyczną minimalną
     wysokość w siatce i cały rząd zwija się pod kolejny. Zaokrąglenie
     krawędzi bierze na siebie skrajne pole. */
  .pas-wskazniki > :first-child { border-radius: var(--r-3) 0 0 var(--r-3); overflow: hidden; }
  .pas-wskazniki > :last-child { border-radius: 0 var(--r-3) var(--r-3) 0; }
  .pas-wskazniki > * {
    min-height: 58px; margin: 0;
    padding: var(--s-3) var(--s-4);
    border-radius: 0; box-shadow: none; background: none;
    display: flex; align-items: center; gap: var(--s-3);
  }
  .pas-wskazniki > * + * { box-shadow: inset 1px 0 0 var(--line-soft); }
  .pas-wskazniki .cutoff { border-left: 0; }
  /* Nieopłacona faktura zostaje żółta, ale jako lewa listwa, nie całe pole —
     wypełnienie kolorem w pasku statusu krzyczy głośniej niż treść. */
  .pas-wskazniki .nota-platnosc { background: none; }
  .pas-wskazniki .nota-platnosc::before {
    content: ""; position: absolute; left: 0; top: 0; bottom: 0;
    width: 3px; background: var(--accent);
  }
  .pas-wskazniki .nota-platnosc { position: relative; }
  .pas-wskazniki .limit-chip { flex-direction: column; align-items: stretch; justify-content: center; gap: 6px; }



  /* ---------- Kategorie jako pasek, nie kafle ---------- */

  /* Kategorie jak chipy filtrów w katalogu — ten sam element, ta sama postać.
     Kwadratowe kafle z ikoną i podpisem pod spodem to wzorzec ekranu
     dotykowego: zajmują dwa razy więcej wysokości i łamią się na drugi rząd. */
  /* Pas kategorii ma dwa końce: pigułki od lewej, wyjście do katalogu przy
     prawej krawędzi. Bez tego drugiego dziewięć pigułek kończyło się 334 px
     przed krawędzią i pas był jedynym blokiem na stronie, który nie dobijał
     do prawej — reszta (stan konta, karty zamówień, promocje, listy) idzie
     równo do 1882 px. */
  .pas-kategorie {
    display: flex; align-items: center; gap: var(--s-4);
  }
  .rail-caly {
    display: inline-flex; align-items: center; gap: var(--s-2);
    flex: none; margin-left: auto;
    min-height: 32px; padding: 0 var(--s-3);
    border-radius: var(--r-1);
    font-size: var(--t-13); font-weight: 600; color: var(--brand);
    white-space: nowrap;
  }
  .rail-caly:hover { background: var(--surface); }
  .rail-caly svg { transform: rotate(180deg); }

  /* Jawne display:flex jest tu konieczne — bazowy .rail to siatka trzech
     równych kolumn (kafle na telefonie). Sam flex-wrap jej nie unieważnia,
     więc chipy rozciągały się na jedną trzecią szerokości ekranu każdy. */
  .rail {
    display: flex; align-items: center;
    gap: var(--s-2); margin-top: 0; padding: 0;
    flex-wrap: wrap; overflow: visible;
    -webkit-mask-image: none; mask-image: none;
  }
  /* flex-direction i justify-content MUSZĄ być tu podane wprost. Bazowy .cat
     to kafel telefonu: kolumna z ikoną nad podpisem. Samo align-items: center
     centruje wtedy w poziomie, a pionem rządzi justify-content — domyślnie
     flex-start, więc napis lądował na górnej krawędzi pigułki (0 px nad,
     16 px pod). Wyglądało to jak przesunięty tekst, a było nieprzestawionym
     kierunkiem osi. */
  .rail .cat {
    width: auto; display: inline-flex;
    flex-direction: row; align-items: center; justify-content: center;
    min-height: 32px; padding: 0 var(--s-4);
    border-radius: var(--r-pill);
    background: var(--surface); box-shadow: var(--hairline);
  }
  .rail .cat:hover { box-shadow: inset 0 0 0 1px var(--line-mid), var(--sh-1); }
  .rail .tile { display: none; }
  .rail .cat > span:last-child {
    margin: 0; min-height: 0;
    font-size: var(--t-13); font-weight: 600; white-space: nowrap; color: var(--text-2);
  }
  .rail .cat:hover > span:last-child { color: var(--brand-deep); }

  /* ---------- Karty promocji: wspólny rytm w rzędzie ----------

     Na telefonie karty stoją jedna pod drugą i nikt nie porówna, na jakiej
     wysokości wypada w nich cena. W rzędzie po cztery każda różnica wychodzi
     od razu: nazwa łamana na trzy linie przesuwała cenę o 19 px, a „karton
     10 kg" zawijane spod ceny — stopkę o kolejne 24 px.

     Cena i przycisk idą do dolnej krawędzi treści zamiast płynąć za tekstem.
     Rezerwa na stałą liczbę linii nazwy niczego by nie załatwiła — nazwy
     mają od jednej do trzech linii zależnie od liczby kolumn, więc każdy
     próg byłby dobry tylko dla jednej szerokości okna. */

  .pk-tlo { flex: 1 1 auto; }

  .pk-ceny {
    display: grid; grid-template-columns: auto minmax(0, 1fr);
    align-items: baseline; column-gap: var(--s-2); row-gap: 1px;
    flex-wrap: nowrap;
  }
  .pk-ceny s { justify-self: start; }
  .pk-ceny small { grid-column: 1 / -1; }

  /* Termin przy dolnej krawędzi. Karty w rzędzie mają wspólną wysokość, więc
     stopka przyklejona do treści zostawiała pod sobą do 56 px pustki. */
  .pk-termin { margin-top: auto; }

  /* ---------- Listy na pulpicie: wiersze, nie karty sklepowe ----------

     Karta ze zdjęciem 160 px pokazuje trzy pozycje tam, gdzie zmieści się
     osiem wierszy. Zaopatrzeniowiec nie ogląda produktów — on je odhacza
     z listy, więc liczy się liczba pozycji na ekranie i przycisk pod ręką.
     Pełne karty zostają w katalogu, gdzie przeglądanie jest celem. */

  /* 360 px to próg, poniżej którego wiersz z pełnym stepperem (kosz, liczba,
     plus — 108 px) zjada miejsce nazwie i „na trasę czw 24.09" łamie się na
     trzy linijki. Przy 300 px szerokie okno robiło pięć takich kolumn. */
  .view[data-tab="start"] .plist {
    grid-template-columns: repeat(auto-fit, minmax(360px, 1fr));
    gap: var(--s-2);
  }
  /* W siatce odstęp daje gap; margines z układu telefonu by go zdublował. */
  .plist > li + li { margin-top: 0; }
  .view[data-tab="start"] .prod > article {
    flex-direction: row; align-items: center; gap: var(--s-3);
    padding: var(--s-2) var(--s-3);
  }
  .view[data-tab="start"] .prod .foto,
  .view[data-tab="start"] .prod .ilu {
    width: 46px; height: 46px; border-radius: var(--r-1);
  }
  .view[data-tab="start"] .prod .body { width: auto; flex: 1; min-width: 0; padding: 0; }
  .view[data-tab="start"] .prod .typ { display: none; }
  .view[data-tab="start"] .prod .meta { margin-top: 1px; }
  .view[data-tab="start"] .prod .cena { font-size: var(--t-15); }
  .view[data-tab="start"] .prod .stock { margin-top: 0; font-size: var(--t-11); white-space: nowrap; }
  /* Termin trasy jest w pasku stanu nad listami; przy ośmiu wierszach naraz
     powtarzał tę samą datę osiem razy i łamał dostępność na dwie linie
     w kartach ze stepperem. */
  .view[data-tab="start"] .prod .stock-trasa { display: none; }
  .view[data-tab="start"] .prod .hist { display: none; }
  .view[data-tab="start"] .prod .qadd,
  .view[data-tab="start"] .prod .stepper { margin: 0; align-self: center; }
  .view[data-tab="start"] .prod .qadd { width: var(--hit); padding: 0; }
  .view[data-tab="start"] .prod .qadd::after { content: none; }
  /* Wiersz pulpitu ma mieć stale trzy linie: kod, nazwa z ceną, dostępność.
     Przelicznik na kilogram nie mieścił się w 230 px i spadał do własnej
     linii w co drugiej pozycji — sąsiednie karty w rzędzie rozjeżdżały się
     wtedy o całą linijkę. W katalogu, gdzie karta jest dwa razy szersza,
     przelicznik zostaje. */
  .view[data-tab="start"] .prod .perkg { display: none; }
  .view[data-tab="start"] .prod .meta { flex-wrap: nowrap; min-height: 22px; align-items: center; }
  .view[data-tab="start"] .prod .meta .pill { flex: none; }

  /* Karty pasma stanu są szerokie (500-800 px), więc treść układa się w nich
     poziomo. Rozciągnięty układ pionowy dawał przycisk „Ponów zamówienie"
     szerokości 730 px i zdjęcie wysokie na 64 px przez całą kartę — to nie
     jest karta zaprojektowana na taką szerokość, tylko kafel telefonu
     naciągnięty na pasmo. */
  .pas-zamowienia .reorder {
    display: flex; align-items: flex-end; gap: var(--s-4);
  }
  .pas-zamowienia .reorder .reorder-tresc { position: relative; flex: 1; min-width: 0; }
  .pas-zamowienia .reorder .thumbs { margin-bottom: 0; }
  .pas-zamowienia .reorder .btn { flex: none; width: auto; padding-inline: var(--s-5); }

  .pas-zamowienia .promo { flex-direction: row; align-items: flex-start; gap: var(--s-4); }
  .pas-zamowienia .promo .foto,
  .pas-zamowienia .promo .ilu {
    flex: none; width: 168px; height: 108px; border-radius: var(--r-2);
  }
  .pas-zamowienia .promo .foto img { object-position: center 45%; }
  .pas-zamowienia .promo h3 { margin-top: 2px; }
  /* Na telefonie notka jest przycięta do trzech wierszy, bo zjadałaby pół
     ekranu. W kolumnie roboczej miejsce jest, a zdanie urwane na „zaczynają
     się w połowie…" wygląda jak błąd, nie jak skrót. Samo display:block
     zdejmuje przycięcie — działa ono wyłącznie na -webkit-box. */
  .pas-zamowienia .promo p { display: block; overflow: visible; }

  /* ---------- Koszyk ---------- */

  /* Pozycje koszyka to lista do odhaczenia, nie wystawa. Klasa .plist dawała
     im siatkę katalogu, więc trzy pozycje stawały obok siebie jak kafle
     produktowe — stepper, kwota i skróty „warstwa/paleta" dusiły się wtedy
     w 300 px, a czwarta pozycja zaczynała drugi rząd. */
  #koszykLista {
    display: flex; flex-direction: column; gap: var(--s-2);
  }
  #koszykLista > li + li { margin-top: 0; }
  #koszykLista .citem { align-items: center; padding: var(--s-2) var(--s-3); }
  #koszykLista .citem .body {
    display: grid; align-items: center;
    grid-template-columns: minmax(0, 1fr) auto auto;
    column-gap: var(--s-4);
  }
  #koszykLista .citem h3 { grid-column: 1; grid-row: 1; }
  #koszykLista .citem .sub { grid-column: 1; grid-row: 2; }
  #koszykLista .citem .packrow { grid-column: 2; grid-row: 1 / -1; margin: 0; }
  #koszykLista .citem .linia-ilosc { grid-column: 3; grid-row: 1 / -1; margin: 0; }
  #koszykLista .citem .kwota { min-width: 104px; text-align: right; }

  /* ---------- Katalog ---------- */

  .prod > article { padding: var(--s-2) var(--s-2) var(--s-3); gap: var(--s-2); }
  .prod .foto, .prod .ilu { height: 140px; border-radius: var(--r-2); }
  .prod-name { font-size: 14px; }
  .prod .cena { font-size: var(--t-15); }
  /* Ceny sąsiednich kart mają stać w jednej linii. Przelicznik na kilogram
     przy wąskiej kolumnie zawijał się pod cenę i podnosił resztę karty. */
  .prod .meta { flex-wrap: nowrap; min-height: 24px; align-items: center; }
  .prod .perkg { overflow: hidden; text-overflow: ellipsis; }
  /* Serce ulubionych jest wyższe od kodu SKU obok, więc karta z ulubionym
     produktem miała całą treść 5 px niżej niż sąsiadka. Stała wysokość
     pierwszej linii wyrównuje oba warianty. */
  .prod .sku { min-height: 18px; align-items: center; }

  /* Znacznik promocji idzie w róg zdjęcia. W linii z ceną zabierał miejsce
     przelicznikowi na kilogram — a to jego porównuje się między dostawcami,
     więc to nie on ma być ucinany do „5,39 zł/…". */
  .view[data-tab="katalog"] .prod .meta .pill {
    position: absolute; top: var(--s-3); left: var(--s-3); z-index: 1;
    box-shadow: 0 1px 2px rgba(29, 5, 60, .18);
  }
}

/* Tabela zamówień dopiero od 1280 px. Przy 1040 px kolumna treści ma 808 px,
   a siedem torów wraz z przyciskami akcji potrzebuje ponad 750 px samej
   siatki — wiersze wychodziły poza kartę. Niżej zamówienie zostaje kartą
   z układu telefonu, która czyta się na każdej szerokości. */
@media (min-width: 1280px) {
  /* ---------- Zamówienia jako tabela ---------- */

  /* Tabela dostaje 40 px ponad wspólną kolumnę roboczą — dokładnie tyle,
     ile trzeba, żeby siedem kolumn zmieściło się bez ucinania nazwy kanału.
     Szerzej nie idziemy: nadmiar rozlałby się w przerwę między miniaturami
     a kwotą i wiersz przestałby się czytać jednym rzutem oka. */
  .view[data-tab="zamowienia"] { padding-inline: max(0px, (100% - 1220px) / 2); }

  #listaZam {
    margin: 0 var(--gutter);
    border-radius: var(--r-3); overflow: hidden;
    background: var(--surface); box-shadow: var(--hairline);
  }
  .order {
    display: grid; align-items: center;
    /* nr | status | termin | miniatury | kwota | akcje

       Żadnej kolumny na auto. Przy auto szerokość liczy się z zawartości
       wiersza, więc zamówienie z trzema miniaturami odsuwało kwotę o 59 px
       względem zamówienia z pięcioma, a przyciski każdego wiersza zaczynały
       się w innym miejscu. Tory podane wprost są identyczne w każdym wierszu,
       więc kolumny stoją w pionie niezależnie od treści.

       Kolumna kanału dochodzi dopiero od 1440 px (niżej) — przy węższym oknie
       nie mieści się bez ucinania nazw kanału do „Z APLIK…". */
    grid-template-columns: 76px 110px 118px minmax(222px, 1fr) 150px 238px;
    column-gap: var(--s-3); row-gap: var(--s-2);
    margin: 0; padding: var(--s-3) var(--s-4);
    border-radius: 0; box-shadow: none;
    border-bottom: 1px solid var(--line-soft);
  }
  .order:last-child { border-bottom: 0; }
  .order:hover { background: var(--surface-2); }
  .order .head { display: contents; }
  .order .head h3 { font-size: var(--t-15); }
  .order .head .pill { justify-self: start; }
  .order .head .when { font-size: var(--t-12); color: var(--mut); }
  .order .kanal { display: none; }
  .order .mini-rzad { grid-column: 4; grid-row: 1; margin: 0; overflow: hidden; }
  .order .order-sum { grid-column: 5; grid-row: 1; margin: 0; padding: 0; border: 0; justify-content: flex-end; text-align: right; }
  .order .order-sum > span:first-child { display: none; }
  /* Adnotacja dostaje własny rząd pod całą szerokością. Bez jawnego numeru
     rzędu wypychała akcje do trzeciego rzędu, więc przyciski raz stały obok
     kwoty, raz pod wierszem. */
  .order .note { grid-column: 1 / -1; grid-row: 2; margin: 0; }
  /* Akcje w kolumnie, nie w osobnym rzędzie — rozciągnięte przyciski robiły
     z wiersza tabeli dwupiętrowy kafel. */
  .order .acts { grid-column: -2; grid-row: 1; justify-content: flex-end; gap: var(--s-2); margin: 0; }
  .order .acts .btn { flex: none; width: auto; padding-inline: var(--s-4); white-space: nowrap; }
  /* W tabeli akcje mają stały tor 238 px — „Domów do dostawy" go rozpycha
     i wchodzi na kolumnę kwoty. Sam czasownik wystarczy obok statusu
     „W realizacji", a na karcie zamówienia na telefonie zostaje pełny. */
  .order .akcja-dopisek { display: none; }
}

/* Szerokie okno: w tabeli zamówień mieści się kanał — aplikacja, opiekun,
   moja.zeelandia.pl. Kolumna jest dostawiana, a nie ściskana z innych, więc
   węższe okno po prostu jej nie pokazuje. Próg to 1520 px, nie 1440: dopiero
   tam kolumna robocza dobija do swoich 1220 px i najdłuższa nazwa kanału
   mieści się w całości. Przy 1440 px tor spadał do minimum i ucinał ją. */
@media (min-width: 1520px) {
  .order {
    grid-template-columns:
      76px 110px 118px minmax(130px, 200px) minmax(222px, 1fr) 150px 238px;
  }
  .order .kanal {
    display: block; grid-column: 4; grid-row: 1; margin: 0;
    font-size: var(--t-11); letter-spacing: .04em;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  }
  /* Data złożenia stoi już w kolumnie terminu — w komórce kanału była tą samą
     liczbą drugi raz i to ona wypychała „z moja.zeelandia.pl" poza krawędź. */
  .order .kanal-data { display: none; }
  .order .mini-rzad { grid-column: 5; }
  .order .order-sum { grid-column: 6; }
}

/* ================================================================
   Rytm pulpitu na telefonie

   Odstęp między kartami musi być większy niż ich wewnętrzny padding —
   przy 12 px bloki czytały się jak jedna płachta poprzecinana kreskami.
   Warunek max-width nie zachodzi na warstwę webową (min-width: 1040px),
   więc te reguły dotyczą wyłącznie telefonu i tabletu.
   ================================================================ */

@media (max-width: 1039.98px) {
  .card-w-drodze,
  .reorder,
  .promo,
  .nota-platnosc,
  .limit-chip,
  .cutoff,
  .search { margin-bottom: var(--s-4); }

  .rail { margin-top: var(--s-5); }
  .shead { margin-top: var(--s-6); }
  .hello + .kol .card-w-drodze,
  .hello + .kol .reorder { margin-top: var(--s-4); }
}
