/*
Theme Name: EPM 2027
Theme URI: https://epm2027.pl/
Update URI: false
Author: SOWA Marketing
Author URI: https://sowamarketing.com/
Description: Lightweight, Git-managed theme for European Presidents Meeting 2027.
Version: 1.4.1
Requires at least: 6.6
Requires PHP: 8.1
Text Domain: epm-2027
*/

/* Self-hosted, matching production's actual fonts exactly (verified via
   computed styles on epm2027.pl: body/UI = Inter, headings = Yantramanav
   700). Not Google Fonts at runtime - the woff2 files are bundled in this
   theme (assets/fonts/), sourced from production's own self-hosted font
   cache, so no external request is added. */
@font-face { font-family: "Inter"; font-style: normal; font-weight: 100 900; font-display: swap; src: url("assets/fonts/inter-latin.woff2") format("woff2"); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: "Inter"; font-style: normal; font-weight: 100 900; font-display: swap; src: url("assets/fonts/inter-latin-ext.woff2") format("woff2"); unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: "Yantramanav"; font-style: normal; font-weight: 700; font-display: swap; src: url("assets/fonts/yantramanav-700-latin.woff2") format("woff2"); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: "Yantramanav"; font-style: normal; font-weight: 700; font-display: swap; src: url("assets/fonts/yantramanav-700-latin-ext.woff2") format("woff2"); unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }

:root {
  --navy: #0b2242;
  --navy-deep: #0b2242;
  --blue: #0578b4;
  --teal: #5abeb4;
  --ink: rgba(40, 30, 60, .82);
  --muted: rgba(40, 30, 60, .68);
  --line: rgba(40, 30, 60, .1);
  --surface: #fff;
  --mist: #f1fbfc;
  --radius: 18px;
  --radius-lg: 22px;
  --shadow: 0 18px 50px rgba(40, 30, 60, .1);
  --glass-bg: linear-gradient(135deg, rgba(255, 255, 255, .82), rgba(255, 255, 255, .62));
  --content: 1140px;
  /* Desktop vertical rhythm pass: the shared .section padding below (was
     56px top / 20px bottom) left every section using it feeling glued to
     its neighbor - a real complaint confirmed against production's own,
     noticeably more generous top/bottom breathing room. One token instead
     of two (56/20) or a set of per-section magic numbers, since production
     doesn't treat top and bottom differently here and neither should this. */
  --section-space-lg: 96px;
  --font: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  --font-heading: Yantramanav, Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
}

*, *::before, *::after { box-sizing: border-box; }
html { scroll-behavior: smooth; scroll-padding-top: 94px; }
body { margin: 0; color: var(--ink); background: #fff; font: 400 15px/1.55 var(--font); }
body.nav-open { overflow: hidden; }
img { display: block; max-width: 100%; height: auto; }
a { color: inherit; }
button, input, textarea { font: inherit; }
.screen-reader-text { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; border: 0; }
.skip-link:focus { position: fixed; z-index: 9999; top: 8px; left: 8px; width: auto; height: auto; clip: auto; padding: 10px 14px; color: #fff; background: var(--navy); }
.wrap { width: min(calc(100% - 40px), var(--content)); margin-inline: auto; }
.section { padding: var(--section-space-lg) 0; }
.section--mist { background: linear-gradient(125deg, #eef9fc 0%, #fff 52%, #effbf8 100%); }
.eyebrow { margin: 0 0 8px; color: rgba(40, 30, 60, .55); font-size: .69rem; font-weight: 800; letter-spacing: .18em; text-transform: uppercase; }
h1, h2, h3, h4 { margin-top: 0; color: var(--navy-deep); font-family: var(--font-heading); font-weight: 700; line-height: 1.05; letter-spacing: -.04em; }
h1 { max-width: 590px; margin-bottom: 18px; font-size: clamp(2.45rem, 3.95vw, 3.35rem); }
h2 { margin-bottom: 10px; font-size: clamp(1.9rem, 3vw, 2.6rem); }
h3 { margin-bottom: 8px; font-size: clamp(1.08rem, 1.55vw, 1.3rem); }
p { margin-top: 0; }
.lead { max-width: 780px; color: var(--muted); font-size: clamp(.98rem, 1.3vw, 1.08rem); }
.section-head { max-width: 780px; margin: 0 auto 22px; text-align: center; }
.section-head p { color: var(--muted); }
.btn { display: inline-flex; min-height: 46px; align-items: center; justify-content: center; gap: 9px; padding: 0 22px; border: 0; border-radius: 14px; color: #fff; background: linear-gradient(135deg, var(--blue) 0%, var(--teal) 45%, var(--blue) 100%); background-size: 220% 220%; background-position: 0% 50%; box-shadow: 0 16px 34px rgba(40, 30, 60, .16); font-weight: 800; letter-spacing: -.01em; line-height: 1; text-decoration: none; cursor: pointer; transition: transform .2s ease, box-shadow .2s ease, background-position .5s ease, filter .2s ease; }
.btn:hover, .btn:focus-visible { transform: translateY(-2px); box-shadow: 0 22px 48px rgba(40, 30, 60, .18); background-position: 100% 50%; filter: saturate(1.06); }
.btn--secondary { color: var(--navy); background: rgba(255,255,255,.78); border: 1px solid var(--line); box-shadow: 0 12px 26px rgba(40,30,60,.08); backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px); }
.btn--wide { width: 100%; }

.site-header { position: sticky; z-index: 1000; top: 0; background: rgba(255,255,255,.70); border-bottom: 1px solid var(--line); backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px); box-shadow: 0 10px 24px rgba(40,30,60,.06); }
.site-header__inner { min-height: 72px; display: flex; align-items: center; justify-content: space-between; gap: 24px; }
.brand { display: inline-flex; align-items: center; gap: 10px; text-decoration: none; }
.brand img { width: 70px; max-height: 52px; object-fit: contain; }
.site-nav { display: flex; align-items: center; gap: clamp(18px, 2.4vw, 34px); }
.site-nav a:not(.btn) { color: var(--navy-deep); font-size: .95rem; font-weight: 750; text-decoration: none; }
.site-nav a:hover, .site-nav a:focus-visible { color: var(--blue); }
.nav-toggle { display: none; width: 46px; height: 46px; padding: 0; border: 1px solid var(--line); border-radius: 12px; color: var(--navy); background: #fff; }
.nav-toggle span { display: block; width: 22px; height: 2px; margin: 5px auto; background: currentColor; }

/* Desktop geometry parity pass: production's Hero (Elementor section
   622e2b2a, page-143-elementor-data.json) renders its artwork at a fixed,
   unscaled 640x901px (image_custom_dimension on the hero image widget,
   confirmed against post-143.css - no responsive override applies above
   the 1024px breakpoint) plus 10em/160px of bottom section padding, for a
   total Hero height around ~1050-1100px at desktop widths. Staging's
   previous 610px art cap and 700px section floor rendered a visibly
   shorter, more compressed banner than the original composition - these
   values restore the same scale (bumped modestly below production's raw
   901px since this section also carries the merged facts/about-card
   content production kept in a separate overlapping section).
   Visual parity v2: switched from a min-height "gap split evenly by
   align-items:center" to an explicit padding-bottom reserved purely for
   .facts. The gap-split version let .facts' absolute bottom:26px position
   eat into the SAME vertical band the hero art image occupies (both
   competing for the bottom of .hero), so the icon-card/about-card row
   visibly overlapped and obscured the lower half of the illustration
   instead of sitting cleanly beneath it - production's equivalent content
   (a separate, much shorter icon-row-plus-text section) only grazes the
   bottom of Hero's own 160px padding, never the image itself. Reserving
   the space explicitly via padding-bottom, with .facts positioned inside
   that reserved band only, keeps the artwork fully visible above it. */
.hero { position: relative; display: grid; align-items: start; overflow: hidden; padding-bottom: 210px; background: radial-gradient(900px 600px at 10% 10%, rgba(5,120,180,.14), transparent 60%), radial-gradient(900px 600px at 90% 10%, rgba(90,190,180,.18), transparent 58%), linear-gradient(180deg, #fff, #f6fbfb); }
.hero::before, .hero::after { content: ""; position: absolute; inset: -120px; pointer-events: none; z-index: 0; }
.hero::before { background: radial-gradient(520px 420px at 12% 18%, rgba(5,120,180,.20), transparent 62%), radial-gradient(620px 520px at 88% 12%, rgba(90,190,180,.26), transparent 60%), radial-gradient(720px 320px at 55% 92%, rgba(5,120,180,.14), transparent 70%); filter: blur(18px); opacity: .95; }
.hero::after { background: radial-gradient(320px 260px at 72% 46%, rgba(90,190,180,.18), transparent 68%), radial-gradient(340px 280px at 34% 64%, rgba(5,120,180,.14), transparent 70%), radial-gradient(260px 220px at 92% 72%, rgba(40,30,60,.06), transparent 72%); filter: blur(22px); opacity: .85; }
.hero__grid { position: relative; z-index: 1; min-height: 860px; display: grid; grid-template-columns: 1fr 1fr; align-items: center; gap: 24px; }
.hero__copy { padding: 54px 0 40px; }
.hero__copy .lead { max-width: 560px; font-size: .96rem; line-height: 1.5; }
.hero__art { align-self: stretch; display: flex; align-items: flex-end; justify-content: center; }
.hero__art img { width: min(100%, 620px); max-height: 860px; object-fit: contain; object-position: center bottom; }
.facts { position: absolute; z-index: 2; right: 0; bottom: 26px; left: 0; display: grid; grid-template-columns: 142px 142px 142px minmax(300px, 1fr); gap: 12px; }
.card { border: 1px solid var(--line); border-radius: var(--radius); background: var(--glass-bg); backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px); box-shadow: var(--shadow), inset 0 1px 0 rgba(255,255,255,.55); }
.fact { min-height: 150px; display: flex; flex-direction: column; align-items: center; justify-content: center; padding: 18px 12px; text-align: center; }
.fact__icon { display: grid; width: 38px; height: 38px; place-items: center; margin-bottom: 9px; border-radius: 50%; color: var(--navy); background: linear-gradient(135deg, rgba(5,120,180,.12), rgba(90,190,180,.12)); font-size: 1.15rem; }
.fact__icon svg { width: 19px; height: 19px; }
.fact strong { display: block; margin-top: 6px; color: var(--navy-deep); line-height: 1.35; }
.about-card { padding: 19px 24px; border-radius: var(--radius-lg); }
.about-card h3 { margin-bottom: 6px; }
.about-card p { margin-bottom: 8px; font-size: .88rem; line-height: 1.42; }
.about-card .btn { margin-top: 5px; }

.split { display: grid; grid-template-columns: .95fr 1.05fr; align-items: center; gap: 52px; }
.feature-list { display: grid; gap: 12px; margin: 25px 0 0; padding: 0; list-style: none; }
.feature-list li { position: relative; min-height: 44px; padding: 4px 0 4px 56px; display: flex; align-items: center; font-weight: 700; color: var(--navy-deep); }
.feature-list li::before { content: "\2713"; position: absolute; left: 0; top: 50%; width: 44px; height: 44px; transform: translateY(-50%); display: grid; place-items: center; border-radius: 5px; background: #f0f9ff; color: #55d27c; font-size: 1.4rem; font-weight: 900; }
/* In-flow image (matches production's Elementor image widget: a normal
   block image ahead of the card grid, not absolutely positioned behind it -
   see docs/DEPLOYMENT.md history / PR discussion for the source-of-truth
   heights below). Avoiding absolute positioning here is what stops this
   artwork from bleeding under the cards once the grid collapses to one
   column on mobile.
   The teal blob used to sit as a background-image on .focus-showcase
   itself, which spans the goat image AND the card grid below it - centered
   on that whole (much taller) box, it rendered mostly behind the cards
   instead of behind the goat. Moving it to a ::before scoped to just
   .focus-showcase__art-wrap (the same bleed technique as .venue-art, so it
   still fades instead of hard-clipping) ties the blob's position to the
   goat image's own box regardless of how tall the card grid below it is. */
.focus-showcase__art-wrap { position: relative; margin: 0 0 24px; }
.focus-showcase__art-wrap::before { content: ""; position: absolute; z-index: 0; inset: -16px -12px; background-image: url('assets/images/EPM_Poznan_www4.png'); background-position: center center; background-repeat: no-repeat; background-size: 460px auto; pointer-events: none; }
/* Visual parity v2 correction: a prior pass raised this to 780px, reasoning
   from the goat image's width/height HTML attributes (434x779) as if they
   were the rendered size. They are not - that's the source file's
   registered "medium_large" WP image size (used for the src/srcset), not
   the widget's actual display box. The Elementor image widget for this
   exact asset (id 3ffc06c0, page-143-elementor-data.json) has its OWN
   explicit width:100%/height:425px controls at desktop with object-fit:
   contain - i.e. production really does render this goat at 425px tall,
   not ~780px. The 780px value visibly oversized the statue relative to
   the text column and the 4-card grid beside/below it. Restored to
   425px, matching production exactly. */
.focus-showcase__art { position: relative; z-index: 1; display: block; width: 100%; height: 425px; object-fit: contain; border-radius: 10px; filter: drop-shadow(0 14px 16px rgba(40,30,60,.14)); }
.focus-grid { display: grid; grid-template-columns: repeat(2, 1fr); column-gap: 25px; row-gap: 10px; }
.focus-card { padding: 18px; border-radius: var(--radius-lg); }

/* Composition redesign v3: v2 fixed "beside" but overcorrected into
   "small and centered behind" - the castle read as buried, not as a
   large background architectural element. v3 keeps the "genuinely
   behind the foreground row" structure from v2, but changes the scale
   and placement: the castle is now sized and positioned so its upper
   architectural mass (roughly 60% of its height) rises clearly above
   the foreground row's top edge, with only its lower ~40% obscured
   behind the card + map - the same "large object behind, foreground
   layered over its lower portion" logic already used for the Hero.
   It's also biased left (top:0;left:-60px below, against the centered
   880px .venue-grid) instead of centered, so the building reads as an
   anchored background element the foreground row cuts across, not a
   symmetric backdrop.
   --castle-w drives both the castle's width and (via margin-top:
   calc(var(--castle-w) * .45) on .venue-grid below) the foreground
   row's vertical offset from a single shared value, so the 60/40
   split holds continuously across viewport widths instead of being
   retuned per breakpoint: at this asset's fixed 4:3 aspect ratio,
   showing 60% of its height above the grid's top edge requires
   margin-top = 0.6 * height = 0.6 * .75 * width = 0.45 * width.
   opacity/blur are gone - v2 needed them to hide the old 340x255
   source's softness at the render size used there; the HD derivative
   (see the comment on .venue-art below) stays crisp at this larger
   size, and the brief now explicitly wants a full-opacity, Hero-like
   "visually important" treatment instead of a soft receded backdrop.
   #venue's own overflow:hidden clips whatever the castle bleeds past the
   section's edges (its own left bleed past .venue-composition, and any
   vertical spillover past that box below) so it can never cause a
   horizontal scrollbar or bleed into the next section. */
#venue { position: relative; overflow: hidden; }
/* Shared positioning context for the castle layer and the foreground
   grid. padding-top is a small top buffer only (not a min-height, unlike
   v2) - the composition's own flow height (margin-top on .venue-grid,
   ~0.45 * castle width, plus the grid's own ~400px+ content height)
   already exceeds the castle's height at every supported width, so
   nothing needs to be reserved or centered here.
   (Tablet/mobile fully replace this with a static, single-column flow -
   see the max-width overrides below.) */
.venue-composition { position: relative; padding-top: 16px; --castle-w: clamp(820px, 58vw, 1150px); }
/* A normal two-card row - no column or lane reserved for the castle.
   margin-top pushes the row down so only the castle's lower ~40% sits
   behind it - see the --castle-w/margin-top derivation in the redesign
   comment above. Capped narrower than the full wrap (880px, not 1140px)
   and centered via margin-inline so the left-biased castle behind it
   (see .venue-art) extends visibly past its left edge rather than just
   filling space beside it. */
.venue-grid { position: relative; z-index: 1; display: grid; grid-template-columns: 1fr 1fr; gap: 24px; width: min(100%, 880px); margin-inline: auto; margin-top: calc(var(--castle-w) * .45); }
/* The large decorative castle layer, a background element behind the
   card row, left-biased and sized so its top/upper-middle mass clearly
   rises above the row (see the redesign comment above for the 60/40
   math).
   epm-zamek-cesarski-hd-v2.webp (1400x1050, transparent, webp q95) is a
   resized-for-web derivative of a real higher-resolution master render of
   the castle, epm-zamek-cesarski-master.png (1448x1086, kept alongside it
   in this directory as the source for any future derivative) - supplied
   directly for this section, replacing both the theme's original 340x255
   source and the synthetic 4x-upscaled derivative built from it in the
   previous pass (no genuinely higher-resolution original existed anywhere
   in this project's history before this master was provided - confirmed
   via a full git-history search across every branch/commit, and the
   production reference export, which never had an image widget in Venue
   at all). The derivative is a straight resize with the alpha channel
   premultiplied before resampling and unpremultiplied after, which avoids
   the dark/light fringing a naive resize of straight-alpha RGBA produces
   at the transparent edge. --castle-w's max (1150px) stays comfortably
   under the derivative's own 1400px native width, so it is only ever
   downscaled, never upscaled further, at any supported viewport.
   "-v2" is a new filename, not just a re-save under the old name: a
   follow-up report that live staging still looked pixelated after this
   asset first shipped turned out to trace to $img() (see front-page.php)
   never having versioned its URLs the way style.css/site.js/the favicon
   links already do via epm_2027_asset_version() - so an unchanged filename
   could keep serving Cloudflare-cached or browser-cached OLD bytes
   indefinitely regardless of what the deployed file actually contained.
   $img() is fixed now, but this asset also gets a genuinely new filename
   so there is no possible cached entry anywhere still keyed to it. The
   webp quality was also bumped from q83 to q95 at the same time, since
   q83 was visibly softening this illustration's fine facade detail more
   than intended for a hero-scale decorative image.
   Decorative-only: the castle is already identified by the section
   heading, the venue card's own heading/address, and the map, so the
   image below carries alt="" and the wrapping element is aria-hidden in
   the markup, rather than duplicating that information for assistive
   tech via a large image with no functional purpose of its own. */
.venue-art { position: absolute; z-index: 0; top: 0; left: -60px; width: var(--castle-w); pointer-events: none; }
/* Same teal-blob-glow technique already used for .hero/#contact/
   .site-footer/.focus-showcase__art-wrap, re-centered/resized to match
   the castle's new left-biased position and larger size - background-size
   scaled up from v2's 840px (matching v2's 760px max castle) by the same
   ratio against v3's 1150px max castle, and inset widened so the glow
   still extends past the illustration at every corner rather than being
   cropped by it. Kept at full opacity (unlike the castle image itself) -
   it's already a soft gradient PNG with no resolution ceiling of its own
   to hide. */
.venue-art::before { content: ""; position: absolute; z-index: 0; inset: -100px -90px; background-image: url('assets/images/EPM_Poznan_www4.png'); background-position: center center; background-repeat: no-repeat; background-size: 1270px auto; pointer-events: none; }
.venue-art img { position: relative; z-index: 1; display: block; width: 100%; height: auto; object-fit: contain; filter: drop-shadow(0 24px 40px rgba(40, 30, 60, .16)); }
.venue-card { padding: 26px; border-radius: var(--radius-lg); }
.venue-card .feature-list { margin-bottom: 26px; }
.map { min-height: 330px; overflow: hidden; border-radius: var(--radius-lg); }
.map iframe { width: 100%; height: 100%; min-height: 330px; border: 0; }
/* Visual parity v2 added a desktop-only +32px/+44px top/bottom top-up here
   (88px/64px) because NH Poznan's own body copy is shorter than the
   original production content this section was adapted from, so it read as
   more compressed than its neighbors under the old 56/20px shared .section
   padding. The vertical-rhythm pass below raised that SHARED base to a
   symmetric 96px, which already exceeds this section's old 88/64 top-up on
   both sides - so the extra rule is now redundant (and would actively
   shrink bottom padding back down to 64px, since an id selector still wins
   regardless of media query) and was removed rather than left as dead
   weight. .accommodation-art's own already-approved blob composition is
   untouched below. */
.accommodation-art { min-height: 430px; display: grid; place-items: center; background-image: url('assets/images/EPM_Poznan_www4.png'); background-position: center center; background-repeat: no-repeat; background-size: 500px auto; }
.accommodation-art img { width: 100%; max-height: 430px; object-fit: contain; object-position: center bottom; filter: drop-shadow(0 18px 30px rgba(40,30,60,.14)); }

.poznan-intro { display: grid; grid-template-columns: 220px 1fr; align-items: center; gap: 78px; margin-bottom: 30px; }
/* Same ::before bleed technique as .venue-art (see the comment above it) -
   the Bamberka sculpture previously sat on the section's own pale
   background with no distinct shape behind it. gap widened from 40px to
   78px (visual parity v2 follow-up): the desktop bleed below was later
   widened to -70px to stop the blob being hard-clipped, which the old
   40px gap couldn't clear - visual-qa's "blob does not overlap the text
   column" assertion caught the resulting overlap once staging's cache
   had actually caught up to the new CSS. 78px leaves 8px of clearance
   past the 70px bleed without shifting the blob off-center (a
   symmetric inset keeps it centered on the art column either way). */
/* Desktop geometry parity pass: Bamberka's own width/height attributes
   (426x903, matching production's rendered "medium_large" size for this
   exact EPM_Poznan_www1.png asset) are a tall, narrow statue - at this
   220px column width that's ~466px tall unclipped, but a 280px max-height
   was cropping/shrinking it well below that. Raised (with a matching
   min-height) to let the statue render near its real proportions instead
   of compressed. Tablet/mobile keep their own shorter overrides below,
   unaffected by this desktop value.
   Visual parity v2: the blob's own background-size (500px) was wider
   than the box it renders in even after the -16px/-12px bleed (220px
   column + 24px bleed = 244px), and a background-image is always clipped
   to its element's box - so the outer ~130px on each side of the blob
   (its soft fade-to-transparent edge) was never painted at all, reading
   as a hard-edged, cropped shape instead of an organic one. Widened the
   bleed to fit the full blob within the box instead of shrinking the
   blob to fit the old bleed. */
.poznan-art { position: relative; min-height: 470px; display: grid; place-items: center; }
.poznan-art::before { content: ""; position: absolute; z-index: 0; inset: -40px -70px; background-image: url('assets/images/EPM_Poznan_www4.png'); background-position: center center; background-repeat: no-repeat; background-size: 340px auto; pointer-events: none; }
.poznan-art img { position: relative; z-index: 1; width: 100%; max-height: 470px; object-fit: contain; object-position: center bottom; filter: drop-shadow(0 18px 30px rgba(40,30,60,.14)); }
.city-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px; }
.city-card { overflow: hidden; border-radius: var(--radius-lg); }
.city-card__icon { display: grid; min-height: 152px; place-items: center; background: linear-gradient(125deg, #eef9fc 0%, #fff 52%, #effbf8 100%); }
.city-card__icon img { width: 84px; height: 84px; }
.city-card__body { padding: 20px; }
.city-card__body p { margin-bottom: 0; color: var(--muted); }
.practical { margin-top: 14px; padding: 22px 26px; border-radius: var(--radius-lg); }
.practical__actions { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 22px; }

.included-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 18px; align-items: stretch; }
.included-card { padding: 20px 18px; min-height: 240px; display: flex; flex-direction: column; }
.included-card p { margin-bottom: 0; color: var(--muted); }
.included-card__icon { display: grid; width: 64px; height: 64px; place-items: center; margin: 0 auto 14px; color: var(--navy); }
.included-card__icon svg { width: 64px; height: 64px; fill: none; stroke: currentColor; stroke-width: 3; stroke-linecap: round; stroke-linejoin: round; }
.included-card h3 { text-align: center; min-height: 44px; display: flex; align-items: center; justify-content: center; }
.included-card p { text-align: center; }

/* Visual parity v2: max-width alone doesn't center a block element - with
   no auto margins, the card sat flush against .wrap's left edge instead
   of centered like the rest of the section (its own header is centered
   via .section-head's margin:0 auto). */
.pricing-card { max-width: 760px; margin-inline: auto; padding: 26px; border-radius: var(--radius-lg); }
.pricing-intro { display: flex; align-items: end; justify-content: space-between; gap: 24px; padding-bottom: 20px; border-bottom: 1px solid var(--line); }
.pricing-intro p { margin: 0; color: var(--muted); }
.tiers { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; margin-top: 20px; }
.tier { padding: 14px 14px 12px; border: 1px solid var(--line); border-radius: var(--radius); background: rgba(255,255,255,.72); text-align: center; }
.tier--featured { border-color: rgba(90,190,180,.55); background: rgba(255,255,255,.85); }
.tier__label { color: var(--navy); font-weight: 900; }
.tier__date { min-height: 30px; color: var(--muted); font-size: .82rem; }
.tier__price { margin: 12px 0 16px; color: var(--navy-deep); font-size: 1.9rem; font-weight: 900; letter-spacing: -.03em; line-height: 1; }
.tier__status { min-height: 44px; display: flex; align-items: center; justify-content: center; border-radius: 12px; background: #edf1f4; color: #7b8793; font-weight: 800; }

/* EPM Sales Control: while a Flash Sale is ACTIVE, the discounted offer is
   the primary pricing decision. The Regular tier remains visible only as
   price context for what happens after the sale, so it is intentionally
   muted and has no competing checkout CTA. */
.tiers--sale-active { grid-template-columns: 1.18fr .91fr .91fr; gap: 14px; align-items: stretch; }
.tier--flash-sale { position: relative; z-index: 1; padding-top: 34px; border: 3px solid transparent; background: linear-gradient(180deg, #fff 0%, rgba(255,255,255,.94) 100%) padding-box, linear-gradient(135deg, var(--blue), var(--teal)) border-box; box-shadow: 0 18px 42px rgba(11,34,66,.14); transform: translateY(-6px); }
.tier--flash-sale .tier__badge { position: absolute; top: -14px; left: 50%; transform: translateX(-50%); padding: 6px 14px; border-radius: 999px; background: linear-gradient(135deg, var(--blue), var(--teal)); color: #fff; font-size: .72rem; font-weight: 900; letter-spacing: .045em; white-space: nowrap; box-shadow: 0 8px 20px rgba(11,34,66,.12); }
.tier--flash-sale .tier__label { font-size: 1.05rem; }
.tier--flash-sale .tier__price { margin: 14px 0 12px; font-size: 2.55rem; }
.tier--flash-sale .tier__was { min-height: 30px; color: var(--muted); font-size: .82rem; text-decoration: line-through; opacity: .78; }
.tier--flash-sale .tier__countdown { display: inline-flex; min-height: 32px; align-items: center; justify-content: center; margin: 0 auto 12px; padding: 5px 10px; border-radius: 999px; background: rgba(31,157,191,.08); color: var(--blue); font-weight: 900; font-size: .86rem; }
.tier--sale-reference,
.tier--sale-future { border-color: rgba(123,135,147,.20); background: rgba(237,241,244,.72); opacity: .58; filter: saturate(.35); }
.tier--sale-reference .tier__label,
.tier--sale-reference .tier__price,
.tier--sale-future .tier__label,
.tier--sale-future .tier__price { color: var(--muted); }
.tier--sale-reference .tier__status,
.tier--sale-future .tier__status { background: rgba(255,255,255,.55); color: var(--muted); }
.tier--flash-sale-ended { opacity: .6; }
.tier--flash-sale-ended .btn[aria-disabled="true"] { cursor: default; pointer-events: none; filter: grayscale(.25); box-shadow: none; }
.tier--flash-sale-ended .btn[aria-disabled="true"]:hover,
.tier--flash-sale-ended .btn[aria-disabled="true"]:focus-visible { transform: none; background-position: 0% 50%; filter: grayscale(.25); box-shadow: none; }

.team-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 14px; align-items: stretch; }
.person { padding: 16px; display: flex; flex-direction: column; gap: 10px; }
.person img { width: 100%; height: 220px; border-radius: 14px; object-fit: cover; border: 1px solid var(--line); }
.person__body { display: flex; flex-direction: column; gap: 2px; }
.person__role { min-height: 20px; color: rgba(11,34,66,.80); font-weight: 800; font-size: .92rem; }
.person__body p { color: var(--muted); font-size: .87rem; }
.person__body a { color: var(--navy); font-weight: 800; }

.partner-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; }
.partner { min-height: 200px; display: flex; flex-direction: column; align-items: center; justify-content: center; padding: 20px; text-align: center; }
.partner img { width: 100%; height: 60px; margin-bottom: 15px; object-fit: contain; filter: saturate(1.05); }
.partner p { margin-bottom: 0; color: var(--muted); font-size: .86rem; }

#faq { position: relative; overflow: hidden; }
#faq::before { content: ""; position: absolute; z-index: 0; top: 0; left: 50%; width: min(90%, 1024px); height: 100%; background-image: url('assets/images/EPM_Poznan_www4.png'); background-position: top center; background-repeat: no-repeat; background-size: contain; opacity: .5; transform: translateX(-50%); pointer-events: none; }
#faq > .wrap { position: relative; z-index: 1; }
.faq-list { display: grid; grid-template-columns: repeat(2, 1fr); gap: 12px; max-width: 900px; margin-inline: auto; }
.faq-item { border: 1px solid var(--line); border-radius: var(--radius); background: rgba(255,255,255,.76); backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px); box-shadow: 0 14px 40px rgba(40,30,60,.08); overflow: hidden; transition: transform .18s ease, box-shadow .18s ease, border-color .18s ease; align-self: start; }
.faq-item:hover { transform: translateY(-1px); box-shadow: 0 18px 54px rgba(40,30,60,.10); }
.faq-item:has(.faq-question[aria-expanded="true"]) { border-color: rgba(90,190,180,.45); }
.faq-question { width: 100%; display: flex; align-items: center; justify-content: space-between; gap: 20px; padding: 16px 48px 16px 16px; border: 0; color: var(--navy-deep); background: transparent; text-align: left; font-weight: 900; letter-spacing: -.02em; cursor: pointer; position: relative; }
.faq-question::after { content: "+"; position: absolute; right: 16px; top: 50%; width: 26px; height: 26px; display: grid; place-items: center; transform: translateY(-50%); border-radius: 10px; color: rgba(11,34,66,.85); background: linear-gradient(135deg, rgba(5,120,180,.10), rgba(90,190,180,.10)); border: 1px solid var(--line); font-size: 1.1rem; font-weight: 900; }
.faq-question[aria-expanded="true"]::after { content: "\2013"; }
.faq-answer { padding: 0 16px 16px; color: var(--muted); font-size: .87rem; line-height: 1.55; }
.faq-answer[hidden] { display: none; }
.faq-cta { max-width: 900px; display: flex; align-items: center; justify-content: space-between; gap: 24px; margin: 24px auto 0; padding: 16px 20px; border-radius: var(--radius); background: rgba(255,255,255,.72); border: 1px solid var(--line); box-shadow: 0 14px 40px rgba(40,30,60,.08); backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px); text-align: left; }
.faq-cta p { margin: 0; }

.countdown { position: relative; overflow: hidden; padding: var(--section-space-lg) 0; color: var(--ink); background: linear-gradient(120deg, #eaf7fc, #fff 50%, #eafbf7); text-align: center; }
/* Visual parity v2: production's own value here (background_overlay_opacity
   0.1 on the equivalent "See you in Poznan" section, page-143-elementor-
   data.json) sits behind a saturated diagonal gradient background
   (a green/teal color stop), which gives a pale silhouette enough contrast
   to read even at low opacity. This section's much lighter gradient
   doesn't provide that same contrast, so the identical opacity value read
   as barely visible rather than a deliberate subtle watermark - raised
   modestly (not to a full illustration-strength opacity) to restore a
   comparable felt presence against this section's lighter background. */
.countdown__art { position: absolute; z-index: 0; top: 50%; left: 50%; width: min(65%, 620px); max-height: 75%; object-fit: contain; opacity: .18; transform: translate(-50%, -50%); pointer-events: none; }
.countdown__inner { position: relative; z-index: 1; max-width: 640px; margin-inline: auto; display: grid; grid-template-columns: 1fr; justify-items: center; gap: 14px; }
.countdown h2, .countdown .eyebrow { color: var(--navy-deep); }
.countdown h2 { margin-bottom: 8px; }
.countdown p { color: var(--muted); }
.timer { display: grid; grid-template-columns: repeat(4, minmax(92px, 1fr)); gap: 12px; }
.timer__cell { min-width: 100px; padding: 14px 18px; border: 1px solid var(--line); border-radius: var(--radius); color: var(--navy-deep); background: rgba(255,255,255,.92); box-shadow: var(--shadow); text-align: center; }
.timer__value { display: block; font-size: 2rem; font-weight: 900; line-height: 1; }
.timer__label { display: block; margin-top: 7px; color: var(--muted); font-size: .75rem; letter-spacing: .12em; text-transform: uppercase; }
.countdown__button { width: min(100%, 420px); }

.contact-grid { display: grid; grid-template-columns: 40fr 60fr; gap: 10px; }
.contact-card { padding: 48px; border-radius: 10px; box-shadow: 0 30px 60px rgba(0,0,0,.1); }
.contact-card .eyebrow { font-size: .8rem; letter-spacing: .1em; }
.contact-divider { display: block; width: 50px; height: 3px; margin: 15px 0; background: #072955; border: 0; }
.contact-icon-list { display: grid; gap: 21px; margin: 28px 0; }
.contact-icon-item { display: flex; align-items: flex-start; gap: 21px; }
.contact-icon-item__icon { display: grid; flex: none; place-items: center; width: 55px; height: 55px; border-radius: 5px; background: #556575; color: #fff; }
.contact-icon-item__icon svg { width: 22px; height: 22px; fill: currentColor; }
.contact-icon-item__label { margin: 0 0 2px; color: #556575; font-weight: 600; font-size: 1rem; }
.contact-icon-item__value { margin: 0; color: #072955; font-family: var(--font-heading); font-weight: 700; font-size: clamp(1.35rem, 2vw, 1.7rem); line-height: 1.1; letter-spacing: -.02em; }
.contact-icon-item__value a { color: inherit; }
.form-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 15px; }
.field { display: grid; gap: 7px; }
.field--full { grid-column: 1 / -1; }
.field label { color: var(--navy); font-size: .9rem; font-weight: 800; }
.field input, .field textarea { width: 100%; border: 1px solid var(--line); border-radius: 12px; padding: 13px 15px; color: var(--ink); background: rgba(255,255,255,.85); outline: none; }
.field input:focus, .field textarea:focus { border-color: var(--blue); box-shadow: 0 0 0 3px rgba(5,120,180,.12); }
.field textarea { min-height: 126px; resize: vertical; }
.hp { position: absolute !important; left: -10000px !important; }
.form-note { margin: 15px 0 0; color: var(--muted); font-size: .84rem; }
.form-alert { margin-bottom: 18px; padding: 13px 16px; border-radius: 12px; background: #e8f8ef; color: #17663a; }
.form-alert--error { background: #fff0ef; color: #912f2a; }

/* #contact and the footer both layer the same production teal-blob asset
   (EPM_Poznan_www4.png, media id 342 on production) as independent
   background decoration - confirmed via Elementor source data they are two
   separate overlays (different crop/position/opacity), not one continuous
   bled image, so each gets its own instance rather than a shared canvas. */
/* Visual parity v2: production's Contact section (Elementor section
   73c630b8, page-143-elementor-data.json) tiles this same teal-blob asset
   as a repeat-x background across the section's FULL height
   (background_overlay_repeat: repeat-x, no height limit on the overlay -
   it simply covers whatever the section's own box is). A fixed
   height:340px here only painted the pattern across the top slice of the
   section, leaving the rest bare - replaced with bottom:0 (alongside the
   existing top:-40px) so it spans edge to edge regardless of how tall the
   section's content makes it, matching production's actual coverage. */
#contact { position: relative; margin-top: 112px; padding-top: 0; padding-bottom: 112px; overflow: visible; }
#contact::before { content: ""; position: absolute; z-index: 0; top: -40px; left: 0; right: 0; bottom: 0; background-image: url('assets/images/EPM_Poznan_www4.png'); background-position: top center; background-repeat: repeat-x; background-size: 500px auto; opacity: .3; pointer-events: none; }
#contact > .wrap { position: relative; z-index: 1; }

.site-footer { position: relative; overflow: hidden; padding: 48px 0 0; color: var(--muted); background: #fff; }
.site-footer::before { content: ""; position: absolute; z-index: 0; top: 0; right: 0; width: 480px; height: 481px; background-image: url('assets/images/EPM_Poznan_www4.png'); background-position: top right; background-repeat: no-repeat; background-size: contain; opacity: .5; pointer-events: none; }
.site-footer > .wrap { position: relative; z-index: 1; }
.footer-grid { display: grid; grid-template-columns: 1.3fr 1fr 1fr; gap: 32px; padding-bottom: 32px; border-bottom: 1px solid var(--line); }
.site-footer h4 { color: #072955; letter-spacing: 0; }
.site-footer a { color: inherit; text-decoration: none; }
.site-footer a:hover { color: var(--blue); }
.footer-brand img { width: 100px; height: auto; }
.footer-brand p { margin: 16px 0 0; max-width: 320px; color: #556575; font-size: 1rem; line-height: 1.5; }
.footer-divider { display: block; width: 50px; height: 3px; margin-top: 15px; background: #072955; }
.footer-links { display: grid; gap: 9px; padding: 0; list-style: none; }
.footer-links a, .footer-links button.cookie-settings { display: inline-flex; align-items: center; gap: 7px; border: 0; padding: 0; color: #556575; background: none; font: inherit; font-size: .875rem; line-height: 1.6; cursor: pointer; }
.footer-links__arrow { width: 14px; height: 14px; flex: none; color: #55d27c; }
.footer-links a:hover, .footer-links button.cookie-settings:hover { color: #1e8fd5; }
.footer-bottom { display: flex; align-items: center; justify-content: space-between; gap: 20px; padding: 16px 0; }
.footer-copyright { color: #556575; font-size: .8125rem; }
.socials { display: flex; flex-wrap: wrap; gap: 7px; }
.socials a { width: 28px; height: 28px; display: grid; place-items: center; border-radius: 4px; color: #fff; background: rgba(85,101,117,1); transition: transform .18s ease, background .18s ease; }
.socials a:hover { transform: translateY(-1px); background: #1292ee; }
.socials svg { width: 14px; height: 14px; fill: currentColor; }

.cookie-banner { position: fixed; z-index: 2000; right: 18px; bottom: 18px; width: min(450px, calc(100% - 36px)); padding: 22px; border: 1px solid var(--line); border-radius: var(--radius-lg); background: #fff; box-shadow: 0 22px 60px rgba(40,30,60,.2); }
.cookie-banner p { margin-bottom: 16px; color: var(--muted); font-size: .9rem; }
.cookie-actions { display: flex; flex-wrap: wrap; gap: 10px; }
.cookie-banner[hidden] { display: none; }

.legal { min-height: 65vh; padding: 86px 0; }
.legal__content { max-width: 820px; }
.legal__content h2 { margin-top: 45px; font-size: 2rem; }

/* Entrance animations - mirrors the exact set used on production (Elementor
   animate.css subset: bounceInUp, fadeIn, fadeInUp, fadeInLeft, fadeInRight,
   and the "pop" hover micro-interaction already covered by .btn/.card
   hover transforms above). Triggered by adding .is-visible via IntersectionObserver
   in site.js; prefers-reduced-motion is respected by the blanket rule below. */
[data-animate] { opacity: 0; }
[data-animate].is-visible { opacity: 1; }
[data-animate="fadeIn"].is-visible { animation: epmFadeIn .7s ease both; }
[data-animate="fadeInUp"].is-visible { animation: epmFadeInUp .7s ease both; }
[data-animate="fadeInLeft"].is-visible { animation: epmFadeInLeft .7s ease both; }
[data-animate="fadeInRight"].is-visible { animation: epmFadeInRight .7s ease both; }
[data-animate="bounceInUp"].is-visible { animation: epmBounceInUp .9s cubic-bezier(.28,.84,.42,1) both; }
@keyframes epmFadeIn { from { opacity: 0; } to { opacity: 1; } }
@keyframes epmFadeInUp { from { opacity: 0; transform: translateY(32px); } to { opacity: 1; transform: translateY(0); } }
@keyframes epmFadeInLeft { from { opacity: 0; transform: translateX(-32px); } to { opacity: 1; transform: translateX(0); } }
@keyframes epmFadeInRight { from { opacity: 0; transform: translateX(32px); } to { opacity: 1; transform: translateX(0); } }
@keyframes epmBounceInUp {
  0% { opacity: 0; transform: translateY(60px); }
  60% { opacity: 1; transform: translateY(-8px); }
  80% { transform: translateY(3px); }
  100% { opacity: 1; transform: translateY(0); }
}

@media (max-width: 1020px) {
  .nav-toggle { display: block; }
  .site-nav { position: fixed; inset: 73px 0 auto; display: none; align-items: stretch; padding: 28px 20px 35px; background: #fff; box-shadow: 0 30px 45px rgba(40,30,60,.13); }
  .site-nav.is-open { display: grid; }
  .site-nav a { padding: 8px 0; }
  .hero { min-height: auto; }
  .hero__grid { min-height: 860px; grid-template-columns: 1fr; }
  .hero__copy { align-self: start; padding-top: 62px; }
  .hero__art { position: absolute; right: 0; bottom: 176px; width: 55%; height: 500px; }
  .facts { grid-template-columns: repeat(3, 1fr); }
  .about-card { grid-column: 1 / -1; }
  .split { grid-template-columns: 1fr; gap: 40px; }
  .focus-showcase { width: min(100%, 680px); margin-inline: auto; }
  /* Tablet/mobile intentionally do NOT try to preserve the same large
     background/layered composition used above 1020px - at these widths
     there's no side margin for the castle to grow into and no room
     beside the grid for it to sit next to, so the absolute-positioning
     model is dropped entirely in favour of the simpler, previously-
     approved treatment: a conventional in-flow decorative image in its
     own row, stacked above the foreground grid. */
  .venue-composition { display: block; min-height: auto; }
  /* The centered-behind-the-cards background treatment (position, the
     reduced opacity, the blur) is desktop-only by design - there's no
     side-by-side row for it to sit behind at these widths, so it goes
     back to being a normal, fully-opaque, unblurred in-flow image in its
     own row above the grid, same as the already-approved pre-redesign
     mobile/tablet treatment. */
  .venue-art { position: static; z-index: auto; top: auto; left: auto; transform: none; width: 100%; min-height: 260px; display: grid; place-items: center; margin: 0 0 20px; opacity: 1; filter: none; }
  /* margin-top: 0 overrides the desktop-only calc(var(--castle-w) * .45)
     push (see .venue-grid above 1020px) - that offset only exists to clear
     the large absolutely-positioned castle, which .venue-art above already
     drops back to a static in-flow element at this width, so the grid
     needs no extra top offset of its own here. */
  .venue-grid { grid-template-columns: 1fr 1fr; width: 100%; margin-inline: 0; margin-top: 0; }
  /* Zamek's art box is now full content width (venue spans the grid) - a
     bigger blob than the desktop size keeps it from looking like an
     isolated dot in the wider box, without overshooting into a hard-edged
     clip again. NH's plain background-image composition doesn't need a
     matching override - see the comment above .venue-art.
     inset is reset back down from the desktop-only -70px/-60px (sized for
     the large background-layer composition's much bigger glow) to the
     original, previously-approved -16px/-12px bleed - left at the
     desktop value, the blob's bled box reached past this now-much-smaller
     static art box's own 20px margin-bottom and into .venue-card below
     it, a real regression the DOM-order/overlap assertion caught. */
  .venue-art::before { inset: -16px -12px; background-size: 460px auto; }
  .venue-art img { max-height: 400px; }
  /* Stacked single-column layout has no side-by-side text column to clear,
     so the desktop-only 78px gap (added to clear the widened blob bleed
     above) isn't needed here - kept at its original 40px so this doesn't
     change already-approved mobile/tablet vertical spacing. */
  .poznan-intro { grid-template-columns: 1fr; gap: 40px; text-align: center; }
  .poznan-art { min-height: 200px; }
  .poznan-art img { max-height: 200px; }
  /* The desktop bleed (inset -40px -70px) was widened specifically to fit
     the enlarged 340px blob without hard-clipping (see the comment above
     the base .poznan-art::before rule) - left as-is here it would bleed
     70px past .poznan-art's own box, which at this width is the full wrap
     content width, pushing 50-56px past the viewport edge and forcing a
     horizontal scrollbar. Tightened to stay inside the wrap's own side
     padding (20px at this breakpoint, 14px at 760px below), matching the
     already-safe .venue-art::before bleed pattern. */
  .poznan-art::before { inset: -20px -16px; background-size: 220px auto; }
  .focus-showcase__art-wrap::before { background-size: 520px auto; }
  .included-grid { grid-template-columns: repeat(2, 1fr); }
  .partner-grid { grid-template-columns: repeat(2, 1fr); }
  /* Production keeps the Host Team at 4-in-a-row through this width and only
     shortens the portraits (see the 900px/760px breakpoints below) - it
     does not drop to fewer columns here the way included/partner do. */
  .person img { height: 210px; }
  .countdown__inner { grid-template-columns: 1fr; }
  .site-footer { padding-top: 32px; }
  #contact { padding-bottom: 80px; }
}

/* Team-specific breakpoint, narrower than the 1020px one above: a real
   desktop browser window (even a non-maximized one, or with devtools open)
   commonly falls in the 900-1020px range, and the Host Team must still read
   as one compact row there - only a genuinely tablet-sized viewport drops
   it to 2x2. */
@media (max-width: 900px) {
  .team-grid { grid-template-columns: repeat(2, 1fr); }
}

@media (max-width: 760px) {
  .wrap { width: min(calc(100% - 28px), var(--content)); }
  .section { padding: 44px 0 16px; }
  .site-header__inner { min-height: 74px; }
  .brand img { width: 70px; max-height: 54px; }
  .site-nav { top: 75px; }
  .hero__grid { min-height: auto; display: block; padding-bottom: 20px; }
  .hero__copy { padding: 48px 0 14px; }
  /* height:auto (not a fixed px value) is the fix: a fixed container height
     that is shorter than the image's max-height let the image overflow
     upward into .hero__copy above it - sizing the container to its own
     content removes that mismatch regardless of the image's aspect ratio. */
  .hero__art { position: static; width: 100%; height: auto; padding: 6px 0 2px; }
  .hero__art img { max-height: 300px; margin-inline: auto; }
  .facts { position: static; grid-template-columns: 1fr; padding-bottom: 18px; gap: 10px; }
  .fact { min-height: 112px; }
  .about-card { grid-column: auto; }
  .focus-showcase__art-wrap { margin-bottom: 16px; }
  .focus-showcase__art-wrap::before { background-size: 300px auto; }
  .focus-showcase__art { height: 281px; }
  .focus-grid, .city-grid, .tiers, .contact-grid { grid-template-columns: 1fr; }
  .tier--flash-sale { transform: none; }
  .focus-grid { gap: 12px; }
  .focus-card { padding: 15px; }
  .venue-grid { grid-template-columns: 1fr; width: 100%; margin-inline: 0; }
  /* Narrowest box for Zamek - the smaller blob is what lets its own soft
     fade complete inside the box instead of being hard-clipped by the box
     edge, which is what made it look like a cropped rectangle on a real
     phone. NH's plain background-image composition is unaffected. */
  .venue-art::before { background-size: 320px auto; }
  /* Same overflow fix as the 1020px breakpoint above, retightened for this
     narrower wrap padding (14px each side). */
  .poznan-art::before { inset: -14px -10px; background-size: 200px auto; }
  .map, .map iframe { min-height: 320px; }
  .included-grid, .team-grid, .partner-grid { grid-template-columns: 1fr; }
  .person img { height: 240px; }
  .pricing-card, .contact-card { padding: 22px 18px; }
  .pricing-intro { display: block; }
  .timer { grid-template-columns: repeat(2, 1fr); }
  .form-grid { grid-template-columns: 1fr; }
  .field--full { grid-column: auto; }
  .faq-list { grid-template-columns: 1fr; }
  .faq-cta { display: grid; text-align: center; }
  .faq-cta .btn { width: 100%; }
  .footer-grid { grid-template-columns: 1fr; gap: 28px; text-align: center; }
  .footer-brand p { margin-inline: auto; }
  .footer-divider { margin-inline: auto; }
  .footer-bottom { display: grid; justify-items: center; text-align: center; }
  .socials { justify-content: center; }
  #contact { padding-bottom: 32px; }
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation-duration: .01ms !important; animation-iteration-count: 1 !important; transition-duration: .01ms !important; }
  [data-animate] { opacity: 1 !important; }
}
