/* innerlumio base layer — reset, elements, prose and the layout shell.

   Semantic tokens only (see tokens.css). If a value here is a raw hex or a
   primitive `--navy-*`/`--gold-*`, that is a bug: it breaks the indirection
   that lets `.surface-navy` invert a whole block without touching components.

   Governing line: "sober structure, warm execution" — restraint in layout,
   type and rules; warmth arrives from photography and writing. So: no
   gradients, no shadows, no rounded cards, no decorative flourishes. */

/* ---------- *
 * 1. Reset    *
 * ---------- */

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

body,
h1,
h2,
h3,
h4,
p,
figure,
blockquote,
dl,
dd,
ul,
ol {
  margin: 0;
}

ul,
ol {
  padding: 0;
}

img,
svg {
  display: block;
  max-width: 100%;
  height: auto;
}

/* ------------------------- *
 * 2. Document and base type  *
 * ------------------------- */

html {
  /* No smooth scrolling: the motion policy allows colour and opacity only. */
  -webkit-text-size-adjust: 100%;
}

body {
  background-color: var(--surface);
  color: var(--on-surface);
  font-family: var(--font-prose);
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  font-weight: 400;
  -webkit-font-smoothing: antialiased;
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

/* Ragged right, never justified — justification opens rivers in Czech, which
   sets long words and stacks marks high. */
p,
li,
dd,
dt,
figcaption {
  text-wrap: pretty;
}

h1,
h2,
h3,
h4 {
  font-family: var(--font-prose);
  color: var(--on-surface);
  text-wrap: balance;
}

h1 {
  font-size: var(--fs-h1);
  line-height: var(--lh-h1);
  letter-spacing: var(--ls-h1);
  font-weight: 700;
}

h2 {
  font-size: var(--fs-h2);
  line-height: var(--lh-h2);
  font-weight: 700;
}

h3 {
  font-size: var(--fs-h3);
  line-height: var(--lh-h3);
  font-weight: 500;
}

/* h4 has no entry in the #109 scale — it sits between h3 and body, and takes
   weight rather than size so the hierarchy stays legible without a fifth step. */
h4 {
  font-size: var(--fs-body);
  line-height: var(--lh-h3);
  font-weight: 700;
}

/* In-paragraph emphasis is weight 500, never italic: Alegreya's italic is
   strongly calligraphic and too loud inside a running line (#109 handoff §5). */
strong,
b {
  font-weight: 500;
}

em,
i {
  font-style: italic;
}

small {
  font-size: var(--fs-small);
  line-height: var(--lh-small);
}

code,
kbd,
samp,
pre {
  font-family: ui-monospace, "Cascadia Mono", "Segoe UI Mono", Menlo, monospace;
  font-size: 0.9em;
}

/* ---------- *
 * 3. Links    *
 * ---------- */

/* Prose links take the accent at 3.23:1 — below the 4.5:1 link text requires.
   A knowing WCAG AA (1.4.3) failure, decided 2026-07-30 for brand cohesion.
   The underline is therefore LOAD-BEARING, not decoration: it is what keeps
   links off colour alone so 1.4.1 still passes. Do not remove it. */
a {
  color: var(--link);
  text-decoration: underline;
  text-decoration-thickness: var(--bw-hair);
  text-underline-offset: 3px;
  transition:
    color var(--motion-duration) var(--motion-easing),
    text-decoration-color var(--motion-duration) var(--motion-easing);
}

a:hover {
  color: var(--link-hover);
  text-decoration-thickness: var(--bw-rule);
}

/* ------------------------------------------- *
 * 4. Focus — one ring, everywhere, never removed *
 * ------------------------------------------- */

:focus-visible {
  outline: var(--bw-focus) solid var(--focus);
  outline-offset: 2px;
}

/* ----------- *
 * 5. Motion    *
 * ----------- */

/* Policy: colour and opacity only, one duration, no transforms, no parallax,
   no scroll-triggered animation. Anything that moves the page is out. */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* ------------------- *
 * 6. Layout shell      *
 * ------------------- */

.shell {
  width: 100%;
  max-width: var(--page-max);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.site-header {
  border-bottom: var(--bw-hair) solid var(--divider);
}

.site-header__inner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--s4) var(--s6);
  padding-block: var(--s5);
}

.site-header__mark {
  display: block;
  text-decoration: none;
}

.site-header__mark img {
  width: 175px;
}

.site-header__end {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s4) var(--s5);
}

/* Nav is interface, not prose — Lato, and NOT the accent colour: gold is
   display and accent only on light surfaces, prose links being the one
   decided exception. */
.site-nav ul {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s4) var(--s5);
  list-style: none;
}

.site-nav a,
.lang-switch a {
  font-family: var(--font-ui);
  font-size: var(--fs-ui);
  line-height: var(--lh-ui);
  font-weight: 700;
  color: var(--on-surface);
  text-decoration: none;
}

.site-nav a:hover,
.lang-switch a:hover {
  color: var(--on-surface);
  text-decoration: underline;
  text-decoration-thickness: var(--bw-rule);
  text-underline-offset: 4px;
}

.site-nav a[aria-current="page"] {
  text-decoration: underline;
  text-decoration-thickness: var(--bw-rule);
  text-underline-offset: 4px;
}

.lang-switch {
  padding-inline-start: var(--s5);
  border-inline-start: var(--bw-hair) solid var(--divider);
}

main {
  flex: 1 0 auto;
  padding-block: var(--s9) var(--s10);
}

.site-footer {
  padding-block: var(--s9);
}

.site-footer__inner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--s5);
}

.site-footer img {
  width: 138px;
}

@media (max-width: 480px) {
  .site-header__inner {
    gap: var(--s4);
  }

  .site-header__mark img {
    width: 150px;
  }

  main {
    padding-block: var(--s7) var(--s9);
  }
}

/* ---------------------------------------- *
 * 7. Prose — the reading column and rhythm   *
 * ---------------------------------------- */

/* `.shell`, not `.prose`, owns the column width: --page-max minus the gutters
   lands within a few characters of the 66ch target at the shipped body size,
   which is what lets the wordmark, the nav and the text below them share one
   left edge. `.prose` therefore carries rhythm and element styling only, and
   caps the measure just for the case where it is used inside a wider block. */
.prose:not(.shell) {
  max-width: min(var(--measure), var(--measure-max));
  margin-inline: auto;
}

/* Vertical rhythm: one paragraph gap, applied at any depth — pages wrap their
   content in <section> and the markdown renderer nests further, so a
   direct-child rule would silently miss most of the page. Margins only, never
   a blank line and never a text-indent.

   `:where()`, not `:is()`, and that is load-bearing: `:is()` contributes its
   most specific argument, so two of them make this (0,1,2) — enough to beat
   any single-class component rule and silently swallow its spacing. `:where()`
   contributes nothing, leaving (0,1,0): a default that a component overrides
   just by naming itself. Every rhythm rule below follows the same convention. */
.prose
  :where(p, ul, ol, dl, figure, blockquote, table, form, hr)
  + :where(p, ul, ol, dl, figure, blockquote, table, form, hr) {
  margin-block-start: var(--s5);
}

/* A heading that opens a section already has the section gap above it. */
.prose section > :first-child {
  margin-block-start: 0;
}

.prose h1 {
  margin-block-end: var(--s4);
}

.prose h2 {
  margin-block-start: var(--s7);
  margin-block-end: var(--s4);
}

.prose h3 {
  margin-block-start: var(--s6);
  margin-block-end: var(--s3);
}

.prose h4 {
  margin-block-start: var(--s5);
  margin-block-end: var(--s3);
}

/* Sections are the top-level blocks on most pages; the gap between them is a
   step up from the paragraph gap, and no rule is drawn — the space does it. */
.prose > section + section {
  margin-block-start: var(--s9);
}

.prose ul,
.prose ol {
  padding-inline-start: var(--s6);
}

.prose :where(li) + :where(li) {
  margin-block-start: var(--s3);
}

.prose ul {
  list-style: disc;
}

.prose ol {
  list-style: decimal;
}

.prose dl {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: var(--s3) var(--s5);
}

.prose dt {
  margin: 0;
  font-family: var(--font-ui);
  font-size: var(--fs-ui);
  line-height: var(--lh-body);
  font-weight: 700;
  color: var(--on-surface-muted);
}

.prose dd {
  margin: 0;
}

.prose table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--fs-small);
  line-height: var(--lh-small);
}

.prose caption {
  font-size: var(--fs-caption);
  line-height: var(--lh-caption);
  color: var(--on-surface-muted);
  text-align: start;
  margin-block-end: var(--s2);
}

.prose th,
.prose td {
  text-align: start;
  padding: var(--s3) var(--s4);
  border-block-end: var(--bw-hair) solid var(--divider);
}

.prose th {
  font-family: var(--font-ui);
  font-size: var(--fs-ui);
  font-weight: 700;
}

.prose tbody tr:nth-child(even) {
  background-color: var(--surface-alt);
}

/* The lead-in above a pull quote is tighter than the paragraph gap and the
   space below it is wider, so the quote reads as belonging to the text above.
   One selector is enough now that the rhythm rule is `:where()`-scoped. */
.prose blockquote {
  padding-inline-start: var(--s6);
  border-inline-start: var(--bw-rule) solid var(--divider);
  font-size: var(--fs-quote);
  line-height: var(--lh-quote);
  font-style: italic;
  margin-block: var(--s3) var(--s7);
}

.prose figcaption,
.prose .caption {
  font-family: var(--font-ui);
  font-size: var(--fs-caption);
  line-height: var(--lh-caption);
  color: var(--on-surface-muted);
}

.prose hr {
  border: 0;
  border-block-start: var(--bw-hair) solid var(--divider);
  margin-block: var(--s8);
}

/* Standfirst / lead paragraph. */
.prose .lead {
  font-size: var(--fs-lead);
  line-height: var(--lh-lead);
  font-style: italic;
}

/* Eyebrow — the one place all-caps is allowed, and it belongs to Lato:
   all-caps Czech in Alegreya collides accents with the cap line. */
.eyebrow {
  font-family: var(--font-ui);
  font-size: var(--fs-eyebrow);
  line-height: var(--lh-eyebrow);
  letter-spacing: var(--ls-eyebrow);
  font-weight: 700;
  text-transform: uppercase;
  color: var(--on-surface-muted);
}

/* Hyphenate only where the measure has collapsed to the viewport. Off on
   desktop, where a 66ch measure sets cleanly ragged. */
@media (max-width: 480px) {
  .prose p,
  .prose li {
    hyphens: auto;
  }
}

/* ------------- *
 * 8. Buttons     *
 * ------------- */

/* The primary button takes the OPPOSITE surface's dominant colour: navy fill
   with a paper label on light (14.19:1), gold fill with a navy label inside
   `.surface-navy` (7.55:1). A gold fill on the light surface is ruled out —
   paper on gold-600 is 3.23:1 and even navy on gold-600 is 4.40:1, just short.
   Both come out of --button-fill / --on-button, so the inversion is automatic. */
.button,
.cta-button,
button {
  display: inline-block;
  font-family: var(--font-ui);
  font-size: var(--fs-ui);
  line-height: var(--lh-ui);
  font-weight: 700;
  padding: var(--s3) var(--s6);
  border: var(--bw-hair) solid transparent;
  border-radius: var(--radius-control);
  background-color: var(--button-fill);
  color: var(--on-button);
  text-align: center;
  text-decoration: none;
  cursor: pointer;
  transition:
    background-color var(--motion-duration) var(--motion-easing),
    color var(--motion-duration) var(--motion-easing),
    border-color var(--motion-duration) var(--motion-easing);
}

.button:hover,
.cta-button:hover,
button:hover {
  background-color: var(--button-fill-hover);
  color: var(--on-button-hover);
  text-decoration: none;
}

/* Secondary: the same shape with no fill, so it can sit beside a primary
   without competing. The border is --border-strong, which is the token that
   carries the 3:1 non-text requirement (--divider deliberately does not). */
.button--secondary {
  background-color: transparent;
  color: var(--on-surface);
  border-color: var(--border-strong);
}

.button--secondary:hover {
  background-color: var(--surface-alt);
  color: var(--on-surface);
  border-color: var(--on-surface);
}

.button[disabled],
button[disabled],
.button[aria-disabled="true"] {
  background-color: var(--surface-alt);
  color: var(--on-surface-muted);
  border-color: var(--divider);
  cursor: not-allowed;
}

/* ------------------ *
 * 9. Forms            *
 * ------------------ */

.field {
  display: grid;
  gap: var(--s2);
}

.field + .field {
  margin-block-start: var(--s5);
}

.field > label {
  font-family: var(--font-ui);
  font-size: var(--fs-ui);
  line-height: var(--lh-ui);
  font-weight: 700;
}

/* 17px is the floor for anything meant to be read, and also keeps iOS from
   zooming the viewport when a field takes focus. */
.field input,
.field select,
.field textarea {
  width: 100%;
  font-family: var(--font-ui);
  font-size: var(--fs-small);
  line-height: var(--lh-ui);
  color: var(--on-surface);
  background-color: var(--surface);
  padding: var(--s3);
  border: var(--bw-hair) solid var(--border-strong);
  border-radius: var(--radius-control);
  transition: border-color var(--motion-duration) var(--motion-easing);
}

.field input:hover,
.field select:hover,
.field textarea:hover {
  border-color: var(--on-surface);
}

.field input[aria-invalid="true"],
.field select[aria-invalid="true"],
.field textarea[aria-invalid="true"] {
  border-color: var(--error);
  border-width: var(--bw-rule);
}

/* Not caption size, deliberately: this class carries the data-collection
   disclosure under the booking form and the payment instructions on the status
   page. That is small print, but it is print people have to be able to read —
   `--fs-small` is the documented floor for anything meant to be read, and
   `--fs-caption` is for photo and table captions. Muted is fine here: 5.97:1
   on paper, measured in Brand-tokens.md. */
.field-help {
  font-family: var(--font-ui);
  font-size: var(--fs-small);
  line-height: var(--lh-small);
  color: var(--on-surface-muted);
}

/* Radio-group questions (health screening, #10): the base .field input rule
   is sized for full-width text controls, so radio inputs need their
   intrinsic size back rather than stretching to the field's width. */
.field-radio-group {
  display: flex;
  gap: var(--s5);
}

.field-radio-option {
  display: inline-flex;
  align-items: center;
  gap: var(--s2);
  font-weight: 400;
}

.field-radio-option input {
  width: auto;
}

/* Messages carry their state in a rule and in the text colour, never in a
   filled panel: --error is 4.61:1 and --success 4.66:1 on the page surface,
   but both fall below 4.5 once a --surface-alt fill sits behind them. */
.message {
  font-family: var(--font-ui);
  font-size: var(--fs-small);
  line-height: var(--lh-small);
  padding-inline-start: var(--s4);
  border-inline-start: var(--bw-rule) solid var(--divider);
}

.message--error {
  color: var(--error);
  border-inline-start-color: var(--error);
}

.message--success {
  color: var(--success);
  border-inline-start-color: var(--success);
}

/* Reserve the widget's rendered height so the submit button below it doesn't
   jump when Turnstile finishes loading. */
.cf-turnstile {
  min-height: 65px;
  margin-block: var(--s5);
}

/* ------------------------------ *
 * 10. Event listing and states     *
 * ------------------------------ */

/* Qualified with `ul` so it outranks `.prose ul`'s disc + indent — the event
   listing is a set of cards that happens to be a list, not a bulleted one. */
ul.event-list {
  list-style: none;
  padding-inline-start: 0;
  display: grid;
  gap: var(--s7);
  margin-block-start: var(--s7);
}

/* The grid `gap` is the only thing spacing the cards. Without this the list
   rhythm's margin would add to it rather than collapse into it — margins never
   collapse in a grid formatting context — and every gap would come out 12px
   too wide. */
.event-list > li {
  margin-block-start: 0;
}

.event-card {
  padding-block-start: var(--s5);
  border-block-start: var(--bw-rule) solid var(--on-surface);
}

.event-card h2 {
  font-size: var(--fs-h3);
  line-height: var(--lh-h3);
  font-weight: 700;
  margin: 0;
}

/* Structural links — card titles, like nav — stay in the ink colour. Gold is
   reserved for prose links (the one decided exception) so it keeps meaning
   "this is a link inside a sentence" rather than "this is clickable". */
.event-card h2 a {
  color: var(--on-surface);
  text-decoration-thickness: var(--bw-hair);
}

.event-card h2 a:hover {
  text-decoration-thickness: var(--bw-rule);
}

.event-card__meta {
  font-family: var(--font-ui);
  font-size: var(--fs-ui);
  line-height: var(--lh-body);
  color: var(--on-surface-muted);
  margin-block-start: var(--s2);
}

/* Availability. Deliberately NOT the eyebrow treatment: all-caps + 0.18em on
   a lowercase Czech phrase (e.g. "Volná místa") reads as shouting. Weight and
   colour carry it. Only renders for the sold-out/cancelled states — #228
   dropped the available-state badge entirely, not just its numeric count. */
.badge {
  display: inline-block;
  font-family: var(--font-ui);
  font-size: var(--fs-ui);
  line-height: var(--lh-ui);
  font-weight: 700;
}

/* Only as a block of its own — inside a <dd> the badge sits on the grid row
   and must not push it. */
p.badge {
  margin-block-start: var(--s3);
}

.badge--soldout {
  color: var(--on-surface-muted);
}

.badge--cancelled {
  color: var(--error);
}

/* Booking status. The state word takes the semantic colour; the rest of the
   line stays in the ink so the page doesn't shout. */
.status strong {
  font-weight: 700;
}

.status--confirmed strong {
  color: var(--success);
}

.status--expired strong,
.status--cancelled strong {
  color: var(--error);
}

/* QR payment code. Left-aligned in the column at a size that scans reliably
   from a phone held at arm's length. */
.qr {
  margin-block: var(--s5);
}

.qr svg {
  width: 100%;
  max-width: 240px;
  height: auto;
}

/* The generated code ships a white backing rect; recolour it to the page
   surface so the QR sits on the paper instead of in a white box. The modules
   are a <path> and stay black — scan contrast is not negotiable. */
.qr svg rect {
  fill: var(--surface);
}

/* ------------------- *
 * 11. Team photos       *
 * ------------------- */

/* Floats need a containing block that clips to content height, or a tall
   photo bleeds into the next section instead of stacking above it. */
.prose > section {
  display: flow-root;
}

.team-photo {
  width: 220px;
  margin-block-end: var(--s5);
}

.team-photo--left {
  float: left;
  margin-inline-end: var(--s6);
}

.team-photo--right {
  float: right;
  margin-inline-start: var(--s6);
}

@media (max-width: 480px) {
  .team-photo {
    float: none;
    width: 100%;
    max-width: 220px;
    margin-inline: 0;
  }
}
