/* Klubliga-appen. Bygger oven på style.css fra prototypen og genbruger dens variabler. */

:root {
  --marine: #10283d;
  --marine-lys: #17344a;
  --marine-kant: #315066;
  --guld: #d6a84b;
  --guld-dyb: #b4832e;
  --papir: #f6f4ef;
  --tekst-dæmpet: #5b6b78;
  --grøn: #3f7d4f;
  --rød: #a63d3d;
  /* Bag login er indholdsfeltet mørkt som prototypens hero, så teksten er lys. */
  --tekst-lys: #d2dce2;
  --tekst-lys-dæmpet: #8fa3b1;
  --grøn-lys: #6ab97e;
  --rød-lys: #e08a8a;

  /* --- Temalaget ---
     Alt inde i .app-main tegnes gennem navnene herunder, aldrig direkte på
     paletten ovenfor. Så kan hele midterstykket skifte farvestærke ved at
     omdefinere de samme navne i blokken "Lyst tema" længere nede.
     Værdierne her er det mørke tema, som også er standard. */
  --flade: var(--marine);
  --flade-haevet: var(--marine-lys);
  --flade-hover: #1d3c53;
  --flade-valgt: #20415a;
  --flade-tabelhoved: #132d42;
  --flade-felt: var(--marine);
  --flade-maerkat: var(--marine);
  --flade-svag: rgba(255, 255, 255, .1);
  --kant: var(--marine-kant);
  --kant-svag: rgba(255, 255, 255, .09);
  --kant-knap: #6c8a9e;
  --tekst: var(--tekst-lys);
  --tekst-svag: var(--tekst-lys-dæmpet);
  --tekst-staerk: #fff;
  --tekst-passiv: #7f939f;
  --placeholder: #7d93a3;
  --accent: var(--guld);
  --ok: var(--grøn-lys);
  --fejl: var(--rød-lys);
  --prik-passiv: #55707f;
  --markering: rgba(214, 168, 75, .1);
  --markering-fejl: rgba(166, 61, 61, .13);

  /* "Nyt"/"Bekræft"-maerkatet. Ren signalgul i BEGGE temaer, ligesom
     guldknappen: mærkatet skal kunne findes i en liste af kampkort uden at
     læse dem, og et mærkat, der skifter farve fra telefon til telefon, er
     ikke det samme mærkat. Kun kanten skifter — se det lyse tema. */
  --nyt-flade: #ffd400;
  --nyt-tekst: var(--marine);
  --nyt-kant: var(--nyt-flade);
}

/* --- Lyst tema ---
   Sat på <html> af det lille script i <head>, så farverne står rigtigt før
   første optegning. Kun midterstykket skifter: header og fod er papirfarvede
   i forvejen, og det offentlige lag (body uden .app) røres ikke.
   Guldet bliver dybere, fordi #d6a84b kun giver 2,2:1 mod hvid. */
html[data-tema="lys"] body.app {
  --flade: #fff;
  --flade-haevet: var(--papir);
  --flade-hover: #ece9e1;
  --flade-valgt: #f5e8cd;
  --flade-tabelhoved: #ebe8df;
  --flade-felt: #fff;
  --flade-maerkat: #fff;
  --flade-svag: rgba(16, 40, 61, .07);
  --kant: #ccd2d7;
  --kant-svag: rgba(16, 40, 61, .12);
  --kant-knap: #8d9aa4;
  --tekst: var(--marine);
  --tekst-svag: var(--tekst-dæmpet);
  --tekst-staerk: var(--marine);
  --tekst-passiv: #6a7883;
  --placeholder: #7a8892;
  --accent: #8a6420;
  --ok: var(--grøn);
  --fejl: var(--rød);
  --prik-passiv: #98a4ac;
  --markering: rgba(214, 168, 75, .3);
  --markering-fejl: rgba(166, 61, 61, .12);
  /* Fladen er den samme gule, men gul mod hvid er kun 1,4:1: uden en mørkere
     kant har mærkatet ingen form på et lyst kort. Teksten er uændret 10,5:1. */
  --nyt-kant: #8a6420;
  color-scheme: light;
}

/* Samme opbygning som det offentlige lag: lys top, mørkt midterstykke, lys fod. */
body.app {
  background: var(--flade);
  color: var(--tekst);
  color-scheme: dark;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}

/* --- Header --- */
.app-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  padding: 0 clamp(18px, 4vw, 48px);
  height: 84px;
  background: var(--papir);
  color: var(--marine);
  border-bottom: 1px solid rgba(16, 40, 61, .16);
}
.app-header .brand-logo { width: 88px; height: 52px; }
.app-nav { display: flex; align-items: center; gap: clamp(14px, 3vw, 30px); }
.app-nav a, .link-button {
  font-size: 13px; font-weight: 600; text-decoration: none; color: inherit;
  background: none; border: 0; padding: 0; cursor: pointer; font-family: inherit;
}
.app-nav a:hover, .link-button:hover { text-decoration: underline; text-underline-offset: 6px; }
.inline-form { display: inline; margin: 0; }

/* --- Midterstykket: mørkt som forsidens hero --- */
.app-main {
  flex: 1;
  background: var(--flade);
  color: var(--tekst);
  padding: clamp(28px, 5vw, 56px) clamp(18px, 4vw, 48px) 72px;
}

/* --- Fod --- */
.app-footer {
  background: var(--papir); color: var(--tekst-dæmpet);
  border-top: 1px solid rgba(16, 40, 61, .16);
  padding: 28px clamp(18px, 4vw, 48px);
  display: flex; align-items: center; gap: 24px; font-size: 11px; flex-wrap: wrap;
}
.app-footer .footer-brand { color: var(--marine); margin-right: auto; font: 800 20px/1 var(--condensed); letter-spacing: .04em; }
.app-footer .footer-brand span { color: var(--guld-dyb); }
.app-footer p { margin: 0; }

/* --- Sideoverskrifter --- */
.side-hoved { max-width: 900px; margin-bottom: 34px; }
/* Størrelsen SKAL stå her, ikke kun farven. `.eyebrow` i style.css sætter 12px
   med én klasse, og både `.side-hoved p` og `.kort > p` herunder vejer en klasse
   plus et element — så eyebrow-linjen voksede til 16px i sidehovedet og 15px
   inde i et kort, mens den udlogget forside beholdt de 12px. Tre størrelser af
   det samme element. Værst på kampsiden, hvor brødkrummen dermed stod fed guld
   i versaler over en titel på 24px og vejede tungere end den. Fundet
   5. september 2026 — usynligt på Min side, fordi linjen dér kun vises for
   admin. */
.side-hoved .eyebrow, .kort .eyebrow { font-size: 12px; color: var(--accent); }
.side-hoved h1 {
  font: 800 clamp(40px, 6vw, 68px)/.92 var(--condensed);
  text-transform: uppercase; letter-spacing: -.02em; margin: 16px 0 14px; color: var(--accent);
}
.side-hoved p { color: var(--tekst); font-size: 16px; max-width: 62ch; margin: 0; }

/* --- Beskeder ---
   Svaret på en indtastning skal ikke kunne overses. Første udgave var en
   dæmpet linje med en farvet kant, og den blev læst som brødtekst: en spiller,
   der havde tastet et ugyldigt sæt, så ikke fejlen og troede, resultatet var
   gemt (rapporteret 26. august 2026).

   Derfor en fyldt banner-flade med mørk tekst og en etiket i versaler foran.
   **Fladen er lys i begge temaer med vilje** — den er en afbrydelse, ikke en
   del af siden, og den skal se ens ud, uanset hvad man har valgt i headeren.
   Det er også derfor, de her regler bruger paletten (--guld, --marine) og ikke
   temanavnene: undtagelsen er den samme som for header, fod og guldknappen. */
.beskeder { max-width: 760px; margin: 0 0 30px; display: grid; gap: 12px; }
.besked {
  margin: 0; padding: 16px 20px; font-size: 15px; line-height: 1.5; font-weight: 600;
  background: var(--papir); color: var(--marine);
  border: 1px solid rgba(16, 40, 61, .18); border-left: 6px solid var(--marine);
}
/* Etiketten foran teksten. ::before frem for markup, så flashbeskeder stadig
   er én <p> og layoutfilen ikke skal kende til de enkelte typer. */
.besked::before {
  content: attr(data-etiket);
  display: block; margin-bottom: 4px;
  font: 800 11px/1 var(--sans); text-transform: uppercase; letter-spacing: .14em;
  opacity: .75;
}
/* Gul med sort skrift: det er fejlen, man skal standse op ved. Marineblå på
   guld måler 6,9:1 — samme par som guldknappen. */
.besked-fejl { background: var(--guld); border-left-color: var(--marine); border-color: var(--guld-dyb); }
.besked-ok { background: #d5e8dc; border-left-color: var(--grøn); border-color: #a9cbb8; }
.besked-info, .besked-besked { background: var(--papir); border-left-color: var(--guld-dyb); }

/* Flashbeskeder på det offentlige layout, hvor der ikke er nogen sideindpakning.
   Samme banner — kun indpakningen er en anden. */
.beskeder-offentlig { max-width: none; margin: 0; padding: 22px clamp(24px, 5vw, 76px) 0; }
.beskeder-offentlig .besked { max-width: 760px; }

/* --- Kort og paneler --- */
.kort {
  background: var(--flade-haevet); border: 1px solid var(--kant);
  padding: clamp(22px, 3vw, 34px); max-width: 560px;
}
.kort h2 { font: 700 28px var(--condensed); text-transform: uppercase; margin: 0 0 8px; color: var(--accent); }
/* Et kort INDE i en sektion skal have en h3, ikke en h2: 28px guld stod kun to
   pixel under `.sektion > h2` og vejede lige så tungt som overskriften over
   kortet ("Erik Vang / Frank Bruun" mod "DIN TILMELDING"). Forholdet er det
   samme som `.kamp-kort h3` på Min pulje — mindre og i tekstfarven, så kortet
   læses som ét indhold og ikke som endnu en overskrift. `.kort h2` bliver
   stående til de kort, der IKKE ligger i en sektion, fx "Der er ingen rangliste
   endnu". */
.kort h3 { font: 700 22px var(--condensed); text-transform: uppercase; margin: 0 0 8px; color: var(--tekst-staerk); }
.kort > p { color: var(--tekst-svag); font-size: 15px; }
/* `.kort > p` vinder over `.hjaelpetekst`, så hjælpeteksten inde i et kort stod
   i 15px — samme størrelse som brødteksten ved siden af — og lignede ikke
   hjælpetekst. 12px er den, den har alle andre steder. */
.kort > p.hjaelpetekst { font-size: 12px; }
/* Handlingen nederst i et kort skal have luft til teksten over den. Stod før som
   style="margin-top:20px" i viewet og var derfor død under CSP'en. */
.kort > .formular, .kort > .knap-raekke { margin-top: 20px; }
/* Kortbredden på rækkesiden. Samme 620px som .aftale-kort og .forslag-kort. */
.kort-bred { max-width: 620px; }

.panel-net { display: grid; gap: 18px; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); max-width: 1100px; }
.panel {
  background: var(--flade-haevet); border: 1px solid var(--kant); border-top: 3px solid var(--accent);
  padding: 24px; display: flex; flex-direction: column; gap: 8px;
}
.panel h3 { font: 700 24px var(--condensed); text-transform: uppercase; margin: 0; color: var(--accent); }
.panel p { margin: 0; color: var(--tekst-svag); font-size: 14px; }
.panel .panel-link { margin-top: auto; padding-top: 14px; font-size: 12px; font-weight: 800; letter-spacing: .08em; text-transform: uppercase; color: var(--accent); }
.panel.kommer { border-top-color: var(--kant); opacity: .72; }
.mærkat {
  display: inline-block; font-size: 10px; font-weight: 800; letter-spacing: .12em; text-transform: uppercase;
  padding: 4px 8px; background: var(--flade-svag); color: var(--tekst-svag); align-self: flex-start;
}

/* --- Profilvælger: én e-mail kan dække flere spillere --- */
.spillervalg { display: grid; gap: 1px; background: var(--kant); border: 1px solid var(--kant); }
/* Højere specificitet end ".formular label", som ellers gør etiketten lodret og med versaler. */
.formular label.spiller, label.spiller {
  display: grid; grid-template-columns: auto 1fr auto; align-items: center; gap: 14px;
  background: var(--flade-haevet); padding: 16px 18px; margin: 0; cursor: pointer;
  text-transform: none; letter-spacing: 0; font-weight: 500; font-size: 15px; color: var(--tekst);
}
label.spiller:hover { background: var(--flade-hover); }
label.spiller input { width: 18px; height: 18px; accent-color: var(--accent); margin: 0; }
label.spiller.spiller-valgt { background: var(--flade-valgt); box-shadow: inset 3px 0 0 var(--accent); }
.spiller-navn { font: 700 20px/1.2 var(--condensed); text-transform: uppercase; letter-spacing: .01em; color: var(--accent); }
.spiller-detalje { font-size: 13px; color: var(--tekst-svag); font-variant-numeric: tabular-nums; }

/* Skifteren i headeren */
.app-header .spiller-skift {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 5px 10px; border: 1px solid rgba(16, 40, 61, .24); font-size: 12px;
}
.app-header .spiller-skift:hover { background: var(--marine); color: #fff; border-color: var(--marine); text-decoration: none; }
.app-header .spiller-skift span { font-weight: 800; }

@media (max-width: 620px) {
  label.spiller { grid-template-columns: auto 1fr; }
  .spiller-detalje { grid-column: 2; }
}

/* --- Tal --- */
.tal-raekke { display: flex; width: fit-content; max-width: 100%; flex-wrap: wrap; gap: 1px; background: var(--kant); border: 1px solid var(--kant); margin-bottom: 30px; }
/* flex-grow: 1 er ikke pynt. Rammen tegnes af beholderens baggrund, der lyser
   igennem 1px-mellemrummene — så en linje, der ikke er fyldt ud, ville stå som
   en lys flade ved siden af det sidste tal. Cellerne fylder derfor deres linje
   ud. Uden ombrydning er beholderen fit-content, og der er intet at fordele. */
.tal { background: var(--flade-haevet); padding: 18px 26px; min-width: 128px; flex-grow: 1; }
.tal strong { display: block; font: 700 34px/1 var(--condensed); color: var(--accent); }
.tal span { font-size: 11px; text-transform: uppercase; letter-spacing: .1em; color: var(--tekst-svag); }

/* --- Formularer --- */
.formular { display: grid; gap: 20px; }
/* .app-main har ingen maksbredde, så en formular uden den her spænder over hele
   skærmen på en desktop — makkerlisten på tilmeldingssiden stod 1370px bred. */
.formular-smal { max-width: 620px; }
.formular label { display: flex; flex-direction: column; gap: 8px; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .08em; }
.formular input[type=text], .formular input[type=email], .formular input[type=tel], .formular input[type=search],
.formular input[type=datetime-local], .formular input[type=date], .formular select {
  width: 100%; border: 0; border-bottom: 1px solid var(--kant); background: transparent;
  padding: 12px 0; border-radius: 0; font: 16px var(--sans); color: var(--tekst-staerk); outline: none;
}
.formular ::placeholder { color: var(--placeholder); }
.formular select option { background: var(--flade-haevet); color: var(--tekst); }
.formular input:focus, .formular select:focus { border-color: var(--accent); }
.formular input[type=file] { font: 14px var(--sans); padding: 12px 0; }
.felt-fejl { color: var(--fejl); font-size: 12px; font-weight: 600; text-transform: none; letter-spacing: 0; }
.hjaelpetekst { font-size: 12px; color: var(--tekst-svag); text-transform: none; letter-spacing: 0; font-weight: 400; }
.knap-raekke { display: flex; flex-wrap: wrap; gap: 12px; align-items: center; }
/* Kun inde i app-layoutet. Uden for det gælder prototypens knapper, hvor bl.a.
   .button-ghost og .button-light bygger på rammen fra style.css. */
body.app .button { border: 0; }
body.app .button-primary { background: var(--guld); color: var(--marine); }
body.app .button-primary:hover { background: #e2bd73; color: var(--marine); }
body.app .button-sekundaer { background: transparent; color: var(--tekst-staerk); border: 1px solid var(--kant-knap); }
body.app .button-sekundaer:hover { background: var(--flade-svag); border-color: var(--tekst-staerk); }
.button-lille { min-height: 44px; gap: 10px; font-size: 11px; }
.afbryd-link { font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: .08em; }
/* Tekstknapper og indlejrede links i det mørke midterstykke. */
.app-main .link-button { color: var(--tekst); }
.app-main a:not(.button):not(.panel-link):not(.kamp-faerdig) { color: var(--accent); }

/* --- Tabeller --- */
.tabel-omslag { overflow-x: auto; border: 1px solid var(--kant); background: var(--flade-haevet); }
table.data { width: 100%; border-collapse: collapse; font-size: 14px; min-width: 620px; }
table.data th, table.data td { text-align: left; padding: 12px 16px; border-bottom: 1px solid var(--kant-svag); }
table.data th {
  font: 700 11px var(--sans); text-transform: uppercase; letter-spacing: .1em;
  color: var(--tekst-svag); background: var(--flade-tabelhoved); position: sticky; top: 0;
}
table.data tr:last-child td { border-bottom: 0; }
table.data td.num { font-variant-numeric: tabular-nums; }
/* Talkolonner, der ikke skal have plads efter indholdet — fx "Seed", der ellers
   tog 240px af bredden, fordi style="width:70px" i viewet var dødt. */
table.data th.kol-smal { width: 70px; }
/* Et mærkat efter en tekst i en celle ("Dig") klistrede op ad navnet. */
table.data td .mærkat { margin-left: 10px; }
tr.inaktiv td { color: var(--tekst-passiv); }
.status-prik { display: inline-block; width: 8px; height: 8px; border-radius: 50%; margin-right: 8px; }
.status-prik.aktiv { background: var(--ok); }
.status-prik.passiv { background: var(--prik-passiv); }

/* --- Søgefelt --- */
.soegeform { display: flex; flex-wrap: wrap; gap: 16px 26px; align-items: flex-end; margin-bottom: 22px; }
.soegeform > label:not(.afkryds) { flex: 0 1 340px; }
.soegeform .knap-raekke { flex: 0 0 auto; margin-bottom: 4px; }
/* Statusvælgeren skal ikke fylde lige så meget som søgefeltet. */
.soegeform > label.smal { flex: 0 1 200px; }
/* … men "Op- og nedrykning fra Runde 1" bliver klippet ved 200px. */
.soegeform > label.smal.bredere { flex: 0 1 320px; }
/* Højere specificitet end ".formular label", som ellers gør etiketten lodret og med versaler. */
.formular label.afkryds, label.afkryds {
  flex: 0 0 auto; flex-direction: row; align-items: center; gap: 10px;
  text-transform: none; letter-spacing: 0; font-weight: 500; font-size: 14px; margin-bottom: 6px;
}
label.afkryds input { width: 18px; height: 18px; accent-color: var(--accent); flex: none; }

/* --- Detaljer / dokumentation --- */
details.info { max-width: 760px; margin: 18px 0 0; font-size: 14px; }
details.info summary { cursor: pointer; font-weight: 700; font-size: 12px; text-transform: uppercase; letter-spacing: .08em; color: var(--accent); }
details.info div { padding: 14px 0 0; color: var(--tekst-svag); }
details.info code { background: var(--flade-svag); padding: 2px 6px; font-size: 13px; }

/* --- Sektionsopdeling --- */
/* Afstanden nedad skal stå her og ikke som en style i den enkelte side: står to
   sektioner i træk, falder de to margener sammen til de 52px, og står der noget
   andet under — et kortnet, en advarsel — får det sin egen luft i stedet for at
   klistre op ad sektionen. */
.sektion { margin-top: 52px; margin-bottom: 34px; }
.sektion > h2 { font: 700 30px var(--condensed); text-transform: uppercase; margin: 0 0 6px; color: var(--accent); }
.sektion > p.sektion-intro { color: var(--tekst-svag); font-size: 15px; margin: 0 0 20px; max-width: 62ch; }

/* --- Advarselsboks --- */
.advarsel { border-left: 3px solid var(--accent); background: var(--flade-haevet); padding: 18px 22px; max-width: 760px; font-size: 14px; color: var(--tekst); }
.advarsel strong { display: block; text-transform: uppercase; font-size: 11px; letter-spacing: .1em; margin-bottom: 6px; color: var(--accent); }

/* --- Centreret login --- */
.midterstil { display: grid; place-items: start center; padding-top: clamp(10px, 4vw, 40px); }
.midterstil .kort { width: 100%; }
/* Login-, kode- og velkomstsiderne har intet .side-hoved: kortets h2 ER sidens
   titel, og 28px fra .kort h2 er for lidt til det. Stod som
   style="font-size:38px;margin-top:14px" i alle fem views og var dødt under
   CSP'en. */
.midterstil .kort > h2 { font-size: 38px; margin-top: 14px; }

/* --- Rækker (modul 02) --- */
.status-maerkat {
  display: inline-block; padding: 5px 11px; margin-right: 12px; vertical-align: 2px;
  font: 800 10px/1 var(--sans); text-transform: uppercase; letter-spacing: .12em;
  border: 1px solid var(--kant); color: var(--tekst-svag); background: var(--flade-maerkat);
}
.status-maerkat.status-tilmelding { border-color: var(--accent); color: var(--accent); }
.status-maerkat.status-i-gang { border-color: var(--ok); color: var(--ok); }
.status-maerkat.status-afsluttet { border-color: var(--prik-passiv); color: var(--tekst-svag); }

/* auto-fill frem for auto-fit: én enkelt række skal ikke strække sig over hele bredden. */
.raekke-liste { display: grid; gap: 18px; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); max-width: 1100px; }
.raekke-kort {
  display: flex; flex-direction: column; gap: 8px; padding: 22px 24px 20px;
  background: var(--flade-haevet); border: 1px solid var(--kant); border-top: 3px solid var(--accent);
  text-decoration: none;
}
.raekke-kort:hover { background: var(--flade-hover); }
.raekke-kort h3 { font: 700 26px var(--condensed); text-transform: uppercase; margin: 0; color: var(--accent); }
/* Slår .app-main-reglen fra, så guldfarven ikke smitter af på hele kortet. */
.app-main a.raekke-kort { color: var(--tekst); }
.raekke-kort .status-maerkat { align-self: flex-start; margin: 0 0 2px; }
.raekke-meta { margin: 0; font-size: 13px; color: var(--tekst-svag); }
.raekke-tal { margin: 0; font-size: 14px; }
.raekke-tal strong { font: 700 22px/1 var(--condensed); color: var(--tekst-staerk); margin-right: 4px; }
.raekke-min { margin: 0; font-size: 13px; color: var(--accent); font-weight: 600; }
.raekke-kort-min { border-left: 3px solid var(--accent); }
.raekke-link { margin-top: auto; padding-top: 14px; font: 800 11px var(--sans); letter-spacing: .1em; text-transform: uppercase; color: var(--accent); }
.raekke-beskrivelse {
  max-width: 760px; margin: 0 0 30px; padding: 16px 20px; font-size: 15px;
  background: var(--flade-haevet); border-left: 3px solid var(--kant); color: var(--tekst);
}

/* --- Seedning --- */
.seed-felt {
  width: 62px; padding: 8px 10px; border: 1px solid var(--kant); background: var(--flade-felt);
  color: var(--tekst-staerk); font: 600 15px var(--sans); border-radius: 0; text-align: center; font-variant-numeric: tabular-nums;
}
.seed-felt:focus { border-color: var(--accent); outline: none; }
.flyt-celle { white-space: nowrap; }
.flyt-knap {
  width: 30px; height: 30px; padding: 0; margin-right: 2px; cursor: pointer;
  border: 1px solid var(--kant); background: var(--flade-felt); color: var(--tekst); font-size: 11px;
}
.flyt-knap:hover { border-color: var(--accent); color: var(--accent); }
.par-navn { display: block; font-size: 15px; color: var(--tekst-staerk); }
.par-kontakt { display: block; margin-top: 3px; font-size: 12px; color: var(--tekst-svag); }
.par-note { display: block; margin-top: 5px; font-size: 12px; color: var(--accent); }

/* --- Udskiftning af én spiller i et par --- */
.udskift-liste { display: grid; gap: 1px; background: var(--kant); border: 1px solid var(--kant); max-width: 760px; }
details.udskift { background: var(--flade-haevet); }
details.udskift > summary {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 6px 14px;
  padding: 16px 20px; cursor: pointer; list-style: none;
}
details.udskift > summary::-webkit-details-marker { display: none; }
details.udskift > summary::after {
  content: "Skift ud ▾"; margin-left: auto;
  font: 800 11px var(--sans); letter-spacing: .08em; text-transform: uppercase; color: var(--accent);
}
details.udskift[open] > summary::after { content: "Luk ▴"; }
details.udskift > summary:hover { background: var(--flade-hover); }
.udskift-par { font: 700 19px/1.2 var(--condensed); text-transform: uppercase; color: var(--accent); }
.udskift-seed { font-size: 12px; color: var(--tekst-svag); font-variant-numeric: tabular-nums; }
.udskift-form { padding: 4px 20px 22px; }
.udskift-hvem { border: 0; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 8px 26px; }
.udskift-hvem legend {
  padding: 0; margin-bottom: 8px;
  font: 700 11px var(--sans); letter-spacing: .08em; text-transform: uppercase; color: var(--tekst);
}
.handling-celle { text-align: right; white-space: nowrap; }
.app-main .link-button-fare { color: var(--fejl); }
.skjult-form { display: none; }
tr.min-raekke td { background: var(--markering); box-shadow: inset 3px 0 0 var(--accent); }

/* --- Forhåndsvisning af parimport --- */
table.data.import-tabel { min-width: 860px; }
.import-tabel td { vertical-align: top; }
.import-soegt { display: block; font-size: 14px; color: var(--tekst-staerk); margin-bottom: 5px; }
.import-match { display: block; font-size: 13px; color: var(--tekst-svag); }
.import-vaelger {
  width: 100%; min-width: 240px; padding: 7px 10px; border: 1px solid var(--kant);
  background: var(--flade-felt); color: var(--tekst-staerk); font: 14px var(--sans); border-radius: 0;
}
.import-vaelger:focus { border-color: var(--accent); outline: none; }
.import-vaelger-tom { border-color: var(--fejl); }
.import-note { display: block; margin-top: 4px; font-size: 11.5px; color: var(--tekst-svag); }
.import-note-fejl { color: var(--fejl); }
tr.import-hul td { background: var(--markering-fejl); }
.import-spring { justify-content: flex-end; margin: 0; }

/* Flerlinjede felter og lister — resten af .formular-reglerne dækker kun input og select. */
.formular textarea {
  width: 100%; border: 1px solid var(--kant); background: transparent; padding: 12px 14px;
  border-radius: 0; font: 15px/1.5 var(--sans); color: var(--tekst-staerk); outline: none; resize: vertical;
}
.formular textarea:focus { border-color: var(--accent); }
.formular select[size] {
  border: 1px solid var(--kant); background: var(--flade-felt); padding: 4px;
  font-size: 15px; height: auto;
}
.formular select[size] option { padding: 8px 10px; }
.vaelger-filter { margin-bottom: -4px; }
.parvalg-form { grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); max-width: 900px; }
.parvalg-form .knap-raekke { grid-column: 1 / -1; }

@media (max-width: 620px) {
  .app-header { height: 72px; }
  .app-header .brand-name { font-size: 18px; }
  .app-header .brand-logo { width: 72px; height: 44px; }
  /* Ordmærket vige for menuen på en telefon: med temaknappen er der fire ting i
     højre side, og "Min side · Rækker · Log ud · ☾" kan ikke være der ved siden
     af både klublogo og KLUBLIGA.DK på 390px. Logoet linker stadig til forsiden. */
  .app-header .brand-name, .app-header .brand-divider { display: none; }
  .side-hoved h1 { font-size: 38px; }
  .knap-raekke .button { width: 100%; justify-content: center; }
  /* Statusknapperne sidder i hver sin .inline-form; uden det her bliver den
     fuldbredde knap klemt inde i en inline forælder. */
  .knap-raekke .inline-form { display: block; width: 100%; }
  .status-maerkat { margin-bottom: 8px; }
  .side-hoved p .status-maerkat { display: block; width: fit-content; }
}

/* --- Modul 03: puljer og kampe --- */

/* Spillerens egen række i en puljetabel. Guldkanten er den samme markering
   som .raekke-kort-min bruger på rækkelisten. */
tr.mit-par td { background: var(--flade-valgt); box-shadow: inset 3px 0 0 var(--accent); }
.dæmpet { color: var(--tekst-svag); font-weight: 400; }

/* Puljen man selv er i, når alle rækkens puljer vises under hinanden. */
.sektion-min > h2 { color: var(--accent); }

/* Kampkortene på "Min pulje". Samme grundform som .panel, men beregnet på en
   liste af mange korte kort frem for et net af få store. */
.kamp-liste { display: grid; gap: 14px; grid-template-columns: repeat(auto-fit, minmax(270px, 1fr)); max-width: 1100px; }
.kamp-kort {
  background: var(--flade-haevet); border: 1px solid var(--kant); border-left: 3px solid var(--kant);
  padding: 18px 20px; display: flex; flex-direction: column; gap: 6px;
}
.kamp-kort-ansvar { border-left-color: var(--accent); }
.kamp-kort h3 { font: 700 20px var(--condensed); text-transform: uppercase; margin: 0; color: var(--tekst); }
.kamp-kort .status-maerkat { align-self: flex-start; margin: 0 0 2px; }
.kamp-ansvar { margin: 0; font-size: 13px; color: var(--tekst-svag); }
.kamp-ansvar-mit { color: var(--accent); font-weight: 700; }
.kamp-meta { margin: 0; font-size: 13px; color: var(--tekst-svag); }

/* Flytteformularen i puljetabellen: vælger og knap på samme linje, og under
   hinanden på en telefon, hvor kolonnen ellers bliver for smal. */
.flyt-form { display: flex; gap: 8px; align-items: center; }
.flyt-form select { min-width: 120px; }

@media (max-width: 620px) {
  .flyt-form { flex-direction: column; align-items: stretch; }
  .flyt-form .button { width: 100%; justify-content: center; }
}

/* --- Temaknap i headeren ---
   Sol i det mørke tema (tryk = skift til lyst), måne i det lyse. Knappen sidder
   i headeren, som er papirfarvet i begge temaer, så den farves som resten af
   navigationen og ikke gennem temalaget.

   Knappen er altid synlig. Der er ingen regel, der kan skjule den. Det har
   kostet to fejlsøgninger at nå hertil: først var den skjult som standard og
   vist af `html.js`, så blev den vist som standard og skjult af `html:not(.js)`
   — og begge dele forsvandt i Safari, fordi de begge hang på, at scriptet i
   <head> nåede at sætte klassen. Uden JavaScript er knappen nu død, men synlig,
   og det er den rigtige vej rundt: appen kræver alligevel JavaScript til
   filupload, seedning og filtre. **Skjul aldrig et betjeningselement med en
   regel, der skal slås fra af noget andet for at virke.**

   `appearance: none` er ikke pynt: Safari tegner ellers sin egen knapflade
   oven i, og `-webkit-` skal med, fordi ældre iOS-Safari kun kender den. */
.app-header-hoejre { display: flex; align-items: center; gap: clamp(14px, 3vw, 30px); }
.tema-knap {
  display: inline-flex; flex: none; width: 36px; height: 36px; padding: 0; cursor: pointer;
  align-items: center; justify-content: center; color: inherit;
  background: none; border: 1px solid rgba(16, 40, 61, .24); border-radius: 0;
  -webkit-appearance: none; appearance: none;
}
.tema-knap:hover { background: var(--marine); color: #fff; border-color: var(--marine); }
/* Både attribut og CSS på ikonerne: Safari giver en inline-SVG uden width/height
   højden 0, når den er flex-barn, og så står knappen tom. */
.tema-knap svg { width: 19px; height: 19px; flex: none; display: block; }
.tema-knap .ikon-maane, html[data-tema="lys"] .tema-knap .ikon-sol { display: none; }
html[data-tema="lys"] .tema-knap .ikon-maane { display: block; }

/* Headeren bryder til to linjer på en telefon (tilføjet 28. august 2026).
   Målt: med ranglisten i menuen kræver spillerens header 467px af de 390px, en
   iPhone har — uden den passede den på 390 på en prik. Ordmærket er allerede
   skjult under 620px, og der er ikke mere at spare væk uden at fjerne et
   menupunkt. Derfor står klublogoet alene på første linje, og menuen med
   sol/måne-knappen på anden: så er hvert punkt stadig synligt og til at ramme,
   i stedet for at ligge uden for skærmkanten.

   Det er IKKE hamburgermenuen. Den hører stadig til, når adminsiderne skal
   bruges på en telefon — adminens header kræver 742px og fylder to fulde linjer
   her. For spilleren, som er den, der bruger appen på mobil, er to linjer nok. */
@media (max-width: 620px) {
  .app-header {
    flex-wrap: wrap;
    height: auto;
    min-height: 84px;
    padding-top: 12px;
    padding-bottom: 12px;
    gap: 10px 20px;
  }
  .app-header-hoejre {
    gap: 14px;
    flex: 1 1 100%;
    flex-wrap: wrap;
    justify-content: space-between;
  }
  .app-nav { flex-wrap: wrap; gap: 10px 16px; }
  .tema-knap { width: 34px; height: 34px; }
  .tema-knap svg { width: 17px; height: 17px; }
}

/* --- Modul 04: kampplanlægning og chat --- */

/* Overskriften på kampsiden: "Anne / Bo mod Carl / Dan". Ordet "mod" står som
   sit eget element, så det kan brydes til sin egen linje på en telefon uden at
   navnene bliver delt midt over.

   Titlen er mindre end appens andre sidetitler, og det er ikke en smagssag:
   .side-hoved h1 er 40-68px, fordi den ellers står med "Pulje 1" eller
   "Hej Morten". Her står fire fulde navne i den, og i den størrelse fylder de
   tre linjer og skubber selve aftalen ned under skærmkanten på en telefon.

   Den var 30px/800 — samme størrelse som sektionsoverskrifterne ("TID OG
   STED"), men en vægt tungere, og med fire navne over tre linjer stod den
   som sidens tungeste element (Finn, 4. september 2026). Nu 24px/700:
   VÆGTEN er den samme som .sektion > h2, så navnene har samme karakter som
   overskrifterne omkring dem, og størrelsen er sat under dem, fordi navnene
   fortæller hvilken kamp man står i — de er ikke sidens ærinde, det er
   aftalen. Ingen clamp: .sektion > h2 har heller ingen, og de to skal følges
   ad. */
/* Vælgeren skal indeholde både .side-hoved og h1: ".side-hoved h1" vejer en
   klasse plus et element, og en klasse alene ville tabe til den — også til
   telefonreglen "font-size: 38px" længere oppe. Og font-weight SKAL stå her:
   .side-hoved h1 sætter 800 gennem font-shorthanden, så en h1 uden sin egen
   vægt arver den tunge. */
.side-hoved h1.kamp-titel {
  font-size: 24px;
  font-weight: 700;
  line-height: 1.15;
  letter-spacing: 0;
}
.kamp-mod {
  display: inline-block; margin: 0 14px; font-size: .55em;
  color: var(--tekst-svag); letter-spacing: .08em;
}

/* Aftalen og forslaget står som to kort under hinanden, fordi de er to
   forskellige ting: aftalen er, hvad der gælder, forslaget er, hvad nogen har
   spurgt om. Blandes de sammen, kan et par ikke se, hvad der er besluttet. */
.aftale-kort, .forslag-kort {
  background: var(--flade-haevet); border: 1px solid var(--kant); border-left: 3px solid var(--kant);
  padding: 20px 24px; max-width: 620px; margin-bottom: 18px;
}
.aftale-kort-aftalt { border-left-color: var(--ok); }
/* Guld kun når det er vores tur: kortet skal kunne skimmes for "skal jeg gøre noget?" */
.forslag-kort-min-tur { border-left-color: var(--accent); }
.aftale-etiket {
  margin: 0 0 8px; font: 800 10px/1 var(--sans); text-transform: uppercase;
  letter-spacing: .12em; color: var(--tekst-svag);
}
.forslag-kort-min-tur .aftale-etiket { color: var(--accent); }
.aftale-tid { margin: 0; font: 700 26px/1.15 var(--condensed); text-transform: uppercase; color: var(--tekst-staerk); }
.aftale-sted { margin: 6px 0 0; font-size: 14px; color: var(--tekst-svag); }
.forslag-form { max-width: 620px; margin-top: 26px; }

/* Kampkortene på "Min pulje" får en fod med knappen til kampens egen side. */
.kamp-kort-fod { display: flex; flex-wrap: wrap; gap: 10px 14px; align-items: center; margin-top: 8px; }
.kamp-kort-fod .button { width: auto; }
.kamp-chat-tal { font-size: 12px; color: var(--tekst-svag); }
/* Venter kampen på vores svar, skal kortet kunne ses i en liste på afstand. */
.kamp-kort-svar { border-left-color: var(--accent); background: var(--flade-valgt); }
.kamp-varsel { margin: 0; font-size: 13px; font-weight: 700; color: var(--accent); }

/* --- Chatten ---
   En liste og ikke et net: samtalen læses oppefra og ned, og de fire spillere
   har ingen glæde af bobler i to farver på en smal skærm. Egne beskeder får
   guldkanten, systemlinjerne står dæmpet og uden afsender. */
ol.chat { list-style: none; margin: 0 0 26px; padding: 0; display: grid; gap: 12px; max-width: 700px; }
.chat-linje {
  background: var(--flade-haevet); border: 1px solid var(--kant); border-left: 3px solid var(--kant);
  padding: 14px 18px;
}
.chat-mig { border-left-color: var(--accent); }
.chat-hoved {
  margin: 0 0 6px; display: flex; flex-wrap: wrap; gap: 4px 12px; align-items: baseline;
  font-size: 12px; color: var(--tekst-svag);
}
.chat-hoved strong { font-size: 13px; color: var(--tekst-staerk); }
.chat-tekst { margin: 0; font-size: 15px; line-height: 1.55; color: var(--tekst); }
.chat-system {
  background: transparent; border: 0; border-left: 3px solid var(--kant-svag);
  padding: 4px 0 4px 14px;
}
.chat-system .chat-tekst { font-size: 13px; color: var(--tekst-svag); }
.chat-tid { margin: 2px 0 0; font-size: 11px; color: var(--tekst-passiv); }
.chat-form { max-width: 700px; }

@media (max-width: 620px) {
  .kamp-mod { display: block; margin: 4px 0; }
  .aftale-kort, .forslag-kort { padding: 16px 18px; }
  .kamp-kort-fod .button { width: 100%; justify-content: center; }
}

/* Afstandene på kampsiden står som klasser og ikke som style="" i markup.
   Det er ikke et krav — CSP'ens `style-src 'self'` rammer inline <style> og
   <script>, ikke style-attributter, og de virker fint på de øvrige sider —
   men kampsiden har den samme luft mange steder, og ét sted at rette den er
   bedre end elleve. */
.advarsel-kamp { margin-bottom: 26px; }
.sektion-foerste { margin-top: 0; }
.hjaelpetekst-luft { display: block; margin-top: 14px; }
.forslag-kort .knap-raekke { margin-top: 18px; }
.forslag-kort .hjaelpetekst { display: block; margin-top: 12px; }
.forslag-form .hjaelpetekst { display: inline; }
.ophaev-form { margin-top: 22px; }
/* Fed brødtekst uden overskrifternes versaler og spærring. Bruges i sidehovedet,
   i sektionernes indledning og i advarselsboksene, hvor <strong> ellers tegnes
   som en etiket i versaler. */
.side-hoved p strong.tekst-fremhaevet,
.sektion > p.sektion-intro strong.tekst-fremhaevet,
.advarsel strong.tekst-fremhaevet,
.kort > p strong.tekst-fremhaevet {
  display: inline; text-transform: none; font-size: inherit; letter-spacing: 0;
}

/* Kvitteringen i aftalekortet. Uden den læses forslagsformularen nedenunder som
   om accepten ikke gik igennem — det var den første ting, der forvirrede i
   gennemgangen 25. august 2026. Grøn som kortets kant, ikke guld: guld betyder
   "du skal gøre noget" alle andre steder i appen. */
.aftale-kvittering {
  margin: 14px 0 0; padding-top: 12px; border-top: 1px solid var(--kant-svag);
  font-size: 14px; line-height: 1.5; color: var(--ok);
}
.aftale-flueben { font-weight: 700; margin-right: 6px; }

/* "Skal I flytte kampen?" — sammenfoldet, når aftalen står fast. */
.aendre-aftale { margin-top: 26px; }
.aendre-aftale > div { padding-top: 4px; }
.aendre-aftale .forslag-form { margin-top: 14px; }

/* --- "Nyt"-markering (tilføjet 25. august 2026, farven skærpet 27. august) ---
   Fyldt flade og ikke bare en kant: mærkatet skal kunne findes i en liste af
   fem kampkort uden at læse dem. Statusmærkaterne ved siden af er omvendte
   (kant, ingen fyld), så de to kan ikke forveksles.
   Farven er ren signalgul og ikke appens dæmpede guld — guldet er den samme
   familie som overskrifter og knapper, så mærkatet forsvandt ind i kortet.
   Gælder både "Nyt" og "Bekræft": begge betyder "du skal gøre noget her". */
.nyt-maerkat {
  display: inline-block; padding: 5px 11px; margin-right: 12px; vertical-align: 2px;
  font: 800 10px/1 var(--sans); text-transform: uppercase; letter-spacing: .12em;
  background: var(--nyt-flade); color: var(--nyt-tekst); border: 1px solid var(--nyt-kant);
}
/* Status og "Nyt" står på samme linje i deres egen række. Uden den ville de to
   blive hver sin flex-linje i kortets kolonne og gøre kortet unødigt højt. */
.kamp-maerkater { display: flex; flex-wrap: wrap; gap: 8px; margin: 0 0 2px; }
.kamp-maerkater .status-maerkat, .kamp-maerkater .nyt-maerkat { margin: 0; }
/* Panelet på Min side er smalt. Mærkat og tekst står som flex, så teksten
   bryder som sin egen blok i stedet for at efterlade et enkelt ord på linje to. */
.panel-varsel {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  margin: 0 0 10px; font-size: 13px; color: var(--tekst);
}
.panel-varsel .nyt-maerkat { margin: 0; }

/* --- Resultater og puljetabel (modul 05) ---
   Farverne kommer fra temalaget (--flade, --kant, --accent, --ok), aldrig fra
   paletten: en komponent skrevet med var(--marine-lys) eller #fff findes kun i
   det ene af de to temaer. */

/* Statusmærkatet for en spillet kamp får den grønne, ligesom "I gang" på
   rækkerne. Uden den er "Ikke aftalt", "Aftalt" og "Spillet" ens at se på. */
.status-maerkat.status-spillet { border-color: var(--ok); color: var(--ok); }

/* Puljetabellen har otte kolonner og skal kunne læses på en telefon. Den
   smallere padding og min-width holder den inden for én vandret scroll i
   stedet for to. */
table.data.puljetabel { min-width: 560px; }
table.data.puljetabel th, table.data.puljetabel td { padding: 10px 12px; }
.tabel-diff { margin-left: 6px; font-size: 12px; color: var(--tekst-svag); }
.tabel-point { font-weight: 800; color: var(--tekst-staerk); }
.tabel-note { max-width: 760px; margin: 12px 0 0; font-size: 12px; color: var(--tekst-svag); }
/* Guld betyder "nogen skal gøre noget" — også når det er en linje under en tabel. */
.tabel-note-varsel { color: var(--accent); font-weight: 700; font-size: 13px; }

/* Resultatkortet på kampsiden. Samme grundform som aftalekortet, så de to
   læses som det samme slags kort — den ene siger hvornår, den anden hvad der
   skete. Grøn kant, når begge par er enige; guld, mens der mangler et svar. */
.resultat-kort {
  background: var(--flade-haevet); border: 1px solid var(--kant); border-left: 3px solid var(--kant);
  padding: 20px 24px; max-width: 620px; margin-bottom: 18px;
}
.resultat-kort-bekraeftet { border-left-color: var(--ok); }
.resultat-kort-afventer { border-left-color: var(--accent); }
.resultat-cifre {
  margin: 0; font: 700 30px/1.15 var(--condensed); letter-spacing: .02em;
  font-variant-numeric: tabular-nums; color: var(--tekst-staerk);
}
.resultat-kort .kamp-varsel { margin-top: 12px; }
.resultat-kort .knap-raekke { margin-top: 18px; }
.resultat-kort .hjaelpetekst { display: block; margin-top: 12px; }
.advarsel .knap-raekke { margin-top: 14px; }

/* Indtastningen. Hvert sæt er en fieldset med to felter og en tankestreg
   imellem, så "jer" og "dem" ikke kan byttes om ved et uheld — det er den ene
   fejl, der er umulig at opdage bagefter. */
.resultat-form { max-width: 620px; }
.resultat-hvem {
  display: flex; flex-wrap: wrap; gap: 4px 24px; margin: 0 0 18px;
  font-size: 14px; color: var(--tekst-svag);
}
.resultat-hvem strong { color: var(--tekst); }
.saet-raekke {
  display: flex; align-items: flex-end; gap: 10px; margin: 0 0 18px;
  border: 0; padding: 0;
}
.saet-raekke legend {
  font: 800 10px/1 var(--sans); text-transform: uppercase; letter-spacing: .12em;
  color: var(--tekst-svag); padding: 0; margin-bottom: 8px;
}
.saet-raekke label { display: flex; flex-direction: column; gap: 6px; margin: 0; }
.saet-raekke label span {
  font: 700 10px/1 var(--sans); text-transform: uppercase; letter-spacing: .1em;
  color: var(--tekst-svag);
}
/* Talfelterne er firkanter og ikke linjer.
   Tallet er hele indtastningen — der står ét ciffer i hvert felt, og det skal
   kunne læses og rammes med en tommelfinger på en bane. Den understregede
   linjestil fra .formular duer ikke her: den ser ud som en tom linje, og man
   kan ikke se, at der er noget at taste i. Derfor en rigtig ramme, høj
   linjehøjde og en font på størrelse med overskrifterne.
   Felterne er `type="text"` med `inputmode="numeric"` (se resultatformular.php),
   fordi maxlength ikke virker på et talfelt. **Derfor er vælgerne herunder
   skrevet med `.formular` foran:** ellers vinder `.formular input[type=text]`
   længere oppe i filen, og felterne får den understregede linjestil tilbage —
   altså præcis den fejl, firkanterne blev lavet for at rette. */
.formular .saet-raekke input {
  width: 78px; height: 76px; padding: 0; text-align: center;
  font: 700 34px/1 var(--condensed); font-variant-numeric: tabular-nums;
  color: var(--tekst-staerk); background: var(--flade-felt);
  border: 1px solid var(--kant); border-radius: 0; outline: none;
  -webkit-appearance: none; appearance: none; -moz-appearance: textfield;
}
.formular .saet-raekke input:focus { border-color: var(--accent); box-shadow: inset 0 0 0 1px var(--accent); }
/* Tiebreaken er en fodnote til sættet, ikke et tredje ciffer. Den står mindre
   og lidt væk, så den ikke kan forveksles med partierne. */
.saet-felt-tiebreak { margin-left: 10px !important; }
.formular .saet-raekke .saet-felt-tiebreak input {
  width: 58px; height: 56px; font-size: 22px; color: var(--tekst-svag);
  background: transparent; border-style: dashed;
}
.saet-streg { padding-bottom: 26px; font-size: 20px; color: var(--tekst-svag); }
.afkryds { display: flex; align-items: flex-start; gap: 10px; margin: 18px 0 0; font-size: 14px; }
.afkryds input { width: auto; margin: 2px 0 0; }

/* Resultatet på kampkortet i Min pulje. Tallene skal kunne skimmes i en liste
   af fem kort, derfor tabular-nums og en større skriftstørrelse end kortets
   øvrige linjer. */
.kamp-resultat {
  margin: 0; font: 700 20px/1.2 var(--condensed); font-variant-numeric: tabular-nums;
  color: var(--tekst-staerk);
}
.kamp-resultat span {
  margin-left: 10px; font: 400 12px/1 var(--sans); text-transform: uppercase;
  letter-spacing: .1em; color: var(--tekst-svag);
}
.kamp-resultat-sejr { color: var(--ok); }
.kamp-resultat-afventer { color: var(--accent); }
/* En færdig kamp skal ikke råbe lige så højt som en, der mangler at blive
   spillet. Klassen bruges nu kun på det kort, en bekræftet kamp beholder, så
   længe der er sket noget nyt i chatten — resten er foldet til linjer herunder. */
.kamp-kort-faerdig { border-left-color: var(--ok); }

/* Spillede kampe på Min pulje: én linje hver, ikke et kort.
   En pulje på seks par giver fem kampe, og er tre af dem spillet, sparer
   linjerne omkring 500px — forskellen på at skulle scrolle til stillingen og
   at have den på skærmen. Listen er IKKE et grid som .kamp-liste: tynde linjer
   i to kolonner ville læses som en tabel uden overskrifter. */
.kamp-faerdige { display: flex; flex-direction: column; gap: 6px; max-width: 1100px; margin: 0; padding: 0; list-style: none; }
/* Hele linjen er trykmålet, og 12px lodret giver de 44px, en finger skal have.
   Undtagelsen står i .app-main-reglens egen :not-kæde og ikke som en regel
   herunder: hvert :not() tæller med i specificiteten, så den generelle regel
   vejer 0,3,1 og kan ikke slås af et .app-main a.klasse (0,2,1) længere nede.
   Uden undtagelsen blev modstanderens navn guldfarvet, og så råbte en færdig
   kamp højere end de kort ovenover, den netop skal vige for. */
.kamp-faerdig {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px 12px;
  padding: 12px 16px; text-decoration: none; color: var(--tekst);
  background: var(--flade-haevet); border: 1px solid var(--kant); border-left: 3px solid var(--ok);
}
.kamp-faerdig:hover { background: var(--flade-hover); }
/* Modstanderen tager pladsen, så resultatet står højrestillet på en bred skærm
   og falder ned under navnet på en smal. To lange dobbeltnavne kan ikke være
   på 390px ved siden af et resultat. */
.kamp-faerdig-modstander { flex: 1 1 170px; font: 700 16px/1.25 var(--condensed); text-transform: uppercase; }
/* Cifrene og udfaldet flytter sig sammen, aldrig hver for sig. */
.kamp-faerdig-facit { flex: 0 0 auto; white-space: nowrap; }
.kamp-faerdig-resultat { font: 700 17px/1.2 var(--condensed); font-variant-numeric: tabular-nums; color: var(--tekst-svag); }
/* Samme lille versallinje som .kamp-resultat span, så udfaldet læses ens
   begge steder. */
.kamp-faerdig-udfald {
  font: 400 11px/1 var(--sans); text-transform: uppercase; letter-spacing: .1em; color: var(--tekst-svag);
}
.kamp-faerdig-sejr .kamp-faerdig-resultat { color: var(--ok); }

/* Mellemoverskrift inde i en sektion, fx "Stillingen" over puljetabellen på
   adminens rundeside. */
.under-overskrift {
  margin: 22px 0 10px; font: 800 11px/1 var(--sans); text-transform: uppercase;
  letter-spacing: .12em; color: var(--tekst-svag);
}

@media (max-width: 620px) {
  /* På en telefon er der ikke plads til et dobbeltnavn OG et resultat på
     samme linje — men kun for NOGLE af kampene, og så fandt facit sin egen
     plads i hver linje: nogle til højre, andre nedenunder. En liste, hvor
     hver række er sat op på sin måde, kan ikke skimmes. Navnet får hele
     bredden, facit står under. To linjer hver gang, ens hver gang. */
  .kamp-faerdig { gap: 2px; }
  .kamp-faerdig-modstander { flex: 1 1 100%; }

  .resultat-kort { padding: 16px 18px; }
  /* Firkanterne skrumper, men bliver ved med at være firkanter. Bliver de
     bredere end høje, ligner de igen et almindeligt tekstfelt. */
  .saet-raekke { gap: 8px; }
  .formular .saet-raekke input { width: 68px; height: 68px; font-size: 30px; }
  .saet-felt-tiebreak { margin-left: 4px !important; }
  .formular .saet-raekke .saet-felt-tiebreak input { width: 50px; height: 50px; font-size: 19px; }
  .saet-streg { padding-bottom: 22px; }
}

/* --- Adminens værktøjer på kampsiden (modul 05, rettet 26. august 2026) ---
   Rettelsen og sletningen lå først som to `details.info`, hvis sammenfoldede
   linje er 12px guld i versaler — nøjagtig samme udseende som "Kampene i pulje
   1" og anden dokumentation. Følgen var, at rettelsen ikke kunne findes,
   selvom den var der hele tiden.

   **En handling skal se ud som en handling.** Kassen har en ramme og en
   etiket, og hver sammenfoldet linje er tegnet som en knap. Det er den samme
   lære som med flashbeskederne: findes funktionen kun for den, der ved, hvor
   den er, findes den ikke. */
.admin-vaerktoej {
  max-width: 620px; margin: 26px 0 0; padding: 18px 20px;
  border: 1px solid var(--kant); background: var(--flade);
}
.admin-vaerktoej-etiket {
  margin: 0 0 14px; font: 800 10px/1 var(--sans); text-transform: uppercase;
  letter-spacing: .14em; color: var(--tekst-svag);
}
.admin-handling { margin: 0; }
.admin-handling + .admin-handling { margin-top: 10px; }
/* Summary tegnet som en sekundær knap. `list-style: none` + ::-webkit-details-marker
   fjerner trekanten; uden begge dele bliver den stående i Safari. */
.admin-handling > summary {
  display: inline-flex; align-items: center; gap: 8px; cursor: pointer;
  padding: 10px 18px; border: 1px solid var(--kant-knap); background: transparent;
  font: 700 12px/1 var(--sans); text-transform: uppercase; letter-spacing: .1em;
  color: var(--tekst-staerk); list-style: none;
}
.admin-handling > summary::-webkit-details-marker { display: none; }
.admin-handling > summary::before { content: "+"; font-size: 15px; line-height: 1; color: var(--accent); }
.admin-handling[open] > summary::before { content: "–"; }
.admin-handling > summary:hover { border-color: var(--accent); color: var(--accent); }
.admin-handling > div { padding: 16px 0 4px; font-size: 14px; color: var(--tekst-svag); }
.admin-handling > div p { margin: 0 0 14px; line-height: 1.55; }
.admin-handling .resultat-form { margin-top: 4px; }

/* Kodeversionen nederst i adminsektionen på Min side. Dæmpet med vilje: den er
   et svar, man leder efter, ikke noget der skal fange øjet. Guld og fed, hvis
   en migration mangler at blive kørt — dét er et problem, der skal ses. */
.kodeversion {
  max-width: 760px; margin: 26px 0 0; padding-top: 14px;
  border-top: 1px solid var(--kant-svag);
  font-size: 12px; line-height: 1.6; color: var(--tekst-passiv);
}
.kodeversion strong { color: var(--tekst-svag); font-weight: 700; }
.kodeversion-advarsel { color: var(--accent); font-weight: 600; }
.kodeversion-advarsel strong { color: var(--accent); }

/* --- Modul 06: afviklingsstatus for admin ---

   Bjælken har to lag oven i hinanden: den fyldte del er spillede kampe, og
   den lodrette streg er, hvor langt vi er i rundens tidsrum. Sammenligningen
   er hele pointen — "30 % spillet" siger intet, før man ved, om der er gået
   en uge eller seks af runden. Ligger fyldet tydeligt til venstre for
   stregen, halter runden.

   Farverne kommer fra temanavnene, så bjælken findes i begge farveskalaer. */
.fremdrift { max-width: 760px; margin: 0 0 26px; }
.fremdrift-bjaelke {
  position: relative; height: 14px; background: var(--flade-felt);
  border: 1px solid var(--kant); overflow: hidden;
}
/* width:0 er ikke pynt. Et display:block-element uden bredde fylder hele
   forælderen, så bjælken ville stå på 100 % — "alle kampe spillet" — hvis
   app.js ikke nåede at sætte den. En tom bjælke er tydeligvis endnu ikke
   udfyldt; en fuld bjælke er en løgn, man tror på. */
.fremdrift-fyld { display: block; width: 0; height: 100%; background: var(--ok); transition: width .3s ease; }
/* Stregen for "hvor langt er tiden nået".
   Den skal kunne ses både oven på fyldet og på den tomme flade, og den må
   ikke have samme farve som fyldet — når runden er bagud, er fyldet guld, og
   en guld streg forsvinder i det. --tekst-staerk står frem på begge dele i
   begge temaer, og stregen er en markør, ikke en advarsel. */
.fremdrift-tid {
  position: absolute; top: -1px; bottom: -1px; width: 2px; margin-left: -1px;
  background: var(--tekst-staerk);
}
.fremdrift-bagud .fremdrift-fyld { background: var(--accent); }
.fremdrift-tekst { margin: 10px 0 0; font-size: 13px; line-height: 1.6; color: var(--tekst-svag); }
.fremdrift-tekst strong { color: var(--tekst); font-weight: 700; }

/* Den lille bjælke inde i puljetabellen. Samme sprog som den store, bare
   uden tidsstregen: linjen har allerede tallene ved siden af. */
.mini-bjaelke {
  display: inline-block; width: 54px; height: 8px; margin-right: 8px; vertical-align: middle;
  background: var(--flade-felt); border: 1px solid var(--kant);
}
.mini-bjaelke span { display: block; width: 0; height: 100%; background: var(--ok); }

/* Mærkat med et tal eller en tilstand. Standarden er neutral; kun de to
   tilstande, der kræver en handling af admin, får farve — ellers holder
   tabellen op med at pege på noget. */
.varsel-maerkat {
  display: inline-block; padding: 3px 9px; border: 1px solid var(--kant-knap);
  font: 700 11px/1.5 var(--sans); text-transform: uppercase; letter-spacing: .08em;
  color: var(--tekst-svag); white-space: nowrap;
}
.varsel-maerkat.varsel-forfalden { border-color: var(--accent); color: var(--accent); background: var(--flade-valgt); }
.varsel-maerkat.varsel-afventer { border-color: var(--accent); color: var(--accent); }
.varsel-maerkat.varsel-mangler { border-color: var(--tekst-passiv); }
/* Hvert varsel på sin egen linje. Løber de sammen i én paragraf, læses "4
   kampe er forfaldne … 1 resultat venter …" som én sætning, og tallene
   hører pludselig til det forkerte. */
.status-varsler { max-width: 760px; margin: 0; display: grid; gap: 8px; justify-items: start; }
.status-varsel { font-size: 13px; line-height: 1.6; color: var(--tekst-svag); }
.status-varsel .varsel-maerkat { margin-right: 6px; }

/* Listen over kampe, der mangler. Bredere end de andre datatabeller, fordi
   den har både to par, pulje, tilstand, dato, baneansvar og to knapper. */
table.data.status-tabel { min-width: 900px; }

/* Statuskortet i adminsektionen på Min side. Det er det samme regnestykke som
   /admin/status — kortet er indgangen, ikke et andet svar. */
.status-kort {
  max-width: 760px; margin: 0 0 26px; padding: 20px 22px;
  border: 1px solid var(--kant); border-left: 3px solid var(--accent); background: var(--flade-haevet);
}
.status-kort h3 { margin: 0 0 4px; font: 700 20px var(--condensed); text-transform: uppercase; color: var(--tekst); }
.status-kort .fremdrift { margin: 14px 0 0; }
.status-kort .status-varsler { margin-top: 12px; }
/* Stod som style="margin-top:16px" i viewet og var derfor død under CSP'en. */
.status-kort .knap-raekke { margin-top: 16px; }
.status-kort-runde { margin: 0; font-size: 13px; color: var(--tekst-svag); }

@media (max-width: 620px) {
  .status-kort { padding: 16px 18px; }
  .fremdrift-tekst { font-size: 12px; }
}

/* De to knapper i listen står ved siden af hinanden, ikke over. Med 60 rækker
   koster en ombrudt knaprække 60 gange den ekstra højde. */
table.data.status-tabel td:last-child { white-space: nowrap; }
table.data.status-tabel td:last-child .knap-raekke { flex-wrap: nowrap; gap: 8px; }

/* Rykkeren i statuslisten. Lukket er den tegnet som en knap — det er
   `.admin-handling`s summary-stil, der genbruges — og åbnet står de fire
   spillere som hver sin knap.

   Grunden til at det ikke bare er ét link: både iMessage på iPhone og Beskeder
   på Mac tager kun den FØRSTE modtager af et sms:-link med flere numre og
   smider resten væk uden at sige det. En rykker til fire skal derfor være fire
   links — og så skal man kunne se, hvem knappen sender til. */
.rykker-fold { display: inline-block; }
.rykker-fold > summary { padding: 8px 14px; }
/* Kassen folder ud i selve rækken og gør den højere.
   Første udgave hang den ud over tabellen som en popover — det så pænere ud,
   men `.tabel-omslag` har `overflow-x: auto`, og den klipper alt, hvad der
   stikker uden for. Den nederste halvdel af kassen — det ene af de to par —
   kunne ikke nås. **En popover kan ikke bo i en scrollende beholder.** */
.rykker-fold > div {
  padding: 14px 0 4px; width: 260px;
  /* Cellen har white-space: nowrap, så knapperne står side om side. Inde i
     folden skal navne og hjælpetekst kunne bryde igen. */
  white-space: normal;
}
.rykker-fold > div .knap-raekke { margin-top: 8px; gap: 8px; flex-wrap: wrap; }
.rykker-fold > div .hjaelpetekst { display: block; }
/* Rykkerens to par. Fire løse fornavne siger ikke, hvem der hører sammen, og
   admin rykker som regel ét bestemt par — det, der skulle have booket banen. */
.rykker-par + .rykker-par { margin-top: 14px; padding-top: 14px; border-top: 1px solid var(--kant-svag); }
.rykker-par-navn { margin: 0; font-size: 13px; font-weight: 600; color: var(--tekst); line-height: 1.45; }
.rykker-ansvar {
  display: inline-block; margin-left: 6px; padding: 2px 7px; border: 1px solid var(--accent);
  font: 700 10px/1.5 var(--sans); text-transform: uppercase; letter-spacing: .08em; color: var(--accent);
}
/* Når rykkeren er foldet ud, skal "Åbn kampen" ikke hoppe ned under den —
   knapperne bliver stående øverst i cellen. */
.rykker-celle { align-items: flex-start; }
/* Når en rykker er foldet ud, bliver rækken høj. Uden det her stod kampens
   navn og lodret centreret midt i den tomme højde. */
table.data.status-tabel td { vertical-align: top; }

/* --- Modul 07: op- og nedrykning ---
   Pilen og ordet står sammen, så bevægelsen kan ses uden at læse farven —
   en rød/grøn markering alene ville ikke sige noget til den, der ikke kan
   skelne dem. Guld op, dæmpet ned: en oprykning er den gode nyhed. */
.ryk {
  display: inline-block; padding: 2px 8px; border: 1px solid var(--kant-knap);
  font: 700 11px/1.5 var(--sans); text-transform: uppercase; letter-spacing: .06em;
  color: var(--tekst-svag); white-space: nowrap;
}
.ryk-op { border-color: var(--accent); color: var(--accent); }
/* Mærkatet og "fra pulje 3" skal stå på én linje. Brydes de, bliver hver
   række dobbelt så høj, og en pulje på 8 par fylder en hel skærm. */
table.data td.ryk-celle { white-space: nowrap; }
/* Kolonnen mere kræver mere bredde, før tabellen begynder at klippe. */
table.data.med-ryk { min-width: 780px; }
.ryk-ned { border-color: var(--kant-knap); color: var(--tekst-svag); }
.ryk-ny { border-color: var(--ok); color: var(--ok); }

/* Parrene, der venter på at blive sat i en pulje. Én linje pr. par: navn,
   puljevælger og knap. */
.udenfor-liste { display: grid; gap: 10px; margin-top: 14px; }
.udenfor-liste .flyt-form { flex-wrap: wrap; gap: 10px; }
.udenfor-navn { flex: 1 1 220px; font-size: 14px; color: var(--tekst); }
.udenfor-navn .dæmpet { margin-left: 8px; font-size: 12px; }

@media (max-width: 620px) {
  .udenfor-liste .flyt-form { flex-direction: column; align-items: stretch; }
  .udenfor-navn { flex: none; font-weight: 600; }
}

/* ============================================================
   Modul 08 — rangliste
   ============================================================ */

/* Tabellen er smallere end puljetabellen: fem kolonner, og fire af dem er tal. */
table.data.ranglistetabel { min-width: 520px; }
/* Spillerens egne tildelinger: fire kolonner, hvoraf tre er korte. table.data
   sætter 620px, som er rigtigt for puljetabellens otte kolonner og for bredt
   her — den skubbede pointtallet ud over kanten inde i kortet. */
table.data.tildelingstabel { min-width: 360px; }
.ranglistetabel td .dæmpet { margin-left: 6px; font-size: 12px; }

/* "spiller nu" er en OPLYSNING og ikke et filter: ranglisten er ikke en
   deltagerliste, og de, der sidder en runde over, bliver stående på den.
   Derfor et dæmpet mærkat og ikke guld — guld betyder "gør noget" i appen. */
.spiller-nu {
  display: inline-block; margin-left: 8px; padding: 2px 7px;
  font: 700 10px/1.5 var(--sans); text-transform: uppercase; letter-spacing: .09em;
  color: var(--tekst-svag); background: var(--flade-maerkat); border: 1px solid var(--kant-svag);
}

/* Spillerens egen stilling. Ét kort pr. rangliste — aldrig ét samlet tal.
   Kortet er bredere end et almindeligt .kort, fordi tildelingstabellen ligger
   inde i det: i 560px blev pointkolonnen — den eneste, man kommer for — skubbet
   uden for kanten og kunne kun ses ved at scrolle tabellen vandret. */
.mine-point { margin-bottom: 26px; max-width: 820px; }
.mine-point h2 { display: flex; flex-wrap: wrap; align-items: baseline; gap: 6px 14px; }
.mine-point-plads {
  font: 700 13px var(--sans); text-transform: uppercase; letter-spacing: .09em;
  color: var(--tekst-svag);
}
.mine-point details.info { max-width: none; }

/* De andre ranglister, spilleren har point på. Blokken er en almindelig
   `.sektion` og har ikke sin egen typografi længere: overskriften stod 20px,
   mens "Stillingen" lige nedenunder stod 30px, og de to er på samme niveau i
   sidens hierarki. Introen brugte `class="sektion-intro"`, men den regel kræver
   en `.sektion`-forælder — så teksten stod 16px i fuld tekstfarve i stedet for
   15px dæmpet som alle andre introer. Begge dele forsvandt, da blokken fik
   `.sektion` med i viewet. */

/* Pointtabellen står i tre spalter, så 120 pladser kan ses uden at scrolle
   gennem en skærm og en halv. */
table.data.skala-tabel { min-width: 460px; font-size: 13px; }
table.data.skala-tabel th, table.data.skala-tabel td { padding: 7px 14px; }

/* "Afbryd" står i sin egen formular under importknappen og klistrede ellers
   op ad den. */
.afbryd-form { margin-top: 20px; }

/* En foldet blok med en tabel i skal have hele bredden. details.info er ellers
   sat til 760px, som er rigtigt for brødtekst og forkert for 168 rækker. */
details.info.bred { max-width: none; }
details.info.bred > div { color: var(--tekst); }

/* ============================================================
   Modul 09 — regelsæt i databasen
   ============================================================ */

/* Søgefeltet på den offentlige regelside. Den ligger i det LYSE offentlige lag
   (layout/offentlig), ikke bag login, så farverne kommer fra paletten og ikke
   fra temanavnene — der er intet mørkt/lyst skift her. */
.regelsoegning {
  display: flex; flex-wrap: wrap; align-items: center; gap: 12px 16px;
  margin: 0 0 28px; padding: 18px 20px;
  background: #17344a; border: 1px solid #315066;
}
.regelsoegning label {
  font: 800 11px var(--sans); text-transform: uppercase; letter-spacing: .12em;
  color: #8fa3b1; flex: none;
}
.regelsoegning input[type=search] {
  flex: 1 1 240px; min-width: 0; padding: 12px 14px;
  font: 16px var(--sans); color: #fff;
  background: var(--ink); border: 1px solid #315066; border-radius: 0;
  -webkit-appearance: none; appearance: none;
}
.regelsoegning input[type=search]::placeholder { color: #7d919f; }
.regelsoegning input[type=search]:focus { outline: 2px solid var(--acid); outline-offset: 2px; }
.regelsoegning .button { flex: none; }
.regelsoegning-ryd { font-size: 13px; color: #d2dce2; }
/* Svaret på en søgning står begge steder — på den lyse offentlige side og bag
   login i app-layoutet — så farven må ikke være bundet til det ene. Med den
   faste --ink stod linjen som marineblå tekst på marineblå bund og var helt
   væk i det mørke tema. */
.regelsoegning-svar { margin: 0 0 26px; font-size: 15px; }
.rules-page .regelsoegning-svar { margin-top: -14px; color: #d2dce2; }
.app-main .regelsoegning-svar { color: var(--tekst); }

/* Træfferne. <mark> er browserens egen gule som standard — den slår ikke til i
   klubbens palet, og på guld ville teksten forsvinde. */
.rules-page mark {
  background: var(--acid); color: var(--ink);
  padding: 1px 3px; border-radius: 0; font-weight: 600;
}

.regel-udgave { margin: 26px 0 0; font-size: 13px; color: #8fa3b1; }
.app-main .regel-udgave { color: var(--tekst-svag); }

/* Ghost-knapper på den LYSE regelside.
   .button-ghost er tegnet til prototypens mørke hero og har hvid tekst — målt
   her: rgb(255,255,255) på papirfarven #f6f4ef, altså 1,05:1 og fuldstændig
   usynligt. Det ramte "Hent regler som PDF" allerede på den statiske side; det
   blev bare aldrig set, fordi ingen kiggede på knappen. Marineblå tekst og kant
   giver 12,6:1 og er den samme knap, bare vendt om.
   style.css rettes ikke — den er kopieret fra prototypen. */
/* .button-ghost har hvid tekst og hører til på mørk bund — hvilket den nu
   igen står på, efter at regelsiden har fået sin subpage-klasse tilbage.
   Derfor er der ikke længere en omvending her.

   Men prototypens .button-ghost sætter kun kant og tekstfarve, ikke baggrund.
   Det går, så længe knappen er et <a> (gennemsigtig af sig selv) — er den et
   <button>, tegner browseren sin egen grå flade, og så står hvid tekst på lys
   grå. Søgeknappen er et <button>. */
button.button-ghost { background: none; -webkit-appearance: none; appearance: none; }

/* Adminens redigering ligger bag login og bruger derfor temanavnene. */
.regel-dokument, .app-main textarea.regel-dokument {
  font: 14px/1.7 ui-monospace, SFMono-Regular, Menlo, monospace;
  min-height: 420px;
}
.regel-raa {
  margin: 0; padding: 16px; overflow-x: auto;
  background: var(--flade-svag); border: 1px solid var(--kant-svag);
  font: 13px/1.7 ui-monospace, SFMono-Regular, Menlo, monospace;
  color: var(--tekst); white-space: pre-wrap; word-break: break-word;
}
table.data.regelhjaelp-tabel { min-width: 420px; }
.regelhjaelp-tabel code {
  background: var(--flade-svag); padding: 2px 6px;
  font: 13px ui-monospace, SFMono-Regular, Menlo, monospace; color: var(--tekst-staerk);
}

/* Indholdsmenuen bag login. Prototypens .rules-nav er en mørk, klæbrig bjælke
   tegnet til den lyse side; inde i app-layoutet ville den enten forsvinde i
   baggrunden eller skære sig igennem den. Her er det en almindelig række links
   i temaets egne farver. */
.regel-indhold {
  display: flex; flex-wrap: wrap; gap: 10px 22px;
  margin: 0 0 26px; padding: 16px 20px;
  background: var(--flade-haevet); border: 1px solid var(--kant);
}
.regel-indhold a {
  font: 700 11px var(--sans); text-transform: uppercase; letter-spacing: .09em;
  color: var(--tekst-svag); text-decoration: none;
}
.regel-indhold a:hover { color: var(--accent); text-decoration: underline; text-underline-offset: 5px; }

/* Adminens forhåndsvisning og spillerens regelside bruger den offentlige sides
   klasser (.official-rules, .rule-section) inde i app-layoutet. De er tegnet
   til lys bund i style.css, så farverne sættes om her. */
.app-main .official-rules .rule-section { border-top: 1px solid var(--kant); }
.app-main .official-rules .rule-number { color: var(--accent); }
.app-main .official-rules h2, .app-main .official-rules h3 { color: var(--accent); }
.app-main .official-rules p, .app-main .official-rules li { color: var(--tekst); }
.app-main .official-rules .rule-highlight {
  background: var(--flade-haevet); border-left: 3px solid var(--accent); color: var(--tekst);
}
.app-main .official-rules .rule-section:first-child { border-top: 0; }
/* Søgetræffere: guld med marineblå tekst i BEGGE temaer — samme par som
   guldknappen (6,9:1) og appens ene faste farveanker. --markering er en 10-30 %
   guldtone tegnet til at farve en hel tabelrække og er alt for svag til et ord. */
.app-main .official-rules mark {
  background: var(--guld); color: var(--marine); padding: 1px 4px; font-weight: 600;
}
.app-main .official-rules .ranking-list { color: var(--tekst); }

/* Fed skrift. style.css sætter .rule-content strong til HVID, fordi
   prototypens regelside står på mørk bund. I det lyse tema bag login gav det
   hvid tekst på hvid flade — usynlig, indtil man markerede den med musen. */
.app-main .official-rules strong { color: var(--tekst-staerk); }

/* Kriterielisten er tegnet som næsten sorte fliser (#171b19) med lys skrift.
   De skal følge temaet, ligesom resten af tabellerne i appen. */
.app-main .official-rules .ranking-list {
  background: var(--kant); border-color: var(--kant);
}
.app-main .official-rules .ranking-list li { background: var(--flade-haevet); }
.app-main .official-rules .rule-example {
  border-top-color: var(--kant-svag); border-bottom-color: var(--kant-svag);
}

/* Luft mellem den første etiket og bjælkens kant på den offentlige side.
   .rules-nav har padding: 18px 0 fra prototypen, så teksten klistrede op ad
   kanten af den mørke flade. */
.rules-page .rules-nav { padding-left: 22px; padding-right: 22px; }

@media (max-width: 620px) {
  .regelsoegning { padding: 14px; }
  .regelsoegning label { flex: 1 1 100%; }
}

/* Slut-CTA'en på den offentlige regelside er limegrøn (#a6c50e) i prototypens
   style.css — en farve, der ikke findes noget andet sted i appen; forsidens
   tilsvarende blok er guld. Her rettes den til guld med marineblå tekst, samme
   par som guldknappen, så regelsiden slutter som resten af det offentlige lag.
   style.css rettes ikke; den er kopieret fra prototypen. */
.rules-page .rules-bottom-cta { background: var(--guld); }
.rules-page .rules-bottom-cta .section-label { color: rgba(16, 40, 61, .7); }

/* =====================================================================
   Modul 10 — beskeder til spillerne
   ===================================================================== */

/* Status på en udsendelse. Farverne følger, hvad admin skal gøre ved den:
   guld når der stadig mangler at blive sendt, grøn når den er færdig, og
   dæmpet når den er stoppet med vilje. */
.status-maerkat.status-klar { border-color: var(--accent); color: var(--accent); }
.status-maerkat.status-sender { border-color: var(--accent); color: var(--accent); }
.status-maerkat.status-sendt { border-color: var(--ok); color: var(--ok); }
.status-maerkat.status-afbrudt { border-color: var(--prik-passiv); color: var(--tekst-svag); }

/* Beskeden, som modtagerne får den. Fladen er hævet og ikke bare et afsnit
   brødtekst: det er en forhåndsvisning af noget, der forlader appen, og den
   forskel skal kunne ses, inden man trykker send. */
.besked-forhaandsvisning {
  max-width: 640px;
  padding: 20px 22px;
  background: var(--flade-haevet);
  border: 1px solid var(--kant);
  font-size: 15px;
  line-height: 1.65;
  color: var(--tekst);
}
.besked-forhaandsvisning p { margin: 0 0 14px; }
.besked-forhaandsvisning p:last-child, .besked-forhaandsvisning ul:last-child { margin-bottom: 0; }
.besked-forhaandsvisning ul { margin: 0 0 14px; padding-left: 20px; }
.besked-forhaandsvisning li { margin: 0 0 6px; }
.besked-forhaandsvisning strong { color: var(--tekst-staerk); font-weight: 700; }

/* Fremdriften under afsendelsen. Bjælken er den samme som modul 06's, men uden
   den lodrette tidsstreg — der er ingen tid at sammenligne med, kun en kø, der
   bliver kortere. Fyldet er derfor altid grønt. */
.udsendelse-fremdrift { margin-bottom: 18px; }
.udsendelse-fremdrift .fremdrift-fyld { background: var(--ok); }

/* Mailknappen i rykkerfolden. Den står øverst og på sin egen linje, fordi den
   er ét tryk til alle fire — SMS-knapperne under er én pr. spiller. */
.rykker-mail {
  display: flex; flex-wrap: wrap; align-items: center; gap: 10px;
  margin: 0 0 14px; padding-bottom: 14px;
  border-bottom: 1px solid var(--kant-svag);
}
.rykker-mail .hjaelpetekst { margin: 0; }

@media (max-width: 620px) {
  .besked-forhaandsvisning { padding: 16px; font-size: 14px; }
  .rykker-mail { gap: 8px; }
}

/* =====================================================================
   Modul 11 — engangskoden fra login-mailen
   ===================================================================== */

/* Feltet er stort og spatieret, fordi seks cifre skal tastes af én, der lige
   har læst dem i en anden app og holder tallene i hovedet imens. Vælgeren har
   `.formular` foran, så den vinder over `.formular input[type=text]`s
   understregede linjestil — samme greb som resultatfirkanterne i modul 05. */
.formular input.kodefelt, input.kodefelt {
  width: 100%; max-width: 280px;
  padding: 14px 16px;
  background: var(--flade-felt);
  border: 1px solid var(--kant-knap);
  color: var(--tekst-staerk);
  font: 700 32px/1.1 var(--condensed);
  letter-spacing: .28em;
  text-align: center;
}
.formular input.kodefelt:focus, input.kodefelt:focus {
  border-color: var(--accent); outline: none;
}
.formular input.kodefelt::placeholder { color: var(--placeholder); letter-spacing: .28em; }

.kodeformular { margin-top: 22px; }

@media (max-width: 620px) {
  .formular input.kodefelt, input.kodefelt { font-size: 28px; letter-spacing: .22em; }
}

/* Rollemærkater (administratorer). Hovedadministratoren er guld, fordi det er
   den ene rolle, der kan dele adgang ud; administratoren er grøn som "i orden".
   Farverne følger de mærkater, der allerede findes for rækker og runder. */
.status-maerkat.rolle-ejer { border-color: var(--accent); color: var(--accent); }
.status-maerkat.rolle-admin { border-color: var(--ok); color: var(--ok); }
.status-maerkat.rolle-spiller { border-color: var(--prik-passiv); color: var(--tekst-svag); }

/* --- "Læg Klubligaen på hjemmeskærmen" (modul 11) --- */

/* En smal linje øverst på Min side, ikke en femte blok. Udtrykket er
   .advarsel's — guld venstrekant på hævet flade — så den læses som en
   bemærkning og ikke som endnu et kort, spilleren skal forholde sig til.

   Bredder og marginer står HER og ikke som style="..." i viewet: CSP'en i
   public/index.php sender style-src 'self', og den blokerer inline
   style-attributter. En margin skrevet i HTML ville være død uden en eneste
   fejlmeddelelse. */
.installer {
  display: flex; flex-wrap: wrap; align-items: center; gap: 14px 24px;
  border-left: 3px solid var(--accent);
  background: var(--flade-haevet);
  padding: 16px 22px; margin-bottom: 30px; max-width: 760px;
}
/* Linjen skjules og vises med elementets hidden-attribut. Uden den her regel
   ville display:flex ovenfor slå [hidden] ihjel, og påmindelsen ville stå
   fremme hos alle — også dem, der har appen på hjemmeskærmen i forvejen. */
.installer[hidden] { display: none; }
/* Står der en advarsel ovenover ("Flere spillere på din adresse"), skal de to
   ikke klistre sammen. Advarslens egen margin-bottom står som en inline style i
   viewet og er derfor død under CSP'en — luften skal komme herfra. */
.advarsel + .installer { margin-top: 30px; }
.installer-tekst { flex: 1 1 320px; }
.installer-tekst strong {
  display: block; text-transform: uppercase; font-size: 11px;
  letter-spacing: .1em; margin-bottom: 6px; color: var(--accent);
}
.installer-tekst p { margin: 0; font-size: 14px; color: var(--tekst); line-height: 1.6; }
.installer-tekst b { color: var(--tekst-staerk); font-weight: 700; }
.installer-knapper { display: flex; align-items: center; gap: 18px; margin-left: auto; }
.installer-knapper [hidden] { display: none; }
.installer-luk { font-size: 12px; color: var(--tekst-svag); }
.installer-luk:hover { color: var(--tekst); text-decoration: underline; text-underline-offset: 4px; }

/* "Administratorer" er det ottende panel, men hører ikke til de syv: kun
   hovedadministratoren ser det. Nettets egen gap er 18px, så en margin på det
   samme gav ingen forskel at se — panelet lignede bare en ottende kasse, der
   var faldet ned på en ny linje. Luft nok til at det læses som sit eget
   afsnit, og en fin streg, der siger hvorfor. */
.panel-net-ejer { margin-top: 38px; padding-top: 34px; border-top: 1px solid var(--kant); }

/* På en telefon er der ikke plads til tekst og knapper ved siden af hinanden —
   vejledningen bliver presset ned i en smal søjle. Samme knæk som headeren
   bruger (620px). */
@media (max-width: 620px) {
  .installer-knapper { margin-left: 0; width: 100%; justify-content: space-between; }
}

/* --- Lukkeligt "Flere spillere på din adresse" --- */

/* Krydset sidder i boksens øverste højre hjørne, og teksten holdes fri af det
   med padding. 44px er projektets mindste trykflade — se .button-lille. */
.advarsel-lukbar { position: relative; padding-right: 58px; }
.advarsel[hidden] { display: none; }
.advarsel-luk-form { position: absolute; top: 4px; right: 4px; margin: 0; }
.advarsel-luk {
  display: grid; place-items: center;
  width: 44px; height: 44px; padding: 0;
  background: none; border: 0; cursor: pointer;
  font: 400 24px/1 var(--sans); color: var(--tekst-svag);
}
.advarsel-luk:hover { color: var(--tekst-staerk); background: var(--flade-svag); }
.advarsel-luk:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }

/* --- Statuslinjen under hilsenen på Min side ---
   Segmenterne er spans, og skillepunktet tegnes af ::before på alle efter den
   første. Så kan et segment udelades — en runde uden slutdato, en spiller uden
   pulje — uden at der bliver et ensomt "·" tilbage i markuppen.
   Farverne kommer fra temalaget, så linjen findes i begge farveskalaer. */
.side-status {
  margin: 0; font-size: 15px; line-height: 1.5; color: var(--tekst-svag); max-width: 62ch;
}
/* Hvert segment er en inline-block, så linjen kun bryder MELLEM segmenterne.
   Uden det brød "Slutter 24. september" midt over, og datoen så ud som to ting.
   Et segment, der er bredere end linjen — et meget langt rækkenavn — bryder
   stadig indeni, så teksten aldrig går ud over kanten. */
.side-status span { display: inline-block; }
.side-status .side-status-hoved { color: var(--tekst-staerk); font-weight: 600; }
/* Skillepunktet står EFTER segmentet og ikke før det næste. Med flex og et
   ::before brød linjen med en ledende "·" på linje to, som om der manglede et
   ord. Bagest hænger prikken på den linje, den hører til, og teksten bryder
   som almindelig tekst. Derfor er linjen inline og ikke flex. */
.side-status span:not(:last-child)::after {
  content: " · "; color: var(--tekst-passiv); white-space: pre;
}

/* --- Næste kamp i "Min pulje"-kortet ---
   Den lå før to tryk inde på /min-pulje. Blokken er hævet ud af kortets flade
   med sin egen kant til venstre, så øjet finder den før panelets brødtekst —
   det er den ene ting på siden, der handler om i dag og ikke om appen. */
.naeste-kamp {
  border-left: 3px solid var(--accent); padding: 2px 0 2px 12px;
  display: flex; flex-direction: column; gap: 3px; margin: 2px 0 4px;
}
.naeste-kamp .naeste-kamp-etiket {
  font: 800 10px/1 var(--sans); text-transform: uppercase; letter-spacing: .12em;
  color: var(--tekst-passiv);
}
.naeste-kamp .naeste-kamp-tid {
  margin: 0; font: 700 21px/1.1 var(--condensed); text-transform: uppercase;
  letter-spacing: .01em; color: var(--tekst-staerk);
}
.naeste-kamp .naeste-kamp-meta { margin: 0; font-size: 13px; color: var(--tekst-svag); }
/* Samme to farver som kampkortets .kamp-ansvar, så baneansvaret ser ens ud,
   uanset om man læser det på Min side eller inde i puljen. */
.naeste-kamp .naeste-kamp-ansvar { margin: 2px 0 0; font-size: 13px; color: var(--tekst-svag); }
.naeste-kamp .naeste-kamp-ansvar-mit { color: var(--accent); font-weight: 700; }

/* Log ud nederst i profilblokken. Står under panel-linket og skilt af en
   hårlinje, så den ikke læses som endnu en indgang: den lukker noget. */
.panel .panel-logud { margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--kant-svag); }
.panel .panel-logud .link-button { font-size: 12px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--tekst-svag); }
.panel .panel-logud .link-button:hover { color: var(--accent); }

/* --- Bundnavigation (kun på hjemmeskærmen) ---
   HÆNGER SAMMEN MED ".standalone .app-nav" længere nede: når bunden bærer
   navigationen, skjules headerens menu. Fjernes den ene, SKAL den anden
   fjernes samtidig — ellers står man uden nogen navigation.

   Linjen står altid i HTML og skjules her. Serveren kan ikke se, om appen
   kører fra hjemmeskærmen; CSS kan. Derfor er standarden "skjult", og de to
   standalone-veje tænder den — det er den modsatte vej af temaknappen, og med
   vilje: fejler alting, er en manglende bundlinje harmløs, fordi headerens
   menu så også står tilbage. */
.bundnav { display: none; }

/* Papirfarvet i begge temaer, som header og fod — bunden er appens ramme og
   ikke en del af indholdet. Guld hårlinje øverst i stedet for en grå kant:
   det er samme greb som panelernes overkant. */
.bundnav {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 30;
  background: var(--papir); border-top: 2px solid var(--guld);
  /* env() er 0, så længe vi ikke sender viewport-fit=cover — men står her, så
     bundlinjen lander rigtigt, hvis den meta-tag en dag bliver sat.
     De 9px er IKKE luft: uden dem ligger de fire punkter helt nede ved
     skærmkanten, og iOS' hjem-strygefelt tager trykket i stedet for appen.
     Polstringen ligger under teksten og ikke over ikonet, så hele punktet
     løftes væk fra kanten — bliver den fjernet, kommer fejlen igen. */
  padding-bottom: calc(9px + env(safe-area-inset-bottom, 0px));
}
.bundnav-punkt {
  flex: 1; display: flex; flex-direction: column; align-items: center; gap: 3px;
  padding: 8px 2px 7px; text-decoration: none; color: var(--marine);
  /* Tekst under ikonet, ikke ikoner alene: klubben har mange ældre medlemmer,
     og et ikon, man skal gætte, er ikke navigation. */
  font: 700 10px/1 var(--sans); text-transform: uppercase; letter-spacing: .06em;
  border-top: 2px solid transparent; margin-top: -2px;
}
.bundnav-ikon { position: relative; display: block; line-height: 0; }
/* Det aktive punkt får guld overstreg OG guld tekst. Kun farve ville være for
   svagt på en telefon i en oplyst hal; kun streg ville ikke ses af den, der
   leder efter ord. */
.bundnav-punkt.er-aktiv { color: var(--guld-dyb); border-top-color: var(--guld-dyb); }
.bundnav-prik {
  position: absolute; top: -2px; right: -4px; width: 9px; height: 9px;
  background: var(--guld-dyb); border: 2px solid var(--papir); border-radius: 50%;
}

/* --- Fanerække til afsnittene inde på en lang side ---
   Bunden bærer STEDER, fanerne bærer AFSNIT. /min-pulje er over fire skærme
   lang på en telefon, og "Stillingen i puljen" ligger to skærmes scroll nede.
   Rækken klæber til toppen, så springet altid er ét tryk væk. */
.sidefaner {
  position: sticky; top: 0; z-index: 20;
  display: flex; gap: 22px; margin: 0 0 30px;
  padding: 13px 0; background: var(--flade);
  border-bottom: 1px solid var(--kant);
  /* Fire faner kan blive for brede på 320px. Vandret scroll frem for brydning:
     en fanerække, der bliver to linjer høj, holder op med at være en fanerække. */
  overflow-x: auto; scrollbar-width: none;
}
.sidefaner::-webkit-scrollbar { display: none; }
.sidefane {
  flex: none; text-decoration: none; color: var(--tekst-svag);
  font: 800 11px/1 var(--sans); text-transform: uppercase; letter-spacing: .09em;
  padding-bottom: 9px; border-bottom: 2px solid transparent; margin-bottom: -14px;
}
.sidefane.er-aktiv { color: var(--accent); border-bottom-color: var(--accent); }
/* Uden det her lander ankerspringet med overskriften gemt UNDER den klæbrige
   fanerække — man trykker "Stillingen" og ser toppen af tabellen uden at vide,
   hvad man kigger på. Tallet er fanerækkens højde plus lidt luft. */
.sektion[id] { scroll-margin-top: 62px; }

/* --- Appen på hjemmeskærmen ---
   Lagt på hjemmeskærmen er der ingen adresselinje og ingen faner: skærmen ER
   appen, og så er en copyright-fod og et ordmærke websidepynt, der koster den
   nederste tomme skærm. Indholdet er det SAMME i browser og på hjemmeskærmen
   — kun pynten ryger, så vi ikke får en side, der findes i to tilstande.

   Begge veje ind er nødvendige: media queryen dækker Android og nyere Safari,
   mens html.standalone sættes af app.js ud fra navigator.standalone, som er
   den eneste, ældre iPhones svarer på. Fejler JavaScript, står pynten bare
   tilbage — den vej rundt er den rigtige. */
@media (display-mode: standalone) {
  .app-main { padding-bottom: 28px; }
  .app-footer .footer-brand, .app-footer .footer-copyright { display: none; }
  .app-footer { min-height: auto; padding-top: 18px; padding-bottom: 18px; gap: 14px; }
  .sidefaner { top: 0; }
}
html.standalone .app-main { padding-bottom: 28px; }
html.standalone .app-footer .footer-brand,
html.standalone .app-footer .footer-copyright { display: none; }
html.standalone .app-footer { min-height: auto; padding-top: 18px; padding-bottom: 18px; gap: 14px; }

/* Med menuen væk er der intet at bryde til linje to. Headeren skal derfor
   tilbage på ÉN linje — ellers står klublogoet alene øverst og temaknappen
   under det, med 113px tom papirflade på en 844px skærm. Reglen slår
   620px-brydningen ovenfor fra, og den gælder både spiller og admin: adminens
   syv menupunkter er nu i bunden, og det var netop dem, der krævede 526px. */
/* BUNDNAVIGATIONEN ER ET TELEFONMØNSTER og bindes derfor til bredden ovenpå
   standalone. Installerer nogen appen på en Mac — Chrome kan det — ville en
   bundlinje i 1400px bredde og en header uden menu være det forkerte svar.
   Brydepunktet er de samme 620px, headeren allerede bruger.

   HEADERENS MENU SKJULES i samme åndedrag, fordi bunden nu bærer den. DE TO
   HÆNGER SAMMEN: fjernes bundnavigationen, SKAL .app-nav-reglen fjernes i
   samme omgang — ellers står man uden nogen navigation på hjemmeskærmen.

   Og med menuen væk er der intet at bryde til linje to, så headeren sættes
   tilbage på ÉN linje: ellers står klublogoet alene øverst og temaknappen
   under det, med 113px tom papirflade på en 844px skærm. Det gælder både
   spiller og admin — adminens syv menupunkter er nu i bunden, og det var
   netop dem, der krævede 526px (det åbne punkt fra modul 03).

   Plads under indholdet, så foden ikke ender bag den faste bundlinje: tallet
   er bundlinjens egen højde og skal følges ad med .bundnav-punkt's padding. */
@media (max-width: 620px) {
  html.standalone .bundnav { display: flex; }
  html.standalone body.app { padding-bottom: calc(69px + env(safe-area-inset-bottom, 0px)); }
  html.standalone .app-nav { display: none; }
  html.standalone .app-header {
    flex-wrap: nowrap; height: 53px; min-height: 0;
    padding-top: 0; padding-bottom: 0;
  }
  html.standalone .app-header-hoejre { flex: 0 0 auto; justify-content: flex-end; }
  html.standalone .app-header .brand-logo { width: 62px; height: 38px; }
}
@media (display-mode: standalone) and (max-width: 620px) {
  .bundnav { display: flex; }
  body.app { padding-bottom: calc(69px + env(safe-area-inset-bottom, 0px)); }
  .app-nav { display: none; }
  .app-header {
    flex-wrap: nowrap; height: 53px; min-height: 0;
    padding-top: 0; padding-bottom: 0;
  }
  .app-header-hoejre { flex: 0 0 auto; justify-content: flex-end; }
  .app-header .brand-logo { width: 62px; height: 38px; }
}

/* min-height OVERSKRIVES, og det er nødvendigt: prototypens style.css har
   `footer { min-height: 170px }` på selve ELEMENTET, og .app-footer har aldrig
   sat noget imod. Foden har derfor hele tiden været 170px høj, uanset hvor
   lidt der stod i den — det var den tomme papirflade under copyrightlinjen.
   Padding alene gør ingenting, så længe min-height står. I browseren bliver de
   170px, fordi det er sådan siden ser ud i dag og på alle andre sider. */

/* Knapperækken nederst i en manual eller på regelsiden. Marginen står her og
   ikke som style="margin-top:40px" i viewet — CSP'en blokerer inline
   style-attributter, så den ville være død. Se afsnittet om inline style i
   CLAUDE.md. */
.knap-raekke-slut { margin-top: 40px; }

/* Manuallinket i app-fodens midte. Foden er papirfarvet i begge temaer og
   bruger derfor paletten direkte, ligesom header og flashbeskeder. */
.app-footer .footer-links { margin: 0; }
.app-footer .footer-links a { color: var(--marine); text-decoration: none; font-weight: 600; }
.app-footer .footer-links a:hover { text-decoration: underline; text-underline-offset: 4px; }
/* To links i foden (manualen og persondata) — luft imellem, og de brydes pænt på en smal skærm. */
.app-footer .footer-links { display: flex; flex-wrap: wrap; gap: 4px 20px; }
.microcopy a + a { margin-left: 14px; }

/* Luft omkring adminens redigeringsbokse. Stod før som style="margin-bottom:26px"
   og style="margin-top:14px" i viewene — begge døde under CSP'en. */
.advarsel-luft { margin-bottom: 26px; }
.knap-raekke-luft { margin-top: 14px; }
.data th.kol-udgave { width: 90px; }

/* --- Skærmbilleder i manualerne (modul 12) --- */

/* Billederne vises både i det offentlige layout (mørk subpage) og bag login i
   begge temaer. Rammen er derfor en neutral grå med lav dækning i stedet for en
   palettefarve — den ville kun findes i det ene tema. */
.manual-billede { margin: 26px 0; }
.manual-billede img {
  display: block; max-width: 100%; height: auto;
  border: 1px solid rgba(128, 128, 128, .35);
}
.manual-billede figcaption { margin-top: 8px; font-size: 12.5px; opacity: .75; }

/* Mangler filen, står der HVAD der mangler i stedet for et brudt billede. */
.manual-billede-mangler {
  margin: 26px 0; padding: 14px 18px; font-size: 13.5px;
  border-left: 3px solid rgba(128, 128, 128, .5); opacity: .8;
}

/* Navne inde i en .advarsel eller et .panel skal IKKE arve overskriftsstilen
   (versaler, lille skrift, spærret). Stod før som style="display:inline;…" i
   viewet og var derfor død under CSP'en — navnet brød linjen og efterlod et
   ensomt punktum bagefter. Se afsnittet om inline style i CLAUDE.md. */
.advarsel strong.tekst-inline, .panel strong.tekst-inline {
  display: inline; text-transform: none; font-size: inherit; letter-spacing: 0; color: inherit;
}
.advarsel strong.tekst-blok, .panel strong.tekst-blok {
  display: block; text-transform: none; font-size: inherit; letter-spacing: 0; color: var(--tekst);
}
