/* SRZ MsO Nové Zámky — the approved "K — Úrad" design, ported.

   One green, one ink, one muted grey, a hairline and a paper background.
   No yellow and no second accent anywhere: the design is deliberately
   quiet, and every emphasis is carried by --zelena alone.

   Measured WCAG 2.x contrast ratios (relative-luminance formula, sRGB).
   Every pair below that carries text passes AA (4.5:1); the icon and
   border pairs are listed with the 3:1 non-text threshold in mind.

     Against --bg (#f3f5f3) — the page:
       --ink   #16211b  -> 15.12:1  (body text)
       --soft  #56655c  ->  5.62:1  (muted text, captions, dates)
       --zelena #1d5c3a ->  7.25:1  (links, current nav item)

     Against --white (#ffffff) — every card, panel and tile:
       --ink   #16211b  -> 16.57:1  (body text, tile and news headings)
       --soft  #56655c  ->  6.16:1  (tile descriptions, table's "zatvorené")
       --zelena #1d5c3a ->  7.94:1  (links, today's row, focus ring)
       --line  #d7dfd9  ->  1.36:1  (hairline borders only — decorative,
                                     never a control's only affordance)

     Against --zelena (#1d5c3a) — the topbar and the highlighted tile:
       #ffffff          ->  7.94:1  (tile heading, topbar hover)
       #dfeee5          ->  6.62:1  (topbar text and links)
       #cfe5d7          ->  5.99:1  (highlighted tile's description)

     Against --zelena-sv (#e3efe7) — nav hover, open-state icon chip,
     a table's header row:
       --ink   #16211b  -> 14.02:1  (nav label on hover, header cells)
       --zelena #1d5c3a ->  6.72:1  (icon stroke, well past the 3:1 icons need)

     Against --ink (#16211b) — the footer:
       #b7c4bc          ->  9.18:1  (footer text)

     Against #eceeec — the closed-state icon chip:
       --soft  #56655c  ->  5.28:1  (icon stroke, past the 3:1 icons need)

     Against #fdf3e3 — editor's warning block (callout--warning):
       #4a3011        -> 11.09:1  (text and border)

     Against --ink (#16211b) — the management section's header bar:
       #cfe5d7          -> 12.50:1  (bar's links)
       #ffffff          -> 16.57:1  (bar's title, button label)
       #676e6b          ->  3.17:1  (button border, blended from #ffffff59 —
                                     a non-text boundary, clears the 3:1
                                     WCAG asks of a control's edge)

     Against --white (#ffffff) — the login page:
       #8a1c1c          ->  9.28:1  (login error text)

   PT Sans is served from this site (web/static/fonts/, SIL Open Font
   Licence 1.1, see OFL.txt beside the files). It is NOT linked from a
   font CDN: the club publishes its own cookie policy and the site must
   not hand a visitor's IP address to a third party to render its text. */

@font-face {
  font-family: "PT Sans";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/pt-sans-400-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: "PT Sans";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/pt-sans-400-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: "PT Sans";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("../fonts/pt-sans-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;
}
@font-face {
  font-family: "PT Sans";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("../fonts/pt-sans-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;
}

:root {
  --zelena: #1d5c3a;
  --zelena-sv: #e3efe7;
  --ink: #16211b;
  --soft: #56655c;
  --line: #d7dfd9;
  --bg: #f3f5f3;
  --white: #ffffff;
  /* The two tints that only ever sit on --zelena. */
  --na-zelenej: #dfeee5;
  --na-zelenej-tlmena: #cfe5d7;
  --wrap: 72rem;
  --radius: 10px;
  /* PT Sans first; the rest are what a phone or a Linux server already
     has, so the page is readable in the blink before the font arrives. */
  --pismo: "PT Sans", "Avenir Next", "Segoe UI", system-ui, -apple-system,
    "Helvetica Neue", Arial, sans-serif;
}

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

/* Headings and the short lines on the cards are balanced, so a title
   that wraps does not leave one word alone on the second line; running
   text asks only that its last line not be a single word. Browsers
   without either keyword simply wrap as they always did. */
h1, h2, h3, h4, h5, h6,
.tile__title, .tile__description,
.uvod__perex, .status__title, .official__role {
  text-wrap: balance;
}
.prose p, .prose li, .novinka__perex, .aktualita__perex { text-wrap: pretty; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--pismo);
  font-size: 1.0625rem;
  line-height: 1.6;
  /* A short page — the 404, a one-paragraph article — would otherwise
     leave the footer floating in the middle of the window. */
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}

a { color: var(--zelena); }

img { max-width: 100%; }

:focus-visible { outline: 3px solid var(--zelena); outline-offset: 3px; }

.wrap { width: min(100% - 2.4rem, var(--wrap)); margin-inline: auto; }

.visually-hidden {
  position: absolute; width: 1px; height: 1px;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap;
}

.skip-link {
  position: absolute; left: -999px;
  background: var(--zelena); color: #fff; padding: .75rem 1rem;
  border-radius: 0 0 var(--radius) 0;
}
.skip-link:focus { left: 0; top: 0; z-index: 30; }
/* Two rings, because the focused skip link straddles two backgrounds:
   it is 51px tall at the top left corner, and the green topbar is only
   36px of that. The page's own green ring was #1d5c3a drawn over
   #1d5c3a — invisible for its whole upper half — and a white one would
   vanish against the white header below it. White on the green (7.94:1)
   and ink on the white (16.57:1) means one of the two is always there. */
.skip-link:focus-visible {
  outline: 3px solid #fff; outline-offset: 0;
  box-shadow: 0 0 0 6px var(--ink);
}

/* The shared icon chip: a rounded square of pale green with one
   line-drawn glyph. Shape and stroke are set here and inherited by the
   <use>d symbol, which is how the dark tile draws the same icon white. */
.icon {
  flex: none; width: 48px; height: 48px; border-radius: var(--radius);
  background: var(--zelena-sv); display: grid; place-items: center;
}
.icon svg {
  width: 26px; height: 26px;
  stroke: var(--zelena); fill: none;
  stroke-width: 2; stroke-linecap: round; stroke-linejoin: round;
}
.ikony-sprite { position: absolute; width: 0; height: 0; overflow: hidden; }

/* Topbar */
.topbar { background: var(--zelena); color: var(--na-zelenej); font-size: .86rem; }
.topbar__kontakt {
  margin: 0; padding-block: .45rem; text-align: right;
  overflow-wrap: anywhere;
}
.topbar a { color: var(--na-zelenej); text-decoration: none; }
.topbar a:hover, .topbar a:focus { color: #fff; text-decoration: underline; }
.topbar :focus-visible { outline-color: #fff; outline-offset: 2px; }

/* Header */
.site-header { background: var(--white); border-bottom: 1px solid var(--line); }
.site-header__inner {
  display: flex; align-items: center; gap: 1rem; padding-block: 1rem;
}
.brand {
  color: var(--ink); text-decoration: none;
  /* nowrap: the emblem and the wordmark are one lockup and must never
     stack, however large the emblem gets. */
  display: flex; flex-wrap: nowrap; align-items: center; gap: .85rem;
}
.brand__logo { width: 48px; height: auto; flex: none; }
.brand__text { display: grid; min-width: 0; }
.brand__name { font-size: 1.2rem; font-weight: 700; line-height: 1.15; }
.brand__tagline { font-size: .86rem; color: var(--soft); }

.nav-toggle {
  /* min-height, because this is the only way into the menu on a phone
     and the padding alone left it 39px tall — under the 44px a thumb
     needs. It is the tallest thing in the header row on a phone, so
     nothing else moves. */
  display: none; margin-left: auto; align-items: center; gap: .5rem;
  min-height: 44px;
  background: none; border: 2px solid var(--line); border-radius: 8px;
  font-family: inherit; font-weight: 700; font-size: .9rem;
  padding: .5rem .8rem; color: var(--ink); cursor: pointer;
}
.nav-toggle__bar,
.nav-toggle__bar::before,
.nav-toggle__bar::after {
  display: block; width: 18px; height: 2px; background: var(--ink); content: "";
}
.nav-toggle__bar::before { transform: translateY(-6px); }
.nav-toggle__bar::after { transform: translateY(4px); }
.nav-toggle[aria-expanded="true"] { border-color: var(--zelena); color: var(--zelena); }
.nav-toggle[aria-expanded="true"] .nav-toggle__bar,
.nav-toggle[aria-expanded="true"] .nav-toggle__bar::before,
.nav-toggle[aria-expanded="true"] .nav-toggle__bar::after { background: var(--zelena); }

/* Navigation: one underlined row, generated from the Page sections. */
.nav { border-top: 1px solid var(--line); }
.nav__list, .nav__sublist { list-style: none; margin: 0; padding: 0; }
.nav__list { display: flex; gap: .2rem; flex-wrap: wrap; }
.nav__section { position: relative; }

.nav__label {
  display: flex; align-items: center; gap: .4rem;
  font-family: inherit; font-size: .95rem; font-weight: 700; color: var(--ink);
  /* line-height too: a <button> does not inherit it, so without this the
     section buttons sit 2px above the plain links beside them. */
  line-height: inherit;
  background: none; border: 0; border-bottom: 3px solid transparent;
  padding: .85rem 1rem; cursor: pointer; text-decoration: none;
}
.nav__label:hover { background: var(--zelena-sv); }
.nav__label[aria-expanded="true"] { background: var(--zelena-sv); }

/* The current page: a green underline, on the link that *is* this URL
   and on the button of the section that holds it. */
.nav__link[aria-current="page"],
.nav__label--aktivna { border-bottom-color: var(--zelena); color: var(--zelena); }
.nav__link[aria-current="true"] { color: var(--zelena); }

.nav__chevron {
  width: .4rem; height: .4rem; border-right: 2px solid var(--soft);
  border-bottom: 2px solid var(--soft); transform: translateY(-2px) rotate(45deg);
  transition: transform .15s ease;
}
.nav__label[aria-expanded="true"] .nav__chevron { transform: translateY(1px) rotate(-135deg); }

/* Closed by default; the button's own state reveals its panel. */
.nav__sublist { display: none; }
.nav__label[aria-expanded="true"] + .nav__sublist { display: block; }
.nav__sublist a { color: var(--ink); text-decoration: none; display: block; font-size: .95rem; }
.nav__sublist a:hover, .nav__sublist a:focus { color: var(--zelena); text-decoration: underline; }
.nav__sublist a[aria-current="page"] { color: var(--zelena); font-weight: 700; }

/* Content */
main { padding-block: 2.2rem 3.4rem; flex: 1; }

/* --- Homepage: the welcome ------------------------------------------- */
.uvod {
  display: grid; grid-template-columns: 1fr 1fr; gap: 2.4rem;
  align-items: center; padding-bottom: 1.2rem;
}
.uvod__nadpis { font-size: clamp(1.9rem, 4vw, 2.6rem); line-height: 1.15; margin: 0 0 .5rem; }
.uvod__perex { margin: 0; color: var(--soft); font-size: 1.08rem; }
.uvod__foto { margin: 0; }
/* Never cropped and never blown up: the original is 650 x 172, all the
   club has of this view, and it falls apart at any larger size. */
.uvod__foto img {
  display: block; width: 100%; max-width: 650px; height: auto;
  border-radius: var(--radius);
}
.uvod__foto figcaption { font-size: .85rem; color: var(--soft); margin-top: .45rem; }

/* --- Homepage: the tile grid ----------------------------------------- */
.tiles {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 1rem;
  padding-block: 1.4rem 2.6rem;
}
.tile {
  display: flex; gap: 1rem; align-items: flex-start;
  background: var(--white); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 1.3rem 1.3rem 1.35rem;
  text-decoration: none; color: var(--ink);
  transition: border-color .15s, box-shadow .15s;
}
.tile:hover { border-color: var(--zelena); box-shadow: 0 6px 18px #1d5c3a1f; }
.tile__text { display: grid; gap: .3rem; }
.tile__title { font-size: 1.12rem; font-weight: 700; line-height: 1.25; }
.tile__description { color: var(--soft); font-size: .93rem; line-height: 1.45; }

.tile--featured { background: var(--zelena); border-color: var(--zelena); color: #fff; }
.tile--featured .tile__description { color: var(--na-zelenej-tlmena); }
.tile--featured .icon { background: #ffffff26; }
.tile--featured .icon svg { stroke: #fff; }
.tile--featured:focus-visible { outline-color: #fff; }

/* --- Homepage: news beside the office -------------------------------- */
.stlpce {
  display: grid; grid-template-columns: 2fr 1fr; gap: 1.6rem;
  align-items: start;
}
.panel { background: var(--white); border: 1px solid var(--line); border-radius: var(--radius); }
.panel__nadpis {
  font-size: 1.2rem; line-height: 1; margin: 0;
  padding: 1.1rem 1.3rem; border-bottom: 1px solid var(--line);
}
.panel__prazdne { margin: 0; padding: 1.05rem 1.3rem; color: var(--soft); }
.panel__odkaz {
  display: block; padding: .9rem 1.3rem; font-weight: 700;
  text-decoration: none; border-top: 1px solid var(--line);
}
.panel__odkaz:hover { text-decoration: underline; }

.novinka { padding: 1.05rem 1.3rem; border-bottom: 1px solid var(--line); }
.novinka:last-of-type { border-bottom: 0; }
.novinka__datum { font-size: .86rem; color: var(--soft); }
.novinka__nazov { font-size: 1.08rem; line-height: 1.35; margin: .2rem 0 .25rem; }
.novinka__nazov a { color: var(--ink); text-decoration: none; }
.novinka__nazov a:hover { color: var(--zelena); text-decoration: underline; }
.novinka__perex { color: var(--soft); font-size: .94rem; }
.novinka__perex > * { margin: 0; }
.novinka__perex > * + * { margin-top: .4rem; }

/* --- Homepage: the office panel -------------------------------------- */
.kancelaria { padding: 1.1rem 1.3rem 1.2rem; }
.stav {
  display: flex; gap: .8rem; align-items: center; margin: 0;
  padding-bottom: 1rem; border-bottom: 1px solid var(--line);
}
.stav .icon { width: 42px; height: 42px; background: #eceeec; }
.stav .icon svg { width: 22px; height: 22px; stroke: var(--soft); }
.status__text { display: grid; }
.status__title { font-size: 1.12rem; line-height: 1.2; }
.status__detail { color: var(--soft); font-size: .92rem; }
.status--open .icon { background: var(--zelena-sv); }
.status--open .icon svg { stroke: var(--zelena); }
.status--open .status__title { color: var(--zelena); }

.hodiny { width: 100%; border-collapse: collapse; margin-top: .7rem; font-size: .95rem; }
.hodiny th, .hodiny td {
  padding: .45rem 0; border-bottom: 1px dashed var(--line);
  vertical-align: top; font-weight: 400; text-align: left;
}
.hodiny td { text-align: right; white-space: nowrap; }
.hodiny tr:last-child th, .hodiny tr:last-child td { border-bottom: 0; }
.hodiny__dnes th, .hodiny__dnes td { font-weight: 700; color: var(--zelena); }
.hodiny__zatvorene { color: var(--soft); }
.hodiny__dnes .hodiny__zatvorene { color: var(--zelena); }

.adresa { margin: 1rem 0 0; font-size: .95rem; line-height: 1.55; }

/* --- Ordinary pages: prose on a card --------------------------------- */
.prose {
  background: var(--white); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 1.6rem 1.8rem 2rem;
  /* flow-root: keeps floated photos from spilling past the card. */
  display: flow-root;
  /* The reading measure. The card is as wide as the homepage grid — 72rem
     — because tables, the revír list and the funkcionári cards need that
     width. Running text does not: at the card's full width a paragraph of
     this regulatory Slovak prose ran 116 characters to the line, where
     45–75 is the comfortable range and ~65 the target.

     37rem is 592px, which measures 66 characters of this text in PT Sans
     at 17px. It is written in rem and not in ch on purpose: `ch` is
     resolved against each element's own font size, so a heading or a
     date would have taken the same 64ch as a wider or narrower column
     and the right-hand rag would step in and out down the page. */
  --miera: 37rem;
}

.prose h1 {
  font-size: clamp(1.75rem, 1.2rem + 2vw, 2.4rem);
  line-height: 1.2; margin: 0 0 1.25rem;
  padding-bottom: .7rem; border-bottom: 1px solid var(--line);
}

/* The migrated pages open their sections at whatever level Joomla left
   them — história and brigády use h3, ochrana osobných údajov h2 then
   h3, the komentár page h6 — so every level has to be legible on its
   own. Unstyled, h4 landed on the body size and h6 on 11px, smaller
   than the text it introduced.

   Each step is at least 1.2x the one below, and every heading keeps far
   more space above it than below: a heading belongs to the text that
   follows it, and the old 1:1 spacing left them floating between two
   paragraphs. */
.prose h2 { font-size: 1.7rem; line-height: 1.25; margin: 2.6rem 0 .6rem; }
.prose h3 { font-size: 1.4rem; line-height: 1.3; margin: 2.2rem 0 .5rem; }
.prose h4 { font-size: 1.18rem; line-height: 1.35; margin: 1.9rem 0 .45rem; }
.prose h5, .prose h6 { font-size: 1.0625rem; line-height: 1.4; margin: 1.7rem 0 .4rem; }
.prose h2, .prose h3, .prose h4, .prose h5, .prose h6 { clear: both; }
.prose a { text-underline-offset: .15em; }
.prose a:hover { color: var(--ink); }
.prose img { height: auto; border-radius: 6px; }

/* Everything that is read line by line is held to the measure. The card
   keeps its full width for the things that need it — the h1 and its rule
   frame the card, and tables, the map, the funkcionári cards and the
   aktuality cards opt out below. */
.prose p,
.prose dt, .prose dd,
.prose blockquote,
.prose h2, .prose h3, .prose h4, .prose h5, .prose h6 {
  max-width: var(--miera);
}
/* A list is capped as a whole and indented by its own marker column, so
   its lines end on the same vertical as the paragraphs above rather than
   the browser's 40px further right, and the bullets hang in the indent.
   `:not([class])` is what separates content from layout here: the
   sanitiser strips every class off imported markup, so a list with a
   class — .officials, .aktuality, .signpost — is one of ours and is a
   grid, not running text. */
.prose ul:not([class]),
.prose ol:not([class]) {
  max-width: var(--miera);
  padding-left: 1.4rem;
}
/* Joomla left a good deal of the text in bare <div>s rather than <p> —
   most of the "Pstruh na VN Dôchodcov" article is written that way — and
   those lines ran the full width of the card while the paragraphs above
   them did not. Only a div with nothing but inline content in it is
   running text: a div that holds blocks is a wrapper (the body arrives
   inside two of them, and the scraper's own .table-scroll is one), and
   capping a wrapper would drag every table and card grid in with it. */
.prose div:not(:has(div, p, table, ul, ol, dl, hr, blockquote, h1, h2, h3, h4, h5, h6)) {
  max-width: var(--miera);
}
.prose .mapa { max-width: none; }

/* Štýly, ktoré ponúka editor. Klub vyberá hotový štýl, nie farbu, takže
   stránka ostáva jednotná a nevznikne nečitateľná kombinácia. */
.prose .text--center { text-align: center; }
.prose .text--right { text-align: right; }

.prose .callout--warning,
.prose .callout--important {
  /* Padding (1rem 1.2rem) narrows the callout despite max-width:
     the padded box fits the measure while the unpadded paragraphs above do. */
  max-width: var(--miera);
  margin-block: 1.4rem;
  padding: 1rem 1.2rem;
  border-radius: var(--radius);
  border-left: 4px solid;
}
.prose .callout--warning {
  background: #fdf3e3; border-left-color: #a15c18; color: #4a3011;
}
.prose .callout--important {
  background: var(--zelena-sv); border-left-color: var(--zelena); color: var(--ink);
}
.prose .callout--warning > :first-child,
.prose .callout--important > :first-child { margin-top: 0; }
.prose .callout--warning > :last-child,
.prose .callout--important > :last-child { margin-bottom: 0; }

/* Náhľad nezverejneného ohlasu pre správcu: zámerné reuse palety varovného bloku
   (audítované: #fdf3e3 pozadie, #4a3011 text a okraj -> 11.09:1). */
.preview {
  background: #fdf3e3; color: #4a3011; border-left: 4px solid #a15c18;
  border-radius: var(--radius); padding: .8rem 1rem; margin-bottom: 1.4rem; font-weight: 700;
}

/* A page with nothing but prose has no reason to be as wide as the card
   the tables need: at 72rem the text column left ~500px of empty card
   beside it. Such a page hugs the measure and centres instead. Pages
   carrying a table keep the full width — the widest migrated table is
   940px and would otherwise scroll. */
.prose--text { max-width: calc(var(--miera) + 3.6rem); margin-inline: auto; }
.prose hr { border: 0; border-top: 1px solid var(--line); margin-block: 1.5rem; }
.prose code { font-size: .92em; background: var(--bg); padding: .1em .35em; border-radius: 4px; }

/* Photos the legacy pages floated beside the text. Below 48rem a floated
   photo would leave a one-word-wide column, so they become full blocks. */
.image--left,
.image--right {
  display: block;
  margin-inline: auto;
  margin-block: 1.25rem;
}

/* A wide table on a phone scrolls inside .table-scroll, the wrapper the
   scraper puts around it. Putting `display: block; overflow-x: auto` on the
   <table> itself — the usual shortcut — costs it its implicit ARIA table
   role in every major browser, and these pages are mostly tables. */
/* The 6px of padding is room for a focus ring. `overflow-x: auto`
   computes `overflow-y` to auto as well, so the wrapper clips in both
   directions, and the PDF links inside these tables sit in the first
   cell of the last row — hard against two of its edges. The negative
   inline margin puts the table back on the same vertical as the
   paragraphs; the block margin is reduced by the same 6px, so the gap
   above and below is the 1.5rem it always was. */
.table-scroll {
  overflow-x: auto;
  padding: 6px; margin: calc(1.5rem - 6px) -6px;
}

.prose table {
  width: 100%; border-collapse: collapse; margin-block: 1.5rem;
  display: table;
}
.table-scroll table { margin-block: 0; }
/* Row rules, not a grid of boxes — the same table language the approved
   design uses for the office hours, where a hairline under each row is
   the only border there is.

   It matters more here than it looks: Joomla used tables for layout as
   well as for data, so "Povolenky / noví členovia" is three single-column
   tables and the rybársky poriadok page ends on a one-cell table holding
   a non-breaking space. Boxed, those read as a broken grid and an empty
   panel; ruled, they read as the lists they are. The first cell loses its
   left padding so every table starts on the same vertical line as the
   paragraphs above it. */
.prose th, .prose td {
  border-bottom: 1px solid var(--line);
  padding: .6rem 1rem; text-align: left; vertical-align: top;
}
.prose th:first-child, .prose td:first-child { padding-left: 0; }
.prose th:last-child, .prose td:last-child { padding-right: 0; }
/* A cell that is alone on its row is a paragraph wearing a table — the
   rozdelenie page opens each section with one, and the sentence in it
   ran 130 characters to the line, wider than anything the measure cap
   reached. `max-width` is no use here: the table layout algorithms
   ignore it on a cell. Percentage padding does work, and it resolves
   against the table, so this takes the cell's own text down to the
   measure and leaves the rule under it spanning the card. Cells holding
   a picture are left alone — the sponsors' logos are laid out this way
   and would be shrunk to the text column. */
.prose tr > td:only-child:not(:has(img)),
.prose tr > th:only-child:not(:has(img)) {
  padding-right: max(0px, calc(100% - var(--miera)));
}
.prose tr:last-child th, .prose tr:last-child td { border-bottom: 0; }
.prose th { background: var(--zelena-sv); font-weight: 700; }

/* Mapa revírov — the embed is the whole point of that page, so give it room. */
.mapa {
  position: relative; margin-block: 1.5rem;
  border: 1px solid var(--line); border-radius: 6px;
  overflow: hidden; aspect-ratio: 4 / 3;
}
.mapa iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }
/* The map is an iframe and an iframe takes focus. `overflow: hidden` on
   .mapa — which is what rounds the embed's corners — cut the ring off
   entirely, so it is drawn inside the frame instead of around it. */
.mapa iframe:focus-visible { outline-offset: -3px; }

/* Funkcionári */
.committee { margin-block: 2.2rem; }
/* The term used to be pulled up 12px to close the browser's default h2
   margin. The heading now sets its own 9.6px, so the pull left the two
   overlapping by 2px — the line under the committee's name belongs to
   it, but not that closely. */
.committee__term { color: var(--soft); margin: .15rem 0 0; }

.officials {
  list-style: none; margin: 1.25rem 0 0; padding: 0;
  display: grid; gap: 1rem;
  grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));
}
.official {
  background: var(--bg); border: 1px solid var(--line);
  border-radius: 6px; padding: .9rem 1rem; display: grid; gap: .2rem;
}
.official__name { font-weight: 700; }
.official__role { color: var(--soft); font-size: .9rem; }
.official__email { font-size: .875rem; overflow-wrap: anywhere; }

/* Aktuality — the archive at /aktuality and the article page. Same white
   card as the homepage panels, so the two read as one site. */
.aktuality { list-style: none; margin: 1.5rem 0 0; padding: 0; display: grid; gap: 1rem; }
.aktualita {
  background: var(--bg); border: 1px solid var(--line);
  border-radius: 6px; padding: 1.1rem 1.25rem;
}
.aktualita__datum { margin: 0 0 .35rem; color: var(--soft); font-size: .86rem; }
/* Scoped past `.prose h2`, which would otherwise push a 2.2rem gap
   between the card's date and its heading. */
.aktuality .aktualita__nazov { margin: 0 0 .5rem; font-size: 1.25rem; line-height: 1.3; }
.aktualita__nazov a { color: var(--ink); text-decoration: none; }
.aktualita__nazov a:hover, .aktualita__nazov a:focus { color: var(--zelena); text-decoration: underline; }

.aktualita__perex { margin: 0; color: var(--soft); }
.aktualita__perex > :first-child { margin-top: 0; }
.aktualita__perex > :last-child { margin-bottom: 0; }

.aktualita__odkaz { margin: .75rem 0 0; font-weight: 700; }
.aktualita__spat { margin-top: 2.5rem; clear: both; font-weight: 700; }

/* Chybové stránky — the migration drops far more URLs than it keeps, so
   the 404 has to be a signpost rather than a dead end. */
.signpost {
  list-style: none; margin: 1.5rem 0 0; padding: 0;
  display: grid; gap: 1.5rem;
  grid-template-columns: repeat(auto-fill, minmax(14rem, 1fr));
}
.signpost__list { list-style: none; margin: .35rem 0 0; padding: 0; }
.signpost__section {
  display: block; font-size: .8rem; text-transform: uppercase;
  letter-spacing: .06em; color: var(--soft); font-weight: 700;
}
.signpost li { margin-block: .15rem; }

/* Footer */
.site-footer { background: var(--ink); color: #b7c4bc; padding-block: 2rem 3rem; font-size: .92rem; }
.site-footer p { margin: 0; }
.site-footer a { color: #fff; }

/* Desktop: the section panel floats over the page as a white card.

   Written as the exact negation of the mobile query below, so that every
   viewport matches one block or the other and never both or neither. A
   `min-width` a hair above 60rem cannot do that: 60.0625rem (961px) left
   fractional widths between 960 and 961px — browser zoom, a scaled
   display, a split window — matching neither block, and 60.0001rem
   overlaps instead, because browsers round lengths to 1/64px and
   960.0016px is 960px. */
@media not all and (max-width: 60rem) {
  .nav__sublist {
    position: absolute; top: 100%; left: 0; z-index: 20;
    min-width: 16rem; padding: .5rem;
    background: var(--white); border: 1px solid var(--line);
    border-radius: 0 var(--radius) var(--radius) var(--radius);
    box-shadow: 0 10px 24px #1d5c3a26;
  }
  .nav__sublist a { padding: .5rem .6rem; border-radius: 6px; }
  .nav__sublist a:hover, .nav__sublist a:focus { background: var(--zelena-sv); text-decoration: none; }
  .nav__sublist a[aria-current="page"] { background: var(--zelena-sv); }
}

@media (max-width: 60rem) {
  .tiles { grid-template-columns: 1fr 1fr; }
  .uvod, .stlpce { grid-template-columns: 1fr; }
  .uvod { gap: 1.4rem; }
  /* The photo keeps its own size rather than stretching to the column,
     and the caption goes with it. Centring the image alone left
     "Kurzweillovo jazero, Nové Zámky" on the column's left edge, 66px
     adrift of the picture it names — measured at 820px, and true from
     about 690px up to the 960px where the two-column layout returns. */
  .uvod__foto { width: fit-content; max-width: 100%; margin-inline: auto; }

  .nav-toggle { display: flex; }
  /* Free: the toggle beside it is already 44px, so the header row does
     not grow — the emblem-and-wordmark link simply fills the height it
     is sitting in instead of being a 35px target in the middle of it. */
  .brand { min-height: 44px; }
  .nav { display: none; }
  .nav--open { display: block; }
  .nav__list { flex-direction: column; gap: 0; padding-block: .4rem .8rem; }
  .nav__label {
    width: 100%; justify-content: space-between;
    border-bottom: 0; border-left: 3px solid transparent; padding: .7rem .8rem;
  }
  .nav__link[aria-current="page"],
  .nav__label--aktivna { border-bottom-color: transparent; border-left-color: var(--zelena); }
  .nav__sublist { padding: .1rem 0 .6rem 1.5rem; }
  /* 44px of tappable row, not 36: these are the only links to most of
     the site on a phone, and they sit directly under each other, so a
     near miss lands on the neighbour. */
  .nav__sublist a { padding: .65rem 0; }
}

@media (min-width: 48rem) {
  /* 36%, not 45%: the photo now insets into a 37rem column rather than
     the whole card, and at 45% it left the text beside it 34 characters
     to the line. At 36% the inset lines hold 40, and because the column
     is a fixed 37rem from 48rem upwards the photo is the same size on a
     tablet as on a 27-inch monitor — the intermediate widths that used
     to misbehave have nothing left to vary. 18rem is a touch over the
     288px these scans actually are, so none of them is ever enlarged. */
  .image--left,
  .image--right {
    max-width: min(36%, 18rem);
    margin-block: .35rem;
  }
  .image--left { float: left; margin-right: 1.4rem; }
  .image--right { float: right; margin-left: 1.4rem; }
  .mapa { aspect-ratio: 16 / 9; }
}

@media (max-width: 36rem) {
  .tiles { grid-template-columns: 1fr; padding-block: 1.2rem 2rem; }
  .prose { padding: 1.2rem 1.1rem 1.5rem; }
  /* The phone number and the address are the two things a member is
     most likely to reach for on a phone, and they were 18px-tall
     targets. The padding moves from the paragraph onto the links
     themselves, so the strip grows by 8px and each link becomes 44px. */
  .topbar__kontakt { text-align: left; padding-block: 0; }
  .topbar a { display: inline-block; padding-block: .7rem; }
  /* The wordmark alone at phone width; the full name is in the footer. */
  .brand__tagline { display: none; }
  .brand__name { font-size: 1.05rem; }
  .brand__logo { width: 40px; }
  .panel__nadpis, .novinka, .panel__prazdne, .panel__odkaz, .kancelaria { padding-inline: 1.1rem; }
}

/* --- Správa obsahu --------------------------------------------------- */
.staff__bar {
  background: var(--ink); color: #fff; padding-block: .7rem; margin-bottom: 2rem;
}
.staff__bar .wrap { display: flex; align-items: center; gap: 1.4rem; flex-wrap: wrap; }
.staff__bar nav { display: flex; gap: 1.2rem; margin-right: auto; }
.staff__bar a { color: #cfe5d7; text-decoration: none; }
.staff__bar a:hover { color: #fff; text-decoration: underline; }
.staff__bar button {
  background: none; border: 1px solid #ffffff59; color: #fff;
  border-radius: 6px; padding: .4rem .8rem; font: inherit; cursor: pointer;
}
.staff__form { max-width: 24rem; }
.staff__form--wide { max-width: 52rem; }
.staff__button {
  display: inline-block; background: var(--zelena); color: #fff;
  text-decoration: none; font-weight: 700; padding: .7rem 1.1rem; border-radius: 8px;
}
.staff__list { width: 100%; border-collapse: collapse; }
.staff__list th, .staff__list td { padding: .6rem .4rem; border-bottom: 1px solid var(--line); }
/* Browsers centre and bold a <th> by default; every other column in this
   table is left-aligned, so the header row would otherwise be the one
   inconsistent line in it. */
.staff__list th { text-align: left; }
.staff__error { color: #8a1c1c; font-weight: 700; }
.staff__photos { display: grid; grid-template-columns: repeat(auto-fill, minmax(12rem, 1fr)); gap: 1rem; }
.staff__photos img { width: 100%; height: auto; border-radius: 8px; border: 1px solid var(--line); }
.staff__photos figcaption { font-size: .78rem; color: var(--soft); word-break: break-all; }

/* Správa obsahu — the forms. `/sprava/aktuality/novy` renders
   `{{ form.as_p }}` untouched; `/sprava/prihlasenie` renders the same
   per-field shape by hand (to drop Django's own non-field error, which
   would otherwise repeat the template's own message) — a label, its
   widget and an optional `span.helptext` inside one bare `<p>`, with a
   `ul.errorlist` landing as that `<p>`'s previous sibling when the field
   fails validation. Nothing below changes that markup — only how it lays
   out inside `.staff__form`. */
.staff__form p { margin: 0 0 1.1rem; }
.staff__form label {
  display: block;
  margin-bottom: .35rem;
  font-weight: 700;
  color: var(--ink);
}
.staff__form input[type="text"],
.staff__form input[type="password"],
.staff__form input[type="email"],
.staff__form textarea {
  width: 100%;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: var(--white);
  color: var(--ink);
  font: inherit;
  padding: .55rem .7rem;
}
.staff__form textarea { resize: vertical; }
.staff__form .helptext {
  display: block;
  margin-top: .3rem;
  font-size: .85rem;
  color: var(--soft);
}

/* `published_at` is a SplitDateTimeField: two bare text inputs sharing
   one label and one `<p>`, nothing else in the markup to tell them apart
   from a single-field row. Selected by `name` — `published_at_0`/`_1`
   are fixed by the field itself — rather than by position. The label's
   `width: 100%` fills the flex row on its own, so the two inputs wrap
   onto the line under it and sit side by side there, at any width. */
.staff__form p:has(input[name="published_at_0"]) {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: .6rem;
}
.staff__form p:has(input[name="published_at_0"]) label { width: 100%; }
.staff__form input[name="published_at_0"],
.staff__form input[name="published_at_1"] {
  width: auto;
  flex: 1 1 8rem;
  min-width: 0;
}

/* A checkbox reads left of its label, both on one line — stacking them
   the way every other field stacks would read as two unrelated lines.
   The help text still drops to its own line under the row. */
.staff__form p:has(input[type="checkbox"]) {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: .5rem;
}
.staff__form p:has(input[type="checkbox"]) label {
  display: inline;
  width: auto;
  margin: 0;
}
.staff__form input[type="checkbox"] { width: auto; margin: 0; }
.staff__form p:has(input[type="checkbox"]) .helptext { flex-basis: 100%; }

/* Same colour as .staff__error above (#8a1c1c, 9.28:1 on white) — this
   is the same kind of message, just the one Django emits itself instead
   of the one the template writes. */
.staff__form .errorlist {
  list-style: none;
  margin: 0 0 .4rem;
  padding: 0;
  color: #8a1c1c;
  font-weight: 700;
  font-size: .92rem;
}

/* The submit button has no class of its own in the template — it isn't
   part of `as_p` — so it is matched by type and given the same look as
   `.staff__button` above, since it is the same action in the same
   section. */
.staff__form button[type="submit"] {
  display: inline-block;
  background: var(--zelena);
  color: #fff;
  border: none;
  font: inherit;
  font-weight: 700;
  padding: .7rem 1.1rem;
  border-radius: 8px;
  cursor: pointer;
}

/* Phone: aktuality is a list of things to act on — open one, publish it,
   delete it — not data anyone compares across a row, so a narrow column
   gets a stacked card instead of a horizontal scroll. At 375px the
   4-column table left the date breaking across three lines and the
   title wrapping hard against it.
   Scoped to the same 36rem "phone" breakpoint the rest of the site uses
   (see above); nothing here touches a selector outside this block, so
   the table above it is exactly what it was. */
@media (max-width: 36rem) {
  .staff__list,
  .staff__list tbody {
    display: block;
  }
  .staff__list tr {
    display: block;
    padding-block: .6rem;
    border-bottom: 1px solid var(--line);
  }
  .staff__list td {
    display: block;
    padding: .1rem 0;
    border-bottom: 0;
  }
  /* Date and state read as one line — the second half of the "block
     with its title, then its date and state" the row becomes. */
  .staff__list td:nth-child(2),
  .staff__list td:nth-child(3) {
    display: inline-block;
  }
  .staff__list td:nth-child(2)::after {
    content: " — ";
  }
  /* The header row names columns a sighted phone reader already reads
     off each stacked card — showing it here would just be a sixth,
     label-only card above the real rows. It stays for a screen reader,
     which still needs it, using the same clip technique as
     .visually-hidden above rather than `display: none`, which would
     drop it from the accessibility tree too. */
  .staff__list thead {
    position: absolute; width: 1px; height: 1px;
    overflow: hidden; clip-path: inset(50%); white-space: nowrap;
  }
}

/* "Teraz" beside the publication date. Sits on the same line as the two
   inputs the `:has()` row above puts side by side, so it reads as part of
   that field rather than as another control in the form. Quieter than the
   save button on purpose: it fills a field in, it does not do anything. */
.staff__now {
  align-self: center;
  background: none;
  border: 1px solid var(--line);
  border-radius: 6px;
  padding: .45rem .8rem;
  font: inherit;
  color: var(--ink);
  cursor: pointer;
  white-space: nowrap;
}
.staff__now:hover { background: var(--zelena-sv); border-color: var(--zelena); }
