  :root {
    /* TrafficWatchdog palette: blue #289be5 → purple #9747ff brand gradient. */
    --brand: #289be5;
    --brand-strong: #1f86c9;
    --brand-deep:   #6d28d9;
    --brand-ghost:  color-mix(in srgb, var(--brand) 8%, #fff);
    --brand-line:   color-mix(in srgb, var(--brand) 28%, #fff);
    --accent: #9747ff;
    --brand-grad: linear-gradient(135deg, #289be5, #9747ff);
    --brand-grad-90: linear-gradient(90deg, #289be5, #9747ff);
    --ink: #0c1424;
    --ink-2: #33405a;
    --muted: #64708a;
    --muted-2: #95a0b8;
    --line: #e3e8f1;
    --line-soft: #eef1f7;
    --bg: #e2e8f3;   /* light page field: a touch bluer/deeper than pure white so the aurora + dots read */
    --card: #ffffff;
    --card-soft: #fbfcfe;
    --ok: #12a150; --ok-bg: #e6f6ec;
    --err: #e5484d; --err-bg: #fdecec;
    --warn: #b45309; --warn-bg: #fff7ed; --warn-line: #fed7aa; --warn-ink: #92400e;
    --radius: 18px;
    --radius-sm: 11px;
    --shadow: 0 1px 2px rgba(16,24,40,.04), 0 14px 34px rgba(16,24,40,.07);
    --shadow-sm: 0 1px 2px rgba(16,24,40,.05), 0 4px 14px rgba(16,24,40,.04);
    --font-ui: "Figtree", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
    --serif: "Source Serif 4", Georgia, "Times New Roman", serif;
  }
  /* Dark: deep-navy surfaces, lifted text, SAME brand gradient (trafficwatchdog vibe). */
  :root[data-theme="dark"] {
    --brand-strong: #4fb2f0;
    --brand-ghost: color-mix(in srgb, var(--brand) 15%, #0e1526);
    --brand-line:  color-mix(in srgb, var(--brand) 40%, #16203a);
    --ink: #eef3fb;
    --ink-2: #c6d0e4;
    --muted: #8e9bb8;
    --muted-2: #66738f;
    --line: #253048;
    --line-soft: #1d2740;
    --bg: #0a101e;
    --card: #141b2b;
    --card-soft: #18202f;
    --ok: #3ecf7a; --ok-bg: #10331f;
    --err: #ff7076; --err-bg: #3a1518;
    --warn: #f0a95c; --warn-bg: #2b1e0e; --warn-line: #4d3413; --warn-ink: #f3c07d;
    --shadow: 0 1px 2px rgba(0,0,0,.3), 0 14px 34px rgba(0,0,0,.38);
    --shadow-sm: 0 1px 2px rgba(0,0,0,.3), 0 4px 14px rgba(0,0,0,.25);
  }
  html { color-scheme: light; }
  html[data-theme="dark"] { color-scheme: dark; }

  body {
    margin: 0;
    font-family: var(--font-ui);
    color: var(--ink);
    /* Static fallback field (animation off / has-bg absent): faint blue dot-grid + two
       soft brand/accent glows. Replaced by the live canvas while it runs (.bg-live). */
    background-color: var(--bg);
    background-image:
      radial-gradient(circle at 1px 1px, color-mix(in srgb, var(--brand) 24%, transparent) 1px, transparent 1.7px),
      radial-gradient(120% 75% at 50% -12%, color-mix(in srgb, var(--brand) 13%, transparent), transparent 60%),
      radial-gradient(90% 60% at 100% 0%, color-mix(in srgb, var(--accent) 11%, transparent), transparent 55%);
    background-size: 24px 24px, 100% 760px, 100% 540px;
    background-repeat: repeat, no-repeat, no-repeat;
    background-attachment: fixed;
    -webkit-font-smoothing: antialiased;
    text-rendering: optimizeLegibility;
  }
  /* Client-supplied background image (templates/bg-pattern.*) replaces the CSS field;
     the canvas skips itself for this case too. */
  body.has-bg {
    background-image:
      linear-gradient(color-mix(in srgb, var(--bg) 60%, transparent), color-mix(in srgb, var(--bg) 74%, transparent)),
      url("/review/assets/bg");
    background-repeat: no-repeat, no-repeat;
    background-position: center top, center top;
    background-size: cover, cover;
    background-attachment: fixed, fixed;
  }
  /* While the live canvas runs, drop the static pattern (color stays). Declared after
     body.has-bg so it also wins over the drop-in image at equal specificity. */
  body.bg-live { background-image: none; }

  #bg-canvas {
    position: fixed; inset: 0; width: 100vw; height: 100vh;
    z-index: -1; pointer-events: none; display: block;
  }
  #bg-canvas[hidden] { display: none; }

  /* Masthead icon toggles (theme / animation). */
  .icon-btn {
    appearance: none; cursor: pointer; font-family: inherit;
    width: 38px; height: 38px; flex: 0 0 auto; border-radius: 11px; padding: 0;
    display: inline-flex; align-items: center; justify-content: center;
    color: var(--ink-2); background: var(--card); border: 1px solid var(--line);
    box-shadow: var(--shadow-sm);
    transition: color .15s, border-color .15s, transform .12s ease, box-shadow .15s ease;
  }
  .icon-btn:hover { color: var(--brand-strong); border-color: var(--brand-line); transform: translateY(-1px); }
  .icon-btn:active { transform: translateY(0); }
  .icon-btn svg { width: 17px; height: 17px; }
  .icon-btn[hidden] { display: none; }
  /* Theme button: moon in light (click → dark), sun in dark. */
  .icon-btn .i-sun, :root[data-theme="dark"] .icon-btn .i-moon { display: none; }
  :root[data-theme="dark"] .icon-btn .i-sun { display: block; }
  /* Animation button: waves, slashed while off. */
  .icon-btn .i-motion-off { display: none; }
  .icon-btn[aria-pressed="false"] .i-motion-on { display: none; }
  .icon-btn[aria-pressed="false"] .i-motion-off { display: block; }
  .icon-btn[aria-pressed="false"] { color: var(--muted-2); }

  /* Primary button: brand gradient that shifts on hover + shine sweep + lift. */
  .btn {
    appearance: none; border: 1px solid transparent; border-radius: 11px;
    padding: 10px 18px; font-size: 14px; font-weight: 700; cursor: pointer;
    font-family: inherit; letter-spacing: -.01em; text-decoration: none;
    display: inline-flex; align-items: center; gap: 7px; justify-content: center;
    color: #fff; white-space: nowrap; position: relative; overflow: hidden;
    background: linear-gradient(90deg, #289be5, #9747ff, #289be5);
    background-size: 220% 100%; background-position: 0% 0;
    box-shadow: 0 1px 2px rgba(16,24,40,.08), 0 6px 16px color-mix(in srgb, var(--brand) 22%, transparent);
    transition: transform .12s ease, box-shadow .18s ease, background-position .5s ease, opacity .15s ease;
  }
  .btn::after {
    content: ""; position: absolute; top: 0; bottom: 0; left: -70%; width: 45%;
    background: linear-gradient(105deg, transparent, rgba(255,255,255,.34), transparent);
    transform: skewX(-18deg); pointer-events: none;
  }
  .btn:hover:not(:disabled) {
    transform: translateY(-1px); background-position: 92% 0;
    box-shadow: 0 10px 26px color-mix(in srgb, var(--brand) 38%, transparent);
  }
  .btn:hover:not(:disabled)::after { left: 130%; transition: left .55s ease; }
  .btn:active:not(:disabled) { transform: translateY(0) scale(.985); box-shadow: 0 3px 10px color-mix(in srgb, var(--brand) 25%, transparent); }
  .btn:disabled { opacity: .5; cursor: default; box-shadow: none; }
  .btn.secondary {
    background: var(--card); color: var(--ink-2); border-color: var(--line); box-shadow: var(--shadow-sm);
    transition: transform .12s ease, box-shadow .18s ease, border-color .18s ease, color .15s ease, background .15s ease;
  }
  .btn.secondary::after { display: none; }
  .btn.secondary:hover:not(:disabled) {
    background: color-mix(in srgb, var(--brand) 6%, var(--card));
    border-color: color-mix(in srgb, var(--brand) 45%, var(--line));
    color: var(--brand-strong); transform: translateY(-1px);
    box-shadow: 0 8px 18px color-mix(in srgb, var(--brand) 14%, transparent);
  }
  @media (prefers-reduced-motion: reduce) {
    .btn, .btn.secondary, .icon-btn { transition: none; }
    .btn::after { display: none; }
  }

  /* Language switcher (masthead): styled like a .btn.secondary pill. */
  .lang-select {
    appearance: none; -webkit-appearance: none; cursor: pointer; font-family: inherit;
    font-size: 13px; font-weight: 700; color: var(--ink-2);
    background: var(--card) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%2364708a' stroke-width='1.6' stroke-linecap='round'/%3E%3C/svg%3E") no-repeat right 10px center;
    border: 1px solid var(--line); border-radius: 11px; padding: 9px 26px 9px 12px;
    box-shadow: var(--shadow-sm); transition: border-color .15s, color .15s;
  }
  .lang-select:hover { border-color: var(--brand-line); color: var(--brand-strong); }

  /* ── Masthead brand lockup (markup: brand_lockup() in _ui_polish.html) ───────
     ONE copy for all three pages — the identical .brand/.studio-logo blocks that used to
     be duplicated in auth/review/settings.css are gone; those keep only the link
     behaviour (cursor/hover), which the auth gate's <span> doesn't want.
     To resize the whole lockup, touch the three custom props + font-size below.
     align-items:flex-end trails the byline off to the RIGHT of the stack (flush with the
     end of the wordmark, always the wider line) instead of parking it under the name;
     .brand-by opts back out with align-self:flex-start (see there). */
  .brand {
    --brand-mark: 54px;       /* the square mark's height — deliberately outgrows the text */
    --brand-by-size: 11.5px;  /* byline size */
    --brand-by-lh: 1.18;
    display: inline-flex; align-items: center; gap: 13px;
    font-weight: 800; font-size: 19.5px; letter-spacing: -.015em; color: var(--ink);
  }
  /* "Media Agent AI": Black (900) + the brand gradient as a clipped text fill. -webkit-*
     properties are the only ones every current engine honours for this; the plain
     `color: transparent` under them is the fallback if text-fill-color is ignored. */
  .brand .brand-ai {
    font-weight: 900;
    background: var(--brand-grad-90);
    -webkit-background-clip: text; background-clip: text;
    -webkit-text-fill-color: transparent; color: transparent;
  }
  /* "Studio": solid near-black, Bold — the quiet half of the two-tone wordmark.
     Dark theme swaps in the theme ink, or it would vanish into the navy background. */
  .brand span.dim { color: #090909; font-weight: 700; }
  :root[data-theme="dark"] .brand span.dim { color: var(--ink); }
  .studio-logo {
    height: var(--brand-mark); width: auto; max-width: 200px;
    object-fit: contain; display: block;
  }
  .brand-stack {
    display: inline-flex; flex-direction: column; align-items: flex-end;
    gap: 0; line-height: var(--brand-by-lh);
    /* No vertical nudge: .brand's align-items:center centres the WHOLE stack (wordmark +
       byline together) on the mark, which is what reads as "balanced" next to the larger
       mark. An earlier version pushed the stack down by half a byline to centre the
       wordmark alone — that left the block visibly bottom-heavy. */
  }
  .brand-name { white-space: nowrap; }
  /* Byline: Light (300), near-black, flush LEFT under the wordmark — align-self overrides
     the stack's flex-end, so it starts where "Media Agent" starts instead of trailing off
     the right edge. Dark theme swaps in the theme ink (same reason as span.dim). */
  .brand-by {
    align-self: flex-start;
    font-size: var(--brand-by-size); font-weight: 300; letter-spacing: .01em;
    color: #090909; white-space: nowrap;
  }
  :root[data-theme="dark"] .brand-by { color: var(--ink); }
  /* "TrafficWatchdog" → trafficwatchdog.pl. A role="link" span (see brand_lockup: no <a>
     inside the lockup's own <a>), so it has to paint its own affordance: kursor + zmiana
     koloru na markowy błękit po najechaniu. Bez podkreślenia — kreska pod bylinią rozbijała
     metrykę lockupu, więc podświetlamy SAM kolor. */
  .brand-by-link { cursor: pointer; text-decoration: none; transition: color .15s ease; }
  .brand-by-link:hover, .brand-by-link:focus-visible {
    color: var(--brand-strong); text-decoration: none;
  }

  /* Cursor-follow highlight on masthead + cards (.glow-track added by JS below). */
  .glow-track { position: relative; }
  .glow-track::after {
    content: ""; position: absolute; inset: 0; z-index: 1; pointer-events: none;
    border-radius: inherit; opacity: 0; transition: opacity .35s ease;
    background: radial-gradient(340px circle at var(--mx, 50%) var(--my, 50%),
      color-mix(in srgb, var(--brand) 8%, transparent), transparent 70%);
  }
  :root[data-theme="dark"] .glow-track::after {
    background: radial-gradient(340px circle at var(--mx, 50%) var(--my, 50%),
      color-mix(in srgb, var(--brand) 12%, transparent), transparent 70%);
  }
  .glow-track:hover::after { opacity: 1; }
  @media (prefers-reduced-motion: reduce) { .glow-track::after { display: none; } }

  /* ── Mobile (shared masthead layout for review + settings) ───────────────────
     Both pages declare .masthead-inner/.masthead-actions in their own stylesheet,
     but never these properties — so these rules win without !important. */
  @media (max-width: 680px) {
    /* Brand keeps the first row, the action pills drop to their own row below. */
    .masthead-inner { flex-wrap: wrap; gap: 10px; padding: 12px 14px; }
    .masthead-actions { flex-wrap: wrap; width: 100%; justify-content: flex-end; gap: 6px; }
    .lang-select { padding: 8px 24px 8px 10px; font-size: 12.5px; }
    /* Whole lockup steps down one size. */
    .brand { --brand-mark: 42px; --brand-by-size: 10.5px; font-size: 17px; gap: 11px; }
    .studio-logo { max-width: 160px; }
  }
  @media (max-width: 380px) {
    /* Last resort at 320–380px: hide the language label, keep the flag. */
    .lang-select { max-width: 96px; text-overflow: ellipsis; }
  }

  /* ── Site footer + cookie notice ─────────────────────────────────────────────
     Markup: templates/_site_footer.html (macros site_footer / cookie_notice).
     Width matches the 1040px masthead on both pages. Background stays transparent
     so the particle canvas keeps showing through — only a hairline separates it.

     --bottom-bar-h is the CONTRACT for pages with their own fixed bottom bar: set it
     to that bar's height and both the footer and the cookie strip step out of its way.
     settings.css declares it for .save-bar; review.html has no such bar, so it stays 0. */
  .site-footer {
    position: relative; z-index: 2; margin-top: 56px;
    border-top: 1px solid var(--line);
    padding: 30px 20px calc(22px + var(--bottom-bar-h, 0px));
    font-size: 13.5px; color: var(--muted);
  }
  .site-footer-inner {
    max-width: 1040px; margin: 0 auto;
    display: flex; flex-wrap: wrap; gap: 28px 64px; align-items: flex-start;
  }
  .foot-h {
    margin: 0 0 10px; font-size: 11.5px; font-weight: 800; letter-spacing: .07em;
    text-transform: uppercase; color: var(--muted-2);
  }
  .foot-col ul { margin: 0; padding: 0; list-style: none; display: grid; gap: 7px; }
  .foot-col a {
    color: var(--ink-2); text-decoration: none;
    border-bottom: 1px solid transparent; transition: color .18s ease, border-color .18s ease;
  }
  .foot-col a:hover { color: var(--brand); border-bottom-color: var(--brand-line); }
  /* Jedyny wpis stopki, który nie jest linkiem: przycisk otwierający formularz kontaktowy
     (templates/_contact_modal.html). Ma wyglądać dokładnie jak sąsiednie <a> — <button> nie
     dziedziczy ani fontu, ani koloru, więc oba trzeba zdjąć z niego ręcznie. Nie <a href="#">:
     to jest akcja na tej stronie, a nie adres, pod który można wejść. */
  .foot-col .foot-link-btn {
    display: inline; padding: 0; border: 0; border-bottom: 1px solid transparent;
    background: none; cursor: pointer; font: inherit; text-align: left;
    color: var(--ink-2); transition: color .18s ease, border-color .18s ease;
  }
  .foot-col .foot-link-btn:hover { color: var(--brand); border-bottom-color: var(--brand-line); }
  /* Kontakt + adres dosunięte do prawej krawędzi; Zasady zostają po lewej. Auto-margines
     zbiera całą wolną przestrzeń, więc rozjazd jest tym większy, im szersze okno — a przy
     zawinięciu (wrap) margines znika sam i kolumny wracają pod siebie. */
  .foot-contact { margin-left: auto; }
  .foot-addr { font-style: normal; line-height: 1.65; }
  .foot-company { display: block; font-weight: 700; color: var(--ink-2); }
  .site-footer-copy {
    max-width: 1040px; margin: 26px auto 0; padding-top: 16px;
    border-top: 1px solid var(--line-soft); font-size: 12.5px; color: var(--muted-2);
  }

  /* Informational strip, not a consent gate — it never blocks the page, so it is a
     plain fixed card (no overlay, no focus trap, not role=dialog). Icon column +
     content column; the brand hairline on top is the only decoration that survives
     dark mode unchanged (both themes read it as "ours", not as a warning). */
  .cookie-note {
    position: fixed; z-index: 60; left: 16px; right: 16px;
    bottom: calc(16px + var(--bottom-bar-h, 0px));
    max-width: 460px; margin: 0 auto;
    display: grid; grid-template-columns: auto 1fr; gap: 14px;
    padding: 18px 20px 17px; border: 1px solid var(--line);
    border-radius: var(--radius); overflow: hidden;
    background: color-mix(in srgb, var(--card) 94%, transparent);
    backdrop-filter: blur(14px) saturate(1.4);
    -webkit-backdrop-filter: blur(14px) saturate(1.4);
    box-shadow: var(--shadow), 0 24px 60px rgba(16, 24, 40, .14);
    color: var(--ink-2); font-size: 12.8px; line-height: 1.55;
    transform: translateY(140%); opacity: 0;
    transition: transform .34s cubic-bezier(.22, 1, .36, 1), opacity .28s ease;
  }
  .cookie-note::before {
    content: ""; position: absolute; inset: 0 0 auto; height: 3px;
    background: var(--brand-grad-90);
  }
  .cookie-note-icon {
    display: grid; place-items: center; width: 34px; height: 34px; border-radius: 50%;
    background: var(--brand-ghost); border: 1px solid var(--brand-line);
    color: var(--brand); flex: 0 0 auto;
  }
  .cookie-note-icon svg { width: 19px; height: 19px; }
  .cookie-note-title {
    margin: 0 0 3px; font-size: 13.5px; font-weight: 800;
    letter-spacing: -.01em; color: var(--ink);
  }
  .cookie-note-actions {
    display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-end;
    gap: 10px 16px; margin-top: 13px;
  }
  .cookie-note.is-in { transform: translateY(0); opacity: 1; }
  .cookie-note[hidden] { display: none; }
  /* Klasa + --cookie-note-h z cookie-notice.js: dopóki pasek wisi (position:fixed),
     stopka rezerwuje miejsce pod nim, żeby nie zasłonił kontaktu i noty copyright.
     Wysokość jest mierzona, bo pasek łamie się na 2–3 wiersze na wąskich ekranach. */
  :root.cookie-note-open .site-footer {
    padding-bottom: calc(var(--cookie-note-h, 96px) + var(--bottom-bar-h, 0px) + 38px);
  }
  .cookie-note-text { margin: 0; color: var(--muted); }
  .cookie-note-link {
    margin-right: auto;  /* link po lewej, przycisk po prawej */
    color: var(--muted); font-weight: 600; font-size: 12.3px; text-decoration: none;
    border-bottom: 1px solid var(--line); transition: color .18s ease, border-color .18s ease;
  }
  .cookie-note-link:hover { color: var(--brand); border-bottom-color: var(--brand-line); }
  .cookie-note-ok { flex: 0 0 auto; padding: 9px 22px; font-size: 12.8px; }
  @media (prefers-reduced-motion: reduce) {
    .cookie-note { transition: none; transform: none; }
  }
  @media (max-width: 680px) {
    .site-footer { padding: 24px 14px calc(18px + var(--bottom-bar-h, 0px)); }
    .site-footer-inner { gap: 22px 36px; }
    .foot-col { flex: 1 1 140px; }
    /* Poniżej 680px kolumny i tak się zawijają, więc dosuwanie kontaktu w prawo
       zostawiłoby tylko dziurę — wraca zwykły, równy układ. */
    .foot-contact { margin-left: 0; }
    .cookie-note {
      left: 10px; right: 10px; bottom: calc(10px + var(--bottom-bar-h, 0px));
      padding: 15px 16px 14px; gap: 12px;
    }
    .cookie-note-actions { margin-top: 12px; }
    .cookie-note-ok { flex: 1 1 auto; text-align: center; }
  }
