/* ==========================================================================
   Webs Butler — portal design system
   One stylesheet for the logged-out tools landing and the logged-in portal.
   Light is the base; dark overrides only the tokens.
   ========================================================================== */

/* Every tool is still its own server-rendered page (no client-side router), so
   navigating between them is a real document load. Chrome/Edge can cross-fade
   that transition instead of showing a blank flash in between — the old
   page's frame (wallpaper included) stays on screen and dissolves into the
   new one, which is what makes it read as one app rather than a stack of
   separate pages. Pure CSS, no JS: unsupported browsers just keep the old
   flash-then-load behaviour, nothing breaks. */
@view-transition {
  navigation: auto;
}

/* ---- tokens -------------------------------------------------------------- */
/* The panel is monochrome by design: neutral glass panels that sit over a photo
   wallpaper the client picks. Colour comes from two places only — the status
   tokens (ok/warn/bad) and --wb-accent, which each wallpaper sets to a value
   sampled from the photo and checked to at least 4.6:1 against the panel behind
   it. Nothing else is tinted, so any wallpaper works without a redesign. */
:root {
  /* Overridden per wallpaper further down. This is the no-wallpaper value, and
     the one place the brand purple still leads. */
  --wb-accent: #8e2de2;

  /* Text and icons *on* a filled accent surface. Flips with the theme because
     the dark-mode accents are light colours — white on #30cfb9 is unreadable,
     near-black on it is not. */
  --wb-accent-contrast: #ffffff;

  /* Kept as names because the stylesheet refers to them in ~25 places, but they
     are no longer brand purple: every filled "brand" surface is now the
     wallpaper's accent, and the glow under it is neutral rather than coloured
     so it reads as depth instead of a second hue. */
  --wb-brand-1: var(--wb-accent);
  --wb-brand-2: rgba(10, 10, 14, 0.42);
  --wb-brand-grad: var(--wb-accent);

  /* The wallpaper layer. --wb-wp is an image (or none) and --wb-wp-dim is how
     hard the scrim over it is pushed — both are written onto <html> by the
     server from the client's saved preference. */
  --wb-wp: none;
  --wb-wp-dim: 0.65;
  --wb-scrim: #f2f2f4;

  --wb-bg: #eeeef1;

  /* Panels are translucent so the wallpaper reads through them, but never so
     translucent that body text has to compete with the photo. 0.72 over the
     scrim is the floor that keeps text at AA on every preset. */
  --wb-surface: rgba(255, 255, 255, 0.72);
  --wb-surface-solid: #ffffff;
  --wb-surface-2: rgba(255, 255, 255, 0.48);
  --wb-surface-sunk: rgba(20, 20, 24, 0.06);

  --wb-text: #16161a;
  --wb-text-soft: #45454d;
  --wb-muted: #63636d;

  --wb-border: rgba(20, 20, 26, 0.12);
  --wb-border-strong: rgba(20, 20, 26, 0.24);

  --wb-ok: #16a34a;
  --wb-ok-bg: rgba(22, 163, 74, 0.12);
  --wb-warn: #d97706;
  --wb-warn-bg: rgba(217, 119, 6, 0.13);
  --wb-bad: #dc2626;
  --wb-bad-bg: rgba(220, 38, 38, 0.12);

  --wb-shadow-sm: 0 2px 8px rgba(10, 10, 14, 0.07);
  --wb-shadow: 0 14px 40px -12px rgba(10, 10, 14, 0.22);
  --wb-shadow-lg: 0 30px 70px -24px rgba(10, 10, 14, 0.34);
  --wb-glow: 0 0 0 1px rgba(20, 20, 26, 0.20), 0 10px 34px -12px rgba(10, 10, 14, 0.45);

  /* How hard the frosted panels blur what is behind them. One knob, because
     every glass surface in the panel should agree. */
  --wb-blur: 22px;

  --wb-r-sm: 10px;
  --wb-r: 16px;
  --wb-r-lg: 22px;
  --wb-r-pill: 999px;

  --wb-rail-w: 268px;
  --wb-bar-h: 68px;

  --wb-ease: cubic-bezier(0.22, 1, 0.36, 1);

  color-scheme: light;
}

:root[data-theme="dark"] {
  --wb-accent: #a781ff;
  --wb-accent-contrast: #16161a;

  --wb-scrim: #0b0b0d;
  --wb-bg: #0d0d10;

  --wb-surface: rgba(26, 26, 31, 0.70);
  --wb-surface-solid: #17171b;
  --wb-surface-2: rgba(40, 40, 47, 0.46);
  --wb-surface-sunk: rgba(255, 255, 255, 0.05);

  --wb-text: #f4f4f6;
  --wb-text-soft: #c8c8d0;
  --wb-muted: #94949f;

  --wb-border: rgba(255, 255, 255, 0.13);
  --wb-border-strong: rgba(255, 255, 255, 0.26);

  --wb-ok: #4ade80;
  --wb-ok-bg: rgba(74, 222, 128, 0.14);
  --wb-warn: #fbbf24;
  --wb-warn-bg: rgba(251, 191, 36, 0.14);
  --wb-bad: #f87171;
  --wb-bad-bg: rgba(248, 113, 113, 0.14);

  --wb-shadow-sm: 0 2px 10px rgba(0, 0, 0, 0.5);
  --wb-shadow: 0 16px 44px -12px rgba(0, 0, 0, 0.75);
  --wb-shadow-lg: 0 34px 80px -26px rgba(0, 0, 0, 0.88);
  --wb-glow: 0 0 0 1px rgba(255, 255, 255, 0.22), 0 12px 40px -12px rgba(0, 0, 0, 0.8);

  color-scheme: dark;
}

/* ---- wallpaper accents ---------------------------------------------------
   One pair per preset, sampled from the photo and then walked to the nearest
   lightness clearing 4.85:1 — measured not against a nominal panel colour but
   against what the panel *composites to* over that photo's most extreme pixel
   (brightest for light mode, darkest for dark), through both the scrim at the
   default 65% and the panel's own alpha. Solving against the nominal colour
   instead put the night preset at 4.35:1, i.e. under AA.

   The crater pair is deliberately NOT the photo's dominant colour: that is the
   pink sky, which covers more area than the lake but is not what anyone means
   by "the turquoise crater lake".

   Re-run the solver if a wallpaper is added or the default dim changes. */
:root[data-wp="crater"] { --wb-accent: #1c786c; }
:root[data-wp="ridge"]  { --wb-accent: #1e7680; }
:root[data-wp="forest"] { --wb-accent: #237695; }
:root[data-wp="dunes"]  { --wb-accent: #3630cf; }
:root[data-wp="night"]  { --wb-accent: #666666; }

:root[data-theme="dark"][data-wp="crater"] { --wb-accent: #30cfb9; }
:root[data-theme="dark"][data-wp="ridge"]  { --wb-accent: #30bfcf; }
:root[data-theme="dark"][data-wp="forest"] { --wb-accent: #30a4cf; }
:root[data-theme="dark"][data-wp="dunes"]  { --wb-accent: #8683e2; }
:root[data-theme="dark"][data-wp="night"]  { --wb-accent: #858585; }

/* An uploaded wallpaper cannot be pre-solved, so it keeps the neutral accent.
   Guessing one from an unknown photo is how you ship 3:1 text. */
:root[data-wp="custom"] { --wb-accent: #666666; }
:root[data-theme="dark"][data-wp="custom"] { --wb-accent: #858585; }

/* ---- Webs Butler brand theme ---------------------------------------------
   The website's 2026 palette (same values as the Polish order wizard in
   assets/order/wizard.css): warm beige, near-black and one orange.

   Unlike the photo presets this one sets the whole surface set, not just the
   accent — there is no photo, so the beige *is* the design.

   The orange is split in two on purpose:
     --wb-brand-grad / --wb-brand-1  #ff6a30  filled surfaces (buttons, active
                                              nav), with white text on top
                                              (chosen for the look, 2.9:1)
     --wb-accent                     #b93a09  orange used *as text* in light
                                              mode; #ff6a30 on beige is 2.5:1,
                                              this is 5.1:1
   In dark mode #ff6a30 clears 5.3:1 against every surface, so both are one. */
:root[data-wp="websbutler"] {
  --wb-accent: #b93a09;
  --wb-accent-contrast: #ffffff;
  --wb-brand-1: #ff6a30;
  --wb-brand-2: rgba(255, 106, 48, 0.38);
  --wb-brand-grad: #ff6a30;

  --wb-scrim: #f4f2ed;
  --wb-bg: #f4f2ed;

  --wb-surface: rgba(255, 253, 248, 0.92);
  --wb-surface-solid: #fffdf8;
  --wb-surface-2: #f8f7f3;
  --wb-surface-sunk: #e9e6de;

  --wb-text: #101012;
  --wb-text-soft: #444139;
  --wb-muted: #67625a;

  --wb-border: rgba(23, 21, 17, 0.13);
  --wb-border-strong: rgba(23, 21, 17, 0.25);

  --wb-shadow-sm: 0 2px 8px rgba(33, 28, 19, 0.06);
  --wb-shadow: 0 25px 65px -35px rgba(33, 28, 19, 0.25);
  --wb-shadow-lg: 0 30px 70px -28px rgba(33, 28, 19, 0.32);
  --wb-glow: 0 0 0 1px rgba(23, 21, 17, 0.18), 0 10px 30px -14px rgba(255, 106, 48, 0.45);
}

:root[data-theme="dark"][data-wp="websbutler"] {
  --wb-accent: #ff6a30;
  --wb-accent-contrast: #ffffff;
  --wb-brand-1: #ff6a30;
  --wb-brand-2: rgba(255, 106, 48, 0.30);
  --wb-brand-grad: #ff6a30;

  --wb-scrim: #0b0b0d;
  --wb-bg: #0b0b0d;

  --wb-surface: rgba(18, 18, 20, 0.94);
  --wb-surface-solid: #19191c;
  --wb-surface-2: #202023;
  --wb-surface-sunk: #252529;

  --wb-text: #f3f1e9;
  --wb-text-soft: #cfcbc1;
  --wb-muted: #a5a095;

  --wb-border: rgba(255, 255, 255, 0.13);
  --wb-border-strong: rgba(255, 255, 255, 0.24);

  --wb-shadow-sm: 0 2px 10px rgba(0, 0, 0, 0.5);
  --wb-shadow: 0 16px 44px -12px rgba(0, 0, 0, 0.75);
  --wb-shadow-lg: 0 34px 80px -26px rgba(0, 0, 0, 0.88);
  --wb-glow: 0 0 0 1px rgba(255, 255, 255, 0.2), 0 12px 36px -14px rgba(255, 106, 48, 0.4);
}

/* Type: Geist for text, Bricolage Grotesque for headings — the website's pair.
   Inter stays in the stack so a slow font load degrades to the old look. */
:root[data-wp="websbutler"] body {
  font-family: 'Geist', 'Inter', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
}

:root[data-wp="websbutler"] :is(h1, h2) {
  font-family: 'Bricolage Grotesque', 'Geist', 'Inter', system-ui, sans-serif;
  font-weight: 650;
  letter-spacing: -0.035em;
}

:root[data-wp="websbutler"] ::selection { background: rgba(255, 106, 48, 0.28); }

/* Gradient text is clipped from --wb-brand-grad, which is the bright fill
   orange here; as text it needs the darker accent to stay readable. */
:root[data-wp="websbutler"] .wb-grad-text {
  background: none;
  -webkit-text-fill-color: currentColor;
  color: var(--wb-accent);
}

/* ---- colour themes --------------------------------------------------------
   Like the brand theme above, these have no photo and set the whole surface
   set. One accent per theme, used both as text and as the button fill; every
   pair (text, soft, muted and accent on each surface, the button label on the
   fill) clears 4.5:1 — computed, not eyeballed. Add a theme in three places:
   here, wb_wallpapers() in app/appearance.php and the list of themes without a
   photo below (body::after). */
:root[data-wp="ocean"] {
  --wb-accent: #1a56c4;
  --wb-accent-contrast: #ffffff;
  --wb-brand-1: #1a56c4;
  --wb-brand-2: rgba(26, 86, 196, 0.38);
  --wb-brand-grad: #1a56c4;

  --wb-scrim: #eef3f8;
  --wb-bg: #eef3f8;

  --wb-surface: rgba(255, 255, 255, 0.92);
  --wb-surface-solid: #ffffff;
  --wb-surface-2: #f4f7fb;
  --wb-surface-sunk: #dfe7f0;

  --wb-text: #0f1b2d;
  --wb-text-soft: #36455a;
  --wb-muted: #56657b;

  --wb-border: rgba(15, 27, 45, 0.13);
  --wb-border-strong: rgba(15, 27, 45, 0.25);

  --wb-shadow-sm: 0 2px 8px rgba(15, 27, 45, 0.06);
  --wb-shadow: 0 25px 65px -35px rgba(15, 27, 45, 0.25);
  --wb-shadow-lg: 0 30px 70px -28px rgba(15, 27, 45, 0.32);
  --wb-glow: 0 0 0 1px rgba(15, 27, 45, 0.18), 0 10px 30px -14px rgba(26, 86, 196, 0.45);
}

:root[data-theme="dark"][data-wp="ocean"] {
  --wb-accent: #6ea8ff;
  --wb-accent-contrast: #08111f;
  --wb-brand-1: #6ea8ff;
  --wb-brand-2: rgba(110, 168, 255, 0.30);
  --wb-brand-grad: #6ea8ff;

  --wb-scrim: #0a1220;
  --wb-bg: #0a1220;

  --wb-surface: rgba(18, 28, 46, 0.94);
  --wb-surface-solid: #121c2e;
  --wb-surface-2: #18243a;
  --wb-surface-sunk: #1e2c45;

  --wb-text: #eaf1fb;
  --wb-text-soft: #c3cfe0;
  --wb-muted: #93a2b8;

  --wb-border: rgba(255, 255, 255, 0.13);
  --wb-border-strong: rgba(255, 255, 255, 0.24);

  --wb-shadow-sm: 0 2px 10px rgba(0, 0, 0, 0.5);
  --wb-shadow: 0 16px 44px -12px rgba(0, 0, 0, 0.75);
  --wb-shadow-lg: 0 34px 80px -26px rgba(0, 0, 0, 0.88);
  --wb-glow: 0 0 0 1px rgba(255, 255, 255, 0.2), 0 12px 36px -14px rgba(110, 168, 255, 0.4);
}

:root[data-wp="ocean"] ::selection { background: rgba(26, 86, 196, 0.24); }
:root[data-wp="ocean"] .wb-grad-text { background: none; -webkit-text-fill-color: currentColor; color: var(--wb-accent); }

:root[data-wp="sage"] {
  --wb-accent: #1f6a3a;
  --wb-accent-contrast: #ffffff;
  --wb-brand-1: #1f6a3a;
  --wb-brand-2: rgba(31, 106, 58, 0.38);
  --wb-brand-grad: #1f6a3a;

  --wb-scrim: #eff3ee;
  --wb-bg: #eff3ee;

  --wb-surface: rgba(252, 253, 251, 0.92);
  --wb-surface-solid: #fcfdfb;
  --wb-surface-2: #f5f8f4;
  --wb-surface-sunk: #e0e7de;

  --wb-text: #121a14;
  --wb-text-soft: #3b473d;
  --wb-muted: #566358;

  --wb-border: rgba(18, 26, 20, 0.13);
  --wb-border-strong: rgba(18, 26, 20, 0.25);

  --wb-shadow-sm: 0 2px 8px rgba(18, 26, 20, 0.06);
  --wb-shadow: 0 25px 65px -35px rgba(18, 26, 20, 0.25);
  --wb-shadow-lg: 0 30px 70px -28px rgba(18, 26, 20, 0.32);
  --wb-glow: 0 0 0 1px rgba(18, 26, 20, 0.18), 0 10px 30px -14px rgba(31, 106, 58, 0.45);
}

:root[data-theme="dark"][data-wp="sage"] {
  --wb-accent: #5fd08a;
  --wb-accent-contrast: #08130b;
  --wb-brand-1: #5fd08a;
  --wb-brand-2: rgba(95, 208, 138, 0.30);
  --wb-brand-grad: #5fd08a;

  --wb-scrim: #0b100c;
  --wb-bg: #0b100c;

  --wb-surface: rgba(20, 28, 22, 0.94);
  --wb-surface-solid: #141c16;
  --wb-surface-2: #1a241c;
  --wb-surface-sunk: #202c23;

  --wb-text: #edf3ec;
  --wb-text-soft: #c6d1c6;
  --wb-muted: #97a598;

  --wb-border: rgba(255, 255, 255, 0.13);
  --wb-border-strong: rgba(255, 255, 255, 0.24);

  --wb-shadow-sm: 0 2px 10px rgba(0, 0, 0, 0.5);
  --wb-shadow: 0 16px 44px -12px rgba(0, 0, 0, 0.75);
  --wb-shadow-lg: 0 34px 80px -26px rgba(0, 0, 0, 0.88);
  --wb-glow: 0 0 0 1px rgba(255, 255, 255, 0.2), 0 12px 36px -14px rgba(95, 208, 138, 0.4);
}

:root[data-wp="sage"] ::selection { background: rgba(31, 106, 58, 0.24); }
:root[data-wp="sage"] .wb-grad-text { background: none; -webkit-text-fill-color: currentColor; color: var(--wb-accent); }

:root[data-wp="rose"] {
  --wb-accent: #ab1f4a;
  --wb-accent-contrast: #ffffff;
  --wb-brand-1: #ab1f4a;
  --wb-brand-2: rgba(171, 31, 74, 0.38);
  --wb-brand-grad: #ab1f4a;

  --wb-scrim: #f8f0f1;
  --wb-bg: #f8f0f1;

  --wb-surface: rgba(255, 251, 251, 0.92);
  --wb-surface-solid: #fffbfb;
  --wb-surface-2: #fbf5f5;
  --wb-surface-sunk: #efe0e2;

  --wb-text: #1d1114;
  --wb-text-soft: #4b393d;
  --wb-muted: #6c555a;

  --wb-border: rgba(29, 17, 20, 0.13);
  --wb-border-strong: rgba(29, 17, 20, 0.25);

  --wb-shadow-sm: 0 2px 8px rgba(29, 17, 20, 0.06);
  --wb-shadow: 0 25px 65px -35px rgba(29, 17, 20, 0.25);
  --wb-shadow-lg: 0 30px 70px -28px rgba(29, 17, 20, 0.32);
  --wb-glow: 0 0 0 1px rgba(29, 17, 20, 0.18), 0 10px 30px -14px rgba(171, 31, 74, 0.45);
}

:root[data-theme="dark"][data-wp="rose"] {
  --wb-accent: #ff7fa3;
  --wb-accent-contrast: #1a0a0f;
  --wb-brand-1: #ff7fa3;
  --wb-brand-2: rgba(255, 127, 163, 0.30);
  --wb-brand-grad: #ff7fa3;

  --wb-scrim: #120b0d;
  --wb-bg: #120b0d;

  --wb-surface: rgba(28, 18, 21, 0.94);
  --wb-surface-solid: #1c1215;
  --wb-surface-2: #24181c;
  --wb-surface-sunk: #2c1e22;

  --wb-text: #f6ecee;
  --wb-text-soft: #d6c5c9;
  --wb-muted: #a89398;

  --wb-border: rgba(255, 255, 255, 0.13);
  --wb-border-strong: rgba(255, 255, 255, 0.24);

  --wb-shadow-sm: 0 2px 10px rgba(0, 0, 0, 0.5);
  --wb-shadow: 0 16px 44px -12px rgba(0, 0, 0, 0.75);
  --wb-shadow-lg: 0 34px 80px -26px rgba(0, 0, 0, 0.88);
  --wb-glow: 0 0 0 1px rgba(255, 255, 255, 0.2), 0 12px 36px -14px rgba(255, 127, 163, 0.4);
}

:root[data-wp="rose"] ::selection { background: rgba(171, 31, 74, 0.24); }
:root[data-wp="rose"] .wb-grad-text { background: none; -webkit-text-fill-color: currentColor; color: var(--wb-accent); }

:root[data-wp="lavender"] {
  --wb-accent: #6230cc;
  --wb-accent-contrast: #ffffff;
  --wb-brand-1: #6230cc;
  --wb-brand-2: rgba(98, 48, 204, 0.38);
  --wb-brand-grad: #6230cc;

  --wb-scrim: #f2f0f9;
  --wb-bg: #f2f0f9;

  --wb-surface: rgba(253, 252, 255, 0.92);
  --wb-surface-solid: #fdfcff;
  --wb-surface-2: #f7f5fc;
  --wb-surface-sunk: #e4e0f1;

  --wb-text: #15121f;
  --wb-text-soft: #403b52;
  --wb-muted: #5e5874;

  --wb-border: rgba(21, 18, 31, 0.13);
  --wb-border-strong: rgba(21, 18, 31, 0.25);

  --wb-shadow-sm: 0 2px 8px rgba(21, 18, 31, 0.06);
  --wb-shadow: 0 25px 65px -35px rgba(21, 18, 31, 0.25);
  --wb-shadow-lg: 0 30px 70px -28px rgba(21, 18, 31, 0.32);
  --wb-glow: 0 0 0 1px rgba(21, 18, 31, 0.18), 0 10px 30px -14px rgba(98, 48, 204, 0.45);
}

:root[data-theme="dark"][data-wp="lavender"] {
  --wb-accent: #b196ff;
  --wb-accent-contrast: #0f0a1c;
  --wb-brand-1: #b196ff;
  --wb-brand-2: rgba(177, 150, 255, 0.30);
  --wb-brand-grad: #b196ff;

  --wb-scrim: #0d0b14;
  --wb-bg: #0d0b14;

  --wb-surface: rgba(23, 19, 34, 0.94);
  --wb-surface-solid: #171322;
  --wb-surface-2: #1e1a2c;
  --wb-surface-sunk: #262136;

  --wb-text: #f0edf9;
  --wb-text-soft: #cbc5dd;
  --wb-muted: #9a93b0;

  --wb-border: rgba(255, 255, 255, 0.13);
  --wb-border-strong: rgba(255, 255, 255, 0.24);

  --wb-shadow-sm: 0 2px 10px rgba(0, 0, 0, 0.5);
  --wb-shadow: 0 16px 44px -12px rgba(0, 0, 0, 0.75);
  --wb-shadow-lg: 0 34px 80px -26px rgba(0, 0, 0, 0.88);
  --wb-glow: 0 0 0 1px rgba(255, 255, 255, 0.2), 0 12px 36px -14px rgba(177, 150, 255, 0.4);
}

:root[data-wp="lavender"] ::selection { background: rgba(98, 48, 204, 0.24); }
:root[data-wp="lavender"] .wb-grad-text { background: none; -webkit-text-fill-color: currentColor; color: var(--wb-accent); }

/* ---- base ---------------------------------------------------------------- */
*,
*::before,
*::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  min-height: 100vh;
  font-family: 'Inter', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
  font-size: 15px;
  line-height: 1.6;
  color: var(--wb-text);
  background: var(--wb-bg);
  -webkit-font-smoothing: antialiased;
  transition: background-color .4s var(--wb-ease), color .3s var(--wb-ease);
}

/* ---- wallpaper ------------------------------------------------------------
   Two fixed layers behind everything: the photo, then a scrim over it. The
   scrim is what makes an arbitrary holiday snap safe to put behind a UI —
   without it, a frosted white panel over a bright sky has no contrast left for
   its text. --wb-wp-dim is the client's own control over how hard it presses.

   Both are `position: fixed`, so the wallpaper stays put while the page scrolls
   and is painted once rather than per scroll frame. */
body::before {
  content: '';
  position: fixed;
  inset: 0;
  z-index: -2;
  pointer-events: none;
  background-image: var(--wb-wp);
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
}

body::after {
  content: '';
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background: var(--wb-scrim);
  opacity: var(--wb-wp-dim);
  transition: opacity .35s var(--wb-ease), background-color .4s var(--wb-ease);
}

/* With no photo the scrim is the background, so it must be fully opaque or the
   body colour shows through at whatever dim the client last chose. */
:root:not([data-wp]) body::after,
:root[data-wp=""] body::after,
:root[data-wp="plain"] body::after,
:root[data-wp="websbutler"] body::after,
:root:is([data-wp="ocean"], [data-wp="sage"], [data-wp="rose"], [data-wp="lavender"]) body::after { opacity: 1; }

a { color: inherit; }

h1, h2, h3, h4 {
  margin: 0;
  letter-spacing: -0.022em;
  line-height: 1.22;
  font-weight: 700;
}

::selection { background: rgba(20, 20, 26, 0.18); }

:focus-visible {
  outline: 2px solid var(--wb-brand-1);
  outline-offset: 2px;
  border-radius: 4px;
}

.wb-grad-text {
  background: var(--wb-brand-grad);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
}

/* ---- top bar ------------------------------------------------------------- */
.wb-bar {
  position: sticky;
  top: 0;
  z-index: 40;
  height: var(--wb-bar-h);
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 0 20px;
  background: var(--wb-surface);
  backdrop-filter: blur(var(--wb-blur)) saturate(150%);
  -webkit-backdrop-filter: blur(var(--wb-blur)) saturate(150%);
  border-bottom: 1px solid var(--wb-border);
}

.wb-bar__logo {
  display: flex;
  align-items: center;
  gap: 10px;
  text-decoration: none;
  flex-shrink: 0;
}

.wb-bar__logo img {
  height: 26px;
  width: auto;
  display: block;
  transition: filter .3s var(--wb-ease);
}

/* the logo file is black artwork — invert it for dark mode rather than ship two files */
:root[data-theme="dark"] .wb-bar__logo img { filter: invert(1) brightness(1.9); }

.wb-bar__spacer { flex: 1; }

.wb-bar__group {
  display: flex;
  align-items: center;
  gap: 8px;
}

/* ---- controls ------------------------------------------------------------ */
.wb-icon-btn {
  display: inline-grid;
  place-items: center;
  width: 38px;
  height: 38px;
  border: 1px solid var(--wb-border);
  border-radius: var(--wb-r-pill);
  background: var(--wb-surface-2);
  color: var(--wb-text-soft);
  cursor: pointer;
  padding: 0;
  transition: all .22s var(--wb-ease);
}

.wb-icon-btn:hover {
  color: var(--wb-accent);
  border-color: var(--wb-border-strong);
  transform: translateY(-1px);
}

.wb-icon-btn svg { width: 17px; height: 17px; }

/* segmented PL / EN */
.wb-seg {
  position: relative;
  display: flex;
  padding: 3px;
  border: 1px solid var(--wb-border);
  border-radius: var(--wb-r-pill);
  background: var(--wb-surface-2);
}

.wb-seg__thumb {
  position: absolute;
  top: 3px;
  left: 3px;
  width: calc(50% - 3px);
  height: calc(100% - 6px);
  border-radius: var(--wb-r-pill);
  background: var(--wb-brand-grad);
  box-shadow: 0 4px 14px -4px var(--wb-brand-2);
  transition: transform .3s var(--wb-ease);
}

.wb-seg[data-i="1"] .wb-seg__thumb { transform: translateX(100%); }

.wb-seg button {
  position: relative;
  z-index: 1;
  min-width: 40px;
  padding: 5px 10px;
  border: 0;
  background: none;
  font: inherit;
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  color: var(--wb-muted);
  cursor: pointer;
  border-radius: var(--wb-r-pill);
  transition: color .25s var(--wb-ease);
}

.wb-seg button[aria-selected="true"] { color: var(--wb-accent-contrast); }

/* buttons */
.wb-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 10px 20px;
  border: 1px solid transparent;
  border-radius: var(--wb-r-pill);
  font: inherit;
  font-size: 0.9rem;
  font-weight: 600;
  text-decoration: none;
  cursor: pointer;
  white-space: nowrap;
  transition: all .22s var(--wb-ease);
}

.wb-btn--primary {
  color: var(--wb-accent-contrast);
  background: var(--wb-brand-grad);
  box-shadow: 0 10px 26px -10px var(--wb-brand-2);
}

.wb-btn--primary:hover {
  transform: translateY(-2px);
  box-shadow: 0 16px 34px -10px var(--wb-brand-2);
}

.wb-btn--ghost {
  color: var(--wb-text-soft);
  background: var(--wb-surface-2);
  border-color: var(--wb-border);
}

.wb-btn--ghost:hover {
  color: var(--wb-accent);
  border-color: var(--wb-border-strong);
}

.wb-btn:disabled { opacity: .55; cursor: not-allowed; transform: none; }

.wb-btn--block { width: 100%; }

/* Sits inline with body text (the SEO summary row), so it has to be smaller
   than a standalone action button. */
.wb-btn--xs { padding: 5px 11px; font-size: .78rem; gap: 6px; }

/* Between --xs and the default: the action on a compact card, where a full-size
   button would be most of the card but --xs reads as an inline link. */
.wb-btn--sm { padding: 8px 14px; font-size: .82rem; gap: 7px; }

/* ---- shell layout -------------------------------------------------------- */
.wb-shell {
  display: grid;
  grid-template-columns: var(--wb-rail-w) minmax(0, 1fr);
  align-items: start;
  gap: 22px;
  max-width: 1560px;
  margin: 0 auto;
  padding: 22px 20px 64px;
}

/* ---- left rail ----------------------------------------------------------- */
.wb-rail {
  position: sticky;
  top: calc(var(--wb-bar-h) + 22px);
  display: flex;
  flex-direction: column;
  gap: 22px;
  padding: 16px 14px;
  background: var(--wb-surface);
  backdrop-filter: blur(var(--wb-blur)) saturate(150%);
  -webkit-backdrop-filter: blur(var(--wb-blur)) saturate(150%);
  border: 1px solid var(--wb-border);
  border-radius: var(--wb-r-lg);
  box-shadow: var(--wb-shadow);
}

.wb-rail__title {
  padding: 0 10px;
  font-size: 0.68rem;
  font-weight: 800;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--wb-muted);
}

.wb-rail__group { display: flex; flex-direction: column; gap: 4px; }
.wb-rail__group .wb-rail__title { margin-bottom: 6px; }

.wb-nav {
  position: relative;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 11px 12px;
  border-radius: var(--wb-r-sm);
  text-decoration: none;
  color: var(--wb-text-soft);
  font-size: 0.9rem;
  font-weight: 500;
  transition: all .2s var(--wb-ease);
}

.wb-nav__ico {
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  flex-shrink: 0;
  border-radius: 9px;
  background: var(--wb-surface-sunk);
  color: var(--wb-muted);
  transition: all .2s var(--wb-ease);
}

.wb-nav__ico svg { width: 16px; height: 16px; }

.wb-nav:hover {
  background: var(--wb-surface-sunk);
  color: var(--wb-text);
}

.wb-nav:hover .wb-nav__ico { color: var(--wb-accent); }

.wb-nav--on {
  color: var(--wb-accent-contrast);
  background: var(--wb-brand-grad);
  box-shadow: 0 10px 26px -12px var(--wb-brand-2);
}

/* Tinted from currentColor, not a literal white: on a dark-mode accent the
   foreground is near-black, and a white wash there would vanish. */
.wb-nav--on .wb-nav__ico {
  background: rgba(255, 255, 255, 0.20);
  background: color-mix(in srgb, currentColor 20%, transparent);
  color: var(--wb-accent-contrast);
}

/* .wb-nav:hover's plain surface background would otherwise win over the
   active gradient here (equal specificity, but .wb-nav:hover comes first) —
   this needs to come after it in source order to take over on hover. */
/* The active item gets no hover treatment: it is already the loudest thing in
   the rail, and tinting its icon to the brand purple sank it into the purple
   pill it sits on. Hover only needs to answer "is this clickable", which the
   filled state already does. */
.wb-nav--on:hover { background: var(--wb-brand-grad); color: var(--wb-accent-contrast); }
.wb-nav--on:hover .wb-nav__ico { color: var(--wb-accent-contrast); }

.wb-nav--locked { cursor: pointer; opacity: .62; }
.wb-nav--locked:hover { opacity: 1; }

.wb-nav__lock {
  margin-left: auto;
  flex-shrink: 0;
  width: 13px;
  height: 13px;
  color: var(--wb-muted);
}

/* ---- admin sub-pages: disclosed, not always listed --------------------
   The sub-pages under "Panel admina" only show once you're actually on one
   of them (server-rendered — see $adminOpen in shell.php); otherwise they
   stay out of the way. Plain inline list, no card background, so it just
   pushes the rest of the rail (down to "Wyloguj się") down instead of
   covering anything.
   Named .wb-rail__subnav, not .wb-subnav — that name was already taken by the
   pill-shaped tool tab strip further down this file (border-radius: 999px),
   and this element inheriting that by accident is what rendered as a giant
   white circle. */
.wb-rail__subnav { display: flex; flex-direction: column; gap: 4px; }

.wb-rail__group--admin:not(.wb-rail__group--admin-open) .wb-rail__subnav,
.wb-rail__group--tools:not(.wb-rail__group--tools-open) .wb-rail__subnav { display: none; }

.wb-nav--sub { padding: 9px 12px 9px 20px; font-size: .86rem; }

/* the upsell card at the bottom of the rail */
.wb-rail__cta {
  padding: 16px;
  border-radius: var(--wb-r);
  border: 1px solid var(--wb-border);
  background:
    linear-gradient(160deg, color-mix(in srgb, var(--wb-brand-1) 12%, transparent), color-mix(in srgb, var(--wb-brand-1) 5%, transparent));
  text-align: center;
}

.wb-rail__cta p {
  margin: 0 0 12px;
  font-size: 0.82rem;
  line-height: 1.5;
  color: var(--wb-text-soft);
}

/* ---- main ---------------------------------------------------------------- */
.wb-main { min-width: 0; display: flex; flex-direction: column; gap: 20px; }

/* The page being left stays in the DOM, out of sight, while a remembered copy
   of the next one stands in for it ("instant navigation" in wb.js). */
.wb-main--away { display: none !important; }

/* Pages that ask for a wider layout ('wide' in wb_shell_start). */
.wb-shell--wide { max-width: 1780px; }

.wb-page-head { display: flex; flex-direction: column; gap: 6px; }
.wb-page-head h1 { font-size: clamp(1.5rem, 3vw, 2rem); }
.wb-page-head p { margin: 0; color: var(--wb-muted); font-size: 0.95rem; }

/* Single-column pages that carry one narrow card and nothing else (sign-in).
   Pinned to the left of a 1112px column the card reads as a stray corner, so
   the column centres its own children instead — head text included, or a
   centred card under a left-aligned h1 looks like a mistake. */
.wb-main--center { align-items: center; }
.wb-main--center > * { width: 100%; max-width: var(--wb-center-w, 460px); }
.wb-main--center .wb-page-head { text-align: center; }

.wb-card {
  padding: 22px;
  background: var(--wb-surface);
  backdrop-filter: blur(var(--wb-blur)) saturate(150%);
  -webkit-backdrop-filter: blur(var(--wb-blur)) saturate(150%);
  border: 1px solid var(--wb-border);
  border-radius: var(--wb-r-lg);
  box-shadow: var(--wb-shadow);
}

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

.wb-card__head h2 { font-size: 1.02rem; }

/* two-pane tool workspace: controls left, live result right */
.wb-work {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 420px);
  gap: 20px;
  align-items: start;
}

.wb-work__out { position: sticky; top: calc(var(--wb-bar-h) + 22px); }

/* ---- form fields --------------------------------------------------------- */
.wb-field { display: flex; flex-direction: column; gap: 7px; margin-bottom: 15px; }
.wb-field:last-child { margin-bottom: 0; }

.wb-label {
  font-size: 0.74rem;
  font-weight: 700;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--wb-muted);
}

.wb-input,
.wb-select,
.wb-textarea {
  width: 100%;
  padding: 12px 15px;
  font: inherit;
  font-size: 0.94rem;
  color: var(--wb-text);
  background: var(--wb-surface-solid);
  border: 1px solid var(--wb-border);
  border-radius: var(--wb-r-sm);
  outline: none;
  transition: border-color .2s var(--wb-ease), box-shadow .2s var(--wb-ease);
}

.wb-textarea { resize: vertical; min-height: 96px; }

.wb-input:focus,
.wb-select:focus,
.wb-textarea:focus {
  border-color: var(--wb-brand-1);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--wb-brand-1) 18%, transparent);
}

.wb-input::placeholder, .wb-textarea::placeholder { color: var(--wb-muted); opacity: .75; }

.wb-row { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }

/* colour swatch input */
.wb-color {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 7px 12px 7px 7px;
  background: var(--wb-surface-solid);
  border: 1px solid var(--wb-border);
  border-radius: var(--wb-r-sm);
}

.wb-color input[type="color"] {
  width: 34px;
  height: 34px;
  padding: 0;
  border: 0;
  border-radius: 8px;
  background: none;
  cursor: pointer;
}

.wb-color input[type="color"]::-webkit-color-swatch-wrapper { padding: 0; }
.wb-color input[type="color"]::-webkit-color-swatch { border: 1px solid var(--wb-border); border-radius: 8px; }
.wb-color span { font-size: 0.84rem; font-weight: 600; color: var(--wb-text-soft); font-variant-numeric: tabular-nums; }

/* pill tabs */
.wb-tabs {
  position: relative;
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  gap: 2px;
  padding: 4px;
  margin-bottom: 18px;
  background: var(--wb-surface-sunk);
  border: 1px solid var(--wb-border);
  border-radius: var(--wb-r-pill);
}

.wb-tabs__thumb {
  position: absolute;
  top: 4px;
  left: 4px;
  height: calc(100% - 8px);
  border-radius: var(--wb-r-pill);
  background: var(--wb-brand-grad);
  box-shadow: 0 6px 18px -6px var(--wb-brand-2);
  transition: transform .32s var(--wb-ease);
}

.wb-tabs button {
  position: relative;
  z-index: 1;
  padding: 9px 14px;
  border: 0;
  background: none;
  border-radius: var(--wb-r-pill);
  font: inherit;
  font-size: 0.82rem;
  font-weight: 700;
  letter-spacing: 0.02em;
  color: var(--wb-muted);
  cursor: pointer;
  transition: color .25s var(--wb-ease);
}

.wb-tabs button[aria-selected="true"] { color: var(--wb-accent-contrast); }

/* choice chips (dot style, quality level, …) */
.wb-chips { display: flex; flex-wrap: wrap; gap: 8px; }

.wb-chip {
  position: relative;
  padding: 9px 16px;
  border: 1px solid var(--wb-border);
  border-radius: var(--wb-r-pill);
  background: var(--wb-surface-solid);
  font-size: 0.84rem;
  font-weight: 600;
  color: var(--wb-text-soft);
  cursor: pointer;
  transition: all .2s var(--wb-ease);
}

.wb-chip input { position: absolute; opacity: 0; pointer-events: none; }

.wb-chip:has(input:checked) {
  color: var(--wb-accent-contrast);
  background: var(--wb-brand-grad);
  border-color: transparent;
  box-shadow: 0 8px 20px -8px var(--wb-brand-2);
}

/* dropzone */
.wb-drop {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 14px 18px;
  text-align: left;
  border: 1.5px dashed var(--wb-border-strong);
  border-radius: var(--wb-r-sm);
  background: var(--wb-surface-sunk);
  color: var(--wb-muted);
  font-size: 0.87rem;
  cursor: pointer;
  transition: all .2s var(--wb-ease);
}

/* without this the icon has no intrinsic size and stretches to fill the box */
.wb-drop svg { width: 18px; height: 18px; flex-shrink: 0; }

/* the tall variant, for tools where the drop target is the primary action */
.wb-drop--tall {
  flex-direction: column;
  padding: 30px 20px;
  text-align: center;
  border-radius: var(--wb-r);
}

.wb-drop--tall svg { width: 26px; height: 26px; }

.wb-drop:hover, .wb-drop.is-over {
  border-color: var(--wb-brand-1);
  color: var(--wb-accent);
  background: color-mix(in srgb, var(--wb-brand-1) 7%, transparent);
}

.wb-drop input[type="file"] { display: none; }

/* ---- file rows (compressor) ---------------------------------------------- */
.wb-files { display: flex; flex-direction: column; gap: 8px; }

.wb-file {
  position: relative;
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 12px 14px;
  overflow: hidden;
  background: var(--wb-surface-solid);
  border: 1px solid var(--wb-border);
  border-radius: var(--wb-r-sm);
}

.wb-file__thumb {
  width: 42px;
  height: 42px;
  flex-shrink: 0;
  object-fit: cover;
  border-radius: 8px;
  background: var(--wb-surface-sunk);
  cursor: pointer;
}

.wb-file__body { flex: 1; min-width: 0; }

.wb-file__name {
  display: block;
  font-size: 0.88rem;
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  cursor: pointer;
}

.wb-file__name:hover { color: var(--wb-accent); }

.wb-file__meta {
  display: flex;
  align-items: center;
  gap: 7px;
  margin-top: 2px;
  font-size: 0.79rem;
  color: var(--wb-muted);
  font-variant-numeric: tabular-nums;
}

.wb-file__meta strong { color: var(--wb-text); font-weight: 700; }

.wb-file__acts { display: flex; gap: 6px; flex-shrink: 0; }

.wb-file__btn {
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  border: 1px solid var(--wb-border);
  border-radius: 9px;
  background: none;
  color: var(--wb-muted);
  cursor: pointer;
  transition: all .2s var(--wb-ease);
}

.wb-file__btn svg { width: 15px; height: 15px; }

/* per-file download carries a word, not just an arrow — one file at a time is
   the common case, and an unlabelled icon reads as decoration */
.wb-file__dl { padding: 7px 14px; font-size: 0.82rem; }
.wb-file__dl svg { width: 14px; height: 14px; }
@media (max-width: 620px) { .wb-file__dl span { display: none; } .wb-file__dl { padding: 7px 10px; } }
.wb-file__btn:hover:not(:disabled) { color: var(--wb-accent); border-color: var(--wb-border-strong); }
.wb-file__btn:disabled { opacity: .35; cursor: not-allowed; }
.wb-file__btn.is-del:hover { color: var(--wb-bad); border-color: var(--wb-bad); }

.wb-file__bar {
  position: absolute;
  left: 0;
  bottom: 0;
  height: 2px;
  width: 0;
  background: var(--wb-brand-grad);
  transition: width .3s var(--wb-ease);
}

.wb-file__bar.is-bad { background: var(--wb-bad); }

/* saving badge, green when the file actually got smaller */
.wb-save-pill {
  padding: 2px 9px;
  border-radius: var(--wb-r-pill);
  font-size: 0.72rem;
  font-weight: 800;
  color: var(--wb-ok);
  background: var(--wb-ok-bg);
}

/* ---- badges & meta ------------------------------------------------------- */
.wb-badge {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 3px 11px;
  border-radius: var(--wb-r-pill);
  font-size: 0.74rem;
  font-weight: 800;
  letter-spacing: 0.02em;
  white-space: nowrap;
}

.wb-badge--ok   { color: var(--wb-ok);   background: var(--wb-ok-bg); }
.wb-badge--warn { color: var(--wb-warn); background: var(--wb-warn-bg); }
.wb-badge--bad  { color: var(--wb-bad);  background: var(--wb-bad-bg); }
.wb-badge--mut  { color: var(--wb-muted); background: var(--wb-surface-sunk); }

/* The top-bar identity chip (.wb-who) lived here. It was removed once the rail
   grew its own — two chips saying the same thing, a few hundred pixels apart. */

/* An uploaded picture takes the same box as the initials, so the two states are
   interchangeable everywhere wb_avatar() is called. object-fit keeps a
   not-quite-square upload from stretching. */
img.wb-me__av,
img.wb-avatar-edit__av,
img.wb-nav__ico--av { object-fit: cover; background: var(--wb-surface-sunk); }

/* ---- header popovers ------------------------------------------------------
   The refer/review asks. They earn a place in the chrome only by staying shut:
   an icon until clicked, then their full copy. */
.wb-pop { position: relative; display: flex; }

.wb-pop__panel {
  position: absolute;
  top: calc(100% + 10px);
  right: 0;
  z-index: 60;
  display: flex;
  flex-direction: column;
  gap: 8px;
  width: 268px;
  padding: 16px;
  background: var(--wb-surface);
  backdrop-filter: blur(var(--wb-blur)) saturate(150%);
  -webkit-backdrop-filter: blur(var(--wb-blur)) saturate(150%);
  border: 1px solid var(--wb-border);
  border-radius: var(--wb-r);
  box-shadow: var(--wb-shadow-lg);
}

.wb-pop__panel[hidden] { display: none; }
.wb-pop__panel h3 { font-size: 0.92rem; font-weight: 650; }
.wb-pop__panel p { margin: 0; font-size: 0.79rem; line-height: 1.5; color: var(--wb-muted); }
.wb-pop__panel .wb-btn { align-self: flex-start; margin-top: 2px; }

/* Anchored to the viewport edge on a phone, where 268px pinned to a button near
   the right edge would otherwise hang off-screen. */
@media (max-width: 480px) {
  .wb-pop { position: static; }
  .wb-pop__panel { right: 12px; left: 12px; width: auto; }
}

/* ---- rail identity chip -------------------------------------------------- */
/* The panel's only "this is your account" marker, sitting above the navigation
   where the eye starts. The top bar used to carry a second one; it went. */
.wb-me {
  display: flex;
  align-items: center;
  gap: 11px;
  margin-top: -6px;
  padding: 9px 10px;
  border: 1px solid var(--wb-border);
  border-radius: var(--wb-r);
  background: var(--wb-surface-2);
  text-decoration: none;
  transition: all .2s var(--wb-ease);
}

.wb-me:hover { border-color: var(--wb-border-strong); background: var(--wb-surface-sunk); }

.wb-me__av {
  display: grid;
  place-items: center;
  width: 36px;
  height: 36px;
  flex-shrink: 0;
  border-radius: 12px;
  color: var(--wb-accent-contrast);
  font-size: 0.88rem;
  font-weight: 800;
  background: var(--wb-brand-grad);
}

.wb-me__txt { display: flex; flex-direction: column; min-width: 0; line-height: 1.3; }

.wb-me__txt strong {
  font-size: 0.86rem;
  font-weight: 650;
  color: var(--wb-text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.wb-me__txt em {
  font-size: 0.72rem;
  font-style: normal;
  color: var(--wb-muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.wb-me__go { margin-left: auto; flex-shrink: 0; color: var(--wb-muted); display: grid; place-items: center; }
.wb-me:hover .wb-me__go { color: var(--wb-accent); }

/* Team account switcher under the chip. The select sits on top of the whole
   row, so the row is the click target and the native picker opens. */
.wb-team-sw {
  position: relative;
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 8px 0 0;
  padding: 7px 10px;
  border: 1px dashed var(--wb-border-strong);
  border-radius: var(--wb-r-sm);
  font-size: 0.76rem;
  color: var(--wb-muted);
}
.wb-team-sw__ico { display: grid; place-items: center; color: var(--wb-brand-1); flex-shrink: 0; }
.wb-team-sw__sel {
  flex: 1;
  min-width: 0;
  border: 0;
  background: transparent;
  color: var(--wb-text);
  font: inherit;
  font-weight: 600;
  cursor: pointer;
  text-overflow: ellipsis;
}
.wb-team-sw__sel:focus-visible { outline: 2px solid var(--wb-brand-1); outline-offset: 2px; border-radius: 6px; }
.wb-team-sw__sel option { color: #1d140c; }
:root[data-rail="collapsed"] .wb-team-sw { display: none; }

/* ---- rail count badges --------------------------------------------------- */
.wb-nav__count {
  margin-left: auto;
  flex-shrink: 0;
  min-width: 21px;
  padding: 2px 7px;
  border-radius: var(--wb-r-pill);
  background: var(--wb-surface-sunk);
  color: var(--wb-muted);
  font-size: 0.72rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  text-align: center;
}

.wb-nav__count--warn { background: var(--wb-warn-bg); color: var(--wb-warn); }

/* On the active row the pill sits on the accent fill, where a muted grey would
   disappear — it borrows the row's own foreground instead. */
.wb-nav--on .wb-nav__count,
.wb-nav--on .wb-nav__count--warn {
  background: rgba(255, 255, 255, 0.22);
  background: color-mix(in srgb, currentColor 22%, transparent);
  color: var(--wb-accent-contrast);
}

/* the free-use counter in the top bar */
.wb-credits {
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 6px 14px 6px 8px;
  border: 1px solid var(--wb-border);
  border-radius: var(--wb-r-pill);
  background: var(--wb-surface-2);
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--wb-text-soft);
}

.wb-credits__dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--wb-ok);
  box-shadow: 0 0 0 3px var(--wb-ok-bg);
}

.wb-credits--out .wb-credits__dot { background: var(--wb-bad); box-shadow: 0 0 0 3px var(--wb-bad-bg); }

/* ---- dashboard: bento tiles + side column -------------------------------- */
/* The overview splits in two: everything the client came to do runs down the
   main column, and the standing prompts (order / refer / review) sit in a
   narrow aside so they stop competing with it. Below 1080px the aside stacks
   underneath, which puts the prompts last — exactly where they belong. */
.wb-dash {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 296px;
  gap: 20px;
  align-items: start;
}

.wb-dash__main { min-width: 0; display: flex; flex-direction: column; gap: 20px; }
.wb-dash__side { display: flex; flex-direction: column; gap: 14px; }

@media (max-width: 1080px) {
  .wb-dash { grid-template-columns: minmax(0, 1fr); }
  /* Side by side rather than a single stack once they are full width, so three
     prompts do not become three screens of scrolling on a tablet. */
  .wb-dash__side { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); }
}

.wb-bento {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(184px, 1fr));
  gap: 14px;
}

/* Two-up on a phone rather than the four-high stack auto-fit would give: the
   whole point of the tiles is to be taken in at a glance, and 600px of scroll
   before the first real content is the opposite of that. */
@media (max-width: 560px) {
  .wb-bento { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
  .wb-stat { padding: 14px; gap: 8px; }
  .wb-stat__ico { width: 30px; height: 30px; border-radius: 9px; }
  .wb-stat__val { font-size: 1.5rem; }
  .wb-stat__val--word { font-size: 0.98rem; }
  .wb-stat__label { font-size: 0.68rem; letter-spacing: .06em; }
  .wb-stat__foot { font-size: 0.75rem; }
}

.wb-stat {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 18px;
  text-decoration: none;
  color: inherit;
  background: var(--wb-surface);
  backdrop-filter: blur(var(--wb-blur)) saturate(150%);
  -webkit-backdrop-filter: blur(var(--wb-blur)) saturate(150%);
  border: 1px solid var(--wb-border);
  border-radius: var(--wb-r-lg);
  box-shadow: var(--wb-shadow-sm);
  transition: transform .25s var(--wb-ease), box-shadow .25s var(--wb-ease), border-color .25s var(--wb-ease);
}

a.wb-stat:hover {
  transform: translateY(-2px);
  border-color: var(--wb-border-strong);
  box-shadow: var(--wb-shadow);
}

.wb-stat__top { display: flex; align-items: center; gap: 10px; }

.wb-stat__ico {
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  flex-shrink: 0;
  border-radius: 11px;
  background: var(--wb-surface-sunk);
  color: var(--wb-accent);
}

.wb-stat__ico svg { width: 17px; height: 17px; }

.wb-stat__label {
  font-size: 0.74rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--wb-muted);
}

/* tabular-nums so a row of tiles does not jitter as the counts change width */
.wb-stat__val {
  font-size: 1.85rem;
  font-weight: 800;
  line-height: 1.05;
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
}

/* Used where the tile states a condition ("Na bieżąco") rather than a count —
   the full-size numeral face would make a word look like a headline. */
.wb-stat__val--word { font-size: 1.12rem; font-weight: 700; letter-spacing: -0.01em; }

.wb-stat__foot {
  display: flex;
  align-items: center;
  gap: 5px;
  margin-top: auto;
  font-size: 0.79rem;
  font-weight: 600;
  color: var(--wb-accent);
}

.wb-stat__foot svg { transition: transform .25s var(--wb-ease); }
a.wb-stat:hover .wb-stat__foot svg { transform: translateX(3px); }

.wb-stat--warn .wb-stat__ico { background: var(--wb-warn-bg); color: var(--wb-warn); }
.wb-stat--warn .wb-stat__val { color: var(--wb-warn); }
.wb-stat--ok .wb-stat__ico { background: var(--wb-ok-bg); color: var(--wb-ok); }

/* ---- compact prompt cards (dashboard aside) ------------------------------ */
.wb-promo {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 16px;
  background: var(--wb-surface);
  backdrop-filter: blur(var(--wb-blur)) saturate(150%);
  -webkit-backdrop-filter: blur(var(--wb-blur)) saturate(150%);
  border: 1px solid var(--wb-border);
  border-radius: var(--wb-r);
  box-shadow: var(--wb-shadow-sm);
}

/* The one card that gets a tint, so the standing "order another site" ask reads
   as an offer rather than another panel. Mixed from --wb-accent rather than a
   literal purple: this was the last hardcoded brand colour in the stylesheet,
   and it stayed lavender while everything around it went monochrome. */
.wb-promo--brand {
  border-color: var(--wb-border-strong);
  background: color-mix(in srgb, var(--wb-accent) 12%, var(--wb-surface));
}

/* Without color-mix the tint is simply skipped — a plain panel is a much better
   failure than a purple one on a monochrome page. */
@supports not (background: color-mix(in srgb, red 10%, blue)) {
  .wb-promo--brand { background: var(--wb-surface); }
}

.wb-promo h3 { font-size: 0.92rem; font-weight: 650; }
.wb-promo p { margin: 0; font-size: 0.79rem; line-height: 1.5; color: var(--wb-muted); }
.wb-promo .wb-btn { align-self: flex-start; margin-top: 4px; }

/* ---- settings layout (account) ------------------------------------------- */
/* The shape every account page the client has already used has: a list of
   sections down the left, one section's worth of controls on the right. The old
   page stacked all four sections at once, which is why it read as a wall — the
   information was fine, there was just no way to be looking at one thing. */
.wb-settings {
  display: grid;
  grid-template-columns: 218px minmax(0, 1fr);
  gap: 20px;
  align-items: start;
}

.wb-settings__nav {
  position: sticky;
  top: calc(var(--wb-bar-h) + 22px);
  display: flex;
  flex-direction: column;
  gap: 3px;
  padding: 10px;
  background: var(--wb-surface);
  backdrop-filter: blur(var(--wb-blur)) saturate(150%);
  -webkit-backdrop-filter: blur(var(--wb-blur)) saturate(150%);
  border: 1px solid var(--wb-border);
  border-radius: var(--wb-r);
  box-shadow: var(--wb-shadow-sm);
}

.wb-stab {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  border: 0;
  border-radius: var(--wb-r-sm);
  background: none;
  color: var(--wb-text-soft);
  font: inherit;
  font-size: 0.88rem;
  font-weight: 550;
  text-align: left;
  cursor: pointer;
  transition: all .18s var(--wb-ease);
}

.wb-stab svg { width: 17px; height: 17px; flex-shrink: 0; color: var(--wb-muted); transition: color .18s var(--wb-ease); }
.wb-stab:hover { background: var(--wb-surface-sunk); color: var(--wb-text); }
.wb-stab:hover svg { color: var(--wb-accent); }

.wb-stab--on,
.wb-stab--on:hover { background: var(--wb-brand-grad); color: var(--wb-accent-contrast); box-shadow: 0 8px 22px -12px var(--wb-brand-2); }
.wb-stab--on svg,
.wb-stab--on:hover svg { color: var(--wb-accent-contrast); }

.wb-settings__panes { min-width: 0; }
.wb-pane { display: none; flex-direction: column; gap: 20px; }
.wb-pane--on { display: flex; }

@media (max-width: 860px) {
  .wb-settings { grid-template-columns: minmax(0, 1fr); }
  /* A horizontal strip on narrow screens, scrollable rather than wrapped, so
     the sections stay on one predictable line. */
  .wb-settings__nav {
    position: static;
    flex-direction: row;
    gap: 6px;
    overflow-x: auto;
    scrollbar-width: none;
  }
  .wb-settings__nav::-webkit-scrollbar { display: none; }
  .wb-stab { flex-shrink: 0; }
}

/* ---- one setting: label + description on the left, control on the right --- */
.wb-set {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 15px 0;
  flex-wrap: wrap;
}

/* Rules go *between* settings, not above the first one. Keyed off the sibling
   rather than :first-of-type, which counts divs — and .wb-card__head is a div,
   so :first-of-type would match the heading and leave a double line under it. */
.wb-set + .wb-set { border-top: 1px solid var(--wb-border); }
.wb-card__head + .wb-set { padding-top: 0; }
.wb-set__txt { min-width: 0; flex: 1 1 240px; }
.wb-set__txt strong { display: block; font-size: 0.9rem; font-weight: 600; }
.wb-set__txt span { display: block; margin-top: 2px; font-size: 0.81rem; line-height: 1.5; color: var(--wb-muted); }
.wb-set__act { flex-shrink: 0; display: flex; align-items: center; gap: 10px; }

/* ---- DNS panel -----------------------------------------------------------
   surface-2 rather than surface-sunk for both this and the file browser: a sunk
   panel darkens the card it sits on, and --wb-accent was solved against the
   card. That cost the accent-coloured text here ~0.3 of its contrast ratio and
   left the breadcrumb links at 4.52:1 — passing, but with no margin at all.
   A lighter nested surface moves it the other way, and reads as raised content
   rather than a hole. */
.wb-dns {
  margin-top: 16px;
  padding: 16px;
  border: 1px solid var(--wb-border);
  border-radius: var(--wb-r);
  background: var(--wb-surface-2);
}

/* The verdicts, before the records anyone would have to interpret themselves. */
.wb-dns__checks {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 6px 16px;
  margin-bottom: 16px;
}

.wb-dns__check {
  display: flex;
  align-items: flex-start;
  gap: 9px;
  font-size: 0.83rem;
  line-height: 1.45;
  color: var(--wb-text-soft);
}

/* A dot rather than an icon: five rows of ticks and crosses reads as an alarm,
   and most of these are informational most of the time. */
.wb-dns__dot {
  width: 8px;
  height: 8px;
  margin-top: 6px;
  flex-shrink: 0;
  border-radius: 50%;
  background: var(--wb-muted);
}

.wb-dns__check--ok   .wb-dns__dot { background: var(--wb-ok); }
.wb-dns__check--warn .wb-dns__dot { background: var(--wb-warn); }
.wb-dns__check--bad  .wb-dns__dot { background: var(--wb-bad); }
.wb-dns__check--bad  { color: var(--wb-text); }

.wb-dns__group + .wb-dns__group { margin-top: 14px; }

.wb-dns__group h4 {
  margin: 0 0 7px;
  font-size: 0.71rem;
  font-weight: 800;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--wb-muted);
}

.wb-dns__rows { display: flex; flex-direction: column; gap: 5px; }

.wb-dns__row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 9px 12px;
  border: 1px solid var(--wb-border);
  border-radius: var(--wb-r-sm);
  background: var(--wb-surface-solid);
}

/* Record values are the one place in the panel where an exact string matters,
   so they get a mono face — and they scroll rather than wrap, because a TXT
   record broken across three lines is unreadable and unselectable.
   The overflow-x is load-bearing beyond the scrollbar: it also zeroes this flex
   item's automatic minimum size, which is what stops a 2000px DKIM key from
   pushing the row — and the whole page — sideways. Don't drop it. */
.wb-dns__row code {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.79rem;
  color: var(--wb-text);
  overflow-x: auto;
  white-space: nowrap;
  scrollbar-width: thin;
}

.wb-dns__meta {
  flex-shrink: 0;
  font-size: 0.72rem;
  font-weight: 600;
  color: var(--wb-muted);
}

.wb-dns__foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-top: 16px;
  padding-top: 12px;
  border-top: 1px solid var(--wb-border);
  flex-wrap: wrap;
}

/* ---- website file browser ------------------------------------------------ */
.wb-files-browser {
  margin-top: 16px;
  padding: 14px 16px 16px;
  border: 1px solid var(--wb-border);
  border-radius: var(--wb-r);
  background: var(--wb-surface-2);
}

.wb-fb__crumbs {
  display: flex;
  align-items: center;
  gap: 4px;
  flex-wrap: wrap;
  padding-bottom: 12px;
  margin-bottom: 4px;
  border-bottom: 1px solid var(--wb-border);
}

.wb-fb__crumb {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 8px;
  border: 0;
  border-radius: var(--wb-r-sm);
  background: none;
  font: inherit;
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--wb-accent);
  cursor: pointer;
  transition: background .15s var(--wb-ease);
}

button.wb-fb__crumb:hover { background: var(--wb-surface-2); }

/* The folder you are actually in is not a link — it would go nowhere. */
.wb-fb__crumb--on { color: var(--wb-muted); cursor: default; font-weight: 550; }
.wb-fb__sep { color: var(--wb-muted); font-size: 0.8rem; }

/* ---- toolbar ---- */
.wb-fb__bar {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  padding: 8px 2px 10px;
}

.wb-fb__all {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-size: 0.8rem;
  color: var(--wb-text-soft);
  cursor: pointer;
}

.wb-fb__count { font-size: 0.78rem; color: var(--wb-accent); font-weight: 600; }

.wb-fb__rows { display: flex; flex-direction: column; }

/* A row is now three things — a checkbox, the row itself, and rename — so the
   hover and the separator move up to the wrapper. */
.wb-fb__item {
  display: flex;
  align-items: center;
  gap: 2px;
  border-radius: var(--wb-r-sm);
  transition: background .15s var(--wb-ease);
}

.wb-fb__item + .wb-fb__item { border-top: 1px solid var(--wb-border); }
.wb-fb__item:hover { background: var(--wb-surface-2); }

.wb-fb__pick { display: grid; place-items: center; padding: 0 4px 0 6px; cursor: pointer; }

.wb-fb__item--dir .wb-fb__name { font-weight: 550; }

/* Rename sits at the end and stays quiet until the row is hovered — it is the
   least-used action on a list someone is mostly reading. */
.wb-fb__rename {
  flex-shrink: 0;
  display: grid;
  place-items: center;
  width: 30px;
  height: 30px;
  margin-right: 4px;
  border: 0;
  border-radius: var(--wb-r-sm);
  background: none;
  color: var(--wb-muted);
  cursor: pointer;
  opacity: 0;
  transition: opacity .15s var(--wb-ease), color .15s var(--wb-ease);
}

.wb-fb__item:hover .wb-fb__rename,
.wb-fb__rename:focus-visible { opacity: 1; }
.wb-fb__rename:hover { color: var(--wb-accent); background: var(--wb-surface-sunk); }

@media (hover: none) { .wb-fb__rename { opacity: 1; } }

.wb-fb__row {
  display: flex;
  align-items: center;
  gap: 11px;
  width: 100%;
  padding: 9px 8px;
  border: 0;
  border-radius: var(--wb-r-sm);
  background: none;
  font: inherit;
  text-align: left;
  text-decoration: none;
  color: var(--wb-text);
  cursor: pointer;
  transition: background .15s var(--wb-ease);
}

/* Hover and separators live on .wb-fb__item now — the row is only the middle
   third of it. */
.wb-fb__ico { display: grid; place-items: center; flex-shrink: 0; color: var(--wb-muted); }

/* Folders read as folders at a glance — amber for a directory, neutral for a
   file. The one place colour carries meaning rather than decoration, so it
   survives the otherwise monochrome palette.
   Declared AFTER the base rule on purpose: same specificity, so source order
   is what decides, and putting it earlier left every folder grey. */
.wb-fb__ico--dir { color: #d99a26; }
:root[data-theme="dark"] .wb-fb__ico--dir { color: #f0be5c; }
.wb-fb__ico--file { color: var(--wb-muted); }

button.wb-fb__row:hover .wb-fb__ico--dir { color: #c8891c; }
:root[data-theme="dark"] button.wb-fb__row:hover .wb-fb__ico--dir { color: #ffd27a; }

.wb-fb__name {
  flex: 1 1 auto;
  min-width: 0;
  font-size: 0.85rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.wb-fb__meta {
  flex-shrink: 0;
  font-size: 0.75rem;
  color: var(--wb-muted);
  font-variant-numeric: tabular-nums;
}

/* The download affordance only appears on hover: on a list of forty files,
   forty arrows is noise, but with none at all a file row looks inert. */
.wb-fb__dl {
  flex-shrink: 0;
  display: grid;
  place-items: center;
  color: var(--wb-accent);
  opacity: 0;
  transition: opacity .15s var(--wb-ease);
}

a.wb-fb__row:hover .wb-fb__dl,
a.wb-fb__row:focus-visible .wb-fb__dl { opacity: 1; }

/* Touch has no hover, so there it is always visible. */
@media (hover: none) {
  .wb-fb__dl { opacity: 1; }
}

/* ---- sub-navigation (within one tool) ------------------------------------ */
.wb-subnav {
  display: inline-flex;
  gap: 3px;
  padding: 4px;
  border: 1px solid var(--wb-border);
  border-radius: var(--wb-r-pill);
  background: var(--wb-surface);
  backdrop-filter: blur(var(--wb-blur)) saturate(150%);
  -webkit-backdrop-filter: blur(var(--wb-blur)) saturate(150%);
  box-shadow: var(--wb-shadow-sm);
  overflow-x: auto;
  scrollbar-width: none;
  max-width: 100%;
}

.wb-subnav::-webkit-scrollbar { display: none; }

.wb-subnav__item {
  flex-shrink: 0;
  padding: 8px 16px;
  border-radius: var(--wb-r-pill);
  font-size: 0.83rem;
  font-weight: 600;
  color: var(--wb-muted);
  text-decoration: none;
  white-space: nowrap;
  transition: all .18s var(--wb-ease);
}

.wb-subnav__item:hover { color: var(--wb-text); background: var(--wb-surface-sunk); }

.wb-subnav__item--on,
.wb-subnav__item--on:hover {
  background: var(--wb-brand-grad);
  color: var(--wb-accent-contrast);
}

/* ---- SEO suite domain header ---------------------------------------------- */
/* Sits above the .wb-subnav tab strip on every "Audyt stron" page — which
   domain this screen is about, and a way to switch or manage it. */
.wb-seo-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
  margin-bottom: 12px;
}

.wb-seo-switch {
  display: flex;
  align-items: center;
  gap: 10px;
}

.wb-seo-switch .wb-select {
  width: auto;
  padding: 8px 12px;
  font-size: 0.86rem;
}

/* ---- wallpaper picker ---------------------------------------------------- */
.wb-wps {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(124px, 1fr));
  gap: 10px;
}

.wb-wp {
  display: flex;
  flex-direction: column;
  gap: 7px;
  padding: 7px;
  border: 1px solid var(--wb-border);
  border-radius: var(--wb-r);
  background: var(--wb-surface-2);
  font: inherit;
  text-align: left;
  cursor: pointer;
  transition: all .18s var(--wb-ease);
}

.wb-wp:hover { border-color: var(--wb-border-strong); }

/* The selected ring is the accent, which is itself set by the wallpaper — so
   picking one shows you its accent colour in the same gesture. */
.wb-wp--on {
  border-color: var(--wb-accent);
  box-shadow: 0 0 0 2px var(--wb-accent);
}

.wb-wp__img {
  display: block;
  aspect-ratio: 16 / 10;
  border-radius: 9px;
  background: var(--wb-surface-sunk) center/cover no-repeat;
  position: relative;
  overflow: hidden;
}

/* the "no wallpaper" swatch: a plain diagonal, so it reads as empty on purpose */
.wb-wp__none {
  position: absolute;
  inset: 0;
  background: linear-gradient(135deg, transparent 47%, var(--wb-border-strong) 47%, var(--wb-border-strong) 53%, transparent 53%);
}

.wb-wp__name {
  font-size: 0.78rem;
  font-weight: 550;
  color: var(--wb-text-soft);
  padding: 0 2px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* A dot of the accent this wallpaper would set, so the pairing is visible
   before you commit to it. */
.wb-wp__dot {
  position: absolute;
  right: 7px;
  bottom: 7px;
  width: 13px;
  height: 13px;
  border-radius: 50%;
  box-shadow: 0 0 0 2px var(--wb-surface-solid);
}

.wb-wp { position: relative; }

/* ---- range slider -------------------------------------------------------- */
.wb-range {
  width: 100%;
  max-width: 420px;
  height: 26px;
  appearance: none;
  -webkit-appearance: none;
  background: none;
  cursor: pointer;
}

.wb-range::-webkit-slider-runnable-track {
  height: 6px;
  border-radius: var(--wb-r-pill);
  background: var(--wb-surface-sunk);
  border: 1px solid var(--wb-border);
}

.wb-range::-moz-range-track {
  height: 6px;
  border-radius: var(--wb-r-pill);
  background: var(--wb-surface-sunk);
  border: 1px solid var(--wb-border);
}

.wb-range::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 18px;
  height: 18px;
  margin-top: -7px;
  border: 0;
  border-radius: 50%;
  background: var(--wb-accent);
  box-shadow: var(--wb-shadow-sm);
}

.wb-range::-moz-range-thumb {
  width: 18px;
  height: 18px;
  border: 0;
  border-radius: 50%;
  background: var(--wb-accent);
  box-shadow: var(--wb-shadow-sm);
}

/* ---- three-way segment (theme) ------------------------------------------ */
/* The two-way .wb-seg animates a sliding thumb, which needs a known count. This
   one just fills the selected button, so it takes any number of options. */
.wb-seg--3 {
  display: inline-flex;
  gap: 2px;
  padding: 3px;
  border: 1px solid var(--wb-border);
  border-radius: var(--wb-r-pill);
  background: var(--wb-surface-2);
}

.wb-seg--3 button {
  padding: 6px 13px;
  border: 0;
  border-radius: var(--wb-r-pill);
  background: none;
  font: inherit;
  font-size: 0.79rem;
  font-weight: 600;
  color: var(--wb-muted);
  cursor: pointer;
  transition: all .18s var(--wb-ease);
}

.wb-seg--3 button:hover { color: var(--wb-text); }

.wb-seg--3 button[aria-selected="true"] {
  background: var(--wb-brand-grad);
  color: var(--wb-accent-contrast);
}

/* ---- avatar picker ------------------------------------------------------- */
.wb-avatar-edit { display: flex; align-items: center; gap: 18px; flex-wrap: wrap; }

.wb-avatar-edit__av {
  display: grid;
  place-items: center;
  width: 84px;
  height: 84px;
  flex-shrink: 0;
  border-radius: 26px;
  color: var(--wb-accent-contrast);
  font-size: 1.9rem;
  font-weight: 800;
  background: var(--wb-brand-grad);
  box-shadow: var(--wb-shadow-sm);
}

img.wb-avatar-edit__av { object-fit: cover; }

.wb-avatar-edit__side { display: flex; flex-direction: column; gap: 8px; min-width: 0; }
.wb-avatar-edit__row { display: flex; gap: 8px; flex-wrap: wrap; }

/* ---- tool grid (landing) ------------------------------------------------- */
.wb-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(258px, 1fr));
  gap: 16px;
}

.wb-tile {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 22px;
  overflow: hidden;
  text-decoration: none;
  color: inherit;
  background: var(--wb-surface);
  backdrop-filter: blur(var(--wb-blur)) saturate(150%);
  -webkit-backdrop-filter: blur(var(--wb-blur)) saturate(150%);
  border: 1px solid var(--wb-border);
  border-radius: var(--wb-r-lg);
  box-shadow: var(--wb-shadow-sm);
  transition: transform .3s var(--wb-ease), box-shadow .3s var(--wb-ease), border-color .3s var(--wb-ease);
}

/* a soft light that follows nothing — just lifts the card on hover */
.wb-tile::after {
  content: '';
  position: absolute;
  inset: -1px;
  border-radius: inherit;
  padding: 1px;
  background: linear-gradient(135deg, color-mix(in srgb, var(--wb-brand-1) 60%, transparent), transparent 46%, color-mix(in srgb, var(--wb-brand-1) 45%, transparent));
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
          mask-composite: exclude;
  opacity: 0;
  transition: opacity .3s var(--wb-ease);
  pointer-events: none;
}

.wb-tile:hover {
  transform: translateY(-4px);
  box-shadow: var(--wb-shadow-lg);
}

.wb-tile:hover::after { opacity: 1; }

.wb-tile__ico {
  display: grid;
  place-items: center;
  width: 46px;
  height: 46px;
  border-radius: 13px;
  color: var(--wb-accent-contrast);
  background: var(--wb-brand-grad);
  box-shadow: 0 10px 24px -10px var(--wb-brand-2);
}

.wb-tile__ico svg { width: 22px; height: 22px; }

.wb-tile h3 { font-size: 1.02rem; }

.wb-tile p {
  margin: 0;
  font-size: 0.87rem;
  line-height: 1.55;
  color: var(--wb-muted);
}

.wb-tile__foot {
  margin-top: auto;
  padding-top: 12px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  font-size: 0.82rem;
  font-weight: 700;
  color: var(--wb-accent);
}

/* ---- empty state --------------------------------------------------------- */
.wb-empty {
  display: grid;
  place-items: center;
  gap: 10px;
  padding: 56px 24px;
  text-align: center;
  color: var(--wb-muted);
}

.wb-empty__ico {
  display: grid;
  place-items: center;
  width: 54px;
  height: 54px;
  border-radius: 16px;
  background: var(--wb-surface-sunk);
  color: var(--wb-accent);
}

/* ---- modal / login wall -------------------------------------------------- */
.wb-modal {
  position: fixed;
  inset: 0;
  z-index: 90;
  display: grid;
  place-items: center;
  padding: 20px;
  background: rgba(12, 6, 26, 0.62);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  animation: wb-fade .22s var(--wb-ease);
}

.wb-modal[hidden] { display: none; }

.wb-modal__box {
  position: relative;
  width: 100%;
  max-width: 420px;
  padding: 30px 28px 26px;
  text-align: center;
  background: var(--wb-surface-solid);
  border: 1px solid var(--wb-border);
  border-radius: var(--wb-r-lg);
  box-shadow: var(--wb-shadow-lg);
  animation: wb-pop .28s var(--wb-ease);
}

.wb-modal__ico {
  display: grid;
  place-items: center;
  width: 54px;
  height: 54px;
  margin: 0 auto 16px;
  border-radius: 16px;
  color: var(--wb-accent-contrast);
  background: var(--wb-brand-grad);
  box-shadow: 0 12px 28px -10px var(--wb-brand-2);
}

.wb-modal__ico svg { width: 24px; height: 24px; }

.wb-modal__box h2 { font-size: 1.18rem; margin-bottom: 8px; }

.wb-modal__box p {
  margin: 0 0 20px;
  font-size: 0.91rem;
  line-height: 1.6;
  color: var(--wb-muted);
}

.wb-modal__close {
  position: absolute;
  top: 12px;
  right: 12px;
  width: 32px;
  height: 32px;
  display: grid;
  place-items: center;
  border: 0;
  border-radius: var(--wb-r-pill);
  background: none;
  color: var(--wb-muted);
  cursor: pointer;
  font-size: 1.1rem;
  line-height: 1;
}

.wb-modal__close:hover { color: var(--wb-text); background: var(--wb-surface-sunk); }

@keyframes wb-fade { from { opacity: 0; } }
@keyframes wb-pop  { from { opacity: 0; transform: translateY(12px) scale(.97); } }

/* ---- "connect your mailbox" dialog (app/sender-form.php, assets/sender.js) --
   Three steps in one box: provider tiles, then address and password, then
   "connected". Left-aligned, unlike the login-wall modal it shares a shell with. */
.wb-modal__box.snd { max-width: 520px; padding: 28px 26px 24px; text-align: left; max-height: calc(100vh - 40px); max-height: calc(100dvh - 40px); overflow-y: auto; }
.snd h2 { margin: 0 0 6px; padding-right: 30px; font-size: 1.2rem; }
.snd .snd__lead { margin: 0 0 16px; font-size: .9rem; line-height: 1.55; color: var(--wb-muted); }
.snd [hidden] { display: none !important; }
.snd-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
.snd-tile {
  display: flex; align-items: center; gap: 11px; min-width: 0; padding: 10px 12px; text-align: left; font: inherit; color: var(--wb-text); cursor: pointer;
  border: 1px solid var(--wb-border); border-radius: var(--wb-r-sm); background: var(--wb-surface-2);
  transition: border-color .18s var(--wb-ease), transform .18s var(--wb-ease), box-shadow .18s var(--wb-ease);
}
.snd-tile:hover { border-color: var(--wb-brand-1); transform: translateY(-1px); box-shadow: 0 6px 18px -12px rgba(0, 0, 0, .45); }
.snd-tile:active { transform: scale(.985); }
.snd-tile:focus-visible { outline: 2px solid var(--wb-brand-1); outline-offset: 2px; }
.snd-tile__text { display: grid; gap: 1px; min-width: 0; flex: 1; }
.snd-tile strong { font-size: .9rem; line-height: 1.3; }
.snd-tile small { font-size: .74rem; line-height: 1.35; color: var(--wb-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.snd-tile__go { flex-shrink: 0; color: var(--wb-muted); opacity: .55; transition: transform .18s var(--wb-ease), opacity .18s var(--wb-ease); }
.snd-tile:hover .snd-tile__go { opacity: 1; transform: translateX(2px); }
.snd-tile--manual { grid-column: 1 / -1; background: none; border-style: dashed; }
.snd-tile--manual small { white-space: normal; }
/* The provider's initial on its own colour — recognisable without anyone's logo. */
.snd-mark {
  --snd-tint: var(--wb-muted);
  display: grid; place-items: center; flex-shrink: 0; width: 36px; height: 36px; border-radius: 10px;
  font-size: 1rem; font-weight: 700; color: var(--snd-tint);
  background: color-mix(in srgb, var(--snd-tint) 14%, transparent);
}
.snd-prov { display: flex; align-items: center; gap: 11px; }
.snd .snd-prov { margin-bottom: 16px; }
.snd-server { margin: 4px 0 14px; padding: 12px 14px 4px; border: 1px solid var(--wb-border); border-radius: var(--wb-r-sm); min-width: 0; }
.snd-server legend { display: flex; align-items: center; gap: 8px; padding: 0 6px; margin-left: -6px; font-size: .78rem; font-weight: 600; color: var(--wb-text-soft); }
.snd-server__tag { padding: 2px 8px; border-radius: 999px; font-style: normal; font-size: .7rem; font-weight: 600; color: var(--wb-ok); background: var(--wb-ok-bg); }
.snd-server__grid { display: grid; grid-template-columns: minmax(0, 1fr) 92px 128px; gap: 10px; }
.snd-server .wb-field { margin-bottom: 10px; }
.wb-modal__box .snd-server__hint { margin: -2px 0 10px; font-size: .78rem; line-height: 1.5; color: var(--wb-muted); }
.wb-modal__box .snd-server__hint.is-ok { color: var(--wb-ok); }
/* The same connection as a card in the profile (account.php#mailbox). */
.wb-mbox { display: flex; align-items: center; gap: 12px; margin: 0 0 16px; padding: 12px 14px; border: 1px solid var(--wb-border); border-radius: var(--wb-r-sm); background: var(--wb-surface-2); }
.wb-mbox[hidden] { display: none; }
.wb-mbox__icon { display: grid; place-items: center; flex-shrink: 0; width: 40px; height: 40px; border-radius: 12px; color: var(--wb-ok); background: var(--wb-ok-bg); }
.wb-mbox__text { display: grid; gap: 2px; min-width: 0; }
.wb-mbox__text strong, .wb-mbox__text span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.wb-mbox-uses { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
.wb-mbox-use { display: grid; gap: 3px; padding: 12px 14px; border: 1px solid var(--wb-border); border-radius: var(--wb-r-sm); color: inherit; text-decoration: none; transition: border-color .18s var(--wb-ease); }
.wb-mbox-use:hover { border-color: var(--wb-brand-1); }
@media (max-width: 620px) { .wb-mbox-uses { grid-template-columns: minmax(0, 1fr); } }
.snd-back { display: inline-flex; align-items: center; gap: 6px; margin: 0 0 12px; padding: 0; border: 0; background: none; font: inherit; font-size: .84rem; font-weight: 600; color: var(--wb-muted); cursor: pointer; }
.snd-back:hover { color: var(--wb-text); }
.snd .wb-field { margin-bottom: 12px; }
.snd-note { margin: -2px 0 14px; padding: 11px 13px; border-radius: var(--wb-r-sm); font-size: .84rem; line-height: 1.55; color: var(--wb-text-soft); background: var(--wb-warn-bg); }
.snd-note a { font-weight: 600; white-space: nowrap; }
.snd-more { margin: 0 0 12px; }
.snd-more summary { cursor: pointer; font-size: .82rem; color: var(--wb-muted); }
.snd-more .wb-field { margin-top: 10px; }
.wb-modal__box .snd-msg { margin: 0 0 12px; font-size: .88rem; line-height: 1.5; color: var(--wb-muted); }
.snd-msg:empty { display: none; }
.snd-msg__detail { display: block; margin-top: 6px; font-size: .76rem; font-weight: 400; line-height: 1.45; color: var(--wb-muted); word-break: break-word; }
.wb-modal__box .snd-msg.is-bad { color: var(--wb-bad); font-weight: 600; }
.wb-modal__box .snd-safe { display: flex; align-items: flex-start; gap: 8px; margin: 12px 0 0; font-size: .78rem; line-height: 1.5; color: var(--wb-muted); }
.snd-safe svg { flex-shrink: 0; margin-top: 2px; }
.snd-ok { display: grid; place-items: center; width: 54px; height: 54px; margin: 0 0 14px; border-radius: 50%; color: var(--wb-ok); background: var(--wb-ok-bg); }
.snd-done-links { display: flex; justify-content: space-between; gap: 12px; margin-top: 14px; }
.snd-link { padding: 0; border: 0; background: none; font: inherit; font-size: .84rem; color: var(--wb-text-soft); text-decoration: underline; text-underline-offset: 3px; cursor: pointer; }
.snd-link--bad { color: var(--wb-bad); }
@media (max-width: 480px) {
  .snd-grid { grid-template-columns: minmax(0, 1fr); }
  .snd-server__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .snd-server__grid .wb-field:first-child { grid-column: 1 / -1; }
}

/* ---- toast --------------------------------------------------------------- */
.wb-toast {
  position: fixed;
  left: 50%;
  bottom: 26px;
  z-index: 95;
  transform: translateX(-50%);
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 12px 20px;
  font-size: 0.88rem;
  font-weight: 600;
  color: var(--wb-text);
  background: var(--wb-surface-solid);
  border: 1px solid var(--wb-border);
  border-radius: var(--wb-r-pill);
  box-shadow: var(--wb-shadow-lg);
  animation: wb-rise .3s var(--wb-ease);
}

@keyframes wb-rise { from { opacity: 0; transform: translate(-50%, 14px); } }

/* ---- lang visibility ----------------------------------------------------- */
[data-lang-pl], [data-lang-en] { display: none; }
:root[data-lang="pl"] [data-lang-pl] { display: revert; }
:root[data-lang="en"] [data-lang-en] { display: revert; }

/* ---- utilities ----------------------------------------------------------- */
.wb-stack { display: flex; flex-direction: column; gap: 14px; }
.wb-hstack { display: flex; align-items: center; gap: 10px; }
.wb-muted { color: var(--wb-muted); }
.wb-small { font-size: 0.83rem; }
.wb-hide { display: none !important; }
.wb-sr {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* ---- navigation chrome: burger, drawer, collapse ------------------------- */

/* Hidden on desktop; the drawer it opens only exists below the breakpoint. */
/* Behind the phone's menu sheet (see "Phones" at the end of this file). */
.wb-rail-scrim {
  position: fixed;
  inset: 0;
  z-index: 55;
  background: rgba(10, 10, 14, .38);
  opacity: 0;
  transition: opacity .32s var(--wb-ease);
}
body.wb-nav-open .wb-rail-scrim { opacity: 1; }

/* Phone-only block of header controls that live inside the drawer instead. */
.wb-rail__utils { display: none; flex-direction: column; gap: 4px; }
.wb-rail__utils-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 10px 12px 2px;
}

/* Desktop-only collapse control. */
.wb-rail__collapse {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: auto;
  padding: 9px 12px;
  border: 1px solid transparent;
  border-radius: var(--wb-r-sm);
  background: none;
  color: var(--wb-muted);
  font-size: .82rem;
  font-weight: 600;
  cursor: pointer;
  transition: all .2s var(--wb-ease);
}
.wb-rail__collapse:hover { background: var(--wb-surface-sunk); color: var(--wb-text); }
.wb-rail__collapse svg { flex-shrink: 0; transition: transform .28s var(--wb-ease); }

/* NB: .wb-collapse-ico is a <span>, so a blanket
   `.wb-rail__collapse span { display:none }` here would hide the icon itself
   and leave the hover target blank. Only the text label is hidden — and the
   button has no text label any more, so nothing is listed. */
:root[data-rail="collapsed"] .wb-rail__cta,
:root[data-rail="collapsed"] .wb-nav__lock,
:root[data-rail="collapsed"] .wb-nav__count,
:root[data-rail="collapsed"] .wb-me__txt,
:root[data-rail="collapsed"] .wb-me__go { display: none; }
:root[data-rail="collapsed"] .wb-nav { justify-content: center; padding: 9px 0; }

/* The chip keeps only its avatar, centred like every icon below it. */
:root[data-rail="collapsed"] .wb-me { justify-content: center; padding: 8px 0; border-color: transparent; background: none; }

/* The label itself becomes the tooltip when collapsed — no duplicated string
   to translate, so it follows the PL/EN switch for free.
   :not(.wb-nav__count) matters: without it the badge would be promoted to a
   second tooltip and land on top of the label. */
:root[data-rail="collapsed"] .wb-nav > span:not(.wb-nav__ico):not(.wb-nav__count) {
  position: absolute;
  /* Clears the rail's own padding and border so the bubble floats free of the
     panel edge rather than butting up against it. */
  left: calc(100% + 20px);
  top: 50%;
  z-index: 45;
  transform: translateY(-50%) translateX(-4px);
  padding: 7px 11px;
  border-radius: 9px;
  background: var(--wb-text);
  color: var(--wb-surface);
  font-size: .82rem;
  font-weight: 600;
  white-space: nowrap;
  opacity: 0;
  pointer-events: none;
  box-shadow: var(--wb-shadow);
  transition: opacity .18s var(--wb-ease), transform .18s var(--wb-ease);
}
:root[data-rail="collapsed"] .wb-nav:hover > span:not(.wb-nav__ico):not(.wb-nav__count),
:root[data-rail="collapsed"] .wb-nav:focus-visible > span:not(.wb-nav__ico):not(.wb-nav__count) {
  opacity: 1;
  transform: translateY(-50%) translateX(0);
}

/* ---- responsive ---------------------------------------------------------- */
@media (max-width: 1180px) {
  .wb-work { grid-template-columns: minmax(0, 1fr); }
  .wb-work__out { position: static; }
}

@media (max-width: 900px) {
  .wb-shell { grid-template-columns: minmax(0, 1fr); padding: 16px 14px 48px; }
  .wb-bar__logo img { height: 22px; }

  .wb-bar__group--wide { display: none; }
  .wb-rail__collapse { display: none; }
  .wb-rail__utils { display: flex; }

  /* The rail leaves the grid entirely and becomes a sheet that rises from the
     bottom edge, over the tab bar — opened by its "Więcej" tab. The curve and
     the timing are the ones iOS uses for its own sheets. */
  .wb-rail {
    position: fixed;
    top: auto;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 60;
    width: 100%;
    max-width: 560px;
    height: auto;
    /* As tall as its list, up to the height the user has dragged it to
       (--wb-sheet-h, set by wb.js; it opens a little over half the screen). */
    max-height: var(--wb-sheet-h, 56vh);
    margin: 0 auto;
    padding: 0 14px calc(18px + env(safe-area-inset-bottom, 0px));
    gap: 18px;
    border-radius: 28px 28px 0 0;
    border-bottom: 0;
    background: var(--wb-surface-solid);
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    box-shadow: 0 -18px 50px -18px rgba(10, 10, 14, .4);
    overflow-y: auto;
    overscroll-behavior: contain;
    transform: translateY(105%);
    visibility: hidden;
    transition: transform .46s cubic-bezier(.32, .72, 0, 1), max-height .42s cubic-bezier(.32, .72, 0, 1), visibility 0s linear .46s;
  }
  body.wb-nav-open .wb-rail {
    transform: translateY(0);
    visibility: visible;
    transition: transform .46s cubic-bezier(.32, .72, 0, 1), max-height .42s cubic-bezier(.32, .72, 0, 1), visibility 0s;
  }
  body.wb-nav-open { overflow: hidden; }

  /* Collapsing is a desktop affordance; it must not follow the rail into the
     drawer, or the drawer would open as an icon strip. */
  :root[data-rail="collapsed"] .wb-shell { grid-template-columns: minmax(0, 1fr); }
  :root[data-rail="collapsed"] .wb-rail { padding: 16px 14px; }
  :root[data-rail="collapsed"] .wb-rail__title { display: block; }
  :root[data-rail="collapsed"] .wb-nav { justify-content: flex-start; padding: 11px 12px; }
  :root[data-rail="collapsed"] .wb-nav > span:not(.wb-nav__ico):not(.wb-nav__count) {
    position: static;
    transform: none;
    padding: 0;
    border-radius: 0;
    background: none;
    color: inherit;
    font-size: .9rem;
    font-weight: 500;
    opacity: 1;
    box-shadow: none;
  }
  /* Same reasoning: the drawer is the full rail, so the chip and its badges
     come back even while data-rail is still "collapsed" from a desktop visit. */
  :root[data-rail="collapsed"] .wb-nav__count { display: block; }
  :root[data-rail="collapsed"] .wb-me__txt { display: flex; }
  :root[data-rail="collapsed"] .wb-me__go { display: grid; }
  :root[data-rail="collapsed"] .wb-team-sw { display: flex; }
  :root[data-rail="collapsed"] .wb-me {
    justify-content: flex-start;
    padding: 9px 10px;
    border-color: var(--wb-border);
    background: var(--wb-surface-2);
  }
}

@media (max-width: 560px) {
  .wb-row { grid-template-columns: 1fr; }
  .wb-bar { padding: 0 14px; gap: 10px; }
  .wb-card { padding: 17px; }

  /* A card heading and its actions stop competing for one line on a phone.
     Without this a website card ellipsised "websbutler.com" down to
     "websbutler.c…" to make room for the revision button — and the domain is
     what the card *is*, so it wins the line. min-width rather than a forced
     100% so short headings still share a row with their action. */
  .wb-card__head { flex-wrap: wrap; }
  .wb-card__head > h2,
  .wb-card__head > .wb-site-title { min-width: 60%; }
}

@media (min-width: 901px) {
  .wb-rail-scrim { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    transition-duration: .01ms !important;
  }
}


/* ==========================================================================
   Rail: fixed, detached, collapsible
   --------------------------------------------------------------------------
   The rail leaves the page grid on desktop and floats as a fixed panel, so
   the main column gets the full remaining width instead of sharing it with a
   grid track that is no longer occupied.
   ========================================================================== */

:root {
  --wb-rail-gap: 20px;        /* how far the panel floats off every edge */
  --wb-rail-w-collapsed: 76px;
}

/* ---- top row: wordmark, and the collapse control ------------------------- */
.wb-rail__top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding-bottom: 14px;
}

.wb-rail__logo { display: flex; align-items: center; min-width: 0; }
.wb-rail__logo-img { max-width: 148px; width: 100%; height: auto; }
.wb-rail__logo-img-collapsed { display: none; width: 34px; height: auto; }

/* The wordmark ships as black artwork, so dark mode inverts it rather than
   shipping a second file. The glow is a drop-shadow on the alpha channel,
   which traces the letterforms instead of boxing them. */
:root[data-theme="dark"] .wb-rail__logo-img,
:root[data-theme="dark"] .wb-rail__logo-img-collapsed {
  filter: invert(1) brightness(1.9)
          drop-shadow(0 0 6px color-mix(in srgb, var(--wb-brand-1) 70%, transparent))
          drop-shadow(0 0 16px color-mix(in srgb, var(--wb-brand-1) 45%, transparent));
}

.wb-collapse-ico { display: flex; align-items: center; justify-content: center; }
.wb-collapse-ico svg { width: 18px; height: 18px; }

/* ---- vertical rhythm ----------------------------------------------------
   Tuned so the whole rail fits without scrolling on a laptop screen: a
   scrollbar here would sit over the panel's rounded right edge and square it
   off. The scrollbar chrome is hidden as a backstop for very short windows —
   the rail still scrolls by wheel, it just never shows a bar. */
.wb-rail { scrollbar-width: none; -ms-overflow-style: none; }
.wb-rail::-webkit-scrollbar { width: 0; height: 0; display: none; }

/* Desktop only: phones keep the roomier rows, since the drawer scrolls
   anyway and fingers need the target. Measured to fit a 1440x768 laptop
   with headroom to about 690px tall. */
@media (min-width: 901px) {
  /* Breathing room between rows comes from the group gap rather than row
     padding: padding would enlarge each row's hit area and, times twelve
     rows, is what pushes the rail past a 768px-tall screen. The tighter
     outer paddings below pay for the extra gap. */
  .wb-rail { gap: 6px; padding: 8px 14px; }
  .wb-rail__top { padding-bottom: 6px; }
  .wb-rail__group { gap: 8px; }
  .wb-rail__group .wb-rail__title { margin-bottom: 0; }
  .wb-rail .wb-nav { padding: 5px 12px; }
  .wb-rail .wb-nav__ico { width: 28px; height: 28px; }
}

/* ---- desktop: float the panel, free the main column --------------------- */
@media (min-width: 901px) {
  .wb-rail {
    position: fixed;
    top: var(--wb-rail-gap);
    left: var(--wb-rail-gap);
    z-index: 50;
    width: var(--wb-rail-w);
    height: calc(100vh - var(--wb-rail-gap) * 2);
    border: 1px solid var(--wb-border);
    border-radius: var(--wb-r-lg);
    overflow-y: auto;
  }

  /* Single column: the rail is out of flow, so a rail-sized grid track would
     just be dead space squeezing the tools. Width comes from padding instead. */
  .wb-shell {
    grid-template-columns: minmax(0, 1fr);
    max-width: none;
    padding: 22px var(--wb-rail-gap) 64px
             calc(var(--wb-rail-w) + var(--wb-rail-gap) * 2);
  }
  .wb-main { width: 100%; max-width: 1240px; margin: 0 auto; }

  /* Fill the leftover viewport height so a lone sign-in card lands at optical
     centre instead of hanging under the top bar. min-height, not height:
     content taller than the viewport still grows and scrolls normally.
     86px = the shell's own 22px top + 64px bottom padding. */
  .wb-main--center {
    justify-content: center;
    min-height: calc(100vh - var(--wb-bar-h) - 86px);
  }

  :root[data-rail="collapsed"] .wb-rail { width: var(--wb-rail-w-collapsed); }
  :root[data-rail="collapsed"] .wb-shell {
    padding-left: calc(var(--wb-rail-w-collapsed) + var(--wb-rail-gap) * 2);
  }

  /* Collapsed labels are tooltips that sit outside the panel, so this one
     cannot clip. Icons alone always fit, so nothing needs to scroll here. */
  :root[data-rail="collapsed"] .wb-rail { overflow: visible; }

  .wb-bar__logo { display: none; }
}

/* ---- collapsed: icon strip ----------------------------------------------
   Desktop-scoped on purpose. The collapsed choice is remembered per browser,
   so data-rail="collapsed" is still set when the same session is opened on a
   phone — unscoped, these cosmetics would shrink the drawer's icons and blank
   out its section headings. */
/* The collapsed-rail mark is the full-colour app icon (assets/logo-mark.svg):
   none of the wordmark's black/invert/glow treatment applies to it. The extra
   .wb-rail makes these outrank the collapsed-state rules below. */
:root .wb-rail .wb-rail__logo-img-collapsed,
:root[data-theme="dark"] .wb-rail .wb-rail__logo-img-collapsed,
:root[data-rail="collapsed"] .wb-rail .wb-rail__logo-img-collapsed,
:root[data-theme="dark"][data-rail="collapsed"] .wb-rail .wb-rail__logo-img-collapsed { filter: none; border-radius: 8px; }

.wb-rail__logo { transition: opacity .2s var(--wb-ease); }

@media (min-width: 901px) {
  :root[data-rail="collapsed"] .wb-rail { padding: 14px 10px; }
  :root[data-rail="collapsed"] .wb-rail__logo-img { display: none; }
  :root[data-rail="collapsed"] .wb-rail__logo-img-collapsed { display: block; filter: brightness(0); }
  :root[data-theme="dark"][data-rail="collapsed"] .wb-rail__logo-img-collapsed {
    filter: brightness(0) invert(1)
            drop-shadow(0 0 6px color-mix(in srgb, var(--wb-brand-1) 70%, transparent))
            drop-shadow(0 0 16px color-mix(in srgb, var(--wb-brand-1) 45%, transparent));
  }

  /* Bigger, box-free icons: dropping the tinted tile is what buys the
     contrast, since the glyph then sits on the panel rather than a pale chip. */
  /* The glyph grows (16 -> 21) while its hit box shrinks a little: without
     the tinted tile the box is invisible anyway, and the taller collapsed
     rows are what would otherwise push the strip past the viewport. */
  :root[data-rail="collapsed"] .wb-rail .wb-nav { padding: 4px 0; }
  :root[data-rail="collapsed"] .wb-rail .wb-nav__ico {
    width: 34px;
    height: 34px;
    background: none;
    color: var(--wb-text-soft);
  }
  :root[data-rail="collapsed"] .wb-rail .wb-nav__ico svg { width: 21px; height: 21px; }
  :root[data-rail="collapsed"] .wb-nav:not(.wb-nav--on):hover .wb-nav__ico { color: var(--wb-accent); }
  :root[data-rail="collapsed"] .wb-nav--on .wb-nav__ico,
  :root[data-rail="collapsed"] .wb-nav--on:hover .wb-nav__ico { background: none; color: var(--wb-accent-contrast); }
  :root[data-rail="collapsed"] .wb-nav--logout .wb-nav__ico { color: inherit; }

  /* The wordmark swaps to an expand affordance on hover. */
  :root[data-rail="collapsed"] .wb-rail__top {
    position: relative;
    justify-content: center;
    min-height: 40px;
  }
  :root[data-rail="collapsed"] .wb-rail__collapse {
    position: absolute;
    inset: 0;
    margin: 0;
    padding: 0;
    justify-content: center;
    background: none;
    opacity: 0;
    pointer-events: none;
    transition: opacity .2s var(--wb-ease);
  }
  :root[data-rail="collapsed"] .wb-rail__top:hover .wb-rail__collapse { opacity: 1; pointer-events: auto; }
  :root[data-rail="collapsed"] .wb-rail__top:hover .wb-rail__logo { opacity: 0; }
  :root[data-rail="collapsed"] .wb-rail__collapse .wb-collapse-ico svg { transform: rotate(180deg); }
}

/* Section headings become hairlines rather than disappearing, so the grouping
   survives the collapse. Desktop-scoped for the same reason as above. */
@media (min-width: 901px) {
  :root[data-rail="collapsed"] .wb-rail__title {
    height: 1px;
    margin: 6px 8px 7px;
    padding: 0;
    font-size: 0;
    background: var(--wb-border);
  }
}

/* On a short window the icon strip can still run past the panel, and with
   overflow visible it would spill down the page instead of stopping at the
   rounded edge. Below this height it scrolls instead — the tooltips clip,
   which is the lesser of the two problems, and the bar stays hidden. */
@media (min-width: 901px) and (max-height: 720px) {
  :root[data-rail="collapsed"] .wb-rail { overflow-y: auto; }
}

/* ---- top bar: chrome only ----------------------------------------------- */
.wb-bar {
  background: transparent;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  border-bottom: none;
  pointer-events: none;
}
.wb-bar > * { pointer-events: auto; }

/* ---- sign out, pinned to the foot of the rail --------------------------- */
.wb-nav--logout { margin-top: auto; color: var(--wb-bad); }
.wb-nav--logout:hover { background: var(--wb-bad-bg, rgba(220, 53, 69, .08)); color: var(--wb-bad); }
.wb-nav--logout .wb-nav__ico { color: inherit; }

/* ---- phones: the logo in the top bar, not in the menu sheet -------------- */
@media (max-width: 900px) {
  .wb-bar__logo { display: flex; }
  .wb-rail__top { display: none; }
  /* On a phone the bar carries the logo over scrolling content: frosted, so
     the page does not show through behind the logo. */
  .wb-bar {
    background: var(--wb-surface);
    backdrop-filter: blur(var(--wb-blur)) saturate(150%);
    -webkit-backdrop-filter: blur(var(--wb-blur)) saturate(150%);
    border-bottom: 1px solid var(--wb-border);
  }
}

/* ---- data list ----------------------------------------------------------- */
/* First real table component in the panel (the invoice and customer lists).
   Row separators only — no vertical rules and no zebra, which keeps it reading
   as a list rather than a spreadsheet. */
.wb-list { width: 100%; border-collapse: collapse; font-size: .9rem; }

.wb-list th {
  padding: 8px 10px;
  font-size: .66rem;
  font-weight: 700;
  letter-spacing: .07em;
  text-transform: uppercase;
  text-align: left;
  white-space: nowrap;
  color: var(--wb-muted);
  border-bottom: 1px solid var(--wb-border);
}

.wb-list td {
  padding: 11px 10px;
  border-bottom: 1px solid var(--wb-border);
  vertical-align: middle;
}

.wb-list tr:last-child td { border-bottom: 0; }
.wb-list tbody tr:hover { background: var(--wb-bg); }
.wb-list .r { text-align: right; }

/* Keeps the action cell from stretching the row on narrow screens. */
.wb-list td.r { white-space: nowrap; }

/* ---- site audit ----------------------------------------------------------- */
.wb-audit-bar {
  height: 8px;
  border-radius: var(--wb-r-pill);
  background: var(--wb-surface-sunk);
  overflow: hidden;
}

.wb-audit-bar > span {
  display: block;
  height: 100%;
  width: 0;
  border-radius: var(--wb-r-pill);
  background: var(--wb-accent);
  transition: width .45s var(--wb-ease);
}

.wb-audit-head { display: flex; align-items: center; gap: 22px; flex-wrap: wrap; }

/* The score is the one number anyone quotes back, so it gets to be big. */
.wb-audit-score {
  display: flex;
  align-items: baseline;
  gap: 4px;
  padding: 14px 22px;
  border-radius: var(--wb-r);
  background: var(--wb-surface-sunk);
}

.wb-audit-score strong { font-size: 2.6rem; font-weight: 800; line-height: 1; letter-spacing: -.03em; }
.wb-audit-score span   { font-size: .82rem; color: var(--wb-muted); }
.wb-audit-score--ok   strong { color: var(--wb-ok); }
.wb-audit-score--warn strong { color: var(--wb-warn); }
.wb-audit-score--bad  strong { color: var(--wb-bad); }

.wb-audit-sums {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(96px, 1fr));
  gap: 14px;
  flex: 1;
  min-width: 0;
}

.wb-audit-sum strong { display: block; font-size: 1.4rem; font-weight: 750; line-height: 1.1; }
.wb-audit-sum span {
  font-size: .72rem;
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--wb-muted);
}
.wb-audit-sum--critical strong { color: var(--wb-bad); }
.wb-audit-sum--warning  strong { color: var(--wb-warn); }

/* ---- one issue group ------------------------------------------------------ */
.wb-issue { padding: 0; overflow: hidden; }

.wb-issue > summary {
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 15px 20px;
  cursor: pointer;
  list-style: none;
}

.wb-issue > summary::-webkit-details-marker { display: none; }
.wb-issue > summary:hover { background: var(--wb-surface-2); }

.wb-issue__dot { width: 9px; height: 9px; border-radius: 50%; flex-shrink: 0; background: var(--wb-muted); }
.wb-issue--critical .wb-issue__dot { background: var(--wb-bad); }
.wb-issue--warning  .wb-issue__dot { background: var(--wb-warn); }

.wb-issue__title { flex: 1; min-width: 0; font-size: .93rem; font-weight: 600; }

.wb-issue__count {
  flex-shrink: 0;
  min-width: 26px;
  padding: 3px 9px;
  border-radius: var(--wb-r-pill);
  background: var(--wb-surface-sunk);
  color: var(--wb-text-soft);
  font-size: .78rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  text-align: center;
}

.wb-issue__what { margin: 0 20px 6px; font-size: .86rem; color: var(--wb-text-soft); }
.wb-issue__fix  { margin: 0 20px 12px; font-size: .84rem; color: var(--wb-muted); }
.wb-issue__fix strong { color: var(--wb-text-soft); }

.wb-issue__rows { padding: 0 20px 18px; }

.wb-issue__row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 14px;
  padding: 7px 0;
  border-top: 1px solid var(--wb-border);
  font-size: .82rem;
}

/* The URL is the one exact string here, and long paths must not push the row
   sideways — they scroll inside it. */
.wb-issue__row a {
  min-width: 0;
  overflow-x: auto;
  white-space: nowrap;
  color: var(--wb-accent);
  text-decoration: none;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: .78rem;
  scrollbar-width: thin;
}

.wb-issue__row a:hover { text-decoration: underline; }
.wb-issue__row span { flex-shrink: 0; color: var(--wb-muted); font-variant-numeric: tabular-nums; }

/* ---- scan packs ----------------------------------------------------------- */
.wb-pack {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 13px 15px;
  border: 1px solid var(--wb-border);
  border-radius: var(--wb-r-sm);
  text-decoration: none;
  color: inherit;
  transition: all .18s var(--wb-ease);
}

.wb-pack:hover { border-color: var(--wb-accent); background: var(--wb-surface-2); }
.wb-pack strong { display: block; font-size: .92rem; }
.wb-pack__price { flex-shrink: 0; color: var(--wb-accent); font-size: 1rem; }

/* ---- admin: tab bar inside a section (app/admin.php wb_admin_tabs) -------- */
.wb-admin-tabs { display: flex; gap: 6px; flex-wrap: wrap; margin: 0 0 18px; padding: 4px; border-radius: var(--wb-r-pill); background: var(--wb-surface-sunk); width: fit-content; max-width: 100%; }
.wb-admin-tabs__item { display: inline-flex; align-items: center; gap: 8px; padding: 8px 16px; border-radius: var(--wb-r-pill); color: var(--wb-text-soft); text-decoration: none; font-weight: 600; font-size: .9rem; white-space: nowrap; }
.wb-admin-tabs__item:hover { color: var(--wb-text); }
.wb-admin-tabs__item.is-on { background: var(--wb-surface-solid, var(--wb-surface-2)); color: var(--wb-text); box-shadow: var(--wb-shadow-sm); }
.wb-admin-tabs__count { min-width: 20px; height: 20px; padding: 0 6px; border-radius: 99px; background: var(--wb-brand-1); color: var(--wb-accent-contrast, #101012); font-size: .72rem; font-weight: 800; display: inline-grid; place-items: center; }

/* ---- tool libraries: the QR grid (tools/qr.php) ---------------------------
   The tool opens on the person's own codes; the first tile is always "new". */
.wb-qrlib { display: grid; grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); gap: 16px; }
.wb-qrlib[data-count="0"] { grid-template-columns: minmax(0, 420px); justify-content: center; padding-top: 4vh; }
.wb-qrlib__new {
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 12px; text-align: center;
  min-height: 250px; padding: 22px; border-radius: var(--wb-r-lg, 20px); text-decoration: none; color: var(--wb-text);
  border: 2px dashed color-mix(in srgb, var(--wb-brand-1) 55%, var(--wb-border));
  background: color-mix(in srgb, var(--wb-brand-1) 6%, var(--wb-surface));
  transition: transform .2s var(--wb-ease), background .2s var(--wb-ease), border-color .2s var(--wb-ease);
}
.wb-qrlib__new:hover { transform: translateY(-3px); border-color: var(--wb-brand-1); background: color-mix(in srgb, var(--wb-brand-1) 11%, var(--wb-surface)); }
.wb-qrlib__plus {
  display: grid; place-items: center; width: 64px; height: 64px; border-radius: 20px;
  background: var(--wb-brand-grad); color: var(--wb-accent-contrast);
  box-shadow: 0 14px 30px -14px var(--wb-brand-1);
  transition: transform .25s var(--wb-ease);
}
.wb-qrlib__new:hover .wb-qrlib__plus { transform: rotate(90deg) scale(1.06); }
.wb-qrlib[data-count="0"] .wb-qrlib__new { min-height: 320px; }
.wb-qrlib[data-count="0"] .wb-qrlib__plus { width: 84px; height: 84px; border-radius: 26px; }
.wb-qrlib__new strong { font-size: 1rem; }
.wb-qrlib__item { position: relative; border-radius: var(--wb-r-lg, 20px); background: var(--wb-surface); border: 1px solid var(--wb-border); box-shadow: var(--wb-shadow-sm); transition: transform .2s var(--wb-ease), box-shadow .2s var(--wb-ease); }
.wb-qrlib__item:hover { transform: translateY(-3px); box-shadow: var(--wb-shadow, 0 18px 40px -20px rgba(0,0,0,.35)); }
.wb-qrlib__open { display: flex; flex-direction: column; gap: 12px; padding: 16px; text-decoration: none; color: var(--wb-text); }
.wb-qrlib__img { display: grid; place-items: center; aspect-ratio: 1; border-radius: 14px; background: #fff; overflow: hidden; }
.wb-qrlib__img svg, .wb-qrlib__img canvas { width: 82%; height: auto; }
.wb-qrlib__meta { display: grid; gap: 2px; min-width: 0; }
.wb-qrlib__meta strong { font-size: .9rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.wb-qrlib__del {
  position: absolute; top: 10px; right: 10px; width: 34px; height: 34px; display: grid; place-items: center;
  border: 0; border-radius: 10px; background: color-mix(in srgb, var(--wb-surface) 88%, transparent); color: var(--wb-bad);
  box-shadow: var(--wb-shadow-sm); cursor: pointer; opacity: 0; transition: opacity .15s;
}
.wb-qrlib__item:hover .wb-qrlib__del, .wb-qrlib__del:focus-visible { opacity: 1; }
@media (hover: none) { .wb-qrlib__del { opacity: 1; } }
.wb-qrbar { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin: 0 0 14px; }
.wb-qrbar__status { font-size: .84rem; color: var(--wb-muted); }
.wb-qrbar__status[data-tone="ok"]::before { content: '✓ '; color: var(--wb-ok); font-weight: 700; }
.wb-qrbar__status[data-tone="bad"] { color: var(--wb-bad); }
@media (max-width: 560px) { .wb-qrlib { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; } .wb-qrlib__new { min-height: 200px; } }

/* Pulpit — "Do zrobienia" (dashboard.php) */
.wb-todo__list { display: grid; gap: 8px; }
.wb-todo__item { display: flex; align-items: center; gap: 12px; padding: 12px 14px; border-radius: var(--wb-r-sm); border: 1px solid var(--wb-border); background: var(--wb-surface-2); color: var(--wb-text); text-decoration: none; transition: border-color .15s, transform .15s; }
.wb-todo__item:hover { border-color: var(--wb-brand-1); transform: translateY(-1px); }
.wb-todo__ico { width: 34px; height: 34px; border-radius: 10px; display: grid; place-items: center; flex-shrink: 0; background: var(--wb-warn-bg, color-mix(in srgb, var(--wb-warn) 14%, transparent)); color: var(--wb-warn); }
.wb-todo__txt { flex: 1; min-width: 0; font-weight: 600; overflow-wrap: anywhere; }
.wb-todo__cta { font-size: .84rem; font-weight: 700; color: var(--wb-brand-1); white-space: nowrap; }
.wb-todo__clear { display: flex; align-items: center; gap: 10px; margin: 0; color: var(--wb-ok); font-weight: 600; }

/* Page loading line (wb.js): grows while a boosted page loads, fills and fades on arrival. */
.wb-loadbar { position: fixed; top: 0; left: 0; z-index: 200; height: 3px; width: 0; opacity: 0; pointer-events: none; background: var(--wb-brand-grad); box-shadow: 0 0 10px var(--wb-brand-1); }
.wb-loadbar.is-on { opacity: 1; width: 85%; transition: width 8s cubic-bezier(.1, .7, .2, 1); }
.wb-loadbar.is-done { width: 100%; opacity: 0; transition: width .2s ease, opacity .3s ease .15s; }
.wb-todo__item--start .wb-todo__ico { background: color-mix(in srgb, var(--wb-brand-1) 14%, transparent); color: var(--wb-brand-1); }

/* Switches (Moje konto → Powiadomienia) */
.wb-toggle { position: relative; display: inline-block; width: 46px; height: 26px; flex-shrink: 0; }
.wb-toggle input { position: absolute; opacity: 0; width: 100%; height: 100%; margin: 0; cursor: pointer; z-index: 1; }
.wb-toggle span { position: absolute; inset: 0; border-radius: 99px; background: var(--wb-border-strong, #bbb); transition: background .2s; }
.wb-toggle span::after { content: ''; position: absolute; top: 3px; left: 3px; width: 20px; height: 20px; border-radius: 50%; background: #fff; box-shadow: 0 1px 3px rgba(0,0,0,.25); transition: transform .2s; }
.wb-toggle input:checked + span { background: var(--wb-brand-1, var(--wb-accent)); }
.wb-toggle input:checked + span::after { transform: translateX(20px); }
.wb-toggle input:focus-visible + span { outline: 2px solid var(--wb-accent); outline-offset: 2px; }
.wb-notify { display: grid; gap: 10px; }
.wb-notify__row { display: flex; align-items: center; gap: 16px; padding: 14px 16px; border: 1px solid var(--wb-border); border-radius: var(--wb-r-sm); cursor: pointer; }
.wb-notify__txt { flex: 1; min-width: 0; display: grid; gap: 2px; }

/* Sign-up consent (login.php) */
.wb-consent { display: flex; gap: 10px; align-items: center; margin: 0; cursor: pointer; color: var(--wb-text-soft); }
.wb-consent input { margin: 0; width: 17px; height: 17px; flex-shrink: 0; accent-color: var(--wb-accent, #ff6a30); }

/* Pulpit: the orange "Audyt stron" card under "Kolejna strona?" */
.wb-promo--hot { background: linear-gradient(140deg, #ff7a3d, #f2541b); border-color: transparent; color: #fff; box-shadow: 0 10px 28px rgba(242, 84, 27, .28); }
.wb-promo--hot h3 { color: #fff; }
.wb-promo--hot p { color: rgba(255, 255, 255, .88); }
.wb-promo--hot .wb-btn { background: #fff; color: #d9480f; border-color: #fff; font-weight: 700; }
.wb-promo--hot .wb-btn:hover { background: #fff3ec; color: #b83a0a; }

/* Panel admina → Wszystkie strony: three a row */
.ad-sites { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px; }
.ad-site { display: flex; flex-direction: column; gap: 3px; padding: 14px 15px; border: 1px solid var(--wb-border); border-radius: var(--wb-r-sm); background: var(--wb-surface); min-width: 0; }
.ad-site__top { display: flex; align-items: center; gap: 8px; min-width: 0; }
.ad-site__domain { font-weight: 700; font-size: .98rem; color: inherit; text-decoration: none; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ad-site__domain:hover { text-decoration: underline; }
.ad-site__dot { width: 9px; height: 9px; border-radius: 50%; flex-shrink: 0; background: var(--wb-muted); }
.ad-site__dot--ok { background: #22c55e; box-shadow: 0 0 0 3px rgba(34, 197, 94, .18); }
.ad-site__dot--warn { background: #f59e0b; box-shadow: 0 0 0 3px rgba(245, 158, 11, .18); }
.ad-site__dot--bad { background: #ef4444; box-shadow: 0 0 0 3px rgba(239, 68, 68, .18); }
.ad-site__meta { font-size: .78rem; color: var(--wb-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ad-site__btns { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
@media (max-width: 1100px) { .ad-sites { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 640px) { .ad-sites { grid-template-columns: minmax(0, 1fr); } }

/* ==========================================================================
   Guides: a labelled button beside whatever may need explaining
   --------------------------------------------------------------------------
   Markup comes from wb_help() (app/shell.php); behaviour from initHelp() in
   wb.js. The button names its question ("Co to jest DNS?") so nobody has to
   guess what a symbol hides; the card opens in the page flow under the line
   the button sits on, in full-size body text, never as small print.
   ========================================================================== */
.wb-help { display: inline-flex; vertical-align: middle; margin-left: 10px; }

.wb-help__btn {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  max-width: 100%;
  padding: 5px 13px 5px 9px;
  border: 1px solid color-mix(in srgb, var(--wb-accent) 26%, var(--wb-border));
  border-radius: var(--wb-r-pill);
  background: color-mix(in srgb, var(--wb-accent) 8%, var(--wb-surface-solid));
  color: var(--wb-text);
  font-family: inherit;
  font-size: 13.5px;
  font-weight: 600;
  line-height: 1.25;
  letter-spacing: 0;
  text-transform: none;
  text-align: left;
  white-space: normal;
  cursor: pointer;
  transition: background-color .18s var(--wb-ease), border-color .18s var(--wb-ease), color .18s var(--wb-ease), transform .12s var(--wb-ease);
}

/* The button is about 28px tall; the hit area reaches 44px for a thumb. */
.wb-help__btn::after { content: ''; position: absolute; inset: -8px -2px; border-radius: inherit; }

.wb-help__bulb { display: inline-flex; color: var(--wb-accent); flex-shrink: 0; transition: color .18s var(--wb-ease); }
.wb-help__bulb svg { width: 16px; height: 16px; }

.wb-help__btn:hover {
  background: color-mix(in srgb, var(--wb-accent) 15%, var(--wb-surface-solid));
  border-color: color-mix(in srgb, var(--wb-accent) 45%, var(--wb-border));
}
.wb-help__btn:active { transform: scale(.97); }

.wb-help__btn[aria-expanded="true"] {
  background: var(--wb-accent);
  border-color: var(--wb-accent);
  color: var(--wb-accent-contrast);
}
.wb-help__btn[aria-expanded="true"] .wb-help__bulb { color: inherit; }

/* Inside small print (a stat label, a checkbox line): a smaller button. */
:is(.wb-small, label, .wb-label) .wb-help__btn { font-size: 12.5px; padding: 3px 10px 3px 7px; }
:is(.wb-small, label, .wb-label) .wb-help__bulb svg { width: 14px; height: 14px; }

/* Beside a page heading it reads as part of the heading row. */
.wb-page-head h1 .wb-help,
.mg-title .wb-help,
.fin-head h1 .wb-help { margin-left: 14px; vertical-align: .2em; }
.wb-page-head h1 .wb-help__btn,
.mg-title .wb-help__btn,
.fin-head h1 .wb-help__btn { font-size: 14px; padding: 6px 14px 6px 10px; }

/* ---- the card -------------------------------------------------------------- */
.wb-help__panel {
  display: block;
  width: 100%;
  margin: 14px 0 18px;
  font-family: inherit;
  font-size: 15px;
  font-weight: 400;
  line-height: 1.65;
  letter-spacing: 0;
  text-align: left;
  text-transform: none;
  opacity: 0;
  transform: translateY(-6px) scale(.985);
  transform-origin: top left;
  transition: opacity .2s var(--wb-ease), transform .24s var(--wb-ease);
}
.wb-help__panel[hidden] { display: none; }
.wb-help__panel.is-open { opacity: 1; transform: none; }
.wb-help__panel:focus { outline: none; }
.wb-page-head .wb-help__panel { margin: 10px 0 4px; }

.wb-help__card {
  position: relative;
  display: flex;
  gap: 16px;
  align-items: flex-start;
  padding: 20px 52px 20px 20px;
  border: 1px solid color-mix(in srgb, var(--wb-accent) 24%, var(--wb-border));
  border-radius: var(--wb-r);
  background: color-mix(in srgb, var(--wb-accent) 6%, var(--wb-surface-solid));
  box-shadow: 0 10px 30px -18px color-mix(in srgb, var(--wb-accent) 60%, transparent);
  color: var(--wb-text-soft);
}

.wb-help__ico {
  display: grid;
  place-items: center;
  flex-shrink: 0;
  width: 42px;
  height: 42px;
  border-radius: 12px;
  background: color-mix(in srgb, var(--wb-accent) 14%, var(--wb-surface-solid));
  color: var(--wb-accent);
}

.wb-help__body { display: block; min-width: 0; max-width: 74ch; }

.wb-help__title {
  display: block;
  margin: 1px 0 8px;
  font-size: 16.5px;
  font-weight: 650;
  line-height: 1.35;
  letter-spacing: -0.01em;
  color: var(--wb-text);
}

.wb-help__p { display: block; margin: 0 0 10px; }
.wb-help__p:last-of-type { margin-bottom: 0; }

.wb-help__foot { display: flex; margin-top: 14px; }

.wb-help__ok {
  padding: 8px 18px;
  border: 0;
  border-radius: var(--wb-r-pill);
  background: var(--wb-accent);
  color: var(--wb-accent-contrast);
  font: inherit;
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  transition: filter .15s var(--wb-ease), transform .12s var(--wb-ease);
}
.wb-help__ok:hover { filter: brightness(1.08); }
.wb-help__ok:active { transform: scale(.97); }

.wb-help__close {
  position: absolute;
  top: 12px;
  right: 12px;
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: none;
  color: var(--wb-muted);
  cursor: pointer;
  transition: background-color .15s var(--wb-ease), color .15s var(--wb-ease);
}
.wb-help__close:hover { background: var(--wb-surface-sunk); color: var(--wb-text); }

@media (max-width: 600px) {
  .wb-help__card { padding: 16px 46px 16px 16px; gap: 12px; }
  .wb-help__ico { width: 36px; height: 36px; border-radius: 10px; }
  .wb-page-head h1 .wb-help,
  .mg-title .wb-help,
  .fin-head h1 .wb-help { display: flex; margin: 10px 0 0; }
}

@media (prefers-reduced-motion: reduce) {
  .wb-help__panel { transition: none; transform: none; }
}

/* ==========================================================================
   Feel — the small movements that make the panel read as one fluid app
   ========================================================================== */

/* A page arriving through boosted navigation: its blocks rise in one after
   another instead of all appearing at once. wb.js adds .is-entering for the
   length of the animation only, so nothing replays when a card re-renders.
   Not used on a full page load — the browser's view transition already
   cross-fades that, and the two together read as a stutter. */
@keyframes wb-enter { from { opacity: 0; transform: translateY(12px); } }

/* The delay per block is set inline by wb.js (it has to skip the <style> and
   <script> elements pages keep between their cards, which nth-child counts). */
.wb-main.is-entering > * { animation: wb-enter .46s var(--wb-ease) backwards; }

/* Pressing something answers under the finger, before the page does. */
.wb-btn:active:not(:disabled),
.wb-icon-btn:active,
.wb-chip:active,
.wb-stab:active { transform: scale(.97); transition-duration: .06s; }
.wb-nav:active { transform: scale(.985); transition-duration: .06s; }
a.wb-stat:active, .wb-tile:active { transform: scale(.99); transition-duration: .06s; }

/* A submitted form's button: a spinner in place of the label's leading icon,
   so a slow save does not look like an ignored click (wb.js sets .is-busy). */
.wb-btn.is-busy { pointer-events: none; opacity: .8; }
.wb-btn.is-busy::before {
  content: '';
  width: 14px;
  height: 14px;
  flex-shrink: 0;
  border: 2px solid currentColor;
  border-top-color: transparent;
  border-radius: 50%;
  animation: wb-spin .7s linear infinite;
}
.wb-btn.is-busy > svg:first-child { display: none; }
@keyframes wb-spin { to { transform: rotate(360deg); } }

/* Toasts leave the way they came, instead of vanishing. */
.wb-toast.is-leaving { opacity: 0; transform: translate(-50%, 10px); transition: opacity .25s var(--wb-ease), transform .25s var(--wb-ease); }

/* Buttons that sit straight on the wallpaper rather than in a card: the
   see-through ghost style is unreadable over a photo, so they get the solid
   surface a card would have given them. */
.wb-main > .wb-btn--ghost,
.wb-main > .wb-hstack > .wb-btn--ghost {
  background: var(--wb-surface-solid);
  color: var(--wb-text);
  border-color: var(--wb-border-strong);
  box-shadow: var(--wb-shadow-sm);
}
.wb-main:not(.wb-main--center) > .wb-btn--ghost { align-self: flex-start; }

/* Headings never leave one word alone on the last line; body copy avoids it. */
h1, h2, h3 { text-wrap: balance; }
p { text-wrap: pretty; }

/* Scrollbars inside the panel (lists, panes, drawers) are part of the chrome:
   thin and quiet. The page's own scrollbar is left as the system draws it. */
body * { scrollbar-width: thin; scrollbar-color: var(--wb-border-strong) transparent; }

/* Disclosures open and close with their content, where the browser can
   animate to an automatic height; elsewhere they simply open. */
@supports (interpolate-size: allow-keywords) {
  :root { interpolate-size: allow-keywords; }
  details::details-content {
    height: 0;
    overflow: clip;
    overflow-clip-margin: 6px;
    opacity: 0;
    transition: height .28s var(--wb-ease), opacity .22s var(--wb-ease), content-visibility .28s allow-discrete;
  }
  details[open]::details-content { height: auto; opacity: 1; }
}

/* ==========================================================================
   Phones: a tab bar at the bottom, the rest of the menu as a sheet
   --------------------------------------------------------------------------
   Up to 900px the rail is not on screen. Navigation is a floating glass bar
   where the thumb already is: four destinations and "Więcej", which raises the
   rail as a sheet. Markup: .wb-tabbar in app/shell.php; behaviour: setActiveNav
   and initNav in wb.js.
   ========================================================================== */
.wb-tabbar,
.wb-bar__me,
.wb-bar__login,
.wb-rail__sheet-head { display: none; }

@media (max-width: 900px) {
  :root {
    --wb-bar-h: 58px;
    --wb-safe-b: env(safe-area-inset-bottom, 0px);
    /* What the bar occupies above the bottom edge: its gap, its height, air. */
    --wb-tabbar-space: calc(86px + var(--wb-safe-b));
  }

  /* ---- top bar: the logo and the account -------------------------------- */
  .wb-bar {
    padding-left: max(16px, env(safe-area-inset-left, 0px));
    padding-right: max(16px, env(safe-area-inset-right, 0px));
  }
  .wb-bar__me { display: flex; border-radius: 12px; }
  .wb-bar__me .wb-me__av { width: 34px; height: 34px; border-radius: 11px; }
  .wb-bar__me:active { transform: scale(.94); }
  .wb-bar__login { display: inline-flex; }

  /* Room under the last card, so the bar never covers what it ends with. */
  .wb-shell {
    padding-bottom: calc(var(--wb-tabbar-space) + 18px);
    padding-left: max(14px, env(safe-area-inset-left, 0px));
    padding-right: max(14px, env(safe-area-inset-right, 0px));
  }

  /* ---- the bar ---------------------------------------------------------- */
  .wb-tabbar {
    position: fixed;
    left: max(12px, env(safe-area-inset-left, 0px));
    right: max(12px, env(safe-area-inset-right, 0px));
    bottom: calc(10px + var(--wb-safe-b));
    z-index: 50;
    display: grid;
    grid-template-columns: repeat(var(--wb-tabs, 5), minmax(0, 1fr));
    max-width: 520px;
    margin: 0 auto;
    padding: 5px;
    border-radius: 30px;
    /* Glass: mostly the surface colour, a little of what is behind it. */
    background: rgba(255, 255, 255, .72);
    background: color-mix(in srgb, var(--wb-surface-solid) 72%, transparent);
    -webkit-backdrop-filter: blur(22px) saturate(180%);
    backdrop-filter: blur(22px) saturate(180%);
    border: 1px solid color-mix(in srgb, var(--wb-text) 9%, transparent);
    box-shadow:
      0 14px 38px -12px rgba(10, 10, 14, .34),
      0 2px 8px rgba(10, 10, 14, .07),
      inset 0 1px 0 rgba(255, 255, 255, .5);
    transition: transform .4s cubic-bezier(.32, .72, 0, 1), opacity .25s var(--wb-ease);
  }
  :root[data-theme="dark"] .wb-tabbar {
    box-shadow:
      0 14px 38px -12px rgba(0, 0, 0, .7),
      0 2px 8px rgba(0, 0, 0, .35),
      inset 0 1px 0 rgba(255, 255, 255, .09);
  }

  /* The capsule under the current tab. One element that slides, so moving
     between tabs reads as moving, not as two things blinking. --wb-tab is the
     tab's position, set by the server and kept by wb.js. */
  .wb-tabbar__thumb {
    position: absolute;
    top: 5px;
    bottom: 5px;
    left: 5px;
    width: calc((100% - 10px) / var(--wb-tabs, 5));
    border-radius: 25px;
    background: color-mix(in srgb, var(--wb-brand-1) 15%, transparent);
    transform: translateX(calc(var(--wb-tab, 0) * 100%));
    transition: transform .5s cubic-bezier(.3, 1.25, .45, 1);
  }

  .wb-tabbar__item {
    position: relative;
    z-index: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 3px;
    min-width: 0;
    min-height: 52px;
    padding: 6px 2px 5px;
    border: 0;
    border-radius: 25px;
    background: none;
    font: inherit;
    font-size: .66rem;
    font-weight: 600;
    letter-spacing: .005em;
    line-height: 1.1;
    color: var(--wb-muted);
    text-decoration: none;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
    touch-action: manipulation;
    user-select: none;
    -webkit-user-select: none;
    transition: color .25s var(--wb-ease), transform .18s var(--wb-ease);
  }
  .wb-tabbar__item svg {
    width: 23px;
    height: 23px;
    transition: transform .45s cubic-bezier(.3, 1.5, .45, 1);
  }
  .wb-tabbar__item > span {
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .wb-tabbar__item.is-on { color: var(--wb-accent); }
  .wb-tabbar__item.is-on svg { transform: translateY(-1px) scale(1.08); }
  /* A press is felt before anything else happens. */
  .wb-tabbar__item:active { transform: scale(.92); }

  /* Something under "Więcej" is waiting (an unpaid invoice). */
  .wb-tabbar__dot {
    position: absolute;
    top: 8px;
    left: calc(50% + 7px);
    width: 9px;
    height: 9px;
    border-radius: 50%;
    background: var(--wb-warn);
    box-shadow: 0 0 0 2px var(--wb-surface-solid);
  }

  /* While the sheet is up the bar steps back; while typing it leaves, so the
     keyboard does not push it up over the field being typed into. */
  body.wb-nav-open .wb-tabbar { transform: translateY(8px) scale(.97); opacity: .0; pointer-events: none; }
  body.wb-typing .wb-tabbar { transform: translateY(160%); }

  /* ---- the sheet ("Więcej") --------------------------------------------- */
  .wb-rail__sheet-head {
    position: sticky;
    top: 0;
    z-index: 2;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    min-height: 44px;
    margin: 0 -14px -12px;
    padding: 6px 14px 8px;
    background: linear-gradient(var(--wb-surface-solid) 72%, transparent);
    /* The whole strip is the handle: a finger does not have to find the line. */
    touch-action: none;
    cursor: grab;
    user-select: none;
    -webkit-user-select: none;
  }
  .wb-rail.is-dragging .wb-rail__sheet-head { cursor: grabbing; }
  .wb-rail__grabber {
    width: 40px;
    height: 5px;
    border-radius: 3px;
    background: var(--wb-border-strong);
    transition: width .2s var(--wb-ease), background .2s var(--wb-ease);
  }
  .wb-rail.is-dragging .wb-rail__grabber { width: 52px; background: var(--wb-muted); }
  .wb-rail__sheet-close {
    position: absolute;
    top: 8px;
    right: 12px;
    display: grid;
    place-items: center;
    width: 30px;
    height: 30px;
    border: 0;
    border-radius: 50%;
    background: var(--wb-surface-sunk);
    color: var(--wb-muted);
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
  }
  .wb-rail.is-dragging { transition: none !important; }

  /* In the sheet the rows are grouped lists, as in a settings screen: one
     rounded block per group, hairlines between rows, a finger-sized row. */
  .wb-rail .wb-rail__group {
    gap: 0;
    padding: 4px;
    border-radius: 18px;
    background: var(--wb-surface-sunk);
  }
  .wb-rail .wb-rail__group .wb-rail__title { margin: 0; padding: 10px 12px 6px; }
  .wb-rail .wb-nav { min-height: 50px; padding: 8px 10px; border-radius: 14px; font-size: .95rem; }
  .wb-rail .wb-nav:active { transform: scale(.985); background: var(--wb-surface-solid); }
  .wb-rail .wb-nav__ico { background: var(--wb-surface-solid); }
  .wb-rail .wb-nav--on .wb-nav__ico { background: color-mix(in srgb, currentColor 20%, transparent); }
  .wb-rail .wb-rail__subnav { padding-left: 6px; }
  .wb-rail .wb-rail__utils { gap: 0; padding: 4px; border-radius: 18px; background: var(--wb-surface-sunk); }
  /* What the sheet would say twice: everything that is a tab of the bar
     (Pulpit, Narzędzia, and the rows marked .wb-nav--tabbed — Strony, Finanse),
     the account, which is the card at the top, and signing out, which ends the
     last list. */
  .wb-rail > .wb-rail__group:first-of-type,
  .wb-rail > .wb-rail__group--tools,
  .wb-rail .wb-nav--tabbed,
  .wb-rail .wb-rail__utils-me,
  .wb-rail > .wb-nav--logout { display: none; }
  /* Signing out comes last, and looks like what it is. */
  .wb-rail__utils a[href$="logout.php"] { order: 9; color: var(--wb-bad); }
  .wb-rail__utils a[href$="logout.php"] .wb-nav__ico { color: inherit; }
  /* The admin pages have no tab: in the sheet they are always listed in full. */
  .wb-rail .wb-rail__group--admin .wb-rail__subnav { display: flex; }
  .wb-rail .wb-me { margin-top: 2px; }

  /* ---- things that used to sit at the bottom edge ----------------------- */
  .wb-toast { bottom: calc(var(--wb-tabbar-space) + 6px) !important; }
  .fin-savebar { bottom: calc(var(--wb-tabbar-space) - 4px) !important; }
  /* The support chat's launcher (Chatwoot) floats above the bar, not on it. */
  .woot-widget-bubble,
  .woot--bubble-holder { bottom: calc(var(--wb-tabbar-space) + 2px) !important; }
  body.wb-nav-open .woot-widget-bubble,
  body.wb-typing .woot-widget-bubble { opacity: 0; pointer-events: none; }

  /* ---- lighter glass ----------------------------------------------------
     Frosted cards mean the phone blurs the wallpaper again for every card on
     every scrolled frame. On a phone the cards are nearly opaque instead, and
     only the two bars (top and bottom) keep the blur — which is where it
     shows. Scrolling stays smooth on mid-range phones. */
  :root { --wb-surface: rgba(255, 255, 255, 0.9); --wb-surface-2: rgba(255, 255, 255, 0.7); }
  :root[data-theme="dark"] { --wb-surface: rgba(26, 26, 31, 0.92); --wb-surface-2: rgba(40, 40, 47, 0.72); }
  :root[data-wp="websbutler"] { --wb-surface: rgba(255, 253, 248, 0.96); --wb-surface-2: #f8f7f3; }
  :root[data-theme="dark"][data-wp="websbutler"] { --wb-surface: rgba(18, 18, 20, 0.96); --wb-surface-2: #202023; }
  .wb-main *, #wb-preview * { -webkit-backdrop-filter: none !important; backdrop-filter: none !important; }
}

/* In the installed app there is no browser chrome under the bar: a little
   more air above the home indicator looks deliberate rather than squeezed. */
@media (max-width: 900px) and (display-mode: standalone) {
  .wb-tabbar { bottom: max(14px, var(--wb-safe-b)); }
}

/* ==========================================================================
   Readability
   --------------------------------------------------------------------------
   Explanations were set in small grey type, and people skip small grey type.
   What explains (a page's lead, a card's description, a field's label) is now
   full-size and in the softer text colour, not the muted one; the muted
   colour stays for metadata (dates, counters) where skimming past is fine.
   ========================================================================== */
.wb-small { font-size: .875rem; }

.wb-page-head p {
  max-width: 68ch;
  color: var(--wb-text-soft);
  font-size: 1.0625rem;
  line-height: 1.55;
}

/* A paragraph is reading matter even when it is marked small or muted. */
p.wb-muted, p .wb-muted:only-child { color: var(--wb-text-soft); }
p.wb-small { font-size: .925rem; line-height: 1.6; }

/* Field labels: sentence case, not shouted in tiny capitals. */
.wb-label {
  font-size: .875rem;
  font-weight: 600;
  letter-spacing: 0;
  text-transform: none;
  color: var(--wb-text-soft);
}

.wb-pop__panel p,
.wb-promo p { font-size: .875rem; color: var(--wb-text-soft); }

/* ==========================================================================
   Search (Ctrl+K) — initSearch() in wb.js, the list from api/search.php
   ========================================================================== */
.wb-search-btn {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  margin: 10px 0 6px;
  padding: 6px 8px 6px 6px;
  border: 1px solid var(--wb-border);
  border-radius: var(--wb-r-sm);
  background: var(--wb-surface-solid);
  color: var(--wb-muted);
  font: inherit;
  font-size: .9rem;
  text-align: left;
  cursor: pointer;
  transition: border-color .18s var(--wb-ease), box-shadow .18s var(--wb-ease), color .18s var(--wb-ease);
}
.wb-search-btn .wb-nav__ico { background: none; }
.wb-search-btn:hover {
  color: var(--wb-text);
  border-color: color-mix(in srgb, var(--wb-accent) 45%, var(--wb-border));
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--wb-accent) 14%, transparent);
}
.wb-search-btn:hover .wb-nav__ico { color: var(--wb-accent); }
.wb-search-btn:active { transform: scale(.98); }
.wb-search-btn__txt { flex: 1; min-width: 0; }
.wb-search-btn__kbd,
.wb-find kbd {
  padding: 2px 6px;
  border: 1px solid var(--wb-border);
  border-bottom-width: 2px;
  border-radius: 6px;
  background: var(--wb-surface-sunk);
  color: var(--wb-muted);
  font: 600 .72rem/1.3 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  white-space: nowrap;
}
:root[data-rail="collapsed"] .wb-search-btn { justify-content: center; padding: 6px 0; border-color: transparent; background: none; }
:root[data-rail="collapsed"] .wb-search-btn__txt,
:root[data-rail="collapsed"] .wb-search-btn__kbd { display: none; }

/* Phones: the rail is a sheet, so the search sits in the top bar. */
.wb-bar__search { display: none; }
@media (max-width: 900px) {
  .wb-bar__search { display: inline-grid; }
  .wb-rail .wb-search-btn { display: none; }
}

/* The installed-app offer: only while the browser can install the panel. */
.wb-nav--install { display: none; width: 100%; border: 0; background: none; font: inherit; font-size: .9rem; text-align: left; cursor: pointer; }
:root.wb-can-install .wb-nav--install { display: flex; margin-top: auto; }
:root.wb-can-install .wb-nav--logout { margin-top: 0; }
@media (display-mode: standalone) { :root.wb-can-install .wb-nav--install { display: none; } }

/* ---- the search window ------------------------------------------------------ */
.wb-find { position: fixed; inset: 0; z-index: 200; display: grid; grid-template-columns: minmax(0, 1fr); justify-items: center; align-items: start; padding: 11vh 16px 16px; }
.wb-find[hidden] { display: none; }
.wb-find__scrim {
  position: absolute;
  inset: 0;
  background: color-mix(in srgb, var(--wb-scrim) 55%, rgba(10, 10, 14, .38));
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  opacity: 0;
  transition: opacity .18s var(--wb-ease);
}
.wb-find__box {
  position: relative;
  display: flex;
  flex-direction: column;
  width: min(660px, 100%);
  max-height: min(640px, 80vh);
  border: 1px solid var(--wb-border);
  border-radius: var(--wb-r-lg);
  background: var(--wb-surface-solid);
  box-shadow: var(--wb-shadow-lg);
  overflow: hidden;
  opacity: 0;
  transform: translateY(-8px) scale(.97);
  transition: opacity .18s var(--wb-ease), transform .22s var(--wb-ease);
}
.wb-find.is-open .wb-find__scrim { opacity: 1; }
.wb-find.is-open .wb-find__box { opacity: 1; transform: none; }

.wb-find__field { display: flex; align-items: center; gap: 12px; padding: 14px 14px 14px 18px; border-bottom: 1px solid var(--wb-border); color: var(--wb-muted); }
.wb-find__input {
  flex: 1;
  min-width: 0;
  padding: 6px 0;
  border: 0;
  outline: none;
  background: none;
  color: var(--wb-text);
  font: inherit;
  font-size: 1.12rem;
}
.wb-find__input::placeholder { color: var(--wb-muted); }
.wb-find__input::-webkit-search-cancel-button { display: none; }
.wb-find__esc {
  padding: 6px 12px;
  border: 1px solid var(--wb-border);
  border-radius: var(--wb-r-pill);
  background: var(--wb-surface-sunk);
  color: var(--wb-text-soft);
  font: inherit;
  font-size: .8rem;
  font-weight: 600;
  cursor: pointer;
}
.wb-find__esc:hover { color: var(--wb-text); }

.wb-find__list { overflow-y: auto; padding: 8px; overscroll-behavior: contain; }
.wb-find__group { margin: 10px 10px 6px; font-size: .72rem; font-weight: 700; letter-spacing: .07em; text-transform: uppercase; color: var(--wb-muted); }
.wb-find__group:first-child { margin-top: 4px; }
.wb-find__item {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 9px 10px;
  border-radius: var(--wb-r-sm);
  color: var(--wb-text);
  text-decoration: none;
  scroll-margin: 8px;
}
.wb-find__item.is-on { background: color-mix(in srgb, var(--wb-accent) 10%, var(--wb-surface-solid)); }
.wb-find__ico {
  display: grid;
  place-items: center;
  flex-shrink: 0;
  width: 36px;
  height: 36px;
  border-radius: 10px;
  background: var(--wb-surface-sunk);
  color: var(--wb-text-soft);
}
.wb-find__item.is-on .wb-find__ico { background: var(--wb-accent); color: var(--wb-accent-contrast); }
.wb-find__txt { display: grid; gap: 1px; flex: 1; min-width: 0; }
.wb-find__txt strong { font-size: .95rem; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.wb-find__txt span { font-size: .82rem; color: var(--wb-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.wb-find__go { flex-shrink: 0; color: var(--wb-accent); font-size: .95rem; opacity: 0; transform: translateX(-3px); transition: opacity .12s var(--wb-ease), transform .12s var(--wb-ease); }
.wb-find__item.is-on .wb-find__go { opacity: 1; transform: none; }

.wb-find__note { margin: 18px 12px; color: var(--wb-muted); }
.wb-find__none { display: grid; justify-items: start; gap: 8px; padding: 18px 14px 20px; }
.wb-find__none strong { font-size: 1rem; }
.wb-find__none span { color: var(--wb-text-soft); }
.wb-find__none .wb-btn { margin-top: 4px; }

.wb-find__foot { display: flex; gap: 18px; padding: 10px 16px; border-top: 1px solid var(--wb-border); background: var(--wb-surface-sunk); font-size: .78rem; color: var(--wb-muted); }
.wb-find__foot kbd { margin-right: 3px; }

@media (max-width: 600px) {
  .wb-find { padding: 10px; }
  .wb-find__box { max-height: calc(100dvh - 20px); }
  .wb-find__foot { display: none; }
}
@media (prefers-reduced-motion: reduce) {
  .wb-find__box, .wb-find__scrim { transition: none; }
}

/* ---- "Czego potrzebujesz?" on the Pulpit: the search, as a big field ------- */
.wb-ask {
  display: flex;
  align-items: center;
  gap: 16px;
  width: 100%;
  padding: 14px 18px 14px 14px;
  border: 1px solid var(--wb-border);
  border-radius: var(--wb-r-lg);
  background: var(--wb-surface-solid);
  box-shadow: var(--wb-shadow-sm);
  color: var(--wb-text);
  font: inherit;
  text-align: left;
  cursor: text;
  transition: border-color .18s var(--wb-ease), box-shadow .2s var(--wb-ease), transform .18s var(--wb-ease);
}
.wb-ask:hover {
  border-color: color-mix(in srgb, var(--wb-accent) 45%, var(--wb-border));
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--wb-accent) 13%, transparent), var(--wb-shadow);
}
.wb-ask:active { transform: scale(.99); }
.wb-ask__ico {
  display: grid;
  place-items: center;
  flex-shrink: 0;
  width: 46px;
  height: 46px;
  border-radius: 14px;
  background: var(--wb-accent);
  color: var(--wb-accent-contrast);
}
.wb-ask__txt { display: grid; gap: 2px; flex: 1; min-width: 0; }
.wb-ask__txt strong { font-size: 1.08rem; font-weight: 650; letter-spacing: -.01em; }
.wb-ask__txt span { font-size: .92rem; color: var(--wb-text-soft); }
.wb-ask__kbd {
  padding: 3px 8px;
  border: 1px solid var(--wb-border);
  border-bottom-width: 2px;
  border-radius: 7px;
  background: var(--wb-surface-sunk);
  color: var(--wb-muted);
  font: 600 .75rem/1.3 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}
@media (max-width: 900px) { .wb-ask__kbd { display: none; } }
@media (max-width: 600px) {
  .wb-ask { padding: 12px 14px 12px 12px; gap: 12px; }
  .wb-ask__ico { width: 40px; height: 40px; border-radius: 12px; }
}

/* Stat tiles: their names in readable sentence case, not tiny capitals. */
.wb-stat__label { font-size: .875rem; font-weight: 600; letter-spacing: 0; text-transform: none; color: var(--wb-text-soft); }

/* ---- "Nowe w panelu" (Pulpit side column) --------------------------------- */
.wb-news { margin: 0; }
.wb-news[hidden] { display: none; }
.wb-news .wb-card__head { margin-bottom: 8px; }
.wb-news__x {
  display: grid;
  place-items: center;
  width: 30px;
  height: 30px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: none;
  color: var(--wb-muted);
  cursor: pointer;
}
.wb-news__x:hover { background: var(--wb-surface-sunk); color: var(--wb-text); }
.wb-news__list { display: grid; gap: 4px; }
.wb-news__item {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  width: 100%;
  padding: 9px 8px;
  border: 0;
  border-radius: var(--wb-r-sm);
  background: none;
  color: var(--wb-text);
  font: inherit;
  text-align: left;
  cursor: pointer;
  transition: background-color .15s var(--wb-ease);
}
.wb-news__item:hover { background: var(--wb-surface-sunk); }
.wb-news__item:active { transform: scale(.98); }
.wb-news__ico {
  display: grid;
  place-items: center;
  flex-shrink: 0;
  width: 34px;
  height: 34px;
  border-radius: 10px;
  background: color-mix(in srgb, var(--wb-accent) 12%, var(--wb-surface-solid));
  color: var(--wb-accent);
}
.wb-news__txt { display: grid; gap: 1px; min-width: 0; }
.wb-news__txt strong { font-size: .92rem; font-weight: 650; }
.wb-news__txt span { font-size: .84rem; line-height: 1.45; color: var(--wb-text-soft); }

/* ==========================================================================
   Przeprowadzka (assets/site-move.js): moving the client's own domain to us
   ========================================================================== */
.js-site-move[hidden] { display: none; }
.smv { display: grid; gap: 18px; }
.wb-site .js-site-move { margin-top: 18px; padding-top: 18px; border-top: 1px solid var(--wb-border); }
.smv__head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px 18px; flex-wrap: wrap; }
.smv__title { margin: 0; font-size: 1.15rem; }
.smv__sub { margin: 4px 0 0; color: var(--wb-text-soft); font-size: .95rem; }
.smv__live { display: inline-flex; align-items: center; gap: 7px; padding: 7px 13px; border: 1px solid var(--wb-border); border-radius: var(--wb-r-pill); background: var(--wb-surface-solid); color: var(--wb-text); font-size: .88rem; font-weight: 600; text-decoration: none; }
.smv__live svg { color: var(--wb-accent); }
.smv__live:hover { border-color: color-mix(in srgb, var(--wb-accent) 45%, var(--wb-border)); }

.smv__road { list-style: none; margin: 0; padding: 0; display: grid; gap: 0; }
.smv__step { position: relative; display: grid; grid-template-columns: 36px minmax(0, 1fr); gap: 14px; padding: 0 0 18px; }
.smv__step:last-child { padding-bottom: 0; }
.smv__step:not(:last-child)::before { content: ''; position: absolute; left: 17px; top: 38px; bottom: 2px; width: 2px; background: var(--wb-border); border-radius: 2px; }
.smv__step.is-done:not(:last-child)::before { background: var(--wb-ok); }
.smv__dot { display: grid; place-items: center; width: 36px; height: 36px; border-radius: 50%; border: 2px solid var(--wb-border-strong); background: var(--wb-surface-solid); color: var(--wb-muted); font-weight: 700; font-size: .95rem; }
.smv__step.is-now .smv__dot { border-color: var(--wb-accent); background: var(--wb-accent); color: var(--wb-accent-contrast); box-shadow: 0 0 0 5px color-mix(in srgb, var(--wb-accent) 18%, transparent); }
.smv__step.is-done .smv__dot { border-color: var(--wb-ok); background: var(--wb-ok); color: #fff; }
.smv__body { min-width: 0; padding-top: 6px; }
.smv__body > strong { display: block; font-size: 1.02rem; }
.smv__step.is-later .smv__body > strong { color: var(--wb-text-soft); }
.smv__line { display: block; margin-top: 2px; color: var(--wb-text-soft); font-size: .92rem; }

.smv__now { margin-top: 10px; display: grid; gap: 12px; justify-items: start; font-size: .97rem; line-height: 1.6; color: var(--wb-text); }
.smv__now p { margin: 0; }
.smv__now--build, .smv__now--done { display: flex; gap: 14px; align-items: flex-start; padding: 16px 18px; border-radius: var(--wb-r); background: color-mix(in srgb, var(--wb-accent) 7%, var(--wb-surface-solid)); border: 1px solid color-mix(in srgb, var(--wb-accent) 22%, var(--wb-border)); margin-top: 0; }
.smv__now--done { background: var(--wb-ok-bg); border-color: color-mix(in srgb, var(--wb-ok) 35%, transparent); }
.smv__now--build > div, .smv__now--done > div { display: grid; gap: 8px; justify-items: start; }
.smv__big { display: grid; place-items: center; flex-shrink: 0; width: 46px; height: 46px; border-radius: 14px; background: var(--wb-surface-solid); color: var(--wb-accent); }
.smv__now--done .smv__big { color: var(--wb-ok); }

.smv__how { margin: 0; padding-left: 22px; display: grid; gap: 10px; }
.smv__how li::marker { font-weight: 700; color: var(--wb-accent); }
.smv__ns { display: grid; gap: 8px; margin-top: 10px; }
.smv__nsrow { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 10px 12px; border: 1px solid var(--wb-border-strong); border-radius: var(--wb-r-sm); background: var(--wb-surface-solid); }
.smv__nsrow code { font-size: 1rem; font-weight: 600; overflow-wrap: anywhere; }
.smv__tip { display: flex; gap: 10px; align-items: flex-start; padding: 12px 14px; border-radius: var(--wb-r-sm); background: var(--wb-warn-bg); color: var(--wb-text); font-size: .93rem; }
.smv__tip svg { flex-shrink: 0; color: var(--wb-warn); margin-top: 2px; }
.smv__wait { display: flex; align-items: center; gap: 10px; color: var(--wb-text-soft); }
.smv__spin { width: 16px; height: 16px; flex-shrink: 0; border-radius: 50%; border: 2px solid var(--wb-border); border-top-color: var(--wb-accent); animation: wb-spin .8s linear infinite; }
.smv__btns { display: flex; gap: 10px; flex-wrap: wrap; }
.smv__boxes { display: flex; gap: 10px; align-items: flex-start; padding: 12px 14px; border-radius: var(--wb-r-sm); background: var(--wb-surface-sunk); font-size: .93rem; }
.smv__boxes svg { flex-shrink: 0; color: var(--wb-accent); margin-top: 2px; }
.smv__boxes > div { display: grid; gap: 4px; }
.smv__muted { color: var(--wb-text-soft); }
.smv__err { margin: 0; color: var(--wb-bad); font-size: .88rem; }
@media (prefers-reduced-motion: reduce) { .smv__spin { animation: none; } }
.smv__next { margin: 0 0 -6px; font-weight: 600; color: var(--wb-text-soft); font-size: .92rem; }

/* Panel admina → klient (admin/client.php): one section at a time. */
.ac-name { margin: 4px 0 12px; font-size: 1.35rem; overflow-wrap: anywhere; }
.ac-tabs { display: flex; gap: 6px; margin: 0 0 18px; padding-bottom: 4px; overflow-x: auto; scrollbar-width: thin; border-bottom: 1px solid var(--wb-border); }
.ac-tabs__item { display: inline-flex; align-items: center; gap: 7px; flex-shrink: 0; padding: 9px 14px; border-radius: var(--wb-r-sm) var(--wb-r-sm) 0 0; color: var(--wb-text-soft); text-decoration: none; font-weight: 500; font-size: .92rem; border-bottom: 2px solid transparent; margin-bottom: -5px; }
.ac-tabs__item:hover { color: var(--wb-text); background: var(--wb-surface-sunk); }
.ac-tabs__item.is-on { color: var(--wb-text); font-weight: 700; border-bottom-color: var(--wb-brand-1); }
.ac-tabs__item em { min-width: 20px; padding: 1px 7px; border-radius: 99px; background: var(--wb-surface-sunk); color: var(--wb-text-soft); font-style: normal; font-size: .72rem; font-weight: 700; text-align: center; }
.ac-tabs__item em.is-bad { background: var(--wb-bad); color: #fff; }
.ac-glance { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 10px; margin: 0 0 18px; }
.ac-tile { display: grid; gap: 4px; padding: 14px 16px; border: 1px solid var(--wb-border); border-radius: var(--wb-r-sm); background: var(--wb-surface-solid, var(--wb-surface)); color: inherit; text-decoration: none; min-width: 0; }
.ac-tile:hover { border-color: var(--wb-brand-1); }
.ac-tile small { font-size: .78rem; color: var(--wb-muted); }
.ac-tile strong { font-size: .95rem; overflow-wrap: anywhere; }
.ac-warn { color: var(--wb-warn); font-weight: 600; font-size: .82rem; }
.ac-bad { color: var(--wb-bad); }
.ac-row { display: flex; align-items: center; flex-wrap: wrap; gap: 10px 14px; margin-bottom: 8px; padding: 12px 15px; border: 1px solid var(--wb-border); border-radius: var(--wb-r-sm); }
.ac-row__t { display: grid; gap: 2px; flex: 1 1 200px; min-width: 0; }
.ac-row__t strong { font-size: .92rem; overflow-wrap: anywhere; }
.ac-row__t small { font-size: .8rem; color: var(--wb-muted); }
.ac-row__btns { display: flex; flex-wrap: wrap; gap: 6px; }
.ac-more { margin-top: 14px; }
.ac-more summary { cursor: pointer; font-size: .85rem; color: var(--wb-muted); margin-bottom: 10px; }
