/* ============================================================================
   layout.css — the site frame shared by every page: skip link, maintenance
   strip, topbar (full-width bar + full-screen mobile menu + menu card),
   main, page top (.page-top), footer, back-to-top, support dock, cookie
   banner, and the standalone shell of the error / maintenance pages (.solo).

   Every element here sets its own colour, margin and font explicitly
   instead of leaning on base element rules.
   ========================================================================== */


/* ── Main ───────────────────────────────────────────────────────────────── */
.site-main {
  display: block;
  flex: 1 0 auto;
  min-height: 50vh;
}
.site-main:focus { outline: none; }

/* Utility for a full-bleed first section that sits under the transparent
   topbar (e.g. the home hero): pull it up and add --nav-h to its padding. */
.under-topbar { margin-top: calc(var(--nav-h) * -1); }


/* ── Page top: the band every inner page opens with ─────────────────────────
   Markup (every subpage):
     <div class="page-top under-topbar"> {Shared/PageHeader} </div>
     <section class="section horizon …"> … </section>
   A page with its own hero (game, news post) puts .page-top under-topbar on
   that hero and pads its content itself.

   The header in the band: Shared/Breadcrumb on top, then eyebrow, title,
   lead, meta chips, actions; on the right (from 1024px) an optional
   engraved watermark word (PageHeader `watermark`, components.css 8); the
   toolbar (search + sort, OS cards, figures) across the bottom.

   The deep floor slides under the transparent topbar (.under-topbar pulls
   it up, the band adds --nav-h back as top padding); the dot grid fades out
   downwards (::before); a soft violet light sits top right with a faint warm
   one beside it and another violet one low on the left (::after).
   No entrance animation (owner: subpages stay simple and responsive) — the
   header and its lights are visible from the first paint.
   z-index 2: a dropdown in the header (the sort menu of the toolbar) opens
   over the next section; only the x axis is clipped for the same reason. */
.page-top {
  position: relative;
  z-index: 2;
  isolation: isolate;
  overflow-x: clip;
  padding-top: var(--nav-h);
  background-color: var(--bg-deep);
}
.page-top::before,
.page-top::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
}
.page-top::before {
  z-index: -2;
  background-image: var(--dot-grid);
  background-size: var(--dot-grid-size);
  -webkit-mask-image: linear-gradient(to bottom, #000 20%, transparent 92%);
          mask-image: linear-gradient(to bottom, #000 20%, transparent 92%);
}
.page-top::after {
  z-index: -1;
  background:
    radial-gradient(36% 62% at 84% 6%, var(--ambient-violet), transparent 72%),
    radial-gradient(20% 34% at 66% 0%, var(--ambient-warm), transparent 70%),
    radial-gradient(30% 54% at 2% 36%, var(--ambient-violet-soft), transparent 70%);
}
/* Two columns from 1024px when the header has a watermark (Shared/
   PageHeader `watermark` → .page-header--mark, components.css): text 7fr ·
   word 5fr, the toolbar across both; below 1024px one column, no word.
   The breadcrumb opens the header (full width). */
.page-top .page-header { padding-block: clamp(2rem, 4.5vw, 3.5rem) clamp(2.75rem, 5vw, 4.5rem); }
.page-top .page-header__main { gap: var(--space-5); }
.page-top .page-header__crumbs { margin-bottom: clamp(var(--space-6), 3vw, var(--space-10)); }
.page-top .page-header__title {
  max-width: 20ch;
  font-size: clamp(2.5rem, 5.4vw, 4.25rem);
  line-height: 1.02;
  letter-spacing: -0.035em;
}
.page-top .page-header__desc { max-width: 44rem; }
.page-top .page-header__actions { margin-top: var(--space-1); }
@media (min-width: 1024px) {
  .page-top .page-header--mark .page-header__title { font-size: clamp(2.75rem, 4.4vw, 4rem); }
  .page-top .page-header__toolbar { margin-top: var(--space-10); }
}
/* Inside the band a search + sort toolbar reads as one control strip. */
.page-top .toolbar__search { flex: 1 1 22rem; max-width: 36rem; }
@media (max-width: 767px) {
  .page-top .toolbar__search { max-width: none; }
}


/* ── Standalone shell (.solo): error + maintenance pages ────────────────────
   web/solo.html.twig — pages rendered without base.html.twig. Put .solo on
   <body>. One design for every status page:
     · the floor: --bg-deep with the dot grid fading out from the middle
       and ONE soft, still violet light high in the middle (both fixed, so
       they stay put on a scrolling phone) — nothing else glows;
     · a logo bar, a centred stage, a footer line;
     · the stage (.solo__stage, an inline-size container): the engraved
       mark (Shared/PageMark — the status code, or an icon — in its
       capture frame, sized by --mark-size against the stage), then the
       content in front of it: eyebrow, h1, lead, the page's extra slot,
       the actions (Shared/Button) and the page's closing slot. It fades up
       once on load (Firefox: fade only — no transform to re-snap).
   Signature motion — the OCR scan: LoreSpeak reads subtitles through a
   capture frame, so a thin violet scan line moves through the mark's
   frame (.solo__scan > .solo__scan-line; one small layer, transform and
   opacity only, positions in container units of the frame):
     .solo__stage--error  the line sweeps down, stalls halfway with two
                          faint flickers ("nothing to read"), finishes and
                          rests — a gentle glitch, then quiet;
     .solo__stage--work   the line sweeps to and fro through the frame,
                          steady and calm ("tuning", maintenance).
   Reduced motion: no scan, no entrance — everything still. */
.solo {
  position: relative;
  isolation: isolate;
  overflow-x: clip;
  background-color: var(--bg-deep);
}
.solo::before,
.solo::after {
  content: '';
  position: fixed;
  inset: 0;
  pointer-events: none;
}
.solo::before {
  z-index: -2;
  background-image: var(--dot-grid);
  background-size: var(--dot-grid-size);
  -webkit-mask-image: radial-gradient(70% 60% at 50% 40%, #000, transparent);
          mask-image: radial-gradient(70% 60% at 50% 40%, #000, transparent);
}
.solo::after {
  z-index: -1;
  background: radial-gradient(36rem 24rem at 50% 28%, var(--ambient-violet-soft), transparent 70%);
}
.solo__bar {
  display: flex;
  justify-content: center;
  padding: var(--space-6) var(--gutter) 0;
}
.solo__brand {
  display: inline-flex;
  border-radius: var(--radius-sm);
}
.solo__brand:focus-visible { outline: 2px solid var(--focus-outline); outline-offset: 4px; }
.solo__brand img { width: auto; height: 2.25rem; }
.solo__main {
  display: flex;
  flex: 1 0 auto;
  align-items: center;
  justify-content: center;
  padding: var(--space-12) var(--gutter);
}

/* The stage */
.solo__stage {
  --mark-size: clamp(6rem, 22vw, 11rem);
  display: flex;
  flex-direction: column;
  align-items: center;
  width: 100%;
  max-width: 40rem;
  text-align: center;
  container-type: inline-size;
  animation: solo-rise 0.7s var(--ease-out) both;
}
/* A flex box, so the mark sits on no line box: the scan covers exactly
   the frame. */
.solo__mark {
  position: relative;
  display: flex;
  max-width: 100%;
  margin-bottom: var(--space-8);
  pointer-events: none;
  user-select: none;
}
.solo__eyebrow {
  display: flex;
  justify-content: center;
  margin-bottom: var(--space-4);
}
.solo__title {
  margin: 0;
  max-width: 22ch;
  color: var(--text-strong);
  font-size: clamp(1.75rem, 4.2vw, 2.5rem);
  font-weight: 600;
  line-height: 1.15;
  letter-spacing: -0.025em;
  text-wrap: balance;
}
.solo__desc {
  max-width: 46ch;
  margin: var(--space-3) 0 0;
  color: var(--text-2);
  font-size: 1.0625rem;
  line-height: 1.65;
  text-wrap: pretty;
}
.solo__actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-3);
  margin-top: var(--space-8);
}

/* The scan: the frame's box (a size container) clipping a 2.5rem band —
   a 1px violet line fading out to both sides over a faint violet haze —
   that the animations move through it. Hidden at rest. */
.solo__scan {
  position: absolute;
  inset: 0;
  overflow: hidden;
  container-type: size;
}
.solo__scan-line {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 2.5rem;
  background:
    linear-gradient(90deg, transparent, var(--accent-400) 50%, transparent) 50% 50% / 100% 1px no-repeat,
    radial-gradient(50% 50% at 50% 50%, var(--ambient-violet-soft), transparent);
  opacity: 0;
  transform: translateY(-50%);
}
@supports (height: 1cqh) {
  @media (prefers-reduced-motion: no-preference) {
    .solo__stage--error .solo__scan-line {
      animation: solo-scan-stall 7s var(--ease-in-out) 0.6s infinite;
    }
    .solo__stage--work .solo__scan-line {
      opacity: 0.6;
      transform: translateY(calc(14cqh - 50%));
      animation: solo-scan-tune 4.8s var(--ease-in-out) 0.6s infinite alternate both;
    }
  }
}
/* Error: down to just past the middle, a stall with two faint flickers,
   on to the bottom edge, gone; rests until the next pass. */
@keyframes solo-scan-stall {
  0%   { transform: translateY(-50%); opacity: 0; }
  6%   { opacity: 0.75; }
  26%  { transform: translateY(calc(52cqh - 50%)); }
  29%  { opacity: 0.75; }
  30%  { opacity: 0.2; }
  31%  { opacity: 0.75; }
  33%  { opacity: 0.3; }
  34%  { opacity: 0.75; }
  38%  { transform: translateY(calc(52cqh - 50%)); }
  56%  { transform: translateY(calc(100cqh - 50%)); opacity: 0.6; }
  62%  { opacity: 0; }
  100% { transform: translateY(calc(100cqh - 50%)); opacity: 0; }
}
/* Maintenance: to and fro between 14% and 86% of the frame. */
@keyframes solo-scan-tune {
  from { transform: translateY(calc(14cqh - 50%)); }
  to   { transform: translateY(calc(86cqh - 50%)); }
}

.solo__foot {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-1) var(--space-6);
  padding: var(--space-6) var(--gutter) var(--space-8);
  color: var(--text-2);
  font-size: var(--fs-sm);
  text-align: center;
}
.solo__foot p { margin: 0; }
.solo__foot a { color: var(--text-1); }
.solo__foot a:hover { color: var(--accent-text); }
.solo__heart {
  display: inline-flex;
  color: var(--accent-400);
  font-size: 0.8125rem;
  vertical-align: -0.05em;
}
@keyframes solo-rise {
  from { opacity: 0.001; transform: translateY(16px); }
  to   { opacity: 1; transform: none; }
}
/* Firefox: the entrance is a fade only (a transform ending re-snaps the
   text and icons by a pixel there). */
@supports (-moz-appearance: none) {
  .solo__stage { animation-name: ls-fade-in; }
}
@media (max-width: 767px) {
  .solo__main { padding-block: var(--space-8); }
  .solo__mark { margin-bottom: var(--space-6); }
  .solo__actions { align-self: stretch; }
  .solo__actions > .btn { flex: 1 1 100%; }
}
@media (prefers-reduced-motion: reduce) {
  .solo__stage { animation: none; }
  .solo__scan { display: none; }
}


/* ── Skip link ──────────────────────────────────────────────────────────── */
.skip-link {
  position: absolute;
  top: 0.75rem;
  left: 0.75rem;
  z-index: var(--z-skip);
  padding: 0.625rem 1rem;
  color: var(--on-accent);
  background-color: var(--accent-500);
  border-radius: var(--radius-md);
  font-family: var(--font-main);
  font-size: var(--fs-sm);
  font-weight: 600;
  text-decoration: none;
  transform: translateY(-200%);
}
.skip-link:focus,
.skip-link:hover { color: var(--on-accent); }
.skip-link:focus { transform: none; outline: none; box-shadow: var(--focus-ring); }


/* ── Maintenance strip (bypass IPs only) ────────────────────────────────────
   _maintenance_notice.html.twig. A warning line above the topbar, pinned:
   the strip is sticky at the top of the viewport and the topbar sticks
   right under it (.topbar top = --maint-offset, the strip's height, kept
   by main.js), so both stay on screen as one header stack while the page
   scrolls; --head-h (tokens.css) is that stack for sticky elements and
   scroll offsets.

   Folding (the strip's button, .is-collapsed): the row closes (grid row
   1fr → 0fr) and fades, the topbar's `top` glides to 0 with the same
   timing, and the strip "drops" into a "Maintenance" bubble (Shared/Chip
   as a button, live dot) floating in the bottom-right corner, just left of
   the back-to-top button (fixed, over the page, no layout space; the
   cookie card sits bottom-left). The bubble opens the strip again. Hidden while the mobile menu is
   open. Reduced motion: instant (base.css). A stored fold is applied on
   load under html.maint-instant (no transitions). */
.maint {
  position: sticky;
  top: 0;
  z-index: calc(var(--z-sticky) + 1);
  display: grid;
  grid-template-rows: 1fr;
  color: var(--text-1);
  font-family: var(--font-main);
  font-size: 0.8125rem;
  line-height: 1.25rem;   /* whole pixels: the strip's height feeds --maint-offset */
  transition: grid-template-rows var(--dur-slow) var(--ease-out);
}
.maint.is-collapsed { grid-template-rows: 0fr; }
/* The grid item: no padding or border of its own, so the 0fr row can
   close it completely. */
.maint__bar {
  min-height: 0;
  overflow: hidden;
  transition: opacity var(--dur-base) var(--ease-standard),
              visibility 0s linear 0s;
}
.maint.is-collapsed .maint__bar {
  opacity: 0;
  visibility: hidden;
  transition: opacity var(--dur-base) var(--ease-standard),
              visibility 0s linear var(--dur-slow);
}
.maint__row {
  background-color: var(--bg-deep);
  border-bottom: 1px solid var(--warning-line);
}
.maint__btn {
  display: flex;
  align-items: center;
  gap: 0.625rem;
  width: 100%;
  min-height: 2.25rem;
  margin: 0;
  padding-block: 0.375rem;
  color: inherit;
  background: none;
  border: 0;
  border-radius: 0;
  font: inherit;
  text-align: left;
  cursor: pointer;
}
.maint__btn:focus-visible { outline: none; box-shadow: inset 0 0 0 2px var(--warning-line); }
.maint__icon {
  display: inline-flex;
  flex-shrink: 0;
  color: var(--warning);
  font-size: 0.875rem;
}
.maint__body {
  display: flex;
  flex: 1;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0 0.5rem;
  min-width: 0;
}
.maint__title { color: var(--warning-text); font-weight: 600; }
.maint__text  { color: var(--text-2); }
.maint__chev {
  display: inline-flex;
  flex-shrink: 0;
  color: var(--text-2);
  font-size: 0.6875rem;
  transition: color var(--dur-fast) var(--ease-standard);
}
.maint__btn:hover .maint__chev { color: var(--text-strong); }

/* The bubble: bottom-right, in line with the back-to-top button (same
   bottom, same 2.75rem height) and just left of it, so the two never
   overlap. Whole-pixel offsets, no translate centring; enter / leave is a
   short fade with a 6px rise (Firefox: fade only). */
.maint__dock {
  position: fixed;
  right: calc(var(--space-6) + 2.75rem + var(--space-3));
  bottom: var(--space-6);
  display: flex;
  pointer-events: none;
}
@media (max-width: 767px) {
  .maint__dock { right: calc(var(--space-4) + 2.75rem + var(--space-2)); bottom: var(--space-4); }
}
.maint__bubble.chip {
  --chip-px: 1rem;   /* side padding (the live ring follows it) */
  height: 2.75rem;
  font-size: 0.8125rem;
  pointer-events: auto;
  background: linear-gradient(var(--tone-soft), var(--tone-soft)), var(--bg-deep);
  box-shadow: var(--shadow-lg);
  opacity: 0;
  visibility: hidden;
  transform: translateY(6px);
  transition: opacity var(--dur-base) var(--ease-standard),
              transform var(--dur-base) var(--ease-out),
              border-color var(--dur-fast) var(--ease-standard),
              visibility 0s linear var(--dur-base);
}
.maint.is-collapsed .maint__bubble.chip {
  opacity: 1;
  visibility: visible;
  transform: none;
  transition-delay: 140ms, 140ms, 0s, 0s;
}
@supports (-moz-appearance: none) {
  .maint__bubble.chip { transform: none; }
}
html:has(.topbar.is-open) .maint__dock { display: none; }

/* Without JS (main.js sets the exact height inline): one line's worth. */
html:has(#maintenanceNotice:not(.is-collapsed)) { --maint-offset: 2.3125rem; }

html.maint-instant .maint,
html.maint-instant .maint *,
html.maint-instant .topbar,
html.maint-instant .read-progress { transition: none !important; }


/* ── Topbar: a classic full-width bar ───────────────────────────────────────
   The <header> is the sticky strip, edge to edge and --nav-h (4rem) tall,
   so .under-topbar keeps its maths. Its content (.topbar__inner) sits in the
   standard .wrap. At the top of the page the bar is transparent over the
   hero; after 24px of scroll main.js adds .is-scrolled and the graphite
   surface fades in (240ms).

   The surface (graphite, blur, 1px --line hairline at the bottom) lives on
   .topbar::before and fades with opacity only. It must stay a
   pseudo-element: backdrop-filter, filter or transform on .topbar or
   .topbar__inner would turn them into the containing block of the fixed
   mobile menu.

   Stacking inside the header: bar surface 2, mobile overlay 1, logo and
   burger 3; on desktop the nav sits above the surface (3).

   It sticks at --maint-offset: right under the maintenance strip while
   that is open (bypass visitors only), at 0 otherwise; `top` glides when
   the strip folds or opens. */
.topbar {
  --topbar-link-h: 2.25rem;

  position: sticky;
  top: var(--maint-offset, 0px);
  z-index: var(--z-sticky);
  height: var(--nav-h);
  margin: 0;
  padding: 0;
  color: var(--text-1);
  background: none;
  border: 0;
  font-family: var(--font-main);
  line-height: 1.4;
  transition: top var(--dur-slow) var(--ease-out);
}
.topbar::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 2;
  background-color: var(--topbar-bg);
  border-bottom: 1px solid var(--line);
  -webkit-backdrop-filter: blur(12px);
          backdrop-filter: blur(12px);
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--dur-base) var(--ease-standard);
}
.topbar.is-scrolled::before { opacity: 1; }
/* Without backdrop-filter the bar is the opaque page colour. */
@supports not ((-webkit-backdrop-filter: blur(1px)) or (backdrop-filter: blur(1px))) {
  .topbar { --topbar-bg: var(--bg); }
}

.topbar__inner {
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--space-4);
  height: 100%;
}

.topbar__brand {
  position: relative;
  z-index: 3;
  display: inline-flex;
  align-items: center;
  flex-shrink: 0;
  border-radius: var(--radius-sm);
}
.topbar__brand:focus-visible { outline: 2px solid var(--focus-outline); outline-offset: 4px; }
.topbar__logo {
  display: block;
  width: auto;
  height: 2.25rem;   /* logo.png is 360×104, so it stays sharp up to ~2× */
  max-width: none;
}

.topbar__nav { position: relative; }
.topbar__links {
  position: relative;
  display: flex;
  margin: 0;
  padding: 0;
  list-style: none;
}
.topbar__links > li { margin: 0; }

.topbar__link {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  height: var(--topbar-link-h);
  margin: 0;
  padding: 0 0.875rem;
  color: var(--text-2);
  background: none;
  border: 0;
  border-radius: var(--radius-sm);
  font-family: var(--font-main);
  font-size: 0.9375rem;
  font-weight: 500;
  line-height: 1;
  white-space: nowrap;
  text-decoration: none;
  cursor: pointer;
  transition: color var(--dur-fast) var(--ease-standard);
}
.topbar__link:hover,
.topbar__link:focus,
.topbar__link[aria-expanded="true"],
.topbar__link.is-active { color: var(--text-strong); }
.topbar__link:focus-visible { outline: none; box-shadow: var(--focus-ring); }
/* Active marker. Mobile: a 6px accent dot after the label (< 1024px block).
   Desktop: a 2px accent underline on the bar's bottom edge (≥ 1024px). */
.topbar__link::after {
  content: '';
  flex-shrink: 0;
  background-color: var(--accent-400);
  opacity: 0;
  transition: opacity var(--dur-fast) var(--ease-standard),
              transform var(--dur-base) var(--ease-out);
}
.topbar__link.is-active::after { opacity: 1; transform: none; }

.topbar__chev {
  font-size: 0.625rem;
  color: var(--text-3);
  transition: transform var(--dur-base) var(--ease-out), color var(--dur-fast) var(--ease-standard);
}
.topbar__drop-toggle:hover .topbar__chev { color: var(--text-2); }
.topbar__drop-toggle[aria-expanded="true"] .topbar__chev { transform: rotate(180deg); color: var(--text-strong); }
.topbar__drop-toggle.is-active .topbar__chev { color: currentColor; }

/* Community menu rows (desktop card + mobile sub-list) */
.topbar__drop { position: relative; }
.topbar__group { display: none; }
.topbar__menu {
  margin: 0;
  padding: 0;
  list-style: none;
}
.topbar__menu > li { margin: 0; }
.topbar__menu-link {
  display: flex;
  align-items: center;
  gap: 0.875rem;
  padding: 0.625rem;
  color: var(--text-1);
  border-radius: var(--radius-md);
  font-family: var(--font-main);
  line-height: 1.3;
  text-decoration: none;
  transition: background-color var(--dur-fast) var(--ease-standard);
}
.topbar__menu-link:focus-visible { outline: none; box-shadow: inset 0 0 0 2px var(--focus-outline); }
.topbar__menu-icon {
  display: inline-grid;
  place-items: center;
  width: 2.375rem;
  height: 2.375rem;
  flex-shrink: 0;
  color: var(--text-2);
  background-color: var(--surface-2);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-md);
  box-shadow: var(--highlight-top);
  font-size: 0.9375rem;
  transition: color var(--dur-fast) var(--ease-standard),
              background-color var(--dur-fast) var(--ease-standard),
              border-color var(--dur-fast) var(--ease-standard);
}
.topbar__menu-text { display: flex; flex-direction: column; gap: 0.125rem; min-width: 0; }
.topbar__menu-title {
  color: var(--text-strong);
  font-size: 0.9375rem;
  font-weight: 600;
  transition: color var(--dur-fast) var(--ease-standard);
}
.topbar__menu-desc { color: var(--text-2); font-size: 0.8125rem; font-weight: 400; }
.topbar__menu-link.is-active .topbar__menu-icon {
  color: var(--accent-300);
  background-color: var(--accent-soft);
  border-color: var(--accent-line);
}
.topbar__menu-link.is-active .topbar__menu-title { color: var(--accent-text); }
/* A menu row (a link block): its hover light is mouse only (tokens.css). */
@media (hover: hover) and (pointer: fine) {
  .topbar__menu-link:hover { color: var(--text-1); background-color: var(--surface-hover); }
  .topbar__menu-link:hover .topbar__menu-icon {
    color: var(--accent-300);
    background-color: var(--accent-soft);
    border-color: var(--accent-line);
  }
}

/* The Pobierz button never moves in the bar: a press offset next to a
   backdrop-filtered layer makes Firefox repaint it with a visible jump. */
.topbar .btn:active { transform: none; }

/* Burger (mobile/tablet only): a round button at the bar's end. */
.topbar__burger {
  position: relative;
  z-index: 3;
  display: inline-grid;
  place-items: center;
  width: 2.5rem;
  height: 2.5rem;
  margin: 0 0 0 auto;
  padding: 0;
  color: var(--text-strong);
  background-color: var(--surface-active);
  border: 1px solid var(--line);
  border-radius: 50%;
  cursor: pointer;
  transition: background-color var(--dur-fast) var(--ease-standard),
              border-color var(--dur-fast) var(--ease-standard);
}
.topbar__burger:hover { background-color: var(--surface-4); border-color: var(--line-hover); }
.topbar__burger:focus-visible { outline: none; box-shadow: var(--focus-ring); }
.topbar__burger-box {
  position: relative;
  display: block;
  width: 1rem;
  height: 0.75rem;
}
.topbar__burger-box span {
  position: absolute;
  left: 0;
  width: 100%;
  height: 2px;
  background-color: currentColor;
  border-radius: var(--radius-full);
  /* As quick as the menu overlay (≈ 200ms); transform only — the outer
     bars slide to the middle (half the box minus half a bar: 5px) and turn. */
  transition: transform 180ms var(--ease-out),
              opacity 120ms var(--ease-standard);
}
.topbar__burger-box span:nth-child(1) { top: 0; }
.topbar__burger-box span:nth-child(2) { top: calc(50% - 1px); }
.topbar__burger-box span:nth-child(3) { top: calc(100% - 2px); }
.topbar.is-open .topbar__burger-box span:nth-child(1) { transform: translateY(calc(0.375rem - 1px)) rotate(45deg); }
.topbar.is-open .topbar__burger-box span:nth-child(2) { opacity: 0; transform: scaleX(0.2); }
.topbar.is-open .topbar__burger-box span:nth-child(3) { transform: translateY(calc(1px - 0.375rem)) rotate(-45deg); }

/* ── Topbar: mobile + tablet (< 1024px) — full-screen menu ──
   The overlay is the bar's own graphite (same colour and blur) over the
   whole viewport. While it is open the bar is a solid strip of the page
   colour with its hairline: the overlay scrolls (a long menu on a short
   phone), and its links must pass under the logo and the close button,
   not show through them. */
@media (max-width: 1023px) {
  .topbar.is-open::before {
    opacity: 1;
    background-color: var(--bg);
    -webkit-backdrop-filter: none;
            backdrop-filter: none;
  }

  .topbar__panel {
    position: fixed;
    inset: 0;
    z-index: 1;
    display: flex;
    flex-direction: column;
    padding: calc(var(--head-h) + var(--space-8)) var(--gutter) calc(var(--space-6) + env(safe-area-inset-bottom, 0px));
    overflow-y: auto;
    overscroll-behavior: contain;
    background-color: var(--topbar-bg);
    -webkit-backdrop-filter: blur(12px);
            backdrop-filter: blur(12px);
    opacity: 0;
    visibility: hidden;
    pointer-events: none;   /* a tap while it fades out reaches the page */
    /* One motion for the whole menu: the overlay fades and drops 8px into
       place. Transitions (not keyframes), so a second tap mid-way reverses
       from where it is. Close (these values): 150ms; open: below. */
    transform: translateY(-8px);
    transition: opacity 150ms var(--ease-standard),
                transform 150ms var(--ease-standard),
                visibility 0s linear 150ms;
  }
  .topbar.is-open .topbar__panel {
    opacity: 1;
    visibility: visible;
    pointer-events: auto;
    transform: none;
    transition: opacity 200ms var(--ease-out),
                transform 200ms var(--ease-out),
                visibility 0s linear 0s;
  }
  /* Firefox: fade only (a transform ending re-snaps the text and icons). */
  @supports (-moz-appearance: none) {
    .topbar__panel,
    .topbar.is-open .topbar__panel { transform: none; }
  }

  .topbar__links { flex-direction: column; }
  .topbar__link {
    width: 100%;
    height: auto;
    padding: 0.375rem 0;
    color: var(--text-strong);
    font-size: 1.75rem;
    font-weight: 600;
    line-height: 1.25;
    letter-spacing: -0.02em;
  }
  .topbar__link:hover { color: var(--accent-300); }
  .topbar__link.is-active { color: var(--accent-text); }
  .topbar__link::after {
    width: 6px;
    height: 6px;
    margin-left: 0.25rem;
    border-radius: 50%;
    transform: scale(0.4);
  }
  .topbar__link.is-active::after { transform: none; }
  .topbar__drop-toggle { display: none; }

  .topbar__group {
    display: block;
    margin: var(--space-6) 0 var(--space-2);
    padding-top: var(--space-6);
    color: var(--text-3);
    border-top: 1px solid var(--line);
    font-family: var(--font-mono);
    font-size: var(--fs-xs);
    font-weight: 500;
    line-height: 1.4;
    letter-spacing: 0.1em;
    text-transform: uppercase;
  }
  .topbar__menu { display: grid; gap: 0.25rem; }
  .topbar__menu-link { margin-inline: -0.625rem; }

  .topbar__cta {
    display: flex;
    flex-direction: column;
    gap: var(--space-5);
    margin-top: auto;
    padding-top: var(--space-10);
  }
  .topbar__cta .btn { display: flex; width: 100%; min-height: 3rem; font-size: 1rem; }
  .topbar__voice { --voiceline-h: 1.75rem; --drift-dur: 7s; }
  /* The rows have no entrance of their own: they come with the overlay
     (above). Reduced motion: base.css makes it instant. */
}

/* ── Topbar: desktop (≥ 1024px) — logo · links (right) · Pobierz ── */
@media (min-width: 1024px) {
  .topbar__logo { height: 2.75rem; }
  .topbar__burger { display: none; }
  .topbar__panel {
    position: relative;
    z-index: 3;
    display: flex;
    flex: 1 1 auto;
    align-items: center;
    justify-content: flex-end;
    gap: 1.25rem;
    min-width: 0;
  }
  .topbar__voice { display: none; }

  /* Active underline: full link width, on the bar's bottom edge (the link
     is centred in the bar, so it reaches down by half the difference). */
  .topbar__link::after {
    position: absolute;
    left: 0;
    right: 0;
    bottom: calc((var(--topbar-link-h) - var(--nav-h)) / 2);
    height: 2px;
    border-radius: 2px 2px 0 0;
    transform: scaleX(0.6);
  }

  /* Menu card under "Społeczność": centred on its link, 8px below the bar,
     with a caret pointing at the link. */
  .topbar__menu {
    position: absolute;
    top: calc(100% + (var(--nav-h) - var(--topbar-link-h)) / 2 + 0.5rem + var(--menu-nudge-y, 0px));
    left: 50%;
    width: 20.5rem;
    /* main.js (snapToPixels) sets the nudges so the card lands on whole
       pixels — Firefox otherwise re-snaps it after the open animation. */
    margin-left: calc(-10.25rem + var(--menu-nudge-x, 0px));
    padding: 0.5rem;
    background-color: var(--surface-overlay);
    border: 1px solid var(--line-strong);
    border-radius: var(--radius-xl);
    box-shadow: var(--shadow-lg), var(--highlight-top);
    opacity: 0;
    visibility: hidden;
    /* Vertical slide only: a scale() made the content near the card's edges
       (the icon tiles) drift sideways as the menu opened. */
    transform: translateY(6px);
    transition: opacity 180ms var(--ease-standard),
                transform 180ms var(--ease-out),
                visibility 0s linear 180ms;
  }
  .topbar__menu::before {
    content: '';
    position: absolute;
    top: -6px;
    left: 50%;
    width: 11px;
    height: 11px;
    margin-left: -5.5px;
    background-color: var(--surface-overlay);
    border-top: 1px solid var(--line-strong);
    border-left: 1px solid var(--line-strong);
    border-top-left-radius: 3px;
    transform: rotate(45deg);
  }
  .topbar__drop.is-open .topbar__menu {
    opacity: 1;
    visibility: visible;
    transform: none;
    transition-delay: 0s;
  }
}

/* Desktop: Pobierz is a compact pill-sized button — present, not shouting:
   smaller height and text, a softer accent fill that lights up on hover.
   (The mobile overlay keeps its full-width button.) */
@media (min-width: 1024px) {
  .topbar__download.btn {
    min-height: 2.125rem;
    padding-inline: 0.875rem;
    gap: 0.4375rem;
    font-size: 0.875rem;
    color: var(--accent-300);
    background: var(--accent-soft);
    border-color: var(--accent-line);
    box-shadow: none;
  }
  .topbar__download.btn:hover,
  .topbar__download.btn:focus-visible {
    color: var(--on-accent);
    background: var(--accent-500);
    border-color: var(--accent-500);
  }
  .topbar__download.btn svg { font-size: 0.875rem; }
}

/* Eight links and Pobierz must fit one row next to the logo (≈ 940px of
   the 976px row at 1024px; "Pomoc" took most of the slack — a ninth link
   needs a new plan): from 1024px to 1200px the link padding, the
   text and the gap before Pobierz grow linearly from their tight values
   (8px · 14px · 12px) to the full ones (14px · 15px · 20px), which they
   keep from 1200px. The row and the content both grow linearly, so if it
   fits at both ends it fits in between. */
@media (min-width: 1024px) {
  .topbar__panel { gap: clamp(0.75rem, 4.545vw - 34.55px, 1.25rem); }
  .topbar__link {
    padding-inline: clamp(0.5rem, 3.409vw - 26.91px, 0.875rem);
    font-size: clamp(0.875rem, 0.568vw + 8.18px, 0.9375rem);
  }
}

/* Scroll lock while the mobile menu or a dialog is open. Only <html>: an
   overflow on <body> would make it a scroll container and the sticky topbar
   would then stick to the body instead of the viewport. scrollbar-gutter on
   <html> keeps the layout from shifting sideways. */
html.has-scroll-lock { overflow: hidden; }


/* ── Footer ─────────────────────────────────────────────────────────────── */
.site-foot {
  position: relative;
  padding: var(--space-16) 0 var(--space-8);
  color: var(--text-2);
  background-color: var(--bg-deep);
  background-image: var(--dot-grid);
  background-size: var(--dot-grid-size);
  border-top: 1px solid var(--line);
  font-family: var(--font-main);
  font-size: 0.9375rem;
  line-height: 1.6;
}
.site-foot__top {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-10);
}
@media (min-width: 1024px) {
  .site-foot__top {
    grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
    gap: var(--space-12);
  }
}

.site-foot__brand {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-4);
  max-width: 24rem;
}
.site-foot__logo { display: inline-block; border-radius: var(--radius-sm); }
.site-foot__logo:focus-visible { outline: 2px solid var(--focus-outline); outline-offset: 4px; }
.site-foot__logo img { display: block; width: auto; height: 3rem; max-width: none; }
.site-foot__about { margin: 0; color: var(--text-2); }
.site-foot__socials { margin-top: var(--space-2); }   /* kit .socials (Shared/SocialLinks) */

.site-foot__cols {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-8) var(--space-6);
}
@media (min-width: 768px) {
  .site-foot__cols { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
/* A column heading: the kit .eyebrow.eyebrow--strong, on a line of its own. */
.site-foot__heading { display: block; margin: 0 0 var(--space-4); }
.site-foot__links {
  display: flex;
  flex-direction: column;
  gap: 0.625rem;
  margin: 0;
  padding: 0;
  list-style: none;
}
.site-foot__links li { margin: 0; }
.site-foot__links a {
  color: var(--text-2);
  text-decoration: none;
  transition: color var(--dur-fast) var(--ease-standard);
}
.site-foot__links a:hover { color: var(--text-strong); }

.site-foot__bottom {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2) var(--space-6);
  margin-top: var(--space-12);
  padding-top: var(--space-6);
  border-top: 1px solid var(--line);
  color: var(--text-2);
  font-size: var(--fs-sm);
}
.site-foot__bottom p { margin: 0; }
.site-foot__bottom a {
  color: var(--text-1);
  text-decoration: none;
  transition: color var(--dur-fast) var(--ease-standard);
}
.site-foot__bottom a:hover { color: var(--accent-text); }
.site-foot__heart {
  display: inline-flex;
  color: var(--accent-400);
  font-size: 0.8125rem;
  vertical-align: -0.05em;
}
/* Phones: Aplikacja · Projekt side by side, Społeczność under them across
   both columns, centred (CSS order — the markup keeps the desktop order);
   the copyright and authorship lines stacked and centred, ending above
   the back-to-top button (fixed bottom-right: 1rem + 2.75rem), so at the
   end of the page it never covers the authorship line. */
@media (max-width: 767px) {
  .site-foot { padding-bottom: calc(2 * var(--space-4) + 2.75rem); }
  /* every column centred: Aplikacja and Projekt each centred in its half */
  .site-foot__col { text-align: center; }
  .site-foot__col--community {
    order: 1;
    grid-column: 1 / -1;
  }
  .site-foot__bottom {
    flex-direction: column;
    justify-content: center;
    text-align: center;
  }
}


/* ── Back to top ────────────────────────────────────────────────────────────
   A kit icon button (.btn.btn--secondary.btn--icon) parked bottom-right;
   here only its place, its 44px size, the floating shadow (through
   --btn-shadow, so the focus ring adds to it) and the fade in / out
   (main.js: .is-visible after 600px of scroll). */
.to-top.btn {
  --btn-shadow: var(--shadow-md), var(--highlight-top);
  position: fixed;
  right: var(--space-6);
  bottom: var(--space-6);
  z-index: var(--z-dock);
  width: 2.75rem;
  min-height: 2.75rem;
  opacity: 0;
  visibility: hidden;
  transition: opacity var(--dur-base) var(--ease-standard),
              visibility 0s linear var(--dur-base),
              color var(--dur-fast) var(--ease-standard),
              background-color var(--dur-fast) var(--ease-standard),
              border-color var(--dur-fast) var(--ease-standard);
}
.to-top.btn.is-visible {
  opacity: 1;
  visibility: visible;
  transition-delay: 0s;
}
@media (max-width: 767px) {
  .to-top.btn { right: var(--space-4); bottom: var(--space-4); }
}


/* ── Support dock (desktop / tablet landscape right edge) ──────────────────
   Tab and panel sit side by side; closed, the dock is pushed right until only
   the tab shows, so opening is a single transform. */
.support-dock {
  --dock-tab-width: 2.75rem;

  /* Centred vertically without translateY(-50%): that put the dock on half a
     pixel, and Firefox re-snapped (jumped / blurred) it after each slide.
     top/bottom 0 + auto margins + a content height centre it on whole
     pixels; only the horizontal slide is a transform. */
  /* Kept 0.5rem off the right edge: overlay scrollbars (Firefox, Windows 11)
     would otherwise cover part of the tab. */
  --dock-gap: 0.5rem;
  position: fixed;
  top: 0;
  bottom: 0;
  right: var(--dock-gap);
  z-index: var(--z-dock);
  display: flex;
  align-items: center;
  height: fit-content;
  margin-block: auto;
  font-family: var(--font-main);
  line-height: 1.5;
  transform: translateX(calc(100% - var(--dock-tab-width)));
  transition: transform var(--dur-slow) var(--ease-out);
}
.support-dock.is-open { transform: none; }
/* Firefox: a transform slide leaves the dock on a sub-pixel position while it
   moves and re-snaps it when the transition ends — the label and icons
   jumped. There the dock slides by its `right` offset instead (whole pixels
   every frame, nothing to re-snap); the panel is 19rem wide. */
@supports (-moz-appearance: none) {
  .support-dock {
    right: calc(var(--dock-gap) - 19rem);
    transform: none;
    transition: right var(--dur-slow) var(--ease-out);
  }
  .support-dock.is-open { right: var(--dock-gap); }
}

.support-dock__tab {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.625rem;
  width: var(--dock-tab-width);
  margin: 0;
  padding: 0.875rem 0;
  color: var(--text-2);
  background-color: var(--surface-2);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-md), var(--highlight-top);
  cursor: pointer;
  transition: color var(--dur-fast) var(--ease-standard),
              border-color var(--dur-fast) var(--ease-standard);
}
.support-dock__tab:hover,
.support-dock.is-open .support-dock__tab {
  color: var(--accent-text);
  border-color: var(--accent-line);
}
.support-dock__tab:focus-visible { outline: none; box-shadow: var(--focus-ring); }
.support-dock__tab-icon { display: grid; place-items: center; font-size: 0.9375rem; }
.support-dock__tab-icon svg { display: block; }
/* Reads bottom-to-top, away from the edge. sideways-lr does that natively
   (no rotated layer — sharper text, no Firefox snapping); older engines get
   vertical-rl + rotate. The last letter's tracking is cancelled so the label
   sits centred between the icon and the bottom edge. */
.support-dock__tab-label {
  writing-mode: vertical-rl;
  transform: rotate(180deg);
  font-size: 0.6875rem;
  font-weight: 600;
  line-height: 1;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  white-space: nowrap;
  margin-inline-end: -0.08em;   /* inline axis is vertical here */
  /* Capitals sit on one side of their line box (no descenders), which put
     the label off the icon's axis: nudge it back onto the centre line. */
  position: relative;
  left: -0.09em;
}
@supports (writing-mode: sideways-lr) {
  .support-dock__tab-label { writing-mode: sideways-lr; transform: none; }
}

.support-dock__panel {
  width: 19rem;
  padding: var(--space-5);
  color: var(--text-1);
  background-color: var(--surface-1);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg), var(--highlight-top);
  /* Off screen while closed, and out of the tab order. */
  visibility: hidden;
  transition: visibility 0s linear var(--dur-slow);
}
.support-dock.is-open .support-dock__panel { visibility: visible; transition-delay: 0s; }
.support-dock__head {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  margin-bottom: var(--space-4);
}
.support-dock__title {
  margin: 0 0 var(--space-2);
  color: var(--text-strong);
  font-size: 1.0625rem;
  font-weight: 600;
  line-height: 1.35;
}
.support-dock__text {
  margin: 0 0 var(--space-5);
  color: var(--text-2);
  font-size: var(--fs-sm);
  line-height: 1.6;
}
.support-dock__foot {
  margin-top: var(--space-4);
  padding-top: var(--space-3);
  border-top: 1px solid var(--line);
}
.support-dock__link {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  color: var(--text-2);
  font-size: var(--fs-sm);
  text-decoration: none;
  transition: color var(--dur-fast) var(--ease-standard);
}
.support-dock__link svg { font-size: 0.75rem; transition: transform var(--dur-fast) var(--ease-out); }
.support-dock__link:hover { color: var(--accent-text); }
@media (hover: hover) and (pointer: fine) {   /* arrow nudge: mouse only (tokens.css) */
  .support-dock__link:hover svg { transform: translateX(2px); }
}

/* Phones and tablet portrait: no dock (owner) — the support card in the
   home contact section and the Wesprzyj / donations links carry it there.
   display: none also takes the tab out of the tab order; main.js only
   reacts to its clicks, so nothing else runs. */
@media (max-width: 1023px) {
  .support-dock { display: none; }
}


/* ── Cookie banner (bottom-left card) ───────────────────────────────────────
   _cookie_banner.html.twig: rises in once (Firefox: a fade — the rise
   ending would re-snap its text); the policy link is the kit .link, the
   close button a kit icon button. */
.cookie {
  position: fixed;
  left: var(--space-4);
  bottom: var(--space-4);
  z-index: var(--z-cookie);
  width: min(25rem, calc(100vw - 2rem));
  font-family: var(--font-main);
  animation: ls-rise-in var(--dur-slow) var(--ease-out) both;
}
@supports (-moz-appearance: none) {
  .cookie { animation-name: ls-fade-in; }
}
.cookie__card {
  position: relative;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: start;
  gap: var(--space-3);
  padding: var(--space-4) 3rem var(--space-4) var(--space-4);
  color: var(--text-1);
  background-color: var(--surface-overlay);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg), var(--highlight-top);
  font-size: var(--fs-sm);
  line-height: 1.55;
}
.cookie__text { margin: 0; color: var(--text-1); }
.cookie__actions { grid-column: 2; display: flex; gap: var(--space-2); }
.cookie__close {
  position: absolute;
  top: 0.625rem;
  right: 0.625rem;
}
/* Out of the way while the mobile menu is open (it sits above the topbar). */
html:has(.topbar.is-open) .cookie { display: none; }
@media (max-width: 767px) {
  .cookie { left: var(--space-3); right: var(--space-3); bottom: var(--space-3); width: auto; }
  .cookie__actions .btn { flex: 1; }
}


/* ── Event theme ─────────────────────────────────────────────────────────────
   Seasonal decorations switched on in the panel (EventTheme/Slot.html.twig;
   the theme's own art and motion: css/events/{theme}.css, loaded only while
   it is on). Every decoration is an .ev: it never takes the pointer, the
   visitor's switch hides them all (html.ev-off, main.js initEventTheme) and
   under reduced motion they stand still. The switch is a kit icon button
   parked bottom-left, the mirror of the back-to-top button. */
.ev {
  pointer-events: none;
  -webkit-user-select: none;
          user-select: none;
}
.ev-off .ev { display: none !important; }
@media (prefers-reduced-motion: reduce) {
  .ev,
  .ev * { animation: none !important; }
}

.ev-toggle.btn {
  --btn-shadow: var(--shadow-md), var(--highlight-top);
  position: fixed;
  left: var(--space-6);
  bottom: var(--space-6);
  z-index: var(--z-dock);
  width: 2.75rem;
  min-height: 2.75rem;
}
.ev-off .ev-toggle.btn { color: var(--text-3); }
@media (max-width: 767px) {
  .ev-toggle.btn { left: var(--space-4); bottom: var(--space-4); }
}
/* Out of the way while the mobile menu is open, like the cookie card. */
html:has(.topbar.is-open) .ev-toggle { display: none; }

/* A theme's short note, opened from a decoration (.ev-note-toggle →
   [hidden] .ev-note, main.js initEventTheme): a small overlay card with a
   two-colour stripe on top (--ev-note-stripe), a date line in
   --ev-note-accent-text, a title, a paragraph and a quote ruled in
   --ev-note-accent; × closes it. The theme places it (position / top /
   left). Markup: e.g. EventTheme/Independence_day/Hero.html.twig. It
   slides down a little as it opens; in Firefox it only fades (a moved
   layer re-snaps its text at the end — see .card--lift). */
.ev-note {
  --ev-note-accent:      var(--accent-400);
  --ev-note-accent-text: var(--accent-text);
  --ev-note-stripe:      var(--accent-500);
  position: absolute;
  width: min(22rem, 100vw - 2 * var(--gutter));
  padding: 1.5rem 1.375rem 1.25rem;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-lg);
  background: var(--surface-overlay);
  box-shadow: var(--shadow-xl);
  overflow: hidden;
  text-align: left;
  pointer-events: auto;
  -webkit-user-select: text;
          user-select: text;
  animation: ev-note-in 0.32s var(--ease-out) both;
}
.ev-note::before {
  content: '';
  position: absolute;
  top: 0;
  right: 0;
  left: 0;
  height: 6px;
  background: var(--ev-note-stripe);
}
.ev-note__close {
  position: absolute;
  top: 1rem;
  right: 0.75rem;
  display: grid;
  place-items: center;
  width: 2rem;
  height: 2rem;
  padding: 0;
  border: 0;
  border-radius: var(--radius-sm);
  background: none;
  color: var(--text-2);
  font-size: 0.875rem;
  cursor: pointer;
  transition: background-color var(--dur-base) var(--ease-standard), color var(--dur-base) var(--ease-standard);
}
.ev-note__close:hover { background: var(--surface-hover); color: var(--text-strong); }
.ev-note__close:focus-visible { outline: 2px solid var(--accent-400); outline-offset: 2px; }
.ev-note__date {
  margin: 0 0 0.375rem;
  color: var(--ev-note-accent-text);
  font-family: var(--font-mono);
  font-size: 0.75rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}
.ev-note__title {
  margin: 0 2rem 0.625rem 0;
  color: var(--text-strong);
  font-size: 1.125rem;
  font-weight: 600;
  line-height: 1.3;
}
.ev-note__text {
  margin: 0;
  color: var(--text-2);
  font-size: 0.875rem;
  line-height: 1.6;
}
.ev-note__quote {
  margin: 1.125rem 0 0;
  padding: 0.125rem 0 0.125rem 0.875rem;
  border-left: 2px solid var(--ev-note-accent);
}
.ev-note__quote p {
  margin: 0;
  color: var(--text-1);
  font-size: 0.9375rem;
  line-height: 1.5;
}
.ev-note__quote cite {
  display: block;
  margin-top: 0.375rem;
  color: var(--text-2);
  font-size: 0.8125rem;
  font-style: normal;
}
@keyframes ev-note-in {
  from { opacity: 0; transform: translateY(-0.375rem); }
  to   { opacity: 1; transform: none; }
}
@keyframes ev-note-fade {
  from { opacity: 0; }
  to   { opacity: 1; }
}
@supports (-moz-appearance: none) {
  .ev-note { animation-name: ev-note-fade; }
}
