/* ==========================================================================
   IVV „Weinkeller" design layer on top of Pico v2
   Warm cream/charcoal neutrals, wine-purple accent (grape logo),
   serif display headings. No webfonts, no external requests.

   Every :hover rule sits inside @media (hover: hover). On a touchscreen the
   hover state latches when you tap and stays until you touch something else,
   so a tapped card kept its lift and a tapped button kept its tint.
   ========================================================================== */

/* ---- Palette -------------------------------------------------------- */

/* Match Pico's own theme-selector specificity so these actually win */
[data-theme=light],
:root:not([data-theme=dark]) {
  --ivv-wine: #722b71;
  --ivv-wine-deep: #5c2159;
  /* Ink for text sitting ON a wine ground. Deliberately not
     --pico-background-color: Pico sets that to `transparent` on every plain
     <a> (:where(a:not([role=button]))), and it inherits, so anything inside a
     link that uses it comes out invisible. */
  --ivv-on-wine: #faf7f2;
  --ivv-serif: ui-serif, "Iowan Old Style", Palatino, "New York", Georgia, serif;

  --pico-background-color: #faf7f2;
  --pico-color: #2b2126;
  --pico-h1-color: #2b2126;
  --pico-h2-color: #2b2126;
  --pico-h3-color: #372c32;
  --pico-muted-color: #6f6367;            /* 5.37:1 on the page, 5.08:1 on a chip */
  --pico-muted-border-color: #e9e0d7;
  --pico-border-radius: 0.5rem;

  --pico-primary: #722b71;
  --pico-primary-background: #722b71;
  --pico-primary-border: #722b71;
  --pico-primary-underline: rgba(114, 43, 113, 0.35);
  --pico-primary-hover: #5c2159;
  --pico-primary-hover-background: #5c2159;
  --pico-primary-hover-border: #5c2159;
  --pico-primary-hover-underline: #5c2159;
  --pico-primary-focus: rgba(114, 43, 113, 0.65);  /* 3.61:1 — the focus ring has to be seen */
  --pico-primary-inverse: #fff;

  --pico-card-background-color: #fffdfa;
  --pico-card-border-color: #e9e0d7;
  --pico-card-box-shadow: 0 1px 2px rgba(59, 34, 51, 0.05);
  --pico-card-sectioning-background-color: #fffdfa;

  --pico-form-element-background-color: #fff;
  --pico-form-element-border-color: #9b8d7e;  /* 3.23:1 — a field has to look like a field */
  --pico-form-element-focus-color: var(--ivv-wine);

  --pico-mark-background-color: #f3e7f3;
  --pico-mark-color: #5c2159;

  --ivv-chip-bg: #f6f0e9;
  --ivv-chip-border: #e2d7cb;
  --ivv-ok: #3e7a3e;
  --ivv-ok-bg: #e9f2e6;
  --ivv-danger: #a23b3b;
  --ivv-danger-bg: #f7e9e7;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme]):not([data-theme=light]) {
    --ivv-wine: #c08bbb;
    --ivv-wine-deep: #d3a6ce;
    --ivv-on-wine: #1d181b;

    --pico-background-color: #1d181b;
    --pico-color: #ece5e9;
    --pico-h1-color: #f2ebef;
    --pico-h2-color: #f2ebef;
    --pico-h3-color: #e5dbe1;
    --pico-muted-color: #a99ba3;
    --pico-muted-border-color: #3a3237;

    --pico-primary: #c08bbb;
    --pico-primary-background: #8a4187;
    --pico-primary-border: #8a4187;
    --pico-primary-underline: rgba(192, 139, 187, 0.4);
    --pico-primary-hover: #d3a6ce;
    --pico-primary-hover-background: #9a4e96;
    --pico-primary-hover-border: #9a4e96;
    --pico-primary-focus: rgba(192, 139, 187, 0.7);  /* 3.77:1 */
    --pico-primary-inverse: #fff;

    --pico-card-background-color: #272025;
    --pico-card-border-color: #3a3237;
    --pico-card-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);
    --pico-card-sectioning-background-color: #272025;

    --pico-form-element-background-color: #211b1f;
    --pico-form-element-border-color: #7d707c;  /* 3.61:1 */
    --pico-form-element-focus-color: var(--ivv-wine);

    --pico-mark-background-color: #3c2b3a;
    --pico-mark-color: #e5cde2;

    --ivv-chip-bg: #2e262b;
    --ivv-chip-border: #453b41;
    --ivv-ok: #8fc48a;
    --ivv-ok-bg: #263323;
    --ivv-danger: #dd9089;
    --ivv-danger-bg: #3b2624;
  }
}

/* ---- Typography ------------------------------------------------------ */

h1, h2, h3, h4, .brand {
  font-family: var(--ivv-serif);
  letter-spacing: 0.01em;
  font-weight: 600;
}
h1 { font-size: 2rem; margin-bottom: 1.25rem; }
h1 a, h2 a, h3 a { text-decoration: none; }
@media (hover: hover) {
  h1 a:hover, h2 a:hover, h3 a:hover { text-decoration: underline; text-underline-offset: 4px; text-decoration-thickness: 1px; }
}

/* ---- Icons (inline SVG sprite, see templates/_icons.html) ------------ */

.icon {
  width: 1em;
  height: 1em;
  vertical-align: -0.125em;
  opacity: 0.62;
  flex-shrink: 0;
}

/* ---- Navigation ------------------------------------------------------ */

body > nav {
  position: sticky;
  top: 0;
  z-index: 10;
  border-bottom: 1px solid var(--pico-muted-border-color);
  margin-bottom: 0.75rem;
  background: color-mix(in srgb, var(--pico-background-color) 85%, transparent);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
}
.brand {
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  font-size: 1.15rem;
  text-decoration: none;
  /* Wine, stated outright. This used to read `var(--pico-color) !important`,
     which looks like the ink from :root but is not: Pico redefines
     --pico-color *on the anchor* (:where(a:not([role=button]))), and .brand is
     either that anchor or a span inheriting from it — so it resolved to the
     primary either way, and the !important had no competitor to beat. Same
     shadowing trap as the --ivv-on-wine note above. For ink instead, this
     needs a token Pico does not shadow, not --pico-color. */
  color: var(--ivv-wine);
  min-width: 0;
}
.brand img { width: 26px; height: 26px; border-radius: 6px; flex-shrink: 0; }
.brand-name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* Small screens: tighter nav padding and a slightly smaller brand so the
   full club name usually fits next to the toggle without ellipsizing. */
@media (max-width: 575.98px) {
  body > nav {
    --pico-nav-element-spacing-vertical: 0.4rem;
    --pico-nav-element-spacing-horizontal: 0.3rem;
  }
  .brand { font-size: 1rem; gap: 0.45rem; }
}

/* ---- Event cards ----------------------------------------------------- */

article {
  border: 1px solid var(--pico-card-border-color);
}

.event-card {
  position: relative;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 1.1rem;
  padding: 1.1rem 1.25rem;
  transition: border-color 0.15s ease, box-shadow 0.15s ease, transform 0.15s ease;
}
@media (hover: hover) {
  .event-card:hover {
    border-color: color-mix(in srgb, var(--ivv-wine) 45%, var(--pico-card-border-color));
    box-shadow: 0 4px 14px rgba(59, 34, 51, 0.09);
    transform: translateY(-1px);
  }
}
/* Events the member is already signed up for get a wine edge accent so they
   stand out at a glance in the full list. Pseudo-element (not border-left) so
   it survives the hover border-color change. */
.event-card.is-joined::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 3px;
  border-radius: var(--pico-border-radius) 0 0 var(--pico-border-radius);
  background: var(--ivv-wine);
}

.event-card .event-title { margin: 0 0 0.2rem; font-size: 1.2rem; line-height: 1.3; }
.event-card .event-title a { text-decoration: none; color: inherit; }
/* The whole card is one tap target: the title's link stretches over it, and
   nothing is lifted back out. The card deliberately contains no other link —
   a venue link here used to swallow taps meant for the event. */
.event-card .event-title a::after { content: ""; position: absolute; inset: 0; }

.date-block {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  min-width: 3.4rem;
  height: 3.6rem;
  border: 1px solid var(--ivv-chip-border);
  border-radius: var(--pico-border-radius);
  background: var(--ivv-chip-bg);
  line-height: 1.1;
  align-self: start;
}
.date-block .date-day {
  font-family: var(--ivv-serif);
  font-size: 1.45rem;
  font-weight: 600;
  color: var(--ivv-wine);
}
.date-block .date-month {
  font-size: 0.68rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--pico-muted-color);
}

.meta {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  margin: 0;
  color: var(--pico-muted-color);
  font-size: 0.9rem;
  line-height: 1.55;
}
.meta a { color: inherit; text-decoration-color: var(--pico-muted-border-color); }
@media (hover: hover) {
  .meta a:hover { color: var(--ivv-wine); }
}
.meta-row { display: flex; gap: 0.45rem; align-items: baseline; }
.meta-row .icon { flex-shrink: 0; position: relative; top: 0.08em; }
/* let row text shrink and wrap under itself instead of stretching the card */
.meta-row > span { min-width: 0; }
.event-card > div:last-child { min-width: 0; }
.nowrap { white-space: nowrap; }


/* ---- Chips & badges --------------------------------------------------- */

.chip {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  padding: 0.12rem 0.6rem;
  border-radius: 999px;
  border: 1px solid var(--ivv-chip-border);
  background: var(--ivv-chip-bg);
  font-size: 0.78rem;
  font-weight: 600;
  color: var(--pico-color);
  white-space: nowrap;
  vertical-align: middle;
}
.chip-price {
  color: var(--ivv-wine);
  border-color: color-mix(in srgb, var(--ivv-wine) 30%, transparent);
  /* A line of its own below the meta block, on the card and the detail page:
     flex makes it block-level so nothing shares the line, fit-content keeps
     it hugging its text instead of stretching. */
  display: flex;
  width: fit-content;
  margin-top: 0.45rem;
}
.chip-joined { color: var(--ivv-ok); background: var(--ivv-ok-bg); border-color: color-mix(in srgb, var(--ivv-ok) 30%, transparent); }
.chip-cancelled { color: var(--ivv-danger); background: var(--ivv-danger-bg); border-color: color-mix(in srgb, var(--ivv-danger) 30%, transparent); }
.chip .icon { opacity: 0.9; }

/* ---- Nav filter toggle (all events / only mine) ------------------------ */

/* One layout box on every page. The header differs only in what is a link —
   the whole bar on the list, the brand and the glass separately elsewhere —
   so building both from the same boxes is what stops the glass moving when
   you open an event. */
body > nav > .nav-bar {
  /* width, not just flex-grow: the bar has to span whether or not the <nav>
     is behaving as a flex container, otherwise space-between has no free
     space to distribute and the glass collapses next to the club name. */
  width: 100%;
  flex: 1 1 auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  min-width: 0;          /* keeps the brand's ellipsis chain intact */
  /* Height has to match across pages too, or the sticky bar jumps. Wide
     screens are driven by Pico's nav spacing, narrow ones by the glass. */
  padding-block: var(--pico-nav-element-spacing-vertical);
  min-height: calc(44px + 0.5rem);
  text-decoration: none;
  color: var(--pico-color);
}
/* The glass keeps a 44px touch box, and centring the 1.4rem icon inside it is
   what sets the icon's distance from the container edge — identically on both
   headers, because it is the same box. */
body > nav .nav-glass {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 44px;
  min-height: 44px;
  flex-shrink: 0;
  text-decoration: none;
  color: var(--ivv-wine);
}
@media (hover: hover) {
  body > nav .nav-glass:hover { opacity: 0.75; }
}
body > nav .nav-glass .icon { width: 1.4rem; height: 1.4rem; opacity: 1; }
.filter-icon { position: relative; display: inline-flex; }
.filter-count {
  position: absolute;
  top: -0.3rem;
  right: -0.6rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 1rem;
  height: 1rem;
  padding: 0 0.22rem;
  border-radius: 999px;
  background: var(--ivv-wine);
  color: var(--ivv-on-wine);
  font-size: 0.7rem;
  font-weight: 700;
  line-height: 1;
  font-variant-numeric: tabular-nums;
}

/* ---- Back link (subpages, above the heading) --------------------------- */

.back-link {
  display: inline-block;
  margin-bottom: 0.6rem;
  padding: 0.35rem 0;   /* widens the tap target without visual bulk */
  color: var(--pico-muted-color);
  font-size: 0.9rem;
  font-weight: 600;
  text-decoration: none;
}
@media (hover: hover) {
  .back-link:hover { color: var(--ivv-wine); }
}

/* ---- Buttons & forms --------------------------------------------------- */

/* No font-weight override here. There used to be `button, [role="button"]
   { font-weight: 600 }`, which reached the two <a role="button"> controls but
   never a real <button>: Pico weights buttons through
   `[role=button],[type=button],[type=reset],[type=submit],button`, so a
   <button type="submit"> is matched by an attribute selector (0,1,0) that
   outranks a bare `button` (0,0,1). The anchors tied on specificity and won on
   order. Result was "Herunterladen" rendering bolder than "Drucken" beside it.
   Pico's own 400 now applies to all nine controls. */
button.secondary, [role="button"].secondary {
  background: transparent;
  border-color: var(--pico-form-element-border-color);
  color: var(--pico-muted-color);
}
@media (hover: hover) {
  button.secondary:hover, [role="button"].secondary:hover {
    background: var(--ivv-chip-bg);
    border-color: var(--pico-muted-color);
    color: var(--pico-color);
  }
}
[role="button"].outline-wine, button.outline-wine {
  background: transparent;
  border-color: color-mix(in srgb, var(--ivv-wine) 45%, transparent);
  color: var(--ivv-wine);
}
@media (hover: hover) {
  [role="button"].outline-wine:hover, button.outline-wine:hover {
    background: color-mix(in srgb, var(--ivv-wine) 8%, transparent);
    border-color: var(--ivv-wine);
  }
}

form.inline-edit {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  align-items: center;
  margin-bottom: 1rem;
}
form.inline-edit select { width: auto; margin-bottom: 0; }
form.inline-edit button { width: auto; margin-bottom: 0; }

.actions {
  display: flex;
  gap: 0.6rem;
  flex-wrap: wrap;
  align-items: center;
}
.actions form { margin: 0; }
.actions button, .actions [role="button"] { width: auto; margin: 0; }

/* ---- Success / status notes ------------------------------------------- */

.status-ok {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  color: var(--ivv-ok);
  font-weight: 600;
}
.status-ok .icon { opacity: 1; }

/* ---- Payment card ------------------------------------------------------ */

.payment-card {
  background: color-mix(in srgb, var(--ivv-wine) 4%, var(--pico-card-background-color));
  border-color: color-mix(in srgb, var(--ivv-wine) 22%, var(--pico-card-border-color));
}
.amount {
  font-family: var(--ivv-serif);
  font-size: 1.7rem;
  font-weight: 600;
  color: var(--ivv-wine);
  line-height: 1.2;
}
.amount small {
  font-family: var(--pico-font-family-sans-serif);
  font-size: 0.85rem;
  font-weight: 400;
  color: var(--pico-muted-color);
}

/* Big standalone Swiss QR code: white frame doubles as quiet zone */
.qr-code-img {
  display: block;
  width: 100%;
  max-width: 420px;
  background: #fff;
  padding: 0.75rem;
  border: 1px solid var(--pico-card-border-color);
  border-radius: 0.4rem;
  margin-bottom: 0.9rem;
}
.payment-details { margin-bottom: 0.9rem; }
.select-all { -webkit-user-select: all; user-select: all; }
/* Copy buttons sit beside IBAN and Mitteilung. They ship hidden and the script
   reveals them only where the async clipboard API exists; .select-all stays the
   no-JS path. 44px keeps the tap target honest without inflating the row, so
   the padding does the work and a negative margin absorbs it. */
.copy-btn {
  width: auto;
  min-width: 44px;
  min-height: 44px;
  margin: -0.7rem 0 -0.7rem 0.1rem;
  padding: 0 0.5rem;
  border: 0;
  background: none;
  color: var(--pico-muted-color);
  line-height: 1;
}
@media (hover: hover) {
  .copy-btn:hover { background: none; color: var(--ivv-wine); }
}
.copy-btn .icon { opacity: 1; }
.copy-btn.is-copied { color: var(--ivv-ok); }
/* Announced to screen readers, invisible on screen. Not display:none, which
   would keep it out of the accessibility tree and defeat aria-live. */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}
#zahlung details { margin-bottom: 0.5rem; }
/* Pico gives every <summary> a rotating chevron, but floats it right — on a
   full-width card it lands metres from the label and reads as decoration
   rather than a control. Making the summary a flex row and ordering the
   pseudo-element first puts it immediately before the text, where it says
   "this opens". float is ignored on flex items, so Pico's rule needs no
   undoing; its rotate(-90deg) → rotate(0) transition still runs on open. */
#zahlung summary {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  color: var(--pico-muted-color);
  font-size: 0.9rem;
}
#zahlung summary::after { order: -1; margin-inline-start: 0; }
.print-only { display: none !important; }

/* Swiss QR-Rechnung: white frame so the QR scans in dark mode */
.qr-bill-img {
  display: block;
  width: 100%;
  max-width: 700px;
  background: #fff;
  border-radius: 0.4rem;
  border: 1px solid var(--pico-card-border-color);
  padding: 0.4rem;
}

/* ---- Flash messages ---------------------------------------------------- */

article.flash { padding: 0.75rem 1rem; }
article.flash-success { border-left: 4px solid var(--ivv-ok); }
article.flash-error { border-left: 4px solid var(--ivv-danger); }
article.flash-info { border-left: 4px solid var(--ivv-wine); }
/* The border colour alone would be the only difference between a confirmation
   and a failure, so each flash also carries an icon. */
article.flash .icon { opacity: 1; margin-right: 0.35rem; }
article.flash-success .icon { color: var(--ivv-ok); }
article.flash-error .icon { color: var(--ivv-danger); }
article.flash-info .icon { color: var(--ivv-wine); }

/* ---- Form errors ------------------------------------------------------- */

/* Django's as_div emits one <ul class="errorlist"> per field. Unstyled they
   read as ordinary body text in a design that already defines a danger colour. */
.errorlist {
  list-style: none;
  margin: 0.3rem 0 0;
  padding: 0.4rem 0.6rem;
  border-left: 3px solid var(--ivv-danger);
  border-radius: 0 var(--pico-border-radius) var(--pico-border-radius) 0;
  background: var(--ivv-danger-bg);
  color: var(--ivv-danger);
  font-size: 0.9rem;
}
.errorlist li + li { margin-top: 0.2rem; }

/* ---- Hint / footer note ------------------------------------------------ */

.hint { color: var(--pico-muted-color); }
.hint a { color: inherit; }
@media (hover: hover) {
  .hint a:hover { color: var(--ivv-wine); }
}

/* ---- Print: only the QR payment slip ----------------------------------- */

@page { size: A4; margin: 10mm 0; }

@media print {
  body { background: #fff; }
  body > nav, .no-print { display: none !important; }
  .print-only { display: block !important; }
  main.container { max-width: none; padding: 0; }
  article#zahlung {
    margin: 0;
    padding: 0;
    border: none;
    box-shadow: none;
    background: #fff;
  }
  .qr-bill-img { width: 210mm; max-width: none; border: none; border-radius: 0; padding: 0; }
}

/* ---- Motion -------------------------------------------------------------- */

@view-transition { navigation: auto; }
html {
  scroll-behavior: smooth;
  /* Always reserve the scrollbar gutter. Switching between Kommende Anlässe
     and Meine Anmeldungen usually swaps a long, scrolling list for a short
     one; on a desktop with classic scrollbars that changed the viewport
     width, so the container, the cards and the glass in the header all
     jumped sideways and the switch read as the page resizing itself. */
  scrollbar-gutter: stable;
}
#zahlung { scroll-margin-top: 5.5rem; }

button:active, [role="button"]:active { transform: scale(0.985); }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { transition: none !important; animation: none !important; }
  html { scroll-behavior: auto; }
@media (hover: hover) {
    .event-card:hover { transform: none; }
}
  button:active, [role="button"]:active { transform: none; }
  @view-transition { navigation: none; }
}

/* ---- Typographic finesse -------------------------------------------------- */

h1, h2, h3 { text-wrap: balance; }
.meta, article p { text-wrap: pretty; }
.chip, .amount, .date-block { font-variant-numeric: tabular-nums; }
::selection { background: color-mix(in srgb, var(--ivv-wine) 22%, transparent); }


/* ---- Fleuron divider ------------------------------------------------------ */

.divider {
  display: flex;
  align-items: center;
  gap: 0.9rem;
  margin: 2.2rem 0 1.4rem;
  color: var(--ivv-wine);
  opacity: 0.75;
  font-size: 0.9rem;
}
.divider::before, .divider::after {
  content: "";
  flex: 1;
  border-top: 1px solid var(--pico-muted-border-color);
}

/* ---- Form comfort ----------------------------------------------------------- */

article form { max-width: 34rem; }
@media (min-width: 576px) {
  /* The primary call to action only. Without the :not() this outranks both
     form.inline-edit button and .actions button — the two rules that exist to
     keep „Ändern“ and „Abmelden“ compact — and stretched them to 11rem. */
  article form:not(.inline-edit) > button[type="submit"]:not(.secondary) {
    width: auto;
    min-width: 11rem;
  }
}

/* ---- Small screens ------------------------------------------------------ */

@media (max-width: 575.98px) {
  h1 { font-size: 1.6rem; }
  .event-card { gap: 0.85rem; padding: 1rem; }
}
