/* Praktikbooking — ét stylesheet for både admin og bookingsiden.
   Farverne ligger i custom properties, så lys/mørk kun sættes ét sted. */

:root {
  color-scheme: light dark;

  --au-blue: #003d73;
  --au-blue-dark: #002546;

  --bg: #f4f6f9;
  --surface: #ffffff;
  --surface-2: #f0f3f7;
  --border: #dbe1e9;
  --border-strong: #c3ccd8;
  --text: #16202c;
  --text-muted: #5c6b7d;
  /* Svagere end --text-muted, og med samme blålige tone som Safari giver
     pladsholderen i et tomt datofelt. Bruges kun til .ghost — se der. */
  --text-faint: #8f9cb0;
  --accent: var(--au-blue);
  --accent-text: #ffffff;
  --accent-soft: #e5eefa;
  --ok: #1c6b45;
  --ok-soft: #e2f3ea;
  --warn: #8a5300;
  --warn-soft: #fdf0da;
  --danger: #a32020;
  --danger-soft: #fbe6e6;
  --danger-line: #eec3c3;
  --shadow: 0 1px 2px rgb(16 32 48 / 6%), 0 6px 20px rgb(16 32 48 / 6%);
  --radius: 10px;
  --radius-sm: 7px;
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg: #12171d;
    --surface: #1a212a;
    --surface-2: #212a35;
    --border: #2d3946;
    --border-strong: #3d4b5a;
    --text: #e6ecf3;
    --text-muted: #9aa9b9;
    --text-faint: #6d7987;
    --accent: #5f9fe0;
    --accent-text: #0b1118;
    --accent-soft: #1e2b3b;
    --ok: #64c79b;
    --ok-soft: #172a22;
    --warn: #e0b169;
    --warn-soft: #2c2416;
    --danger: #ef8b8b;
    --danger-soft: #2e1b1b;
    --danger-line: #4d2d2d;
    --shadow: 0 1px 2px rgb(0 0 0 / 30%), 0 8px 24px rgb(0 0 0 / 30%);
  }
}

* { box-sizing: border-box; }

/* Egne display-regler (fx .topbar { display: flex }) slår browserens
   [hidden] { display: none }, så den skal sættes igen her. */
[hidden] { display: none !important; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font: 15px/1.55 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3 { line-height: 1.25; margin: 0 0 .5rem; font-weight: 650; letter-spacing: -0.01em; }
h1 { font-size: 1.4rem; }
h2 { font-size: 1.15rem; }
h3 { font-size: 1rem; }
p { margin: 0 0 .75rem; }
a { color: var(--accent); }

.muted { color: var(--text-muted); }
.small { font-size: .86rem; }
.nowrap { white-space: nowrap; }
.right { text-align: right; }
.grow { flex: 1; }
.hidden { display: none !important; }

/* ── Rammen ─────────────────────────────────────────────────────────────── */

/* Topbar og faner følger med ned, så holdvælgeren og fanerne er inden for
   rækkevidde midt i en lang liste. Højden varierer (topbaren ombryder på en
   smal skærm), så den måles i admin.js og lægges i --sticky-h; kort der selv
   skal klæbe ved, regner deres afstand ud fra den. Reserven på 6.6rem gælder
   kun det korte øjeblik før første måling. */
.stickytop {
  position: sticky;
  top: 0;
  z-index: 30;
}

.topbar {
  background: var(--au-blue-dark);
  color: #fff;
  padding: .7rem 1.25rem;
  display: flex;
  align-items: center;
  gap: 1rem;
  flex-wrap: wrap;
}
.topbar .brand { font-weight: 650; letter-spacing: -0.01em; }
.topbar .brand span { opacity: .65; font-weight: 400; }
.topbar select {
  /* width: auto frem for feltbredden på 100%, så holdvælgeren ikke skubber
     "Log ud" ned på en linje for sig. Reglen står her og ikke som en
     style-attribut, fordi CSP'en ikke tillader style-attributter. */
  width: auto;
  max-width: 20rem;
  background: rgb(255 255 255 / 12%);
  color: #fff;
  border: 1px solid rgb(255 255 255 / 22%);
}
.topbar select option { color: #16202c; }
.topbar .linkbtn { color: #fff; opacity: .8; }
.topbar .linkbtn:hover { opacity: 1; }

nav.tabs {
  display: flex;
  gap: .15rem;
  padding: 0 1rem;
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  overflow-x: auto;
}
nav.tabs button {
  appearance: none;
  background: none;
  border: 0;
  border-bottom: 2px solid transparent;
  border-radius: 0;
  padding: .8rem .85rem;
  font: inherit;
  color: var(--text-muted);
  cursor: pointer;
  white-space: nowrap;
}
nav.tabs button:hover { color: var(--text); }
nav.tabs button[aria-current="true"] { color: var(--accent); border-bottom-color: var(--accent); font-weight: 600; }

main { max-width: 1180px; margin: 0 auto; padding: 1.5rem 1rem 4rem; }
.narrow { max-width: 640px; }

/* ── Kort og felter ─────────────────────────────────────────────────────── */

.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 1.1rem 1.2rem;
  margin-bottom: 1.1rem;
  box-shadow: var(--shadow);
}
.card > :last-child { margin-bottom: 0; }
.card-head { display: flex; align-items: baseline; gap: .75rem; flex-wrap: wrap; margin-bottom: .85rem; }
.card-head h2, .card-head h3 { margin: 0; }

/* Et kort der bliver stående lige under den faste header — skabelonvælgeren på
   Mails, så man kan skifte mail uden at scrolle op igen. Den lodrette luft
   fyldes ud, så modtagerne ikke kan ses stikke frem over kanten. */
.card-sticky {
  position: sticky;
  top: calc(var(--sticky-h, 6.6rem) + .6rem);
  z-index: 5;
}
.card-sticky::before {
  content: "";
  position: absolute;
  inset: -.7rem -1px auto -1px;
  height: .7rem;
  background: var(--bg);
}

.row { display: flex; gap: .6rem; flex-wrap: wrap; align-items: center; }
.grid { display: grid; gap: .8rem; }
.grid-2 { grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); }
.grid-3 { grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); }

label { display: block; font-size: .82rem; font-weight: 600; color: var(--text-muted); margin-bottom: .28rem; }

input[type="text"], input[type="password"], input[type="email"], input[type="date"],
input[type="time"], input[type="number"], input[type="url"], input[type="tel"],
select, textarea {
  width: 100%;
  padding: .5rem .6rem;
  font: inherit;
  line-height: 1.55;
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
}
/* Alle felter på én linje skal være lige høje, og det kan hverken padding eller
   line-height klare alene: browseren tvinger `line-height: normal` på et
   <select>, og et datofelt bliver et par pixels højere end et tekstfelt på
   grund af sit eget kalenderikon. Højden regnes derfor ud af de samme tal som
   reglen ovenfor: linjehøjde + luft foroven og forneden + de to rammer. */
input[type="text"], input[type="password"], input[type="email"], input[type="date"],
input[type="time"], input[type="number"], input[type="url"], input[type="tel"], select {
  height: calc(1.55em + 1rem + 2px);
}

textarea { min-height: 8rem; resize: vertical; line-height: 1.5; }
textarea.tall { min-height: 22rem; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: .85rem; }
input:focus-visible, select:focus-visible, textarea:focus-visible, button:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}
input[type="checkbox"] { width: auto; accent-color: var(--accent); }

.field { margin-bottom: .8rem; }
.hint { font-size: .8rem; color: var(--text-muted); margin-top: .25rem; }

/* Et forslag der endnu ikke er en værdi — datoerne i praktikperioden, når
   felterne står tomme. De betyder det samme som en pladsholder: her står der
   endnu ingenting, og de gemmes ikke af sig selv. Skriften bliver almindelig,
   i det øjeblik nogen vælger eller taster en dato.

   --text-faint og ikke --text-muted: farven er valgt efter den Safari selv
   giver et tomt datofelt, som Samuel bad om at ramme. --text-muted er mørkere
   og bruges til hjælpetekst, hvor det er meningen at man skal kunne læse den
   uden at kigge efter. */
input.ghost { color: var(--text-faint); }

/* Farven skal komme fra os i begge datofelter, ellers kan de ikke ligne
   hinanden: et tomt datofelt tegner sin egen pladsholder — Safari med dagens
   dato, andre med dd.mm.åååå — i en farve browseren selv bestemmer.
   ::-webkit-datetime-edit kan ikke overskrive den; det er prøvet. Derfor får
   begge felter et forslag med .ghost på, så det er den samme regel der maler
   dem. Se SUGGESTED i students.js. */

/* Fejl under et felt. Fed frem for kun rød, så den også ses uden farvesyn —
   samme princip som statusmarkeringerne i tabellen. */
.hint.bad { color: var(--danger); font-weight: 650; }
input[aria-invalid="true"], select[aria-invalid="true"] { border-color: var(--danger); }

/* Rammer om felterne i redigeringsdialogen: én ramme pr. slags oplysning, så
   det er rammen og ikke feltets navn der siger, hvem telefonnummeret hører til.
   min-width: 0 skal med — en fieldset nægter ellers at krympe, og så bliver
   gitteret indeni bredere end dialogen. */
fieldset {
  min-width: 0;
  margin: 0 0 1rem;
  padding: .9rem 1rem .1rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface);
}
fieldset > legend {
  padding: 0 .4rem;
  margin: 0;
  font-size: .75rem;
  font-weight: 700;
  letter-spacing: .05em;
  text-transform: uppercase;
  color: var(--text-muted);
}

/* ── Knapper ────────────────────────────────────────────────────────────── */

button, .btn {
  appearance: none;
  font: inherit;
  font-weight: 550;
  padding: .48rem .85rem;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border-strong);
  background: var(--surface);
  color: var(--text);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: .4rem;
  text-decoration: none;
}
button:hover, .btn:hover { background: var(--surface-2); }
button:disabled { opacity: .5; cursor: not-allowed; }
.btn-primary { background: var(--accent); border-color: var(--accent); color: var(--accent-text); }
.btn-primary:hover { filter: brightness(1.08); background: var(--accent); }
.btn-danger { color: var(--danger); border-color: var(--danger); background: transparent; }
.btn-danger:hover { background: var(--danger-soft); }
.btn-sm { padding: .3rem .55rem; font-size: .84rem; }
.btn-quiet { border-color: transparent; background: transparent; color: var(--text-muted); }
.btn-quiet:hover { background: var(--surface-2); color: var(--text); }
.linkbtn {
  background: none; border: 0; padding: 0; color: var(--accent);
  cursor: pointer; font: inherit; text-decoration: underline; text-underline-offset: 2px;
}

/* ── Tabeller ───────────────────────────────────────────────────────────── */

/* Vandret scroll står kun i den smalle medieforespørgsel herunder, ikke her —
   se hvorfor lige nedenfor .matrix:not(.mailmatrix) thead th. */
.table-wrap { margin: 0 -1.2rem -1.1rem; padding: 0 1.2rem 1.1rem; }
table { width: 100%; border-collapse: collapse; font-size: .9rem; }
th, td { text-align: left; padding: .5rem .6rem; border-bottom: 1px solid var(--border); vertical-align: top; }
th { font-size: .78rem; text-transform: uppercase; letter-spacing: .04em; color: var(--text-muted); font-weight: 650; white-space: nowrap; }
tbody tr:hover { background: var(--surface-2); }
/* Knapperne i handlingskolonnen skal stå på linje med statusmarkeringerne, og
   ikke i toppen af en række der er tre linjer høj. */
td.actions { white-space: nowrap; text-align: right; vertical-align: middle; }

/* ── Mærkater ───────────────────────────────────────────────────────────── */

.pill {
  display: inline-block;
  padding: .1rem .48rem;
  border-radius: 999px;
  font-size: .78rem;
  font-weight: 600;
  background: var(--surface-2);
  color: var(--text-muted);
  border: 1px solid var(--border);
}
.pill-ok { background: var(--ok-soft); color: var(--ok); border-color: transparent; }
.pill-warn { background: var(--warn-soft); color: var(--warn); border-color: transparent; }
.pill-danger { background: var(--danger-soft); color: var(--danger); border-color: transparent; }
.pill-accent { background: var(--accent-soft); color: var(--accent); border-color: transparent; }

/* ── Statusmarkeringer ──────────────────────────────────────────────────────
   Grøn cirkel med flueben = på plads. Bleg firkant med et stort rødt kryds =
   mangler. De to skilles ad på tre ting på én gang — form, farve og vægt: et
   fyldt mærke over for et tonet. Derfor kan de også læses uden farvesyn, og
   hver markering har en title/aria-label med samme besked. */

.mark {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.6rem;
  height: 1.6rem;
  padding: 0;
  font-size: .95rem;
  line-height: 1;
  font-weight: 700;
  border: 1px solid transparent;
}

/* Fluebenet er det fyldte af de to: hvidt på grønt, med faste farver, fordi
   chippen har sin egen baggrund og derfor holder kontrasten i begge temaer. */
.mark-ok { background: #15704a; color: #fff; border-radius: 50%; }

/* Krydset er vendt om: bleg baggrund og selve krydset i rødt, større end
   fluebenet. Et bord med tres mættede røde firkanter er et bord af larm, og det
   man leder efter er fluebenene — så de skal være dem der fylder. Krydset
   bliver ikke svagere af det: det er stort og står 5,8:1 mod sin baggrund i lys
   visning og 6,8:1 i mørk. Farverne er temaafhængige her, netop fordi flader og
   tekst bytter plads. */
.mark-no {
  background: var(--danger-soft);
  color: var(--danger);
  border-color: var(--danger-line);
  border-radius: 4px;
  font-size: 1.2rem;
}

/* Klikbare markeringer er knapper; de statiske skal ikke se ud som noget man
   kan trykke på. */
button.mark { cursor: pointer; }
button.mark:hover { filter: brightness(1.15); }
button.mark:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.mark-static { cursor: default; }

th.col-task, td.col-task {
  text-align: center;
  vertical-align: middle;
}
/* Overskrifterne indeholder blødt bindestreg (&shy;), så "Kontaktdetaljer" må
   brydes frem for at presse de sidste kolonner ud af skærmen. Cellerne under
   dem skal stadig holde datoen på én linje. */
th.col-task { white-space: normal; max-width: 6.5rem; letter-spacing: .02em; }
td.col-task { white-space: nowrap; }

.matrix th { vertical-align: bottom; }

/* `border-collapse: collapse` (sat globalt på `table` foroven) slår
   `position: sticky` fra på th/td i flere browsere. `border-spacing: 0`
   holder cellerne lige så tætte som collapse gjorde; det er harmløst her, for
   ingen søjle har en kant der skal mødes med naboens — kun `border-bottom` er
   sat, ikke `border-top`, så der er intet at kollapse i forvejen. */
.matrix { border-collapse: separate; border-spacing: 0; }

/* Overskrifterne skal blive stående, når en lang liste scrolles ned igennem —
   ellers ved man ikke hvilken kolonne man kigger på et stykke nede. Toppen
   regnes ud af --sticky-h, samme mål som .card-sticky bruger, for headeren
   over fanerne (.stickytop) klæber selv og overskrifterne skal stoppe lige
   under den. Gælder ikke .mailmatrix: den har sin egen klæbende boks
   (skabelonvælgeren, se .card-sticky i mail.js) som allerede optager pladsen
   lige under headeren, og de to ville overlappe hinanden.

   Derfor har .table-wrap heller ikke `overflow-x: auto` her: en forfader med
   overflow sat til andet end 'visible' — også kun på x-aksen — bliver selv
   den boks som sticky regner sin top-afstand fra, i stedet for siden. Toppen
   ville så blive regnet fra kortets top og ikke fra vinduets, og overskriften
   ville hoppe et helt --sticky-h ned og ligge midt i den første række.
   Vandret scroll (til navnet der klæber til venstre, se col-name-reglen
   nedenfor) er derfor flyttet ned i den smalle medieforespørgsel, hvor den
   klæbende overskrift alligevel slås fra. */
.matrix:not(.mailmatrix) thead th {
  position: sticky;
  top: var(--sticky-h, 6.6rem);
  z-index: 2;
  background: var(--surface);
}
.tally { font-weight: 600; color: var(--text-muted); letter-spacing: 0; text-transform: none; font-size: .78rem; }
.tally.done { color: var(--ok); }
.matrix tbody td { padding-top: .55rem; padding-bottom: .55rem; }

/* Klikbare overskrifter. Knappen arver th'ets typografi, så den ser ud som en
   overskrift og ikke som en knap — men den er en knap, så tastatur og
   skærmlæser kan bruge den. */
.sorthead {
  background: none;
  border: 0;
  padding: 0;
  font: inherit;
  color: inherit;
  letter-spacing: inherit;
  text-transform: inherit;
  cursor: pointer;
  white-space: inherit;
  text-align: inherit;
}
.sorthead:hover { color: var(--text); text-decoration: underline; text-underline-offset: 3px; }
th.sortable[aria-sort="ascending"] .sorthead,
th.sortable[aria-sort="descending"] .sorthead { color: var(--accent); }

/* Den studerendes navn er indgangen til at redigere. Samme vægt som før — det
   er kun blevet klikbart. */
.namelink {
  background: none;
  border: 0;
  padding: 0;
  font: inherit;
  font-weight: 700;
  color: var(--text);
  cursor: pointer;
  text-align: left;
}
.namelink:hover { color: var(--accent); text-decoration: underline; text-underline-offset: 2px; }
.namelink:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 2px; }

/* Navnet skal blive stående, når matrixen scrolles vandret på en smal skærm —
   ellers ved man ikke hvis række man ser på. */
.matrix td.col-name, .matrix thead th:first-child {
  position: sticky;
  left: 0;
  min-width: 13rem;
  background: var(--surface);
  z-index: 1;
}
.matrix tbody tr:hover td.col-name { background: var(--surface-2); }

/* Hjørnet er klæbet både til toppen og til venstre, og skal derfor ligge over
   begge de andre lag — ellers forsvinder det bag en overskrift der scroller
   vandret ind under det. */
.matrix:not(.mailmatrix) thead th:first-child {
  z-index: 3;
}

/* Mailtabellen er den samme matrix, men kolonnerne er skabelonnavne — hele
   sætninger ("Invitation til booking af besøg") frem for de enkelte ord under
   Praktikanter. Derfor mere bredde og almindelige bogstaver; fem navne i
   versaler bliver en mur. */
.mailmatrix th.col-task {
  max-width: 9rem;
  min-width: 6rem;
  text-transform: none;
  letter-spacing: 0;
  font-size: .8rem;
}
/* Afkrydsningen til bunkemailen står sammen med navnet, ikke i en kolonne for
   sig: navnekolonnen er den der klæber ved vandret scroll, så valget følger med
   den man vælger. Feltet må ikke strækkes af flex'en. */
.pickname { display: flex; align-items: center; gap: .5rem; }
.pickname input[type="checkbox"] { flex: none; width: 1rem; height: 1rem; margin: 0; }
.pickname input[type="checkbox"]:disabled { opacity: .35; }

/* Den valgte skabelons kolonne er tonet, så det er synligt hvilken af de fem
   knappen til højre og forhåndsvisningen nedenfor handler om. */
.mailmatrix th.col-current, .mailmatrix td.col-current { background: var(--accent-soft); }

/* På Mails er overskriften to ting: navnet skifter hvilken mail der arbejdes
   med, og trekanten sorterer. De er skilt ad i hver sit klikmål, fordi de gør
   noget forskelligt — men de står sammen, fordi de handler om samme kolonne. */
.mailmatrix .sorthead.is-current { color: var(--accent); }

/* Trekanten står ved siden af tællingen på statuskolonner, og ved siden af
   skriften på dem uden. Begge steder er den lodret midtstillet. */
.headfoot {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: .2rem;
  margin-top: .1rem;
}
.headline { display: inline-flex; align-items: center; gap: .15rem; }

/* Én trekant, ikke et par. Den peger nedad, indtil der sorteres opad — så er
   hvilepositionen den samme overalt, og et klik er hele historien. Farven, ikke
   retningen, siger om det er den kolonne der sorteres på. */
.sortdir {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: none;
  border: 0;
  /* Klikmålet er sat, ikke overladt til tegnet: trekanten er smal, og en knap
     på under en halv centimeter skal rammes for præcist med musen. */
  min-width: 1.5rem;
  height: 1.4rem;
  padding: 0 .2rem;
  border-radius: 4px;
  cursor: pointer;
  color: var(--text-muted);
  opacity: .55;
  font-size: .95rem;
  line-height: 1;
}
.sortdir.on { color: var(--accent); opacity: 1; }
.sortdir:hover { background: var(--surface-2); opacity: 1; }
.sortdir:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

/* Praktikstedet fylder tre linjer (navn, vejleder, adresse) og skal have plads
   til dem frem for at brække hvert ord for sig. En adresse er længere end den
   periode der stod her før, deraf bredden. */
td.col-place { min-width: 14rem; }

/* Mailadresser og vejledernavne der åbner mailklienten, og adresser der åbner
   kortet. Prikket understregning frem for en fuld linkstyling: den røber at der
   er noget at klikke på, uden at tabellen bliver et tæppe af blå tekst. Farven
   arves, så en adresse i en muted linje bliver ved med at være dæmpet. */
.maillink, .maplink {
  color: inherit;
  text-decoration: underline dotted;
  text-underline-offset: 2px;
}
.maillink:hover, .maplink:hover { color: var(--accent); text-decoration: underline; }
.maillink:focus-visible, .maplink:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 2px; }

.legend { margin-top: .9rem; align-items: center; gap: .4rem; }
.legend .mark { width: 1.2rem; height: 1.2rem; font-size: .75rem; }

.stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: .8rem; }
.stat { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); padding: .85rem 1rem; }
.stat .n { font-size: 1.7rem; font-weight: 650; letter-spacing: -0.02em; }
.stat .l { font-size: .82rem; color: var(--text-muted); }
.stat.warn .n { color: var(--warn); }
.stat.ok .n { color: var(--ok); }

/* ── Beskeder ───────────────────────────────────────────────────────────── */

.notice { padding: .7rem .9rem; border-radius: var(--radius-sm); margin-bottom: 1rem; border: 1px solid transparent; }
.notice-info { background: var(--accent-soft); color: var(--text); border-color: var(--border); }
.notice-ok { background: var(--ok-soft); color: var(--ok); }
.notice-warn { background: var(--warn-soft); color: var(--warn); }
.notice-error { background: var(--danger-soft); color: var(--danger); }

#toasts { position: fixed; right: 1rem; bottom: 1rem; display: grid; gap: .5rem; z-index: 60; max-width: min(28rem, 92vw); }
.toast {
  background: var(--surface); border: 1px solid var(--border-strong);
  border-left: 3px solid var(--accent);
  border-radius: var(--radius-sm); padding: .6rem .85rem; box-shadow: var(--shadow);
  animation: slide-in .18s ease-out;
}
.toast.error { border-left-color: var(--danger); }
.toast.ok { border-left-color: var(--ok); }
@keyframes slide-in { from { opacity: 0; transform: translateY(6px); } }
@media (prefers-reduced-motion: reduce) { .toast { animation: none; } }

/* ── Dialog ─────────────────────────────────────────────────────────────── */

dialog {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 0;
  background: var(--surface);
  color: var(--text);
  box-shadow: var(--shadow);
  width: min(46rem, 94vw);
  max-height: 88vh;
}
dialog::backdrop { background: rgb(10 18 28 / 45%); }
dialog .dlg-head { padding: 1rem 1.2rem .4rem; }
dialog .dlg-body { padding: .5rem 1.2rem 1rem; overflow-y: auto; max-height: 62vh; }
dialog .dlg-foot {
  padding: .8rem 1.2rem; border-top: 1px solid var(--border);
  display: flex; gap: .5rem; justify-content: flex-end; flex-wrap: wrap;
  background: var(--surface-2); border-radius: 0 0 var(--radius) var(--radius);
}
dialog .dlg-foot .grow { flex: 1; }

/* ── Kalender / tider ───────────────────────────────────────────────────── */

.daylist { display: grid; gap: .7rem; }
.day {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  overflow: hidden;
}
.day-head {
  padding: .55rem .85rem;
  background: var(--surface-2);
  border-bottom: 1px solid var(--border);
  display: flex; align-items: center; gap: .6rem; flex-wrap: wrap;
  font-weight: 600;
}
.day-head .muted { font-weight: 400; }

/* Ugenummer ved en dato. Dæmpet, så datoen stadig læses først. */
.weekpill {
  font-size: .78rem;
  font-weight: 500;
  color: var(--text-muted);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: .05rem .45rem;
  white-space: nowrap;
}

/* ── Månedsoversigten i "Opret tider" ───────────────────────────────────── */

.monthgrid { table-layout: fixed; }
.monthgrid th { text-align: center; padding: .2rem; }
.monthgrid td { padding: 1px; border-bottom: 0; }

/* Ugenumrene står i deres egen smalle kolonne til venstre, adskilt af en
   streg så de ikke forveksles med datoerne. */
.monthgrid .weekno {
  width: 2.4rem;
  text-align: right;
  padding-right: .5rem;
  font-size: .78rem;
  font-variant-numeric: tabular-nums;
  color: var(--text-muted);
  border-right: 1px solid var(--border);
}
.monthgrid th.weekno { text-transform: none; letter-spacing: 0; font-weight: 500; }
.slotrow {
  display: flex; align-items: center; gap: .7rem; flex-wrap: wrap;
  padding: .55rem .85rem;
  border-bottom: 1px solid var(--border);
}
.slotrow:last-child { border-bottom: 0; }
.slotrow .time { font-variant-numeric: tabular-nums; font-weight: 600; min-width: 6.6rem; }
.slotrow.taken { background: var(--surface-2); }
.slotrow.closed { opacity: .6; }

/* Bookingsidens tidsknapper */
.slotgrid { display: grid; grid-template-columns: repeat(auto-fill, minmax(11rem, 1fr)); gap: .5rem; padding: .7rem .85rem; }
.slotpick {
  display: flex; flex-direction: column; align-items: flex-start; gap: .1rem;
  padding: .6rem .7rem; text-align: left; width: 100%;
  border: 1px solid var(--border-strong); border-radius: var(--radius-sm);
  background: var(--surface); cursor: pointer;
}
.slotpick .t { font-weight: 650; font-variant-numeric: tabular-nums; }
.slotpick .s { font-size: .8rem; color: var(--text-muted); }
.slotpick:hover:not(:disabled) { border-color: var(--accent); background: var(--accent-soft); }
.slotpick:disabled { cursor: not-allowed; background: var(--surface-2); color: var(--text-muted); border-style: dashed; }
.slotpick.mine { border-color: var(--ok); background: var(--ok-soft); color: var(--ok); }

/* ── Kortet ─────────────────────────────────────────────────────────────── */

/* Kort til venstre, liste til højre. Under 900 px er der ikke plads til to
   spalter, og så lægger listen sig under kortet. */
.mapsplit {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(15rem, 20rem);
  gap: 1rem;
  align-items: start;
}
@media (max-width: 900px) {
  .mapsplit { grid-template-columns: 1fr; }
}

.map {
  position: relative;
  overflow: hidden;
  /* min-height er et gulv: i et lavt vindue ville 64vh give et kort på et par
     centimeter, og der er ingen grund til at tegne et kort man ikke kan se noget
     på. */
  height: min(64vh, 34rem);
  min-height: 22rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  /* Baggrunden ses hvor fliserne endnu ikke er hentet, og i havet i kanterne. */
  background: var(--surface-2);
  cursor: grab;
  touch-action: none;      /* ellers scroller siden når man trækker på en telefon */
  user-select: none;
}
.map.dragging { cursor: grabbing; }
.map:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.map-layer { position: absolute; inset: 0; }
.map-pins { pointer-events: none; }

.map-tile {
  position: absolute;
  /* Fliserne støder op til hinanden; en brøkdels pixel imellem giver et gitter
     af lyse streger hen over kortet. */
  outline: .5px solid transparent;
  -webkit-user-drag: none;
}

/* Nålen står med spidsen på koordinatet. Dråbeformen er et kvadrat med tre
   runde hjørner, drejet en ottendedel omgang, så det fjerde hjørne peger nedad.
   .32rem er hvor langt det hjørne stikker ud under kassen efter drejningen —
   uden den korrektion ville nålen pege lidt under det rigtige sted. */
.map-pin {
  position: absolute;
  pointer-events: auto;
  transform: translate(-50%, calc(-100% - .32rem));
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
  line-height: 0;
}
.map-pin-dot {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 1.55rem;
  height: 1.55rem;
  border-radius: 50% 50% 50% 0;
  transform: rotate(-45deg);
  background: var(--au-blue);
  border: 2px solid #fff;
  box-shadow: 0 1px 4px rgb(0 0 0 / 35%);
}
/* Nummeret drejes tilbage, så det står ret op i den drejede dråbe. */
.map-pin-no {
  transform: rotate(45deg);
  color: #fff;
  font-size: .74rem;
  font-weight: 700;
  line-height: 1;
}
.map-pin:hover .map-pin-dot { background: var(--au-blue-dark); }
.map-pin.picked { z-index: 2; }
.map-pin.picked .map-pin-dot { background: var(--danger); }
.map-pin:focus-visible .map-pin-dot { outline: 2px solid var(--accent); outline-offset: 2px; }

.map-zoom { position: absolute; top: .5rem; right: .5rem; display: grid; gap: .25rem; }
.map-btn {
  width: 2rem; height: 2rem; padding: 0;
  justify-content: center;
  font-size: 1.1rem; font-weight: 700; line-height: 1;
  background: var(--surface);
  box-shadow: 0 1px 3px rgb(0 0 0 / 25%);
}

/* OpenStreetMaps vilkår kræver at ophavsmanden nævnes på kortet. */
.map-credit {
  position: absolute;
  right: 0; bottom: 0;
  padding: .05rem .35rem;
  font-size: .7rem;
  background: rgb(255 255 255 / 78%);
  border-radius: var(--radius-sm) 0 0 0;
}
.map-credit a { color: #16202c; text-decoration: none; }
.map-credit a:hover { text-decoration: underline; }

.maplist {
  display: grid;
  gap: .25rem;
  /* Følger kortets højde, så de to spalter flugter. */
  max-height: max(22rem, min(64vh, 34rem));
  overflow-y: auto;
}
.maprow {
  display: flex;
  gap: .55rem;
  align-items: flex-start;
  width: 100%;
  text-align: left;
  padding: .45rem .55rem;
  border-color: transparent;
  background: none;
  font-weight: inherit;
}
.maprow:hover { background: var(--surface-2); }
.maprow.picked { background: var(--accent-soft); border-color: var(--accent); }
.mapnum {
  flex: none;
  display: inline-flex; align-items: center; justify-content: center;
  width: 1.5rem; height: 1.5rem;
  border-radius: 50%;
  background: var(--au-blue);
  color: #fff;
  font-size: .74rem; font-weight: 700;
}
.maprow.picked .mapnum { background: var(--danger); }
.maprow-more { padding: 0 .55rem .5rem 2.65rem; }

/* Hvem der mangler en adresse. Listen skal kunne løbes igennem, ikke pyntes. */
.maplacking { margin: .5rem 0 0; padding-left: 1.2rem; }
.maplacking li { margin-bottom: .1rem; }

/* ── Bookingsiden ───────────────────────────────────────────────────────── */

.book-page { max-width: 46rem; margin: 0 auto; padding: 1.5rem 1rem 4rem; }
.book-head { background: var(--au-blue-dark); color: #fff; padding: 1.4rem 1rem; }
.book-head .inner { max-width: 46rem; margin: 0 auto; }
.book-head h1 { margin: 0 0 .2rem; }
.book-head .sub { opacity: .78; }

.confirmed {
  border: 1px solid var(--ok);
  background: var(--ok-soft);
  border-radius: var(--radius);
  padding: 1rem 1.15rem;
  margin-bottom: 1.1rem;
}
.confirmed .when { font-size: 1.2rem; font-weight: 650; color: var(--ok); }

.checklist { list-style: none; padding: 0; margin: 0; display: grid; gap: .3rem; }
.checklist li { display: flex; gap: .5rem; align-items: baseline; }

.spinner {
  width: 1rem; height: 1rem; border-radius: 50%;
  border: 2px solid var(--border-strong); border-top-color: var(--accent);
  animation: spin .7s linear infinite; display: inline-block;
}
@keyframes spin { to { transform: rotate(360deg); } }

footer.page-foot { max-width: 1180px; margin: 0 auto; padding: 0 1rem 2rem; color: var(--text-muted); font-size: .82rem; }

@media (max-width: 640px) {
  /* Vandret scroll hører kun til her — se .matrix:not(.mailmatrix) thead th
     foroven for hvorfor den ikke står ubetinget på .table-wrap. Den klæbende
     overskrift slås fra i samme ombæring: en forfader med overflow-x sat
     ville ellers gøre den til sin egen sticky-beholder og flytte
     overskriften ned midt i den første række. */
  .table-wrap { overflow-x: auto; margin: 0 -1.2rem -1.1rem; }
  .matrix:not(.mailmatrix) thead th { position: static; }
  .topbar { padding: .6rem .8rem; }
  main { padding: 1rem .8rem 3rem; }
}

@media print {
  .topbar, nav.tabs, .noprint, button { display: none !important; }
  /* Klæbende elementer bliver hængende på hver side i et print. */
  .stickytop, .card-sticky, .matrix thead th { position: static; }
  .card-sticky::before { display: none; }
  body { background: #fff; }
  .card { box-shadow: none; border-color: #ccc; break-inside: avoid; }
}
