
/* Colour values sampled directly from the live sint-antonius.org (Wix) pages. */
:root {
  --ink: #444444;              /* header/nav charcoal */
  --ink-soft: #59564f;
  /* Neutral greys, at the same lightness as the warm cream tints they replaced. */
  --grey: #dcdcdc;
  --grey-light: #f2f2f2;
  --paper: #ffffff;
  /* Inner pages sit on a flat light grey rather than the live site's blurred photo. Panels
     stay translucent white over it — the content panels a touch more opaque than the title
     banner, so the banner reads as a lighter strip against them. */
  --page-bg: #e9e9e9;
  --panel: rgba(255,255,255,0.93);
  --panel-banner: rgba(255,255,255,0.7);
  --accent: #375b3b;           /* the site's green buttons */
  --accent-ink: #2b4a2e;
  --border: #d8d8d8;
  --text: #222222;
  --text-muted: #767676;
  /* Remarks the app makes about a form. The Serment ochre (#f0a63f) darkened until it carries as
     body text on white — as a badge fill it is unreadable at 13px. */
  /* Dezelfde waarde als in app-css.js, waar ze nagerekend is op 4.58:1 tegen wit. Ze stond hier
     op #a8600a en deed niets: alles wat --note gebruikt zit achter de login, en daar wint de
     definitie uit app-css.js omdat die stylesheet erna komt. Twee waarden onder één naam is een
     val voor wie er later een aanpast. */
  --note: #b45f06;
  --danger: #d64d3f;
  --footer-bg: #888888;
  --footer-text: #eeeeee;
  --content-width: 980px;
  font-family: "Nunito Sans", "Nunito-Sans", sans-serif;
}
* { box-sizing: border-box; }
body {
  margin: 0;
  background: var(--grey-light);
  color: var(--text);
  font-family: "Nunito Sans", "Nunito-Sans", sans-serif;
  font-size: 16px;
  line-height: 1.55;
}
/* Inner pages sit on the background photo rendered as a pale grey wash. The flex column keeps
   the footer at the bottom of short pages instead of leaving the background showing below it. */
.sa-body-inner {
  background: var(--page-bg);
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}
.sa-body-inner .sa-main { flex: 1 0 auto; }
.sa-body-inner .sa-footer { flex-shrink: 0; }
.sa-page-bg {
  /* Inset beyond the viewport so the blur doesn't feather in at the edges. Desaturated and
     held at low opacity over --page-bg, so the photo reads as light grey rather than colour
     — whatever the photo's own tones are. */
  position: fixed; inset: -24px; z-index: -1;
  background-image: url('/background-1.avif');
  background-size: cover;
  background-position: center;
  filter: grayscale(1) blur(4px);
  opacity: 0.35;
}
.sa-page-banner {
  /* width:100% is required because body is a flex column here — an auto cross-axis margin
     disables stretch, which would otherwise shrink this to its text width. */
  width: 100%;
  min-width: 0;
  max-width: var(--content-width);
  margin: 14px auto 0;
  padding: 24px;
  background: var(--panel-banner);
  border-radius: 5px;
  text-align: center;
}
.sa-page-banner h1 {
  font-family: "Montserrat", sans-serif;
  font-weight: 700;
  font-size: 30px;
  letter-spacing: 1.5px;
  color: var(--text);
  margin: 0;
}
h1, h2, h3, h4 {
  font-family: "Montserrat", sans-serif;
  font-weight: 600;
  color: var(--ink);
  margin: 0 0 0.5em;
}
a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; }

.sa-header { background: var(--ink); color: #fff; }
.sa-header-inner {
  max-width: 1080px;
  margin: 0 auto;
  padding: 14px 24px;
  display: flex;
  align-items: center;
  gap: 24px;
  flex-wrap: wrap;
}
.sa-brand { display: flex; align-items: center; gap: 18px; color: #fff; }
.sa-crest { width: 73px; height: 73px; object-fit: contain; flex-shrink: 0; }
.sa-brand:hover { text-decoration: none; }
.sa-brand-text { display: flex; flex-direction: column; justify-content: center; }
/* Header wordmark, matching the live site: Nunito Sans, both lines uppercase and white. */
.sa-eyebrow {
  font-family: "Nunito Sans", sans-serif; font-size: 15px; font-weight: 400;
  line-height: 22px; text-transform: uppercase; color: #fff;
}
.sa-title {
  font-family: "Nunito Sans", sans-serif; font-size: 23px; font-weight: 700;
  line-height: 22.1px; letter-spacing: 0.69px; text-transform: uppercase; color: #fff;
}

.sa-header-right { display: flex; align-items: center; gap: 10px; margin-left: auto; }
/* Square NL/FR toggle, matching the live site's language switcher exactly. */
.sa-lang { display: flex; }
.sa-lang a {
  display: flex; align-items: center; justify-content: center;
  min-width: 40px; height: 40px; padding: 0 10px;
  font-size: 15px; font-weight: 400; border-radius: 0;
  background: rgba(170,170,170,0.1); color: #888888;
}
.sa-lang a.active { background: #cccccc; color: #222222; }
.sa-lang a:hover { text-decoration: none; }

.sa-menu { position: relative; }
/* The same 40px as the NL/FR tiles beside it, so the two line up top and bottom. The tiles are
   40x40 squares taken from the live site, so it is this button that follows them; the height is
   set rather than left to the padding, which put it at 37px. */
.sa-menu-trigger {
  display: flex; align-items: center; gap: 8px;
  height: 40px; box-sizing: border-box;
  background: transparent; border: 1px solid rgba(255,255,255,0.3); border-radius: 6px;
  color: #fff; font-family: "Nunito Sans", sans-serif; font-size: 14px; font-weight: 600;
  padding: 0 14px; cursor: pointer;
}
.sa-menu-trigger:hover { background: rgba(255,255,255,0.08); }
.sa-menu-trigger svg { flex-shrink: 0; opacity: 0.8; }
.sa-menu-panel {
  display: none;
  position: absolute; top: calc(100% + 6px); right: 0; min-width: 220px;
  background: #1c1c1a; border: 1px solid rgba(255,255,255,0.1); border-radius: 8px;
  padding: 8px; box-shadow: 0 12px 28px rgba(0,0,0,0.35); z-index: 50;
}
.sa-menu-panel.open { display: block; }
.sa-menu-panel a, .sa-menu-panel button {
  display: block; width: 100%; text-align: left;
  padding: 9px 12px; border-radius: 5px; border: none; background: none;
  color: #d6d2c9; font-family: "Nunito Sans", sans-serif; font-size: 14px; font-weight: 500;
  cursor: pointer;
}
.sa-menu-panel a:hover, .sa-menu-panel button:hover, .sa-menu-panel a.active {
  background: rgba(255,255,255,0.08); color: #fff; text-decoration: none;
}
.sa-menu-divider { height: 1px; background: rgba(255,255,255,0.1); margin: 6px 4px; }
.sa-menu-panel form { margin: 0; }

.sa-main { width: 100%; min-width: 0; max-width: var(--content-width); margin: 0 auto; padding: 24px 0 60px; }
.sa-main-wide { max-width: var(--content-width); }
/* The admin screens only. They are an internal tool with wide tables, not part of the 980px
   column the members' area copies from the live site — so they get their own width, and the
   member-facing pages keep theirs untouched.

   Breadcrumbs, title banner and content all take it, or the page reads as a wide table that has
   slipped out from under a narrower heading. */
.sa-body-admin {
  /* Back to the same 980px as every other page, on the board's instruction. The wide tables keep
     working: .sa-table-card scrolls sideways inside the panel rather than stretching the page. */
  --admin-width: var(--content-width);
}
.sa-main-admin,
.sa-body-admin .sa-page-banner,
.sa-body-admin .sa-breadcrumbs { max-width: var(--admin-width); }
/* The admin screens are a working tool, not the members' translucent chrome: solid white with a
   real edge, so the panel and its tables stand off the grey page instead of melting into it. */
.sa-body-admin .sa-panel {
  background: #fff; border: 1px solid #cfcfcf; box-shadow: 0 1px 4px rgba(0,0,0,0.10);
}
.sa-body-admin .sa-table-card { border-color: #cfcfcf; }
.sa-body-admin .sa-wix-table th { border-bottom-color: #cfcfcf; }
.sa-body-admin .sa-wix-table td { border-bottom-color: #e6e4e0; }
/* A card inside the admin panel needs its own surface: the panel went solid white, and a
   translucent white card on white is no card at all — the dashboard's tiles had become numbers
   floating in space. */
.sa-body-admin .sa-card {
  background: #f7f6f4; border: 1px solid #d8d5cf; padding: 18px;
}
.sa-body-admin a.sa-card:hover { background: #f0eeea; border-color: #bdb9b1; }

/* The dashboard: counts in a row of their own, then the links as a grid of equal cards. */
.sa-body-admin .sa-card h3 { font-size: 15px; }
.sa-main-bare { margin: 0; padding: 0; }

.sa-hero {
  position: relative; overflow: hidden;
  min-height: calc(100vh - 65px);
  display: flex; align-items: center; justify-content: center;
  background: var(--ink);
}
/* The live hero shows the photo unmodified — no blur, no darkening — with the crest and
   wordmark stacked in dark type over the bright right-hand side of the image. */
.sa-hero-photo {
  position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover;
}
.sa-hero-content {
  /* Extra bottom padding lifts the stack ~14px so it lands where the live site puts it —
     there the photo runs under an overlaying header, here the header is a solid bar. */
  position: relative; text-align: left; padding: 40px 0 68px;
  /* De stapel staat in dezelfde kolom als de tekst eronder, en begint waar die tekst begint.
     Op de site van de club zweeft hij op ongeveer 64% van het venster — een maat die bij niets
     hoort — en dan staat het wapenschild een paar tientallen pixels naast de kolom eronder; het
     bestuur wees erop (september 2026). Dit is de band zelf, met de linkerkolom en de
     tussenruimte als padding, zodat de inhoud op de rechterkolom begint. */
  display: grid; grid-template-columns: 40.97% 40.97%; justify-content: space-between;
  width: calc(100% - 32px); max-width: 1179px;
  margin: 0 auto;
}
/* Zo breed als het woordmerk en geen pixel meer, want daar hangt de plaats van het schild aan:
   het staat gecentreerd bóven de tekst, niet gecentreerd in de kolom. Met een omhulling van de
   volle 483 zou het schild een eind rechts van het woordmerk komen te zweven — het bestuur wees
   daar op nadat de stapel links was uitgelijnd. */
/* Alles in de stapel deelt één as: het schild, het bovenschrift, het woordmerk en het jaartal.
   De stapel is zo breed als haar breedste regel, dus dat is het woordmerk — en daar centreert de
   rest op. Links uitlijnen zag er in het Nederlands goed uit, waar bovenschrift en woordmerk
   toevallig even breed zijn (296 tegen 294), maar niet in het Frans: "CHEF CONFRÉRIE DE" is 225
   en stond dan een heel eind links onder een gecentreerd schild. */
/* justify-self: center en niet start: de stapel staat in het **midden van de rechterkolom**,
   niet tegen haar linkerrand. Met start viel de linkerrand van het woordmerk samen met die van
   de tekst eronder, en dan hangt het wapenschild links in zijn kolom — het bestuur wees daar drie
   keer op voor ik het goed las. Wat gevraagd is, is de verticale as: die van het schild valt
   samen met die van het tekstblok eronder.
   (Geen backticks in dit commentaar: dit blok is een JS template literal.) */
.sa-hero-stack { grid-column: 2; justify-self: center; width: max-content; max-width: 100%; text-align: center; }
/* Het schild wordt nooit breder dan het woordmerk eronder, en dat is de hele truc. De stapel is
   zo breed als haar breedste kind; groeide het schild daaroverheen (bij een venster vanaf ~1700px
   haalde het de 328 van de club), dan bepaalde hét de breedte, stond de tekst er links in, en
   stond het schild zeventien pixels naast het woordmerk. Het bestuur zag dat op een breed scherm.
   De bovengrens is daarom 276 — de breedte die het bij 1440 al had — tegen een woordmerk van 294
   in het Nederlands en 295 in het Frans. */
.sa-hero-crest {
  display: block; margin: 0 auto 24px;
  width: min(19.2vw, 276px); min-width: 190px;
}
.sa-hero-text > * { line-height: 1.25; }

/* The live site fades the crest and the wordmark in on load — Wix's "motion-fadeIn", copied
   here exactly: pure opacity, 0.8s, same easing, both starting together (no stagger). */
@keyframes sa-fade-in { from { opacity: 0; } to { opacity: 1; } }
.sa-hero-crest,
.sa-hero-text {
  animation: sa-fade-in 0.8s cubic-bezier(0.445, 0.05, 0.55, 0.95) both;
}
@media (prefers-reduced-motion: reduce) {
  .sa-hero-crest, .sa-hero-text { animation: none; }
}
.sa-hero-eyebrow { font-family: "Montserrat", sans-serif; font-size: 21px; font-weight: 400; letter-spacing: -0.21px; color: #000; }
.sa-hero-title { font-family: "Montserrat", sans-serif; font-weight: 700; font-size: 36px; letter-spacing: -0.36px; color: #000; margin: 0 0 6px; }
.sa-hero-tagline { font-family: "Montserrat", sans-serif; font-size: 16px; font-weight: 400; color: #666; }

/* Too narrow for the off-centre stack, so centre it — and pan the photo towards its bright
   right-hand side, otherwise the dark type lands on the dark gun barrel and stops being
   readable. (The live site swaps in a separate Wix mobile layout here, so there is no
   original to copy at this width.) */
/* Zodra de banden eronder stapelen, staat er geen rechterkolom meer om op uit te lijnen — dus
   gaat de stapel terug naar het midden, zoals de mobiele opmaak van de club hem zet. Dit punt
   moet met de banden meelopen (1215) en niet met de 900 die hier stond: met een vaste breedte
   van 483 en een verschuiving van 696 liep de stapel er anders zo het venster uit. */
/* Onder deze breedte stapelt de hele bladzijde, en dan is er geen rechterkolom meer om de
   stapel op te zetten: ze gaat naar het midden, zoals de mobiele opmaak van de club. Het punt
   ligt op 900 en niet meer op 1215, sinds de kolommen meeschalen — twee kolommen van ruim 350px
   houden het daar nog uit. */
@media (max-width: 900px) {
  .sa-hero-content { display: block; max-width: 483px; text-align: center; }
  .sa-hero-stack { width: auto; }
}

@media (max-width: 900px) {
  .sa-hero-photo { object-position: 78% center; }
  .sa-hero-crest { width: min(45vw, 240px); }
  .sa-hero-eyebrow { font-size: 16px; }
  .sa-hero-title { font-size: 28px; }
}

/* Green, 5px-radius buttons matching the live site's own form buttons. */
.sa-btn {
  display: inline-block;
  font-family: "Nunito Sans", sans-serif;
  font-weight: 400;
  font-size: 14px;
  padding: 9px 22px;
  border-radius: 5px;
  border: 1px solid transparent;
  cursor: pointer;
  background: var(--accent);
  color: #fff;
}
.sa-btn:hover { background: var(--accent-ink); text-decoration: none; color: #fff; }
.sa-btn-outline { background: transparent; border-color: #a9a49b; color: #fff; }
.sa-header .sa-btn-outline { border-color: rgba(255,255,255,0.5); }
.sa-btn-outline:hover { background: rgba(255,255,255,0.1); }
/* Light grey rather than white: on a white panel a white button reads as an outline and is
   easy to miss, so it gets a fill of its own. */
.sa-btn-secondary { background: var(--grey-light); color: var(--text); border-color: var(--border); }
.sa-btn-secondary:hover { background: var(--grey); color: var(--text); }
.sa-btn-danger { background: var(--danger); }
.sa-btn-danger:hover { background: #b23b2f; }
.sa-btn[disabled] { opacity: 0.5; cursor: not-allowed; }

/* Translucent white panels, matching the live site's content blocks. */
.sa-card {
  background: var(--panel);
  border: none;
  border-radius: 5px;
  padding: 28px;
  margin-bottom: 20px;
}

label { display: block; font-weight: 400; font-size: 14px; color: var(--text-muted); margin-bottom: 5px; }
/* Everything except the controls that render as buttons or boxes. Listing types individually
   let new ones (datetime-local, number) slip through unstyled, showing the browser's own font
   in the middle of a form. */
/* The search box styles itself (.sa-search input) — left in here it inherited this rule's
   12px padding under its own icon, and a 16px margin that made its form taller than the
   field, which put the magnifier 8px below centre. */
input:not([type=checkbox]):not([type=radio]):not([type=submit]):not([type=button]):not([type=search]),
select, textarea {
  width: 100%;
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: 4px;
  background: #fff;
  font-family: inherit;
  font-size: 15px;
  color: var(--text);
}
/* The spacing under a field belongs to the field's wrapper, not to the control. It used to sit
   in the rule above, whose five :not() clauses outweigh any .sa-fcell input reset — so the
   grid forms carried an invisible 16px under every box and could not get rid of it. */
.sa-field > input, .sa-field > select, .sa-field > textarea { margin-bottom: 16px; }
/* The browser's own arrow sits hard against the right edge and cannot be moved, so the select
   draws its own: the same chevron, 15px in instead of 10. The padding keeps the longest option
   ("Affiliated Member") clear of it. */
select {
  appearance: none; -webkit-appearance: none;
  padding-right: 34px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5 6 6.5 11 1.5' fill='none' stroke='%23555' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 15px center;
}
/* One height for every control on a form. Left to the content, a date input comes out 45px
   against 43 for the rest: the browser draws its own calendar button inside, and that is taller
   than a line of text. Two pixels, but they show as soon as two fields sit side by side. */
input:not([type=checkbox]):not([type=radio]):not([type=submit]):not([type=button]):not([type=search]),
select { height: 43px; }

/* The hidden attribute means display:none — but only where nothing else sets display. A grid
   or a flex row overrides it and stays on screen: that is why the billing address kept showing
   for members with no company. */
[hidden] { display: none !important; }

textarea { min-height: 90px; resize: vertical; }
.sa-field { margin-bottom: 4px; }
.sa-field-narrow { width: 90px; }
.sa-row { display: flex; gap: 16px; flex-wrap: wrap; }
.sa-row > * { flex: 1; min-width: 220px; }

.sa-error { background: #f6e4e1; border: 1px solid var(--danger); color: #7a2f28; padding: 10px 14px; border-radius: 6px; margin-bottom: 16px; font-size: 14px; }
.sa-success { background: #e6ede7; border: 1px solid var(--accent); color: var(--accent-ink); padding: 10px 14px; border-radius: 6px; margin-bottom: 16px; font-size: 14px; }
/* Not a success and not an error: the app filled something in and the member should check it. */
.sa-notice-info { background: #fdf5e6; border: 1px solid #d9b45b; color: #5a3200; padding: 10px 14px; border-radius: 6px; margin-bottom: 16px; font-size: 14px; }
.sa-muted { color: var(--text-muted); font-size: 14px; }
/* A remark about the form — what a field will do on its own, what the limit is, what is not
   there yet. Ochre, the Serment colour taken down to a weight that reads as text on white:
   these are the lines a board member should notice, and grey made them disappear. */
.sa-note { color: var(--note); font-size: 13px; }
/* inline-flex + align-items keeps the label centred inside the pill even when a flex row
   stretches the badge to match a taller neighbour (the bordered countdown badge). */
.sa-badge { display: inline-flex; align-items: center; font-size: 11px; font-weight: 600; padding: 2px 8px; border-radius: 10px; background: var(--grey); color: var(--ink); }
.sa-badge-accent { background: var(--accent); color: #fff; }
.sa-badge-muted { background: #e6e2da; color: var(--text-muted); }
.sa-badge-danger { background: var(--danger); color: #fff; }
/* The Eed — the guild's board — beside the member's name. The same orange the calendar's
   "+ PARTNER" badge uses, so the two read as one family rather than a new colour. */
.sa-badge-serment { background: #f5b661; color: #5a3200; }

/* The two action buttons line up down the table: each is as wide as the longest label its own
   column can carry, in either language ("Uitnodiging opnieuw versturen", "Heractiveren"), so a
   row where the wording changes doesn't shift the column.

   The cell itself must stay a real table cell — display:flex on a <td> takes it out of the
   table's row box, so its bottom border is drawn at the height of the buttons instead of the
   row's, and the dividers no longer line up across the table. The forms are laid out inline
   inside it instead. */
.sa-actions-cell > form { display: inline-block; vertical-align: middle; }
.sa-actions-cell > form + form { margin-left: 6px; }
/* The membership is one of five fixed labels, so it never needs to wrap. */
.sa-membership-cell { white-space: nowrap; }
/* The archive's theme headings — the club's own folder names, with the count beside them. */
.sa-archive-heading {
  font-family: "Montserrat", sans-serif; font-size: 15px; font-weight: 700; color: #333;
  margin: 0; padding: 12px 0 10px; border-bottom: 1px solid var(--border);
  display: flex; align-items: baseline; gap: 8px; cursor: pointer;
  list-style: none;
}
/* The browser's own triangle is replaced by one that sits on the baseline of the heading and
   turns when the theme opens. */
.sa-archive-heading::-webkit-details-marker { display: none; }
.sa-archive-heading::before {
  content: '▸'; color: var(--text-muted); font-size: 12px;
  transition: transform 0.15s ease; display: inline-block;
}
.sa-archive-group[open] > .sa-archive-heading::before { transform: rotate(90deg); }
.sa-archive-heading:hover { color: #000; }
.sa-archive-group > .sa-grid { margin: 16px 0 24px; }
.sa-archive-group > .sa-table-card { margin: 12px 0 20px; }
.sa-archive-heading span { font-family: "Nunito Sans", sans-serif; font-size: 13px; font-weight: 400; color: var(--text-muted); }

/* ---- The members list, laid out like the club's own Wix "Contacts" screen ---- */
.sa-lead { margin: 0 0 18px; color: #222; font-size: 16px; font-weight: 600; }

.sa-toolbar { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin-bottom: 16px; }
.sa-toolbar-count { font-family: "Montserrat", sans-serif; font-size: 14px; font-weight: 600; color: #222; }
.sa-toolbar-add { margin-left: auto; }
/* Under the table rather than beside the count: adding a member is what you do after reading
   the list, not before. */
.sa-table-add { display: flex; justify-content: center; margin-top: 22px; }
/* The filters sit on their own line under the search, so a narrow window stacks them instead of
   pushing the Add button off the edge. */
.sa-filters { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin: -4px 0 16px; }
/* width and margin reset: the shared form rule gives every select 100% width and a bottom
   margin, which put each filter on a line of its own. */
.sa-filters select {
  width: auto; margin: 0; height: 34px; padding: 0 28px 0 10px;
  border: 1px solid var(--border); border-radius: 6px;
  background: #fff; font-family: "Nunito Sans", sans-serif; font-size: 13px; color: #333;
}
.sa-filters { flex-wrap: nowrap; overflow-x: auto; }
@media (max-width: 820px) { .sa-filters { flex-wrap: wrap; overflow-x: visible; } }
.sa-filters-label { font-size: 13px; color: var(--text-muted); }
.sa-filter-clear { font-size: 13px; color: var(--accent-ink); }

/* Sortable headers: the whole cell is the link, with the arrow only on the column in use. */
.sa-wix-table th a { display: inline-flex; align-items: center; gap: 4px; color: inherit; text-decoration: none; }
.sa-wix-table th a:hover { color: #222; text-decoration: underline; }
.sa-sort-arrow { font-size: 10px; color: var(--text-muted); }
/* The search box is a plain GET form, so the result is a normal page a member can bookmark. */
.sa-search { position: relative; display: flex; align-items: center; height: 40px; flex: 1 1 260px; max-width: 420px; }
/* Centred on the field, not sitting on the text baseline: an absolutely positioned child of a
   flex container keeps its static top, which put the magnifier over the placeholder. */
.sa-search svg { position: absolute; left: 12px; top: 50%; transform: translateY(-50%); color: #888; pointer-events: none; }
.sa-search input {
  width: 100%; height: 40px; box-sizing: border-box; margin: 0;
  padding: 0 12px 0 36px; border: 1px solid var(--border); border-radius: 6px;
  font-family: "Nunito Sans", sans-serif; font-size: 14px; color: var(--text); background: #fff;
}
.sa-search input:focus { outline: 2px solid rgba(55,91,59,0.35); outline-offset: -1px; }

.sa-table-card { background: #fff; border: 1px solid var(--border); border-radius: 8px; overflow-x: auto; }
/* Three weights, one per rank, so a list reads in the order it should: 700 for the name that
   is the row's subject and is also its link, 600 for anything that labels the row (column
   headings, chips, badges, the count above the table), 400 for the data and for every second
   line. Before this the column heading weighed as much as the name under it, and the activity
   status badge more than the membership chip beside it in the next list. */
.sa-wix-table { width: 100%; border-collapse: collapse; font-size: 14px; }
.sa-wix-table th {
  text-align: left; text-transform: none; font-family: "Nunito Sans", sans-serif;
  font-size: 13px; font-weight: 600; color: #555;
  padding: 14px 16px; border-bottom: 1px solid var(--border); white-space: nowrap;
}
.sa-wix-table td { padding: 12px 16px; border-bottom: 1px solid #f0efec; vertical-align: middle; }
.sa-wix-table tbody tr:last-child td { border-bottom: none; }
.sa-wix-table tbody tr:hover td { background: #fafaf8; }

/* Name cell: the avatar and the two lines of text sit on one baseline grid. */
.sa-cell-name a { display: flex; align-items: center; gap: 12px; text-decoration: none; }
.sa-avatar {
  flex: 0 0 36px; width: 36px; height: 36px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  color: #fff; font-family: "Montserrat", sans-serif; font-size: 13px; font-weight: 700;
  letter-spacing: 0.5px;
}
.sa-name-block { display: flex; flex-direction: column; min-width: 0; }
.sa-name { font-weight: 700; color: #222; white-space: nowrap; }
.sa-cell-name { min-width: 240px; }
/* The name block must be allowed to shrink, or a long second line (a document's file name runs
   to 90 characters) widens the column until every other one is pushed off the card. */
.sa-name-block { max-width: 100%; overflow: hidden; }
.sa-name-sub { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* A document title is a sentence, not a person's name, so it wraps instead of running on. */
.sa-cell-doc { max-width: 440px; }
.sa-cell-doc .sa-name { white-space: normal; }
.sa-name-sub { font-size: 12px; color: var(--text-muted); }
.sa-cell-name a:hover .sa-name { text-decoration: underline; }
.sa-cell-mail { max-width: 220px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* A document's own picture in the admin list — landscape rather than the round member avatar,
   because these are sheets of paper. */
.sa-doc-thumb {
  flex: 0 0 auto; width: 46px; height: 34px; border-radius: 3px; object-fit: cover;
  background: #ededed; display: block; border: 1px solid var(--border);
}
.sa-doc-thumb-none { background: #f4f3f0; }
/* The theme is the club's own folder name and can run long ("Sas de Gand (Voormuide) - zie
   ook…"), so it wraps rather than stretching the column. */
.sa-cell-theme { max-width: 260px; font-size: 13px; color: #555; }
/* The activity's photo beside its title — landscape, the shape the calendar cards use. */
.sa-event-thumb {
  flex: 0 0 auto; width: 64px; height: 44px; border-radius: 4px; object-fit: cover;
  background: #ededed; display: block; border: 1px solid var(--border);
}
.sa-event-thumb-none { background: #f4f3f0; }
.sa-cell-event .sa-name { white-space: normal; }

/* Chips rather than the app's rounded badges: the Wix screen sets them square-ish and pale. */
/* The chips themselves never break, but a cell holding two of them may stack them rather than
   push the table past the card and clip the last one. */
.sa-cell-chips { white-space: normal; min-width: 120px; }
/* A chip has to read as an object on a white row, so it carries a border of its own and a
   background dark enough to see. The pale fills it started with disappeared against the table. */
.sa-chip {
  display: inline-block; margin: 2px 4px 2px 0; padding: 3px 8px; border-radius: 4px;
  background: #e2dfd8; border: 1px solid #c8c4bb; color: #3a3a3a;
  font-size: 12px; font-weight: 600; white-space: nowrap;
}
.sa-chip-ok { background: #cfe0d2; border-color: #a9c4ae; color: #1f4426; }
.sa-chip-off { background: #f3cfcb; border-color: #dda49d; color: #7a2119; }
.sa-chip-serment { background: #f0a63f; border-color: #cf8620; color: #4a2900; }
/* An administrator is marked by the colour of their avatar — the same ochre as the Serment
   badge — rather than by a chip or a highlight behind the name. The title attribute names it
   for anyone who cannot read the colour. */
.sa-avatar-admin { background: #f5b661; color: #5a3200; }
.sa-chip-quiet { background: transparent; border-color: transparent; color: var(--text-muted); font-weight: 400; padding-left: 0; }
/* One quiet tint per membership. All five sit in the same cool, low-saturation family, so the
   column still reads as one kind of fact — but a Past Member is findable in a run of Full
   Members without reading a word. None of them competes with the green and red of the status
   chips beside them, which is what the eye should catch first. */
.sa-chip-m-full { background: #bcd3ea; border-color: #92b3d2; color: #1b3b5c; }
.sa-chip-m-affiliated { background: #dbe4ee; border-color: #b3c3d5; color: #2f4a66; }
.sa-chip-m-honorary { background: #9dbdda; border-color: #7aa0c1; color: #142d49; }
.sa-chip-m-past { background: #d3d8dd; border-color: #b0b8c0; color: #47525d; }
.sa-chip-m-junior { background: #aec5da; border-color: #89a7c2; color: #22405c; }

@media (max-width: 900px) {
  /* Phone and Labels are the first to go: the name, address and status carry the screen.
     Alleen op de ledenlijst, waar die twee kolommen staan. De regel gold voor élke tabel met
     deze klasse, en dat wist op een scoreblad van negen ronden zonder meer de derde en de vijfde
     kolom — T1 en T3 stonden er niet, en niets op het scherm zei dat. Elke tabel in het
     ledengedeelte schuift trouwens al zijwaarts in haar eigen kaart; kolommen verbergen is een
     oplossing van vóór die kaart. */
  .sa-leden-tabel th:nth-child(3), .sa-leden-tabel td:nth-child(3),
  .sa-leden-tabel th:nth-child(5), .sa-leden-tabel td:nth-child(5) { display: none; }
}
/* One date per line in the admin tables — 09/09/2026 (17h00) never needs to wrap. */
.sa-when-cell { white-space: nowrap; }
/* The French title under the Dutch one in the admin lists — a shade lighter, so the pair reads
   as one entry in two languages rather than two rows that happen to touch. */
.sa-title-fr { display: block; color: var(--text-muted); font-size: 13px; }
/* Invite and deactivate on the member's own screen, set apart from the save button above by a
   rule — they act at once, where everything above them waits for Opslaan. */
.sa-form-note { font-size: 13px; margin: -2px 0 14px; }
/* A button that reads as a link: it reveals a block rather than submitting anything. */

.sa-linklike {
  background: none; border: 0; padding: 0; cursor: pointer;
  font-family: "Nunito Sans", sans-serif; font-size: 14px; color: var(--accent-ink);
  text-decoration: underline;
}
.sa-linklike:hover { color: #000; }

/* The member form on a twelve-column grid: fields that belong together share a line, each as
   wide as its content warrants. A postcode gets two columns, an email five. */
/* The member's record in four groups — who they are, where they live, their standing in the
   guild, and the rest. A real <fieldset>/<legend>, so a screen reader announces the group when
   it reaches the first field of it. */
.sa-fset { border: 0; border-top: 1px solid var(--border); margin: 0 0 6px; padding: 16px 0 0; }
.sa-fset:first-of-type { border-top: 0; padding-top: 0; }
.sa-fset > legend {
  font-family: "Montserrat", sans-serif; font-size: 13px; font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.6px; color: #555;
  padding: 0; margin-bottom: 12px;
}
.sa-fgrid { display: grid; grid-template-columns: repeat(12, 1fr); gap: 0 16px; margin-bottom: 14px; }
.sa-fcell { grid-column: span var(--span, 3); min-width: 0; }
.sa-fcell label {
  display: block; font-size: 13px; color: var(--text-muted); margin-bottom: 4px;
}
.sa-fcell input, .sa-fcell select { margin-bottom: 0; }
/* The note sits on the same line as the dates it explains, aligned with their fields rather
   than their labels. */
/* Room above it: on its own line under the permit dates it was sitting against them, reading
   as a caption of the last field rather than a remark about both. */
.sa-fnote { align-self: end; font-size: 13px; color: var(--note); margin-top: 16px; padding-bottom: 10px; }
/* A line that explains the whole block sits under its heading, before the fields it is about,
   rather than under the last input where it reads as a note on that one field. */
/* No pull-up: with a line between the blocks, a remark should start where a field label does. */
.sa-fset-note { font-size: 13px; color: var(--note); margin: 0 0 14px; }
/* A checkbox has no field box to sit in, so it lines up with the inputs beside it rather than
   with their labels. */
.sa-fcheck { align-self: end; padding-bottom: 10px; }
/* The member's own permit scans on their record — small, side by side, each opening the full
   document. */
.sa-permit-strip { display: flex; gap: 8px; }
/* Half again as large, and always landscape: a permit is a card held sideways, so the frame
   keeps that shape whatever way round the member photographed it. object-fit: cover crops a
   portrait scan to the same window rather than letting it stand the row on end. */
.sa-permit-strip a { display: block; width: 108px; height: 75px; border-radius: 4px; overflow: hidden; border: 1px solid var(--border); background: #ededed; }
/* Green while the permit runs, red once it has passed. Two pixels, so it reads as a state and
   not as a decorative frame. */
.sa-permit-strip-valid a { border: 2px solid var(--accent); }
.sa-permit-strip-expired a { border: 2px solid var(--danger); }
.sa-permit-valid-frame .sa-permit-preview { box-shadow: 0 0 0 2px var(--accent); }
.sa-permit-expired-frame .sa-permit-preview { box-shadow: 0 0 0 2px var(--danger); }
/* Anchored to the top, not the middle. Twenty-one of the club's scans are an A4 sheet with the
   card in the top corner, and a centre crop showed the blank middle of the page — a white box
   with a coloured border and nothing in it. The top band is where the card is on a sheet, and on
   a photo of the card itself it makes no difference. */
.sa-permit-strip img { width: 100%; height: 100%; object-fit: cover; object-position: top; display: block; }
.sa-permit-strip-none { display: block; width: 100%; height: 100%; }
.sa-permit-strip-empty { margin: 0 0 8px; font-size: 13px; color: var(--note); }
/* Nothing uploaded yet: an empty card in the size a scan gets, so the block keeps its shape and
   the gap reads as "this is missing" rather than as a rendering fault. The dashed edge says it
   is a slot, not a picture that failed to load. */
.sa-permit-placeholder { display: block; width: 108px; height: 75px; }
.sa-permit-placeholder svg { display: block; width: 100%; height: 100%; }
.sa-permit-empty p { margin: 0 0 8px; }
/* A field the member may read but not change. Without this it looks exactly like one they can
   type in, and they would wonder why their edit never sticks. The selector repeats the generic
   input rule's five :not() clauses: that rule is (0,5,1), so a plain .sa-fcell input:disabled
   loses to it and the field stays white — the same specificity trap that once hid a margin. */
input:not([type=checkbox]):not([type=radio]):not([type=submit]):not([type=button]):not([type=search]):disabled {
  background: #f4f3f0; color: #6b6862; border-color: #ddd9d2; cursor: not-allowed;
}

.sa-form-foot {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap; justify-content: flex-end;
  margin-top: 20px; padding-top: 18px; border-top: 1px solid var(--border);
}
/* An action that is not about saving this form belongs at the other end of the row, not beside
   the save button where a stray click lands on it. The auto margin takes the whole gap. */
.sa-form-foot .sa-btn-left { margin-right: auto; }
.sa-check { display: inline-flex; align-items: center; gap: 8px; font-size: 14px; }
.sa-check input { width: auto; margin: 0; }

/* Below the width the twelve columns need, every field takes the full line rather than being
   squeezed to a few characters. */
@media (max-width: 900px) {
  .sa-fgrid { grid-template-columns: 1fr; gap: 0; }
  .sa-fcell { grid-column: 1 / -1; margin-bottom: 12px; }
  .sa-form-foot { justify-content: flex-start; }
}
.sa-member-actions {
  display: flex; gap: 10px; flex-wrap: wrap;
  margin-top: 24px; padding-top: 20px; border-top: 1px solid var(--border);
}
.sa-btn-row { padding: 4px 8px; font-size: 11px; white-space: nowrap; }
.sa-btn-invite { min-width: 11.5rem; }
.sa-btn-status { min-width: 6.5rem; }

table { width: 100%; border-collapse: collapse; font-size: 14px;
  /* Solid, not translucent like the panel around it: the background photo showing through a
     block of data made it harder to read. */
  background: var(--paper);
}
th, td { text-align: left; padding: 7px 12px; border-bottom: 1px solid var(--border); }
/* A phone number that wraps turns every row of the directory into two lines. The table
   already scrolls sideways inside its own container on a narrow screen. */
.sa-nowrap { white-space: nowrap; }
th { font-family: "Montserrat", sans-serif; font-size: 12px; text-transform: uppercase; letter-spacing: 0.04em; color: var(--text-muted); }

.sa-list { list-style: none; margin: 0; padding: 0; }
.sa-list li { padding: 14px 0; border-bottom: 1px solid var(--border); }
.sa-list li:last-child { border-bottom: none; padding-bottom: 0; }
.sa-list li:first-child { padding-top: 0; }

/* Attendee rows: the member's name and guests, with what they filled in underneath. Tighter
   than the shared list spacing — a row here is two or three lines, so 14px above and below
   each one left the panel very airy. */
.sa-list li.sa-attendee { padding: 10px 0; }
.sa-attendee { display: flex; align-items: baseline; justify-content: space-between; gap: 16px; flex-wrap: wrap; }
.sa-attendee-main { flex: 1 1 220px; min-width: 0; }
.sa-attendee-detail { font-size: 13px; margin-top: 2px; line-height: 1.5; }
.sa-attendee-declined .sa-attendee-main { opacity: 0.6; }
/* The head count sits in its own tinted box above the list, rather than being separated from
   it by a rule. */
.sa-attendee-summary {
  background: var(--grey-light);
  border-radius: 5px;
  padding: 14px 16px;
  margin-bottom: 18px;
}
.sa-panel-past .sa-attendee-summary { background: rgba(255,255,255,0.55); }
/* Mijn Inschrijvingen: a small photo of the event beside its details. The crest stands in
   where an event has no photo, as it does on the calendar cards. */
.sa-inscription { display: flex; gap: 16px; align-items: stretch; position: relative; }
/* Pinned to the card's top-right corner. The title line reserves room for it so a long event
   name wraps rather than running underneath. */
.sa-inscription-flag { position: absolute; top: 0; right: 0; background: #dcdcdc; color: #5a5a5a; }
.sa-inscription-past .sa-inscription-head { padding-right: 90px; }
.sa-inscription-thumb {
  /* Fixed width, height stretching to the text beside it, so the photo squares off against
     the block of text however many lines it has. Not aspect-ratio: combined with a stretched
     height that feeds back into the width and the photo eats the whole row. */
  flex: 0 0 116px; align-self: stretch; min-height: 76px;
  border-radius: 5px; overflow: hidden; background: #2a2a28; display: block;
}
.sa-inscription-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.sa-inscription-thumb-fallback {
  width: 100%; height: 100%; display: flex; align-items: center; justify-content: center;
}
.sa-inscription-thumb-fallback img { width: 58%; height: auto; object-fit: contain; }
.sa-inscription-body { flex: 1 1 auto; min-width: 0; }
/* The event's name, set off from the date and address below it. */
.sa-inscription-head { margin-bottom: 8px; }
/* A registration for an event that has been and gone, greyed like the calendar's past cards. */
.sa-inscription-past .sa-inscription-thumb img { filter: grayscale(1); }
.sa-inscription-past .sa-inscription-body,
.sa-inscription-past .sa-inscription-head a { color: var(--text-muted); }

/* The public site: the club's own text, and the timeline of the guild's founding years. */
/* Measured off the live page at a 1440px viewport, where Wix serves its desktop layout — the
   figures in its stylesheet are the most common ones, not this page's, and reading them led me
   wrong once already. Section headings are Montserrat 56px at regular weight; the body is
   Nunito Sans 13px/19.5px in #666, noticeably smaller and lighter than the members' area. */
.sa-public { font-size: 13px; line-height: 19.5px; color: #666; }
.sa-public-heading {
  font-family: "Montserrat", sans-serif;
  font-size: 56px; line-height: 27px; font-weight: 400; color: #222;
  margin: 48px 0 20px;
}
.sa-public-heading:first-child { margin-top: 0; }
.sa-public-text p { margin: 0 0 12px; }
.sa-timeline-row { display: flex; gap: 20px; padding: 10px 0; border-bottom: 1px solid var(--border); }
.sa-timeline-row:last-child { border-bottom: none; }
.sa-timeline-year { flex: 0 0 68px; font-weight: 700; color: var(--accent); }
.sa-timeline-text { flex: 1 1 auto; min-width: 0; }
.sa-timeline-text p:last-child { margin-bottom: 0; }
/* The Euverdekens table, matching the live page's own: a #888 header bar (the same grey as the
   quotation band and the footer) with white bold labels, a 100px year column, and rows
   alternating white and light grey. */
.sa-deans { max-width: 420px; margin: 4px 0 8px; }
.sa-deans table {
  width: 100%; border-collapse: collapse; background: transparent;
  font-family: "Nunito Sans", sans-serif;
}
.sa-deans th {
  background: #888888; color: #fff;
  font-family: "Nunito Sans", sans-serif; font-size: 14px; font-weight: 700;
  text-align: left; padding: 7px 14px; border: 0;
}
.sa-deans th:first-child, .sa-deans td:first-child { width: 100px; }
.sa-deans td { font-size: 14px; color: #222; padding: 7px 14px; border: 0; }
.sa-deans td:first-child { font-weight: 700; }
.sa-deans tbody tr:nth-child(odd) { background: #ffffff; }
.sa-deans tbody tr:nth-child(even) { background: #f2f2f2; }

/* The "Welkom" section's two columns. Measured on the live page at a 1440px viewport: the
   photos are 417x312 with a 24px gap, their column starting at x=150; the text column is also
   417px wide and starts at x=788. That is a 1055px band with a 221px gutter — wider than the
   980px the rest of the page uses, so it gets its own width instead of --content-width. The
   photo stack starts level with the section's first paragraph, 157px under the heading's top. */
/* The public homepage is plain white, not the grey-and-panels chrome of the members' area:
   its sections sit straight on the page, each one a two-column band of its own. */
.sa-body-bare { background: #fff; }

/* None of the three bands is centred on the live page — Wix has them hand-placed on a canvas
   that sits left of the window's middle, by a different amount each time. So each band takes
   its own measured offset from centre (at 1440px: Welkom at x=150, Historiek at x=56, the
   guild section at x=30) rather than following a rule none of them actually share. */
.sa-welkom, .sa-history, .sa-guild {
  display: grid;
  justify-content: space-between;
  width: 100%; min-width: 0;
  margin: 0 auto;
  position: relative;
  /* Twee helften van 420, even breed, op alle drie de banden (het bestuur, september 2026). Op
     de site van de club is elke band anders verdeeld — 417/417, 637/397 en 606/419 — en elke
     band stond bovendien op zijn eigen plaats, hand geplaatst links van het midden. Nu is het
     één regel: dezelfde kolommen, dezelfde breedte, en **gecentreerd** in plaats van naar links
     geschoven.
     Dat laatste is het sluitstuk. Uitgelijnd maar naar links geschoven gaf 30px marge links
     tegen 231 rechts, en dan staat de bladzijde scheef in het venster al staan de kolommen
     onderling gelijk. Gecentreerd valt de scheiding grijs/wit — die op de helft van het venster
     ligt — ook precies in het midden van de tussenruimte tussen de twee kolommen.
     De verschuiving is daarmee weg, en met haar de klem die hem binnen het venster hield: een
     gecentreerde band valt er per definitie niet buiten.
     De kolommen zijn daarna nog eens 15% verbreed, van 420 naar 483, en dat gaat naar het
     midden toe: de band blijft 1179 breed, dus de buitenranden staan waar ze stonden en de
     tussenruimte krimpt van 339 naar 213. De ruimte in het midden was de prijs van twee gelijke
     helften, en die prijs is daarmee deels teruggenomen.
     De kolommen zijn daarna meeschalend gemaakt: 40,97% elk, met de 18,06% die overblijft als
     tussenruimte. Bij een band van 1179 komt dat op dezelfde 483 + 213 + 483 uit als de vaste
     maten die hier stonden, maar de opzet houdt nu stand op een smaller venster in plaats van te
     stapelen. Dat scheelde: met vaste kolommen paste de band pas vanaf ~1211px, en een browser
     van 1200 — niet ongewoon — kreeg de gestapelde bladzijde te zien, waar alles wat hierboven
     is uitgelijnd niet van toepassing is. */
  grid-template-columns: 40.97% 40.97%;
  width: calc(100% - 32px);
  max-width: 1179px;
}

/* **Eén kleur per band, over de volle breedte.** Op de site van de club is elke band half wit en
   half grijs, gesplitst op de helft van het vénster, met de grijze kant die om en om wisselt.
   Die kleuren zijn hier destijds nauwkeurig afgelezen — door de hele stapel overlays op een punt
   te compositeren, niet door de achtergrond van één element te lezen, wat daar twee keer het
   verkeerde antwoord gaf.
   Ze zijn er in september 2026 toch uit. Zolang de kolommen op hun plaats van Wix stonden, viel
   de scheiding tussen de twee kolommen; nu de banden gecentreerd zijn en de kolommen breder,
   loopt ze dwars door een alinea. Het bestuur wees erop: elke band draagt zijn eigen achtergrond,
   geen dubbele. Wat blijft is de kleur die elke band al had. */
.sa-welkom-band {
  background: linear-gradient(to right, #eeeeee 0 50%, #ffffff 50%);
  padding-top: 69px;
}
.sa-history-band {
  background: linear-gradient(to right, #ffffff 0 50%, #f3f3f3 50%);
  padding-top: 69px;
}
/* 52,4 en niet 69 zoals de twee banden erboven, en dat is geen slordigheid. De lucht die je
   ziet is die tot de eerste letter, en deze kop is Nunito Sans 30px in een regel van 45 — die
   begint 10,9px ónder zijn vak, waar de Montserrat 56px/27 van Welkom en Historiek 5,7px bóven
   het hare begint. Met dezelfde 69 stond deze band dus 16,6px losser dan de andere twee. Zo
   komen alle drie op 63,3px inkt-lucht uit; nagemeten met measureText, niet geschat, en om
   dezelfde reden als bij de twee koppen van de Historiek-band. */
.sa-guild-band {
  background: linear-gradient(to right, #eeeeee 0 50%, #ffffff 50%);
  padding: 52.4px 0 0;
}

/* The short rule under "Welkom" and "Historiek" — 30px of a 1px dark-brown line, sitting
   101px below the heading's top with the opening paragraph 44px under it. Nothing else on
   the page carries one.

   Ze stond ingesprongen: 4px onder Welkom en 20px onder Historiek. Dat waren de maten van Wix,
   afgelezen van hun eigen bladzijde (x=792 in een kolom die op 788 begint, x=76 in een kolom die
   op 56 begint) — en net als de scheve banden hoorden die twee getallen bij niets. Op een
   bladzijde waar de kop en de alinea eronder allebei op de kolomrand beginnen, leest een streepje
   dat twintig pixels verderop begint als een vergissing. Het bestuur wees erop (oktober 2026),
   dus staat ze nu links uitgelijnd met de tekst waar ze bij hoort — in allebei de banden, want
   één streepje op 4 en één op 0 zou hetzelfde verschil in het klein herhalen. */
.sa-rule {
  width: 30px; height: 5px;
  border-top: 1px solid rgb(73, 47, 15);
  margin: 74px 0 39px;
}
/* De verschuiving naar links is geklemd: ze geldt tot de band de vensterrand raakt en houdt
   daar op. Zonder die klem schuift een band gewoon door — bij 1250px stond de eerste kolom van
   Historiek op -38 en die van de gilde op -65, dus liepen de eerste letters van elke regel
   buiten beeld. Dat is precies de breedte van een gewone laptop, en het viel niemand op omdat
   er geen horizontale balk bij hoort: wat links buiten het venster valt, is gewoon weg.
   De 16px is dezelfde marge die elke band bij het stapelen aanhoudt. */
/* De fotokolom staat verticaal in het midden van de tekstkolom ernaast (het bestuur, september
   2026). Ze begon op 157px onder de kop, gelijk met de eerste alinea — de maat van de live
   bladzijde — maar de tekst is een stuk langer dan de twee foto's, dus hing de stapel in de
   bovenste helft en stond er onderaan een gat. align-items: center laat de kortste kolom
   zichzelf plaatsen in plaats van hem een vaste afstand te geven die bij elke tekstwijziging
   opnieuw klopt of niet. (Geen backticks hierin: dit blok is een JS template literal.) */
.sa-welkom {
  padding: 0 0 63.3px;
  align-items: center;
}
/* **De halvering valt weg zodra de kolommen stapelen.** Zolang ze naast elkaar staan valt de
   scheiding op de helft van het venster precies in de tussenruimte ertussen — de band is
   gecentreerd, dus die twee punten vallen samen (nagemeten bij 1440: tussenruimte 614…827,
   scheiding 720). Gestapeld is er geen tussenruimte meer en loopt diezelfde scheiding dwars door
   een alinea: een regel half op wit en half op grijs. Dat is wat het bestuur zag (september 2026).
   Elke band houdt dan zijn eigen kleur, volvlaks.
   Deze regels moeten ná de drie banddefinities hierboven staan: ze wegen even zwaar, dus beslist
   de volgorde. In het blok bij de hero — dat eerder in dit bestand staat — deden ze niets. */
@media (max-width: 900px) {
  .sa-welkom-band { background: #eeeeee; }
  .sa-history-band { background: #f3f3f3; }
  .sa-guild-band { background: #eeeeee; }
}

.sa-history-band .sa-history, .sa-guild-band .sa-guild { padding-top: 0; }
.sa-welkom-photos { padding-top: 0; }
.sa-welkom-photos img { display: block; width: 100%; height: 312px; object-fit: cover; }
.sa-welkom-photos img + img { margin-top: 24px; }
.sa-welkom-caption {
  font-family: "Montserrat", sans-serif;
  font-size: 12px; line-height: 16.8px; color: #000;
  margin: 21px 0 0;
}
.sa-welkom-caption a { color: #000; text-decoration: none; }
.sa-welkom-caption a:hover { text-decoration: underline; }
/* Two blank lines stand between the heading and the text on the live page, which is why the
   gap under it is so much larger here than under the page's other headings. */
.sa-welkom-text .sa-public-heading { margin: 0; }
.sa-welkom-text p { font-size: 14px; line-height: 21px; color: #000; margin: 0 0 21px; }
.sa-welkom-text p:last-child { margin-bottom: 0; }
/* The guild's full French name opens the section, larger and lighter than the body under it.
   Both of these carry the paragraph selector so they outrank the rule above. */
.sa-welkom-text p.sa-welkom-lead { font-size: 18px; line-height: 27px; color: #444; }
.sa-welkom-text p.sa-welkom-signoff { font-size: 13px; line-height: 19.5px; margin: 21px 0 0; }

/* The fourth section: the guild's history in a wide left column with De Eed, the Euverdekens
   and the shooting photo beside it. Measured on the live page at 1440px — left column 606px at
   x=30, right column 419px at x=788, so a 1178px band with a 153px gutter. Like the Welkom
   band its right edge lines up with the page's 980px column, so it takes the same shift.
   Its headings are Nunito Sans 30px, not the Montserrat 56px of the sections above. */
/* The history column and the dated timeline beside it. */
/* De tijdlijn begon op x=759 waar De Eed eronder op 789 begint — dertig pixels verschil tussen
   twee rechterkolommen die onder elkaar staan. Het bestuur vroeg ze gelijk te zetten (september
   2026). De band is daarvoor 30px breder (1099 -> 1129) en schuift 15px minder ver naar links,
   zodat de linkerkolom op 57 blijft staan en de rechter op 789 uitkomt — dezelfde x als De Eed
   en als de tekstkolom van Welkom. Drie rechterkolommen op één lijn dus, waar het er twee waren. */
.sa-history {
  padding: 0 0 63.3px;
}
.sa-history-text .sa-public-heading { margin: 0; }
/* Montserrat, not Nunito Sans: this one paragraph is set in the heading face on the live page. */
.sa-history-lead { font-family: "Montserrat", sans-serif; font-size: 18px; line-height: 27px; color: #222; margin: 0 0 21px; }
.sa-history-text p { font-size: 14px; line-height: 21px; color: #222; margin: 0 0 21px; }
.sa-history-text p.sa-history-lead { font-family: "Montserrat", sans-serif; font-size: 18px; line-height: 27px; }
.sa-history-text p.sa-history-sub { font-weight: 700; margin-bottom: 0; }
/* In the timeline the year stands on its own line above its description, not in a gutter. */
/* De tijdlijn begint op de hoogte van de **eerste alinea** links, niet van de grote kop erboven.
   Dat is een omgekeerde beslissing: ze heeft een dag op één lijn met "Historiek" gestaan, op
   vraag van het bestuur, en datzelfde bestuur vroeg daarna om de alinea als ijkpunt. Dat is ook
   het patroon van de club zelf — in de Welkom-band begon de fotokolom op 157px onder de kop,
   gelijk met de eerste alinea, en 141 + 69 komt op diezelfde hoogte uit.
   De 141 is nagemeten met de inktgrenzen uit measureText en niet geschat: deze kop is Nunito
   Sans 30px in een regel van 45 en begint 10,9px ónder zijn vak, dus vakken gelijkzetten zou
   hem te laag zetten. (Geen backticks in dit commentaar: dit blok is een JS template literal.) */
.sa-history-timeline { padding-top: 141px; }
.sa-history-timeline .sa-guild-heading { line-height: 45px; margin: 0 0 44px; }
.sa-tl { margin-bottom: 22px; }
.sa-tl-year {
  font-family: "Montserrat", sans-serif;
  font-size: 18px; line-height: 21.6px; font-weight: 700; color: #222; margin-bottom: 4px;
}
.sa-tl-text { font-size: 13px; line-height: 17.5px; color: #222; }

.sa-guild {
  padding: 0 0 63.3px;
}
/* Nunito Sans, not the Montserrat the page's other headings use — this section's own choice
   on the live site, and h2 would otherwise inherit the site heading font. */
.sa-guild-heading {
  font-family: "Nunito Sans", sans-serif;
  font-size: 30px; line-height: 27px; font-weight: 400; color: #222;
  margin: 0 0 32px;
}
/* The history column's heading sits on a taller line than the two beside it. */
.sa-guild-heading-wide { line-height: 45px; margin-bottom: 21px; }
.sa-guild-side .sa-guild-heading { margin-top: 48px; }
.sa-guild-side .sa-guild-heading:first-child { margin-top: 0; }
.sa-guild p { font-size: 14px; line-height: 21px; color: #222; margin: 0 0 21px; }
/* The board's current membership is set in Montserrat, a size smaller than the text above it.
   Both need the .sa-guild prefix to outrank the paragraph rule above. (No backticks in here:
   this whole block is a JS template literal.) */
.sa-guild p.sa-guild-members { font-family: "Montserrat", sans-serif; font-size: 13px; line-height: 21px; }
.sa-guild p.sa-guild-note { font-size: 13px; line-height: 19.5px; color: #666; }
/* Boven de foto stond 8px en eronder 21, terwijl twee alinea's in diezelfde kolom ook 21 uit
   elkaar staan: de foto kleefde daardoor aan de tabel met de Chefs-doyen erboven. Het bestuur
   wees erop (september 2026). Nu draagt ze aan beide kanten dezelfde 21 als de tekst eromheen. */
.sa-guild-photo { display: block; width: 100%; height: 228px; object-fit: cover; margin: 21px 0; }
.sa-guild .sa-deans { max-width: none; margin: 0 0 8px; }

@media (max-width: 900px) {
  .sa-history {
    grid-template-columns: 1fr; max-width: var(--content-width);
    padding-left: 16px; padding-right: 16px; left: 0; gap: 40px;
  }
  .sa-history-timeline .sa-guild-heading { margin-top: 0; }
}

@media (max-width: 900px) {
  .sa-guild {
    grid-template-columns: 1fr; max-width: var(--content-width);
    padding-left: 16px; padding-right: 16px; left: 0; gap: 40px;
  }
  .sa-guild-photo { max-width: 419px; height: auto; aspect-ratio: 419 / 228; }
  /* Year and name stretched across the full column would read as a sparse table. */
  .sa-guild .sa-deans { max-width: 420px; }
}

/* "Mijn Jachtverlof", matching the club's own: the two opening lines in brown, the field
   label above the picker, the format notes as a grey bulleted list, and a full-width green
   send button. Measured on their page — Montserrat 14px throughout, brown rgb(73,47,15). */
.sa-permit { font-family: "Montserrat", sans-serif; }
.sa-permit-intro { font-size: 14px; line-height: 1.5; color: rgb(73, 47, 15); margin: 0 0 2px; }
.sa-permit-intro-bold { font-weight: 700; margin-bottom: 26px; }
.sa-permit-label { display: block; font-size: 14px; color: #242323; margin-bottom: 10px; }
.sa-permit input[type="file"] { display: block; margin-bottom: 12px; }
/* The scans already on file, each with its own remove button beside it. */
/* The page itself is Montserrat, matching the club's own — but the file list is data rather
   than prose, and reads better in the body face. */
.sa-permit-files { list-style: none; margin: 0 0 26px; padding: 0; font-family: "Nunito Sans", sans-serif; }
/* A picture of the scan, so a member sees at a glance which side is which. A permit is an
   identity document, so it is never cached to disk — see the no-store on its route. */
.sa-permit-preview {
  flex: 0 0 auto; width: 96px; height: 66px; border-radius: 4px; overflow: hidden;
  background: #ededed; display: block;
}
.sa-permit-preview img { width: 100%; height: 100%; object-fit: cover; object-position: top; display: block; }
.sa-permit-preview-none { display: block; width: 100%; height: 100%; }
.sa-permit-files li {
  display: flex; align-items: center; gap: 12px;
  padding: 8px 0; border-bottom: 1px solid var(--border);
}
.sa-permit-files li:last-child { border-bottom: none; }
.sa-permit-files form { margin: 0 0 0 auto; }
.sa-permit-remove {
  background: none; border: 0; padding: 0; cursor: pointer;
  font-family: "Nunito Sans", sans-serif; font-size: 13px; color: var(--text-muted);
  text-decoration: underline;
}
.sa-permit-remove:hover { color: #b3261e; }
.sa-permit-full { margin: 0 0 20px; }
/* An expired permit is what a board member is scanning the list for. */
.sa-permit-expired { color: #b3261e; font-weight: 700; }
.sa-permit-hints { margin: 0 0 26px; padding-left: 20px; font-size: 14px; color: var(--note); }
.sa-permit-hints li { margin-bottom: 3px; }
/* The send button runs the full width of the panel, as it does on the live page. */
.sa-permit .sa-permit-send { display: block; width: 100%; padding: 12px; font-size: 16px; }

/* The legal pages (cookies, privacy, disclaimer), matching the club's own: plain white, the
   title left in Montserrat 30px black, body Nunito Sans 14px #222 with bold sub-headings and
   bulleted lists. No banner, no panel — the text runs straight down the page. */
.sa-legal {
  width: 100%; min-width: 0; max-width: var(--content-width);
  margin: 0 auto; padding: 60px 24px 80px;
  font-family: "Nunito Sans", sans-serif; font-size: 14px; line-height: normal; color: #222;
}
.sa-legal-title {
  font-family: "Montserrat", sans-serif; font-size: 30px; font-weight: 700; color: #000;
  margin: 0 0 40px;
}
.sa-legal p { margin: 0 0 14px; }
/* 2px onder een tussenkop, zoals de artikelkop op de Statuten en het reglement: hij hoort bij de
   alinea eronder, maar hij is er niet de eerste regel van. De graad blijft die van de tekst — op
   de eigen bladzijde van de club staat deze kop alleen vet, niet groter. */
.sa-legal p.sa-legal-sub { font-weight: 700; margin: 24px 0 2px; }
/* An address block: its lines belong together, so they sit on consecutive lines rather than a
   paragraph apart. */
.sa-legal p.sa-legal-lines { margin: 0 0 14px; }
.sa-legal-list { margin: 6px 0 14px; padding-left: 22px; }
.sa-legal-list li { margin-bottom: 6px; }
.sa-legal a { color: inherit; }

/* An admin-editable text page ("Diverse"), matching the club's own. Measured on the live page:
   section headings Montserrat 18px/27px bold #444, article labels Montserrat 13px bold #444,
   body Nunito Sans 14px #444, and the reference material in brown rgb(73,47,15). */
.sa-page-text { font-family: "Nunito Sans", sans-serif; font-size: 14px; color: #444; }
.sa-page-heading {
  font-family: "Montserrat", sans-serif; font-size: 18px; line-height: 27px; font-weight: 700;
  color: #444; margin: 34px 0 14px;
}
.sa-page-heading:first-child { margin-top: 0; }
.sa-page-label {
  font-family: "Montserrat", sans-serif; font-size: 13px; font-weight: 700; color: #444;
  margin: 18px 0 0;
}
.sa-page-text p { margin: 0 0 14px; line-height: normal; }
.sa-page-text p.sa-page-label { margin: 18px 0 2px; }
.sa-page-link { font-size: 14px; }
.sa-page-link strong { font-family: "Nunito Sans", sans-serif; }
/* The club's reference material — the register link and the address block — is set in brown. */
.sa-page-brown, .sa-page-link, .sa-page-link a { color: rgb(73, 47, 15); }
/* Bruin is een kleur, geen afstand. Deze regel zette ook margin-bottom: 0, wat klopte toen het
   bruine blok alleen het adresblok van de Statuten was — maar het intern reglement eindigt óók
   bruin, en daar plakten de slotalinea's tegen elkaar. De aansluiting zit nu in .sa-page-line,
   waar de tekst zelf om vraagt. */
.sa-page-text p.sa-page-brown { line-height: normal; }

/* Their site styles the two languages of this page differently: the Dutch sets its article
   labels in Montserrat 13px grey, the French in Nunito Sans 14px brown with the body brown
   too. Reproduced rather than unified — it is their own page, not our inconsistency to fix. */
html[lang="fr"] .sa-page-text p { color: rgb(73, 47, 15); }
html[lang="fr"] .sa-page-text p.sa-page-label {
  font-family: "Nunito Sans", sans-serif; font-size: 14px; color: rgb(73, 47, 15);
}

/* The membership table: a #888 header bar with white centred labels, rows alternating white
   and #eee, exactly as the live page has it. */
.sa-fees { overflow-x: auto; margin: 0 0 30px; }
/* Een streep onder de laatste rij, zoals de streep boven de tabel onder "Lidmaatschap" staat:
   zonder haar houdt de tabel onderaan op zonder te sluiten. */
.sa-fees table { width: 100%; border-collapse: collapse; background: transparent; border-bottom: 1px solid var(--border); }
/* The header is NOT uppercased — the shared table-header rule does that, and the club's own
   table reads "Affiliation", not "AFFILIATION". Padding comes from their row heights: a 32px
   header row on 12px text, 41px body rows on 13px. (No backticks in here: this whole block is
   a JS template literal.) */
.sa-fees th {
  background: #888888; color: #fff; text-align: center;
  font-family: "Montserrat", sans-serif; font-size: 12px; font-weight: 700;
  line-height: normal; text-transform: none; letter-spacing: normal;
  padding: 8px; border: 0;
}
/* De scheiding tussen twee cellen is wit: op de grijze rijen leest ze als een raster, op de witte
   is ze er niet. De club zet er 1px, het bestuur vroeg een fijnere lijn — een halve pixel, wat op
   een scherm met dubbele dichtheid een echte haarlijn geeft en elders op één pixel afrondt. */
.sa-fees td {
  font-family: "Nunito Sans", sans-serif; font-size: 13px; line-height: normal; color: #000;
  text-align: center; padding: 11px 8px; border: 0.5px solid #fff;
}
.sa-fees tbody tr:nth-child(odd) { background: #ffffff; }
.sa-fees tbody tr:nth-child(even) { background: #eeeeee; }
/* Het vinkje en het kruisje van de app: in de tarieventabel in plaats van "Inbegrepen" en "Niet
   inbegrepen", en in de deelnemerslijst voor wie meeschiet en wie mee-eet. Eén teken, zodat de
   twee niet uit elkaar groeien. Het woord staat als label op het teken, dus wie de bladzijde laat
   voorlezen of erop blijft hangen, leest de tekst terug. */
.sa-mark-yes, .sa-mark-no { display: inline-flex; }
.sa-mark-yes svg, .sa-mark-no svg {
  width: 17px; height: 17px; display: block;
  fill: none; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round;
}
.sa-mark-yes svg { stroke: #2f5a43; }
.sa-mark-no svg { stroke: #a32b1c; }

/* Tips & Tricks, laid out like the club's own page: one large frame, a strip of three
   thumbnails under it, and a "Doorgaan" arrow bottom-right. */
.sa-tips { padding: 20px; }
.sa-tip-stage { position: relative; cursor: pointer; background: #000; aspect-ratio: 16 / 9; }
.sa-tip-stage-photo { display: block; width: 100%; height: 100%; object-fit: cover; }
.sa-tip-stage iframe { display: block; width: 100%; height: 100%; border: 0; }
/* The red pill the live page puts over the still. */
/* The red pill, in the same red the 404 page uses for its line. */
.sa-tip-stage-btn {
  position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);
  display: flex; align-items: center; gap: 10px;
  background: rgb(195, 43, 20); color: #fff; border: 0; border-radius: 999px;
  padding: 11px 28px; font-family: "Nunito Sans", sans-serif; font-size: 18px; cursor: pointer;
}
.sa-tip-strip { display: grid; grid-template-columns: repeat(3, 1fr); gap: 24px; margin-top: 24px; }
.sa-tip-card { display: block; text-decoration: none; color: inherit; }
.sa-tip-thumb { position: relative; display: block; aspect-ratio: 16 / 9; overflow: hidden; }
.sa-tip-thumb img { display: block; width: 100%; height: 100%; object-fit: cover; }
/* White on solid black, square, bottom-left — the live strip's own badge. */
.sa-tip-duration {
  position: absolute; left: 8px; bottom: 8px;
  background: #000; color: #fff; font-size: 14px; padding: 1px 6px;
}
/* Each thumbnail carries the same red pill, smaller. It shows on the one under the pointer and
   stays on the one now playing, where it reads "Wordt afgespeeld" instead. */
.sa-tip-play {
  position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);
  display: flex; align-items: center; gap: 7px; white-space: nowrap;
  background: rgb(195, 43, 20); color: #fff; border-radius: 999px;
  padding: 7px 16px; font-size: 14px;
  opacity: 0; transition: opacity 0.15s;
}
.sa-tip-card:hover .sa-tip-play, .sa-tip-card-current .sa-tip-play { opacity: 1; }
.sa-tip-title {
  display: -webkit-box; -webkit-line-clamp: 1; -webkit-box-orient: vertical; overflow: hidden;
  margin-top: 10px; font-size: 12px; color: #222;
}
.sa-tip-channel { display: block; margin-top: 3px; font-size: 12px; color: rgba(34, 34, 34, 0.5); }
.sa-tip-nav { display: flex; justify-content: space-between; margin-top: 22px; }
.sa-tip-nav a {
  display: inline-flex; align-items: center; gap: 14px;
  color: #222; text-decoration: none; font-size: 14px;
}
.sa-tip-nav a:hover { text-decoration: underline; }

@media (max-width: 760px) {
  .sa-tip-strip { grid-template-columns: 1fr; }
  .sa-tip-stage-btn { padding: 10px 20px; font-size: 15px; }
}

/* De 404 van de club, in de rustige vorm die het ledengedeelte sinds september 2026 draagt. Het
   bestuur vroeg erom (september 2026): de bladzijde was een rookfoto over het hele scherm met
   "OOPS!" in Oswald Medium 430px erover, en dat stond naast de rest van hun site alleen. Wat
   meekomt is waaraan ze te herkennen is — het woord, het korte bruine streepje, hun twee zinnen
   en hun eigen knop — in een kaart van 980px, dezelfde breedte als elke andere bladzijde hier.

   Het streepje staat optisch in het midden tussen "OOPS!" en de rode regel, en de marges zijn
   daarom niet gelijk. Dezelfde meting staat bij de 404 van het ledengedeelte in app-css.js; de
   getallen verschillen omdat de rode regel hier Montserrat 20px/30px is en daar Nunito Sans
   18px/27px. */
.sa-404 { padding: 56px 24px 72px; text-align: center; }
.sa-404-content {
  max-width: var(--content-width); margin: 0 auto;
  background: #fff; border: 1px solid #dbd8d1; border-radius: 5px;
  padding: 44px 24px 52px;
}
.sa-404-oops {
  font-family: "Oswald", sans-serif; font-weight: 500;
  font-size: min(180px, 22vw); line-height: 0.9; color: #666666;
}
.sa-404-rule {
  width: 83px; border-top-color: rgb(149, 132, 110);
  margin: 47px auto 38px;
}
.sa-404-lead {
  font-family: "Montserrat", sans-serif; font-weight: 700;
  font-size: 20px; line-height: 30px; color: rgb(195, 43, 20); margin: 0 0 22px;
}
.sa-404-hint { font-size: 16px; line-height: 28.8px; color: #222; margin: 0 0 26px; }
.sa-404-btn {
  display: inline-block; width: 170px; padding: 9px 0; line-height: 22px;
  background: #666666; color: #fff; text-decoration: none;
  border-radius: 5px; font-size: 15px;
}
/* The French line is a size smaller on the live page, where it runs longer. */
html[lang="fr"] .sa-404-lead { font-size: 18px; }

/* The Yourcenar quotation: a full-window grey band, the same #888 as the footer. */
.sa-quote-band {
  background: #888888; color: #fff; text-align: center;
  padding: 40px 24px 28px; margin: 0;
}
.sa-quote-band p { font-size: 20px; line-height: 24px; font-style: italic; margin: 0; }
.sa-quote-band .sa-quote-author { font-size: 14px; line-height: 18.2px; font-style: normal; margin-top: 22px; }

/* Below the width the two columns need, they stack — photos under the text, as Wix's own
   mobile layout does. The fixed 312px height goes with them, so the photos keep their ratio. */
@media (max-width: 900px) {
  .sa-welkom-band { padding-top: 40px; }
  .sa-welkom { grid-template-columns: 1fr; max-width: var(--content-width); padding: 0 16px 48px; left: 0; }
  .sa-welkom-text .sa-public-heading { margin-bottom: 30px; }
  .sa-welkom-photos { padding-top: 32px; order: 2; }
  /* Capped at their own size: blown up to the full column width they would tower over the
     text. Wix serves a separate mobile layout here, so there is no original to copy. */
  .sa-welkom-photos img { height: auto; max-width: 483px; aspect-ratio: 483 / 359; }
  .sa-welkom-caption { max-width: 483px; }
}

/* A form's own submit button sits bottom-right of its panel, where the calendar card puts its
   Details button. Only a form that is a panel's direct child: the small publish/delete buttons
   in the admin tables sit inside table cells and stay where they are. */
/* The action buttons at the end of an admin table row, right-aligned like the form buttons
   in the panels — the row's own text stays left. */
.sa-actions-cell { white-space: nowrap; text-align: right; }

.sa-panel > form > button[type="submit"].sa-btn:last-child,
.sa-card > form > button[type="submit"].sa-btn:last-child {
  display: block;
  margin-left: auto;
}
/* The event title on the detail page. It repeats the page banner, so it sits well clear of
   the badge row above it: 6px originally, plus the 15px the club asked for. */
.sa-event-title { margin: 21px 0 4px; }

/* Breadcrumbs sit between the page banner and the content, at the same width. */
/* Its own dark block, clear of the header and in the same column as the title banner below
   it — dark rather than white so it never has to compete with the background photo. */
.sa-breadcrumbs {
  width: 100%; min-width: 0; max-width: var(--content-width);
  margin: 22px auto 0;
  padding: 10px 24px;
  background: var(--ink);
  color: #fff;
  border-radius: 5px;
  font-size: 14px;
  display: flex; flex-wrap: wrap; gap: 10px; align-items: center;
}
.sa-breadcrumbs a { color: #fff; }
.sa-breadcrumbs a:hover { text-decoration: underline; }
/* The page you are on: not a link, and dimmed, so it reads as the end of the trail. */
.sa-breadcrumbs [aria-current] { color: rgba(255,255,255,0.65); }
.sa-breadcrumb-sep { color: rgba(255,255,255,0.45); }
.sa-sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

.sa-tabs { display: flex; gap: 8px; margin-bottom: 20px; flex-wrap: wrap; }
.sa-tabs a { padding: 8px 16px; border-radius: 20px; background: var(--paper); border: 1px solid var(--border); color: var(--ink); font-size: 13px; font-weight: 600; }
.sa-tabs a.active { background: var(--ink); color: #fff; border-color: var(--ink); }
.sa-tabs a:hover { text-decoration: none; }

.sa-video { position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden; border-radius: 8px; margin-bottom: 12px; background: #000; }
.sa-video iframe { position: absolute; top: 0; left: 0; width: 100%; height: 100%; border: 0; }

.sa-empty { color: var(--text-muted); font-style: italic; padding: 24px 0; }

/* Fits three cards per row at the 980px content width, matching the live Foto's /
   Resultaten grids, and drops to 2 then 1 as the viewport narrows. */
.sa-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 20px; margin: 0 0 20px; }
.sa-media-card {
  display: block; background: var(--ink); border-radius: 8px; overflow: hidden;
  color: #fff; text-decoration: none;
}
.sa-media-card:hover { text-decoration: none; opacity: 0.92; }
.sa-media-card-badge {
  font-family: "Montserrat", sans-serif; font-weight: 700; font-size: 13px; letter-spacing: 0.04em;
  text-align: center; padding: 10px 8px; background: rgba(255,255,255,0.06);
}
.sa-media-card-thumb {
  aspect-ratio: 4 / 3; width: 100%; object-fit: cover; display: block; background: #2a2a28;
}
.sa-media-card-thumb-placeholder {
  aspect-ratio: 4 / 3; width: 100%; display: flex; align-items: center; justify-content: center; background: #2a2a28;
}
.sa-media-card-thumb-placeholder img { width: 55%; }
.sa-media-card-thumb-placeholder svg { width: 38%; opacity: 0.6; }
.sa-media-card-title { padding: 12px 14px 4px; font-weight: 700; font-size: 14px; text-align: center; }
.sa-media-card-date { padding: 0 14px 14px; font-size: 12px; text-align: center; color: #cfcac2; }

.sa-content-body { white-space: pre-wrap; line-height: 1.7; }

.sa-event-card {
  display: flex; flex-wrap: wrap; background: var(--paper); border: none;
  border-radius: 5px; overflow: hidden; margin-bottom: 20px;
}
.sa-event-photo-wrap { position: relative; flex: 0 0 320px; max-width: 100%; background: #2a2a28; }
.sa-event-photo { width: 100%; height: 100%; min-height: 200px; object-fit: cover; display: block; }
.sa-event-photo-placeholder {
  width: 100%; height: 100%; min-height: 200px; display: flex; align-items: center; justify-content: center;
}
.sa-event-photo-placeholder img { width: 40%; }
/* Column layout so the Details button can be pinned to the bottom-right of the card. */
.sa-event-body { flex: 1 1 320px; padding: 22px 26px; display: flex; flex-direction: column; }
.sa-event-actions { margin-top: auto; align-self: flex-end; padding-top: 14px; }
.sa-event-status-row { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 10px; }
.sa-badge-closed { background: var(--danger); color: #fff; }
.sa-badge-countdown { background: #fff; border: 1px solid var(--border); color: var(--text-muted); }
.sa-badge-partner { background: #f5b661; color: #5a3200; }
.sa-badge-registered { background: #3e8e41; color: #fff; }

/* A translucent panel wrapper for pages whose content isn't already in .sa-card. */
.sa-panel { background: var(--panel); border-radius: 5px; padding: 28px; margin-bottom: 20px; }
/* Section headings are solid chips rather than text on the photo, so the two sections are
   told apart at a glance: green for what's coming up, grey for the archive. */
.sa-section-heading {
  display: inline-block;
  font-family: "Montserrat", sans-serif; font-size: 14px; font-weight: 700;
  text-transform: uppercase; letter-spacing: 1px;
  background: var(--accent); color: #fff;
  padding: 9px 20px; border-radius: 4px;
  margin: 4px 0 14px;
}
/* Extra breathing room so the archive reads as a separate block. */
.sa-section-heading-past { background: #8f8f8f; margin-top: 80px; }

/* Past events are shown in grey — greyscale photo, muted panel and text — so the archive is
   clearly distinct from what's still coming up. */
.sa-event-card-past { background: #f0f0f0; }
.sa-event-card-past .sa-event-photo { filter: grayscale(1); }
.sa-event-card-past .sa-event-photo-placeholder { background: #3a3a3a; }
.sa-event-card-past .sa-event-photo-placeholder img { filter: grayscale(1); }
.sa-event-card-past .sa-event-body,
.sa-event-card-past .sa-event-body h3 a { color: var(--text-muted); }
.sa-event-card-past .sa-badge-partner { background: #dcdcdc; color: #5a5a5a; }
.sa-event-card-past .sa-badge-closed { background: #9a9a9a; }
.sa-event-card-past .sa-badge-accent { background: #8a8a8a; }
.sa-event-card-past .sa-badge-registered { background: #8a8a8a; }

/* A past event's detail page, greyed like its card on the calendar. */
/* Solid rather than translucent — the calendar and the event page carry photos and long
   lists, and the background showing through made both restless. */
.sa-panel-solid { background: var(--paper); }
.sa-panel-past { background: #f0f0f0; color: var(--text-muted); }
.sa-panel-past img { filter: grayscale(1); }
.sa-panel-past h2, .sa-panel-past h3, .sa-panel-past .sa-event-title { color: var(--text-muted); }
.sa-panel-past .sa-badge-registered, .sa-panel-past .sa-badge-accent { background: #8a8a8a; }
.sa-panel-past .sa-badge-partner { background: #dcdcdc; color: #5a5a5a; }

.sa-meta-label { font-weight: 700; }
/* Explicit margins so the meta lines sit the same on the card (divs) and the detail page
   (paragraphs, which carry a default margin). */
.sa-event-meta-date { margin: 10px 0 0; }
.sa-event-meta-addr { margin: 0; }
/* The divider carries the space above the Info block, on the card and the detail page alike. */
.sa-event-divider { border: none; border-top: 1px solid var(--border); margin: 20px 0 14px; }
/* The description carries no "Info:" label — the divider above it sets it apart. */
.sa-event-meta-info { margin: 0; }
/* On the detail page the teaser leads the long text, so it is set bold. The calendar card
   keeps it plain: there it is the only body text, and bold would make the whole list heavy. */
.sa-event-lead { font-weight: 600; color: var(--text); }
/* The long "Over het evenement" text, when Wix has one, sits under the teaser. Its
   paragraphs are real <p> elements, so the space between them is this margin rather than
   a blank line at the body line-height. */
.sa-event-about { margin-top: 14px; line-height: 1.7; }
.sa-event-about p { margin: 0 0 10px; }
.sa-event-about p:last-child { margin-bottom: 0; }
/* A "Belangrijk:" / "Opgelet:" paragraph, flagged with the warning colour and an icon. */
.sa-notice { display: flex; gap: 8px; align-items: flex-start; color: var(--danger); font-weight: 700; }
.sa-notice svg { flex-shrink: 0; margin-top: 3px; }
.sa-panel > h2:first-child, .sa-panel > h3:first-child { margin-top: 0; }

.sa-footer { background: var(--footer-bg); color: var(--footer-text); font-size: 13px; }
.sa-footer-inner {
  max-width: var(--content-width); margin: 0 auto; padding: 26px 24px;
  display: flex; gap: 32px; flex-wrap: wrap; justify-content: space-between;
}
.sa-footer-col { line-height: 1.6; }
.sa-footer-col-right { text-align: right; }
.sa-footer-heading { font-weight: 700; margin-bottom: 4px; }
.sa-footer a { color: var(--footer-text); text-decoration: underline; }
.sa-footer-links { margin-top: 6px; }

/* De voettekst volgt de bladzijde waaronder ze staat, en dat verschilt per bladzijde. Op de
   juridische bladzijden klopte ze al: die dragen de kolom van 980px en de voettekst staat er tot
   op de pixel onder (beide 135…1115 bij een venster van 1250). De startbladzijde draagt bredere
   banden, en daar stond de voettekst tweehonderd pixels naar binnen ten opzichte van de tekst
   erboven; het bestuur wees erop. Ze neemt daar nu de maten van de gildeband — de band die er
   pal boven staat — zodat haar linker- en rechterrand op die van de tekst vallen (30…1208 bij
   1440). De zijpadding gaat eraf omdat de band die ook niet heeft; de 26px boven en onder blijft. */
/* Het wapenschild stond op x=204 terwijl de bladzijde eronder op 131 begint — de kopbalk draagt
   een kolom van 1080 met 24px padding, en die hoort bij niets. Op de startbladzijde neemt ze nu
   dezelfde 1179 als de banden, zodat het schild en de eerste letter van de tekst eronder op één
   verticale lijn staan (en de taaltegels rechts op de rechterrand). Het bestuur vroeg erom
   (september 2026). De juridische bladzijden dragen een kolom van 980 en blijven ongemoeid. */
body.sa-body-home .sa-header-inner,
body.sa-body-home .sa-footer-inner {
  width: calc(100% - 32px); max-width: 1179px;
  padding-left: 0; padding-right: 0;
}
/* Zodra de gildeband stapelt, doet de voettekst dat mee — met dezelfde 16px marge, anders
   beginnen de twee acht pixels uit elkaar. */
@media (max-width: 900px) {
  body.sa-body-home .sa-footer-inner {
    max-width: var(--content-width);
    padding-left: 16px; padding-right: 16px;
    left: 0;
  }
}

/* Below the content width there is no room for the centred 980px column, so add gutters. */
@media (max-width: 1010px) {
  .sa-main { padding-left: 16px; padding-right: 16px; }
  .sa-page-banner, .sa-breadcrumbs { margin-left: 16px; margin-right: 16px; width: auto; }
}
@media (max-width: 720px) {
  .sa-footer-col-right { text-align: left; }
  .sa-page-banner h1 { font-size: 22px; }
  .sa-card, .sa-panel { padding: 20px; }
  /* Stacked above the text, a full-height photo dominates the card — crop it instead. */
  .sa-event-photo-wrap { flex-basis: 100%; max-height: 220px; }
}

body.sa-app {
  --bg: #fbfbfa;
  --surface: #ffffff;
  /* De twee lijndiktes van de app: --line voor een rand die iets omsluit (kaart, veld, tabel),
     --line-soft voor een streep tussen twee blokken. Ze stonden op 1.26:1 en 1.16:1 tegen wit,
     wat op een scherm met wat omgevingslicht bijna niets is. Een stap donkerder, met het verschil
     tussen de twee behouden. */
  --line: #dbd8d1;      /* 1.42:1 */
  --line-soft: #e4e1da; /* 1.31:1 */
  /* Drie graden zwart op wit, elk met hun contrast tegen --surface erbij. De derde was #8b8f96
     en haalde maar 3.25:1, terwijl hij op 11 tot 13px staat — kolomkoppen, kruimelpad, de regels
     onder een veld. De vloer voor kleine tekst is 4.5, dus die viel eronder. Nu 4.69, en de
     tweede een stap mee, zodat de rangorde tussen de drie blijft staan. */
  --ink: #16181b;   /* 17.8:1 */
  --ink-2: #4e5158; /*  8.0:1 */
  --ink-3: #70747b; /*  4.7:1 */
  --accent: #2f5a43;
  --accent-ink: #21432f;
  --accent-soft: #edf3ef;
  --gold: #8a6d1f;
  --gold-soft: #f7f1e0;
  /* The colour of a remark the app makes — the disclaimers, the empty states, the instruction on
     Mijn Jachtverlof. Its own token rather than --gold, which also fills the Serment badges and
     the administrator's avatar and should stay the ochre the board asked for.
     This is as orange as it can get and still carry as 12.5px text: 4.58:1 on white, where the
     accessibility floor for small text is 4.5. #bf5a00 is 4.49 and #c25e00 is 4.29 — visibly
     brighter, and below the line. Louder than this means larger text, not a louder colour. */
  --note: #b45f06;
  --danger: #a32b1c;
  --danger-soft: #fbecea;
  /* Wat een hele klikbare rij wordt zodra de muis erover staat. Het was #f5f5f5: neutraal grijs
     in een verder warm palet, en 1.09:1 tegen wit — zo weinig dat een rij die volledig een link
     is er niet als een link uitzag. Nu warm en een stap sterker. */
  --hover: #efece7; /* 1.18:1 */
  --radius: 6px;
  --sidebar: 236px;

  background: var(--bg);
  color: var(--ink);
  font-size: 14px;
  line-height: 1.5;
  margin: 0;
  -webkit-font-smoothing: antialiased;
}
body.sa-app * { box-sizing: border-box; }
/* One family for the whole members' area: Nunito Sans, the club's own, the same face as the body
   text on the public site.
   The universal selector, not a list. Naming the elements caught the ones that do not inherit
   font-family — <button>, <input>, <th> — but missed a second kind entirely: a class in the
   stylesheet the public site uses that sets its *own* family. .sa-page-label, .sa-fees,
   .sa-archive-heading and .sa-permit each carry Montserrat, and an explicit declaration always
   beats an inherited one, so those blocks stayed Montserrat inside the app.
   body.sa-app * is (0,1,1) against their (0,1,0), so it wins wherever it applies — and it cannot
   reach the public site, which never carries the class. */
body.sa-app, body.sa-app * {
  font-family: "Nunito Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
}

/* ---- Shell --------------------------------------------------------------- */
.sa-shell { display: grid; grid-template-columns: var(--sidebar) 1fr; min-height: 100vh; }
.sa-col { min-width: 0; display: flex; flex-direction: column; }

.sa-side {
  background: var(--surface); border-right: 1px solid var(--line);
  padding: 20px 14px; position: sticky; top: 0; height: 100vh; overflow-y: auto;
}
.sa-app .sa-brand { display: flex; align-items: center; gap: 10px; padding: 0 8px 20px; text-decoration: none; color: inherit; }
.sa-app .sa-brand img { width: 34px; height: 34px; object-fit: contain; }
/* The wordmark follows the masthead on the public site: uppercase, the eyebrow regular over the
   name bold with its letter-spacing. Scaled to a 236px sidebar — the public one is 15/23px beside
   a 73px crest — which is why the sizes differ and the ratio does not. */
.sa-brand-eyebrow, .sa-brand-name { text-transform: uppercase; }
.sa-brand-eyebrow { display: block; font-size: 9.5px; font-weight: 400; line-height: 14px; color: var(--ink-3); }
.sa-brand-name {
  display: block; font-size: 14.5px; font-weight: 700; line-height: 15px; letter-spacing: 0.43px;
  color: var(--ink);
}
.sa-nav-label {
  font-size: 10.5px; font-weight: 600; letter-spacing: 0.8px; text-transform: uppercase;
  color: var(--ink-3); padding: 14px 8px 6px;
}
.sa-nav a, .sa-nav-out button {
  display: flex; align-items: center; gap: 9px; width: 100%;
  padding: 7px 8px; border-radius: var(--radius); border: 0; background: none;
  font-size: 13.5px; font-weight: 400; color: var(--ink-2);
  text-decoration: none; text-align: left; cursor: pointer;
}
.sa-nav a:hover, .sa-nav-out button:hover { background: var(--line-soft); color: var(--ink); }
.sa-nav a.on { background: var(--accent-soft); color: var(--accent-ink); font-weight: 500; }
.sa-nav svg { width: 15px; height: 15px; flex: 0 0 15px; stroke: currentColor; fill: none; stroke-width: 1.6; }

.sa-top {
  display: flex; align-items: center; gap: 14px; padding: 0 32px; height: 56px;
  background: var(--surface); border-bottom: 1px solid var(--line); position: sticky; top: 0; z-index: 5;
}
.sa-side-toggle { display: none; border: 0; background: none; padding: 4px; cursor: pointer; color: var(--ink-2); }
.sa-side-toggle svg { width: 18px; height: 18px; display: block; }
.sa-app .sa-crumbs { font-size: 12.5px; color: var(--ink-3); flex: 1; min-width: 0; }
.sa-app .sa-crumbs a { text-decoration: none; color: inherit; }
.sa-app .sa-crumbs a:hover { color: var(--ink-2); }
.sa-app .sa-crumbs > span { margin: 0 6px; color: #c9c7c2; }
.sa-app .sa-crumbs [aria-current] { margin: 0; color: var(--ink-2); }
.sa-who { display: flex; align-items: center; gap: 10px; font-size: 13px; color: var(--ink-2); white-space: nowrap; }
.sa-who-link { display: flex; align-items: center; gap: 10px; text-decoration: none; color: inherit; }
.sa-who-name { text-decoration: none; color: inherit; }
.sa-who-link:hover .sa-who-name { color: var(--ink); }
.sa-app .sa-lang { display: flex; border: 1px solid var(--line); border-radius: var(--radius); overflow: hidden; background: none; }
/* NL en FR in het midden van hun tegel. De publieke opmaak centreert ze met flex; hier stond
   display: block, en dan doet justify-content niets — het woord kwam tegen de linkerrand te staan
   binnen een tegel die 40px breed blijft (min-width uit diezelfde publieke regel), 9px links en
   16px rechts. */
.sa-app .sa-lang a {
  display: flex; align-items: center; justify-content: center;
  padding: 3px 9px; font-size: 12px; text-decoration: none; color: var(--ink-3);
  background: none; width: auto; height: auto; font-weight: 400;
}
.sa-app .sa-lang a.active { background: var(--ink); color: #fff; }

.sa-app .sa-avatar {
  width: 28px; height: 28px; flex: 0 0 28px; border-radius: 50%; background: var(--accent); color: #fff;
  display: flex; align-items: center; justify-content: center;
  font-family: inherit; font-size: 11px; font-weight: 600; letter-spacing: 0;
}
.sa-app .sa-avatar-admin { background: var(--gold); color: #fff; }

.sa-page { padding: 28px 32px 40px; max-width: 1180px; width: 100%; flex: 1; }
/* De titel links, en rechts wat bij de hele bladzijde hoort. Zonder een tweede kind gedraagt de
   rij zich als voorheen. */
.sa-page-head { display: flex; align-items: center; justify-content: space-between; gap: 16px; margin-bottom: 20px; }
/* De titel met wat er pal naast hoort — "+ Partner" bij een activiteit — als één groep links. */
.sa-page-titel { display: flex; align-items: center; gap: 10px; min-width: 0; }
.sa-page-aside { flex: 0 0 auto; line-height: 0; }
/* Die line-height: 0 is er voor het beeldmerk van ShotKam, dat als enige kind een afbeelding is;
   de labels van een activiteit staan er sinds september 2026 ook, en die dragen tekst. */
.sa-page-aside .sa-event-status-row { line-height: normal; }
/* Op de hoogte van de titel: het beeldmerk is 800x133, dus 22px hoog is 132px breed. */
.sa-page-aside img { height: 22px; width: auto; display: block; }
.sa-page-head h1 { font-size: 23px; font-weight: 700; letter-spacing: -0.3px; margin: 0; }

.sa-app-foot {
  display: flex; justify-content: space-between; gap: 16px; flex-wrap: wrap;
  padding: 16px 32px; border-top: 1px solid var(--line);
  font-size: 12.5px; color: var(--ink-3);
}
.sa-app-foot a { color: inherit; margin-left: 14px; }
/* De maker staat in dezelfde regel als het copyright en niet bij de drie links rechts, dus valt
   de 14px die daar de links uit elkaar houdt hier weg. */
.sa-app-foot .sa-credit { margin-left: 0; font-weight: 600; }

/* Het vinkvakje, getekend in plaats van dat van het besturingssysteem. Dat laatste is op elke
   Mac, elke Windows en elke telefoon iets anders, en het blauw ervan is het enige blauw in deze
   app. Dit is er de groene kaart van: wit vakje met een rand als elk ander veld, gevuld met het
   accent zodra het aanstaat, en een wit vinkje erin.

   Het vinkje is een SVG in de achtergrond en geen ::after op de input: pseudo-elementen op een
   vervangen element zijn niet overal betrouwbaar. In de data-URI staat stroke='white' en geen
   hexkleur, want een # erin zou het adres afkappen.

   appearance: none haalt ook het toetsenbordkader weg dat de browser zelf tekende, dus staat
   :focus-visible er expliciet bij — anders is met Tab niet meer te zien waar je staat. */
.sa-app input[type=checkbox] {
  appearance: none; -webkit-appearance: none;
  width: 18px; height: 18px; flex: 0 0 18px; margin: 0; padding: 0;
  border: 1.5px solid var(--line); border-radius: 5px; background: var(--surface);
  cursor: pointer; vertical-align: middle;
  transition: background-color 0.12s ease, border-color 0.12s ease;
}
.sa-app input[type=checkbox]:hover { border-color: var(--ink-3); }
.sa-app input[type=checkbox]:checked {
  background-color: var(--accent); border-color: var(--accent);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='white' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3.5 8.4l3 3 5.8-6'/%3E%3C/svg%3E");
  background-size: 15px 15px; background-position: center; background-repeat: no-repeat;
}
.sa-app input[type=checkbox]:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.sa-app input[type=checkbox]:disabled { cursor: not-allowed; background-color: #f4f3f0; border-color: #ddd9d2; }
.sa-app input[type=checkbox]:disabled:checked { background-color: var(--ink-3); border-color: var(--ink-3); }

/* De rappelknop staat naast de filterbalk en niet erin: die balk is een GET-formulier en dit is
   een POST. Dezelfde regel, dezelfde hoogte. */
.sa-app .sa-rappel { display: inline-flex; margin: 0 0 0 10px; }

/* De plaatshouders boven een e-mailtekst. Als code gezet, want het zijn tekens die letterlijk
   overgenomen moeten worden; de verplichte dragen het accent, zodat te zien is welke niet weg mag. */
/* De plaatshouder links, wat hij invult rechts: een <dl> op twee kolommen, de linker zo breed als
   de langste plaatshouder. Het was een rij losse codes zonder uitleg, en dan blijft {inschrijven_tot}
   iets om te raden. */
/* De uitleg staat ónder zijn plaatshouder en niet ernaast. Het was een raster van twee kolommen,
   met de naam op max-content — en sinds elke plaatshouder er twee draagt is die kolom breder dan
   de popup: de uitleg kreeg nog drie woorden per regel en liep rechts het vak uit. Onder elkaar
   past elke naam, hoe lang hij ook wordt. */
.sa-app .sa-plaatshouders { margin: 13px 0 0; }
.sa-app .sa-plaatshouders dt { margin: 14px 0 0; }
.sa-app .sa-plaatshouders dt:first-child { margin-top: 0; }
.sa-app .sa-plaatshouders dd { margin: 2px 0 0; font-size: 12.5px; color: var(--ink-2); }
/* Geen vakje om een plaatshouder: de accolades zeggen al dat het er een is, en een rand plus een
   vulling eromheen maakt er een knop van. Halfvet houdt hem los van de uitleg ernaast; een
   verplichte houdt daarbij het accent, dat nu het enige is wat hem onderscheidt. */
.sa-app .sa-plaatshouders code {
  font-size: 12.5px; font-weight: 600; padding: 0;
  background: none; border: 0; color: var(--ink-2);
}
.sa-app .sa-plaatshouders code.sa-verplicht { color: var(--accent); }
/* In de popup is elke plaatshouder een knop die zichzelf invoegt. Ze ziet eruit als de code die
   ze was — geen vakje, geen rand — want een rij knoppen met randen leest als een werkbalk, en dit
   is een opsomming. Wat zegt dat ze aanklikbaar is: het handje, en de onderstreping onder de muis.
   Een verplichte houdt het accent, net als voorheen. */
.sa-app .sa-ph-knop {
  font: inherit; font-size: 12.5px; font-weight: 600; font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  padding: 0; border: 0; background: none; color: var(--ink-2); cursor: pointer; text-align: left;
  white-space: normal;
}
.sa-app .sa-ph-knop:hover { text-decoration: underline; }
.sa-app .sa-ph-knop.sa-verplicht { color: var(--accent); }
.sa-app .sa-ph-knop:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 3px; }
/* De Franse naam van dezelfde plaatshouder, lichter: het is één knop en geen tweede keuze. Welke
   van de twee er ingevoegd wordt, beslist het veld waarin de cursor stond. */
.sa-app .sa-ph-fr { color: var(--ink-3); font-weight: 400; }

/* ---- Surfaces ------------------------------------------------------------ */
.sa-app .sa-panel, .sa-app .sa-card, .sa-app .sa-table-card {
  background: var(--surface); border: 1px solid var(--line); border-radius: 8px;
  box-shadow: none; backdrop-filter: none; padding: 0; margin: 0 0 18px;
}
.sa-app .sa-panel, .sa-app .sa-card { padding: 20px; }
.sa-app .sa-table-card { overflow-x: auto; }
.sa-app .sa-panel-solid { background: var(--surface); }
.sa-app .sa-panel-past, .sa-app .sa-inscription-past { opacity: 0.72; }

/* Every title carries the same weight: 700. The small uppercase labels — section headings,
   fieldset legends, column headers — stay at 600; they name a group, they are not titles. */
.sa-app h2 {
  font-family: inherit; font-size: 15px; font-weight: 700; letter-spacing: 0;
  text-transform: none; color: var(--ink); margin: 0 0 12px;
}
/* The section headings on the calendar were filled green pills. Here they are what they say
   they are: a heading over the group of rows that follows. */
.sa-app .sa-section-heading, .sa-app .sa-section-heading-past {
  display: block; background: none; color: var(--ink-3); padding: 0; border-radius: 0;
  /* Halfvet, waar de titel van een blok vet staat. Die opent een kaart en draagt haar naam; deze
     staat los boven een lijst en hoeft alleen te zeggen waar de ene groep ophoudt en de andere
     begint. Op het bestuur zijn vraag lichter gehouden dan de naam van de avond eronder. */
  font-family: inherit; font-size: 11px; font-weight: 600; letter-spacing: 0.8px;
  text-transform: uppercase; margin: 0 0 12px;
}
/* Een sectiekop opent een blok, dus draagt hij de alineagrens van 34px boven zich — ook de
   eerste, waar hij tegen de paginatitel aan komt te staan: die 34 klapt samen met de 20 van
   .sa-page-head en wint. Zo staat "Binnenkort" onder de titel even ver van wat erboven staat als
   "Voorbije activiteiten" onder de lijst erboven. */
.sa-app .sa-section-heading, .sa-app .sa-section-heading-past { margin-top: 34px; }
/* Een lijn tussen wat komt en wat geweest is. De 34px erboven zei al dat er een grens was, maar op
   een bladzijde met één rij in elke groep leest die ruimte als lucht en niet als scheiding. Alleen
   wanneer er iets boven staat: is er niets komends, dan opent deze kop de bladzijde en valt er
   niets te scheiden. Geldt op Mijn Inschrijvingen en op de Kalender, die dezelfde twee groepen
   dragen — twee schermen die hetzelfde tonen, tonen het hetzelfde. */
.sa-app .sa-section-heading-past:not(:first-child) {
  border-top: 1px solid var(--line-soft); padding-top: 26px;
}
.sa-app h3 { font-size: 14px; font-weight: 700; margin: 0 0 8px; }
.sa-app .sa-lead { font-size: 13.5px; color: var(--ink-2); }
.sa-app .sa-muted { color: var(--ink-3); font-size: 13px; }
/* Every remark the app makes inside a form: what a field will fill in on its own, what the limit
   is, who keeps this data. One colour and one mark, so a member learns to recognise them.
   The mark sits on the first line rather than above the block — these are sentences in a form,
   not empty states — and the indent keeps a second line under the first instead of under the
   icon. It is a background image because the views print a bare <p>. */
.sa-app .sa-note, .sa-app .sa-fset-note,
.sa-app .sa-permit-hints, .sa-app .sa-permit-full {
  color: var(--note); font-size: 12.5px;
}
.sa-app .sa-note, .sa-app .sa-fset-note, .sa-app .sa-permit-full {
  padding-left: 23px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='15' height='15' viewBox='0 0 24 24' fill='none' stroke='%23b45f06' stroke-width='1.8' stroke-linecap='round'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3Cpath d='M12 7.5v5.5'/%3E%3Cpath d='M12 16.4v.1'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: 0 2px;
}
/* De lijst onder het jachtverlof draagt dezelfde mark als elke andere opmerking, per regel, in
   plaats van een opsommingsteken. Het waren er ooit vier waarvan drie hetzelfde zeiden; nu zijn
   het er twee of drie die elk iets anders melden, en dan is het teken geen ruis meer maar wat ze
   verbindt met de opmerkingen in de rest van het formulier. */
.sa-app .sa-permit-hints { list-style: none; padding-left: 0; margin: 0; }
.sa-app .sa-permit-hints li {
  padding-left: 23px; margin-bottom: 7px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='15' height='15' viewBox='0 0 24 24' fill='none' stroke='%23b45f06' stroke-width='1.8' stroke-linecap='round'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3Cpath d='M12 7.5v5.5'/%3E%3Cpath d='M12 16.4v.1'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: 0 2px;
}
.sa-app .sa-permit-hints li:last-child { margin-bottom: 0; }
/* Twee opmerkingen onder elkaar staan overal even ver uit elkaar: dicht genoeg om als een groep
   te lezen, ruim genoeg om twee zinnen te blijven. Het was 4px in de lijst onder het jachtverlof
   en 13px tussen de twee losse opmerkingen onder het wachtwoord. De marges klappen samen, dus
   allebei de zijden moeten het zeggen — vandaar de :has(). */
/* Een voetnoot onderaan een blok: dezelfde okerkleur en dezelfde maat als elke andere opmerking,
   maar zonder het rondje met de i — hier is het sterretje zelf de verwijzing, en twee tekens voor
   één regel is er een te veel. De marker staat in een eigen kolom zodat een tweede regel onder de
   eerste uitkomt en niet onder het sterretje. Het bestuur vroeg deze vorm (oktober 2026): de
   verduidelijkingen onderaan, met * en ** naar het veld waar ze bij horen. */
.sa-app .sa-voetnoot {
  color: var(--note); font-size: 12.5px;
  display: grid; grid-template-columns: 23px 1fr; margin: 0;
}
.sa-app .sa-voetnoot + .sa-voetnoot { margin-top: 7px; }
/* Het sterretje van een voetnoot, achter het label van het veld waar ze over gaat. */
.sa-app .sa-voetnoot-teken { color: var(--note); font-weight: 600; }

/* Twee opmerkingen onder elkaar staan 3px uit elkaar, overal in de app. Het was 7, en dat las als
   twee losse zinnen waar het één groep moet zijn; het bestuur wees erop (oktober 2026). Op de inkt
   gemeten is het verschil groter dan het getal doet vermoeden: de regelafstand legt er aan elke
   kant ruim 3px bij, dus 3px marge geeft ±9px tussen de letters, tegen ±6px tussen twee regels
   bínnen dezelfde opmerking. Dicht genoeg om samen te horen, ver genoeg om twee zinnen te blijven.
   Allebei de kanten moeten het zeggen: aangrenzende marges klappen samen en de grootste wint. */
.sa-app .sa-note:has(+ .sa-note) { margin-bottom: 3px; }
.sa-app .sa-note + .sa-note { margin-top: 3px; }

/* Every message that says "there is nothing here" looks the same: centred, ochre, semi-bold,
   with a mark above it — the shape the Resultaten page already used. Grey italics read as a
   fault; this reads as news. Set on .sa-empty itself, so all fourteen places that print one
   follow without being touched. The icon is a background image because the views print a bare
   <p> and there is nowhere to hang an <svg>. */
.sa-app .sa-empty {
  display: block; text-align: center; padding: 34px 20px;
  font-size: 14px; font-weight: 600; font-style: normal; color: var(--note);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='30' height='30' viewBox='0 0 24 24' fill='none' stroke='%23b45f06' stroke-width='1.5' stroke-linecap='round'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3Cpath d='M8.5 12h7'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: center 34px;
  padding-top: 76px;
}
/* The Resultaten page keeps its own mark — the cup that section will hold — but the same shape. */
.sa-soon { text-align: center; padding: 34px 20px; }
.sa-app a { color: var(--accent-ink); }

/* Nothing in the members' area underlines on hover. What is clickable says so by lighting up:
   a row takes --hover across its whole width, a card takes it behind the card. Five rules in the
   stylesheet the public site uses reach in here — a bare a:hover among them — so they are turned
   off by name rather than hoped away. */
body.sa-app a:hover,
body.sa-app .sa-wix-table th a:hover,
body.sa-app .sa-cell-name a:hover .sa-name,
body.sa-app .sa-crumbs a:hover,
body.sa-app .sa-breadcrumbs a:hover {
  text-decoration: none;
}
/* The ones that had only the underline to show they were live get the background instead. */
body.sa-app .sa-wix-table th a:hover { color: var(--ink); }
body.sa-app .sa-crumbs a:hover { color: var(--ink); }
body.sa-app .sa-tip-card:hover, body.sa-app .sa-archive-heading:hover { background: var(--hover); }

/* ---- Buttons ------------------------------------------------------------- */
.sa-app .sa-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  height: 34px; padding: 0 14px; border-radius: var(--radius);
  font-family: inherit; font-size: 13px; font-weight: 500; letter-spacing: 0;
  border: 1px solid var(--accent); background: var(--accent); color: #fff;
  text-decoration: none; cursor: pointer; width: auto;
}
.sa-app .sa-btn:hover { background: var(--accent-ink); border-color: var(--accent-ink); }
.sa-app .sa-btn-secondary, .sa-app .sa-btn-outline {
  background: var(--surface); border-color: var(--line); color: var(--ink);
}
.sa-app .sa-btn-secondary:hover, .sa-app .sa-btn-outline:hover { background: var(--line-soft); border-color: #d9d6d1; }
.sa-app .sa-btn-danger { background: var(--surface); border-color: var(--line); color: var(--danger); }
.sa-app .sa-btn-danger:hover { background: var(--danger-soft); border-color: #e8c4bf; }
.sa-app .sa-btn-row, .sa-app .sa-btn-s { height: 28px; padding: 0 10px; font-size: 12.5px; }
/* De knoppen van een beheerlijst staan op gelijke afstand van elkaar, en dat vroeg een flexrij.
   Inline naast elkaar is de ruimte ertussen deels de spatie die de HTML zelf meebrengt (de
   regelovergang tussen twee elementen) en deels een marge: tussen twee links stond er alleen die
   spatie, tussen een link en een formulier die spatie plus 6px. Drie knoppen, drie verschillende
   gaten. Met een flexrij telt alleen de gap nog, want tekstknopen tussen flexitems vallen weg.
   Het bestuur wees erop (oktober 2026).
   De marge die het publieke stylesheet op een tweede formulier zet, moet daarvoor terug naar nul:
   ze kwam anders bij de gap bovenop. */
.sa-app .sa-actions-cell { text-align: right; white-space: nowrap; }
.sa-app .sa-acties {
  display: flex; justify-content: flex-end; align-items: center; gap: 6px;
}
/* Een kolom met getallen staat gecentreerd, kop en cellen samen, en met cijfers van gelijke
   breedte zodat de reeks niet gaat wiebelen.
   De kop draagt de tabelnamen mee (.sa-wix-table th, thead th): die regel staat verderop en zet
   text-align: left met dezelfde zwaarte, dus zonder die selectors erbij bleef de kop links staan
   terwijl de cellen eronder al gecentreerd waren. */
.sa-app td.sa-num,
.sa-app .sa-wix-table th.sa-num,
.sa-app thead th.sa-num { text-align: center; font-variant-numeric: tabular-nums; }
.sa-app .sa-actions-cell .sa-btn { height: 28px; padding: 0 10px; font-size: 12.5px; }
/* Het formulier om één knop is zelf een flexitem, zo breed als die knop. Het heeft één versie
   lang display:contents gedragen (geen backticks hier: die sluiten de stylesheet) — dan is de knop
   het flexitem en telt de gap tussen de knoppen
   zelf — maar een formulier dat geen vak meer maakt, is een verrassing voor wie dit later leest,
   en het levert hier niets op: één knop in een krimpend vak is even breed als die knop.
   De marge die het publieke stylesheet op een tweede formulier zet, gaat naar nul; ze kwam
   anders bovenop de gap.

   De flexrij staat in een omhulling ín de cel en niet op de cel zelf: display:flex op een <td>
   haalt die uit de tabelrij, en dan houdt de scheidingslijn onder elke rij op waar de knoppen
   beginnen. Dat was goed te zien. */
.sa-app .sa-acties form { display: flex; margin-left: 0; }

/* ---- Forms --------------------------------------------------------------- */
/* 2px tussen een label en zijn veld. Het waren er 5; het bestuur zette ze stap voor stap dichter. */
.sa-app .sa-field, .sa-app .sa-fcell { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.sa-app .sa-field { margin-bottom: 14px; }
.sa-app .sa-field > label, .sa-app .sa-fcell > label { font-size: 12px; color: var(--ink-2); font-weight: 400; }
.sa-app input:not([type=checkbox]):not([type=radio]):not([type=submit]):not([type=button]),
.sa-app select, .sa-app textarea {
  height: 36px; padding: 0 11px; font: inherit; font-size: 13.5px;
  border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface); color: var(--ink); width: 100%; margin: 0;
}
.sa-app textarea { height: auto; min-height: 90px; padding: 9px 11px; line-height: 1.5; }
.sa-app input:focus, .sa-app select:focus, .sa-app textarea:focus {
  outline: 2px solid rgba(47,90,67,0.25); outline-offset: -1px; border-color: var(--accent);
}
.sa-app input:not([type=checkbox]):not([type=radio]):disabled, .sa-app select:disabled {
  background: #f7f6f4; color: var(--ink-3); border-color: var(--line); cursor: not-allowed;
}
.sa-app select {
  appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' stroke='%238b8f96' stroke-width='1.5' fill='none' stroke-linecap='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 12px center; padding-right: 32px;
}
.sa-app .sa-row, .sa-app .sa-grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 0 14px; }
/* De tussenruimte tussen twee rijen zit in het raster (row-gap), niet als marge onder elke cel.
   Met een celmarge draagt het raster die 14px ook onder zijn láátste rij, en dan is de afstand tot
   de streep boven de knop 40px in een blok dat op velden eindigt en 26px in een blok dat op een
   opmerking eindigt. De 18px tussen twee rijen blijft: 14 uit het raster en 4 uit zijn marge. */
/* De velden van een rij staan met hun ónderkant op één lijn, niet met hun bovenkant. Een label dat
   over twee regels loopt — "Aantal genodigden voor de schieting (jezelf uitgezonderd)" naast een
   smalle kolom — zou zijn invoervak anders een regel lager duwen dan dat ernaast. */
.sa-app .sa-fgrid { display: grid; grid-template-columns: repeat(12, 1fr); gap: 14px; margin-bottom: 18px; align-items: end; }
/* Een rij waarin de cellen niet even hoog zijn, lijnt op haar bovenkant uit: de labels staan dan
   naast elkaar in plaats van de onderranden van ongelijke vakken. */
.sa-app .sa-fgrid-top { align-items: start; }
.sa-app .sa-fcell { grid-column: span var(--span, 4); }
.sa-app .sa-fcheck { justify-content: flex-end; padding-bottom: 9px; }
/* Twee vinkjes die een blok afsluiten, samen en tegen de rechterkant. Buiten het raster:
   in het raster braken ze de rij waarop ze stonden in tweeën. */
/* Twee velden onder elkaar in één kolom van het raster. Ze staan zo hoog als de tegel ernaast en
   horen bij elkaar; naast elkaar aten ze twee kolommen op zonder dat te verdienen. */
.sa-app .sa-fstack { gap: 14px; }
/* Dezelfde 2px tussen een label en zijn veld als overal: deze stapel droeg er nog 5, van voor het
   bestuur die afstand liet inkrimpen. */
.sa-app .sa-fstack > div { display: flex; flex-direction: column; gap: 2px; }

/* De popup achter "Wachtwoord vergeten?". Een <dialog>, dus het openen, Escape en de
   focusval zijn de browser zijn werk; hier staat alleen hoe hij eruitziet. */
.sa-app .sa-dialog {
  width: min(420px, calc(100vw - 32px)); padding: 26px;
  /* position: fixed en niet relative. De browser geeft een dialoogvenster van zichzelf
     position: absolute met inset: 0 en margin: auto, en dan wordt het gecentreerd in de
     BLADZIJDE en niet in het venster — op een gescrolde bladzijde staat het dus boven of onder
     het beeld. Hier stond relative, wat het nog erger maakt: dan valt het terug op zijn plaats in
     de tekst. Met fixed klopt het centreren op elke scrollhoogte, en het blijft een houvast voor
     de sluitkruisjes die er absolute in staan.
     Een lijst met elf plaatshouders is langer dan een laag venster, vandaar de max-height: zonder
     die loopt ze eronderuit en is de sluitknop niet te bereiken. */
  position: fixed; inset: 0; margin: auto;
  max-height: calc(100vh - 48px); overflow-y: auto;
  background: var(--surface); color: var(--ink);
  border: 1px solid var(--line); border-radius: 8px;
  box-shadow: 0 18px 44px rgba(22,24,27,0.16);
}
.sa-app .sa-dialog::backdrop { background: rgba(22,24,27,0.32); }
.sa-app .sa-dialog h2 { margin: 0 0 8px; font-size: 17px; font-weight: 600; }
.sa-app .sa-dialog p { margin: 0 0 14px; font-size: 13px; }
.sa-app .sa-dialog label { display: block; font-size: 12px; color: var(--ink-2); margin-bottom: 5px; }
.sa-app .sa-dialog .sa-btn { width: 100%; height: 40px; margin-top: 20px; }
.sa-app .sa-dialog-close-form { position: absolute; top: 8px; right: 10px; margin: 0; }
.sa-app .sa-dialog-close {
  background: none; border: 0; padding: 4px 6px; line-height: 1;
  font-size: 22px; color: var(--ink-3); cursor: pointer;
}
.sa-app .sa-dialog-close:hover { color: var(--ink); }

/* ---- De kalender achter een datumveld ------------------------------------
   Wat een datumveld van zichzelf opentrekt, is de kalender van de browser: Engelse dagletters,
   een blauw dat nergens anders in deze app staat, en op elke machine iets anders. Die is hier
   vervangen door een eigen (server/views/datumkalender.js), zoals het vinkvakje dat van het
   besturingssysteem verving. Het icoon van de browser gaat daarbij weg — maar alleen binnen
   .sa-datumveld, en die schil bestaat alleen wanneer het script gedraaid heeft: zonder script
   staat het veld er weer bij zoals de browser het tekent, met zijn eigen kalender. */
.sa-app .sa-datumveld { position: relative; display: block; }
.sa-app .sa-datumveld input::-webkit-calendar-picker-indicator { display: none; }
.sa-app .sa-datumveld input { padding-right: 38px; }
.sa-app .sa-datumknop {
  position: absolute; top: 1px; right: 1px; width: 34px; height: 34px;
  display: flex; align-items: center; justify-content: center;
  background: none; border: 0; border-radius: 0 7px 7px 0;
  color: var(--ink-3); cursor: pointer;
}
.sa-app .sa-datumknop:hover { color: var(--ink); background: var(--hover); }
.sa-app .sa-kal {
  position: absolute; z-index: 40; top: calc(100% + 6px); left: 0;
  width: 284px; padding: 12px;
  background: var(--surface); border: 1px solid var(--line); border-radius: 8px;
  box-shadow: 0 10px 28px rgba(22,24,27,0.14);
}
/* Naar boven wanneer ze er onder niet uit kan. */
.sa-app .sa-kal.boven { top: auto; bottom: calc(100% + 6px); }
.sa-app .sa-kal-kop { display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px; }
/* Maand en jaar zijn keuzelijsten, maar ze horen als het opschrift van de kaart te lezen: geen
   rand, geen vulling, alleen het pijltje dat de app overal onder een keuzelijst zet. Zonder die
   twee is een geboortedatum onbereikbaar — van vandaag naar december 1962 zijn 767 kliks op het
   maandpijltje. */
.sa-app .sa-kal-maand { display: flex; align-items: center; gap: 2px; font-size: 13.5px; font-weight: 600; }
.sa-app .sa-kal-kies {
  width: auto; height: 28px; border: 0; background-color: transparent;
  font-size: 13.5px; font-weight: 600; color: var(--ink);
  padding: 0 17px 0 4px; background-position: right 4px center; border-radius: 6px;
}
.sa-app .sa-kal-kies:hover { background-color: var(--hover); }
.sa-app .sa-kal-pijl {
  width: 28px; height: 28px; display: flex; align-items: center; justify-content: center;
  background: none; border: 0; border-radius: 6px; color: var(--ink-3); cursor: pointer;
}
.sa-app .sa-kal-pijl:hover { background: var(--hover); color: var(--ink); }
/* Een vinger lucht tussen de vakjes: zonder die tussenruimte raakt het groen van de gekozen dag
   zijn buren, en dan leest een rij als een balk in plaats van als zeven dagen. De koprij draagt
   dezelfde tussenruimte, anders staan MA..ZO niet meer boven hun eigen kolom. */
.sa-app .sa-kal-dagen, .sa-app .sa-kal-raster {
  display: grid; grid-template-columns: repeat(7, 1fr); gap: 3px;
}
.sa-app .sa-kal-dagen span {
  text-align: center; font-size: 10.5px; font-weight: 600; letter-spacing: 0.4px;
  text-transform: uppercase; color: var(--ink-3); padding-bottom: 4px;
}
.sa-app .sa-kal-dag {
  height: 30px; display: flex; align-items: center; justify-content: center;
  background: none; border: 0; border-radius: 6px;
  font-size: 13px; color: var(--ink); cursor: pointer; font-variant-numeric: tabular-nums;
}
.sa-app .sa-kal-dag:hover { background: var(--hover); }
.sa-app .sa-kal-dag.buiten { color: var(--ink-3); opacity: 0.55; }
.sa-app .sa-kal-dag[disabled] { color: var(--ink-3); opacity: 0.35; cursor: default; background: none; }
/* Vandaag draagt een rand, de gekozen dag het accent — twee verschillende dingen, dus twee
   verschillende tekens. */
.sa-app .sa-kal-dag.nu { box-shadow: inset 0 0 0 1px var(--line); }
.sa-app .sa-kal-dag.on { background: var(--accent); color: #fff; font-weight: 600; box-shadow: none; }
/* Het uur, voor het ene veld dat er een draagt: de datum van een activiteit. Twee keuzelijsten en
   geen twee kolommen om door te rollen — een uur is een keuze uit vierentwintig, geen lijst om in
   te zoeken. */
.sa-app .sa-kal-tijd {
  display: flex; align-items: center; gap: 6px;
  margin-top: 8px; padding-top: 8px; border-top: 1px solid var(--line-soft);
}
/* Het woord staat bij zijn vakjes en niet tegen de overkant van de kaart: "Uur" links en de twee
   lijsten rechts liet er honderd pixels niets tussen, en dan hoort het ene niet meer bij het
   andere. */
.sa-app .sa-kal-tijd span { font-size: 12.5px; color: var(--ink-2); }
/* Zolang het uur niet gezet is, draagt de rij de okerkleur van een opmerking. Dat is nodig omdat
   een dagklik op een leeg veld er 00:00 in schrijft: dat is een volledige waarde, dus de required
   van de browser houdt ze niet meer tegen, en een activiteit op middernacht is altijd een
   vergissing. */
.sa-app .sa-kal-tijd.te-zetten span { color: var(--note); font-weight: 600; }
.sa-app .sa-kal-tijd.te-zetten select { border-color: var(--note); }
.sa-app .sa-kal-tijd em { font-style: normal; color: var(--ink-3); }
.sa-app .sa-kal-tijd select {
  /* De app tekent haar eigen pijltje in de achtergrond van een keuzelijst, op 12px van rechts met
     32px padding ernaast. Hier stond alleen de padding uit, en dan valt dat pijltje over het
     cijfer. Allebei de maten horen dus mee te krimpen. */
  width: auto; height: 30px; padding: 0 22px 0 9px; font-size: 13px;
  background-position: right 7px center;
  font-variant-numeric: tabular-nums;
}
.sa-app .sa-kal-voet {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  margin-top: 8px; padding-top: 8px;
  border-top: 1px solid var(--line-soft);
}
.sa-app .sa-kal-voet > span { display: flex; gap: 10px; }
.sa-app .sa-kal-klaar { color: var(--accent-ink); font-weight: 600; }
.sa-app .sa-kal-link {
  background: none; border: 0; padding: 2px 4px; border-radius: 6px;
  font-size: 12.5px; color: var(--ink-2); cursor: pointer;
}
.sa-app .sa-kal-link:hover { background: var(--hover); color: var(--ink); }

/* De regel onder de aanmeldkaart: "Wachtwoord vergeten?", "Terug naar aanmelden". */
/* De opmerking onder het wachtwoordveld op het aanmeldscherm: wat er in dat veld hoort zolang
   een lid nog nooit een eigen wachtwoord koos. Ze draagt de gewone mark van een opmerking in een
   formulier, en staat dichter bij het veld erboven dan bij de knop eronder — ze hoort bij het
   veld. Links uitgelijnd, want het is een zin en geen etiket. */
/* Een blok waar een link rechtstreeks naartoe springt, stopt niet onder de bovenbalk. Die balk is
   sticky en 57px hoog (56 plus haar lijn), dus zonder deze marge schuift de browser het blok tot
   tegen de bovenkant van het venster en valt zijn eigen titel eronder weg — wie de rappelmail
   volgde, landde op een rood kader zonder te zien waar hij was. Het bestuur wees erop (oktober
   2026). 80px laat 23px lucht tussen de balk en de kaart.

   Het geldt voor het jachtverlofblok, het enige blok in deze app waar van buitenaf naartoe
   gelinkt wordt (#jachtverlof, vanuit de rappelmail en vanaf de tegel op de startbladzijde). */
.sa-app .sa-permit { scroll-margin-top: 80px; }

/* Een voorbije activiteit staat grijs in Activiteiten beheren, zoals een voorbije rij op de
   Kalender. Twee dingen die het anders doet dan daar, en allebei met reden:

   De **knoppen blijven op volle sterkte**. Op de Kalender dooft de hele rij, maar hier staan er
   vier op elke regel waarvan er één wist — een knop die half vervaagd is, is nog altijd een knop
   die ingedrukt kan worden, en dan is de vervaging alleen maar moeilijker lezen zonder iets tegen
   te houden. Wat dooft is wat zegt wélke avond het is: de foto, de naam, de plaats, de datum, het
   uur en het label.

   En **onder de muis komt ze terug**, zoals elke beheerlijst hier oplicht: wie ergens op gaat
   klikken, leest eerst. */
.sa-app tr.sa-rij-voorbij .sa-cell-name,
.sa-app tr.sa-rij-voorbij .sa-when-cell,
.sa-app tr.sa-rij-voorbij .sa-badge { opacity: 0.5; transition: opacity .15s ease; }
.sa-app tr.sa-rij-voorbij img.sa-event-thumb,
.sa-app tr.sa-rij-voorbij .sa-event-thumb img { filter: grayscale(1); transition: filter .15s ease; }
.sa-app tr.sa-rij-voorbij:hover .sa-cell-name,
.sa-app tr.sa-rij-voorbij:hover .sa-when-cell,
.sa-app tr.sa-rij-voorbij:hover .sa-badge { opacity: 1; }
.sa-app tr.sa-rij-voorbij:hover img.sa-event-thumb,
.sa-app tr.sa-rij-voorbij:hover .sa-event-thumb img { filter: none; }

/* Een regel op de fiche die zegt dat er iets mis is met dít lid — vandaag: het kan niet
   aanmelden. Rood en halfvet zoals elke andere melding van die aard in de app, klein, en pal onder
   de waarde die de oorzaak is. Geen driehoek: dat is de vorm van een waarschuwing in een
   formulier, en dit hangt aan één veld. */
.sa-app .sa-waarde-let-op {
  margin: 6px 0 0; color: var(--danger); font-weight: 600; font-size: 12.5px; line-height: 17px;
}

.sa-app .sa-gate-note { margin: 6px 0 0; text-align: left; }
.sa-app .sa-gate-aside { margin: 16px 0 0; text-align: center; font-size: 13px; }
.sa-app .sa-gate-aside a { color: var(--ink-2); text-decoration: none; border-bottom: 1px solid var(--line); }
.sa-app .sa-gate-aside a:hover { color: var(--accent-ink); border-bottom-color: var(--accent); }
.sa-app .sa-check { display: inline-flex; align-items: center; gap: 8px; font-size: 13px; }
/* Elk blok van een formulier is zijn eigen kaart — Persoonsgegevens, Adresgegevens,
   Facturatiegegevens, Lidmaatschap, Jachtverlof. Ze stonden onder elkaar in één kaart, met een
   haarlijn ertussen; drie titels en twee strepen in één vlak lezen als één lang blok waar het er
   drie zijn. Losse kaarten zeggen dat met hun rand, en dan is de streep er een te veel.

   De onderrand is 16 en de bovenrand 20: het laatste raster in een blok draagt zelf 4px onder
   zich (zoals elke rasterrij), en samen is dat weer 20.

   De <legend> zweeft, want een legend ligt van zichzelf óp de rand van de fieldset en zou er een
   gat in knippen zodra die rand er is. Met een breedte van 100% gedraagt hij zich als een gewone
   regel; het raster eronder is een grid en dus een eigen blokcontext, die naast een zwevend
   element van volle breedte niet past en er netjes onder komt. */
.sa-app .sa-form .sa-fset {
  background: var(--surface); border: 1px solid var(--line); border-radius: 8px;
  margin: 0 0 18px; padding: 20px 20px 16px;
}
/* En wat onder de titel staat, moet er ook echt onder staan: een zwevend element van volle
   breedte laat naast zich geen ruimte over, maar een raster is een eigen blokcontext en gaat
   ernáást staan in wat er over is — nul breedte, dus vier velden op een speld. clear zet ze
   eronder. Zonder dit liep de opmerking bovendien dwars door haar eigen titel. */
.sa-app .sa-form .sa-fset > legend { float: left; width: 100%; }
.sa-app .sa-form .sa-fset > legend ~ * { clear: both; }
/* Een kaart in een kaart is een vlak om een vlak. Waar de blokken hun eigen rand dragen, laat het
   paneel of de kaart eromheen die van zichzelf vallen — dezelfde regel als bij de albums en de
   archiefmappen. */
.sa-app .sa-card:has(> .sa-form > .sa-fset),
.sa-app .sa-panel:has(> .sa-form > .sa-fset) {
  background: none; border: 0; padding: 0;
}
.sa-app .sa-fset { border: 0; margin: 0 0 22px; padding: 0; }
.sa-app .sa-fset > legend {
  /* Vet, niet halfvet: nu elk blok zijn eigen kaart is, opent deze titel een vlak in plaats van
     een stuk van een lijst, en dan mag hij zwaarder staan dan een veldlabel. */
  font-family: inherit; font-size: 11px; font-weight: 700; letter-spacing: 0.8px;
  /* De kop van een blok draagt --ink-2, niet --ink-3: op 11px in kapitalen was het lichtste grijs
     te weinig om een blok te openen. Hoofdletters, spatiëring en gewicht houden hem een titel en
     geen label, ook nu hij dezelfde kleur heeft als een veldlabel. */
  text-transform: uppercase; color: var(--ink-2); padding: 0; margin-bottom: 10px;
}
/* De haarlijn tussen twee blokken is weg: elk blok draagt nu zijn eigen rand, en twee randen met
   ruimte ertussen zeggen hetzelfde als een streep. */
.sa-app .sa-form-foot {
  display: flex; justify-content: flex-end; align-items: center; gap: 10px; flex-wrap: wrap;
  /* Dezelfde 22px onder de streep als een blok eronder heeft. */
  margin-top: 6px; padding-top: 21px; border-top: 1px solid var(--line);
}
/* Staat het formulier in losse kaarten, dan hoort de knop eronder en niet achter een streep: de
   rand van de laatste kaart heeft de scheiding al gemaakt. De 18px komt uit de marge van die
   kaart. */
.sa-app .sa-form:has(.sa-fset) .sa-form-foot {
  border-top: 0; margin-top: 0; padding-top: 0;
}
.sa-app .sa-form-foot .sa-btn-left { margin-right: auto; }
/* Wat naar elders leidt staat links, wat deze kaart bewaart rechts. Als groep en niet per knop:
   een auto-marge op de eerste knop duwt alleen die naar links en laat de tweede rechts staan. */
.sa-app .sa-form-foot .sa-foot-links { display: flex; gap: 10px; flex-wrap: wrap; margin-right: auto; }
/* What the app says back after a save, and what it says when it refuses. Both carry a mark on
   the first line, the way every remark in a form does — a bare sentence in a coloured box has to
   be read before it is understood, a mark says which of the two it is before that. The left
   padding is the box's own 13px plus room for the icon; the indent keeps a second line under the
   first rather than under the mark. A background image, because the views print a bare <div>. */
.sa-app .sa-success, .sa-app .sa-error {
  border-radius: var(--radius); padding: 10px 13px 10px 36px; font-size: 13px; margin-bottom: 16px;
  border: 1px solid; background-repeat: no-repeat; background-position: 13px 11px;
}
.sa-app .sa-success {
  background-color: var(--accent-soft); border-color: #cfe0d6; color: var(--accent-ink);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='15' height='15' viewBox='0 0 24 24' fill='none' stroke='%2321432f' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3Cpath d='M8 12.2l2.7 2.7L16 9.5'/%3E%3C/svg%3E");
}
.sa-app .sa-error {
  background-color: var(--danger-soft); border-color: #e8c4bf; color: var(--danger);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='15' height='15' viewBox='0 0 24 24' fill='none' stroke='%23a32b1c' stroke-width='1.8' stroke-linecap='round'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3Cpath d='M12 7.5v5.5'/%3E%3Cpath d='M12 16.4v.1'/%3E%3C/svg%3E");
}

/* ---- Tables -------------------------------------------------------------- */
.sa-app table, .sa-app .sa-wix-table { width: 100%; border-collapse: collapse; font-size: 14px; }
.sa-app .sa-wix-table th, .sa-app thead th {
  text-align: left; padding: 10px 16px; background: none;
  font-family: inherit; font-size: 11px; font-weight: 600; letter-spacing: 0.6px; text-transform: uppercase;
  color: var(--ink-3); border-bottom: 1px solid var(--line); white-space: nowrap;
}
.sa-app .sa-wix-table td, .sa-app tbody td {
  padding: 11px 16px; border-bottom: 1px solid var(--line-soft); vertical-align: middle;
}
.sa-app tbody tr:last-child td { border-bottom: 0; }
/* Geen oplichtende regel onder de muis in het ledengedeelte: op vraag van het bestuur. Ze was
   bedoeld om het oog in een lange lijst de regel te laten volgen, maar op een lijst waar een regel
   iets ís — een inschrijving, een deelnemer — leest ze als een keuze, alsof die regel aanstaat
   terwijl er alleen een muis overheen staat. De regel hieronder zet ze uit in plaats van ze weg te
   laten: de stylesheet van de publieke site draagt er een van zichzelf
   (.sa-wix-table tbody tr:hover td), en die blijft daar staan. */
.sa-app tbody tr:hover td { background: transparent; }
/* In het beheer wél, op vraag van het bestuur (september 2026). Daar is elke regel een weg naar
   een bewerkscherm, en dan wijst de oplichting aan wat je aanklikt in plaats van te suggereren dat
   er iets aanstaat. Dat draait de eerdere keuze terug, maar alleen voor de beheerlijsten: de
   Ledenlijst die een lid ziet, en de deelnemerslijst bij een activiteit, blijven vlak. */
.sa-app.sa-body-admin tbody tr:hover td { background: var(--hover); }
/* Behalve op de twee bladen die formulieren zijn. Een regel vol invoervakken is geen link, en
   dertig regels die onder de muis grijs worden terwijl je van vak naar vak gaat, is rumoer. */
.sa-app.sa-body-admin .sa-scoreblad tbody tr:hover td,
.sa-app.sa-body-admin .sa-inschrijfblad tbody tr:hover td { background: transparent; }
.sa-app .sa-wix-table th a { color: inherit; text-decoration: none; display: inline-flex; align-items: center; gap: 4px; }
.sa-app .sa-sort-arrow { font-size: 9px; color: #c9c7c2; }
.sa-app .sa-name { font-weight: 500; color: var(--ink); white-space: nowrap; }
.sa-app .sa-name-sub { font-size: 12.5px; color: var(--ink-3); }
.sa-app .sa-cell-name { min-width: 230px; }
/* Het e-mailadres staat er voluit. Het publieke stylesheet klemt deze cel op 220px en kapt de
   rest af met een beletselteken — het langste adres van de club is 35 tekens en haalde dat net
   niet. Achter de login is de inhoudskolom 1180px breed en staan er maar vier kolommen, dus die
   klem kostte alleen leesbaarheid. Het bestuur wees erop (oktober 2026).
   nowrap blijft: een adres over twee regels maakt de rij hoger dan de rest. */
.sa-app .sa-cell-mail { max-width: none; }

/* De kolommen van de Ledenlijst staan vast, en dat moest wel: een tabel meet haar kolommen aan de
   rijen die erin staan, dus sprong de hele lijst van vorm zodra er op een tegel geklikt werd of er
   een letter in het zoekvak kwam. Bij alle 67 leden was Naam 221px breed, bij de negen van de Eed
   148 en bij het ene erelid 189 — telkens dezelfde tabel. Het bestuur wees erop (oktober 2026).

   In procenten en niet in pixels, zodat de verhouding op elke breedte klopt en de tabel blijft
   meekrimpen zoals ze deed. Wat elke kolom nodig heeft is nagemeten (de breedste inhoud plus de
   32px padding): 197 · 134 · 286 · 120 · 126 · 117, samen 980. De e-mail krijgt de ruimte die
   overblijft — het is de enige kolom met lange inhoud, en de andere vijf dragen een naam, een
   nummer of een label. */
.sa-app .sa-leden-tabel { table-layout: fixed; width: 100%; }
.sa-app .sa-leden-tabel th:nth-child(1) { width: 18.5%; }
.sa-app .sa-leden-tabel th:nth-child(2) { width: 12.5%; }
.sa-app .sa-leden-tabel th:nth-child(3) { width: 32%; }
.sa-app .sa-leden-tabel th:nth-child(4) { width: 12%; }
.sa-app .sa-leden-tabel th:nth-child(5) { width: 12.5%; }
.sa-app .sa-leden-tabel th:nth-child(6) { width: 12.5%; }
/* In een vaste kolom loopt tekst met nowrap gewoon door over de kolom ernaast; een adres dat niet
   meer past krijgt daarom een beletselteken. Dat gebeurt pas onder een venster van ongeveer
   1220px: het langste adres vraagt 286px en krijgt er 356 op een scherm van 1440. */
.sa-app .sa-leden-tabel td:nth-child(3) { overflow: hidden; text-overflow: ellipsis; }


.sa-app .sa-cell-doc .sa-name { white-space: normal; }
.sa-app .sa-when-cell { font-variant-numeric: tabular-nums; color: var(--ink-2); font-size: 13px; }

/* ---- Toolbar, search, filters -------------------------------------------- */
.sa-app .sa-toolbar { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; margin-bottom: 14px; }
.sa-app .sa-toolbar-count { font-family: inherit; font-size: 13px; font-weight: 500; color: var(--ink-2); }
.sa-app .sa-toolbar-add { margin-left: auto; }
.sa-app .sa-search { position: relative; flex: 0 0 300px; margin: 0; }
/* On the members' own list it stands alone above the table rather than inside a toolbar, so it
   needs its own room and a width that fits the placeholder. */
.sa-app form.sa-search { display: block; max-width: 420px; margin: 0 0 14px; }
/* The full :not() chain, because the generic rule for input carries five of them and sets the
   padding outright — a selector with only classes in front loses, and the placeholder then runs
   underneath the magnifier. This is the fourth time that chain has had to be repeated; anything
   that has to beat the generic input rule needs it. */
.sa-app .sa-search input:not([type=checkbox]):not([type=radio]):not([type=submit]):not([type=button]) {
  padding-left: 34px;
}
.sa-app .sa-search svg {
  position: absolute; left: 10px; top: 50%; transform: translateY(-50%);
  /* display:block, or the inline baseline leaves it sitting two pixels low. */
  display: block; width: 15px; height: 15px; stroke: var(--ink-3); fill: none;
}
/* The filters are a form of <select>s, not links. A select in here takes the width of what it
   holds — the global rule makes every field full width, which stacked them one per row. */
/* Het aantal boven de rij in plaats van ervoor: als kopje van de lijst die eronder komt. */
.sa-app .sa-list-count { font-size: 13px; font-weight: 500; color: var(--ink-2); margin: 0 0 10px; }
.sa-app .sa-filters { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 14px; }
/* Zoeken en filteren staan in dezelfde rij, dus dragen ze daar geen eigen ondermarge, en de
   keuzelijsten zijn even hoog als het zoekveld. */
/* De -4px bovenmarge komt uit de publieke opmaak, waar de filterrij tegen de rij erboven werd
   getrokken. In één rij is dat precies 4px scheefstand. */
.sa-app .sa-toolbar > .sa-search, .sa-app .sa-toolbar > .sa-filters { margin: 0; }
.sa-app .sa-toolbar > .sa-filters select { height: 36px; }
/* Het zoekveld is een inline-block op een basislijn, en die laat er 4px onder staan — genoeg om
   het formulier eromheen 40px hoog te maken naast keuzelijsten van 36. Als blok in een omhulsel
   van precies 36 staan de drie op dezelfde lijn. */
.sa-app .sa-toolbar > .sa-search, .sa-app .sa-toolbar > .sa-filters { height: 36px; }
.sa-app .sa-toolbar > .sa-search input { display: block; }
.sa-app .sa-filters-label { font-size: 12px; color: var(--ink-3); margin-right: 2px; }
.sa-app .sa-filters select {
  width: auto; min-width: 0; max-width: 260px; height: 32px;
  font-size: 12.5px; padding: 0 30px 0 11px; border-radius: 999px; color: var(--ink-2);
}
.sa-app .sa-filters select:hover { border-color: #d9d6d1; }
.sa-app .sa-filter-clear { font-size: 12.5px; color: var(--ink-3); text-decoration: none; margin-left: 2px; }
.sa-app .sa-filter-clear:hover { color: var(--ink); }
.sa-app .sa-filters a, .sa-app .sa-tabs a {
  display: inline-flex; align-items: center; gap: 6px; height: 30px; padding: 0 11px;
  border: 1px solid var(--line); border-radius: 999px; background: var(--surface);
  font-size: 12.5px; color: var(--ink-2); text-decoration: none;
}
.sa-app .sa-filters a.active, .sa-app .sa-tabs a.active { background: var(--ink); border-color: var(--ink); color: #fff; }
/* De rubriekkeuze boven een tekstpagina: losse knoppen, op de breedte van die pagina en met
   dezelfde afstand eronder als tussen twee kaarten. Ze zijn een dag lang één strook met tabbladen
   geweest; het bestuur wil ze los. */
.sa-app .sa-page-tabs { display: flex; flex-wrap: wrap; gap: 8px; max-width: 980px; margin-bottom: 18px; }
.sa-app .sa-page-tabs a { height: 34px; padding: 0 16px; }
.sa-app .sa-table-add { display: flex; justify-content: center; margin-top: 16px; }

/* ---- Chips and badges ---------------------------------------------------- */
.sa-app .sa-chip, .sa-app .sa-badge {
  display: inline-flex; align-items: center; justify-content: center; text-align: center;
  height: 21px; padding: 0 8px; margin: 1px 3px 1px 0;
  border: 0; border-radius: 4px; font-size: 11.5px; font-weight: 500; white-space: nowrap;
  background: #f2f1ee; color: var(--ink-2); letter-spacing: 0; text-transform: none;
}
/* De 3px rechts houdt twee labels uit elkaar; op het laatste label van een rij duwt hij alleen de
   hele rij van de rand af. Dat scheelde: op de startbladzijde eindigde het label van een schieting
   3px eerder dan dat van het jachtverlof ernaast, in kaarten die even breed zijn. */
.sa-app .sa-chip:last-child, .sa-app .sa-badge:last-child { margin-right: 0; }
.sa-app .sa-chip-ok, .sa-app .sa-badge-accent { background: var(--accent-soft); color: var(--accent-ink); }
.sa-app .sa-chip-off, .sa-app .sa-badge-closed { background: var(--danger-soft); color: var(--danger); }
.sa-app .sa-chip-serment, .sa-app .sa-badge-serment { background: var(--gold-soft); color: var(--gold); }
/* "+ Partner" draagt het zand van het bestuur, en niet langer de tint van de Serment-tegels: het
   zegt iets over de avond, niet over wie in de Eed zit. De tint is die van het bestuur, precies
   zoals gekozen: wit haalt erop 2.88:1, onder de 4.5 die 11.5px nodig heeft, en dat is hun
   afweging — donkere letters zouden er 6.3:1 halen. Op een voorbije avond gaat het label mee in
   het grijs, zoals elk ander. */
.sa-app .sa-chip-partner, .sa-app .sa-badge-partner { background: #ac974e; color: #fff; }
.sa-app .sa-evrow-past .sa-chip-partner, .sa-app .sa-panel-past .sa-chip-partner {
  background: #f2f1ee; color: var(--ink-2);
}
/* "Ingeschreven" is het enige label dat over het lid zelf gaat, en het is wat hij op de kalender
   zoekt: staat het er, dan hoeft hij niets meer te doen. Vol groen in plaats van de lichte tint die
   de andere labels dragen — die tint zegt "in orde", dit zegt "dit gaat over jou". Het eigen
   klassenaampje houdt "Geldig" bij het jachtverlof en "Actief" op de ledenlijst zoals ze waren;
   die delen sa-chip-ok.
   De letters staan er wit op. Op het #6bb27a dat het bestuur koos haalt wit 2.54:1, onder de 4.5
   die 11.5px nodig heeft, dus is het groen een stap donkerder: #4a8659 draagt wit op 4.51:1 en
   blijft hetzelfde groen. */
.sa-app .sa-badge-registered, .sa-app .sa-chip-registered { background: #4a8659; color: #fff; }
/* "Inschrijvingen afgesloten" draagt een vulling van zichzelf: het is de enige mededeling in de
   rij die een deur dicht doet, en stond in hetzelfde grijs als het koppental ernaast. Het rood
   van het bestuur, #d28f8f, is een stap donkerder gezet — wit haalt daarop 2.60:1, onder de 4.5
   die 11.5px nodig heeft, en op #b35c5c 4.56:1. Lichter dan het rood van een afgelaste avond
   (--danger), want afgesloten is geen afgelasting. */
.sa-app .sa-chip-closed { background: #b35c5c; color: #fff; }
.sa-app .sa-badge-countdown, .sa-app .sa-badge-muted { background: #f2f1ee; color: var(--ink-2); }
/* Een ontwerp is lichtblauw: het staat naast een gepubliceerde avond in het groen en een
   afgelaste in het rood, en grijs las als "geen uitspraak" waar het er wel een is — deze avond is
   nog niet gepubliceerd. De maten volgen de andere tinten: de tegel 1.14:1 op wit, de tekst
   7.6:1 op de tegel, tussen het groen (9.8) en het rood (6.3) in. */
.sa-app .sa-badge-draft { background: #eaf1f8; color: #1f4e79; }
.sa-app .sa-chip-quiet { background: none; color: var(--ink-3); padding-left: 0; }
/* De winnaars onder de titel van een schieting: elk op zijn eigen regel, met 4px ertussen en
   dezelfde afstand tot de tabel als de regel erboven. */
.sa-app .sa-winnaars { display: flex; flex-direction: column; gap: 4px; margin: -6px 0 12px; }

/* De telling onder de ledenlijst, die tijdens het typen meeloopt. */
.sa-app .sa-lijst-telling { margin-top: 12px; }

/* De naam van een winnaar op een rij die verder uit datum en methode bestaat: halfvet, want het
   is het enige op die regel wat over een mens gaat. */
.sa-app .sa-winnaar { font-weight: 700; color: var(--ink); }

/* De regel onder een paginatitel die zegt wat er op die bladzijde staat — de methode van een
   schieting, haar datum, haar stand. Ze stond 20px onder de titel en raakte de kaart eronder,
   zodat ze in die kaart leek te vallen. Nu staat ze er even ver van als van de titel: 12 en 12,
   dezelfde maat als een opmerking boven een tabel op Resultaten. De titel geeft de helft van zijn
   eigen ruimte af, want die marge valt niet samen met de onze. */
.sa-app .sa-page-head:has(+ .sa-subtitel) { margin-bottom: 12px; }
.sa-app .sa-subtitel { margin: 0 0 12px; }

/* Het podium. Vet en halfvet, niet gekleurd: het is een rangorde en geen uitspraak. De winnaar
   draagt het volle gewicht, de twee naast hem een graad minder — zo is het podium in één oogopslag
   te zien én is meteen duidelijk wie er bovenaan staat. */
.sa-app tr.sa-rij-winnaar td { font-weight: 700; color: var(--ink); }
.sa-app tr.sa-rij-podium td { font-weight: 600; color: var(--ink); }

/* Een scoreblad past op één scherm. Elke cel draagt een getal van twee cijfers met 16px vulling
   aan weerszijden — meer ruimte dan het getal zelf — en met vijftien kolommen kwam de tabel 44px
   te breed uit, zodat ze zijwaarts moest schuiven. Op 10px past ze, en een kolom van vijf tekens
   houdt nog genoeg lucht. De naam houdt zijn 16px links: die staat tegen de rand van de kaart. */
.sa-app .sa-tabel-cijfers th, .sa-app .sa-tabel-cijfers td { padding-left: 10px; padding-right: 10px; }
.sa-app .sa-tabel-cijfers th:first-child, .sa-app .sa-tabel-cijfers td:first-child { padding-left: 16px; }
.sa-app .sa-tabel-cijfers th:last-child, .sa-app .sa-tabel-cijfers td:last-child { padding-right: 16px; }

/* De ronden op een scoreblad. Een avond van negen ronden geeft vijftien kolommen, en dan kost de
   ruimte naast een getal van twee cijfers meer dan het getal zelf: 32px vulling om 34px kop. Deze
   kolommen krijgen er 8 in plaats van 16, en de kop laat zijn spatiëring vallen — die is er om een
   woord te openen, niet om "T1 (12)" te spreiden. */
/* De starthandicap achter de naam op een scoreblad. Lichter dan de naam: het is een gegeven over
   de schutter en niet zijn naam, en de haakjes zeggen dat al. */
.sa-app .sa-hcp { color: var(--ink-3); }
.sa-app .sa-kolom-ronde { padding-left: 8px; padding-right: 8px; }
.sa-app th.sa-kolom-ronde { letter-spacing: 0; }
/* Het maximum van een ronde staat als breuk achter haar nummer — T1/24 — lichter en een graad
   kleiner: het hoort bij de kop maar is niet de kop. Zo weegt het niet mee in de breedte van de
   kolom, en die breedte is wat een blad van negen ronden onleesbaar maakte.
   De twee helften staan schuin tegenover elkaar, zoals in een gezette breuk: de teller een paar
   tienden hoger, de noemer even laag. Met relatieve plaatsing en niet met vertical-align, want
   super en sub rekken de regelhoogte van de kop op. */
.sa-app .sa-kolom-nr { position: relative; top: -3px; }
.sa-app .sa-kolom-max {
  position: relative; top: 3px;
  margin-left: 0; font-size: 9.5px; font-weight: 400; color: var(--ink-3);
}

/* Een vak voor één score op het scoreblad. Een score is twee cijfers, hooguit drie; een vak van
   een kwart kolom belooft iets anders. Het staat op de as van zijn kolom, net als het cijfer dat
   er later in de leeslijst van gemaakt wordt. */
/* Geen op- en neerpijltjes op een getalveld, nergens. Ze worden hier nooit gebruikt — een score,
   een aantal ronden of een maximum wordt ingetypt — en ze kosten de halve breedte van een vak van
   58px. Het veld blijft een getalveld, dus een telefoon geeft nog altijd het cijferklavier en de
   browser blijft op min en max controleren. Het stond er alleen voor de scorevakken. */
.sa-app input[type="number"] { -moz-appearance: textfield; appearance: textfield; }
.sa-app input[type="number"]::-webkit-outer-spin-button,
.sa-app input[type="number"]::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }

.sa-app .sa-scoreblad td { padding-top: 4px; padding-bottom: 4px; }
.sa-app input.sa-score:not([type="checkbox"]):not([type="radio"]):not([type="file"]):not([type="submit"]):not([type="button"]) {
  width: 58px; text-align: center; padding-left: 6px; padding-right: 6px;
}
/* Het maximum van een ronde, in de kop van haar eigen kolom: hetzelfde vak als een score maar een
   maat kleiner en lichter, zodat de kop een kop blijft en geen regel van het blad wordt. */
/* Elke kop van een scoreblad staat bovenaan uitgelijnd, niet alleen die van een ronde. Een
   rondekop draagt twee regels — T1 met het maximum of het invulvak eronder — en de koppen ernaast
   gingen in het midden van die twee staan zweven. Bovenaan staan ze allemaal op dezelfde lijn. */
.sa-app .sa-tabel-cijfers th { vertical-align: top; }
.sa-app th.sa-kolom-ronde .sa-kolom-nr { display: block; top: 0; margin-bottom: 4px; }
.sa-app input.sa-max:not([type="checkbox"]):not([type="radio"]):not([type="file"]):not([type="submit"]):not([type="button"]) {
  width: 46px; height: 26px; font-size: 12px; font-weight: 400; color: var(--ink-2);
  padding-left: 4px; padding-right: 4px;
}

/* Een tabel die vrijwel alleen uit getallen bestaat, zet ze op hun as: de naam blijft links, de
   rest staat gecentreerd, kop en cijfer. De gedeelde tabelkopregel lijnt links uit, vandaar de
   koppen erbij. */
.sa-app .sa-tabel-cijfers th, .sa-app .sa-tabel-cijfers td { text-align: center; }
.sa-app .sa-tabel-cijfers th:nth-child(2), .sa-app .sa-tabel-cijfers td:nth-child(2) { text-align: left; }
/* Op het scoreblad staat de naam vooraan: daar is de eerste kolom de linkse, en de tweede een
   getal als elk ander. */
.sa-app .sa-tabel-naam-eerst th:first-child, .sa-app .sa-tabel-naam-eerst td:first-child { text-align: left; }
.sa-app .sa-tabel-naam-eerst th:nth-child(2), .sa-app .sa-tabel-naam-eerst td:nth-child(2) { text-align: center; }
/* En de naam breekt niet af. "Gaëtan Kervyn d'Oud Mooreghem" over drie regels maakt van één rij
   drie, en dan staan de cijfers ernaast niet meer op één lijn met die van de rij erboven. De
   tabel schuift liever zijwaarts in haar eigen kaart. */
.sa-app .sa-tabel-naam-eerst td:first-child { white-space: nowrap; }

/* De eigen regel in een klassement. Een lid loopt de eerste kolom af om zichzelf te zoeken; een
   lichte vulling scheelt hem dat. Het groen van het label ernaast, maar dan als tint: een hele
   regel in vol groen zou de tabel overnemen. */
.sa-app .sa-rij-eigen > td { background: #eef5f0; }
.sa-app .sa-chip-m-full { background: #eef1f4; color: #3c4a57; }
.sa-app .sa-chip-m-junior { background: #eaeff3; color: #35505f; }
.sa-app .sa-chip-m-affiliated { background: #f0f1f2; color: #4b5259; }
.sa-app .sa-chip-m-honorary { background: var(--gold-soft); color: var(--gold); }
.sa-app .sa-chip-m-past { background: #f4f3f1; color: #7c7f84; }

/* ---- Cards: events, media, tips ------------------------------------------ */
.sa-app .sa-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; }
.sa-app .sa-media-card {
  background: var(--surface); border: 1px solid var(--line); border-radius: 8px;
  overflow: hidden; color: inherit; text-decoration: none; display: block;
}
.sa-app .sa-media-card:hover { border-color: #d4d1cb; background: var(--hover); }
.sa-app .sa-media-card-thumb, .sa-app .sa-media-card-thumb-placeholder {
  width: 100%; aspect-ratio: 3 / 2; object-fit: cover; display: block;
  /* The old cards were dark, so an album with only the crest sat on near-black. Here the crest
     sits on the same paper as everything else. */
  background: var(--line-soft); border-bottom: 1px solid var(--line);
}
.sa-app .sa-media-card-thumb-placeholder {
  display: flex; align-items: center; justify-content: center;
}
.sa-app .sa-media-card-thumb-placeholder img { width: 46%; height: auto; opacity: 0.85; }
.sa-app .sa-media-card-title {
  font-size: 13.5px; font-weight: 500; padding: 11px 13px 2px; color: var(--ink);
  text-align: left; text-transform: none; letter-spacing: 0; font-family: inherit;
}
/* An album carries only its name under the picture — no date line — so that name is centred in
   the strip rather than sitting against the photograph with a two-pixel gap under it. A card
   that does have a date keeps the padding above, where the two lines set their own rhythm.
   The min-height keeps a row of cards level when one title runs to two lines. */
.sa-app .sa-media-card:not(:has(.sa-media-card-date)) .sa-media-card-title {
  display: flex; align-items: center; min-height: 52px; padding: 8px 13px;
}
.sa-app .sa-media-card-date { font-size: 12.5px; color: var(--ink-3); padding: 0 13px 12px; text-align: left; }
.sa-app .sa-media-card-badge { position: static; }
/* A panel that holds nothing but cards is a surface drawn around surfaces — a box in a box. It
   applies wherever the thing inside carries its own border: the album and document grids, the
   collapsible archive groups, and the registration list. */
.sa-app .sa-panel:has(> .sa-grid),
.sa-app .sa-panel:has(.sa-archive-group) {
  background: none; border: 0; padding: 0;
}
/* The list itself is a plain <ul>, so it needs the browser's own bullets and indent removed. */
.sa-app .sa-list { list-style: none; margin: 0; padding: 0; }
/* Eén lijn tussen twee rijen, niet twee: elke rij droeg er al een onder zich (zie .sa-evlist
   verderop), en deze regel legde er de bovenrand van de volgende bovenop. Twee haarlijnen met een
   witte streep ertussen — te zien op elke kalenderrij. */
.sa-app .sa-media-card-badge {
  background: var(--accent-soft); color: var(--accent-ink); border-radius: 4px;
  font-size: 11.5px; font-weight: 500; padding: 1px 7px;
}

.sa-app .sa-event-card {
  display: flex; gap: 16px; align-items: flex-start;
  background: var(--surface); border: 1px solid var(--line); border-radius: 8px;
  padding: 14px 16px; margin-bottom: 12px; box-shadow: none;
}
.sa-app .sa-event-card:hover { border-color: #d4d1cb; }
.sa-app .sa-event-photo-wrap { flex: 0 0 150px; }
.sa-app .sa-event-photo, .sa-app .sa-event-photo-placeholder {
  width: 150px; height: 100px; object-fit: cover; border-radius: 6px; border: 1px solid var(--line);
  background: var(--line-soft); display: block;
}
/* The activity's own name, on its detail page. Heavier than a section heading: it is the
   subject of the page, and everything under it — date, venue, teaser — hangs off it. */
.sa-app .sa-event-title { font-size: 16px; font-weight: 700; margin: 0 0 4px; letter-spacing: -0.1px; }
/* "+ Partner" stond tegen de titel aan geplakt en hing er laag naast: een inline-flex staat op de
   basislijn van zijn eigen tekst, zodat de pil onder de titel uitzakt. De titel wordt dezelfde
   flexrij als een kalenderrij (.sa-evrow-t), waar het label al goed staat — één regel voor beide
   in plaats van een marge en een uitlijning die het benaderen. */
.sa-app .sa-event-title { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; }
.sa-app .sa-event-title .sa-chip { margin: 0; }
.sa-app .sa-event-meta-date, .sa-app .sa-event-meta-addr { font-size: 13px; color: var(--ink-2); }
.sa-app .sa-meta-label { color: var(--ink-3); }
/* De streep tussen de gegevens van de avond en haar tekst: meer lucht dan een regelafstand, en
   evenveel boven als onder. Ze stond op 9/13 — de alinea eronder draagt zelf nog 4px — en dan hangt
   de streep aan de tekst eronder in plaats van tussen de twee in te staan. */
.sa-app .sa-event-divider { border: 0; border-top: 1px solid var(--line-soft); margin: 16px 0; }
.sa-app .sa-event-divider + * > :first-child { margin-top: 0; }
.sa-app .sa-event-meta-info { font-size: 13px; color: var(--ink-2); }
.sa-app .sa-event-lead { font-weight: 500; }
/* The same teaser on an activity that has passed: still there to read, but not asking for
   attention the way the lead-in to an upcoming one does. */
.sa-app .sa-event-teaser-past { color: var(--ink-3); font-weight: 400; }
/* Title left, badges right, both on one line under the photograph. The badges keep to their own
   side when the title runs long, and drop under it only when there is no room left. */
/* The head count above the attendee list. One grey, whatever the state of the activity: the
   stylesheet the public site uses turns it near-white on a past event, which left the block
   invisible on exactly the pages where the list is longest. */
.sa-app .sa-attendee-summary,
.sa-app .sa-panel-past .sa-attendee-summary {
  background: #f2f1ee; border-radius: 6px; padding: 14px 16px; margin-bottom: 18px;
}

/* The photograph at the head of an activity. Its size and the space under it were an inline
   style, which no stylesheet rule can outweigh — so they live here now, where they can be
   adjusted. The gap under it is this margin plus the title row's own top margin. */
.sa-app .sa-event-hero {
  display: block; width: 100%; max-height: 320px; object-fit: cover;
  border-radius: 6px; margin-bottom: 11px;
}
/* De kop van een blok dat geen formulier is: dezelfde vorm als de <legend> van een formulierblok,
   zodat "Details" naast "Inschrijven" staat en niet als een ander soort titel leest. */
.sa-app .sa-blok-kop {
  font-family: inherit; font-size: 11px; font-weight: 700; letter-spacing: 0.8px;
  text-transform: uppercase; color: var(--ink-2); margin: 0 0 10px;
}
/* De foto over de volle breedte, boven de twee kolommen: ze hoort bij de avond en niet bij de ene
   helft ervan. In haar eigen kaart draagt ze geen ruimte onder zich — de kaart doet dat al. */
.sa-app .sa-ev-beeld .sa-event-hero { margin-bottom: 0; max-height: 280px; }
.sa-app .sa-event-status-row { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin: 0; }
.sa-app .sa-event-actions { margin-top: 12px; display: flex; gap: 8px; flex-wrap: wrap; }
.sa-app .sa-event-about { font-size: 13.5px; color: var(--ink-2); }


/* ---- Permit -------------------------------------------------------------- */

/* ---- Archive groups ------------------------------------------------------ */
.sa-app .sa-archive-group { border: 1px solid var(--line); border-radius: 8px; background: var(--surface); margin-bottom: 10px; }
.sa-app .sa-archive-heading {
  padding: 12px 16px; font-size: 13.5px; font-weight: 500; cursor: pointer; list-style: none;
  /* Op het midden in plaats van op de basislijn: het driehoekje hieronder is een getekende vorm
     zonder tekst, en die heeft geen basislijn om op te staan. */
  align-items: center;
}
.sa-app .sa-archive-heading::-webkit-details-marker { display: none; }
/* De documenten binnen een map lijnen uit met haar titel in plaats van tegen haar rand te staan.
   Er stond 16px lucht boven en 24 onder, maar links en rechts niets, zodat de rand van een kaart
   op 1px van de rand van de map viel: twee lijnen naast elkaar, een dubbel kader. */
.sa-app .sa-archive-group > .sa-grid { margin: 16px; }
.sa-app .sa-archive-group > .sa-table-card { margin: 12px 16px 16px; }
/* De koppen van de tarieventabel staan boven hun kolom, zoals de cellen eronder. De gedeelde regel
   voor een tabelkop in het ledengedeelte lijnt links uit, en die staat ná de opmaak van deze tabel,
   dus ze moet hier terug op het midden. De kapitalen van diezelfde regel blijven staan: het
   bestuur heeft ze op alle tabellen van het ledengedeelte gelijk gehouden, ook op deze. */
.sa-app .sa-fees th { text-align: center; }
/* En de streep onder de tabel in dezelfde kleur als de streep erboven, die van de kop
   "Lidmaatschap" komt: binnen het ledengedeelte is dat --line en niet de --border van de
   publieke opmaak. */
.sa-app .sa-fees table { border-bottom-color: var(--line); }

/* Het teken ▸ werd op 12px maar een paar pixels inkt. Hetzelfde getekende driehoekje als op het
   blok dat opengaat, maar een maat groter: 6 breed en 10 hoog naast een regel van 13.5. Een vorm
   met randen is op elke pixel dezelfde grootte, waar een letterteken van het lettertype afhangt. */
.sa-app .sa-archive-heading::before {
  content: ""; width: 0; height: 0; color: var(--ink-3);
  border-left: 6px solid currentColor;
  border-top: 5px solid transparent; border-bottom: 5px solid transparent;
}

/* ---- Home -------------------------------------------------------------- */
.sa-stats { display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px; margin-bottom: 18px; }
.sa-stats-5 { grid-template-columns: repeat(5, 1fr); }
.sa-app .sa-entry {
  display: flex; align-items: center; gap: 12px; padding: 15px 16px;
  background: var(--surface); border: 1px solid var(--line); border-radius: 8px;
  text-decoration: none; color: inherit;
}
.sa-app .sa-entry:hover { border-color: #d4d1cb; background: var(--hover); }
/* Een ingang die er drie achter zich heeft. Het vak zelf draagt de rand en de hoek; de regel
   erbovenaan ziet eruit als elke andere ingang, en de drie eronder verschijnen pas als er op
   geklikt wordt. Het vak groeit dan mee in zijn rij van het raster. */
/* Een blok dat een lid kan dichtklappen: de deelnemers en het scoreblad onder een activiteit. Het
   blok ís de kaart — de kop is haar bovenrand en niet een grijs vak binnen een kaart, want dat
   liet dichtgeklapt een strook wit onder zich staan. Open komt er een haarlijn onder de kop, zoals
   tussen twee delen van een kaart.
   Dichtgeklapt bij het laden: een lid opent wat hij zoeken wil. */
.sa-app .sa-vouwblok {
  background: var(--surface); border: 1px solid var(--line); border-radius: 8px;
  margin-bottom: 18px; overflow: hidden;
}
.sa-app .sa-vouwblok > summary {
  display: flex; align-items: baseline; gap: 8px; padding: 14px 16px;
  cursor: pointer; list-style: none;
}
.sa-app .sa-vouwblok > summary::-webkit-details-marker { display: none; }
.sa-app .sa-vouwblok[open] > summary { border-bottom: 1px solid var(--line); }
.sa-app .sa-vouwblok:hover > summary { background: var(--hover); }
.sa-app .sa-vouwblok-t { font-size: 15px; font-weight: 600; flex: 0 0 auto; }
/* Wat er in het blok staat, op één regel achter de titel: het aantal deelnemers, of waarop er
   geschoten werd. Loopt het niet, dan breekt het af in plaats van de titel weg te duwen. */
.sa-app .sa-vouwblok-s { flex: 1 1 auto; min-width: 0; font-size: 13px; color: var(--ink-3); }
/* Een em-streep tussen de titel en wat erin staat — twee feiten van verschillende aard op één
   regel, de regel die dit ledengedeelte daarvoor aanhoudt. Een ruimte alleen liet ze lezen als
   twee dingen die toevallig naast elkaar stonden. Het teken staat hier en niet in de vertaling:
   het is opmaak, en geen woord dat het bestuur schreef. */
.sa-app .sa-vouwblok-s::before { content: '— '; }
.sa-app .sa-vouwblok-s .sa-meta-label { color: var(--ink-3); }
.sa-app .sa-vouwblok > summary::after {
  content: ''; width: 0; height: 0; margin-left: auto; flex: 0 0 auto; align-self: center;
  border-left: 6px solid var(--ink-3); border-top: 5px solid transparent; border-bottom: 5px solid transparent;
  transition: transform 0.12s ease;
}
.sa-app .sa-vouwblok[open] > summary::after { transform: rotate(90deg); }
/* De inhoud draagt de ruimte, niet de kaart: dichtgeklapt is er dan niets om ruimte aan te geven.
   De tabel erin heeft haar eigen rand al, dus die valt weg tegen de kaart eromheen. */
.sa-app .sa-vouwblok-body { padding: 16px; }
.sa-app .sa-vouwblok-body > .sa-table-card { border: 0; border-radius: 0; margin: 0; }
/* Dezelfde regel voor een tabel in een tegel op de startbladzijde: een kaart in een kaart is een
   vlak om een vlak, en dat las als een dubbel kader. De tegel draagt de rand, de tabel niet. */
.sa-app .sa-tile > .sa-table-card { border: 0; border-radius: 0; margin: 0; }
.sa-app .sa-vouwblok-body > .sa-list { margin: 0; }
/* De titel van één scoreblad wanneer er op één avond meer dan één geschoten is. */
.sa-app .sa-vouwblok-sub { font-size: 13px; font-weight: 600; color: var(--ink-2); margin: 0 0 8px; }

/* Elke ingang houdt haar eigen hoogte: in een raster rekt een vak zich anders uit tot de hoogste
   van zijn rij, en dan worden de twee buren van een opengeklapte ingang even hoog als zij. */
.sa-app .sa-grid > * { align-self: start; }
.sa-app .sa-entry-fold { display: block; padding: 0; }
.sa-app .sa-entry-fold > summary {
  display: flex; align-items: center; gap: 12px; padding: 15px 16px;
  cursor: pointer; list-style: none;
}
.sa-app .sa-entry-fold > summary::-webkit-details-marker { display: none; }
.sa-app .sa-entry-fold > summary::after {
  content: ''; width: 0; height: 0; margin-left: auto;
  border-left: 5px solid var(--ink-3); border-top: 4px solid transparent; border-bottom: 4px solid transparent;
  transition: transform 0.12s ease;
}
.sa-app .sa-entry-fold[open] > summary::after { transform: rotate(90deg); }
.sa-app .sa-entry-fold > nav { display: flex; flex-direction: column; }
.sa-app .sa-entry-fold > nav a {
  padding: 11px 16px 11px 50px; border-top: 1px solid var(--line-soft);
  font-size: 13px; color: var(--ink-2); text-decoration: none;
}
/* Een gewone ingang licht helemaal op onder de muis, maar een opengeklapte is een lijst: dan hoort
   de regel op te lichten waar de muis op staat, en niet de hele kaart. Dat deed ze wel, in
   dezelfde kleur als de regel zelf, en dan zie je niets bewegen — je ziet alleen een vak dat grijs
   wordt. Opengeklapt houdt de kaart dus haar eigen wit, en lichten de kop en de vier regels elk
   apart op. */
.sa-app .sa-entry-fold[open]:hover { background: var(--surface); border-color: var(--line); }
.sa-app .sa-entry-fold > summary:hover { background: var(--hover); }
.sa-app .sa-entry-fold[open] > summary:hover { border-radius: 7px 7px 0 0; }
.sa-app .sa-entry-fold > nav a:hover { background: var(--hover); color: var(--ink); }

/* 22px: het icoon stond op 18 naast een regel van 21, en oogde daardoor te klein. */
.sa-app .sa-entry svg { width: 22px; height: 22px; flex: 0 0 22px; stroke: var(--accent); fill: none; stroke-width: 1.4; }
.sa-entry-t { display: block; font-weight: 500; }
.sa-entry-s { color: var(--ink-3); font-weight: 400; font-variant-numeric: tabular-nums; }
.sa-stat {
  background: var(--surface); border: 1px solid var(--line); border-radius: 8px; padding: 16px 18px;
  display: flex; flex-direction: column; align-items: center; text-align: center;
}
/* Een vaste regelhoogte, zodat het onderschrift van elke tegel op dezelfde hoogte staat — ook
   naast de tegel die een datum draagt in plaats van een getal en dus een kleinere graad heeft. */
.sa-stat-n {
  font-size: 26px; font-weight: 600; letter-spacing: -0.5px; font-variant-numeric: tabular-nums;
  line-height: 38px;
}
/* Een vak dat geen getal draagt maar een datum. Het draagt dezelfde kleur en hetzelfde gewicht
   als de aantallen ernaast, maar niet hun 26px: "08/09/2026 (07h42)" is dan 242px breed, en op
   het smalste venster waar de drie tegels nog naast elkaar staan (990px, net boven de sprong naar
   twee kolommen) is er 185px plaats. 18px is de grootste maat die daar op één regel past. */
.sa-app .sa-stat-n-sm { font-size: 18px; letter-spacing: 0; line-height: 38px; }
.sa-stat-l { font-size: 12.5px; color: var(--ink-3); margin-top: 2px; }
/* Een tegel die een link is, ziet er uit als de tegel ernaast: het is de rand die onder de muis
   verandert en niet de tekst, zoals bij de ingangen op het beheerscherm. */
.sa-app a.sa-stat { text-decoration: none; color: inherit; }
.sa-app a.sa-stat:hover { border-color: var(--ink-3); }
.sa-app a.sa-stat:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* Twee kolommen die elk hun eigen vakken opstapelen. Als één raster van vier vakken begon de
   tweede rij pas onder de hoogste van de eerste, en dan stond er onder Jachtverlof een gat zo hoog
   als de lijst met activiteiten ernaast. */
.sa-home-cols { display: grid; grid-template-columns: 1.6fr 1fr; gap: 16px; align-items: start; }
.sa-home-kolom { display: flex; flex-direction: column; gap: 16px; min-width: 0; }
.sa-tile { background: var(--surface); border: 1px solid var(--line); border-radius: 8px; }
/* The two tiles sit side by side, so their headers have to line up. One carries a button and
   the other only a heading, which made the left one taller by exactly the button's overhang.
   A fixed height settles that whatever a tile happens to hold.
   The heading is centred in the tile, so the button is taken out of the flow rather than laid
   out beside it — otherwise it pushes the heading off centre by half its own width, and the two
   tiles' titles no longer sit at the same place. */
.sa-tile-head {
  position: relative;
  display: flex; align-items: center; justify-content: center;
  height: 54px; padding: 0 18px; border-bottom: 1px solid var(--line);
}
.sa-tile-head .sa-btn { position: absolute; right: 18px; top: 50%; transform: translateY(-50%); }
.sa-app .sa-tile-head h2 { margin: 0; font-size: 14px; }
.sa-tile-body { padding: 16px 18px; }
.sa-app .sa-tile-body p { margin: 0 0 12px; }

/* The date box and the photograph stretch to whatever the text beside them needs, so a row that
   carries a teaser lines up over four lines and a row without one stays at --row-h. A fixed
   height left the box and the photo floating in the middle of the taller rows. */
.sa-evrow {
  display: flex; align-items: stretch; gap: 14px; padding: 13px 18px;
  border-bottom: 1px solid var(--line-soft); text-decoration: none; color: inherit;
}
.sa-evrow:last-child { border-bottom: 0; }
/* De hele rij is één <a>, dus de hele rij reageert: de achtergrond kleurt en de titel neemt de
   accentkleur aan. Zonder dat tweede leek alleen de titel het klikbare deel. */
.sa-evrow:hover { background: var(--hover); }
.sa-evrow:hover .sa-evrow-t { color: var(--accent-ink); }
.sa-evrow, .sa-evrow:hover .sa-evrow-t { text-decoration: none; }
/* The date box sets the height of a row, and the photo beside it matches — one measurement so
   the two line up top and bottom whether or not the box carries a year. */
.sa-evrow { --row-h: 62px; }
.sa-daybox {
  flex: 0 0 52px; min-height: var(--row-h);
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  border: 1px solid var(--line); border-radius: var(--radius); background: #fdfdfc;
}
.sa-daybox b { display: block; font-size: 17px; font-weight: 600; line-height: 1; }
.sa-daybox span { display: block; font-size: 10.5px; letter-spacing: 0.6px; text-transform: uppercase; color: var(--ink-3); margin-top: 3px; }
.sa-evrow-x { flex: 1; min-width: 0; display: flex; flex-direction: column; justify-content: center; }
/* Top-right, always — on a row with a teaser the badges would otherwise drift down to the middle
   of the block and stop lining up with the row above. */
.sa-evrow-tags { align-self: flex-start; }
/* De titel met het partnerlabel ernaast op één regel; bij een lange titel op een smal venster
   valt het label naar de volgende regel in plaats van de titel in te drukken. */
.sa-evrow-t {
  display: flex; align-items: center; flex-wrap: wrap; gap: 8px;
  /* De naam van de avond is waar een lid op zoekt als hij de lijst afloopt, en hij is de link. */
  font-weight: 700;
}
.sa-evrow-m { display: block; font-size: 12.5px; color: var(--ink-3); margin-top: 1px; }
/* The teaser, on the calendar rows of activities that have been and gone. Clamped to two lines:
   it is there to be read, but a row is still a row. */
.sa-evrow-desc {
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
  font-size: 12.5px; color: var(--ink-3); margin-top: 4px;
}
@media (max-width: 980px) {
  body.sa-app .sa-stats, body.sa-app .sa-stats-5 { grid-template-columns: repeat(2, 1fr); }
  body.sa-app .sa-home-cols { grid-template-columns: 1fr; }
  /* Op één kolom blijft de volgorde die van de bladzijde zelf: activiteiten, jachtverlof, stand,
     schietingen. De twee kolomwikkels verdwijnen daarvoor uit de opmaak (display: contents), zodat
     de vier vakken weer rechtstreeks in het raster liggen en elk hun eigen plaats kan krijgen. */
  body.sa-app .sa-home-kolom { display: contents; }
  body.sa-app .sa-home-kolom:first-child > :first-child { order: 1; }
  body.sa-app .sa-home-kolom:last-child > :first-child { order: 2; }
  body.sa-app .sa-home-kolom:first-child > :last-child { order: 3; }
  body.sa-app .sa-home-kolom:last-child > :last-child { order: 4; }
}

/* A text page keeps the club's own 980px. The content column is 1180 so that a table of
   sixty-seven members has room; prose at that width runs past a comfortable line length, and
   these pages are the Statuten and the fee table — things people actually read. */
.sa-app .sa-page-text { max-width: 980px; }
.sa-app .sa-page:has(> .sa-page-text) .sa-page-head { max-width: 980px; }

/* The permit tile's body lines up with the activity rows beside it: the same top padding as a
   row, so the first sentence starts level with the first activity's title. The badge is taken
   out of the flow into the corner, or it would push that sentence sideways. */
/* Measured against the activity row beside it, not guessed: its two lines sit centred in the
   row, which puts the title 23px below the top of the list. The paragraphs here take the same
   1px between them that the row's second line takes, so the two blocks have the same rhythm as
   well as the same first line. Both are 14px on 21px already. */
/* De vraag boven de waarschuwing in het jachtverlofblok: dezelfde afstand eronder als tussen twee
   alinea's, zodat de twee als één blok lezen. */
.sa-app .sa-permit-ask { margin: 0 0 10px; }

/* De tegel zonder geldig verlof: het label linksboven op zijn eigen regel, de waarschuwing
   eronder over de volle breedte. Het label is hier een hele zin — "Nog geen jachtvergunning
   geüpload." — en naast de tekst zetten perst die in een kolom van vier regels. */
.sa-app .sa-permit-waarschuwing { display: block; padding: 13px 18px 16px; }
.sa-app .sa-permit-waarschuwing > .sa-chip { float: none; margin: 0 0 8px; }
/* De driehoek staat in het label en niet meer voor de zin eronder. Het label draagt al de kleur
   van de waarschuwing, dus het teken neemt die over (currentColor in NOTICE_ICON) en hoeft niets
   van zichzelf. inline-flex met align-items: center zet hem op het midden van de tekst in plaats
   van op haar basislijn — een getekend teken heeft er geen. */
.sa-app .sa-permit-waarschuwing > .sa-chip { display: inline-flex; align-items: center; gap: 6px; }
.sa-app .sa-permit-waarschuwing > .sa-chip svg { width: 14px; height: 14px; flex: none; }
/* "verplicht" draagt het gewicht van de zin: vet én onderlijnd. Het is de enige plaats in de app
   waar een woord onderstreept staat, en dat is precies waarom het opvalt. */
.sa-app .sa-permit-waarschuwing strong { text-decoration: underline; text-underline-offset: 2px; }
/* De waarschuwing sluit het blok af, dus haar eigen marge eronder valt weg: die stond er om een
   volgende alinea op afstand te houden, en er komt er geen. */
.sa-app .sa-permit-waarschuwing > :last-child { margin-bottom: 0; }

/* 13px onder de streep, dezelfde afstand als een rij in de tegel ernaast: die twee staan naast
   elkaar en begonnen 10px uit elkaar. */
.sa-permit-summary { position: relative; padding: 13px 18px 16px; }
/* Het label staat op de hoogte van de regel waar het iets over zegt: dezelfde vulling als boven
   de tekst. Het stond hoger en hing daardoor los van de zin ernaast — allebei zijn ze 21px hoog,
   dus met dezelfde bovenkant vallen hun middens samen. */
.sa-app .sa-permit-summary > .sa-chip { position: absolute; top: 13px; right: 18px; margin: 0; }
.sa-app .sa-permit-summary p { margin: 0 0 1px; }
.sa-app .sa-permit-summary p:last-child { margin-bottom: 0; }
.sa-app .sa-permit-summary p:first-of-type { padding-right: 62px; }
.sa-app .sa-permit-summary p:last-child { margin-bottom: 0; }

/* ---- The calendar, one row per activity ---------------------------------- */
/* Elke activiteit is een kaart van zichzelf: één afspraak, één vlak. Ze stonden in één lijst met
   haarlijnen ertussen — en die lijnen waren er zelfs twee, want elke rij droeg er een onder zich
   én de volgende een boven zich. Zo leest de Kalender als de rest van het ledengedeelte, waar een
   blok altijd zijn eigen rand draagt. */
.sa-evlist { margin-bottom: 22px; }
.sa-app .sa-evlist > li, .sa-app .sa-evlist > .sa-evrow {
  background: var(--surface); border: 1px solid var(--line); border-radius: 8px;
  margin-bottom: 10px; overflow: hidden;
}
.sa-app .sa-evlist .sa-evrow { padding: 12px 16px; }
.sa-evrow-thumb {
  flex: 0 0 92px; width: 92px; height: auto; min-height: var(--row-h); align-self: stretch;
  border-radius: 5px; object-fit: cover;
  border: 1px solid var(--line); background: var(--line-soft); display: block;
}
/* Zonder foto het wapenschild, op de beheerlijsten net zo goed als op de ledenschermen: een leeg
   grijs vak zegt niet wat er ontbreekt, het wapen wel. */
.sa-app .sa-event-thumb-none { display: flex; align-items: center; justify-content: center; }
.sa-app .sa-event-thumb-none img { width: 58%; height: auto; opacity: 0.8; }
.sa-evrow-thumb-none { display: flex; align-items: center; justify-content: center; }
.sa-evrow-thumb-none img { width: 60%; height: auto; opacity: 0.8; }
.sa-evrow-tags { display: flex; align-items: center; gap: 6px; flex-shrink: 0; }
/* An activity that has been and gone: the row lightens and its photograph loses its colour, the
   same treatment the club's own past cards had. Both come back under the pointer, so a member
   looking one up sees it as it was. */
.sa-evrow-past { opacity: 0.66; }
.sa-evrow-past .sa-evrow-thumb { filter: grayscale(1); transition: filter .15s ease; }
.sa-evrow-past:hover { opacity: 1; }
.sa-evrow-past:hover .sa-evrow-thumb { filter: none; }
.sa-daybox i { display: block; font-style: normal; font-size: 10px; color: var(--ink-3); margin-top: 1px; }
@media (max-width: 720px) {
  body.sa-app .sa-evrow { flex-wrap: wrap; }
  body.sa-app .sa-evrow-thumb { display: none; }
  body.sa-app .sa-evrow-tags { width: 100%; padding-left: 66px; }
}

/* A section that is announced rather than empty: centred, ochre, with the icon of what will
   live here. The .sa-empty rule sets grey italics, which reads as a fault rather than as news. */
.sa-soon svg {
  width: 32px; height: 32px; display: block; margin: 0 auto 12px;
  stroke: var(--note); fill: none; stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round;
}
.sa-app .sa-soon p {
  margin: 0 auto; max-width: 420px;
  font-size: 14px; font-weight: 600; font-style: normal; color: var(--note);
}

/* The year over each group of albums. Not a badge on every card: on a page of 109 albums that
   printed the same four digits over and over without ever letting the eye jump to a season. */
.sa-app .sa-year-heading {
  display: flex; align-items: baseline; gap: 10px;
  font-size: 17px; font-weight: 700; color: var(--ink);
  margin: 44px 0 14px; padding-bottom: 8px; border-bottom: 1px solid var(--line);
}
.sa-app .sa-year-heading:first-child { margin-top: 0; }
.sa-app .sa-year-heading span { font-size: 12.5px; font-weight: 400; color: var(--ink-3); }
.sa-year-grid { margin-bottom: 4px; }

/* The memberships of the club, above its list: how many of each, and a way in. The chosen one
   is filled, the rest are outlines — the same shape as the stat tiles on the home, but these
   are links, so they say so by lighting up. */
/* Een raster en geen flexrij, sinds de Eed er als zevende tegel bij kwam: een flexrij rekt wat
   er op de laatste regel overblijft uit tot de volle breedte, en dan stond "Serment" in zijn
   eentje over het hele scherm terwijl de zes erboven 148px breed waren. Met auto-fit houdt een
   tegel die wegvalt de breedte van haar kolom. Onder 640px komt dat vanzelf op twee per regel uit,
   waar hier eerst een mediablok voor stond. */
.sa-memb-tiles {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(130px, 1fr));
  gap: 12px; margin-bottom: 18px;
}
.sa-app .sa-memb-tile {
  min-width: 0;
  display: flex; flex-direction: column; align-items: center; text-align: center; gap: 2px;
  padding: 13px 15px; border: 1px solid var(--line); border-radius: 8px;
  background: var(--surface); text-decoration: none; color: inherit;
}
.sa-app .sa-memb-tile:hover { border-color: #d4d1cb; background: var(--hover); }
.sa-app .sa-memb-tile.on { border-color: var(--accent); background: var(--accent-soft); }
.sa-memb-n { font-size: 22px; font-weight: 600; letter-spacing: -0.4px; font-variant-numeric: tabular-nums; }
.sa-memb-l { font-size: 12.5px; color: var(--ink-3); }
.sa-app .sa-memb-tile.on .sa-memb-l { color: var(--accent-ink); }

/* ---- Mijn Jachtverlof ---------------------------------------------------- */
/* The two faces of the card, side by side and large enough to read the dates off. A member
   files a picture, not a document: the file name their phone chose and the day they uploaded it
   said nothing, so neither is shown. */
/* De twee zijden staan in het raster van Mijn Account, elk drie kolommen breed, zodat ze
   samenvallen met de velden erboven. Daarom een breedte van 100% met de verhouding van een
   pasje (85 x 54 mm) in plaats van de vaste 260x172 van toen dit een eigen pagina was. */
.sa-permit-tile { display: flex; flex-direction: column; gap: 6px; }
.sa-permit-tile > a {
  display: block; width: 100%; aspect-ratio: 1.57; border-radius: 6px; overflow: hidden;
  border: 1px solid var(--line); background: var(--line-soft);
}
.sa-permit-tile img { width: 100%; height: 100%; object-fit: cover; object-position: top; display: block; }
.sa-permit-tile-none { display: block; width: 100%; height: 100%; }
/* Groen zolang het verlof loopt, rood zodra het verstreken is — dezelfde uitspraak als op het
   scherm van het bestuur, en geen uitspraak wanneer er geen periode bekend is. */
.sa-permit-tile.sa-permit-valid-frame > a { border: 2px solid var(--accent); }
.sa-permit-tile.sa-permit-expired-frame > a { border: 2px solid var(--danger); }
/* De tekening van een pasje vult zijn tegel, met de verhouding van de scan ernaast. Er stond nog
   een vaste 108x75 uit de tijd dat dit een strookje miniaturen was; een expliciete hoogte wint van
   aspect-ratio, dus de lege zijde kwam 75px hoog uit naast een scan van 127. */
.sa-permit-tile-empty .sa-permit-placeholder { display: block; width: 100%; height: auto; aspect-ratio: 1.57; }
.sa-permit-tile-empty .sa-permit-placeholder svg { width: 100%; height: 100%; display: block; }
.sa-app .sa-permit-remove {
  border: 0; background: none; padding: 0; font: inherit; font-size: 12.5px;
  color: var(--ink-3); cursor: pointer; text-align: left;
}
.sa-app .sa-permit-remove:hover { color: var(--danger); }
.sa-permit-tile-empty { opacity: 0.75; }
/* Onder 980px wordt elke rastercel de volle breedte. Een scan van een pasje moet dan niet
   meegroeien tot 760px — hij houdt zijn eigen maat, zoals de foto's op de publieke site. */
@media (max-width: 980px) {
  body.sa-app .sa-permit-tile { max-width: 300px; }
}

/* A line that continues the one above it — the second and further lines of an address. Tight
   against its predecessor, and never bold: only the line that opens the block is a label. */
/* Een regel die aansluit bij de regel erboven, draagt geen ruimte bóven zich; en wat erboven staat
   verliest de ruimte eronder. Twee regels voor één grens: marges klappen hier niet samen, want de
   ene is 0 en de andere 14, en dan blijft die 14 staan. */
.sa-app .sa-page-line { margin-top: 0; }
.sa-app .sa-page-text p:has(+ .sa-page-line) { margin-bottom: 0; }
/* De artikelkop een graad groter dan de club hem zet, en met 2px onder zich in plaats van niets:
   hij is een kop en geen eerste regel van zijn alinea. De regel moet ná die hierboven staan — die
   maakt van elke aansluitende alinea een marge van 0, en de twee wegen even zwaar, dus beslist de
   volgorde. De twee talen houden hun eigen graad (het Nederlands 13, het Frans 14 op de site van
   de club zelf); ze schuiven allebei één op, zodat het verschil blijft zoals het is. */
.sa-app .sa-page-text p.sa-page-label { font-size: 14px; margin-bottom: 2px; }
html[lang="fr"] body.sa-app .sa-page-text p.sa-page-label { font-size: 15px; }

/* The one instruction on this page that a member must not miss: uploading a file does nothing
   until Versturen is pressed. Ochre with a mark beside it, like every other remark the app makes
   — the line above it stays the club's own brown prose. The icon is a background image because
   the view prints a bare <p>; it sits on the first line, not centred, because this is an
   instruction in a sentence rather than an empty state. */
.sa-app .sa-permit-intro-bold {
  color: var(--note); font-weight: 600;
  padding-left: 26px; margin-bottom: 26px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='17' height='17' viewBox='0 0 24 24' fill='none' stroke='%23b45f06' stroke-width='1.8' stroke-linecap='round'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3Cpath d='M12 7.5v5.5'/%3E%3Cpath d='M12 16.4v.1'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: 0 2px;
}

/* A light rule under each heading on a text page, the way the club sets its own: it separates
   "Lidmaatschap" from the table under it and "Statuten" from the articles. */
/* A section heading on a text page carries more than a tile header does — it opens the Statuten,
   the fee table, the addresses — so it takes the size of the year headings rather than the 15px
   the app's h2 rule would otherwise give it. */
/* Geen streep onder een sectiekop. Ze stond er zolang deze kop de bovenste van de bladzijde was
   en dus haar titel; nu de titel van het stuk er boven staat, met haar eigen streep, zou de kop
   eronder dezelfde scheiding een tweede keer maken. De 34px boven en de graad houden hem een kop. */
.sa-app .sa-page-heading {
  font-size: 17px;
  padding-bottom: 0; margin-bottom: 14px; border-bottom: 0;
  /* De alineagrens van deze app, 34px — dezelfde afstand als boven een tussenkop op de Kalender.
     Het was 52, op de redenering dat een kop hier een heel hoofdstuk opent en dus meer lucht
     verdient; op de bladzijde viel dat gat te ruim uit. De kop houdt zijn onderscheid aan zijn
     graad, zijn gewicht en de streep eronder. De reset moet herhaald worden: de regel van de app
     staat na de basisregel en wint van haar :first-child. */
  margin-top: 34px;
}
.sa-app .sa-page-heading:first-child { margin-top: 0; }
/* De titel van het stuk zelf, boven zijn eerste hoofdstuk: een graad boven een sectiekop, met
   dezelfde streep eronder. De sectiekop die erop volgt draagt zijn 34px niet meer — hij opent
   geen blok meer maar staat onder de titel van het stuk. */
.sa-app .sa-page-doctitle {
  font-family: "Montserrat", sans-serif; font-size: 20px; font-weight: 700; color: #444;
  margin: 0 0 14px; padding-bottom: 8px; border-bottom: 1px solid var(--line);
}
.sa-app .sa-page-doctitle + .sa-page-heading { margin-top: 0; }
/* Wat het bestuur met een lege alinea vraagt: een gat, niet alleen een alineagrens. */
.sa-app .sa-page-spaced { margin-top: 30px; }

/* Een opsomming op een tekstpagina: de wisselbekers, de schietingen met handicap. */
.sa-app .sa-page-list { margin: 0 0 14px; padding-left: 20px; }
.sa-app .sa-page-list li { margin-bottom: 3px; }
.sa-app .sa-page-list li:last-child { margin-bottom: 0; }
/* De twee dingen die een ingeschreven lid nog kan doen, naast elkaar: de avond in zijn agenda
   zetten, of zich uitschrijven. */
.sa-app .sa-ev-actions { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.sa-app .sa-ev-actions form { margin: 0; }
.sa-app .sa-ev-ics svg { flex-shrink: 0; }

/* De geldigheidsdatum draagt dezelfde uitspraak als het kader om de scans, en sinds september 2026
   voluit gekleurd: lichtgroen met donkergroene tekst zolang het verlof loopt, vol rood met witte
   tekst zodra het niet meer geldt. Het waren zachte vullingen (--accent-soft, --danger-soft) met gewone inkt erin; het
   bestuur vond dat te weinig voor wat het veld zegt, en zette het in stappen om.

   De twee kanten zijn daarbij níét elkaars spiegelbeeld, en dat is een keuze: het rood draagt
   witte tekst en het groen donkergroene. Het bestuur vroeg om steeds lichter groen, en wit houdt
   dat niet bij — op #3d7a58 haalt het nog 5,1:1, een stap lichter (#458863) nog 4,2 en dus onder
   de vloer van 4,5. Hoe lichter het vlak, hoe beter donkere tekst het juist doet: #21432f op
   #b5dcc7 haalt 7,4:1. Op het rood haalt wit 7,2:1.

   Daarom staat er ook geen omgekeerd kalendericoon meer op het groene veld: dat icoon is donker,
   en dat klopt nu weer op een licht vlak. Op het rode blijft de omkering nodig.

   De volle :not()-ketting: de algemene regel voor input zet de achtergrond ronduit, en een
   selector met alleen klassen ervoor verliest daarvan. Ze weegt ook zwaarder dan de
   :disabled-regel hierboven, die het grijs zet achter het alleen-lezen veld op Mijn gegevens — zo
   draagt dat veld de kleur zonder er bewerkbaar uit te zien. -webkit-text-fill-color hoort erbij,
   want daarmee kleurt WebKit de tekst van een uitgeschakeld veld grijs, bóven color heen; de rand
   neemt dezelfde kleur, omdat een hairline in --line om een vol vlak als een rafel leest. */
.sa-app input.sa-date-valid:not([type=checkbox]):not([type=radio]):not([type=submit]):not([type=button]) {
  background: #b5dcc7; border-color: #b5dcc7;
  color: var(--accent-ink); -webkit-text-fill-color: var(--accent-ink); font-weight: 600; opacity: 1;
}
/* Ongeldig is het volle rood met witte tekst, op alle drie de schermen: de fiche, het
   bewerkscherm ernaast en Mijn gegevens. Het was een lichtrood vlak, wat naast het groen van een
   lopend verlof te weinig verschil maakte voor wat het zegt — geen geldig verlof is de reden
   waarom een lid niet op de schietstand mag. Het bestuur zette het in drie stappen: lichtrood,
   rode tekst op wit, en dit. Wit op #a32b1c haalt 7,2:1, ruim boven de vloer.

   Op de fiche staat er geen datum in dit veld maar wat er aan de hand is ("Vervallen sinds
   30 juni 2026", "Geen geldig jachtverlof"); op de twee andere schermen een datum.

   -webkit-text-fill-color moet erbij, want daarmee kleurt WebKit de tekst van een uitgeschakeld
   veld grijs, bóven color heen. De rand neemt dezelfde kleur: een hairline in --line om een vol
   vlak leest als een rafel. En het kalendericoon van een type=date wordt omgekeerd, anders staat
   een zwart icoon op een rode achtergrond. */
.sa-app input.sa-date-expired:not([type=checkbox]):not([type=radio]):not([type=submit]):not([type=button]) {
  background: var(--danger); border-color: var(--danger);
  color: #fff; -webkit-text-fill-color: #fff; font-weight: 600; opacity: 1;
}
.sa-app input.sa-date-expired::-webkit-calendar-picker-indicator { filter: invert(1); }

/* Dezelfde waarschuwingsdriehoek als op de tegel van de startbladzijde, in het rode veld (het
   bestuur, oktober 2026). Drie dingen die het nodig had:

   - **alleen op een uitgeschakeld veld.** Daar staat geen datum maar een zin — "Nog geen scan
     opgeladen" — en dat is wat een teken verdient. In het bewerkscherm ernaast staat er een datum
     die het bestuur typt, en dan zou een teken links van de cursor komen te staan.
   - **een achtergrondbeeld en geen element**: in een <input> past niets. Daarom ook de ruimte
     links, zodat de tekst er niet bovenop komt.
   - **wit en met %23 geschreven.** De tekst in dit veld is wit, dus het teken ook; een kale # in
     een data-URI kapt het adres af. Dezelfde val als bij het vinkvakje.

   De :not()-ketting staat er ook hier, en dat is geen kopieerwerk: de regel hierboven zet
   background als verkorting, wat background-image op none zet, en met vier :not()'s weegt ze
   zwaarder dan een losse :disabled. Zonder die ketting wint zij en blijft het teken weg —
   nagegaan, want zo stond het er eerst. */
.sa-app input.sa-date-expired:not([type=checkbox]):not([type=radio]):not([type=submit]):not([type=button]):disabled {
  padding-left: 32px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='15' height='15' viewBox='0 0 24 24' fill='%23ffffff'%3E%3Cpath d='M12 2.5 1.5 21h21L12 2.5Zm0 5.2c.6 0 1 .5 1 1.1l-.3 5.4a.7.7 0 0 1-1.4 0l-.3-5.4c0-.6.4-1.1 1-1.1Zm0 9a1.2 1.2 0 1 1 0 2.4 1.2 1.2 0 0 1 0-2.4Z'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: 11px center;
}

/* Wat er vandaag ligt, boven het vak om het te vervangen: even breed als dat vak, met dezelfde
   ronding als elke andere kaart. Het stond op 200px met een eigen ronding in een style-attribuut. */
/* Een vak voor een getal van twee cijfers. De rastercel is al smal, maar zodra de cellen onder
   elkaar vallen neemt een veld de volle breedte — en een vak van vierhonderd pixels voor "9" zegt
   dat er iets langers in hoort. */
.sa-app input.sa-veld-kort { max-width: 90px; }

.sa-app .sa-admin-preview {
  display: block; width: 100%; max-width: 460px; height: auto;
  border: 1px solid var(--line); border-radius: 8px; margin-bottom: 10px;
}

/* Een kolom die alleen ja of nee draagt, is zo breed als haar kop en niet breder: het vinkje
   staat eronder in het midden, zodat dertig regels één rechte kolom vormen. */
.sa-app .sa-cel-vink { width: 1%; white-space: nowrap; text-align: center; }
.sa-app .sa-wix-table th.sa-cel-vink, .sa-app thead th.sa-cel-vink { text-align: center; }
/* Het vinkje staat op het midden van de regel en niet op de basislijn: als inline-flex sleept het
   de ruimte onder de basislijn mee, en dat maakte elke rij met een vinkje vijf pixels hoger dan
   haar tekst nodig had — op een lijst van zestig regels is dat een half scherm. */
.sa-app .sa-cel-vink .sa-mark-yes { display: inline-flex; vertical-align: middle; }

/* Iets minder lucht boven en onder een rij dan de 11 die een gewone tabel draagt: deze lijst is
   lang, en een lid met zijn genodigden en zijn opmerking is al drie tot vijf regels. */
.sa-app .sa-attendee-table td { padding-top: 8px; padding-bottom: 8px; }
/* Deze staat vóór de regels hieronder en niet erna: een gastrij en een notaregel dragen hun eigen,
   kleinere padding, en die wegen even zwaar. Stond ze erna, dan won ze en stonden de genodigden
   weer twaalf pixels uit elkaar in plaats van vier. */

/* Het blad waarop het bestuur de inschrijvingen beheert. Het draagt dezelfde tabel als de
   deelnemerslijst, maar met velden erin: de naamkolom rekt mee, de vinkkolommen zijn zo breed als
   hun kop, en de opmerking krijgt wat overblijft. */
/* De verdeling. Zonder dit vroeg de naamkolom alles op: het veld van een genodigde stond op 100%
   van een kolom die meerekt, dus groeiden ze samen tot zeshonderd pixels terwijl de opmerking er
   zevenentachtig overhield en bij een breder scherm buiten de kaart viel. Nu is elk veld zo breed
   als een naam of een opmerking hoort te zijn, en verdeelt wat overblijft zich niet meer over één
   kolom. */
/* Een echte breedte op het veld en niet 100% van zijn cel: die cel had geen inhoud van zichzelf,
   dus zakte ze in tot de breedte van haar kop — zevenentachtig pixels — terwijl de naamkolom, die
   meerekt, alles opeiste.
   
   De selector herhaalt de vijf :not()-clausules van de algemene inputregel. Die weegt (0,5,1) en
   zet width op 100%; een gewone klasseselector verliest daarvan. Dat is in dit bestand nu de derde
   plaats waar die val staat — zie ook het uitgeschakelde veld en de inspringing van een gastnaam. */
/* De opmerking vult haar kolom, en die kolom is degene die meerekt. Ze stond op een vaste 220px
   terwijl de naamkolom alles opeiste, en dan was een opmerking een vakje van een paar woorden op
   een blad van elfhonderd pixels. Nu is het omgekeerd: de naam is zo breed als de langste naam,
   de vinkjes staan er pal naast, en wat overblijft is voor wat een lid schreef. */
.sa-app .sa-inschrijfblad td.sa-cel-nota
  input:not([type=checkbox]):not([type=radio]):not([type=submit]):not([type=button]) { width: 100%; }
.sa-app .sa-inschrijfblad
  input.sa-gastveld:not([type=checkbox]):not([type=radio]):not([type=submit]):not([type=button]) {
  width: 280px;
}
.sa-app .sa-inschrijfblad td.sa-cel-nota input,
.sa-app .sa-inschrijfblad .sa-gastveld { height: 32px; font-size: 13px; margin: 0; }
/* De naam van een genodigde is hier een veld en geen tekst, dus de inspringing zit op de cel en
   niet op de tekst erin: de 16px die elke cel draagt plus de 20px waarmee een genodigde onder zijn
   gastheer inspringt. Het stond op 20 in het geheel, wat klopte zolang het blad de klasse van de
   deelnemerslijst droeg — die zet de eerste cel op nul. */
.sa-app .sa-inschrijfblad td.sa-gastnaam { padding-left: 36px; }
.sa-app .sa-inschrijfblad .sa-gastrij > td { padding-top: 2px; padding-bottom: 2px; }

/* Een genodigde staat onder zijn gastheer: ingesprongen en grijs, zodat de lijst leest als één
   naam met wie hij meebrengt en niet als twee soorten regels door elkaar. De lijn boven zo'n regel
   is er niet — een lid en zijn genodigden zijn één gezelschap — en de lijn onder de laatste van
   hen sluit de groep af. */
.sa-app .sa-gastrij > td { border-bottom: 0; padding-top: 0; padding-bottom: 2px; }
/* De laatste genodigde van een groep sluit ze af: 8px, dezelfde als een gewone rij eronder draagt,
   waar het er 11 waren. */
.sa-app .sa-gastrij:last-child > td,
.sa-app .sa-gastrij:has(+ .sa-attendee-row) > td { padding-bottom: 8px; }
.sa-app .sa-attendee-row:has(+ .sa-gastrij) > td { border-bottom: 0; padding-bottom: 1px; }
.sa-app .sa-gastrij + .sa-attendee-row > td { border-top: 1px solid var(--line-soft); }
/* De inspringing moet het over de algemene celregel halen (.sa-app .sa-wix-table td), vandaar de
   klasse óp td en niet ernaast. Een punt kleiner dan de naam van het lid (13 tegen 14): de
   inspringing en het grijs zeggen al bij wie hij hoort, de maat maakt het af. */
.sa-app .sa-wix-table td.sa-gastnaam { color: var(--ink-3); font-size: 13px; }
/* De inspringing draagt :first-child mee omdat de regel die de eerste kolom tegen de rand van de
   kaart zet even zwaar weegt en later staat: zonder dit stond een genodigde recht onder zijn
   gastheer in plaats van eronder ingesprongen, en dan leest de lijst als twee soorten regels door
   elkaar. Twintig vanaf de rand van de kaart, waar het er vierendertig waren vanaf een tabel die
   zelf al zestien inspong. */
.sa-app .sa-attendee-table td.sa-gastnaam:first-child { padding-left: 20px; }

/* Wat het lid antwoordde, onderaan zijn groep over de hele breedte. Een punt kleiner dan de naam
   van een genodigde (12 tegen 13): het is een aantekening bij de namen erboven en geen naam. Het
   pijltje zegt bij wie ze hoort, zoals de + dat doet bij een genodigde, en staat in de marge zodat
   de tekst zelf uitlijnt met de ingesprongen namen. */
.sa-app .sa-attendee-table .sa-notarij > td {
  border-bottom: 0; padding-top: 2px; padding-bottom: 8px;
  color: var(--note); font-size: 12px; line-height: 17px; white-space: normal;
}
/* "Nota:" voor de tekst, waar eerst een pijltje stond. Het woord zegt wat het is; een pijltje
   zei alleen dat er iets boven stond. De hele regel staat in de okerkleur van een opmerking
   (--note), de kleur die elders in dit ledengedeelte al zegt "dit is een aantekening" — dat doet
   het werk waar eerst cursief voor stond, en cursief op 12px leest slecht. Het springt mee in tot waar de + van een genodigde
   staat, zodat elke ingesprongen regel van de groep op dezelfde plaats begint — de inspringing zit
   draagt :first-child mee: de regel die de eerste kolom tegen de rand van de kaart zet weegt
   anders even zwaar en wint, en dan begint "Nota:" twintig pixels links van de genodigden. Dat is
   nu twee keer gebeurd — bij de gastnaam en hier. */
.sa-app .sa-attendee-table .sa-notarij > td:first-child { padding-left: 20px; }
.sa-app .sa-nota-in { display: flex; gap: 6px; }
.sa-app .sa-nota-label { flex: 0 0 auto; }
/* Het teken staat op de eerste regel van de opmerking en niet op het midden van het blok: bij
   twee antwoorden onder elkaar zou het anders tussen de twee zweven. */
.sa-app .sa-nota-label svg { display: block; margin-top: 2px; }
/* Meer dan één antwoord staat onder elkaar, uitgelijnd achter het woord en niet eronder. */
.sa-app .sa-nota-tekst { display: flex; flex-direction: column; min-width: 0; }
/* De regel onder de groep komt van de rij erna; een notaregel sluit de groep dus zelf af. */
.sa-app .sa-notarij:last-child > td { padding-bottom: 11px; }
.sa-app .sa-notarij + .sa-attendee-row > td { border-top: 1px solid var(--line-soft); }
.sa-app .sa-attendee-row:has(+ .sa-notarij) > td,
.sa-app .sa-gastrij:has(+ .sa-notarij) > td { border-bottom: 0; padding-bottom: 1px; }
/* Genodigden onder elkaar staan tegen elkaar aan: ze zijn één gezelschap onder één naam. De
   ruimte tussen twee van hen kwam vooral uit de regelhoogte, niet uit de padding — 19.5px op
   tekst van 13 laat ruim drie pixels boven en onder. */
.sa-app .sa-attendee-table .sa-gastrij > td { line-height: 17px; }
.sa-app .sa-gastrij:has(+ .sa-gastrij) > td { padding-bottom: 0; }

/* Een naam blijft op één regel. Zonder dit deelt de browser de breedte over vijf kolommen en
   breekt "Philippe De Groulaer" over drie regels, terwijl de kolom ernaast een vinkje draagt. */
/* Geen rand van zichzelf: de tabel staat al in de kaart met de deelnemers, en een kaart in een
   kaart is een vlak rond een vlak — dezelfde regel die het albumraster en de archiefmappen volgen.
   Het scheelt de rand plus de ronding aan weerszijden. */
.sa-app .sa-attendee-table { border: 0; border-radius: 0; margin: 0; }
/* De koppen bovenaan, de rijen in het midden. Alles stond een tijd bovenaan omdat de opmerking in
   een kolom "Extra info" over drie regels liep en de naam ernaast tussen die regels zweefde; nu de
   opmerking een rij van zichzelf heeft, is er in een rij niets meer dat hoger is dan één regel. */
.sa-app .sa-attendee-table th { vertical-align: top; }
.sa-app .sa-attendee-table td { vertical-align: middle; }
/* De kop blijft op één regel; de namen eronder niet. Met nowrap op de cellen werd de naamkolom zo
   breed als de langste naam — "+ Nicolas del Fosse d'Espierres" ingesprongen — en op een activiteit
   waar deze kaart naast Details staat is die kolom nog geen vierhonderd pixels breed. De tabel
   schoof dan zijwaarts en de kolom Diner viel buiten de kaart. Een naam die niet past breekt nu
   over twee regels, wat op een lijst van zevenennegentig een paar rijen hoger maakt en niets
   verbergt. */
.sa-app .sa-attendee-table th:first-child { white-space: nowrap; }
/* De tabel begint waar de kop en de telling erboven beginnen: geen inspringing meer aan de
   binnenzijde van de kaart. Ze had er 16 van de algemene celregel, en dan stond "Naam" zestien
   pixels rechts van "Aantal deelnemers". Aan de andere kant hetzelfde, zodat ze de kaart vult. */
.sa-app .sa-attendee-table th:first-child,
.sa-app .sa-attendee-table td:first-child { padding-left: 0; }
.sa-app .sa-attendee-table th:last-child,
.sa-app .sa-attendee-table td:last-child { padding-right: 0; }
/* Eén kolom rekt mee (.sa-cel-rek) en de rest is zo breed als haar inhoud. Zonder dat verdeelt de
   browser wat er overblijft over álle kolommen, en dan staan de twee vinkjes een halve kaart van
   hun naam vandaan. Welke kolom meerekt, kiest de view: de vrije tekst wanneer die er is, anders
   de kolom met de knoppen, anders de naam. */
.sa-app .sa-attendee-table th, .sa-app .sa-attendee-table td { width: 1%; }
.sa-app .sa-attendee-table .sa-cel-rek { width: 100%; }
/* De twee handelingen van het lid staan onderaan rechts in Details, waar in dit ledengedeelte de
   knoppen van een kaart staan. De 22px erboven is de afstand die een blok onder zich draagt voor
   wat erop volgt; hier volgt de onderrand van de kaart. */
.sa-app .sa-ev-acties { justify-content: flex-end; margin-top: 22px; }


/* Het inschrijvingsformulier: één regel per persoon — het lid bovenaan met zijn eigen naam, de
   gasten eronder.

   Het formulier is één kolom van 660px en niet de volle kaart. Over de volle breedte stond een
   naamveld van vijftienhonderd pixels met de twee vinkjes een halve bladzijde verderop, en dan
   hoort de vraag niet meer bij het antwoord. Zo krijgt de naam de ruimte van een naam, staan de
   twee vragen er meteen naast, en vallen de rechterrand van de tabel, die van het opmerkingenvak
   en die van de knop op dezelfde lijn. De kaart zelf behoudt haar breedte: ze hoort bij de kaarten
   erboven. */
/* De twee kaarten naast elkaar zolang er ingeschreven kan worden: wat de avond is links, wie er
   meekomt rechts. De linkerkolom krijgt iets meer, want ze draagt de foto en de tekst; allebei
   beginnen ze bovenaan (align-items: start), anders wordt de kortste van de twee even hoog als de
   langste en staat er een lege kaart. Onder 1000px staan ze weer onder elkaar: twee kolommen van
   nog geen 400px maken van een naamveld een vakje. */
.sa-app .sa-ev-twee {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 18px; align-items: start;
}
.sa-app .sa-ev-twee > * { margin-bottom: 0; }
/* De kaarten binnen het raster dragen geen marge meer, dus draagt het raster ze: zonder dit stond
   het blok met de deelnemers tegen de onderrand van de kaarten aan. */
.sa-app .sa-ev-twee { margin-bottom: 18px; }
/* De telling onder de kop van de deelnemerskaart: met hoeveel, hoeveel ervan schieten en hoeveel
   mee-eten, elk op een regel. Ze stond in de kop van het vouwblok, achter de titel, en daarna één
   regel met punten ertussen. De 4px houdt de drie bij elkaar als één opsomming; de 14 eronder
   scheidt ze van de lijst. */
/* Dezelfde interlinie als in de kaart ernaast. De tellingen droegen vier pixels tussen hun regels
   waar Datum, Locatie en Adres links op hun eigen regelhoogte staan — 24 tegen 20 — en twee
   kaarten naast elkaar horen hetzelfde te lezen. */
.sa-app .sa-deelnemers-tel { margin: 0 0 14px; }
.sa-app .sa-deelnemers-tel p { margin: 0; }

@media (max-width: 1000px) {
  .sa-app .sa-ev-twee { grid-template-columns: minmax(0, 1fr); }
}

/* Evenveel ruimte binnen de twee kaarten naast elkaar. De linkerkaart draagt haar eigen 20px rondom;
   de rechter heeft er geen — daar is het blok zélf de kaart, met 20px boven en 16px onder, plus de
   22px die een blok onder zich draagt voor het blok dat erop volgt. Hier volgt er geen: het is het
   enige blok in die kaart. Dus die marge eraf, en onderaan een padding die mét de 5px die de
   knoppenrij zelf meebrengt op dezelfde 21px uitkomt als links (nagemeten, niet geschat). */
.sa-app .sa-rsvp-form .sa-fset { margin-bottom: 0; padding-bottom: 16px; }
.sa-app .sa-rsvp-form .sa-fset > :not(legend) { max-width: 660px; }
/* "Opmerkingen" staat in dezelfde kolomkop-vorm als NAAM, SCHIETING en DINER erboven: het is een
   veldnaam in hetzelfde blok, en twee soorten etiketten onder elkaar lezen als twee soorten velden. */
.sa-app .sa-rsvp-form label[for="sa-rsvp-note"] {
  font-size: 11px; font-weight: 600; letter-spacing: 0.6px; text-transform: uppercase;
  color: var(--ink-3);
}
/* Vaste kolommen, want het zijn twee tabellen: de eigen regel draagt de koppen, de gastregels
   staan in een tweede tabel achter de vouw. Zonder een vaste breedte rekent elke tabel haar eigen
   kolommen uit en staan de vinkjes niet meer onder hun kop. */
.sa-app .sa-rsvp-tabel { table-layout: fixed; }
.sa-app .sa-rsvp-tabel td { vertical-align: middle; }
/* Het naamveld krijgt wat de twee vraagkolommen niet nodig hebben: die zijn zo breed als hun kop
   (96px is "SCHIETING" op 11px in kapitalen plus haar ruimte) en geen pixel meer, en de naamcel
   houdt links noch rechts een marge die niets draagt. */
.sa-app .sa-rsvp-tabel th:first-child, .sa-app .sa-rsvp-tabel td:first-child {
  padding-left: 0; padding-right: 8px;
}
.sa-app .sa-rsvp-tabel .sa-cel-vink { width: 96px; padding-left: 10px; padding-right: 10px; }

/* "Ik breng iemand mee": de gastregels staan dicht, want de meeste leden komen alleen. Het is een
   knop — dezelfde als elke andere lichte knop in de app (.sa-btn.sa-btn-secondary), hier op een
   <summary>, zodat het openklappen van de browser blijft komen en er nog altijd geen script aan te
   pas komt. Het icoon is een persoon met een plus: de knop voegt iemand toe, en dat zegt meer dan
   een driehoekje, dat alleen zegt dat er iets opengaat. */
.sa-app .sa-gasten { margin: 2px 0 16px; }
.sa-app .sa-gasten > summary {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  height: 34px; padding: 0 14px; border-radius: var(--radius);
  font-family: inherit; font-size: 13px; font-weight: 500;
  border: 1px solid var(--line); background: var(--surface); color: var(--ink);
  cursor: pointer; list-style: none; width: auto;
}
.sa-app .sa-gasten > summary::-webkit-details-marker { display: none; }
.sa-app .sa-gasten > summary svg { flex: 0 0 auto; }
.sa-app .sa-gasten > summary:hover { background: var(--line-soft); border-color: #d9d6d1; }
/* De eerste gastregel draagt zelf de lijn boven zich: de tabel erboven sluit met een rand die er
   dicht al staat. */
.sa-app .sa-gasten table { margin-top: 10px; }
.sa-app .sa-vinkje { display: inline-flex; margin: 0; }

/* De twee knoppen naast de eigen inschrijving in de deelnemerslijst: de avond in de agenda, en
   annuleren. De rij is al een flexrij met space-between, dus ze belanden rechts; op een smal
   scherm vallen ze onder de naam in plaats van hem in te drukken. */
.sa-app .sa-attendee-actions { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; flex: 0 0 auto; }
/* De twee eigen handelingen staan rechtsonder op de rij van de eigen inschrijving — geen regel
   van zichzelf, want een lid dat zichzelf in de lijst ziet staan, staat daar. Ze stonden op de
   basislijn van de eerste regel, dus hoog naast een rij van drie regels. */
.sa-app .sa-attendee { align-items: flex-end; }
.sa-app .sa-attendee-actions form { margin: 0; }

/* De knoppenrij ín een blok, rechtsonder tegen de rand. Anders dan .sa-form-foot, die onder de
   kaarten van een formulier staat: daar slaat één knop meerdere blokken op, hier bevestigt een lid
   het blok waar hij in staat. */
.sa-app .sa-fset-foot {
  display: flex; justify-content: flex-end; align-items: center; gap: 10px; flex-wrap: wrap;
  margin-top: 4px;
}
.sa-app .sa-fset-foot form { margin: 0; }

/* Een opsomming in de tekst van een activiteit: dezelfde maat als de alinea's eromheen. */
.sa-app .sa-rich-list { margin: 0 0 12px; padding-left: 20px; }
.sa-app .sa-rich-list li { margin-bottom: 3px; }

/* De knop onder de tekstvelden van een activiteit, met haar opmerking ernaast. */
.sa-app .sa-translate { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin: 4px 0 0; }
/* Allebei de kinderen zonder eigen marge, anders lijnt de rij niet uit op wat je ziet: flex
   centreert de **marge**box, en de knoppenrij draagt er 13px boven zich (de gewone afstand van een
   knoppenrij tot het veld erboven). De helft daarvan — 6,5px — duwde de knoppen omlaag ten
   opzichte van de opmerking ernaast. De rij zelf houdt haar eigen 4px boven. */
.sa-app .sa-translate .sa-note, .sa-app .sa-translate .sa-knoprij { margin: 0; }

/* ---- Choosing a file ------------------------------------------------------ */
/* The generic input rule gives every field a 36px box and 11px of padding, which squashes the
   native file control and stretches it across the whole panel. A file input is not a text field:
   it is a button plus the name of what was picked. So it gets its own box — dashed, to read as a
   slot waiting to be filled — and the browser's own button is dressed as one of ours through
   ::file-selector-button, which needs no script and no hidden-input trick. */
.sa-app input[type=file]:not([type=checkbox]):not([type=radio]):not([type=submit]):not([type=button]) {
  height: auto; padding: 9px 11px; max-width: 460px;
  border: 1px dashed #cfccc6; border-radius: var(--radius); background: #fcfcfb;
  font-size: 13px; color: var(--ink-2); cursor: pointer;
}
.sa-app input[type=file]:hover { border-color: var(--accent); background: var(--accent-soft); }
.sa-app input[type=file]::file-selector-button {
  margin-right: 12px; height: 28px; padding: 0 12px;
  border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface); color: var(--ink);
  font-family: inherit; font-size: 12.5px; font-weight: 500; cursor: pointer;
}
.sa-app input[type=file]::file-selector-button:hover { background: var(--hover); border-color: #d9d6d1; }
/* Two slots under one another rather than side by side, each on its own line. */
.sa-app .sa-permit-input { display: block; width: 100%; margin-bottom: 4px; }

/* One slot per side of the card, each saying which side it is. */
.sa-permit-drop { display: block; font-size: 12px; color: var(--ink-3); }
/* De laatste opmerking is het enige dat het lid nog moet doen, dus halfvet. */
.sa-app .sa-permit-remind { font-weight: 600; }
/* Elke kaart eindigt met dezelfde afstand tussen haar laatste inhoud en de streep boven de knop.
   Die afstand komt van de marge onder het blok (22px); wat er als laatste in staat brengt er
   4px bij, zoals een rasterrij dat doet. Zonder dit stond de opmerkingenlijst 26px onder zich te
   dragen en het jachtverlofblok dus 48px waar de andere twee er 26 hadden. */
.sa-app .sa-fset > :last-child { margin-bottom: 4px; }
.sa-app .sa-fset > .sa-fgrid:last-child { margin-bottom: 4px; }
/* En dezelfde afstand onder elke bloktitel. Een <legend> ligt op de rand van de fieldset,
   niet in de padding, dus haar marge klapt niet samen met die van het element eronder:
   een opmerking met 12.5px erboven zette de ene titel 23px van haar inhoud en de andere 10. */
.sa-app .sa-fset > legend + *, .sa-app .sa-fset > summary + * { margin-top: 0; }

/* Een blok dat opengaat op zijn eigen titel. De <summary> ziet eruit als een <legend> en draagt
   een driehoekje dat meedraait; verder doet de browser het werk. De haarlijn eronder staat er
   expliciet: de gedeelde regel gebruikt :last-of-type, en dat kijkt per elementsoort — een
   <details> tussen fieldsets is altijd de laatste van zijn soort en zou de streep dus missen. */
.sa-app .sa-fset-fold > summary {
  display: flex; align-items: center; gap: 7px; cursor: pointer; list-style: none;
  font-size: 11px; font-weight: 700; letter-spacing: 0.8px; text-transform: uppercase;
  color: var(--ink-2); margin-bottom: 10px;
}
.sa-app .sa-fset-fold > summary::-webkit-details-marker { display: none; }
.sa-app .sa-fset-fold > summary::before {
  content: ""; width: 0; height: 0; border-left: 5px solid currentColor;
  border-top: 4px solid transparent; border-bottom: 4px solid transparent;
  transition: transform .12s ease;
}
.sa-app .sa-fset-fold[open] > summary::before { transform: rotate(90deg); }
.sa-app .sa-fset-fold > summary:hover { color: var(--ink); }
/* Gesloten is dit blok alleen zijn titel; dan draagt de titel geen ruimte meer onder zich, zodat
   de kaart even hoog is als de titelbalk die ze toont. */
.sa-app .sa-form .sa-fset-fold:not([open]) { padding-bottom: 20px; }
.sa-app .sa-form .sa-fset-fold:not([open]) > summary { margin-bottom: 0; }
/* De waarschuwing over de verzekering. Dezelfde rode driehoek als in de activiteitenteksten,
   maar halfvet in plaats van vet: hij staat in een formulier, niet in lopende tekst. */
/* De zin onder het label. Ze droeg zelf de driehoek en de inspringing van .sa-notice; sinds het
   teken in het label staat, is ze een gewone regel in de kleur van de waarschuwing. */
.sa-app .sa-permit-notice {
  font-weight: 600; font-size: 12.5px; margin: 0 0 14px; color: var(--danger);
}
/* De waarschuwing boven het inschrijvingenblad sluit aan op datum, locatie en adres, en die drie
   staan als één groep tegen elkaar (geen marge, 19px per regel). Zonder deze ruimte raakte ze de
   adresregel — nul pixels ertussen — en dan leest ze als een vierde feit in plaats van als een
   waarschuwing erover. Dertien is dezelfde afstand die een opmerking onder een veld draagt.

   Wat er niet verandert: het teken staat op de linkerrand, gelijk met "Datum:" erboven, en de
   tekst springt 26px in. Dat is de vorm van elke waarschuwing hier, en ze is er voor een tweede
   regel: die hoort onder het eerste woord te beginnen en niet onder de driehoek.

   Deze regel staat ná .sa-permit-notice en niet ervóór: die zet margin als verkorting en weegt
   even zwaar, dus beslist de volgorde. Ervóór deed ze niets. */
.sa-app .sa-blad-waarschuwing { margin-top: 13px; }

/* Datum, locatie en adres openen het inschrijvingenblad, en dan hoort hun eigen marge eraf: elke
   andere kaart in deze app begint op 21px van haar rand — de 20 van de kaart plus de 1 die een kop
   meebrengt — en deze begon op 31, omdat een alinea er 10 van zichzelf bij legde. Alleen als
   eerste kind: op de bladzijde van een lid staan diezelfde drie regels ónder de kop "Details", en
   daar is die 10px precies de ruimte die ze van de kop scheidt. */
.sa-app .sa-panel > .sa-event-meta-date:first-child { margin-top: 0; }

/* A file input takes a dropped file by itself; this only says so while one is over it. */
.sa-app input[type=file].sa-dropping {
  border-color: var(--accent); border-style: solid; background: var(--accent-soft);
}

/* ---- The door ------------------------------------------------------------ */
.sa-gate { display: flex; align-items: center; justify-content: center; min-height: 100vh; padding: 40px 24px; }
.sa-gate-box { width: 100%; max-width: 380px; }
.sa-gate-brand { display: block; text-align: center; text-decoration: none; color: inherit; margin-bottom: 40px; }
/* The crest carries the page, so it is given the room to: 58px rather than 48, and the wordmark
   set clear of it. */
.sa-gate-brand img { display: block; width: 87px; height: 87px; margin: 0 auto 16px; }
.sa-gate-brand .sa-brand-eyebrow { font-size: 13px; line-height: 19px; }
.sa-gate-brand .sa-brand-name { font-size: 20px; line-height: 24px; letter-spacing: 0.6px; }
/* De titel is de kop van de kaart, niet iets dat erboven zweeft — dezelfde plaats als in de
   popup, en links uitgelijnd zoals elk ander bloktitel in de app. */
.sa-app .sa-gate-card h1 { font-size: 18px; font-weight: 600; margin: 0 0 18px; text-align: left; }
.sa-gate-card { background: var(--surface); border: 1px solid var(--line); border-radius: 8px; padding: 28px 26px; }
/* The space between the fields is put on the labels, not on the inputs. A margin on the input
   loses: the generic rule for input carries five :not() clauses and sets margin 0, which
   outweighs anything scoped by class alone — the same trap that once hid a margin on the member
   fiche. The label has no such rule over it. */
.sa-app .sa-gate-card label {
  display: block; font-size: 12px; color: var(--ink-2); margin: 22px 0 6px;
}
.sa-app .sa-gate-card label:first-of-type { margin-top: 0; }
.sa-app .sa-gate-card .sa-btn { width: 100%; height: 40px; margin-top: 26px; }
.sa-gate-lang { display: flex; justify-content: center; margin-top: 28px; }

@media (max-width: 980px) {
  body.sa-app .sa-shell { grid-template-columns: 1fr; }
  body.sa-app .sa-side {
    position: fixed; inset: 0 auto 0 0; width: 260px; z-index: 30;
    transform: translateX(-100%); transition: transform .18s ease;
  }
  body.sa-app .sa-side.open { transform: none; box-shadow: 0 0 0 100vmax rgba(0,0,0,0.25); }
  body.sa-app .sa-side-toggle { display: block; }
  body.sa-app .sa-page, body.sa-app .sa-top, body.sa-app .sa-app-foot { padding-left: 18px; padding-right: 18px; }
  body.sa-app .sa-grid { grid-template-columns: repeat(2, 1fr); }
  body.sa-app .sa-row, body.sa-app .sa-grid-2 { grid-template-columns: 1fr; }
  body.sa-app .sa-fcell { grid-column: span 12; }
}
@media (max-width: 640px) {
  body.sa-app .sa-grid { grid-template-columns: 1fr; }
  body.sa-app .sa-event-card { flex-direction: column; }
  body.sa-app .sa-who-name { display: none; }
}

/* De 404 binnen het ledengedeelte. De bladzijde van de club, teruggebracht tot waaraan ze te
   herkennen is: "OOPS!" in Oswald over het korte bruine streepje, hun twee zinnen eronder. Wat
   niet meekomt is de rookfoto achter de tekst — het ledengedeelte draagt geen foto meer achter
   zijn tekst. Het woord staat hier op 180px in plaats van 430: het deelt een kolom met een
   zijbalk, en op het scherm van de club had het de hele breedte.

   Oswald wordt alleen door deze bladzijde opgehaald (headExtra in de schil); elders is er geen
   woord dat het draagt. Het lettertype moet de universele regel van de schil verslaan — die zet
   Nunito Sans op body.sa-app * en weegt (0,1,1) — vandaar de klasse van de bladzijde ervoor. */
.sa-app .sa-404-app { text-align: center; padding: 34px 0 30px; }
.sa-app .sa-404-app .sa-404-oops {
  font-family: "Oswald", sans-serif; font-weight: 500;
  font-size: min(180px, 22vw); line-height: 0.9; color: var(--ink-3);
}
/* Het streepje staat optisch in het midden tussen de twee: 44px onder de inkt van "OOPS!" en
   44px boven die van de rode regel. De marges zijn daarom niet gelijk. Boven staat 46 omdat de
   letters bij een regelhoogte van 0,9 twee pixels buiten hun eigen vak zakken; onder staat 37
   omdat de rode regel binnen haar regelhoogte nog zeven pixels boven haar inkt draagt. Gelijke
   marges zetten zou het streepje zichtbaar naar boven trekken — nagemeten met de inktgrenzen uit
   canvas measureText, niet geschat. */
.sa-app .sa-404-app .sa-404-rule {
  width: 83px; height: 0; margin: 46px auto 37px;
  border: 0; border-top: 1px solid rgb(149, 132, 110);
}
.sa-app .sa-404-app .sa-404-lead {
  font-weight: 700; font-size: 18px; line-height: 27px;
  color: rgb(195, 43, 20); margin: 0 0 10px;
}
.sa-app .sa-404-app .sa-404-hint {
  font-size: 15px; line-height: 24px; color: var(--ink-2); margin: 0 0 26px;
}

/* Een rij knoppen binnen een blok — vandaag de twee proefmails onder de tekst van een e-mail.
   De afstand tot de opmerking erboven is die van een veld tot zijn opmerking, andersom gelezen. */
.sa-app .sa-knoprij { display: flex; gap: 8px; margin: 13px 0 0; }

/* Een plaatshouder is geen waarde. Hij stond op het grijs dat de browser zelf kiest, en dat ligt
   zo dicht bij de inkt van een ingevulde naam dat "Naam genodigde" en "Adrien Seynaeve" op het
   inschrijvingenblad naast elkaar even ingevuld lezen. Dit is lichter dan elk grijs dat tekst
   draagt (2,9:1), en dat mag: het is geen inhoud, en elk veld hier draagt zijn eigen label of
   aria-label, dus er gaat niets verloren wanneer de plaatshouder niet gelezen wordt.
   De regel zet ook opacity op 1, omdat Firefox er van zichzelf 0,54 op zet. */
.sa-app ::placeholder { color: #9ba0a7; opacity: 1; }

/* Wat het inschrijvingenblad overhield toen het sa-attendee-table losliet. Die klasse is die van
   de deelnemerslijst die een lid ziet: ze haalt rand, achtergrond en zijkantlijnen weg omdat ze
   daar al ín een kaart staat. Hier staat het blad in niets, dus lag het kaal op de bladzijde.
   Vier dingen blijven nodig, en meer niet.

   Het blad gebruikt de volle kaart, en de kolom die meerekt is de **opmerking** en niet de naam.
   Dat is waar het één keer misging: met de naam als rekkende kolom stond er een naam links en zijn
   twee vinkjes duizend pixels verderop, en toen is de tabel op 780px gezet om ze bij elkaar te
   houden — waarna de opmerking een vakje van 220px bleef op een blad van elfhonderd. Andersom
   klopt allebei: de naam is zo breed als de langste naam, de vinkjes staan er pal naast, en wat
   overblijft is voor de opmerking. */
.sa-app .sa-inschrijfblad th, .sa-app .sa-inschrijfblad td { width: 1%; }
/* De naam blijft op één regel. Zolang zij de rekkende kolom was, sprak dat vanzelf; nu ze zo
   breed is als haar inhoud, brak "Guillaume de Breyne" over twee regels en werd elke rij hoger. */
.sa-app .sa-inschrijfblad th:first-child, .sa-app .sa-inschrijfblad td:first-child { white-space: nowrap; }
/* Lucht onderaan de kaart. Een gewone tabel krijgt die van de padding van haar laatste cel, maar
   een gastrij draagt er twee pixels — dat is wat een rij vol invulvakken compact houdt — en dan
   stond het laatste vak drie pixels boven de rand van de kaart, tegen de ronding aan. Tien erbij
   zet het op dezelfde afstand als de koptekst erboven (12px). */
.sa-app .sa-inschrijfblad { padding-bottom: 10px; }
.sa-app .sa-inschrijfblad .sa-cel-rek { width: 100%; }
.sa-app .sa-inschrijfblad th { vertical-align: top; }
.sa-app .sa-inschrijfblad td { vertical-align: middle; }

/* Een waarde op de leespagina van Mijn gegevens: geen vak eromheen, en niet hoger dan haar eigen
   regel. Ze heeft één dag de hoogte van een veld gedragen (36px, met 8 erboven) zodat een waarde
   niet zou verspringen bij het drukken op Bewerken — maar dat is zestien pixels lucht per regel op
   een bladzijde die niets anders doet dan tonen, en het bestuur vond het te los. De twee
   bladzijden verschillen nu in rijhoogte; de kolommen blijven wel op elkaar staan.

   Het streepje waar niets staat, staat in het lichtste grijs: het is geen waarde, het zegt dat
   er geen is. */
/* Het label draagt hier geen marge onder zich: bij een veld houdt die vier pixels het etiket van
   het vak, maar boven een regel tekst is dat lucht in een blok dat alleen leest. Wat overblijft is
   de eigen regelhoogte van het label, en dat is genoeg om de twee uit elkaar te houden. */
.sa-app label:has(+ .sa-waarde) { margin-bottom: 0; }
.sa-app .sa-waarde {
  margin: 0; padding: 0;
  font-size: 14px; line-height: 20px; color: var(--ink);
}
.sa-app .sa-waarde-leeg { color: var(--ink-3); }

/* Rechtsboven naast de titel staat vandaag één knop: "Bewerken" op Mijn gegevens. Die plaats is er
   voor wat bij de bladzijde hoort en niet bij een rij erin, en ze zet line-height op 0 voor het
   beeldmerk van ShotKam — het enige andere dat er staat. Een knop draagt tekst, dus die zet hem
   terug. */
.sa-app .sa-page-aside .sa-btn { line-height: normal; }

/* Negen ronden op één blad, zonder zijwaarts te schuiven. Het scoreblad van de Tir au Roi draagt
   veertien kolommen — de naam, negen ronden, score, netto, nieuwe handicap en de rang — en dat was
   81px meer dan de kaart breed is. De bladzijde die een lid ziet past wél: daar staat in elke cel
   een getal van twee tekens, hier een invulvak van 58px.

   Dus wordt er daar gehaald waar het te veel zat: het vak gaat naar 48 en de kolommen dragen 8px
   aan weerskanten in plaats van 10. De naamkolom houdt haar 16 — die regel staat op :first-child
   en weegt zwaarder. Samen scheelt dat ongeveer 140px, ruim genoeg voor de 81 die tekortkwam, en
   de overschot gaat vanzelf naar de kolommen omdat de tabel 100% breed is.

   Het geldt alleen voor .sa-scoreblad, dus alleen voor het blad van het bestuur: de tabellen die
   een lid ziet passen al en blijven zoals ze zijn. */
.sa-app .sa-scoreblad th, .sa-app .sa-scoreblad td { padding-left: 8px; padding-right: 8px; }
.sa-app .sa-scoreblad input.sa-score:not([type="checkbox"]):not([type="radio"]):not([type="file"]):not([type="submit"]):not([type="button"]) {
  width: 48px;
}

/* De ontvangers van een bericht: elk lid met zijn adres, aan te vinken. Kolommen zo breed als het
   scherm toelaat, want zevenenzestig namen onder elkaar is een lijst waar niemand doorheen komt. */
.sa-app .sa-ontvangers {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
  gap: 6px 16px;
}
.sa-app .sa-ontvanger {
  display: grid; grid-template-columns: auto 1fr; align-items: center;
  column-gap: 8px; font-size: 13px; cursor: pointer;
}
.sa-app .sa-ontvanger .sa-muted { grid-column: 2; font-size: 12px; }

/* De bewaarde tekst van een verzonden mail, op het logboekscherm. Ze staat in de database zoals
   een bestuurslid ze typte, dus met haar eigen regelovergangen; die horen op het scherm te
   blijven staan. */
.sa-app .sa-mailtekst { white-space: pre-wrap; }
