/* ============================================================
   Tørst Cocktailbar — POS designsystem
   Mørkt, touchoptimeret, høj kontrast, dansk.
   ============================================================ */

:root {
  /* Baggrunde — mørk neutral, ikke sort */
  --bg-0: #0b0d10;   /* dybeste baggrund */
  --bg-1: #101215;   /* app-baggrund */
  --bg-2: #171a1f;   /* kort */
  --bg-3: #1e222a;   /* forhøjet kort / input */
  --bg-4: #272c36;   /* hover / aktiv flade */
  --bg-5: #333944;   /* kant-flade */

  /* Streger */
  --line-1: #2a2f39;
  --line-2: #3a4150;
  --line-strong: #525c6e;

  /* Tekst */
  --tx-1: #f2f5f9;   /* primær */
  --tx-2: #b6bfcd;   /* sekundær */
  /* ------------------------------------------------------------
     DAEMPET — MEN STADIG LAESBAR PAA HUSETS LYSESTE FLADE

     Den gamle vaerdi gav 5,12:1 paa den moerkeste bund og
     **4,35:1** paa den lyseste — og husets krav er 4,5. Alt, hvad
     der er `muted`, faldt derfor igennem inde i en dialog, hvor
     bunden er lysere end fladen udenfor.

     Maalt 1. september 2026 tre steder, foer det gik op for mig,
     at det var det samme token hver gang: felttekster
     («Bordnummer eller klokkeslæt»), rollenavne («Restaurantleder»
     under Overdrag bord) og forklaringer i menuerne.

     Lysnet lige nok: 4,65 paa den lyseste, 5,47 paa den moerkeste.
     Forskellen paa den gamle og den nye er ikke til at se med det
     blotte oeje — det er forskellen paa at bestaa og ikke.
     ------------------------------------------------------------ */
  --tx-3: #818b9e;   /* dæmpet */
  --tx-inv: #0b0d10; /* på lyse flader */

  /* Handlingsfarver */
  --orange: #ff7a1a;      /* primære ordrehandlinger */
  --orange-dk: #d95f06;
  --orange-soft: rgba(255, 122, 26, 0.16);
  /* Orange TEKST. Paa en moerk grund er den husets orange; paa en
     lys grund overstyrer temaet den, fordi 4,44 : 1 ikke er nok
     til normal tekst. Se `--orange-tx` i data/theme.js. */
  --orange-tx: #ff7a1a;
  --green: #22b562;       /* betaling */
  --green-dk: #16904a;
  --green-soft: rgba(34, 181, 98, 0.16);

  /* Status / opmærksomhed */
  --at-normal: #3a4150;
  --at-soon: #e8c020;     /* gul */
  --at-late: #f28c1c;     /* orange */
  --at-critical: #e5484d; /* rød */

  --blue: #3f8cff;
  --purple: #9d6bff;

  /* Bordplanens materialer. De skal kunne kendes fra hinanden på
     en meters afstand — ikke være pæne. */
  --plan-trae:   #6b4a2f;
  --plan-flise:  #3a3d42;
  --plan-taeppe: #4a3540;
  --plan-vand:   #1e3a5f;
  --plan-graes:  #2c4a2c;
  --plan-vaeg:   #55585e;
  --plan-bar:    #5a2230;
  --plan-sofa:   #6d6350;
  --plan-groen:  #2f6b3f;
  --plan-moerk:  #14161a;
  --red: #e5484d;
  --red-dk: #b83236;
  --yellow: #e8c020;

  /* Radius */
  --r-sm: 8px;
  --r-md: 12px;
  --r-lg: 16px;
  --r-xl: 22px;

  /* Touch */
  --touch-min: 44px;
  --touch: 56px;
  --touch-lg: 68px;

  /* Afstand */
  --sp-1: 4px;
  --sp-2: 8px;
  --sp-3: 12px;
  --sp-4: 16px;
  --sp-5: 24px;
  --sp-6: 32px;

  --shadow-1: 0 1px 2px rgba(0,0,0,.4);
  --shadow-2: 0 6px 20px rgba(0,0,0,.45);
  --shadow-3: 0 18px 50px rgba(0,0,0,.6);

  /* ============================================================
     ACCENT — ET NAVN, DER ALDRIG BLEV SAT

     ------------------------------------------------------------
     DET, DER VAR GALT

     61 regler i denne fil bruger `var(--accent)`, og temaet har
     aldrig defineret den. En ugyldig værdi gør hele erklæringen
     ugyldig, og reglen falder bort uden en lyd.

     Målt 31. august 2026 i browseren: `--accent` var tom på
     `html`, `body`, `#root` og på selve elementet. Det, der ikke
     virkede, var blandt andet
       · `.input:focus` og `.bfelt__input:focus` — fokusrammen
         på hvert eneste skrivefelt i huset
       · `.kbd__key:active`, `.funk:active`, `.linjeknap:active`
         — kvitteringen for, at tasten blev ramt
       · `.linjeknap--plus` — plusknappens kant og farve

     En tjener, der taster en kode og ikke kan se, hvilket felt
     hun står i, taster den i det forkerte.

     ------------------------------------------------------------
     HVORFOR HER OG IKKE I TEMAET

     Husets regel er, at farver hører i `data/theme.js` og ikke
     skrives i hånden her (se `.pv__afsend`). Det er stadig sandt:
     der står ingen farve nedenfor. Der står et SYNONYM, som
     peger på temaets egne to værdier — accenten er `--orange`,
     og teksten oven på den er `--tx-inv`, som temaet selv
     beskriver med «Oven på orange og grøn».

     Lagdes de i temaet i stedet, ville huset få to farvevælgere
     for den samme farve, og de ville før eller siden komme til
     at sige noget forskelligt.
     ============================================================ */
  --accent: var(--orange);
  --accent-tx: var(--tx-inv);
  --accent-svag: color-mix(in srgb, var(--orange) 32%, transparent);

  /* ---- Afledte farver ----
     Sættes automatisk ud fra hovedfarverne, når temaet ændres.
     Står her, så systemet også virker uden JavaScript og så man
     kan se hvad standardværdien er. */
  --orange-lt: #ff8c38;    /* orange, lysere — når man holder på knappen */
  --green-lt: #2ccb70;
  --red-lt: #ef5d61;
  /* ------------------------------------------------------------
     ROED SOM TEKST — IKKE SOM FLADE

     `--red` er en god FLADE: den raaber, og den er husets farve
     for fare. Som TEKST paa en moerk bund er den for moerk.
     Maalt 1. september 2026: «Slet» og «Luk bord» i menuen stod
     paa 4,07:1, og husets krav er 4,5.

     Den her er den samme roede, lysnet lige nok. Farven er stadig
     tydeligt roed — den er bare til at laese. Skifter `--red`,
     foelger den med.
     ------------------------------------------------------------ */
  --red-tekst: color-mix(in srgb, var(--red) 85%, white);

  --tx-on-danger: #ffffff; /* tekst på rød */
  --tx-on-accent: #ffffff; /* tekst på husets farve */
  /* ------------------------------------------------------------
     GUL ER LYS I ALLE TEMAER — OGSÅ DET LYSE

     `--tx-inv` betyder «tekst på farve», og hint'et i temaeditoren
     siger hvilke: «Oven på orange og grøn». På et lyst tema vender
     den til hvid, fordi orange og grøn dér er blevet mørke nok til
     at bære hvid tekst.

     Gul blev ikke mørk nok. Det lyse temas gul er #b98d00, og hvid
     på den er 3,06 : 1. VENT-chippen er 11,5 px — kravet er 4,5.
     Chippen, der siger at en bon holdes tilbage, var den eneste
     tekst på skærmen, man ikke kunne læse.

     Målt 6. september 2026 med husets egen kontrastmåler:

       tema             --tx-inv på gul   #0b0d10 på gul
       mørk (standard)          11,11           11,11
       lyst                      3,06            6,37
       sort / høj               14,75           14,75
       blå                      10,72           11,11

     Gul bærer mørk tekst i ALLE fire. Derfor sit eget navn — samme
     løsning som `--tx-on-danger`, og af samme grund: et token, der
     betyder «på orange og grøn», kan ikke også betyde «på gul».
     ------------------------------------------------------------ */
  --tx-on-yellow: #0b0d10; /* tekst på gul */

  /* Statusfarver — chippens fyld, tekst og kant */
  --st-ledigt: #7c869a;
  --st-optaget: #3f8cff;
  --st-betaler: #9d6bff;
  --st-klargoeres: #e8c020;
  --st-ledigt-tx: #a6b0c2;
  --st-optaget-tx: #7fb0ff;
  --st-service-tx: #ffa963;
  --st-betaler-tx: #bd9bff;
  --st-betalt-tx: #5fd694;
  --st-klargoeres-tx: #e8c020;
  --st-ledigt-bg: rgba(124, 134, 154, 0.16);
  --st-optaget-bg: rgba(63, 140, 255, 0.16);
  --st-betaler-bg: rgba(157, 107, 255, 0.16);
  --st-klargoeres-bg: rgba(232, 192, 32, 0.16);
  --red-soft: rgba(229, 72, 77, 0.14);

  --tx-neg: #ff9aa0;       /* fravalg og fejl i en linje */

  /* ------------------------------------------------------------
     RØD SOM TEKST ER IKKE RØD SOM FLADE

     `--red` er husets røde fyld: den bærer hvid tekst på en knap
     og en kant om noget, der er gået galt. Bruges den SOM tekst
     på en mørk flade, er den for mørk til at læse.

     Målt 30. august 2026 på «Slet» i funktionsblokken:
     4,07 : 1 i det mørke tema, 3,55 : 1 i Skagen. WCAG AA vil
     have 4,5 : 1.

     Derfor et eget token til den røde TEKST. Fladen er urørt.
     ------------------------------------------------------------ */
  --red-tx: #ff8085;
  --tx-pos: #7fd6a3;       /* tilvalg */

  --toast-ok-bg: #14361f;    --toast-ok-tx: #8ee5b3;
  --toast-warn-bg: #3a2f08;  --toast-warn-tx: #f4dd85;
  --toast-error-bg: #3a1416; --toast-error-tx: #ffb0b3;

  --banner-noed-1: #5a1e00;  --banner-noed-2: #6b2400;  --banner-noed-tx: #ffd7b3;
  --banner-lukket-1: #4a0d16; --banner-lukket-2: #5c1119; --banner-lukket-tx: #ffd0d6;

  --giftcard-1: #1b1f27;   --giftcard-2: #2a2130;

  --font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --mono: ui-monospace, "SF Mono", "Cascadia Mono", Menlo, Consolas, monospace;
}

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

html, body {
  margin: 0;
  padding: 0;
  height: 100%;
  overflow: hidden;
  overscroll-behavior: none;
}

body {
  font-family: var(--font);
  background: var(--bg-1);
  color: var(--tx-1);
  font-size: 16px;
  line-height: 1.35;
  -webkit-font-smoothing: antialiased;
  -webkit-tap-highlight-color: transparent;
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  touch-action: manipulation;
}

button, input, select, textarea { font: inherit; color: inherit; }
button { cursor: pointer; border: none; background: none; }

/* Ingen tekstmarkering i POS-flader — undgår utilsigtet markering ved hurtige tryk */
.app-root { user-select: none; -webkit-user-select: none; }
.selectable { user-select: text; -webkit-user-select: text; }

/* ============================================================
   APPENS BOKS ER DEN, LAYOUTET SKAL SPØRGE

   ------------------------------------------------------------
   DET, DER VAR GALT

   Tredive `@media`-regler spurgte BROWSERVINDUET, hvor stor
   skærmen var. Motoren regner på appens egen flade, og de to er
   ikke det samme, så snart nogen prøvekører et andet format.

   Målt 31. august 2026: en prøveflade på 393 x 852 fik motorens
   bånd til at skifte til «smal», mens hver eneste `@media`-regel
   blev ved med at tro, at skærmen var 1024 bred. Bordplanen så
   derfor rigtig ud i målingen og forkert på en telefon — og
   omvendt. En prøve, der kan sige begge dele, er ingen prøve.

   ------------------------------------------------------------
   RETTELSEN

   `#root` er en STØRRELSESCONTAINER, og reglerne spørger den i
   stedet. I drift er de to det samme — `.app-root` er `fixed;
   inset: 0` og fylder vinduet — så der ændrer sig ingenting.
   Under en prøveflade følger de med, og det, der måles, er det,
   der vises.

   Tilbage som `@media` står kun to ting, og med vilje:
   `:root`-tokens (`html` er containerens forfader og kan ikke
   spørge den) og modalerne (de hænger på `body`, fordi skallens
   `mount` ellers ville slette dem ved hver optegning — se
   «MODALEN HAENGER PÅ `body`» i `modal.js`).
   ------------------------------------------------------------ */
.app-root {
  container-type: size;
  container-name: pos;
}

/* ---------- Approot: fuld højde, safe-area ---------- */
.app-root {
  position: fixed;
  inset: 0;
  height: 100dvh;
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  min-width: 0;
  background: var(--bg-1);
  padding-top: env(safe-area-inset-top);
  padding-left: env(safe-area-inset-left);
  padding-right: env(safe-area-inset-right);
}

/* Finansafstemningsbjælken (#finans-bar, src/core/finansalarm.js) ligger fast i bunden og fortæller sin højde i `--finans-bar-h`
   (og klassen `har-finans-bar` på <body>). Appen trækker højden fra, så bjælken står UNDER siden og ikke dækker nogen handling.
   Den ligger over «lukket lager»-bjælken (`--lukket-bar-h`), som den også tager højde for. */
body.har-finans-bar .app-root {
  bottom: calc(var(--finans-bar-h, 0px) + var(--lukket-bar-h, 0px));
  height: calc(100dvh - var(--finans-bar-h, 0px) - var(--lukket-bar-h, 0px));
  min-height: 0;
}

/* Alle flex/grid-kolonner der indeholder scroll skal have min-height:0 */
.col, .row { display: flex; min-width: 0; min-height: 0; }
.col { flex-direction: column; }
.row { flex-direction: row; }
.flex-1 { flex: 1 1 auto; min-width: 0; min-height: 0; }
.flex-0 { flex: 0 0 auto; }

.scroll-y {
  overflow-y: auto;
  overflow-x: hidden;
  min-height: 0;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: thin;
  scrollbar-color: var(--line-2) transparent;
}
/* ============================================================
   Stak — lodret indhold der ALDRIG kan klemmes sammen

   .col er flex, og flex-børn kan krympe under deres eget indhold.
   Til lange, rullende sider er det den forkerte grundform: så
   snart indholdet bliver højere end skærmen, skrumper afsnittene
   og teksten lægger sig oven i hinanden.

   .stack er almindeligt block-layout med afstand imellem. Block
   kan ikke krympe børn. Brug .stack til alt der ruller, og .col
   til lag hvor noget SKAL fordele pladsen.
   ============================================================ */
.stack { display: block; }
.stack > * + * { margin-top: var(--sp-4); }
.stack-1 > * + * { margin-top: var(--sp-1); }
.stack-2 > * + * { margin-top: var(--sp-2); }
.stack-3 > * + * { margin-top: var(--sp-3); }
.stack-1, .stack-2, .stack-3 { display: block; }

/* Lange etiketter må ombryde i stedet for at skubbe beløbet ud */
/*
   Et område der kun VISER hvordan noget ser ud. Der kan ikke
   trykkes på noget inde i det, så der opstår ingen døde knapper.
*/
.demo, .demo * { pointer-events: none; user-select: none; }

.total-line > :first-child { min-width: 0; overflow-wrap: anywhere; }
.total-line > :last-child { flex: 0 0 auto; white-space: nowrap; }

/*
   Indhold i et rullende område må ALDRIG klemmes sammen.

   .col og .row sætter min-height: 0, så et flex-barn KAN krympe
   under sit eget indhold. Er det rullende område samtidig et
   flex-layout med begrænset højde, sker det: afsnittene skrumper,
   og teksten lægger sig oven i hinanden i stedet for at rulle.
   Her slås krympningen fra, så området ruller som det skal.
*/
.scroll-y > * { flex-shrink: 0; }

.scroll-y::-webkit-scrollbar { width: 10px; }
.scroll-y::-webkit-scrollbar-thumb { background: var(--line-2); border-radius: 6px; }
.scroll-y::-webkit-scrollbar-track { background: transparent; }

/* ============================================================
   Topbar
   ============================================================ */
.topbar {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  height: 60px;
  padding: 0 var(--sp-4);
  background: var(--bg-2);
  border-bottom: 1px solid var(--line-1);
}
/* Husets navn er en knap ind til Systeminfo. Den skal se ud
   præcis som før — browserens knap-standarder nulstilles derfor,
   og kun trykfladen er ny. */
.topbar__brand {
  appearance: none;
  -webkit-appearance: none;
  background: none;
  border: 0;
  margin: 0;
  padding: var(--sp-1) var(--sp-2);
  margin-left: calc(var(--sp-2) * -1);
  /* En tast, en tommelfinger skal ramme, skal være mindst 44 px.
     Topbaren er 54–60 px høj, så den fulde højde er der. */
  min-height: var(--touch-min);
  display: flex;
  flex-direction: column;
  justify-content: center;
  border-radius: var(--r-sm);
  color: inherit;
  font-family: inherit;
  text-align: left;
  cursor: pointer;
  min-width: 0;
  font-weight: 700;
  font-size: 15px;
  letter-spacing: .2px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* Baade navnet og enhedsnavnet forkortes hver for sig. Uden det
   klipper flexbeholderen dem uden ellipsis — se «NAVNET I SIT
   EGET ELEMENT» i shell.js. */
.topbar__navn,
.topbar__brand small {
  display: block;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.topbar__brand small {
  display: block;
  font-weight: 500;
  font-size: 11px;
  color: var(--tx-3);
  letter-spacing: .6px;
  text-transform: uppercase;
}
.topbar__brand:hover { background: var(--bg-3); }
.topbar__brand:active { background: var(--bg-4); }
.topbar__brand:focus-visible { outline: 2px solid var(--blue); outline-offset: 1px; }

.topbar__spacer { flex: 1 1 auto; min-width: 0; }

/* ============================================================
   Knapper
   ============================================================ */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  min-height: var(--touch);
  min-width: var(--touch-min);
  padding: 0 var(--sp-4);
  border-radius: var(--r-md);
  background: var(--bg-3);
  color: var(--tx-1);
  font-weight: 600;
  font-size: 15px;
  border: 1px solid var(--line-1);
  transition: background .12s, transform .06s, border-color .12s;
  text-align: center;
  white-space: nowrap;
}
.btn:hover:not(:disabled) { background: var(--bg-4); }
.btn:active:not(:disabled) { transform: scale(.975); }
.btn:disabled { opacity: .38; cursor: not-allowed; }
.btn:focus-visible { outline: 3px solid var(--blue); outline-offset: 2px; }

.btn--lg { min-height: var(--touch-lg); font-size: 17px; padding: 0 var(--sp-5); }
.btn--sm { min-height: var(--touch-min); font-size: 14px; padding: 0 var(--sp-3); border-radius: var(--r-sm); }
.btn--block { display: flex; width: 100%; }

/* Primær ordrehandling — orange */
.btn--primary {
  background: var(--orange);
  border-color: var(--orange);
  color: var(--tx-inv);
  font-weight: 800;
}
.btn--primary:hover:not(:disabled) { background: var(--orange-lt); border-color: var(--orange-lt); }
.btn--primary:active:not(:disabled) { background: var(--orange-dk); border-color: var(--orange-dk); }

/* Betaling — grøn */
.btn--pay {
  background: var(--green);
  border-color: var(--green);
  color: var(--tx-inv);
  font-weight: 800;
}
.btn--pay:hover:not(:disabled) { background: var(--green-lt); border-color: var(--green-lt); }
.btn--pay:active:not(:disabled) { background: var(--green-dk); border-color: var(--green-dk); }

/* Fare */
/* ------------------------------------------------------------
   HVID PAA ROED ER 3,91:1

   Maalt 1. september 2026 paa «Fjern» i linjedialogen. Husets
   krav er 4,5 for tekst i den stoerrelse.

   Fladen moerknes til `--red-dk`, som huset allerede har og
   allerede bruger som knappens :active — saa der kommer ingen ny
   farve ind i huset. Hvid paa den er 5,92:1.
   ------------------------------------------------------------ */
.btn--danger { background: var(--red-dk); border-color: var(--red-dk); color: var(--tx-on-danger); font-weight: 700; }
.btn--danger:hover:not(:disabled) { background: var(--red); border-color: var(--red); }
.btn--danger:active:not(:disabled) { background: var(--red-dk); border-color: var(--red-dk); filter: brightness(.9); }

/* Ghost / sekundær */
/* ------------------------------------------------------------
   «NEJ TAK» — MINDRE OG RØD, MEN IKKE EN ADVARSEL

   Dennis, 1. september 2026: «stor grøn knap, eller mindre rød for
   nej tak».

   Ikke `--danger`: den er fyldt rød og er husets ord for «det her
   sletter noget». At sige nej til en kvittering sletter ingenting.

   Kant og rød tekst i stedet — samme sprog som «Luk bord» i
   AFSLUT-arket. Den er tydeligt den anden vej, uden at være en
   advarsel. `--red-tekst` og ikke `--red`, fordi husets røde er
   lavet til at ligge UNDER hvid tekst, ikke til at være tekst selv.
   ------------------------------------------------------------ */
.btn--nejtak {
  background: transparent;
  border-color: var(--red);
  color: var(--red-tekst);
  font-weight: 700;
}
.btn--nejtak:hover:not(:disabled) { background: var(--red-soft); }
.btn--nejtak:active:not(:disabled) { background: var(--red-dk); color: var(--tx-on-danger); }

.btn--ghost { background: transparent; border-color: var(--line-2); color: var(--tx-2); }
.btn--ghost:hover:not(:disabled) { background: var(--bg-3); color: var(--tx-1); }

/* Aktivt valg */
.btn--on {
  background: var(--orange-soft);
  border-color: var(--orange);
  color: var(--orange);
}

/* VENT-tilstand */
.btn--wait-on {
  background: var(--yellow);
  border-color: var(--yellow);
  color: var(--tx-inv);
  font-weight: 800;
  animation: waitpulse 1.6s ease-in-out infinite;
}
@keyframes waitpulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(232,192,32,.55); }
  50%      { box-shadow: 0 0 0 8px rgba(232,192,32,0); }
}

/* ============================================================
   Kort
   ============================================================ */
.card {
  background: var(--bg-2);
  border: 1px solid var(--line-1);
  border-radius: var(--r-lg);
  padding: var(--sp-4);
}
.card--flat { background: var(--bg-3); }

/* ============================================================
   Chips
   ============================================================ */
.chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 24px;
  padding: 0 10px;
  border-radius: 999px;
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: .4px;
  text-transform: uppercase;
  white-space: nowrap;
  border: 1px solid transparent;
}
.chip--sm { height: 20px; font-size: 10.5px; padding: 0 8px; }

/* Primær bordstatus */
.chip--ledigt     { background: var(--st-ledigt-bg);     color: var(--st-ledigt-tx);     border-color: var(--st-ledigt); }
.chip--optaget    { background: var(--st-optaget-bg);    color: var(--st-optaget-tx);    border-color: var(--st-optaget); }
.chip--service    { background: var(--orange-soft);      color: var(--st-service-tx);    border-color: var(--orange); }
.chip--betaler    { background: var(--st-betaler-bg);    color: var(--st-betaler-tx);    border-color: var(--st-betaler); }
.chip--betalt     { background: var(--green-soft);       color: var(--st-betalt-tx);     border-color: var(--green); }
.chip--klargoeres { background: var(--st-klargoeres-bg); color: var(--st-klargoeres-tx); border-color: var(--st-klargoeres); }

/* Servicefase — dæmpet, mindre */
.chip--phase {
  background: var(--bg-4);
  color: var(--tx-2);
  border-color: var(--line-2);
  text-transform: none;
  letter-spacing: 0;
  font-weight: 600;
}

/* VENT-markering */
.chip--vent { background: var(--yellow); color: var(--tx-on-yellow); border-color: var(--yellow); }
.chip--kaldt { background: var(--orange); color: var(--tx-inv); border-color: var(--orange); }
/* Hvid paa `--red` er 3,91:1, og chippen er lille tekst — kravet
   er 4,5. `--red-dk` giver 5,92 og er husets egen. Se «HVID PAA
   ROED ER 3,91:1» ved `.btn--danger`. Det her er den chip, der
   siger «Kan ikke sælge»; den maa vaere den mest laesbare paa
   skaermen, ikke den mindst. */
.chip--allergi { background: var(--red-dk); color: var(--tx-on-danger); border-color: var(--red-dk); }

/* ============================================================
   Bordkort — neutralt kort + opmærksomhedsramme
   ============================================================ */
.tablecard {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-height: 118px;
  padding: 10px 12px;
  background: var(--bg-2);
  border: 2px solid var(--at-normal);
  border-radius: var(--r-lg);
  text-align: left;
  transition: border-color .2s, background .12s, transform .06s;
}
.tablecard:active { transform: scale(.98); }
.tablecard:hover { background: var(--bg-3); }
.tablecard:focus-visible { outline: 3px solid var(--blue); outline-offset: 2px; }

.tablecard--free { background: var(--bg-1); border-style: dashed; border-color: var(--line-1); }
.tablecard--free .tablecard__no { color: var(--tx-2); }

/* Opmærksomhedsniveau — kun rammen, kortet forbliver læsbart */
.tablecard--soon     { border-color: var(--at-soon); }
.tablecard--late     { border-color: var(--at-late); }
.tablecard--critical { border-color: var(--at-critical); animation: critpulse 2s ease-in-out infinite; }
@keyframes critpulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(229,72,77,.5); }
  50%      { box-shadow: 0 0 0 6px rgba(229,72,77,0); }
}

.tablecard__no {
  font-size: 26px;
  font-weight: 800;
  line-height: 1;
  letter-spacing: -.5px;
  font-variant-numeric: tabular-nums;
}
.tablecard__meta { font-size: 12px; color: var(--tx-3); line-height: 1.3; }
/* Bookingen paa listekortet. Samme tre farver som figurens
   `pv__bookingmaerke`, saa plan og liste laeses ens — og aldrig
   KUN farve: klokkeslaettet staar i teksten. */
.tablecard__booking { font-weight: 700; }
.tablecard__booking--booket    { color: var(--blue); }
.tablecard__booking--forsinket { color: var(--red); }
.tablecard__booking--sidder    { color: var(--green); }
.tablecard__total {
  margin-top: auto;
  font-size: 16px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}
.tablecard__flags { display: flex; flex-wrap: wrap; gap: 4px; }

/* ============================================================
   Touch-tastatur (bordnummer / beløb)
   ============================================================ */
.keypad { display: flex; flex-direction: column; gap: var(--sp-3); }

.keypad__display {
  height: 64px;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  padding: 0 var(--sp-4);
  background: var(--bg-0);
  border: 2px solid var(--line-2);
  border-radius: var(--r-md);
  font-size: 34px;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  letter-spacing: 1px;
  overflow: hidden;
}
.keypad__display--empty { color: var(--tx-3); font-size: 18px; font-weight: 600; letter-spacing: 0; justify-content: center; }
.keypad__display--error { border-color: var(--red); color: var(--red); }

.keypad__grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--sp-2); }

.key {
  min-height: var(--touch-lg);
  border-radius: var(--r-md);
  background: var(--bg-3);
  border: 1px solid var(--line-1);
  font-size: 26px;
  font-weight: 700;
  color: var(--tx-1);
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background .1s, transform .06s;
}
.key:hover { background: var(--bg-4); }
.key:active { background: var(--bg-5); transform: scale(.96); }
.key--fn { font-size: 17px; font-weight: 700; color: var(--tx-2); }
.key--wide { grid-column: span 2; }

.keypad__msg { min-height: 20px; font-size: 13px; font-weight: 600; color: var(--red); }

/* ============================================================
   Ordreliste
   ============================================================ */
/* ------------------------------------------------------------
   F-055 · LUFTEN I LINJEN MÅ VIGE FOR NAVNET

   Tre mellemrum á 12 px og 12 px polstring i hver side tog 60 af
   linjens 303 px. Navnefeltet, der skal rumme "TEST · Cheddar
   Burger" og fem tilvalg, fik 74.

   Luft er ikke ingenting — den holder tal og tekst adskilt. Men
   den er heller ikke det vigtigste på en linje, hvor tjeneren
   skal kunne se, at burgeren er UDEN cheddar. 8 px adskiller
   stadig tydeligt og giver navnet 24 px mere.
   ------------------------------------------------------------ */
.orderline {
  display: flex;
  gap: 8px;
  /* ------------------------------------------------------------
     LUFTEN, IKKE FINGEREN

     Linjen var 66 px høj: 44 px til −/+ og 22 px ren luft.
     Fingermålet er 44 og bliver det — en tast, man ikke kan
     ramme, er ingen besparelse. Men de 22 px er en femtedel af
     linjen, og på en spalte til fire linjer er det næsten en
     linje mere, gratis.

     Dennis, 5. september 2026, om regningen: «kan vi optimere det
     område derover, så man kan se måske 5 linjer.»
     ------------------------------------------------------------ */
  padding: 5px 8px;
  border-radius: var(--r-md);
  background: var(--bg-2);
  border: 1px solid var(--line-1);
  border-left: 4px solid var(--line-2);
  align-items: flex-start;
}
/* Ny (ikke sendt) skal springe i øjnene; sendt skal træde tilbage.
   Farven står aldrig alene — der er også et mærke og en tekst. */
.orderline--unsent {
  border-left: 6px solid var(--orange);
  background: var(--orange-soft);
  border-color: var(--orange);
}
.orderline--sent   { border-left-color: var(--line-strong); opacity: .6; }
.orderline--vent   { border-left-color: var(--yellow); }
.orderline--kaldt  { border-left-color: var(--orange); }
.orderline--paid   { border-left-color: var(--green); opacity: .6; }
.orderline--void   { border-left-color: var(--red); opacity: .5; text-decoration: line-through; }
.orderline.is-selected { background: var(--bg-4); border-color: var(--orange); }

/* ============================================================
   REGNINGEN I FARVER — KANTSTRIBEN SIGER DET, TEKSTEN SAGDE

   ------------------------------------------------------------
   HVAD DER BLEV BYTTET VÆK

   Hver linje bar to tekstlinjer: «? Afsendelse ukendt» og
   «Sendt». Det er 24 px pr. vare. På en regning med otte varer
   er det 192 px — næsten tre varer — brugt på at skrive noget,
   en farve kan sige.

   ------------------------------------------------------------
   HVAD FARVERNE BETYDER

     ORANGE  slået ind, ikke sendt endnu
     GRØN    sendt til køkken eller bar
     RØD     afsendelsen fejlede, eller printeren tav
     GUL     VENT — bevidst holdt tilbage
     GRÅ     annulleret

   Striben er 6 px og ikke 4: en farve, der skal læses på tværs
   af et bord i halvmørke, skal have noget at stå på.

   ------------------------------------------------------------
   HVORFOR TEKSTEN IKKE ER VÆK

   Den står som `title` på linjen og i linjedialogen. En farve
   alene er et gæt for den, der er ny — og en ny tjener på sin
   første aften skal kunne slå det op uden at spørge.
   ============================================================ */
:root[data-pos-regningstil="farver"] .orderline {
  border-left-width: 6px;
  padding: 7px 8px;
  gap: 7px;
}
/* Sendt er GRØN her, ikke grå. Grå er «ingenting», og det er
   ikke ingenting at have sendt en bøf til køkkenet. */
:root[data-pos-regningstil="farver"] .orderline--sent,
:root[data-pos-regningstil="farver"] .orderline--kaldt {
  border-left-color: var(--green);
  opacity: 1;
}
:root[data-pos-regningstil="farver"] .orderline--unsent {
  border-left-color: var(--orange);
}
:root[data-pos-regningstil="farver"] .orderline--vent {
  border-left-color: var(--yellow);
}
/* Slår igennem oven på «sendt»: er bonnen ikke kommet ud, er
   varen ikke lavet, og det skal ses før alt andet. */
:root[data-pos-regningstil="farver"] .orderline--afsendelsesfejl {
  border-left-color: var(--red);
  background: var(--red-soft, var(--bg-2));
}
:root[data-pos-regningstil="farver"] .orderline--void {
  border-left-color: var(--line-strong);
}

.orderline__mark {
  flex: 0 0 auto;
  align-self: center;
  font-size: 11px;
  font-weight: 800;
  letter-spacing: .04em;
  padding: 3px 7px;
  border-radius: 999px;
}
.orderline__mark--ny    { background: var(--orange); color: var(--tx-inv); }
.orderline__mark--sendt { color: var(--green); border: 1px solid var(--green); }
/* QA-14b fund 20: «SENDER…» og «IKKE SENDT» er ikke «SENDT» — ikke grønt, ikke samme ord. */
.orderline__mark--afventer { color: var(--blue); border: 1px solid var(--blue); }
.orderline__mark--problem  { color: var(--red); border: 1px solid var(--red); font-weight: 800; }
/* «SENDT (SIMULERET)»: bonnen blev kun vist på skærmen, ikke printet. Orange, ikke grøn, og må
   bryde over to linjer, så teksten kan stå fuldt ud. */
.orderline__mark--simuleret {
  color: var(--orange); border-color: var(--orange);
  white-space: normal; text-align: center; line-height: 1.15;
  max-width: 96px; border-radius: 10px;
}

.billsection {
  font-size: 12px;
  font-weight: 800;
  letter-spacing: .06em;
  text-transform: uppercase;
  padding: 6px 4px 2px;
}
.billsection--sendt { color: var(--tx-3); }
.billsection--ny    { color: var(--orange); border-top: 2px solid var(--orange); margin-top: 6px; padding-top: 8px; }

.orderline__qty {
  flex: 0 0 auto;
  min-width: 26px;
  font-size: 17px;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
}
/* ------------------------------------------------------------
   NAVNET MÅ BLIVE KLIPPET — DET MÅ IKKE MALE HEN OVER PRISEN

   `min-width: 0` er rigtigt: navnekolonnen skal kunne give sig,
   så antal, pris og plus/minus altid er der. Men uden `overflow`
   løb teksten bare ud over sin egen kasse.

   Målt 30. august 2026 på 958 px: navnekolonnen var presset ned
   på 24 px, og «Sodavand» stod hen over «70,00». Beløbet var
   ulæseligt — på en regning.

   Nu klippes navnet inde i sin egen kasse. Er der for lidt
   plads, mister man enden af et varenavn; man mister ikke
   prisen.
   ------------------------------------------------------------ */
.orderline__body { flex: 1 1 auto; min-width: 0; overflow: hidden; }
.orderline__name,
.orderline__variant,
.orderline__mods,
.orderline__note { overflow-wrap: anywhere; }
.orderline__name { font-size: 15px; font-weight: 600; }
.orderline__variant { font-size: 12.5px; color: var(--tx-2); }
.orderline__mods { font-size: 12.5px; color: var(--tx-3); margin-top: 2px; }
.orderline__mods .neg { color: var(--tx-neg); }
.orderline__mods .pos { color: var(--tx-pos); }
.orderline__note { font-size: 12.5px; color: var(--yellow); margin-top: 2px; font-style: italic; }
.orderline__price {
  flex: 0 0 auto;
  font-size: 15px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  text-align: right;
}

/* ============================================================
   Produktknapper
   ============================================================ */
.prodgrid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
  gap: var(--sp-2);
}
.prodbtn {
  min-height: 84px;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  align-items: flex-start;
  gap: 4px;
  padding: 10px;
  border-radius: var(--r-md);
  background: var(--bg-3);
  border: 1px solid var(--line-1);
  text-align: left;
  transition: background .1s, transform .06s;
}
.prodbtn:hover { background: var(--bg-4); }
.prodbtn:active { transform: scale(.97); }
.prodbtn__name { font-size: 14.5px; font-weight: 700; line-height: 1.2; }
.prodbtn__price { font-size: 13px; color: var(--tx-2); font-variant-numeric: tabular-nums; }
.prodbtn--out { opacity: .4; }
.prodbtn__badge {
  position: absolute; top: 6px; right: 6px;
}

/* ============================================================
   Modal
   ============================================================ */
.modal-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(0,0,0,.66);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 900;
  /*
     Sikkerhedsafstanden lægges på baggrunden, ikke på dialogen.
     Så kan dialogen bruge max-height: 100% og kan aldrig få sin
     fod skubbet ned under skærmkanten på en iPhone.
  */
  padding: calc(var(--sp-4) + env(safe-area-inset-top))
           calc(var(--sp-4) + env(safe-area-inset-right))
           calc(var(--sp-4) + env(safe-area-inset-bottom))
           calc(var(--sp-4) + env(safe-area-inset-left));
}
.modal {
  display: flex;
  flex-direction: column;
  width: 100%;
  max-width: 640px;
  max-height: 100%;
  min-height: 0;
  background: var(--bg-2);
  border: 1px solid var(--line-2);
  border-radius: var(--r-xl);
  box-shadow: var(--shadow-3);
  overflow: hidden;
}
.modal--wide { max-width: 940px; }
.modal--full { max-width: 1280px; }

/* Centrering med align-items må ikke kunne skubbe toppen ud af skærmen */
.modal { margin: auto; }

/*
   Sikkerhedsregel: knapper i gitre og flexrækker skal kunne krympe.
   Uden dette får de min-width: auto og bryder layoutet, så snart
   teksten er længere end kolonnen.
*/
.modal__body .btn,
.prodgrid .btn,
.floor__cards .btn { min-width: 0; }

.modal__body .btn {
  white-space: normal;
  line-height: 1.2;
  overflow-wrap: anywhere;
}
.modal__head {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  padding: var(--sp-4);
  border-bottom: 1px solid var(--line-1);
}
/* Pilen tilbage staar FOER overskriften og fylder ikke i den:
   `flex: 0 0 auto`, saa titlen beholder hele resten af raekken.
   Tegnet er husets eget «‹» — det samme som «‹ BORD 2» i
   toplinjen, saa de to betyder det samme sted i huset. */
.modal__tilbage {
  flex: 0 0 auto;
  min-width: 40px;
  font-size: 22px;
  line-height: 1;
  padding: 0;
}
.modal__title { font-size: 18px; font-weight: 700; flex: 1 1 auto; min-width: 0; }
.modal__body {
  flex: 1 1 auto;
  min-height: 0;
  min-width: 0;
  overflow-y: auto;
  overflow-x: hidden;
  padding: var(--sp-4);
}

.modal__foot {
  flex: 0 0 auto;
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2);
  padding: var(--sp-4);
  border-top: 1px solid var(--line-1);
  background: var(--bg-2);
}

/*
   Flex-elementer har som standard min-width: auto og kan derfor ikke
   krympe under deres indhold. Sammen med nowrap skubbede lange
   knaptekster foden ud af skærmen. Knapperne skal kunne krympe og
   ombryde teksten i stedet.
*/
.modal__foot .btn {
  min-width: 0;
  /* btn--block sætter width:100%, hvilket tvinger hver knap ned på
     sin egen række i foden. Her skal flex bestemme bredden. */
  width: auto;
  white-space: normal;
  line-height: 1.15;
  padding: 8px 12px;
  overflow-wrap: anywhere;
}

/* Er der ikke plads til alle knapper på én række, går den primære
   handling nederst i fuld bredde, hvor tommelfingeren er.

   Bredden kommer fra layoutmotoren, ikke fra et tal skrevet her.
   `smal` er motorens egen grænse — se `skaermlayout.js`. Den
   sidste håndskrevne POS-grænse i filen er dermed væk, og en ny
   enhedsprofil flytter foden med sig, uden at nogen retter CSS. */
:root[data-pos-bredde="smal"] .modal__foot { flex-direction: column-reverse; }
:root[data-pos-bredde="smal"] .modal__foot .btn { flex: 1 1 auto !important; width: 100%; }

/* ============================================================
   DIALOGERNE PÅ DEN KOMPAKTE FLADE

   ------------------------------------------------------------
   DET, DER VAR GALT

   Fladen fik det godkendte udtryk, men dialogerne beholdt husets
   gamle. Målt 31. august 2026 på en iPad: linjedialogen viste
   «Luk» som en lille firkant og «Annullér vare» som en bred, rød
   flade, der fyldte resten af foden.

   Den mest ødelæggende handling var altså den største og mest
   indbydende knap på skærmen — på en flade, man betjener med en
   tommelfinger, i en fyldt restaurant.

   ------------------------------------------------------------
   VÆGTEN FØLGER KONSEKVENSEN, IKKE PLADSEN

   Den sikre vej er bred. Den, der ikke kan fortrydes, står som en
   rød kontur: fuldt læsbar, ramt med vilje, aldrig ramt ved et
   uheld. Det er samme regel som i den godkendte skitse.

   Der styres på `kind`, som skærmene allerede sætter
   (`kind: 'danger'`), så en ny dialog arver vægtningen, uden at
   nogen skal huske at gøre noget.

   `!important` står her af samme grund som ovenfor: enkelte
   skærme sætter `style.flex` direkte på knappen, og en inline
   stil kan kun slås af en anden med samme vægt.
   ============================================================ */
:root[data-pos-flade="kompakt"] .modal__foot {
  gap: var(--sp-3);
  padding: var(--sp-4);
}
:root[data-pos-flade="kompakt"] .modal__foot .btn {
  flex: 1 1 auto !important;
  min-height: 52px;
  font-size: 15px;
  font-weight: 700;
  border-radius: 11px;
}
:root[data-pos-flade="kompakt"] .modal__foot .btn--danger {
  /* Smal og stille — men aldrig smallere end at ordene kan læses,
     og den skal kunne rammes af den, der VIL ramme den. */
  flex: 0 0 auto !important;
  width: auto;
  min-width: 150px;
  background: transparent;
  /* Roed TEKST paa moerk bund — se `--red-tekst`. Kanten maa gerne
     blive den maettede roede; det er tekstens laesbarhed, kravet
     handler om. */
  border: 1px solid var(--red);
  color: var(--red-tekst);
}
:root[data-pos-flade="kompakt"] .modal__foot .btn--danger:active {
  background: color-mix(in srgb, var(--red) 18%, transparent);
}

/* ------------------------------------------------------------
   «NEJ TAK» FØLGER DEN FARLIGES FORM — MEN ER IKKE FARLIG

   Dennis, 1. september 2026: «stor grøn knap, eller mindre rød
   for nej tak».

   Huset har allerede formen: `--danger` er «smal og stille» i
   den kompakte fod. Den form er præcis den rigtige her — den
   siger «det her er den anden vej» uden at fylde.

   Forskellen er, hvad den betyder. `--danger` sletter noget. At
   sige nej til en kvittering sletter ingenting; det er bare det
   sjældnere svar. Derfor sit eget navn, samme form.

   Og den grønne er den store: det svar, gæsten som regel vil
   have, skal kunne rammes uden at sigte.
   ------------------------------------------------------------ */
:root[data-pos-flade="kompakt"] .modal__foot .btn--nejtak {
  flex: 0 0 auto !important;
  width: auto;
  min-width: 130px;
  min-height: var(--touch-min);
  font-size: 14px;
  background: transparent;
  border: 1px solid var(--red);
  color: var(--red-tekst);
}
:root[data-pos-flade="kompakt"] .modal__foot .btn--nejtak:active {
  background: color-mix(in srgb, var(--red) 18%, transparent);
}
:root[data-pos-flade="kompakt"] .modal__foot .btn--pay {
  min-height: var(--touch-lg);
  font-size: 17px;
}

/* Er foden stablet (smal skærm), giver bredder ingen mening —
   dér er rækkefølgen det, der skiller dem ad, og den farlige
   knap skal stadig være den stille. */
:root[data-pos-flade="kompakt"][data-pos-bredde="smal"] .modal__foot .btn--danger {
  min-width: 0;
  width: 100%;
}

/* Hovedet og kroppen følger med: en titel, man kan læse på en
   armslængdes afstand, og et lukkekryds, der er en rigtig knap. */
:root[data-pos-flade="kompakt"] .modal__title { font-size: 20px; font-weight: 800; }
:root[data-pos-flade="kompakt"] .modal__head > .btn {
  min-width: var(--touch-min);
  min-height: var(--touch-min);
  font-size: 16px;
}
:root[data-pos-flade="kompakt"] .modal__body { padding: var(--sp-4) var(--sp-5); }

/* ============================================================
   Toast
   ============================================================ */
.toast-host {
  position: fixed;
  left: 50%;
  bottom: calc(24px + env(safe-area-inset-bottom));
  transform: translateX(-50%);
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  z-index: 1000;
  pointer-events: none;
  width: min(520px, calc(100vw - 32px));
}
/* ------------------------------------------------------------
   EN BESKED MÅ IKKE LÆGGE SIG PÅ DEN KNAP, DEN HANDLER OM

   Beskeden står nederst i midten — præcis dér, hvor en modals
   handlingsknapper sidder. Da et salg blev afvist («husets
   opsætning er ikke rullet ud»), lagde den sig hen over
   «GENNEMFØR», og den, der trykkede, så ingenting og trykkede
   igen. Målt i browseren: klikket NÅEDE knappen hver gang —
   beskeden var bare ikke til at læse.

   Er der en modal åben, flytter beskeden op i toppen, hvor der
   ikke er knapper. Ingen JavaScript ændres; falder `:has()`
   væk i en gammel browser, står vi præcis hvor vi stod.
   ------------------------------------------------------------ */
body:has(.modal-backdrop) .toast-host {
  top: calc(16px + env(safe-area-inset-top));
  bottom: auto;
}

/* ------------------------------------------------------------
   OG DEN KOMPAKTE FLADE HAR ALTID KNAPPER I BUNDEN

   Samme fejl, ny flade: ORDRE · HANDLING · KONFIG · AFSLUT står
   nederst hele tiden, og beskeden lagde sig hen over dem. Målt
   31. august 2026 — «Varen kan kun flyttes mellem de varer, der
   endnu ikke er sendt» dækkede HANDLING og KONFIG.

   Her er der ingen «nogle gange»: bjælken er der altid, så
   beskeden løftes op over den. Højden er `--kbund-hoejde`, som
   bjælken selv bruger — ét tal, ét sted.
   ------------------------------------------------------------ */
:root[data-pos-flade="kompakt"] .toast-host {
  bottom: calc(var(--kbund-hoejde) + var(--sp-4) + env(safe-area-inset-bottom));
}
/* Er der en modal ovenpå, gælder reglen ovenfor stadig — den
   gentages her, fordi den ellers ville tabe på vægt til linjen
   over. En modals knapper er de nærmeste, og de vinder. */
:root[data-pos-flade="kompakt"] body:has(.modal-backdrop) .toast-host {
  top: calc(16px + env(safe-area-inset-top));
  bottom: auto;
}

.toast {
  padding: 12px 18px;
  border-radius: var(--r-md);
  background: var(--bg-4);
  border: 1px solid var(--line-2);
  box-shadow: var(--shadow-2);
  font-size: 14.5px;
  font-weight: 600;
  text-align: center;
  animation: toastin .18s ease-out;
}
.toast--ok    { background: var(--toast-ok-bg);    border-color: var(--green);  color: var(--toast-ok-tx); }
.toast--warn  { background: var(--toast-warn-bg);  border-color: var(--yellow); color: var(--toast-warn-tx); }
.toast--error { background: var(--toast-error-bg); border-color: var(--red);    color: var(--toast-error-tx); }
@keyframes toastin { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }

/* ============================================================
   Hjælpeklasser
   ============================================================ */
.num { font-variant-numeric: tabular-nums; }
.muted { color: var(--tx-3); }
.dim { color: var(--tx-2); }
.strong { font-weight: 700; }
.center { text-align: center; }
.right { text-align: right; }
.gap-1 { gap: var(--sp-1); } .gap-2 { gap: var(--sp-2); }
.gap-3 { gap: var(--sp-3); } .gap-4 { gap: var(--sp-4); }
.p-3 { padding: var(--sp-3); } .p-4 { padding: var(--sp-4); }
.hidden { display: none !important; }

.label {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .8px;
  text-transform: uppercase;
  color: var(--tx-3);
}

.total-line {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--sp-3);
  font-variant-numeric: tabular-nums;
}
.total-line--grand { font-size: 24px; font-weight: 800; }

/* Nøddrift-banner */
.emergency-banner {
  flex: 0 0 auto;
  background: repeating-linear-gradient(45deg, var(--banner-noed-1), var(--banner-noed-1) 12px, var(--banner-noed-2) 12px, var(--banner-noed-2) 24px);
  border-bottom: 2px solid var(--orange);
  color: var(--banner-noed-tx);
  font-weight: 800;
  font-size: 13px;
  letter-spacing: 1px;
  text-transform: uppercase;
  text-align: center;
  padding: 6px;
}

/*
   Lukket kasse. Dagen er afsluttet med en Z-rapport, og der kan
   ikke sælges. Båndet er en knap, så man kommer direkte hen og
   åbner dagen igen i stedet for at lede efter den.
*/
.closed-banner {
  flex: 0 0 auto;
  width: 100%;
  border: none;
  border-bottom: 2px solid var(--red);
  background: repeating-linear-gradient(45deg, var(--banner-lukket-1), var(--banner-lukket-1) 12px, var(--banner-lukket-2) 12px, var(--banner-lukket-2) 24px);
  color: var(--banner-lukket-tx);
  font-weight: 800;
  font-size: 13px;
  letter-spacing: 1px;
  text-transform: uppercase;
  text-align: center;
  padding: 8px 6px;
  cursor: pointer;
  font-family: inherit;
  /* Banneret ER en knap — den åbner dagen. Med 8px polstring og
     13px tekst blev den 36px høj, altså under husets eget
     `--touch-min`. Bredden var aldrig problemet; højden var.
     Flex i stedet for block, så teksten bliver stående i midten,
     når højden vokser. */
  min-height: var(--touch-min);
  display: flex;
  align-items: center;
  justify-content: center;
}
.closed-banner:active { filter: brightness(1.25); }
/* Er der ikke noget at trykke paa — fordi den, der staar ved
   kassen, ikke selv maa aabne dagen — skal bjaelken heller ikke
   se ud som en knap. Den er en oplysning, ikke en vej. */
.closed-banner--besked { cursor: default; }
.closed-banner--besked:active { filter: none; }

/* ============================================================
   Responsive
   ============================================================ */

/* Håndholdt — under 640px */
/* `:root` og modalerne ligger UDEN FOR appens boks — `html` er
   containerens forfader, og modalen haenger paa `body`, fordi
   skallens `mount` ellers ville slette den ved hver optegning.
   Se «MODALEN HAENGER PAA `body`» i modal.js. */
@media (max-width: 639px) {
  :root { --touch: 52px; --touch-lg: 62px; }
  .modal { max-width: 100%; border-radius: var(--r-lg); }
  .modal-backdrop {
    padding: calc(8px + env(safe-area-inset-top))
             calc(8px + env(safe-area-inset-right))
             calc(8px + env(safe-area-inset-bottom))
             calc(8px + env(safe-area-inset-left));
  }
  .modal__head, .modal__body, .modal__foot { padding: var(--sp-3); }
}
@container pos (max-width: 639px) {
  .topbar { height: 54px; padding: 0 var(--sp-3); }
  .prodgrid { grid-template-columns: repeat(auto-fill, minmax(112px, 1fr)); }
  .tablecard { min-height: 104px; }
  .tablecard__no { font-size: 23px; }
}

/* Meget lav skærm i liggende visning på telefon */
@media (max-height: 480px) {
  :root { --touch: 44px; --touch-lg: 50px; }
}
@container pos (max-height: 480px) {
  .topbar { height: 48px; }
  .keypad__display { height: 48px; font-size: 26px; }
}

/* Tablet */
@container pos (min-width: 640px) and (max-width: 1023px) {
  .prodgrid { grid-template-columns: repeat(auto-fill, minmax(132px, 1fr)); }
}

/* Kasse / desktop */
@container pos (min-width: 1024px) {
  .prodgrid { grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); }
}

/* Bundnavigation på håndholdt — indhold må aldrig ligge under */
.bottomnav {
  flex: 0 0 auto;
  display: flex;
  justify-content: center;
  gap: 2px;
  background: var(--bg-2);
  border-top: 1px solid var(--line-1);
  padding-bottom: env(safe-area-inset-bottom);
}
.bottomnav__item {
  flex: 1 1 0;
  /* På en stor kasse skal fanerne ikke trækkes ud over hele skærmen */
  max-width: 200px;
  min-width: 0;
  min-height: var(--touch);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  font-size: 11px;
  font-weight: 600;
  color: var(--tx-3);
  padding: 6px 2px;
}
.bottomnav__item.is-active { color: var(--orange); background: var(--orange-soft); }

/* ============================================================
   DEN GAMLE STRIBE STÅR IKKE PÅ DEN KOMPAKTE FLADE

   Elleve punkter à 11 px tekst er den store kasses navigation.
   Her er de fire døre i bunden husets vej rundt — og stribens
   destinationer ligger inde i dem. Se `navigation()` i shell.js
   og menuerne i posKompakt.js.

   Reglen står her OGSÅ, selv om skallen ikke tegner striben paa
   den kompakte flade: falder `JC.posKompakt` væk, tegner skallen
   striben som reserve, og så skal den ikke pludselig stå der som
   en anden navigation ved siden af.
   ============================================================ */
:root[data-pos-flade="kompakt"] .bottomnav { display: none; }
/* Men ikke paa den haandholdte flade: dér skjuler husets eget
   `hh`-saet allerede baade topbar og stribe, og `haandholdtskaermtest`
   maaler at de er der og er skjulte. Se `haandholdtFlade()` i shell.js. */
body.hh .bottomnav { display: none; }


/* ============================================================
   Bordplan
   ============================================================ */
.floor { min-height: 0; }

.scroll-x {
  overflow-x: auto;
  overflow-y: hidden;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
}
.scroll-x::-webkit-scrollbar { display: none; }

.floor__tabs {
  flex: 0 0 auto;
  display: flex;
  gap: 2px;
  padding: 6px 8px;
  background: var(--bg-2);
  border-bottom: 1px solid var(--line-1);
  /* ------------------------------------------------------------
     OMRÅDERNE RULLER — SIDEN GØR IKKE

     Huset har flere områder, end der er plads til i bredden på en
     telefon. Uden det her skubbede fanerækken HELE fladen sidelæns:
     bordene lå uden for skærmen, og man skulle skubbe siden tilbage
     for at trykke på et bord.

     Nu ruller kun rækken selv. Ingenting forsvinder, og resten af
     skærmen står stille.
     ------------------------------------------------------------ */
  overflow-x: auto;
  overflow-y: hidden;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
}
.floor__tabs::-webkit-scrollbar { display: none; }
.floor__tab {
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1px;
  min-height: var(--touch-min);
  padding: 6px 14px;
  border-radius: var(--r-sm);
  font-size: 14px;
  font-weight: 600;
  color: var(--tx-2);
  white-space: nowrap;
}
.floor__tab:hover { background: var(--bg-3); color: var(--tx-1); }
.floor__tab.is-active { background: var(--orange-soft); color: var(--orange); }
.floor__tabcount { font-size: 11px; font-weight: 600; opacity: .75; font-variant-numeric: tabular-nums; }

.floor__main {
  display: flex;
  flex-direction: row;
  min-height: 0;
  min-width: 0;
}
.floor__grid { padding: 10px; }
.floor__cards {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(138px, 1fr));
  gap: 8px;
  align-content: start;
}
/* ------------------------------------------------------------
   ET LANGT BORD I LISTEN

   Bordene, der hoerer sammen, staar i den samme ramme med en
   overskrift. Rammen spaender over hele raekken — `grid-column:
   1 / -1` — for ellers ville et selskab paa tre borde blive
   klemt ned i én kolonne, og saa var det ikke til at se, at de
   staar SAMMEN.

   Se `samledeKort` i `floorplan.js`.
   ------------------------------------------------------------ */
.floor__saml {
  grid-column: 1 / -1;
  border: 2px dashed var(--line-2);
  border-radius: var(--r-md);
  padding: 6px 8px 8px;
  background: color-mix(in srgb, var(--bg-2) 60%, transparent);
}
.floor__saml--optaget {
  border-style: solid;
  border-color: var(--accent);
}
.floor__saml__mrk {
  display: flex;
  align-items: baseline;
  gap: 8px;
  flex-wrap: wrap;
  padding: 0 2px 6px;
}
.floor__saml__nr {
  font-size: 15px;
  font-weight: 800;
  color: var(--tx-1);
  font-variant-numeric: tabular-nums;
}
.floor__saml__hvad {
  font-size: 11.5px;
  color: var(--tx-3);
}
.floor__saml__kort {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(138px, 1fr));
  gap: 8px;
}

.floor__side {
  flex: 0 0 320px;
  min-height: 0;
  overflow-y: auto;
  padding: 10px 10px 10px 0;
  border-left: 1px solid var(--line-1);
}

/*
   Tastaturet skal kunne rummes selv på en lav skærm. Bliver pladsen
   for trang, krymper tasterne i stedet for at ÅBN BORD forsvinder
   ud under bundnavigationen.
*/
@container pos (min-width: 900px) and (max-height: 940px) {
  .floor__side .keypad__grid .key { min-height: 56px; font-size: 23px; }
  .floor__side .keypad__display { height: 56px; font-size: 29px; }
  .floor__side .btn--lg { min-height: 58px; }
}
@container pos (min-width: 900px) and (max-height: 800px) {
  .floor__side .keypad__grid .key { min-height: 46px; font-size: 20px; }
  .floor__side .keypad__display { height: 48px; font-size: 25px; }
  .floor__side .btn--lg { min-height: 50px; font-size: 15px; }
  .floor__side .keypad { gap: var(--sp-2); }
}

/* ============================================================
   BORDPLANEN PÅ EN SMAL SKÆRM

   ------------------------------------------------------------
   DET, DER VAR GALT

   Tastaturet stod som `flex: 0 0 auto` og tog sin fulde
   indholdshøjde. Målt 31. august 2026 ved 500 px bredde: bordene
   fik 20 px, «Åbn bord direkte» fik 658 — inde i en flade på 467.

   Bordplanen ER skærmen. Det er dér, tjeneren ser, hvem der
   sidder hvor, og hvor længe de har ventet. «Åbn bord direkte»
   er genvejen for den, der allerede kender nummeret. Genvejen
   havde spist hovedsagen.

   ------------------------------------------------------------
   MOTOREN, IKKE ET TAL

   Grænserne stod som `max-width: 899px` og `max-height: 560px`.
   De svarer ikke på husets skærmprofiler, og de reagerer ikke på
   prøvefladen — så en måling ved 393 px viste noget andet end en
   rigtig telefon. Nu er det motorens egne bånd, og en ny
   enhedsprofil flytter bordplanen med sig.

   `smal` og `mellem` er alt under motorens `bred` (900 px), og
   `lav` er dens egen grænse for en flad skærm — en telefon på
   siden. Se `skaermlayout.js`.
   ============================================================ */
:root[data-pos-bredde="smal"] .floor__main,
:root[data-pos-bredde="mellem"] .floor__main { flex-direction: column; }

:root[data-pos-bredde="smal"] .floor__side,
:root[data-pos-bredde="mellem"] .floor__side {
  /* `0 1 auto` og et loft. Bordplanen er hovedsagen — det er dér,
     tjeneren ser hvem der sidder hvor. «Åbn bord direkte» er
     genvejen for den, der allerede kender nummeret, og en genvej
     må ikke tage mere end genvejens del. Derfor 40/60 og ikke
     halvt: displayet og to rækker taster kan ses, resten ruller. */
  flex: 0 1 auto;
  max-height: 40%;
  overflow-y: auto;
  border-left: none;
  border-top: 1px solid var(--line-1);
  padding: 8px;
  background: var(--bg-1);
}
:root[data-pos-bredde="smal"] .floor__grid,
:root[data-pos-bredde="mellem"] .floor__grid {
  /* Bordene beholder de tre femtedele, også når tastaturet er højt. */
  flex: 1 1 auto;
  min-height: 60%;
}
:root[data-pos-bredde="smal"] .floor__side .keypad__grid .key,
:root[data-pos-bredde="mellem"] .floor__side .keypad__grid .key { min-height: 52px; font-size: 22px; }
:root[data-pos-bredde="smal"] .floor__side .keypad__display,
:root[data-pos-bredde="mellem"] .floor__side .keypad__display { height: 52px; font-size: 27px; }
:root[data-pos-bredde="smal"] .floor__cards,
:root[data-pos-bredde="mellem"] .floor__cards { grid-template-columns: repeat(auto-fill, minmax(116px, 1fr)); }

/* Liggende telefon: der er ikke højde til at stable. Gitter og
   tastatur står side om side igen, og bordene får bredden. */
:root[data-pos-hoejde="lav"]:not([data-pos-bredde="bred"]) .floor__main { flex-direction: row; }
:root[data-pos-hoejde="lav"]:not([data-pos-bredde="bred"]) .floor__side {
  flex: 0 0 268px;
  max-height: none;
  border-top: none;
  border-left: 1px solid var(--line-1);
}
:root[data-pos-hoejde="lav"]:not([data-pos-bredde="bred"]) .floor__grid { min-height: 0; }
/* 40 px stod her, fordi den gamle regel kun naaede telefoner
   under 819 px. Motorens baand naar videre, og saa var tasterne
   pludselig under husets fingermaal paa en iPhone paa siden —
   maalt 67 x 40 den 31. august 2026. Fire raekker a 44 px er 176,
   og der er 393 at tage af. Gulvet holder. */
:root[data-pos-hoejde="lav"]:not([data-pos-bredde="bred"]) .floor__side .keypad__grid .key { min-height: var(--touch-min); font-size: 19px; }
:root[data-pos-hoejde="lav"]:not([data-pos-bredde="bred"]) .floor__side .keypad__display { height: 42px; font-size: 22px; }

/* ============================================================
   Bestillingsskærm
   ============================================================ */
.ordhead {
  align-items: center;
  padding: 8px 12px;
  background: var(--bg-2);
  border-bottom: 1px solid var(--line-1);
  flex-wrap: wrap;
  row-gap: 6px;
}

.waitbanner {
  background: var(--yellow);
  color: var(--tx-inv);
  font-weight: 800;
  font-size: 12.5px;
  letter-spacing: .3px;
  text-align: center;
  padding: 7px 12px;
  line-height: 1.3;
}

.ordmain {
  display: flex;
  flex-direction: row;
  min-height: 0;
  min-width: 0;
}

.ordleft { min-width: 0; min-height: 0; }

.ordright {
  flex: 0 0 372px;
  min-height: 0;
  min-width: 0;
  border-left: 1px solid var(--line-1);
  background: var(--bg-1);
}

/*
   Regningen skal have plads. Handlingsknapperne er derfor lavere
   her end i resten af systemet, og regningen får en garanteret
   minimumshøjde, så den ikke klemmes sammen til ingenting.
*/
.ordright .scroll-y { min-height: 140px; }
.ordright .btn { min-height: 46px; }
/* ------------------------------------------------------------
   UNDTAGELSEN HØRER TIL PÅ BETALINGSSKÆRMEN — OG KUN DÉR

   Her stod `.ordright .btn--sm { min-height: 38px }`. Grunden
   står ovenfor: regningen skal have plads, når man deler en
   betaling, og de seks pixels pr. knap er den handel.

   Men `.ordright` bruges også af knap-editoren, og dér er der
   ingen regning at give plads til. «Omdøb», «Fjern dem» og «Sæt
   dem i stand» blev 38 px høje — under husets eget fingermål —
   uden at nogen havde besluttet det. Målt 31. august 2026.

   Undtagelsen er derfor bundet til betalingsspalten. Et
   fingermål, der falder væk et sted, ingen har tænkt over, er
   ikke en undtagelse; det er en fejl, der spreder sig. */
.pay .ordright .btn--sm { min-height: 38px; font-size: 13px; }
.ordright .total-line { font-size: 14px; }
.ordright .total-line--grand { font-size: 20px; }

@container pos (min-height: 900px) {
  .ordright .btn { min-height: 52px; }
  .ordright .scroll-y { min-height: 220px; }
}

/* ============================================================
   BETALINGEN PÅ DEN KOMPAKTE FLADE

   ------------------------------------------------------------
   DET, DER VAR GALT

   Målt 31. august 2026 på iPad liggende: betalingsknapperne var
   46 px høje, og under dem stod der 204 px tom. Til venstre stod
   238 px tom under den sidste vare. Skærmen bad om et tryk på de
   mindste felter, den havde, mens en tredjedel af fladen lå ubrugt.

   Undtagelsen ovenfor — `.pay .ordright .btn--sm` på 38 px — blev
   truffet, dengang spalten var trang. På en flade med 204 px til
   overs er begrundelsen der ikke længere.

   ------------------------------------------------------------
   DET HER ER IKKE I STRID MED D-0013

   Dér blev den tomme plads under VAREFLADEN bevaret, fordi
   husets knapside har tolv rækker, og en fordeling ville give de
   otte tomme rækker del i pladsen og skubbe ANTAL-panelet ud.

   Betalingspanelet har ingen tomme rækker. Der er kun de knapper,
   der faktisk findes, og de deler den plads, der faktisk er.

   ------------------------------------------------------------
   INGEN HØJDEGRÆNSE

   Der står ingen `min-height`-forespørgsel her. Knapperne vokser
   med `1fr`, til de rammer et loft, og holder deres gulv, når der
   er trangt. Så virker det på en iPhone liggende med 393 px og på
   en iPad stående med 1024 — uden at nogen skriver et tal ned.
   ============================================================ */
:root[data-pos-flade="kompakt"] .pay .paypanel {
  flex: 1 1 auto;
  min-height: 0;
}
:root[data-pos-flade="kompakt"] .pay .paymetoder {
  flex: 1 1 auto;
  min-height: 0;
  /* Loftet, saa to knapper paa en hoej iPad ikke bliver to plader.
     Gulvet er husets fingermaal. */
  grid-auto-rows: minmax(var(--touch-min), 1fr);
  max-height: 340px;
  /* ------------------------------------------------------------
     NAAR DER IKKE ER PLADS, RULLER DE — DE VOKSER IKKE UD

     Foerste udgave gav kun `flex: 1 1 auto`. Paa iPhone liggende
     (852x393) er der ikke 44 px til tre raekker OG totalerne OG
     vejen tilbage — og gitteret lagde sig hen over «Tilbage til
     bordet». Maalt 31. august 2026: to overlappende par.

     Gulvet paa 44 px maa ikke give efter — en betalingsknap, der
     skrumper, er vaerre end en, man ruller til. Derfor ruller
     gitteret, og vejen tilbage bliver staaende.
     ------------------------------------------------------------ */
  overflow-y: auto;
}
:root[data-pos-flade="kompakt"] .pay .ordright .btn,
:root[data-pos-flade="kompakt"] .pay .ordright .btn--sm {
  min-height: var(--touch-min);
  height: auto;
  font-size: 15px;
  font-weight: 700;
}
/* «Tilbage til bordet» er en vej ud, ikke en betaling. Den skal
   kunne rammes, men aldrig konkurrere med Kort og Kontant om
   opmaerksomheden. */
:root[data-pos-flade="kompakt"] .pay .paypanel > .btn--ghost {
  flex: 0 0 auto;
  min-height: var(--touch-min);
}

.guestbar {
  padding: 8px 10px;
  background: var(--bg-2);
  border-bottom: 1px solid var(--line-1);
  align-items: center;
}
.guestbar .btn { flex: 0 0 auto; }

/* Tablet og håndholdt: regningen lægger sig under produkterne */
@container pos (max-width: 1023px) {
  .ordright { flex: 0 0 320px; }
}

@container pos (max-width: 819px) {
  .ordmain { flex-direction: column; }
  .ordleft { flex: 1 1 auto; min-height: 180px; }
  .ordright {
    flex: 0 0 auto;
    max-height: 52%;
    border-left: none;
    border-top: 2px solid var(--line-2);
  }
  .ordright .scroll-y { max-height: 34vh; }
  .ordhead { padding: 6px 10px; }
}

/* Liggende telefon: tilbage til to spalter, ellers er der ikke plads */
@container pos (max-width: 819px) and (orientation: landscape) and (max-height: 560px) {
  .ordmain { flex-direction: row; }
  .ordright {
    flex: 0 0 300px;
    max-height: none;
    border-top: none;
    border-left: 1px solid var(--line-2);
  }
  .ordright .scroll-y { max-height: none; }
}

/*
   Tastatur inde i en dialog skal fylde mindre end på bordplanen,
   så GENNEMFØR altid er synlig uden at rulle.
*/
.modal .keypad { gap: var(--sp-2); }
.modal .keypad__display { height: 54px; font-size: 28px; }
.modal .keypad__grid { gap: 6px; }
.modal .keypad__grid .key { min-height: 52px; font-size: 22px; }
.modal .keypad__msg { min-height: 0; }
.modal .btn--lg { min-height: 54px; font-size: 16px; }

@media (max-height: 820px) {
  .modal .keypad__display { height: 46px; font-size: 24px; }
  .modal .keypad__grid .key { min-height: 44px; font-size: 20px; }
  .modal .btn--lg { min-height: 46px; font-size: 15px; }
  .modal__head { padding: var(--sp-3) var(--sp-4); }
  .modal__title { font-size: 16px; }
}

/* ============================================================
   Knapopsætning — gitter med flettede felter
   ============================================================ */
.buttongrid {
  display: grid;
  gap: 4px;
  width: 100%;
  /* Felterne skal være kvadratiske nok til at ramme med en finger */
  grid-auto-rows: minmax(56px, auto);
}
.buttongrid--compact { grid-auto-rows: minmax(44px, auto); }

/* ------------------------------------------------------------
   I drift FYLDER gitteret skærmen

   Der må ikke være knapper, der gemmer sig længere nede. Rækkerne
   deler den plads der er, i stedet for at kræve en fast højde og
   skubbe resten ud over kanten. I editoren er det omvendt: dér er
   det i orden at rulle, for man sidder og arbejder.
   ------------------------------------------------------------ */
/* ============================================================
   HUSETS INVARIANT: INTET KRITISK POS-UI UDEN FOR SKÆRMEN

   ------------------------------------------------------------
   REGLEN

   Hele bordvisningen skal kunne bruges inden for den viewport,
   browseren faktisk har. Ingen knap må være klippet, ingen
   plus/minus må forsvinde, og ingen primær handling må kræve, at
   man ruller på SIDEN.

   Der er ÉN undtagelse: PLU-vinduet — varegitteret — må rulle
   indeni. Alt andet skal være der.

   ------------------------------------------------------------
   HVAD DER VAR GALT

   `.kasse__varer` og `.gitterflade` er den SAMME node, og
   `.kasse__varer` satte `overflow: hidden`. Gitteret voksede til
   668 px inde i en flade på 509 — og resten blev KLIPPET væk.
   Ikke skjult bag en rullebjælke: væk.

   Målt 30. august 2026 på 958 × 707: hele ANTAL-rækken lå på
   y 757–801. Under skærmkanten, uden nogen måde at nå den på.
   Samtidig var ANTAL-knapperne 38 px brede, hvor huset selv
   kræver 44.

   ------------------------------------------------------------
   HVORFOR DET SKETE — OG HVAD DER LØSER DET

   En flex-boks nægter at blive mindre end sit indhold, med
   mindre man siger `min-height: 0`. Mangler det ét sted i kæden,
   vokser hele kæden ud over skærmen, og den yderste `overflow:
   hidden` klipper enden af. Derfor står `min-height: 0` hele
   vejen ned til fladen — og fladen er så den ENESTE, der ruller.

   Og rækkerne: en bund på KNAPPEN får rækker til at lægge sig
   oven i hinanden, når gitteret klemmes. Bunden hører til på
   SPORET. `minmax(min-content, 1fr)` lader tomme rækker falde
   sammen og giver kun de rækker, der har knapper, deres
   fingerhøjde. Det er dét, der gør, at et layout med tolv rækker
   og to fyldte ikke spiser skærmen.
   ============================================================ */
.gitterflade {
  flex: 1 1 0;
  min-width: 0;
  min-height: 0;
  display: flex;
  /* ------------------------------------------------------------
     AL PLADSEN SKAL BRUGES

     Dennis, 10. september 2026: «Hvorfor har vi frirum over
     Forside-fanen? Vi skal udnytte al plads. Og samme over
     produkterne?»

     Her stod `align-items: flex-start` og `padding: 6px`, med den
     begrundelse at gitteret gerne maa vaere hoejere end fladen og
     saa rulle. Den begrundelse holdt, da raekkerne havde en fast
     mindstehoejde. Nu deler de pladsen (`minmax(0, 1fr)` i
     `buttonGrid.js`), og saa er der ingen overhoejde at rulle —
     kun seks pixels luft i toppen og et gitter, der ikke naaede
     bunden.

     MAALT samme dag: fladen 468 px fra y=175, gitteret 493 px fra
     y=181. Seks px luft foroven, femogtyve px ud over kanten
     forneden, og fanesoejlen ved siden af startede seks px
     hoejere end den foerste varetast.

     `stretch` og ingen polstring: gitteret begynder, hvor fladen
     begynder, og slutter, hvor den slutter. Rulningen bliver
     staaende for de flader, der stadig har brug for den — et
     gitter, der ER hoejere, kan stadig rulles.
     ------------------------------------------------------------ */
  align-items: stretch;
  padding: 0;
  /* DEN ENESTE RULLEFLADE I BORDVISNINGEN */
  overflow: auto;
  overscroll-behavior: contain;
}
/* ------------------------------------------------------------
   HER STOD DET SAMME EN GANG TIL

   1005 linjer — fra `.gitterflade > .buttongrid` til og med
   funktionsblokken — laa BAADE her og 1692 linjer laengere nede,
   tegn for tegn ens. Omkring en tiendedel af hele stilarket.

   Det er ikke et layoutproblem; det er et vedligeholdelsesproblem.
   Retter man en fejl i den ene kopi, vinder den anden — eller
   ikke — alt efter hvad der ellers staar imellem dem, og man kan
   ikke se det paa den fil, man har aabnet.

   FOERSTE kopi er fjernet og ikke den anden. De var ens, saa det
   aendrer ingenting i sig selv — men reglerne, der staar MELLEM
   de to kopier, blev tidligere overskrevet af den nederste. Den
   relation er bevaret ved at lade den nederste blive staaende.

   Fjernet 1. september 2026. Maalt bagefter: `skaermtest` 753,
   `fladetest` 70 paa seks enheder.
   ------------------------------------------------------------ */

.kasse__regningsrum > .kasse__regning { flex: 1 1 auto; min-width: 0; }
.kasse__regningsrum > .funkblok--lodret { flex: 0 0 auto; align-self: stretch; }

/* ------------------------------------------------------------
   F-055 · TO KOLONNER NÅR SKÆRMEN ER LAV

   Ni taster i én kolonne kræver 9 × 40 px + 8 × 3 px mellemrum
   = 384 px. Regningsrummet får sin højde af skærmen minus
   sortiment, antalfelt og betalingsknapper — cirka 460 px. Så
   under en skærmhøjde på ~845 px rækker én kolonne ikke.

   Grænsen er sat til 860 px med lidt luft. Over den er der plads
   til én kolonne (på kassernes 982 px bliver hver tast ~55 px);
   under den lægger blokken sig i to, og hver tast bliver højere
   end i én kolonne — ikke lavere.

   Rækkefølgen er stadig læseretning: Slet, Retur, Genkald …
   Hånden skal kunne finde dem uden at kigge, og en kolonne mere
   ændrer ikke, at pladsen er den samme hver gang.
   ------------------------------------------------------------ */
/* ------------------------------------------------------------
   TO KOLONNER — NÅR MOTOREN SIGER DET

   Her stod `@media (max-height: 860px)`. Det var det sidste
   hardkodede breakpoint i bordvisningen, og det målte VINDUET.

   Motoren regner på den flade, kassen faktisk har. De to var ikke
   enige: motoren lovede regningslinjen 333 px ud fra én kolonne à
   96 px, mens stilarket gav to à 150 — og linjen fik 303 og
   brækkede. Målt 31. august 2026.

   Nu kommer tallet ét sted fra. Se `funktionerKolonner` i
   skaermlayout.js: elleve taster à 43 px kræver 473 px i højden;
   er der mindre, lægger blokken sig i to.
   ------------------------------------------------------------ */
:root[data-pos-taster="2"][data-pos-funktioner="lodret"] .funkblok--lodret {
  grid-template-columns: 1fr 1fr;
  grid-auto-rows: minmax(40px, 1fr);
  /* 150, ikke 2 x 92. Teksterne er korte, og hver px, blokken
     tager, er en px mindre til varenavnet ved siden af. */
  width: 150px;
}
:root[data-pos-taster="2"][data-pos-funktioner="lodret"] .funkblok--lodret .funk {
  font-size: 11.5px; padding: 2px 1px;
}

/* Håndholdt: striben lægger sig ned igen. På en telefon er der
   ikke bredde til både taster og regning ved siden af hinanden. */
/* ------------------------------------------------------------
   FUNKTIONSBLOKKEN FLYTTER NED — NÅR MOTOREN SIGER DET

   Her stod `@media (max-width: 1100px)`. Tallet var rigtigt nok
   som tommelfingerregel: under det bliver der for lidt tilbage
   til regningslinjen, når blokken står ved siden af.

   Men et bredde-tal kan ikke se, hvor bred regningen faktisk
   BLEV. Den samme 1100 px skærm har forskellig plads i linjen,
   alt efter om regningen fik 400 eller 460, og om blokken står i
   én kolonne eller to. Målt 30. august 2026 på 958 px: blokken
   flyttede ned, men lagde sig som et fire-kolonners felt oven i
   regningen og skjulte ordrelinjerne.

   Nu regner `skaermlayout.js` det ud — regningens bredde minus
   blokkens 96 px skal levne de 230, linjen skal bruge — og
   svaret står i `data-pos-funktioner`. Se `skaermstyring.js`.
   ------------------------------------------------------------ */
:root[data-pos-funktioner="bund"] .kasse__regningsrum {
  flex-direction: column-reverse;
}
:root[data-pos-funktioner="bund"] .funkblok--lodret {
  width: auto;
  height: auto;
  grid-template-columns: repeat(auto-fit, minmax(78px, 1fr));
  grid-auto-rows: minmax(var(--touch-min, 44px), auto);
  padding: 5px 0 0;
  border-top: 1px solid var(--line-1);
  /* ------------------------------------------------------------
     LISTEN VINDER OVER TASTERNE — OGSÅ I HØJDEN

     Her stod `flex: 0 0 auto`. Motoren vogter, at regningsLINJEN
     får sin BREDDE — `linjeMindst` er 333 px, og det er dét, der
     afgør, om tasterne står ved siden af eller flytter ned. Men
     flytter de ned, er der INTET, der vogter højden: blokken
     tager sine rækker først, og listen får resten.

     Dennis, 5. september 2026: «regningen på siden du er på nu,
     den er ikke særlig synlig.»

     Målt på 1500 × 723: rummet var 220 px. Tasterne tog 144, og
     regningen fik 76 — plads til ÉN linje, mens der stod tre
     varer på bordet.

     `0 1 auto` gør blokken eftergivende, og loftet holder den på
     sin del af rummet. Rækkerne beholder deres fingerhøjde; det
     er kun ANTALLET af synlige rækker, der giver sig, og blokken
     kan rulles. En taste, man skal rulle til, er stadig bedre end
     en regning, man ikke kan læse.

     NB: hele det her regelsæt står TO gange i filen — se den
     anden kopi længere nede. Rettes kun den ene, sker der
     ingenting, for den sidste vinder.
     ------------------------------------------------------------ */
  flex: 0 1 auto;
  min-height: 0;
  overflow-y: auto;
  max-height: 38%;
}
:root[data-pos-funktioner="bund"] .kasse__regningsrum > .kasse__regning {
  /* Listen tager alt, hvad tasterne ikke skal bruge. */
  flex: 1 1 auto;
  min-height: 0;
}
:root[data-pos-funktioner="lodret"] .kasse__regningsrum {
  flex-direction: row;
}

/* ============================================================
   SAMLET FORM — NÅR SPALTEN ER FOR LAV TIL ELLEVE TASTER

   Målt 30. august 2026 på 958 × 564: regningsspalten blev 366 px
   høj. Titel, elleve taster og handlingsblokken tog 360 af dem,
   og ordrelisten fik 6 px. Ikke én linje var synlig.

   Så bliver de fire, hånden bruger hele tiden — Rette, Fortryd,
   Gentag, Retur — stående på én række, og resten flytter ind
   under «Diverse». Rækken er 56 px høj i stedet for 148, og de
   92 px går til listen.

   Tasterne beholder deres fingermål. Det er ANTALLET, der giver
   sig, ikke størrelsen — en tast, man ikke kan ramme, er ikke en
   besparelse.
   ============================================================ */
.funkblok--samlet {
  grid-template-columns: repeat(auto-fit, minmax(72px, 1fr));
  grid-auto-rows: minmax(var(--touch-min, 44px), auto);
  height: auto;
  width: auto;
  flex: 0 0 auto;
  padding: 6px 0 0;
  background: transparent;
  border-top: 1px solid var(--line-1);
}
.funkblok--samlet .funk { min-height: var(--touch-min, 44px); font-size: 12px; }

/* Diverse skiller sig ud: den er ikke en handling, den er en dør */
.funk--diverse {
  background: var(--bg-4, var(--bg-3));
  border-color: var(--line-1);
}

/* Arket bag «Diverse». Fuld fingerstørrelse — det betjenes med en
   tommelfinger på en skærm, der står i en bar. */
.divark {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(132px, 1fr));
  gap: 8px;
}
.divark__tast {
  min-height: max(var(--touch-min, 44px), 56px);
  font-size: 14px;
}

/* ============================================================
   BUNDMENUEN — «HANDLING» OG «SEND»

   På en iPad står tasterne ikke på fladen. De ligger bag to
   brede knapper i bunden, hvor tommelfingeren er, når man
   holder skærmen.

   Knapperne er høje med vilje: det her er de to eneste steder,
   alt det, der afgør noget, kan nås fra. Rammes de forkert,
   står man og leder — og gæsten står og venter.
   ============================================================ */
.posmenu {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
  padding: 8px 10px 10px;
  background: var(--bg-2);
  border-top: 1px solid var(--line-1);
}
.posmenu__knap {
  min-height: max(var(--touch-min, 44px), 64px);
  font-size: 17px;
  font-weight: 700;
  letter-spacing: .3px;
}
/* «Send» er den, der koster penge at ramme forkert — den skal
   se anderledes ud end den, der kun åbner en liste. */
.posmenu__knap--send {
  background: var(--bg-4, var(--bg-3));
  border-color: var(--line-1);
}
/* Står der usendte varer, siger knappen det selv. Tjeneren skal
   ikke åbne menuen for at finde ud af, om der er noget at sende. */
/* ------------------------------------------------------------
   PLUSSET, MENS DER TRÆKKES

   Tallet skal kunne læses, mens fingeren står på knappen — og
   knappen skal se anderledes ud, så man ved, at man er i gang
   med noget andet end et almindeligt tryk.
   ------------------------------------------------------------ */
/* Uden dette tolker browseren trækket som en rulning i
   regningen, og `pointermove` når aldrig knappen. */
.linjeknap--plus { touch-action: none; }

.linjeknap--traekker {
  background: var(--orange);
  border-color: var(--orange);
  color: var(--bg-0);
  font-size: 15px;
  font-weight: 800;
}

.posmenu__knap--venter {
  background: var(--orange);
  border-color: var(--orange);
  color: var(--bg-0);
}

/* ------------------------------------------------------------
   DEN STORE TOTALRÆKKE — DEN ENESTE, DER STÅR TO STEDER

   Beløbet står allerede øverst til højre på skærmen, i
   bordlinjen, i samme størrelse. På en høj skærm er gentagelsen
   god: øjet finder den, hvor det kigger.

   På en lav skærm koster den 52 px, som ordrelisten mangler. Så
   bliver den til en almindelig linje. Den forsvinder ikke — den
   holder bare op med at råbe.
   ------------------------------------------------------------ */
:root[data-pos-taethed="samlet"] .total-line--grand {
  font-size: 17px;
  padding: 2px 0;
}
:root[data-pos-taethed="samlet"] .panel--total { gap: 4px; }
:root[data-pos-taethed="samlet"] .kasse__handlinger { padding-top: 6px; gap: 6px; }

.funk {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 36px;
  padding: 2px 4px;
  background: var(--bg-3);
  border: 1px solid var(--line-2);
  border-radius: var(--r-sm);
  color: var(--tx-1);
  text-align: center;
  font-size: 12.5px;
  font-weight: 700;
  letter-spacing: .2px;
  line-height: 1.1;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.funk:active { background: var(--accent); color: var(--accent-tx); }

/* Kan tasten ikke bruges lige nu, står den mat — men den bliver
   liggende, og den svarer stadig når man trykker */
.funk--fra { opacity: .45; }
.funk--fra:active { background: var(--bg-4); color: var(--tx-1); }

.funk--fare { color: var(--red-tx); }
.funk--fra.funk--fare { color: var(--tx-2); }

/* ------------------------------------------------------------
   SLÅET TIL: RETUR VENTER PÅ DEN NÆSTE VARE

   Her stod `--red` (#e5484d). Hvid tekst på den giver 3,91:1, og
   husets krav er 4,5 for almindelig tekst. MÅLT 12. september
   2026 af `iphoneknaptest` på 428 × 926: «RETTE TIL» dumpede
   kontrasten i syvogtredive af otteogtredive fund.

   `--red-dk` (#b83236) giver 5,92:1 med den samme hvide tekst.
   Det er ikke et nyt valg — `.btn--danger` har brugt præcis det
   par siden august, og af præcis den grund. Den lyse røde bliver
   stående dér, hvor den er en FLADE og ikke bærer tekst.
   ------------------------------------------------------------ */
.funk--paa {
  background: var(--red-dk);
  border-color: var(--red-dk);
  color: var(--tx-on-danger);
}

.funkblok--retur { background: var(--red-soft); }
.funkblok--rette { background: var(--orange-soft); }

/* Fortryd er en vej TILBAGE, ikke en handling. Den skal se
   anderledes ud end de taster der ændrer noget. */
.funk--fortryd { border-style: dashed; }

.rettebanner {
  background: var(--orange);
  color: var(--tx-inv);
  font-weight: 800;
  font-size: 12.5px;
  letter-spacing: .3px;
  text-align: center;
  padding: 7px 12px;
  line-height: 1.3;
}

/* Mens Rette er slået til, skal man kunne SE at et tryk på en
   linje fjerner den. Ellers er det en fælde. */
.orderline--rammes {
  border-left-color: var(--orange);
  box-shadow: inset 0 0 0 1px var(--orange);
}
.orderline--rammes .orderline__name::after {
  content: '  ×';
  color: var(--orange);
  font-weight: 800;
}

.returbanner {
  /* --red (#e5484d) mod hvid er 3,91 — under AA's 4,5, og teksten
     her er 12,5px, altsaa ikke «stor tekst». Baandet siger «RETUR —
     den naeste …», og det skal kunne laeses paa en telefon i et
     halvmoerkt lokale. --red-dk giver 5,92. Samme rettelse som
     `.funk--paa` fik; fundet af `iphoneknaptest` begge gange. */
  background: var(--red-dk);
  color: var(--tx-on-danger);
  font-weight: 800;
  font-size: 12.5px;
  letter-spacing: .3px;
  text-align: center;
  padding: 7px 12px;
  line-height: 1.3;
}

/* En returlinje er en modpost. Rød kant og negativt beløb, så
   den aldrig forveksles med et salg. */
.orderline--retur { border-left-color: var(--red); }
.orderline--retur .orderline__price { color: var(--red); font-weight: 800; }

/* På en smal skærm bliver teksten mindre — men tasterne bliver
   liggende på én række. Pladserne må ikke skifte med bredden. */
@container pos (max-width: 819px) {
  .funk { min-height: 34px; font-size: 10px; letter-spacing: 0; padding: 2px; }
}

/* ------------------------------------------------------------
   MEN PÅ EN TELEFON ER 34 PX IKKE EN TAST

   34 px er en tabletbeslutning: der er bredde nok til at få alle
   taster på én række, og en lav række giver plads til regningen.

   På 390 punkter ligger tasterne allerede i flere rækker — og så
   er der ingenting at vinde ved at gøre dem lave. En tast, der
   ikke kan rammes med en tommelfinger, er ikke en spareplads; den
   er «Slet» ramt i stedet for «Retur» midt i en service.

   Blokken bliver højere. Det er den rigtige vej rundt.
   ------------------------------------------------------------ */
@container pos (max-width: 639px) {
  .funk,
  .funkblok--lodret .funk { min-height: var(--touch-min); font-size: 11px; }
}

/* ------------------------------------------------------------
   Antal-feltet

   Ligger som et felt PÅ siden, ikke som en bjælke over den. Så
   flytter intet sig, når man åbner en kategori — og huset kan
   selv bestemme, hvor det skal være, eller om det skal være der.
   ------------------------------------------------------------ */
.panel--antal { padding: 3px; justify-content: center; }
.panel--antal .antalbar {
  padding: 0;
  background: transparent;
  border-bottom: none;
  gap: 3px;
}
/* ------------------------------------------------------------
   F-055 · CIFRENE SKAL KUNNE RAMMES MED EN FINGER

   Her stod `min-height: 0`, så cifrene fyldte det felt, huset
   havde tegnet — og i et lavt felt blev de 28 px høje.

   28 px er en musemålsknap. Kassen betjenes med en finger på en
   travl aften, og et fejltryk på antallet sender fire øl af sted
   i stedet for én.

   Feltet må gerne være lavt; cifrene må ikke. Bliver feltet for
   lavt til dem, vokser det — det er den rigtige vej rundt.
   ------------------------------------------------------------ */
/* ------------------------------------------------------------
   40 BLEV TIL 44 — HUSETS EGET MINDSTEMÅL GÆLDER OGSÅ HER

   Tallet var en bevidst afvejning: 40 px giver fire punkter mere
   til varerne på en kasse, hvor der er højde nok. Målt 22. august
   2026 var det de ENESTE trykmål under 44 på hele kassefladen —
   alle andre skærme var rene.

   Argumentet ovenfor gælder stadig, og det peger den anden vej:
   et fejltryk på ANTAL sender fire øl af sted i stedet for én.
   Det er en økonomisk fejl på en regning, ikke en skønhedsfejl.
   Fire punkters skærmplads er ikke den risiko værd, og huset har
   i forvejen besluttet, hvad et trykmål mindst er: `--touch-min`.
   ------------------------------------------------------------ */
.panel--antal .antal__ciffer { min-height: var(--touch-min); height: 100%; }
.panel--antal .antal__visning { flex: 0 0 62px; font-size: 15px; }

/* ------------------------------------------------------------
   PÅ EN TELEFON SKRUMPER CIFRENE IKKE

   40 px er en tablet-beslutning: der er plads nok i højden, og en
   lavere række giver mere skærm til varerne. På 390 punkter er der
   ingenting at spare — og et ciffer, der ikke kan rammes, er en
   forkert mængde på en regning.

   Reglen står HER og ikke oppe ved de andre brudpunkter, fordi
   `.panel--antal .antal__ciffer` ellers vinder på rækkefølge. En
   regel, der taber, er værre end ingen regel: den ser rigtig ud i
   filen og gør ingenting på skærmen.
   ------------------------------------------------------------ */
@container pos (max-width: 639px) {
  .antal__ciffer,
  .panel--antal .antal__ciffer { min-height: var(--touch-min); }
}


/* ============================================================
   Rabat, pris og opslag
   ============================================================ */

.rabatbanner,
.prisbanner {
  background: var(--orange);
  color: var(--tx-inv);
  font-weight: 800;
  font-size: 13px;
  letter-spacing: .3px;
  padding: 7px 12px;
  text-align: center;
}

/* Totalpanelet kan rammes, når Rabat er tændt */
.panel--rammes {
  outline: 2px solid var(--orange);
  outline-offset: -2px;
}

.rabat__overskrift {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .6px;
  text-transform: uppercase;
  color: var(--tx-3);
  margin-top: 4px;
}

.rabat__aarsager {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 6px;
}
.rabat__aarsager .btn { min-height: 52px; flex-direction: column; gap: 0; }

.rabat__pct {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(84px, 1fr));
  gap: 6px;
}

.bfelt__input--stor {
  min-height: 54px;
  font-size: 24px;
  font-weight: 700;
  text-align: center;
}

/* ---------- Opslag ---------- */
.opslag__liste {
  display: flex;
  flex-direction: column;
  max-height: 46vh;
  overflow-y: auto;
  border-top: 1px solid var(--line-1);
}
.opslag__rk {
  display: grid;
  grid-template-columns: 68px 1fr auto;
  gap: 10px;
  align-items: center;
  min-height: 46px;
  padding: 8px 10px;
  background: transparent;
  border: none;
  border-bottom: 1px solid var(--line-1);
  color: var(--tx-1);
  text-align: left;
  font-size: 15px;
  cursor: pointer;
}
.opslag__rk:hover, .opslag__rk:focus { background: var(--bg-3); }
.opslag__plu {
  font-variant-numeric: tabular-nums;
  color: var(--tx-3);
  font-size: 13px;
}
.opslag__navn { font-weight: 600; }
.opslag__pris { font-variant-numeric: tabular-nums; white-space: nowrap; }

/* Rabat og prisændring på selve linjen */
.orderline__rabat {
  font-size: 11.5px;
  font-weight: 700;
  color: var(--orange);
  margin-top: 1px;
}
.orderline__foer {
  display: block;
  font-size: 11.5px;
  font-weight: 500;
  color: var(--tx-3);
  text-decoration: line-through;
}

/* ---------- Kreditnota ---------- */
.knrk {
  display: grid;
  grid-template-columns: 1fr auto 110px;
  gap: 12px;
  align-items: center;
  padding: 9px 12px;
  background: var(--bg-2);
  border: 1px solid var(--line-1);
  border-radius: var(--r-sm);
}
.knrk--valgt { border-color: var(--red); background: var(--red-soft); }
.knrk__antal { display: flex; align-items: center; gap: 8px; }
.knrk__antal .btn { min-width: 40px; }
.knrk__tal {
  min-width: 56px;
  text-align: center;
  font-variant-numeric: tabular-nums;
  font-weight: 700;
}
.knrk__sum {
  text-align: right;
  font-variant-numeric: tabular-nums;
  font-weight: 700;
  color: var(--red-lt);
}

/* ---------- Kontokunder ---------- */
.kundrk {
  display: grid;
  grid-template-columns: 60px 1fr auto;
  gap: 12px;
  align-items: center;
  min-height: 56px;
  padding: 9px 12px;
  background: transparent;
  border: none;
  border-bottom: 1px solid var(--line-1);
  color: var(--tx-1);
  text-align: left;
  cursor: pointer;
}
.kundrk:hover, .kundrk:focus { background: var(--bg-3); }
.kundrk--fuld { background: var(--red-soft); }
.kundrk__nr {
  font-variant-numeric: tabular-nums;
  color: var(--tx-3);
  font-size: 13px;
}
.kundrk__saldo {
  text-align: right;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* ============================================================
   Indtastningsfelter i dialoger

   Lå kun i backend.css, som kassen ikke indlæser. Derfor stod
   felterne i Rabat, Kreditnota og På regning som hvide kasser
   fra browserens standard — midt i en mørk skærm.

   De hører til begge steder, så de bor her.
   ============================================================ */
/* ------------------------------------------------------------
   `.input` — det almindelige skrivefelt

   Klassen blev brugt ni steder (licens, login, retur, kladde,
   gensend bon, overtag bord), men den fandtes ikke i nogen
   stilfil. Uden en regel arvede feltet kun `color: inherit` fra
   nulstillingen — næsten hvid tekst — mens baggrunden blev
   browserens egen hvide. Man kunne skrive i feltet, men ikke se
   hvad. Fundet på licensskærmen, hvor nøglen skal tastes tegn
   for tegn.

   Den ligner `.bfelt__input` med vilje: ét skrivefelt i huset,
   ikke to.
   ------------------------------------------------------------ */
.input {
  width: 100%;
  min-height: 44px;
  padding: 9px 12px;
  background: var(--bg-3);
  border: 1px solid var(--line-2);
  border-radius: var(--r-sm);
  color: var(--tx-1);
  font-size: 15px;
}
.input::placeholder { color: var(--tx-3); }
.input:focus { outline: none; border-color: var(--accent); }
.input:disabled { opacity: .6; }

/* ------------------------------------------------------------
   FELTER UDEN KLASSE SKAL OGSÅ KUNNE RAMMES

   `.input` har fingermålet, men et felt, der er skrevet uden
   klassen, falder udenom. Målt 31. august 2026 på printerskærmen:
   fem bare `<select>` på 42 px — to px under, og ingen havde
   besluttet det.

   Kun på den kompakte flade. På den store kasse med mus står der
   tætte tabeller i backenden, hvor et gulv ville skubbe rækkerne
   fra hinanden uden gevinst.
   ------------------------------------------------------------ */
:root[data-pos-flade="kompakt"] select,
:root[data-pos-flade="kompakt"] input:not([type="checkbox"]):not([type="radio"]):not([type="range"]) {
  min-height: var(--touch-min);
}

.bfelt { display: flex; flex-direction: column; gap: 4px; }
.bfelt__navn {
  font-size: 11.5px;
  color: var(--tx-3);
  font-weight: 600;
}
.bfelt__input {
  min-height: 44px;
  padding: 9px 12px;
  background: var(--bg-3);
  border: 1px solid var(--line-2);
  border-radius: var(--r-sm);
  color: var(--tx-1);
  font-size: 15px;
  width: 100%;
}
.bfelt__input::placeholder { color: var(--tx-3); }
.bfelt__input:focus { outline: none; border-color: var(--accent); }

.bhjaelp {
  padding: 12px 14px;
  background: var(--bg-2);
  border: 1px solid var(--line-1);
  border-left: 3px solid var(--accent);
  border-radius: var(--r-sm);
  font-size: 13px;
  line-height: 1.6;
  color: var(--tx-2);
}

.blogin__fejl {
  padding: 9px 12px;
  border-radius: var(--r-sm);
  background: var(--red-soft);
  border: 1px solid var(--red);
  color: var(--red-lt);
  font-size: 13.5px;
}

.btom {
  padding: 32px 16px;
  text-align: center;
  color: var(--tx-3);
  font-size: 14px;
  line-height: 1.6;
}

.bunder {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .6px;
  text-transform: uppercase;
  color: var(--tx-3);
  margin: 12px 0 6px;
}

.brække {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: 12px;
  margin-bottom: 12px;
}

/* ============================================================
   Bordplanen på kassen — lokalet, levende
   ============================================================ */
.floor__baand {
  display: flex;
  align-items: center;
  gap: 22px;
  padding: 8px 14px;
  background: var(--bg-2);
  border-bottom: 1px solid var(--line-1);
  flex: 0 0 auto;
}
.floor__tal { display: flex; flex-direction: column; line-height: 1.15; }
.floor__tal__vaerdi { font-size: 17px; font-weight: 800; font-variant-numeric: tabular-nums; }
.floor__tal__navn { font-size: 11px; color: var(--tx-3); }
.floor__tal--haster .floor__tal__vaerdi { color: var(--red); }

/* ------------------------------------------------------------
   NÅR PLANEN IKKE KAN VÆRE DER

   Længere nede står husets beslutning: «Planen skal fylde fladen
   — ikke ligge i et rullefelt. Skal man rulle for at finde bord
   55, er den ikke bedre end listen.» Den står ved magt.

   Men planen skalerer kun ned til `MINDSTE_CELLE`. Derunder kan
   den ikke: et bord, der er mindre end en finger, er ikke et
   bord. Målt 31. august 2026 på 800 × 600: feltet gav 362 px,
   planen skulle bruge 464 — 28 % for meget. Resten laa ned under
   bundbjælken, hvor hverken øje eller finger kunne nå den.

   `auto` og ikke `scroll`: passer planen, er der ingen
   rullebjælke, og beslutningen ovenfor gælder uændret. Kan den
   ikke, er valget mellem at rulle og at gøre bordene for små at
   ramme — og så ruller vi hellere.

   (Huset har i forvejen «Vis som liste» til de rigtig store
   planer. Den er stadig den bedre vej, når rummet er stort.)
   ------------------------------------------------------------ */
/* Rulningen ligger paa rammen udenom, ikke paa planen selv — se
   «PLANEN MAA IKKE SLUGE DEN RULNING, DEN IKKE HAR» laengere nede.
   Her stod `overflow: auto` og `overscroll-behavior: contain`, og
   de to regler sagde hver sit om den samme flade. */
/* ------------------------------------------------------------
   PLANEN SKAL STAA MIDT I LOKALET — OG GJORDE DET IKKE

   `.floor__grid` er `justify-content: safe center`, og noten dér
   siger selv hvorfor: planen skal staa midt i fladen. Men `.pv`
   havde `flex: 1 1 auto` og voksede ud i HELE bredden. En
   centrering af et barn, der allerede fylder alt, flytter
   ingenting — og `.pv__flade` inde i den lagde sig i venstre
   kant, som et blokelement goer.

   MAALT 10. september 2026 hos Toerst: fladen var 1139 px bred,
   `.pv` blev 1119, og rummet blev tegnet 729. 390 pixels tom
   plads i hoejre side, hver eneste optegning.

   Dennis: «Kan man ikke vaelge om den skal stretch eller faktisk
   stoerrelse — her mener jeg fylde skaermen — og saa om den skal
   centreres?»

   `flex: 0 0 auto` goer `.pv` praecis saa bred, som planen er.
   Saa virker centreringen, og «safe» sikrer stadig, at der ikke
   klippes af toppen, naar planen er stoerre end fladen.

   REGLEN STAAR TO STEDE I DEN HER FIL, ord for ord. Den sidste
   vinder. Rettes den ene og ikke den anden, siger de to hver sit
   om den samme flade (fejlklasse 1) — derfor er BEGGE rettet.
   ------------------------------------------------------------ */
.pv {
  padding: 12px;
  flex: 0 0 auto;
  min-height: 0;
  overflow: visible;
}
.gitterflade > .buttongrid {
  flex: 1 1 auto;
  min-width: 0;
  /* Mindst så højt som fladen — ellers står der en tom stribe
     under gitteret — og gerne højere, når rækkerne kræver det. */
  min-height: 100%;

  /* ------------------------------------------------------------
     `1fr` GIVER OGSÅ DE TOMME RÆKKER EN ANDEL

     Og det var dét, der skubbede ANTAL-rækken ud over kanten.
     Husets layout har tolv rækker; tre af dem har knapper, og
     ANTAL-panelet står på række tolv. Med `1fr` fik alle tolv
     52 px — 668 px i alt i en flade på 509 — så de otte tomme
     rækker i midten skubbede ANTAL ned under skærmen.

     `auto` deler ikke pladsen ud. Så bliver rækken præcis så høj,
     som dens indhold kræver: en tom række falder sammen til
     ingenting, og en række med knapper får sin fingerhøjde fra
     cellen nedenfor. Otte tomme rækker koster nu 0 px i stedet
     for 416.

     `align-content: start` holder rækkerne samlet i toppen, så
     den plads, der bliver til overs, lægger sig under gitteret i
     stedet for at blive fordelt ud i luft mellem knapperne.
     ------------------------------------------------------------ */
  grid-auto-rows: minmax(min-content, auto);
  align-content: start;
}

/* Fingerstørrelsen står på de celler, der FAKTISK er noget —
   tomme pladser i layoutet skal ikke koste en hel række. */
/* ------------------------------------------------------------
   BUNDEN GAELDER, TIL HUSET SELV HAR VALGT ET RAEKKETAL

   `--touch-min` er 44 px, fordi det er dét, en finger rammer
   paalideligt. Den bund staar — men den maa ikke OVERSTYRE et
   tal, huset selv har sat i kassens opsaetning.

   Dennis, 10. september 2026: «Vi maa tilpasse hoejden paa
   knapper samt bredden til antal oenskede knapper, man vil
   have.»

   Uden det her vandt bunden: tolv raekker à 44 px kraever 528 px
   paa en flade med 468, og saa stak gitteret ud over kanten og
   raekkerne laa oven i hinanden. Vaelger huset tolv, faar det
   tolv — og `kasseflade.proev()` har sagt, hvad knappen bliver,
   FOER nogen gemte. Bunden gaelder stadig alle de flader, hvor
   ingen har valgt.
   ------------------------------------------------------------ */
.gitterflade > .buttongrid > .gridcell { min-height: var(--touch-min, 44px); }
.kasse__varefelt:has(> .katstribe--venstre) .gitterflade > .buttongrid > .gridcell {
  min-height: 0;
}
.gitterflade > .buttongrid > .gridcell--empty,
.gitterflade > .buttongrid > .gridcell--slot { min-height: 0; }

/* ------------------------------------------------------------
   EN KNAP MÅ ALDRIG BLIVE SMALLERE END EN FINGER

   Gitteret bruger husets EGEN kolonnetælling — den, layoutet er
   bygget med — og det er med vilje: knapperne skal stå det samme
   sted hver gang, ellers virker vanen ikke.

   Men uden en nedre grænse betyder det, at en smal skærm bare
   klemmer kolonnerne sammen. Målt 30. august 2026 på 1024 px med
   husets 11-kolonners layout: 37 px pr. knap. Huset har selv sat
   `--touch-min` til 48 px — og til 60 px i det høje kontrasttema,
   som er lavet til dem, der ser dårligst.

   Knapperne viste «F… 45,00», «H… 65,0», «S… 35,0». Man kunne
   hverken læse navnet eller ramme rigtigt.

   Derfor: knappen holder sin mindstebredde, og er layoutet
   bredere end fladen, ruller fladen. Så flytter knapperne sig
   ikke i forhold til hinanden, og ingen af dem bliver for små at
   ramme. Ruller man, er det fordi huset har valgt flere
   kolonner, end skærmen har plads til — og det kan ses.
   ------------------------------------------------------------ */
.gitterflade > .buttongrid {
  overflow-x: auto;
  /* QA-14b fund 3: var `hidden` — rækker, der ikke kunne være der, var klippet væk uden at kunne nås. Nu ruller fladen
     (finger og hjul), og rækkerne snapper til kanten, så en række aldrig står klippet midt over, når man slipper. */
  overflow-y: auto;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
  scroll-snap-type: y proximity;
  scrollbar-width: thin;
}
.gitterflade > .buttongrid > .gridcell { scroll-snap-align: start; }
/* Redigering: gitteret er opsætningen, som den er bygget — den rulles ikke, den ses i sin helhed. */
.gitterflade > .buttongrid:has(.gridcell--edit) { overflow-y: hidden; scroll-snap-type: none; }
/* TEMAFAST — en maske er en stencil på alfakanalen, ikke en farve (se «TEMAFAST» ovenfor) */
.gitterflade > .buttongrid[data-mere-ned="ja"] {
  -webkit-mask-image: linear-gradient(to bottom, #000 calc(100% - 26px), transparent 100%);
  mask-image: linear-gradient(to bottom, #000 calc(100% - 26px), transparent 100%);
}
/* TEMAFAST SLUT */

/* Mindstebredden staar paa KOLONNESPORET — se buttonGrid.js. */

/* ------------------------------------------------------------
   Total og betal må ALDRIG klemme knapperne væk

   Feltet er lavt, og der er både tal og to store knapper i det.
   Bliver pladsen for lille, er det TALLENE der viger — knapperne
   skal kunne rammes. Uden dette lå Betal ude over kanten.
   ------------------------------------------------------------ */
.panel--total .total-line { flex: 0 1 auto; min-height: 0; overflow: hidden; }

/* Knapperne får resten af pladsen og skalerer med feltet. Er der
   næsten ingen plads, er det tallene der forsvinder — man kan
   altid se totalen i regningen, men man kan ikke betale uden en
   knap at ramme. */
/* ------------------------------------------------------------
   GULVET VAR UNDER HUSETS EGET MINIMUM

   Noten ovenfor siger det selv: «man kan ikke betale uden en knap
   at ramme». Men gulvet stod paa 34 px, og husets minimum er 44 —
   saa i den klemte tilstand blev knapperne netop dét, reglen var
   skrevet for at forhindre.

   Maalt 2. september 2026 af husets egen `trykmaalbrowsertest`:
   «Luk bord · send» og «Betal · 566,00 kr.» begge 194x34 paa
   kassens bestillingsflade. Kravet er 44.

   Gulvet er nu husets minimum. Tallene viger et stykke mere — og
   det er praecis den byttehandel, noten ovenfor har valgt: totalen
   kan altid ses i regningen, knappen kan ikke undvaeres.
   ------------------------------------------------------------ */
.panel--total .row { flex: 1 1 auto; min-height: var(--touch-min, 44px); }
.panel--total > .btn { flex: 0 0 auto; }
.panel--total .btn--lg {
  min-height: var(--touch-min, 44px);
  height: 100%;
  font-size: 15px;
  padding: 4px 8px;
}

/* ------------------------------------------------------------
   Regningen bladres med pile — ikke med en rullebjælke

   En rullebjælke er til en mus. Her er der fingre, og der skal
   være noget at ramme. To små pile i højre side, og de er kun
   der, når der FAKTISK er mere at se.
   ------------------------------------------------------------ */
.medpile {
  position: relative;
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
}
.medpile__flade {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  scrollbar-width: none;
}
.medpile__flade::-webkit-scrollbar { width: 0; height: 0; }

/* ------------------------------------------------------------
   BLADREPILENE SKAL KUNNE RAMMES

   26 x 40 px. Husets fingermaal er 44 i BEGGE led, og pilene er
   den ene af to veje til at se resten af regningen — den anden er
   at rulle med fingeren.

   Fundet af `fladetest` 1. september 2026 paa kasseprofilen, da
   den blev maalt med den samme scanner som de kompakte flader.
   Den havde staaet saadan hele tiden; ingen havde maalt den.

   De 18 px, soejlen vokser med, tages fra regningslinjen. Den har
   400-520 px at give af, og en linje, der er 18 px kortere, kan
   stadig baere «1× Boef Bearnaise 225,00» — det er maalt i
   `skaermprofiler.kasse`. En pil, man rammer ved siden af, kan
   ingenting.
   ------------------------------------------------------------ */
.medpile__pile {
  /* Soejlen tager den bredde, KNAPPEN skal have — den saetter den
     ikke selv. Med `flex: 0 0 44px` og 6 px polstring blev
     knappen 38, og saa var maalet stadig ikke naaet. */
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 6px;
  padding: 2px 0 2px 4px;
}
.medpile__pil {
  flex: 0 0 auto;
  min-width: var(--touch-min, 44px);
  height: var(--touch-min, 44px);
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--bg-3);
  border: 1px solid var(--line-2);
  border-radius: var(--r-sm);
  color: var(--tx-2);
  font-size: 14px;
  line-height: 1;
}
.medpile__pil:active { background: var(--accent); color: var(--accent-tx); }
.medpile__pil[disabled] { opacity: .25; }

/* Op og ned står lige over hinanden og gør det modsatte. De skal
   kunne skelnes af en finger — og kassen er lige så meget en
   touchskærm som den håndholdte. Se `.linjeknap` for den samme
   begrundelse; reglen gælder derfor på ALLE bredder. */
.medpile__pil { min-height: var(--touch-min); }

.gridcell {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: center;
  gap: 1px;
  min-width: 0;
  /* Stramt lodret, så både navn og pris kan være i en knap på
     45 px. Det er der plads til 12 rækker på en almindelig skærm. */
  padding: 4px 7px;
  border-radius: var(--r-sm);
  background: var(--bg-3);
  border: 1px solid var(--line-1);
  color: var(--tx-1);
  text-align: left;
  overflow: hidden;
  transition: background .1s, transform .06s, border-color .12s;
}
.gridcell:active { transform: scale(.97); }
.gridcell:hover { background: var(--bg-4); }

/* «fra» er ikke en del af beloebet — det er et forbehold. Mindre
   og daempet, saa tallet stadig er det, oejet finder foerst. */
.gridcell__fra {
  font-size: .82em;
  font-weight: 600;
  color: var(--tx-3);
  letter-spacing: .2px;
}

.gridcell__label {
  font-size: 12.5px;
  font-weight: 700;
  line-height: 1.1;
  width: 100%;
  overflow: hidden;
  display: -webkit-box;
  /* To linjer, medmindre huset selv har braekket navnet med `\`.
     Se `L.knapnavn` og noten i `buttonGrid.js`. */
  -webkit-line-clamp: var(--knaplinjer, 2);
  -webkit-box-orient: vertical;
  /*
     `anywhere` brækkede ord midt over — "Smørrebrø / d med".
     `break-word` gjorde det samme, bare sjældnere: "Drikkevar /
     e" og "FRONTEN / D TEST" stod på kassen.

     Et brækket ord ligner en stavefejl. Et klippet ord med "…"
     ligner det, det er: et navn, der ikke kunne være der. Derfor
     bryder vi KUN mellem ord ("Smørrebrød / med rejer") og lader
     resten klippe.
  */
  overflow-wrap: normal;
  word-break: normal;
  /* ------------------------------------------------------------
     F-055 · INGEN ORDDELING I KNAPTEKSTER

     Her stod `hyphens: auto`. Browseren delte så ordene efter
     sine egne regler, og på kassen kom der til at stå
     "Soda-vand", "Drikkeva-re" og "FRON-TEND…".

     En tjener læser ikke knappen — han genkender den. Et ord med
     en bindestreg midt i ligner ikke det ord, hånden leder efter,
     og så bruger han et halvt sekund på at læse i stedet.

     Uden orddeling brydes teksten kun MELLEM ord. Passer et navn
     stadig ikke, klipper `text-overflow` det med "…", og så er
     det tydeligt, at der mangler noget — i stedet for at ligne
     et ord, der bare stavedes underligt.
     ------------------------------------------------------------ */
  hyphens: none;
  /* Klippes der alligevel, skal det ses — ikke bare mangle */
  text-overflow: ellipsis;
  /* ------------------------------------------------------------
     KLEMMEN SKAL OGSAA VIRKE I EN NY BROWSER

     `-webkit-line-clamp` kraever `display: -webkit-box`. Nyere
     Chrome har den standardiserede `line-clamp`, og de to skal
     staa side om side — ellers er klemmen slaaet fra i den ene og
     til i den anden, og teksten klippes UDEN tegn.

     MAALT 10. september 2026 i den koerende kasse: `display`
     regnede ud som `flow-root`, klemmen virkede ikke, og 26 af 66
     varenavne stod hugget af uden ellipse.
     ------------------------------------------------------------ */
  line-clamp: var(--knaplinjer, 2);
  /* NAVNET er det vigtige. Bliver feltet lavt, må prisen vige —
     aldrig navnet. Uden dette klemte gitteret navnet helt væk,
     så knapperne kun viste et beløb. */
  flex: 0 0 auto;
}
.gridcell__price {
  font-size: 11px;
  line-height: 1.1;
  font-weight: 600;
  opacity: .8;
  font-variant-numeric: tabular-nums;
  /* Enten er hele prisen der, eller også er den der ikke.
     En halv talrække er værre end ingen. */
  flex: 0 0 auto;
  white-space: nowrap;
}
.gridcell__key {
  position: absolute;
  top: 3px;
  right: 4px;
  font-size: 9.5px;
  font-weight: 700;
  opacity: .55;
  font-family: var(--mono);
}
.gridcell__arrow {
  position: absolute;
  top: 4px;
  right: 6px;
  font-size: 15px;
  font-weight: 800;
  opacity: .6;
}

/* Feltets art ses på venstrekanten */
.gridcell--kategori { border-left: 3px solid var(--blue); }
.gridcell--side     { border-left: 3px solid var(--purple); }
.gridcell--handling { border-left: 3px solid var(--orange); }
.gridcell--tekst {
  background: transparent;
  border-color: transparent;
  color: var(--tx-3);
  font-weight: 700;
  justify-content: flex-end;
  /* ------------------------------------------------------------
     EN OVERSKRIFT ER IKKE EN KNAP

     Tekstfelter tegnes som `<button>` ligesom alt andet i
     gitteret, men `posScreen.udfoer` har ingen gren for dem — et
     tryk gjorde bogstavelig talt ingenting. Tjeneren trykkede på
     «AFTENKORT», og skærmen svarede ikke.

     En knap, der ikke gør noget, er værre end ingen knap: man
     prøver igen. Så teksten tager ikke imod tryk — bortset fra i
     editoren, hvor den netop skal kunne vælges og rettes.
     ------------------------------------------------------------ */
  pointer-events: none;
}
.gridcell--tekst.gridcell--edit { pointer-events: auto; }

/* Peger feltet på en slettet vare, skal det ses med det samme */
.gridcell--broken {
  background: var(--red-soft);
  border-color: var(--red);
  color: var(--toast-error-tx);
}

/* Tomme pladser er usynlige i drift, synlige i editoren */
.gridcell--empty { background: transparent; border: none; }
.gridcell--slot {
  background: transparent;
  border: 1px dashed var(--line-1);
  color: var(--line-2);
  align-items: center;
  justify-content: center;
  font-size: 17px;
  font-weight: 700;
}
.gridcell--slot:hover {
  border-color: var(--orange);
  color: var(--orange);
  background: var(--orange-soft);
}

.gridcell.is-selected {
  outline: 2px solid var(--orange);
  outline-offset: 1px;
}

/* ---------- Paneler ---------- */
.gridcell--panel {
  background: rgba(63, 140, 255, .10);
  border: 1px dashed var(--blue);
  border-left: 3px solid var(--blue);
  align-items: flex-start;
  justify-content: flex-start;
  padding: 8px 10px;
}
.gridcell__panelinfo {
  position: absolute;
  bottom: 4px;
  right: 6px;
  font-size: 10.5px;
  font-weight: 700;
  color: var(--blue);
  font-variant-numeric: tabular-nums;
}
/* Panelet er for lille til at kunne bruges */
.gridcell--panel[title*="mindst"] {
  border-color: var(--at-late);
  background: rgba(242, 140, 28, .12);
}

/* Værten tegner selv indholdet i drift */
.gridcell--panelhost {
  background: transparent;
  border: none;
  padding: 0;
  display: flex;
  min-height: 0;
  overflow: hidden;
}
.gridcell--panelhost > * { flex: 1 1 auto; min-width: 0; min-height: 0; }

/* ---------- Paneler i drift ---------- */
.panel {
  display: flex;
  flex-direction: column;
  min-width: 0;
  min-height: 0;
  width: 100%;
  height: 100%;
  padding: 8px;
  border-radius: var(--r-sm);
  background: var(--bg-2);
  border: 1px solid var(--line-1);
  gap: 6px;
  overflow: hidden;
}
.panel--info { flex-direction: row; padding: 6px 10px; }
.panel--regning { padding: 6px; gap: 5px; }
.panel--total { justify-content: flex-end; }
.panel--gaester { flex-direction: row; padding: 5px 8px; }
.panel--soeg { padding: 4px; }
.panel--tastatur { padding: 5px; }
.panel--tastatur .keypad { height: 100%; }
.panel--tastatur .keypad__grid { flex: 1 1 auto; }
.panel--tastatur .key { min-height: 0; }
.panel--tastatur .keypad__display { height: 40px; font-size: 20px; }

/* ---------- Træk og slip ---------- */
.gridcell--edit { cursor: grab; touch-action: none; }
.gridcell--edit.is-dragging { cursor: grabbing; opacity: .45; }

.gridcell__grip {
  position: absolute;
  right: 0;
  bottom: 0;
  width: 18px;
  height: 18px;
  cursor: nwse-resize;
  opacity: 0;
  transition: opacity .12s;
  /* De to skrå streger der viser at hjørnet kan trækkes */
  background:
    linear-gradient(135deg, transparent 45%, currentColor 45%, currentColor 55%, transparent 55%),
    linear-gradient(135deg, transparent 70%, currentColor 70%, currentColor 80%, transparent 80%);
}
.gridcell--edit:hover .gridcell__grip,
.gridcell.is-selected .gridcell__grip { opacity: .55; }
.gridcell__grip:hover { opacity: 1 !important; }

/* Skygge der viser hvor feltet lander */
.gridshadow {
  border: 2px solid var(--orange);
  background: var(--orange-soft);
  border-radius: var(--r-sm);
  pointer-events: none;
  z-index: 5;
}
.gridshadow--blokeret {
  border-color: var(--red);
  background: rgba(229, 72, 77, .18);
}

@container pos (max-width: 819px) {
  .buttongrid { gap: 3px; grid-auto-rows: minmax(48px, auto); }
  .gridcell { padding: 4px 6px; }
  .gridcell__label { font-size: 12px; -webkit-line-clamp: 2; }
}

/* ------------------------------------------------------------
   OTTE SMALLE KNAPPER SKAL KUNNE LÆSES

   Med husets otte kolonner (`kolonner.liggende` i
   `skaermprofiler.js`) og kategorisøjlen ved siden af blev
   varetasten 84 px bred. To linjer à 13 px rummer «OSTEBRÆT»
   men ikke «CHARCUTERIE», og så stod der «CHARCU…» på en tast,
   tjeneren skal ramme uden at læse.

   MÅLT 10. september 2026 på 1440 × 710: 84 × 50 px pr. tast,
   otte af de 66 navne på forsiden blev hugget af.

   En tredje linje er der plads til, når tasten er høj nok —
   navnet fylder resten, prisen står stadig under. Under 78 px
   bredde er tre linjer ikke nok, og så skrumper skriften det
   sidste stykke. Bunden på 44 px i højden er urørt; det er
   husets regel.
   ------------------------------------------------------------ */
.gridcell--vare .gridcell__label {
  /* Tre linjer, naar navnet er flere ord — «TAPAS PR PERSON». */
  -webkit-line-clamp: var(--knaplinjer, 3);
  /* Og en anelse mindre skrift. Husets regel er, at et ord ikke
     braekkes midt over (`overflow-wrap: normal` ovenfor, med sin
     egen begrundelse) — saa et LANGT ENKELT ord kan kun komme
     med, hvis bogstaverne er smallere. «CHARCUTERIE» er 68 px ved
     13 px og 60 ved 11,5; tasten har 70. */
  font-size: 11.5px;
  line-height: 1.08;
  /* ------------------------------------------------------------
     NAVNET MAA BRUGE HELE KNAPPEN

     Knappen er 88 px, polstringen tager 7 px i hver side, og
     navnet fik 72. Polstringen er der for fingerens skyld — den
     skal ikke ogsaa koste bogstaver.

     MAALT i den koerende kasse 10. september 2026: «AMARETTO
     SOUR» kraevede 74 px, «STRAWBERRY SOUR» 76, «GLAS
     CHARDONNAY» 78. Alle tre var hugget af med to til seks pixels
     — og et ord braekkes aldrig, saa en linjeklemme kan ikke give
     dem en ellipse.

     Navnet laaner fire pixels tilbage i hver side. Der er stadig
     luft, og fingermaalet paa 44 px i hoejden er uroert: det er
     kun teksten, der bliver bredere.
     ------------------------------------------------------------ */
  margin-left: -4px;
  margin-right: -4px;
  width: calc(100% + 8px);
}

/* ============================================================
   ET ENKELT LANGT ORD — EEN LINJE MED EN RIGTIG ELLIPSE

   Et ord uden mellemrum kan ikke ombrydes, og huset braekker
   aldrig et ord midt over (se «F-055» ovenfor). Saa er der kun
   een aerlig maade at vise «CHARCUTERIE» i 72 px paa: een linje,
   der klippes med «…».

   MAALT i den koerende kasse: 26 af 66 varenavne paa forsiden var
   klippet, og ingen af dem havde et tegn. «CHARCUTER» uden
   ellipse er ikke en forkortelse — det er et andet ord.

   Hele navnet staar stadig i knappens `title`.
   ============================================================ */
.gridcell__label--etord > .gridcell__navn {
  display: block;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  -webkit-line-clamp: none;
  line-clamp: none;
}

/* ============================================================
   KLEMMEN BOR PAA BARNET

   `.gridcell` er en flexbeholder, og et flexbarn blokificeres:
   `display: -webkit-box` paa etiketten regnes ud som `flow-root`,
   og saa gaelder `-webkit-line-clamp` ikke. Etiketten var bare en
   kasse med `overflow: hidden`, og den sidste linje blev hugget
   af UDEN ellipse.

   MAALT i den koerende kasse 10. september 2026: «GLAS ZINFANDEL
   COCOON» stod som «GLAS ZINFANDEL». Otte navne paa forsiden.

   `.gridcell__navn` er ikke et flexbarn. Der virker klemmen.
   ============================================================ */
.gridcell__navn {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: var(--knaplinjer, 2);
  line-clamp: var(--knaplinjer, 2);
  overflow: hidden;
  text-overflow: ellipsis;
  overflow-wrap: normal;
  word-break: normal;
  hyphens: none;
  width: 100%;
}

/* ------------------------------------------------------------
   EDITORENS FANESOEJLE

   En KOPI af kassens soejle, i samme maal — se noten i
   `layoutEditor.js`. Den er ikke til at roere: fanerne baeres af
   kataloget, ikke af knapsiden.
   ------------------------------------------------------------ */
/* `nowrap`: soejlen og gitteret staar ved siden af hinanden, som
   paa kassen. Med `wrap` blev gitteret skubbet NED under soejlen,
   saa snart husets kolonner kraevede mere end resten af bredden —
   og saa saa editoren ikke ud som kassen alligevel. Er gitteret
   bredere end fladen, ruller det vandret, som det altid har
   gjort. */
/* Ingen lodret rulning, naar huset har valgt raekketallet: gitteret
   deler den plads, der er, praecis som paa kassen. Se noten ved
   `gridTemplateRows` i `buttonGrid.js`. */
.editorflade--medfaner { display: flex; flex-wrap: nowrap; gap: 8px; align-items: stretch;
  overflow-y: hidden; }
.editorflade--medfaner > p.muted {
  position: absolute; left: 10px; right: 10px; top: 10px; margin: 0;
}
.editorflade--medfaner { position: relative; padding-top: 44px !important; }
.editorflade--medfaner > .buttongrid { flex: 1 1 0; min-width: 0; overflow-x: auto; }
/* Soejlen kan TRYKKES — den aabner fanevaelgeren. Knapperne i den
   kan ikke traekkes rundt; de er ikke husets knapper. */
.editor__faner { opacity: .9; cursor: pointer; }
.editor__faner .katstribe__knap { pointer-events: none; cursor: pointer; }
.editor__faner:hover { opacity: 1; outline: 2px dashed var(--line-strong); outline-offset: 2px; }

/* Gavekort — visning og print */
.giftcard {
  background: linear-gradient(140deg, var(--giftcard-1) 0%, var(--giftcard-2) 100%);
  border: 2px solid var(--orange);
  border-radius: var(--r-lg);
  padding: 22px;
  text-align: center;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.giftcard__brand {
  font-size: 12px;
  font-weight: 800;
  letter-spacing: 3px;
  color: var(--orange);
}
.giftcard__amount {
  font-size: 40px;
  font-weight: 800;
  letter-spacing: -1px;
}
.giftcard__code {
  font-family: var(--mono);
  font-size: 19px;
  font-weight: 700;
  letter-spacing: 3px;
  padding: 10px;
  background: var(--bg-0);
  border-radius: var(--r-sm);
  word-break: break-all;
}
.giftcard__meta { font-size: 12.5px; color: var(--tx-2); }
.giftcard__msg { font-size: 14px; font-style: italic; color: var(--tx-1); }
.giftcard__terms {
  font-size: 10.5px;
  color: var(--tx-3);
  line-height: 1.45;
  border-top: 1px solid var(--line-1);
  padding-top: 10px;
}

/* TEMAFAST — papir er altid sort på hvidt og må ikke følge temaet */
@media print {
  .giftcard {
    background: #fff;
    color: #000;
    border-color: #000;
  }
  .giftcard__brand, .giftcard__amount, .giftcard__msg { color: #000; }
  .giftcard__code { background: #eee; color: #000; }
  .giftcard__meta, .giftcard__terms { color: #333; }
}
/* TEMAFAST SLUT */

/* Kombinationsmenu på regningen — én post med retterne under */
.combobox {
  border: 1px solid var(--purple);
  border-radius: var(--r-md);
  background: rgba(157, 107, 255, .07);
  overflow: hidden;
}
.combobox__head {
  display: flex;
  align-items: baseline;
  gap: 8px;
  padding: 8px 10px;
  background: var(--st-betaler-bg);
  font-size: 14.5px;
}
.combobox__save {
  padding: 0 10px 6px;
  font-size: 11.5px;
  color: var(--st-betaler-tx);
  font-weight: 600;
}

/* Byttepenge- og kursvisning i betalingsdialogerne */
/* Byttepengene staar nu i kortet oeverst, sammen med «At betale».
   Den er en linje mellem to tal, ikke en tekstboks — derfor uden
   egen ramme og med husets groenne paa selve beloebet. */
.paychange {
  min-height: 24px;
  font-size: 14px;
  line-height: 1.5;
}
.paychange .strong { color: var(--green); }
.paychange:empty { display: none; }
/* `.total-line` saetter `display: flex`, og en forfatterregel slaar
   browserens egen `[hidden] { display: none }`. Uden den her stod
   ordet «Byttepenge» med et tomt tal, foer der var tastet noget. */
.paychange[hidden] { display: none; }
.paychange--error { border-color: var(--red); color: var(--toast-error-tx); }

/* Advarsel om manglende obligatorisk valg i produktdialogen */
.reqbanner {
  background: var(--orange-soft);
  border: 1px solid var(--orange);
  color: var(--st-service-tx);
  border-radius: var(--r-md);
  padding: 10px 12px;
  font-size: 13.5px;
  font-weight: 700;
  line-height: 1.3;
}

/* ============================================================
   KDS — køkken- og barskærm
   Læsbar på afstand, høj kontrast, store bogstaver.
   ============================================================ */
.kds-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(268px, 1fr));
  gap: 10px;
  align-content: start;
}

.kds-card {
  display: flex;
  flex-direction: column;
  background: var(--bg-2);
  border: 2px solid var(--line-2);
  border-radius: var(--r-lg);
  overflow: hidden;
}
.kds-card--wait { border-color: var(--yellow); opacity: .96; }
.kds-card--ready { border-color: var(--green); }
.kds-card--allergy { border-color: var(--red); }

.kds-card__head {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 8px;
  padding: 10px 12px;
  background: var(--bg-3);
  border-bottom: 1px solid var(--line-1);
}
.kds-card__table { font-size: 19px; font-weight: 800; letter-spacing: .5px; }
.kds-card__meta { font-size: 11.5px; color: var(--tx-3); margin-top: 2px; }
/* Hvor bonnen kom fra. Læsbar på afstand, men aldrig så stor at
   den forveksles med det bord, maden skal bæres hen til. */
.kds-card__fra { font-size: 13px; font-weight: 700; color: var(--at-late); margin-top: 1px; }
.kds-card__time {
  font-size: 17px;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  margin-top: 4px;
}

.kds-allergy {
  background: var(--red);
  color: var(--tx-on-danger);
  font-weight: 800;
  font-size: 13px;
  letter-spacing: 1px;
  text-align: center;
  padding: 6px;
}

.kds-waitbar {
  background: var(--yellow);
  color: var(--tx-inv);
  font-weight: 800;
  font-size: 12px;
  letter-spacing: 1px;
  text-align: center;
  padding: 6px;
}

.kds-card__lines {
  flex: 1 1 auto;
  min-height: 0;
  padding: 10px 12px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.kds-line { display: flex; gap: 10px; align-items: flex-start; }
.kds-line--void { opacity: .4; text-decoration: line-through; }
.kds-line__qty {
  flex: 0 0 auto;
  min-width: 32px;
  font-size: 19px;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
}
.kds-line__name { font-size: 16px; font-weight: 700; line-height: 1.2; letter-spacing: .2px; }
.kds-line__mods { font-size: 13px; color: var(--tx-2); font-weight: 600; margin-top: 2px; }
.kds-line__mods .neg { color: var(--tx-neg); }
.kds-line__allergy {
  font-size: 13px;
  font-weight: 800;
  color: var(--tx-on-danger);
  background: var(--red);
  padding: 3px 6px;
  border-radius: 4px;
  margin-top: 4px;
  display: inline-block;
}
.kds-line__note { font-size: 13px; font-weight: 700; color: var(--yellow); margin-top: 2px; }

.kds-card__foot {
  flex: 0 0 auto;
  display: flex;
  /* ------------------------------------------------------------
     FIRE KNAPPER SKAL KUNNE VÆRE DER — ELLERS BRYDER DE

     «Start · Klar · Bon · Gensend» stod på én række uden
     ombrydning i et kort, der kun er 268 px bredt. Kortet har
     `overflow: hidden`, så den sidste blev skåret midt over:
     målt 31. august 2026 på 852 x 393 stod der «Gensen», og
     27 px var væk.

     Køkkenet læser det her på afstand og trykker med en handske
     eller en våd finger. En knap, hvis navn er hugget af, er en
     knap, ingen tør trykke på.

     Med ombrydning bliver kortet højere i stedet for smallere.
     Højden er der plads til — gitteret ruller.
     ------------------------------------------------------------ */
  flex-wrap: wrap;
  gap: 6px;
  padding: 10px 12px;
  border-top: 1px solid var(--line-1);
}
.kds-card__foot > .btn { flex: 1 1 auto; min-width: 0; }

@container pos (max-width: 639px) {
  .kds-grid { grid-template-columns: 1fr; }
}

/* ============================================================
   Bon — sort/hvid til termisk printer
   ============================================================ */
/* TEMAFAST — papir er altid sort på hvidt og må ikke følge temaet */
.bon {
  width: 302px;
  margin: 0 auto;
  background: #fff;
  color: #000;
  font-family: var(--mono);
  font-size: 12px;
  line-height: 1.35;
  padding: 10px 12px;
  white-space: pre-wrap;
}
.bon__hr { border-top: 1px dashed #000; margin: 6px 0; }
.bon__big { font-size: 17px; font-weight: 700; letter-spacing: .5px; }
.bon__center { text-align: center; }
.bon__box {
  border: 3px solid #000;
  padding: 6px;
  text-align: center;
  font-weight: 700;
  font-size: 15px;
  letter-spacing: 2px;
  margin: 6px 0;
}
.bon__line { display: flex; gap: 8px; }
.bon__qty { flex: 0 0 auto; min-width: 26px; font-weight: 700; }
.bon__mod { padding-left: 26px; }
.bon__allergy {
  border: 3px solid #000;
  background: #000;
  color: #fff;
  padding: 4px 6px;
  font-weight: 700;
  text-align: center;
  margin: 4px 0;
}

@media print {
  body { background: #fff; color: #000; }
  .app-root, .toast-host, .modal-backdrop { display: none !important; }
  .bon-print-host { display: block !important; }
  .bon { width: auto; padding: 0; }
  @page { margin: 4mm; }
}

/* TEMAFAST SLUT */
/* ---------- Tastatur på skærmen ---------------------------------- */
/* Kasserne har hverken mus eller tastatur, så al fritekst skrives her */
/* Feltet er et <input>, ikke en <div> — se keyboard.js. Et input
   arver hverken skrifttype, bredde eller farve, så de står her.
   Målene er de samme som før, så dialogen ikke skifter udseende. */
.kbd__display {
  display: block; width: 100%; box-sizing: border-box;
  min-height: 52px; padding: 12px 14px;
  background: var(--bg-0); border: 2px solid var(--accent);
  border-radius: var(--r-md);
  font-family: inherit; color: var(--tx-1);
  font-size: 18px; line-height: 1.35; word-break: break-word;
}
.kbd__display::placeholder { color: var(--tx-3); opacity: 1; }
/* Rammen er accentfarvet i forvejen. En browserring oven i den
   flytter feltet en pixel og ser ud som en fejl. */
.kbd__display:focus { outline: none; box-shadow: 0 0 0 3px var(--accent-svag, rgba(255,255,255,.14)); }
.kbd__count { font-size: 12px; color: var(--tx-3); text-align: right; }
.kbd { display: block; }
.kbd__row { display: flex; gap: 6px; margin-bottom: 6px; }
.kbd__key {
  flex: 1 1 0; min-width: 0; min-height: 54px;
  background: var(--bg-3); color: var(--tx-1);
  border: 1px solid var(--line-2); border-radius: var(--r-md);
  font-size: 19px; font-weight: 600; cursor: pointer;
  -webkit-user-select: none; user-select: none;
}
.kbd__key:active { background: var(--accent); color: var(--accent-tx); }
.kbd__key--mod { flex: 1.4 1 0; font-size: 15px; background: var(--bg-2); }
.kbd__key--on { background: var(--accent); color: var(--accent-tx); }
.kbd__key--space { flex: 6 1 0; font-size: 15px; }

/* ------------------------------------------------------------
   TASTERNE LAGT NED

   `display: none` og ikke `height: 0` med overflow: et skjult
   gitter må ikke kunne rammes af en finger, der lander lige uden
   for kanten, og det må ikke tælle med, når dialogen måler sin
   egen højde. Dialogen krymper, så det, der står bagved, kommer
   til syne — det er hele formålet.
   ------------------------------------------------------------ */
.kbd-omslag { display: block; }
.kbd-omslag--skjult { display: none; }

.kbd__minimer {
  width: 100%;
  min-height: var(--touch-min);
  justify-content: center;
  font-size: 15px;
  letter-spacing: .2px;
}

/* Felt der ligner et inputfelt, men åbner tastaturet ved tryk */
.tekstfelt {
  display: block; width: 100%; min-height: 48px;
  padding: 12px 14px; text-align: left;
  background: var(--bg-3); color: var(--tx-1);
  border: 1px solid var(--line-2); border-radius: var(--r-md);
  font-size: 15px; line-height: 1.35; cursor: pointer;
  word-break: break-word;
}
/* ------------------------------------------------------------
   EN TOM FELTTEKST SKAL OGSAA KUNNE LAESES

   «Bordnummer eller klokkeslæt» er ikke pynt — det er den eneste
   forklaring paa, hvad man skal taste. Den stod i `--tx-3`, som
   giver 5,12:1 paa husets moerkeste flade, men kun **4,35:1**
   inde i en dialog, hvor bunden er lysere. Maalt 1. september
   2026 paa «Genkald».

   Rettelsen viste sig at vaere `--tx-3` selv: det token var for
   moerkt paa husets lyseste flade. Se «DAEMPET — MEN STADIG
   LAESBAR» ved tokenet. Felttekster bruger derfor stadig
   `--tx-3` — det er forskellen paa en tom og en udfyldt linje,
   der betyder noget her.
   ------------------------------------------------------------ */
.tekstfelt--tom { color: var(--tx-3); }
.tekstfelt--danger { border: 2px solid var(--red); background: var(--bg-0); }

/* ---------- Antalbjælken: taltastatur over varerne ----------- */
/* Seks sodavand skal koste to tryk: 6, og så varen. */
.antalbar {
  align-items: stretch;
  padding: 6px 10px;
  background: var(--bg-2);
  border-bottom: 1px solid var(--line-1);
  gap: 4px;
}
.antalbar--aktiv {
  background: var(--orange-soft);
  border-bottom: 2px solid var(--orange);
}
.antal__visning {
  flex: 0 0 74px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 17px;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  color: var(--tx-3);
  letter-spacing: .5px;
}
.antalbar--aktiv .antal__visning { color: var(--orange); font-size: 22px; }
.antal__ciffer {
  flex: 1 1 0;
  min-width: 0;
  min-height: 44px;
  padding: 0;
  font-size: 19px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}
.antal__ciffer--dim { opacity: .35; }
.antal__ciffer--ryd { flex: 0 0 52px; color: var(--tx-3); }

@container pos (max-width: 819px) {
  .antal__visning { flex: 0 0 58px; font-size: 15px; }
  .antal__ciffer { min-height: 40px; font-size: 17px; }
}


/* ---------- Valgliste: ét spørgsmål ad gangen ---------------- */
/* Store linjer, numre foran. Hånden skal kunne ramme uden at kigge. */
.valgliste__hjaelp {
  font-size: 13px;
  color: var(--tx-2);
  line-height: 1.45;
  margin-bottom: var(--sp-2);
}
.valgliste__rows { display: block; }
.valgliste__linje {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  min-height: 62px;
  padding: 10px 14px;
  margin-bottom: 6px;
  text-align: left;
  background: var(--bg-3);
  border: 1px solid var(--line-2);
  border-radius: var(--r-md);
  color: var(--tx-1);
  font-size: 18px;
  line-height: 1.25;
}
.valgliste__linje--valgt {
  background: var(--accent);
  color: var(--accent-tx);
  border-color: var(--accent);
  font-weight: 700;
}
.valgliste__linje--fra { opacity: .4; }
.valgliste__nr {
  flex: 0 0 34px;
  font-variant-numeric: tabular-nums;
  font-weight: 700;
  opacity: .8;
}
.valgliste__navn { flex: 1 1 auto; min-width: 0; }
.valgliste__pris {
  flex: 0 0 auto;
  font-variant-numeric: tabular-nums;
  font-weight: 700;
}

.valgliste__rul {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: var(--sp-2);
}
.valgliste__pil { flex: 0 0 84px; min-height: 46px; font-size: 18px; }
.valgliste__tael {
  flex: 1 1 auto;
  text-align: center;
  font-size: 13px;
  color: var(--tx-3);
  font-variant-numeric: tabular-nums;
}

.valgliste__tal {
  display: flex;
  gap: 5px;
  margin-top: var(--sp-3);
}
.valgliste__ciffer {
  flex: 1 1 0;
  min-width: 0;
  min-height: 46px;
  padding: 0;
  font-size: 18px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

/* På telefonen fylder listen skærmen — ingen småting at ramme forbi */
@container pos (max-width: 639px) {
  .valgliste__linje { min-height: 58px; font-size: 17px; }
  .valgliste__ciffer { min-height: 42px; font-size: 16px; }
}

/* ---------- Plus og minus direkte på linjen ------------------ */
/* Kun på varer der ikke er sendt — en sendt vare får ingen knapper,
   så ingen tror at de bare er holdt op med at virke. */
.linjeknapper {
  display: flex;
  flex: 0 0 auto;
  gap: 4px;
  align-self: center;
}
.linjeknap {
  /* ------------------------------------------------------------
     44, IKKE 40 — KASSEN ER OGSÅ EN TOUCHSKÆRM

     Reglen herunder gav 44 px «på en telefon», fordi 40 var
     «nok med en mus». Men huset har ingen mus: kasserne er rene
     touchskærme (se `bordinfo.js` om skærmtastaturet). Plus og
     minus står ved siden af hinanden og gør det MODSATTE af
     hinanden — et fejltryk giver gæsten en vare mere i stedet
     for en mindre, på hendes regning.

     Målt 22. august 2026 var de sammen med ANTAL-rækken de
     eneste trykmål under 44 på hele kassefladen.
     ------------------------------------------------------------ */
  width: var(--touch-min);
  height: var(--touch-min);
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--bg-3);
  border: 1px solid var(--line-2);
  border-radius: var(--r-md);
  color: var(--tx-1);
  font-size: 22px;
  font-weight: 700;
  line-height: 1;
}
.linjeknap:active { background: var(--accent); color: var(--accent-tx); }

/* ------------------------------------------------------------
   PLUS OG MINUS PÅ EN TELEFON

   40 px er nok med en mus. På en håndholdt sidder de to knapper
   lige ved siden af hinanden på en linje i regningen, og de gør
   det MODSATTE af hinanden. Rammer man forkert, får gæsten en
   vare mere i stedet for en mindre.

   Der er plads: linjen er bred, og knapperne er kvadratiske.
   ------------------------------------------------------------ */
@container pos (max-width: 639px) {
  .linjeknap { width: var(--touch-min); height: var(--touch-min); }
}

/* Linjen skal kunne følge fingeren under et swipe */
.orderline { transition: transform .12s ease-out; }

/* Plus på en sendt vare betyder "bestil én mere" — den skal
   skille sig ud, så man kan se at der sker noget nyt */
.linjeknap--plus { border-color: var(--accent); color: var(--accent); }

/* ============================================================
   Den faste tasteblok under regningen

   Fem taster på ÉN række. Pladserne ligger fast: en tast flytter
   sig aldrig, og der kommer aldrig en ekstra ind imellem dem.
   Det er hele pointen — hånden skal kunne finde RETUR uden at
   øjnene skal med.

   Blokken skal fylde så lidt som overhovedet muligt. Regningen
   er det man kigger på; tasterne skal bare være der.
   ============================================================ */
.funkblok {
  flex: 0 0 auto;
  display: grid;
  /* Bred række — bruges kun dér, hvor blokken ligger under noget */
  grid-template-columns: repeat(auto-fit, minmax(78px, 1fr));
  gap: 4px;
  padding: 5px 8px;
  background: var(--bg-2);
  border-top: 1px solid var(--line-1);
}

/* ------------------------------------------------------------
   LODRET STRIBE VED SIDEN AF REGNINGEN

   Tasterne handler om linjerne i regningen. Står de ved siden af,
   peger hånden på det, den arbejder med — og regningen får hele
   højden i stedet for at blive klemt af en bred tasterække.

   Bredden er fast. En tast, der ændrer bredde, fordi teksten
   skifter fra "Rette" til "RETTE TIL", ville flytte de andre —
   og så kan hånden ikke længere finde dem uden at kigge.
   ------------------------------------------------------------ */
.funkblok--lodret {
  grid-template-columns: 1fr;
  /* Alle ni skal kunne ses PÅ ÉN GANG. Skal man rulle for at nå
     Genkald, kan hånden ikke finde den uden at kigge — og så er
     hele pointen med en fast blok væk. `1fr` deler højden ligeligt
     i stedet for at give hver tast en mindstehøjde, der tvinger
     den sidste ud over kanten. */
  grid-auto-rows: 1fr;
  /* Højden skal komme fra rummet, ikke fra tasterne. Uden
     `height: 100%` regner gitteret sin egen højde ud af
     mindstehøjderne — og så stikker den sidste tast neden ud og
     bliver klippet af. Genkald var væk. */
  height: 100%;
  min-height: 0;
  width: 92px;
  padding: 0 6px 0 0;
  background: transparent;
  border-top: 0;
  overflow: hidden;
}
.funkblok--lodret {
  gap: 3px;
}
.funkblok--lodret .funk {
  /* INGEN mindstehøjde her. Rækkerne deler højden med `1fr`, og
     en mindstehøjde oven i den gør summen større end rummet — så
     stikker den sidste tast ud og bliver klippet af. Det var
     Genkald, der forsvandt.

     ------------------------------------------------------------
     F-055 · MEN SÅ MÅ BLOKKEN LÆGGE SIG I TO KOLONNER

     Følgen af `1fr` var, at ni taster på en lav skærm blev 26 px
     høje. Det er en musemålsknap, ikke en fingermålsknap.

     Første forsøg var en mindstehøjde på RUMMET. Det flyttede
     bare klipningen: nu stak Betal og Luk bord neden ud af siden.
     Højden er ikke til forhandling — den er, hvad skærmen giver.

     Det, der ER til forhandling, er hvor mange RÆKKER de ni
     taster ligger på. To kolonner giver fem rækker i stedet for
     ni, og så er der plads til 40 px hver. Se højde-forespørgslen
     nedenfor.
     ------------------------------------------------------------ */
  min-height: 0;
  font-size: 11.5px;
  padding: 2px;
  line-height: 1.05;
}

/* Rummet, tasterne og regningen deler */
.kasse__regningsrum {
  display: flex;
  gap: 0;
  min-height: 0;
  overflow: hidden;
}
.kasse__regningsrum > .kasse__regning { flex: 1 1 auto; min-width: 0; }
.kasse__regningsrum > .funkblok--lodret { flex: 0 0 auto; align-self: stretch; }

/* ------------------------------------------------------------
   F-055 · TO KOLONNER NÅR SKÆRMEN ER LAV

   Ni taster i én kolonne kræver 9 × 40 px + 8 × 3 px mellemrum
   = 384 px. Regningsrummet får sin højde af skærmen minus
   sortiment, antalfelt og betalingsknapper — cirka 460 px. Så
   under en skærmhøjde på ~845 px rækker én kolonne ikke.

   Grænsen er sat til 860 px med lidt luft. Over den er der plads
   til én kolonne (på kassernes 982 px bliver hver tast ~55 px);
   under den lægger blokken sig i to, og hver tast bliver højere
   end i én kolonne — ikke lavere.

   Rækkefølgen er stadig læseretning: Slet, Retur, Genkald …
   Hånden skal kunne finde dem uden at kigge, og en kolonne mere
   ændrer ikke, at pladsen er den samme hver gang.
   ------------------------------------------------------------ */
/* Reglen er flyttet: den styres nu af `data-pos-taster` fra
   motoren i stedet for af vinduets højde. Se blokken «TO
   KOLONNER — NÅR MOTOREN SIGER DET» længere oppe. */

/* Håndholdt: striben lægger sig ned igen. På en telefon er der
   ikke bredde til både taster og regning ved siden af hinanden. */
/* ------------------------------------------------------------
   FUNKTIONSBLOKKEN FLYTTER NED — NÅR MOTOREN SIGER DET

   Her stod `@media (max-width: 1100px)`. Tallet var rigtigt nok
   som tommelfingerregel: under det bliver der for lidt tilbage
   til regningslinjen, når blokken står ved siden af.

   Men et bredde-tal kan ikke se, hvor bred regningen faktisk
   BLEV. Den samme 1100 px skærm har forskellig plads i linjen,
   alt efter om regningen fik 400 eller 460, og om blokken står i
   én kolonne eller to. Målt 30. august 2026 på 958 px: blokken
   flyttede ned, men lagde sig som et fire-kolonners felt oven i
   regningen og skjulte ordrelinjerne.

   Nu regner `skaermlayout.js` det ud — regningens bredde minus
   blokkens 96 px skal levne de 230, linjen skal bruge — og
   svaret står i `data-pos-funktioner`. Se `skaermstyring.js`.
   ------------------------------------------------------------ */
:root[data-pos-funktioner="bund"] .kasse__regningsrum {
  flex-direction: column-reverse;
}
:root[data-pos-funktioner="bund"] .funkblok--lodret {
  width: auto;
  height: auto;
  grid-template-columns: repeat(auto-fit, minmax(78px, 1fr));
  grid-auto-rows: minmax(var(--touch-min, 44px), auto);
  padding: 5px 0 0;
  border-top: 1px solid var(--line-1);
  /* ------------------------------------------------------------
     ÉN RÆKKE, DER KAN SWIPES

     Dennis, 5. september 2026: «hvad med man lavede de knapper så
     der kun var en i højde, og man kan swipe i dem?»

     Tre rækker taster tog 144 px af et rum på 220. Én række tager
     54 — og de 90 px går til regningen, hvor de gør en forskel,
     man kan læse.

     Tasterne beholder deres fingerhøjde. Det er stablingen, der
     ryger, ikke størrelsen. Rækken ruller vandret med fingeren,
     og de fire, hånden bruger hele tiden — Rette, Fortryd,
     Gentag, Retur — står forrest, så de ligger samme sted hver
     gang. Man swiper efter de sjældne, ikke efter de daglige.

     Den her kopi er den, der gælder, fordi den står sidst i
     filen. Se noten ved den første forekomst.
     ------------------------------------------------------------ */
  flex: 0 0 auto;
  min-height: 0;
  /* Én række: kolonnerne løber vandret i stedet for at ombryde. */
  grid-auto-flow: column;
  /* ------------------------------------------------------------
     HELE ORDET, ELLER INTET

     `auto` maalte mod den plads, der var, ikke mod teksten — og
     «Send rettet bon» manglede otte pixels og stod som «end
     rettet bo». En taste, hvis navn er klippet, er en taste, man
     skal gaette paa.

     Dennis, 5. september 2026: «teksten på knapperne skal være
     synlig, den må ikke mangle noget tekst.»

     `max-content` giver hver taste praecis den bredde, ordet skal
     bruge; de 84 px er gulvet, saa de korte stadig kan rammes.
     Naar raekken alligevel ruller, koster en bred taste ingenting
     — den skubber bare de sjaeldne laengere ud.
     ------------------------------------------------------------ */
  grid-auto-columns: auto;
  grid-template-columns: none;
  grid-template-rows: minmax(var(--touch-min, 44px), auto);
  overflow-x: auto;
  overflow-y: hidden;
  /* Fingeren skal kunne kaste rækken, og den skal standse pænt. */
  -webkit-overflow-scrolling: touch;
  scroll-snap-type: x proximity;
  scrollbar-width: thin;
}
/* ============================================================
   PAA DEN STORE KASSE ER DER PLADS TIL FLERE RAEKKER

   ------------------------------------------------------------
   HVAD DER BLEV MAALT

   Een raekke, der ruller vandret, er husets egen beslutning fra
   5. september — Dennis: «hvad med man lavede de knapper saa der
   kun var en i hoejde, og man kan swipe i dem?» Den blev truffet
   for en skaerm, man HOLDER, hvor tre raekker taster tog 144 px
   af et rum paa 220.

   Men den kom til at gaelde alt, ogsaa kassen. MAALT i den
   koerende kasse 10. september 2026 paa 1440 x 710: tretten
   taster i en kasse paa 468 px. Otte af dem — Gavekort, Reprint,
   Opslag, Genkald, Regningen, Prisniveau, Send rettet bon og Se
   log — laa uden for kanten, og de kan kun naas ved at swipe. Paa
   en fastmonteret kasse med mus og en skaerm i fuld hoejde.

   ------------------------------------------------------------
   HVAD DER GAELDER NU

   Er fladen KLASSISK — altsaa kassen, over 1180 px — ombryder
   raekken igen. Tabletten og den haandholdte beholder den
   godkendte een-raekkes swipe, praecis som den blev besluttet;
   det er kun den store skaerm, der faar sin plads igen.

   Loftet paa hoejden staar: regningen skal stadig kunne laeses,
   og bliver der flere taster, end der er plads til, ruller
   blokken lodret i stedet for at aede listen.
   ============================================================ */
:root[data-pos-flade="klassisk"][data-pos-funktioner="bund"] .funkblok--lodret {
  grid-auto-flow: row;
  /* QA-14b fund 2: FEM kolonner i stedet for «så mange à 84 px, der er plads til» (fire i en spalte på 413 px). Fjorten taster
     er så tre rækker i stedet for fire (150 px i stedet for 198), og «Aktuel regning» får de 48 px — den havde kun 143 px
     (1,5 linje) på 1280 × 800. «Genåbn køkkenbestilling» fylder to kolonner (`.funk--lang`), så 13 + 2 = 15 pladser. */
  grid-template-columns: repeat(5, minmax(0, 1fr));
  grid-template-rows: none;
  grid-auto-columns: auto;
  grid-auto-rows: minmax(var(--touch-min, 44px), auto);
  overflow-x: hidden;
  overflow-y: auto;
  /* ------------------------------------------------------------
     TRE RAEKKER KOSTER 21 PX — OTTE SKJULTE TASTER KOSTER MERE

     MAALT i `fladetest` paa kassen: blokken vil have 143 px til
     sine tretten taster og fik 122, fordi den gav efter for
     listen. Tre taster — Prisniveau, Send rettet bon og Se log —
     laa saa under kanten.

     `0 0 auto` lader den beholde sine raekker.

     ------------------------------------------------------------
     OG LOFTET MAA IKKE SKAERE MIDT I EN RAEKKE

     Her stod `max-height: 40%`. En procent af regningsrummet er
     ikke et helt antal taster, og rummet skifter hoejde med
     regningen. MAALT i den koerende kasse med een vare paa bord
     12: rummet var 305 px, loftet 122, og blokken ville have 143.
     Saa stod «Prisniveau», «Send rettet bon» og «Se log» skaaret
     over paa midten — halve taster, der ligner en fejl og ikke en
     besked om at der er mere.

     Loftet er nu et HELT ANTAL RAEKKER. Tre raekker rummer husets
     tretten taster; bliver der flere, ruller blokken lodret — og
     den ruller til en hel raekke, ikke til en halv.
     ------------------------------------------------------------ */
  /* ------------------------------------------------------------
     FIRE RAEKKER — OG ET TEGN, NAAR DER ALLIGEVEL ER FLERE

     MAALT i browseren 18. oktober 2026 (QA-002), 1280 x 800: fjorten
     taster ligger i fire raekker à 4 kolonner. Loftet paa TRE raekker
     (143 px) lod «Se log» og «Genaabn koekkenbestilling» ligge i en
     fjerde raekke, der kun kunne naas ved at scrolle i blokken — uden
     scrollbar og uden nogen antydning. Loftet er nu fire raekker.

     Bliver der engang flere taster, ruller blokken stadig, men saa
     toner nederste raekke ud (`data-mere-ned`, sat af funktionsblok.js),
     saa det kan ses, at der er mere.
     ------------------------------------------------------------ */
  max-height: calc(4 * (var(--touch-min, 44px) + 4px) + 6px);
  flex: 0 0 auto;
  -webkit-mask-image: none;
  mask-image: none;
}
/* TEMAFAST — en maske er en stencil paa alfakanalen, ikke en farve */
:root[data-pos-flade="klassisk"][data-pos-funktioner="bund"] .funkblok--lodret[data-mere-ned="ja"] {
  -webkit-mask-image: linear-gradient(to bottom, #000 calc(100% - 22px), transparent 100%);
  mask-image: linear-gradient(to bottom, #000 calc(100% - 22px), transparent 100%);
}
/* TEMAFAST SLUT */
:root[data-pos-flade="klassisk"][data-pos-funktioner="bund"] .funkblok--lodret > .funk {
  width: auto;
  min-width: 0;
  /* Ombrydningen giver hver taste sin egen kolonne igen, og saa
     skal et langt navn kunne staa paa to linjer i stedet for at
     skubbe raekken bredere. */
  white-space: normal;
}

:root[data-pos-funktioner="bund"] .funkblok--lodret > .funk {
  scroll-snap-align: start;
  white-space: nowrap;
  /* Ingen ellipse her. Enten er der plads til ordet, eller ogsaa
     er tasten bred nok til at der bliver det — se `max-content`
     ovenfor. En afkortet tast maa ikke kunne opstaa i stilhed. */
  overflow: visible;
  text-overflow: clip;
  padding-left: 10px;
  padding-right: 10px;
  /* Gitterets `max-content` faldt tilbage paa gulvet paa 84 px,
     fordi tasten ikke selv bidrog med sin tekstbredde. Saa siger
     vi det direkte: bredden ER ordet, og 84 px er kun gulvet. */
  width: max-content;
  min-width: 84px;
}

/* Raekken ruller, og det skal kunne SES. Uden et tegn ligner den
   sidste synlige taste den sidste taste. */
:root[data-pos-funktioner="bund"] .kasse__regningsrum {
  position: relative;
}
/* TEMAFAST — en maske er ikke en farve, den er en stencil

   `#000` her er ikke sort. En maske laeses paa ALFAKANALEN: sort
   betyder «helt synlig», transparent betyder «helt vaek». Farven
   naar aldrig skaermen, og der er intet at rette i Udseende.

   Bandt vi den til en temavariabel, ville et lyst tema kunne
   goere masken gennemsigtig — og saa ville hele tasterraekken
   forsvinde i stedet for at tone ud i kanten. Den skal vaere
   uigennemsigtig i ethvert tema, og derfor staar den fast. */
:root[data-pos-funktioner="bund"] .funkblok--lodret {
  -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 26px), transparent 100%);
  mask-image: linear-gradient(to right, #000 calc(100% - 26px), transparent 100%);
}
/* TEMAFAST SLUT */
:root[data-pos-funktioner="bund"] .funkblok--lodret:not([data-mere="ja"]) {
  -webkit-mask-image: none;
  mask-image: none;
}
/* ------------------------------------------------------------
   HER LAA 568 LINJERS ORDRET KOPI AF LINJE 2018-2604.

   Fundet 12. september 2026, og den var ved at koste noget:
   `iphoneknaptest` klagede over kontrasten paa `.funk--paa`, og
   reglen stod TO gange — i kopien og i originalen. Rettede man
   den oeverste, vandt den nederste i stilles. Det er fejlklasse 1
   skrevet i CSS: to sandheder om det samme, og den daarlige er
   den, der gaelder.

   Maalt foer sletningen, ikke antaget:
     · 83 regler i kopien — alle findes ovenfor med ordret samme krop
     · ingen regel i kopien, som originalen ikke har
     · ingen selektor med samme navn og forskellig krop
     · tuborgbalancen er 0 baade foer og efter
     · kun EEN selektor (`.linjeknap--plus`) staar baade i blokken
       og i omraadet imellem — og de to saetter forskellige
       egenskaber, saa raekkefoelgen betyder ingenting for den

   En senere regel vinder altid, saa det at fjerne den TIDLIGERE
   af to ens kopier kan kun aendre noget, hvis der ligger en
   overskrivning imellem dem. Det er praecis dét, der blev maalt.
   ------------------------------------------------------------ */
/* ------------------------------------------------------------
   BORDPLANEN MÅ IKKE LØBE UD OVER SKÆRMEN

   Planen har sin egen geometri: husets rum er tegnet i et
   bestemt format, og `.pv__flade` er lige så høj, som rummet er.
   Er skærmen lavere, stak den ud forneden — ned under
   bundbjælken og videre ud af fladen.

   Målt 31. august 2026 på 800 × 600: arbejdsfeltet var 483 px,
   planen 480 px høj og lå fra 191 til 671. Borde og «ÅBN BORD»
   laa under navigationen, hvor de hverken kunne ses eller
   rammes.

   Planen skaleres ikke ned — et bord, der er for lille at ramme,
   er værre end et bord, man skal rulle til. I stedet ruller
   feltet, og hele rummet er stadig tilgængeligt.
   ------------------------------------------------------------ */
/* ============================================================
   PLANEN MAA IKKE SLUGE DEN RULNING, DEN IKKE HAR

   `.pv` var sin egen rulleflade med `overflow: auto` og
   `overscroll-behavior: contain`. Men den vokser med sit indhold
   og har derfor ALDRIG noget at rulle selv — det er den ydre
   `.floor__grid`, der ruller.

   Foelgen paa en telefon: fingeren lander paa planen, `.pv` tager
   rulningen, har intet at give, og `overscroll-behavior: contain`
   forbyder den at give den videre. Saa sker der ingenting.

   Maalt 2. september 2026 paa iPhone staaende: planen 1789 px
   hoej, rammen kunne rulle 844 px — og baade et swipe og et
   hjulrul paa planen flyttede den 0 px. De nederste to
   tredjedele af husets borde kunne ikke naas.

   Planen ruller ikke selv; den bliver saa hoej, den skal vaere,
   og rammen udenom ruller. Klipningen af det, der stikker uden
   for gulvets firkant, ligger i `.pv__flade` nedenfor og er
   uroert.
   ============================================================ */
/* ------------------------------------------------------------
   PLANEN SKAL STAA MIDT I LOKALET — OG GJORDE DET IKKE

   `.floor__grid` er `justify-content: safe center`, og noten dér
   siger selv hvorfor: planen skal staa midt i fladen. Men `.pv`
   havde `flex: 1 1 auto` og voksede ud i HELE bredden. En
   centrering af et barn, der allerede fylder alt, flytter
   ingenting — og `.pv__flade` inde i den lagde sig i venstre
   kant, som et blokelement goer.

   MAALT 10. september 2026 hos Toerst: fladen var 1139 px bred,
   `.pv` blev 1119, og rummet blev tegnet 729. 390 pixels tom
   plads i hoejre side, hver eneste optegning.

   Dennis: «Kan man ikke vaelge om den skal stretch eller faktisk
   stoerrelse — her mener jeg fylde skaermen — og saa om den skal
   centreres?»

   `flex: 0 0 auto` goer `.pv` praecis saa bred, som planen er.
   Saa virker centreringen, og «safe» sikrer stadig, at der ikke
   klippes af toppen, naar planen er stoerre end fladen.

   REGLEN STAAR TO STEDE I DEN HER FIL, ord for ord. Den sidste
   vinder. Rettes den ene og ikke den anden, siger de to hver sit
   om den samme flade (fejlklasse 1) — derfor er BEGGE rettet.
   ------------------------------------------------------------ */
.pv {
  padding: 12px;
  flex: 0 0 auto;
  min-height: 0;
  overflow: visible;
}
/* ------------------------------------------------------------
   RAMMEN ER RAMMEN

   Alt uden for planens firkant klippes væk på kassen. Sætter
   nogen et gulv, der stikker en meter ud over kanten, skal det
   ikke lægge sig hen over bordnumrene på tjenerens skærm.

   Det gælder KUN kassen. I editoren skal man kunne se, at noget
   stikker ud — ellers kan man ikke få fat i det igen. Der
   markeres det i stedet, se `.bp__flade` og "Tilpas planen".
   ------------------------------------------------------------ */
.pv__flade {
  position: relative;
  overflow: hidden;
  border-radius: var(--r-md);
}

.pv__bord {
  position: absolute;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0;
  padding: 2px;
  border-radius: var(--r-sm);
  border: 1.5px solid var(--line-2);
  background: var(--bg-3);
  color: var(--tx-1);
  overflow: hidden;
  touch-action: none;
  transition: none;
}
.pv__bord--rund { border-radius: 50%; }
.pv__bord--bar  { border-style: dashed; }

/* Farven er tilstanden. Ledigt er tomt og roligt; alt andet
   lyser, fordi der er nogen, der venter på noget. */
.pv__bord--ledigt      { background: var(--bg-1); border-style: dashed; color: var(--tx-3); }
/* Bordene ligger over gulve, vægge og bar — man skal kunne ramme
   dem, uanset hvad der er tegnet omkring dem */
.pv__bord { z-index: 5; }

.pv__bord--optaget     { background: var(--bg-4); border-color: var(--accent); }
.pv__bord--service     { background: var(--bg-4); border-color: var(--blue, var(--accent)); }
.pv__bord--betaler     { background: var(--orange-soft, var(--bg-4)); border-color: var(--orange); }
.pv__bord--betalt      { background: var(--green-soft, var(--bg-4)); border-color: var(--green); }
.pv__bord--klargoeres  { background: var(--bg-2); border-color: var(--line-2); color: var(--tx-3); }

/* Ventetid uden aktivitet — det er dét, der bliver til en klage.
   Gul ved 10 minutter, rød ved 15, og ved 20 en stiplet kant:
   så er bordet ikke bare sent, det er glemt, og den stiplede
   kant skal kunne ses tværs gennem lokalet. */
/* Ventetidens ringe er blevet til statusringene nedenfor. Kun
   den stiplede kant ved «glemt» bliver — den siger noget, farven
   ikke kan: ingen har vaeret der i tyve minutter. */
.pv__bord--haster-gul   { }
.pv__bord--haster-roed  { }
.pv__bord--haster-glemt {
  outline: 3px dashed var(--red);
  outline-offset: 3px;
}

.pv__bord--traekker { z-index: 20; opacity: .9; box-shadow: 0 10px 30px rgba(0,0,0,.6); }
.pv__bord.is-maal   { outline: 3px solid var(--accent); outline-offset: 2px; }

.pv__tekst { display: flex; flex-direction: column; align-items: center; line-height: 1.15; }
.pv__navn    { font-size: 15px; font-weight: 800; line-height: 1.05; }

/* ------------------------------------------------------------
   NAVNET PÅ SELSKABET

   Det skal være tydeligt — det er dét, tjeneren leder efter — og
   det må ALDRIG gøre bordet højere. Et bord, der vokser, skubber
   tid, beløb og VENT ud over kanten, og på en plan med 55 borde
   hopper hele lokalet.

   Derfor: én linje, fast linjehøjde, og `ellipsis` når navnet er
   for langt. Bredden bindes til bordfeltet, ikke til teksten, så
   «Familien Sørensen-Bjerregaard» klippes i stedet for at brede
   sig ud over nabobordet. Hele navnet står i `title` og inde i
   borddialogen.
   ------------------------------------------------------------ */
.pv__bordnavn {
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 11px;
  font-weight: 700;
  line-height: 1.1;
  letter-spacing: .1px;
}

/* ------------------------------------------------------------
   ET SELSKAB PÅ FLERE BORDE

   Otte mennesker ved bord 20 og 21 er ÉT selskab og ÉN regning.
   Uden et mærke ligner det to selskaber, der tilfældigvis kom
   samtidig — og så bæres maden hen til det forkerte bord.

   Alle bordene i kombinationen får en ramme, så man kan se, at de
   hører sammen. Bonbordet får en fuldt optrukket ramme og teksten
   "20 + 21"; de øvrige får en stiplet og en pil hen mod bonbordet.
   Forskellen er ikke kun farve — en tjener, der ikke ser forskel
   på grøn og gul, skal stadig kunne se, hvor regningen hænger.
   ------------------------------------------------------------ */
.pv__samlet {
  font-size: 10px;
  font-weight: 700;
  color: var(--tx-2);
  line-height: 1.1;
  font-variant-numeric: tabular-nums;
}
.pv__bord--samlet {
  outline: 2px dashed var(--tx-3);
  outline-offset: -3px;
}
.pv__bord--samlet.pv__bord--bonbord {
  outline: 2.5px solid var(--tx-2);
}
.pv__pladser { font-size: 10px; color: var(--tx-3); }
.pv__tid     { font-size: 10.5px; color: var(--tx-3); font-variant-numeric: tabular-nums; }
/* Stakken i en bordfigur var cirka 6 px hoejere end figuren, saa
   nederste linje blev skaaret. Tallene staar taettere; de er korte
   og skal laeses paa afstand, ikke laeses laenge. */
.pv__belob   { font-size: 11.5px; font-weight: 700; font-variant-numeric: tabular-nums;
               line-height: 1.05; max-width: 100%; overflow: hidden;
               text-overflow: ellipsis; white-space: nowrap; }
.pv__navn    { line-height: 1.05; }
.pv__tjener {
  position: absolute; top: 2px; right: 4px;
  font-size: 9.5px; font-weight: 800; color: var(--tx-3);
}
.pv__vent {
  position: absolute; bottom: 2px; left: 4px;
  font-size: 8.5px; font-weight: 800; color: var(--red);
  letter-spacing: .5px;
}

.pv__element {
  position: absolute;
  display: flex; align-items: center; justify-content: center;
  border-radius: 3px;
  font-size: 10px;
  color: var(--tx-3);
  background: var(--bg-2);
  border: 1px solid var(--line-1);
  pointer-events: none;
}
.pv__element--vaeg  { background: var(--line-2); border: none; }
.pv__element--doer  { background: transparent; border-style: dashed; }
.pv__element--tekst { background: transparent; border: none; }

/* Stolene omkring bordet */
.pv__gruppe { position: absolute; }
.pv__gruppe > .pv__bord { position: absolute; }
/* ============================================================
   STOLENE ER TEGNING PÅ EN FLADE, MAN RØRER VED

   Stolen er en rigtig knap: et tryk åbner bordet PÅ den plads.
   Men den tegnes i målestok sammen med bordet, og målt 31. august
   2026 på iPad blev den 12 x 12 px. Husets eget fingermål er 44.

   Et fejltryk lander på bordet nedenunder, som gør noget ANDET —
   åbner regningen uden plads. Genvejen var altså ikke bare svær;
   den var upålidelig på præcis den måde, der er værst: den så ud
   til at virke.

   At give stolen et større trykfelt ville lægge det hen over
   bordkanten og nabostolene, og så ville et tryk på bordet ramme
   en stol i stedet. Byttet er ikke bedre — det er bare omvendt.

   Derfor: på den kompakte flade er stolen tegning. Trykket går
   til bordet, hvor det hører hjemme, og pladsen vælges i
   ORDRE > «Næste gæst · skift stol», hvor feltet er 96 px højt.
   Funktionen forsvinder ikke; den flytter derhen, hvor den kan
   rammes. Se det godkendte design: ingen funktion må ligge bag
   noget, der er svært at ramme.

   Den store kasse med mus beholder genvejen. Dér kan 12 px rammes.
   ============================================================ */
:root[data-pos-flade="kompakt"] .pv__stol { pointer-events: none; }

.pv__stol {
  position: absolute;
  display: flex; align-items: center; justify-content: center;
  border-radius: 50%;
  border: 1px solid var(--line-2);
  background: var(--bg-2);
  color: var(--tx-3);
  font-size: 9px;
  font-weight: 700;
  padding: 0;
  line-height: 1;
  touch-action: none;
  z-index: 2;
}
/* En plads der er bestilt til, skal kunne ses uden at åbne regningen */
.pv__stol--optaget {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--tx-on-accent);
}

/* Farve på bordet — "Uden Bar Print" er ikke et gæstebord, og
   det skal kunne ses på en halv meters afstand */
.pv__bord--f-groen { background: var(--green-soft, var(--bg-4)); border-color: var(--green); }
.pv__bord--f-blaa  { background: var(--bg-4); border-color: var(--blue, var(--accent)); }
.pv__bord--f-gul   { background: var(--orange-soft, var(--bg-4)); border-color: var(--orange); }
.pv__bord--f-lilla { background: var(--bg-4); border-color: var(--purple, var(--tx-3)); }

/* Besked på bordet — den skal kunne ses PÅ planen */
.pv__besked {
  position: absolute; top: 2px; left: 4px;
  width: 13px; height: 13px;
  display: flex; align-items: center; justify-content: center;
  border-radius: 50%;
  background: var(--orange);
  color: var(--tx-on-danger);
  font-size: 9.5px; font-weight: 800;
}

/* Bord info */
.bordinfo__besked {
  padding: 10px 12px;
  border-radius: var(--r-sm);
  background: var(--orange-soft, var(--bg-3));
  border-left: 3px solid var(--orange);
  font-size: 14px;
  line-height: 1.5;
}
.bordinfo__plads {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 5px 0;
  border-bottom: 1px solid var(--line-1);
}
.bordinfo__plads:last-child { border-bottom: none; }
.bordinfo__nr {
  flex: 0 0 auto;
  width: 26px; height: 26px;
  display: flex; align-items: center; justify-content: center;
  border-radius: 50%;
  border: 1px solid var(--line-2);
  font-size: 12px; font-weight: 700;
}
.bordinfo__navn { flex: 1 1 auto; min-width: 0; }
.bordinfo__sum {
  flex: 0 0 auto;
  min-width: 86px;
  text-align: right;
  font-variant-numeric: tabular-nums;
  font-weight: 700;
}
.bordinfo__plads--fri { opacity: .8; }
/* Knappen må ikke brække "Bestil" over to linjer */
.bordinfo__plads .btn { flex: 0 0 auto; white-space: nowrap; }

/* Bordet er lovet væk */
.pv__bord--booket    { border-style: solid; border-color: var(--blue, var(--accent)); }
.pv__bord--forsinket { border-style: solid; border-color: var(--red); }
.pv__booket {
  font-size: 10px;
  font-weight: 700;
  line-height: 1.1;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ---------- MÆRKET FOR EN BOOKING ----------
   Navnet stod her før og blev klippet: Havnevej har 55 borde, så
   feltet er hundrede pixels bredt, og "Familien Bjerre" blev til
   "Familie". Det ligner en fejl.

   Nu bærer bordet de to ting, man skal bruge på tværs af et
   lokale: at der ER en booking, og hvornår. Resten står i
   dialogen, hvor der er plads.

   Aldrig kun farve. Klokkeslættet står ved siden af, så en
   tjener, der ikke ser forskel på gul og grøn — og det er hver
   tolvte mand — stadig kan læse bordet. */
.pv__bookingmaerke {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  flex: 0 0 auto;
  margin: 1px auto 0;
  box-shadow: 0 0 0 1.5px rgba(0, 0, 0, .35);
}
.pv__bookingmaerke--booket    { background: var(--blue); }
.pv__bookingmaerke--forsinket { background: var(--red); }
.pv__bookingmaerke--sidder    { background: var(--green); }
.pv__bookingtid {
  font-size: 10px;
  font-weight: 700;
  line-height: 1.15;
  font-variant-numeric: tabular-nums;
  max-width: 100%;
  overflow: hidden;
  white-space: nowrap;
}
/* ---------- FLYT TIL ET ANDET BORD ----------
   Alle husets borde i én rullende skuffe, i husets orden med
   laveste nummer først. Optagne borde kan ikke vælges — de er
   slukkede, ikke skjulte, så man kan se HVORFOR bordet ikke kan
   bruges i stedet for at lede efter det. */
.res__skuffe {
  max-height: 46vh;
  overflow: auto;
  border: 1px solid var(--line-1);
  border-radius: 10px;
  padding: 6px;
}
.res__omrhoved {
  position: sticky;
  top: 0;
  z-index: 1;
  background: var(--bg-2);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: .02em;
  text-transform: uppercase;
  color: var(--tx-2);
  padding: 6px 4px 4px;
}
.res__borde {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(78px, 1fr));
  gap: 6px;
  margin-bottom: 6px;
}
.res__bord {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1px;
  padding: 8px 4px;
  min-height: 52px;
}
.res__bord.is-valgt { background: var(--blue); color: var(--bg-1); border-color: var(--blue); }
.res__bord.is-taget { opacity: .38; }
/* Rækker de valgte borde ikke til selskabet, skal det stå MENS man
   vælger — ikke først når autoriteten siger nej. */
.res__mangler { margin: 0; color: var(--red); font-weight: 600; }
.res__bordnr { font-size: 15px; font-weight: 700; font-variant-numeric: tabular-nums; }
.res__bordpax { font-size: 11px; opacity: .75; }

.res__tider {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(72px, 1fr));
  gap: 6px;
  max-height: 190px;
  overflow-y: auto;
}

/* ============================================================
   Bordplanens materialer

   Mønstrene er lavet af gradienter, ikke billeder: de skalerer
   med gitteret, virker offline, og koster ikke en eneste
   hentning på en håndholdt over wifi.
   ============================================================ */
.pv__element--m-trae {
  background-color: var(--plan-trae);
  background-image: repeating-linear-gradient(
    90deg, rgba(0,0,0,.18) 0 1px, transparent 1px 9px);
}
.pv__element--m-flise {
  background-color: var(--plan-flise);
  background-image:
    repeating-linear-gradient(0deg,  rgba(255,255,255,.05) 0 1px, transparent 1px 16px),
    repeating-linear-gradient(90deg, rgba(255,255,255,.05) 0 1px, transparent 1px 16px);
}
.pv__element--m-taeppe { background-color: var(--plan-taeppe); }
.pv__element--m-vand   { background-color: var(--plan-vand); }
.pv__element--m-graes  { background-color: var(--plan-graes); }
.pv__element--m-vaeg   { background-color: var(--plan-vaeg); }
.pv__element--m-bar    { background-color: var(--plan-bar); }
.pv__element--m-sofa   { background-color: var(--plan-sofa); border-radius: 4px; }
.pv__element--m-groen  { background-color: var(--plan-groen); }
.pv__element--m-moerk  { background-color: var(--plan-moerk); }
.pv__element--m-aaben  { background: transparent; }

/* Formen hører til typen, ikke til materialet */
.pv__element--plante { border-radius: 50%; }
.pv__element--soejle { border-radius: 50%; }
.pv__element--doer   { border: 2px dashed var(--line-2); background: transparent; }
.pv__element--vindue { border: 2px solid var(--plan-vand); }
.pv__element--tekst  { border: none; background: transparent; font-weight: 700; }
.pv__element--trappe {
  background-image: repeating-linear-gradient(
    0deg, rgba(0,0,0,.3) 0 2px, transparent 2px 10px);
}

/* Planen skal fylde fladen — ikke ligge i et rullefelt.
   Skal man rulle for at finde bord 55, er den ikke bedre end
   listen.

   `safe` er ikke pynt. Et centreret flex-barn, der er HØJERE end
   beholderen, lægger halvdelen af sit overløb OVEN OVER kanten —
   og dér kan man ikke rulle hen, for `scrollTop` kan ikke blive
   negativ. I listevisningen betød det, at bord 1, bord 2 og
   knappen «Vis bordplanen» lå uden for skærmen for altid: man
   kunne komme ind i listen, men ikke tilbage.
   `safe center` centrerer, når der er plads, og falder tilbage
   til start, når der ikke er. */
.floor__grid {
  display: flex;
  align-items: safe center;
  justify-content: safe center;
  /* ------------------------------------------------------------
     PLANEN MÅ HELLERE RULLE END BLIVE FOR LILLE AT RAMME

     Cellegulvet er hævet, så et bord altid er mindst 44 px (F-10,
     `planvisning.js`). En stor plan kan derfor ikke længere altid
     presses ned i vinduet — og så skal den kunne rulles til.
     `safe center` sørger for, at den stadig centreres, når der ER
     plads, uden at klippe toppen når der ikke er.
     ------------------------------------------------------------ */
  overflow: auto;
  -webkit-overflow-scrolling: touch;
}
.pv { padding: 8px; }

/* ============================================================
   DEN SAMLEDE KASSESKÆRM

   Én flade, der fylder vinduet. Ingen sidescroll — kun
   regningslisten ruller indeni, og kun når der er flere varer,
   end der er plads til.

   Det er dét, der gør, at knapperne ikke flytter sig under
   fingeren, når man slår en vare ind.
   ============================================================ */
.kasse {
  min-height: 0;          /* uden denne kan flex-børn ikke krympe */
  overflow: hidden;
}

.kasse__krop {
  display: flex;
  gap: 10px;
  padding: 10px;
  min-height: 0;
  overflow: hidden;
}

/* ============================================================
   VAREFELTET — STRIBEN OG GITTERET UNDER DEN

   Varefladen var før den node, der tog resten af pladsen. Nu
   ligger den i et felt sammen med kategoristriben, og det er
   FELTET, der tager pladsen. Striben har sin faste højde;
   gitteret får resten og ruller indeni.
   ============================================================ */
/* ============================================================
   KATEGORIERNE STAAR I EN SOEJLE TIL VENSTRE

   ------------------------------------------------------------
   HVORFOR

   Dennis, 10. september 2026, med et foto af Toersts rigtige
   ICRTouch-kasse: «Jeg vil have det samme, bare med fanerne i
   venstre side, men produkterne ud for paa samme maade.»

   Paa den kasse staar kategorierne i en LODRET soejle ved siden
   af varefeltet — FORSIDE, TAPAS, SIGNATUR, KLASSISKE, SPRITZ &
   TONICS, ALKOHOLFRI, VIN & BOBLE, OEL & SODA, KAFFE, DIVERSE —
   og varerne ligger i gitteret ud for dem. Det er den flade,
   personalet har staaet ved i aarevis.

   ------------------------------------------------------------
   HVAD DET AENDRER

   Kun RETNINGEN. Striben er den samme vej rundt, den samme
   raekkefoelge, de samme knapper — den ligger bare paa hoejkant.
   `katstribe__knap` beholder sine 44 px i hoejden (husets regel,
   maalt i `trykmaalbrowsertest`) og faar hele soejlens bredde.

   Soejlen ruller LODRET, hvis huset har flere kategorier end der
   er plads til. Samme undtagelse som foer: striben er en del af
   varefeltet, og det maa rulle indeni.

   Bredden er bundet til fladen, ikke til et fast tal: en stor
   kasseskaerm skal ikke give en telefonbred soejle, og en lille
   skal ikke give kategorierne halvdelen af bordet.
   ============================================================ */
.kasse__varefelt {
  flex: 1 1 auto;
  min-width: 0;
  min-height: 0;
  display: flex;
  /* Retningen foelger fanernes placering: staar de i toppen, er
     varefeltet en soejle som altid; staar de i siden, er det en
     raekke. Se `kasseflade.js` og `kategoristribe()`. */
  flex-direction: column;
  gap: 8px;
}
.kasse__varefelt:has(> .katstribe--venstre) { flex-direction: row; }
.kasse__varefelt > .kasse__varer { flex: 1 1 auto; min-height: 0; min-width: 0; }

/* ------------------------------------------------------------
   KATEGORISTRIBEN

   «ikke så høje, men synlige knapper» — Dennis, 30. august 2026.
   Derfor 40 px og ikke husets 44: striben er en VEJ, ikke en
   handling. Man rammer den én gang på vej et sted hen, og den
   skal ikke tage plads fra de knapper, man rammer hundrede
   gange i timen.

   Den ruller vandret, hvis huset har mange kategorier. Det er
   ikke en undtagelse fra husets regel om rulning: striben er
   en del af PLU-vinduet, og det må rulle indeni.
   ------------------------------------------------------------ */
/* ------------------------------------------------------------
   FANERNE I TOPPEN — SOM KASSEN ALTID HAR SET UD

   En vandret stribe, der ruller (swipes), naar huset har flere
   kategorier end der er plads til. Det er standarden, og den er
   uroert: den nye soejle er et VALG, ikke en udskiftning.
   ------------------------------------------------------------ */
.katstribe--top {
  display: flex;
  flex-direction: row;
  gap: 6px;
  overflow-x: auto;
  overflow-y: hidden;
  overscroll-behavior-x: contain;
  padding-bottom: 2px;
  scrollbar-width: thin;
}
.katstribe--top .katstribe__knap {
  height: auto;
  min-height: 44px;
  width: auto;
  font-size: 14px;
  white-space: nowrap;
}

.katstribe--venstre {
  /* Et GITTER med knapsidens raekketal og dens `gap: 4px`, saa en
     fane er praecis lige saa hoej som en varetast. Se noten ved
     `kategoristribe()` i `posScreen.js`. */
  display: grid;
  /* ------------------------------------------------------------
     EN FANE ER PRAECIS ÉN AF KNAPSIDENS RAEKKER

     Raekkehoejden regnes af det SAMME stykke: soejlen og
     knapsiden er soeskende i samme flexraekke og altsaa lige
     hoeje, og `gap` er de samme 4 px som `.buttongrid`. Saa er
     hoejden pr. raekke (100% - (n-1) x 4px) / n — uden at tallet
     staar skrevet to steder (fejlklasse 1).

     Er der FLERE kategorier end raekker, ruller soejlen. Det er
     den aerlige udgang: alternativet er faner, der er lavere end
     tasterne, og det var netop dét, der skulle rettes.
     ------------------------------------------------------------ */
  --fanehoejde: calc((100% - (var(--fanerraekker, 12) - 1) * 4px) / var(--fanerraekker, 12));
  grid-auto-rows: var(--fanehoejde);
  align-content: start;
  /* Bredden er husets egne tal: `faneKolonner` af det samlede
     `faneKolonner + varekolonner`. Bad huset om 2 + 8, faar
     soejlen praecis to tiendedele. Se `kasseflade.js`. */
  flex: 0 0 calc(100% * var(--fanekolonner, 2) /
                 (var(--fanekolonner, 2) + var(--varekolonner, 8)));
  gap: 4px;
  overflow-y: auto;
  overflow-x: hidden;
  overscroll-behavior-y: contain;
  padding-right: 2px;
  scrollbar-width: thin;
}
/* «Fast»: ingen rulning. Er der flere faner end raekker, deler de
   pladsen i stedet — og opsaetningen har sagt det, foer nogen
   gemte. Se `proev()` i `kasseflade.js`. */
.katstribe--fast {
  /* Ingen rulning — og raekkehoejden er HUSETS tal, ikke antallet
     af faner. Er der flere faner end raekker, bladrer sidste
     raekke i stedet. Se noten i `posScreen.js`. */
  overflow: hidden;
  grid-auto-rows: var(--fanehoejde);
}
.katstribe__knap--flere {
  background: var(--bg-2);
  border-color: var(--line-strong);
  font-style: italic;
}
.katstribe__knap {
  flex: 0 0 auto;
  /* Soejlen er smal; knappen fylder den helt, saa teksten har
     hele bredden og traeffladen er hele feltet. */
  width: 100%;
  text-align: center;
  /* ------------------------------------------------------------
     44, IKKE 40

     Husets egen regel er, at et trykmaal er mindst 44 punkter
     hoejt — den staar i `trykmaalbrowsertest` og gaelder hver
     eneste flade. Kategoristriben stod paa 40 og var det ENESTE
     sted paa kassen, der brod den: ti knapper, alle 40 px hoeje,
     maalt 6. september 2026 paa 1280x800.

     Og det er den daarligste knap at goere for lille. Striben
     trykkes flere gange i minuttet en hel aften — den staar
     mellem tjeneren og hver eneste vare i huset. De fire punkter
     er ikke pynt; de er forskellen paa at ramme og at ramme ved
     siden af, naar der er travlt.
     ------------------------------------------------------------ */
  /* Fanen fylder sin gitterraekke helt — det er dét, der goer den
     praecis lige saa hoej som en varetast ved siden af. Bunden paa
     44 px ligger i raekkens `minmax`. */
  height: 100%;
  min-height: 0;
  padding: 6px 8px;
  background: var(--bg-3);
  border: 1px solid var(--line-2);
  border-radius: var(--r-sm);
  color: var(--tx-1);
  font-size: 13.5px;
  font-weight: 700;
  line-height: 1.15;
  /* Et langt navn brydes i stedet for at blive hugget af.
     «Spritz & tonics» skal kunne laeses paa en smal soejle. */
  white-space: normal;
  overflow-wrap: anywhere;
  cursor: pointer;
}
.katstribe__knap.is-active {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--accent-tx);
}
/* Forsiden står først og ser anderledes ud — den er en vej
   hjem, ikke en kategori. */
.katstribe__knap--hjem {
  background: var(--bg-2);
  border-color: var(--line-strong);
}

/* Varefladen tager al den plads, der er tilovers */
.kasse__varer {
  flex: 1 1 auto;
  min-width: 0;
  min-height: 0;
  display: flex;
  /* IKKE `hidden`. Den her node ER gitterfladen (se klasserne på
     elementet), og `hidden` klippede ANTAL-rækken helt væk i
     stedet for at lade fladen rulle. Overflow sættes ét sted:
     i `.gitterflade` ovenfor. */
}
.kasse__varer > * { flex: 1 1 auto; min-height: 0; }

/* Højre spalte: fast bredde, så regningen ikke skifter størrelse,
   hver gang et varenavn er langt */
.kasse__side {
  /* Bredere end før: tasterne står nu VED SIDEN AF regningen og
     tager 88 px af den. Uden de ekstra pixels ville et varenavn
     med en rettet pris brække i seks linjer.

     ------------------------------------------------------------
     F-055 · OG DET SKETE IGEN

     428 px rakte til en øl. Det rakte ikke til en Gin & Tonic med
     størrelse, gin, mixer og et fravalg: navnet brød over tre
     linjer og tilvalgene over fire. Seks linjer for én drink.

     Navnekolonnen fik 115 px. Resten gik til antal, pris, plus og
     minus — som alle skal være der.

     Så bredden følger nu skærmen. På en lille skærm er 428 px
     stadig det rigtige; der er ikke mere at tage af. På husets
     17-tommer er der 1500 px, og varefladen har rigeligt tilbage,
     når regningen får 520.

     Det er ikke pynt. En tjener skal kunne læse regningen på et
     halvt sekund — og seks linjer for én drink er ikke til at
     overskue, når der står otte varer på bordet.
     ------------------------------------------------------------ */
  /* ------------------------------------------------------------
     BREDDEN FØLGER SKÆRMEN — MEN INDEN FOR GRÆNSER

     Her stod `flex: 0 0 428px`: den samme bredde uanset skærm. På
     husets 17-tommer er det fint. På en 958 px bred flade tog
     regningen 45 % — og varegitteret sad tilbage med 452 px til
     elleve kolonner, altså 41 px pr. knap, under husets egen
     `--touch-min`.

     `clamp` gør det, den faste bredde ikke kunne: aldrig under
     300 px (så en Gin & Tonic med tilvalg stadig kan læses),
     aldrig over 460 (så regningen ikke breder sig på en stor
     skærm), og derimellem en tredjedel af skærmen.

     `0 1` og ikke `0 0`: regningen må gerne give plads, hvis der
     bliver for lidt tilbage til varerne. Den må bare ikke vokse.
     ------------------------------------------------------------ */
  /* `0 0` og ikke `0 1`: bredden er clamp'ens, hverken mere eller
     mindre. Med `0 1` gav regningen efter for varegitteret og
     klappede sammen til 182 px — «Total» stod med ét bogstav pr.
     linje, og knapperne lå oven i hinanden. Målt 30. august 2026.

     `min-width` er den samme som clamp'ens bund: en flex-boks
     nægter ellers at gå under sit eget indhold, og så var
     clamp'en uden virkning (målt 482 px, hvor den skulle have
     været 326). */
  /* ------------------------------------------------------------
     BUNDEN ER DÉR, HVOR REGNINGSLINJEN HOLDER OP MED AT VIRKE

     Målt 30. august 2026: ved 326 px lagde linjen sig sammen —
     «2× Sodavand» og «70,00» oven i hinanden, og plusknappen
     forsvandt helt. Navnekolonnen, antal, pris, plus og minus
     skal alle være der, og de kan ikke være i mindre end omkring
     400 px.

     Så bunden er 400, ikke 300. Derover følger bredden skærmen
     (en tredjedel), og loftet er 460, så regningen ikke breder
     sig på en stor skærm. Under 900 px stables spalterne i
     stedet — se mediereglen længere nede.
     ------------------------------------------------------------ */
  flex: 0 0 clamp(400px, 34vw, 460px);
  min-width: 400px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  min-height: 0;
  background: var(--bg-2);
  border: 1px solid var(--line-1);
  border-radius: var(--r-md);
  padding: 10px;
}

/* ------------------------------------------------------------
   HAR HUSET TEGNET SIN EGEN «AKTUEL REGNING»

   …er spalten ét gitter og ikke tre stablede dele. Gitteret
   skal fylde hele spalten, ellers ligger husets felter i toppen
   med en grå flade under — og «vælge størrelse på områderne»
   ville ikke betyde noget.

   Titlen står ikke over et gitter, huset selv har tegnet: der
   kan ligge hvad som helst øverst, og en overskrift, der lyver
   om indholdet, er værre end ingen.
   ------------------------------------------------------------ */
.kasse__side--gitter { gap: 0; }
.kasse__side--gitter > * { flex: 1 1 auto; min-height: 0; }
/* ------------------------------------------------------------
   Reglen står HER, efter definitionen ovenfor.

   Første forsøg lagde den seks hundrede linjer længere oppe, og
   så vandt `428px` — samme specificitet, sidste regel tæller.
   Skærmen var uændret, og det så ud, som om rettelsen ikke
   virkede.
   ------------------------------------------------------------ */
/* Bredden er ikke længere et breakpoint. Se blokken
   «SPALTERNE ER MOTORENS» nedenfor. */

/* ------------------------------------------------------------
   F-055 · HVOR BREDDEN BLEV TAGET FRA

   Funktionsblokken gik fra 92 til 150 px, da den lagde sig i to
   kolonner, og de 58 px kom fra regningen: navnefeltet faldt fra
   186 til 128 px.

   Det er den rigtige handel. 128 px rummer stadig "TEST · Gin &
   Tonic" og fem tilvalg på fire linjer, og linjen kan læses.
   Tasterne gik til gengæld fra 26 til 53 px — og Slet, Retur og
   Genkald er taster, man rammer i blinde med en finger.

   Vi prøvede også at tage bredden fra sortimentet i stedet (560
   og 600 px til siden). Så stod der "Sodava…" og "Specia…" på
   kategorierne, og en kategori, man ikke kan læse, er værre end
   en regningslinje, der bryder én gang ekstra. Derfor står
   siden stadig på 520.

.kasse__sidetitel { padding: 0 2px; }

/* KUN her må der rulles */
.kasse__regning {
  min-height: 0;
  display: flex;
  overflow: hidden;
}
.kasse__regning > * { flex: 1 1 auto; min-height: 0; }

.kasse__handlinger {
  padding-top: 8px;
  border-top: 1px solid var(--line-1);
}

/* ============================================================
   SPALTERNE ER MOTORENS

   ------------------------------------------------------------
   HVAD DER STOD HER FØR

     @container pos (min-width: 1280px) { .kasse__side { 520px } }
     @media (max-width: 900px)  { .kasse__krop { column } }

   To tal, der ikke vidste noget om hinanden, og et hul imellem
   dem. På 958 × 707 gjaldt ingen af dem: regningen fik sin
   clamp-bredde, funktionsblokken tog 150 af den, og navnet i
   regningslinjen endte på 24 px.

   ------------------------------------------------------------
   HVAD DER STÅR HER NU

   `skaermlayout.js` regner ÉT svar ud af husets profil og den
   skærm, kassen faktisk står med. Det svar kommer herned som to
   ting:

     data-pos-regning   «hoejre» eller «over»
     --pos-regning-*    den bredde eller højde, den så får

   CSS'en beslutter ikke længere noget. Den tegner det, der er
   besluttet — og der er kun ét sted at kigge, når det er
   forkert.

   ------------------------------------------------------------
   HVORFOR «OVER» OG IKKE «UNDER»

   På en skærm, man holder i hånden, læser man øverst og rører
   nederst. Regningen er dét, man læser; varerne er dét, man
   rører hundrede gange i timen. Derfor `column-reverse`: siden
   står først i markup'en efter varefladen, men tegnes ovenover.
   ============================================================ */
:root[data-pos-regning="hoejre"] .kasse__krop {
  flex-direction: row;
}
:root[data-pos-regning="hoejre"] .kasse__side {
  /* `0 0` og ikke `0 1`: motoren har allerede taget hensyn til
     varefladen. Giver regningen efter oveni, bliver den smallere
     end det, regnestykket lovede — og så klapper linjen sammen. */
  flex: 0 0 var(--pos-regning-bredde, 400px);
  min-width: var(--pos-regning-bredde, 400px);
  max-height: none;
}

:root[data-pos-regning="over"] .kasse__krop {
  flex-direction: column-reverse;
}
:root[data-pos-regning="over"] .kasse__side {
  flex: 0 0 auto;
  /* Ikke en fast højde: en regning med to varer skal ikke fylde
     40 % af skærmen og skubbe varerne ned. Den vokser med sit
     indhold — til loftet, motoren har sat. */
  min-width: 0;
  width: auto;
  max-height: var(--pos-regning-hoejde, 40vh);
}

/* ------------------------------------------------------------
   SPÆRRET, FORDI DER ER VARER, DER IKKE ER SENDT

   Knappen bliver stående og forklarer sig i stedet for at
   forsvinde. En knap, der er væk, ser ud som en fejl; en knap,
   der er tydeligt spærret, er en besked.
   ------------------------------------------------------------ */
.is-spaerret {
  opacity: .4;
  cursor: not-allowed;
}

/* Mærket på bordet og i overskriften: varer der ikke er sendt */
.chip--usendt {
  background: color-mix(in srgb, var(--orange) 22%, transparent);
  color: var(--orange);
  border: 1px solid var(--orange);
  font-weight: 800;
}
/* Ringen kommer fra `.pv__bord--st-*` — se «EEN RING» nedenfor.
   Klassen bliver staaende, fordi andre regler og proever bruger
   den til at vide, at der ER usendte varer. */
.pv__bord--kladde { }
.pv__usendt {
  font-size: 10px;
  font-weight: 800;
  color: var(--orange);
}

/* ------------------------------------------------------------
   AFSENDELSE TIL PRODUKTIONEN

   Tre forskellige ting, tre forskellige mærker:
     orange  varen mangler at blive sendt
     blå     bonnen er på vej
     rød     bonnen kom aldrig af sted, eller vi ved det ikke

   Farven står aldrig alene — der er ikon og tekst med, så en
   farveblind tjener og en skærm i sollys begge kan læse den.
   ------------------------------------------------------------ */
.pv__afsend {
  font-size: 10px;
  font-weight: 800;
  letter-spacing: .02em;
}
/* Ingen reservefarve skrevet i hånden: står `--blue` ikke i
   temaet, skal den tilføjes dér — ikke gemmes her, hvor huset
   aldrig finder den, når det skifter farver. */
.pv__afsend--sending        { color: var(--blue); }
.pv__afsend--send_failed,
.pv__afsend--send_unknown   { color: var(--red-tekst); }
.pv__afsend--partially_sent { color: var(--orange); }

.pv__bord--afs-sending        { }
/* Pulsen bliver — den er afsendelsens EGEN stemme, og den siger
   noget, ingen anden status siger: bonnen er maaske aldrig
   kommet ud. Ringens FARVE kommer fra `--st-roed`. */
.pv__bord--afs-send_failed,
.pv__bord--afs-send_unknown   {
  animation: afsPuls 1.6s ease-in-out infinite;
}
@keyframes afsPuls {
  0%, 100% { box-shadow: inset 0 0 0 3px var(--red); }
  50%      { box-shadow: inset 0 0 0 3px var(--red), 0 0 12px rgba(255,80,80,.45); }
}

/* Status på selve regningslinjen */
.line__afsend {
  font-size: 11px;
  font-weight: 700;
}
.line__afsend--sending        { color: var(--blue); }
.line__afsend--sent           { color: var(--green); }
/* `--red-tekst` og ikke `--red`. Husets røde er lavet til at ligge
   UNDER hvid tekst; som tekst på en mørk flade giver den 4,19:1,
   hvor kravet er 4,5. Samme rettelse som «?»-mærket på
   regningslinjen fik 1. september 2026 — og her stod den samme
   fejl og ventede på, at en afsendelse gik galt.

   Målt af `fladetest` på kassen, da printeren fejlede. */
.line__afsend--send_failed,
.line__afsend--send_unknown   { color: var(--red-tekst); }
.line__afsend--partially_sent { color: var(--orange); }
.line__afsend--not_sent       { color: var(--orange); }
/* Printsimulering: vist på skærmen, aldrig printet. Dæmpet og aldrig grøn —
   grøn er «sendt», og det er den ikke. */
.line__afsend--simulated      { color: var(--tx-2); font-style: italic; }

/* ------------------------------------------------------------
   STOLETYPER

   En barstol og en almindelig stol er ikke det samme, og en
   bænk er slet ikke en stol. Formen fortæller det, uden at der
   skal stå noget.
   ------------------------------------------------------------ */
.pv__stol--barstol {
  border-radius: 50%;
  border-width: 2px;
  border-style: double;
}
.pv__stol--baenk {
  border-radius: 3px;
  transform: scaleX(1.7);
}

.pv__stol--sofa {
  border-radius: 6px 6px 2px 2px;
  transform: scaleX(2);
}
/* Sidder stolen inde i bordet, skal den kunne ses mod bordets
   egen baggrund */
.pv__stol--p-indenfor { opacity: .92; border-style: dashed; }

/* ------------------------------------------------------------
   RETURFORLØBET

   Ét skærmbillede med trin, ikke otte sider. Trinbjælken viser
   hvor man er, hvad der er gjort, og lader en gå tilbage — en
   retur skal kunne fortrydes hele vejen, indtil den er
   gennemført.
   ------------------------------------------------------------ */
.retur__trin {
  gap: 2px;
  padding: 6px 10px;
  border-bottom: 1px solid var(--line-1);
  overflow-x: auto;
}
.retur__trinknap {
  display: flex;
  align-items: center;
  gap: 6px;
  /* Trinnene er knapper, ikke overskrifter: man kan gaa tilbage
     til «Vaelg varer» efter at have staaet i «Aarsag». Maalt
     31. august 2026 var de 36 px hoeje — under husets fingermaal.
     En retur er penge ud af kassen; det er ikke stedet, hvor man
     rammer ved siden af. */
  min-height: var(--touch-min);
  padding: 7px 12px;
  border: 1px solid transparent;
  border-radius: var(--r-sm);
  background: transparent;
  color: var(--tx-3);
  font-size: 13px;
  font-weight: 700;
  white-space: nowrap;
  cursor: pointer;
}
.retur__trinknap:disabled { opacity: .45; cursor: default; }
.retur__trinknap.is-gjort { color: var(--green); }
.retur__trinknap.is-aktiv {
  background: var(--bg-3);
  border-color: var(--accent);
  color: var(--tx-1);
}
.retur__trintal {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 20px; height: 20px;
  border-radius: 50%;
  border: 1px solid currentColor;
  font-size: 11px;
}
.retur__krop { padding-bottom: 6px; }
.retur__bund {
  padding: 10px;
  border-top: 1px solid var(--line-1);
  background: var(--bg-1);
}

/* ============================================================
   RETUR PÅ EN FLAD SKÆRM

   ------------------------------------------------------------
   DET, DER VAR GALT

   Målt 31. august 2026 på 852 x 393: hovedet tog 61 px, trinnene
   57, handlingsbjælken 89 — og varelisten, som er hele opgaven,
   fik 73. Rækkerne er 53 px, så der var plads til ÉN vare ad
   gangen i et vindue, man skulle rulle i.

   Rammen og vejviseren fyldte tilsammen mere end det, de var
   ramme om. En retur er penge ud af kassen; det er ikke stedet,
   hvor man vælger i blinde.

   ------------------------------------------------------------
   RAMMEN VIGER — IKKE INDHOLDET

   På en lav skærm strammes trinstriben og handlingsbjælken til
   husets fingermål og ikke en px mere. Begge kan stadig rammes;
   de fylder bare ikke mere end de skal. Pladsen går til varerne.
   ============================================================ */
:root[data-pos-hoejde="lav"] .retur__trin { padding: 2px 8px; }
:root[data-pos-hoejde="lav"] .retur__trinknap {
  min-height: var(--touch-min);
  padding: 4px 10px;
}
:root[data-pos-hoejde="lav"] .retur__bund {
  padding: 5px 10px;
}
:root[data-pos-hoejde="lav"] .retur__bund .btn { min-height: var(--touch-min); }

/* ============================================================
   LOKALET, IKKE ET REGNEARK

   Bordplanen skal ligne det rum, personalet står i: træplader
   under varmt lys, læder langs væggen, planter i hjørnerne. En
   tjener, der kigger op fra en håndholdt, skal kunne genkende
   sig selv i planen på et halvt sekund — ikke læse en tabel af
   grå firkanter.

   ALT er tegnet med gradienter. Ingen billeder: de skalerer med
   gitteret, virker offline, og koster ikke en eneste hentning
   over husets wifi.

   Reglerne står på `data-mat`, ikke på en klasse med præfiks —
   så gælder de både på kassens plan (.pv__) og i backendens
   editor (.bp__) uden at skulle skrives to gange.
   ============================================================ */

/* TEMAFAST — materialerne er FYSISKE, ikke tema

   Eg skal ligne eg i alle temaer. Skiftede farverne med temaet,
   ville et lyst trægulv blive blåt i det mørke tema, og så kan
   personalet ikke længere genkende lokalet på materialerne — som
   er hele grunden til, at de er der.

   Derfor står de som rigtige farver og ikke som variabler. Vil
   huset have en anden bordplade, vælger man et andet MATERIALE,
   ikke en anden temafarve. */

/* ---------- Bordpladerne ---------- */
[data-mat="lystrae"] {
  background-color: #c9925c;
  background-image:
    /* årerne */
    repeating-linear-gradient(92deg,
      rgba(90,58,32,.22) 0 1px, rgba(255,255,255,.05) 1px 3px,
      transparent 3px 11px),
    /* lyset falder skråt ind ad vinduet */
    linear-gradient(135deg, rgba(255,232,200,.30), rgba(60,36,18,.28));
  border-color: #6b4a2f !important;
  color: #241608;
}
[data-mat="moerktrae"] {
  background-color: #7b5237;
  background-image:
    repeating-linear-gradient(92deg,
      rgba(28,16,8,.34) 0 1px, rgba(255,255,255,.045) 1px 3px,
      transparent 3px 12px),
    linear-gradient(135deg, rgba(255,215,170,.16), rgba(20,10,4,.4));
  border-color: #3a2618 !important;
  color: #f3e6d6;
}
[data-mat="marmor"] {
  /* Samme tone som møbeltegningen maler med (`m1` i
     planmoebler.js). De stod med hver sin i to cifre — usynligt
     på skærmen, men det betød, at kontrasten blev regnet på en
     farve, bordet ikke havde. `bordfarvetest.js` holder dem
     sammen nu. */
  background-color: #e8e5df;
  background-image:
    linear-gradient(118deg, transparent 0 34%, rgba(120,125,135,.5) 34% 35%, transparent 35% 100%),
    linear-gradient(74deg,  transparent 0 58%, rgba(120,125,135,.32) 58% 59%, transparent 59% 100%),
    linear-gradient(150deg, transparent 0 72%, rgba(140,145,155,.28) 72% 73%, transparent 73% 100%),
    linear-gradient(140deg, rgba(255,255,255,.9), rgba(196,196,190,.75));
  border-color: #9c9a94 !important;
  color: #2a2a2a;
}
[data-mat="staal"] {
  background-color: #8e949c;
  background-image:
    repeating-linear-gradient(90deg,
      rgba(255,255,255,.16) 0 1px, rgba(0,0,0,.10) 1px 2px, transparent 2px 4px),
    linear-gradient(135deg, rgba(255,255,255,.4), rgba(50,55,62,.45));
  border-color: #5d636b !important;
  color: #16181c;
}
[data-mat="sort"] {
  background-color: #24262b;
  background-image: linear-gradient(140deg, rgba(255,255,255,.11), rgba(0,0,0,.5));
  border-color: #101216 !important;
  color: #e8eaee;
}
[data-mat="dug"] {
  background-color: #f4f2ec;
  background-image:
    repeating-linear-gradient(45deg,
      rgba(0,0,0,.028) 0 3px, transparent 3px 6px),
    linear-gradient(140deg, rgba(255,255,255,1), rgba(214,211,202,.9));
  border-color: #c9c6bd !important;
  color: #2a2a2a;
}

/* Bordet er en genstand i et rum: det kaster skygge og fanger
   lys på kanten. Uden det flyder pladen sammen med gulvet. */
.pv__bord, .bp__bord {
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.22),
    inset 0 -2px 3px rgba(0,0,0,.20),
    0 3px 7px rgba(0,0,0,.42);
}
.pv__bord[data-mat] .pv__nr,
.pv__bord[data-mat] .pv__pladser,
.bp__bord[data-mat] .bp__nr,
.bp__bord[data-mat] .bp__pladser { color: inherit; opacity: .72; }

/* Bordets driftsfarve skal stadig kunne ses OVEN PÅ materialet.
   Et bord, der venter på betaling, er vigtigere end træsorten. */
.pv__bord--optaget[data-mat]    { box-shadow: inset 0 0 0 3px var(--accent), 0 3px 7px rgba(0,0,0,.42); }
.pv__bord--betaler[data-mat]    { box-shadow: inset 0 0 0 3px var(--orange), 0 3px 7px rgba(0,0,0,.42); }
.pv__bord--betalt[data-mat]     { box-shadow: inset 0 0 0 3px var(--green),  0 3px 7px rgba(0,0,0,.42); }
.pv__bord--service[data-mat]    { box-shadow: inset 0 0 0 3px var(--blue, var(--accent)), 0 3px 7px rgba(0,0,0,.42); }
/* Et ledigt bord er stilfærdigt — men det er stadig et bord.
   Dæmpes det for hårdt, forsvinder træet, og så er vi tilbage
   ved grå firkanter. */
.pv__bord--ledigt[data-mat]     { filter: brightness(.9); border-style: solid; }
.pv__bord--klargoeres[data-mat] { filter: saturate(.45) brightness(.68); }

/* ---------- Gulvene ---------- */
/* Rigtige brædder med forskudte samlinger — ikke striber */
.pv__element--m-trae, .bp__element[data-mat="trae"] {
  background-color: #7a5636;
  background-image:
    /* samlinger på tværs, forskudt hver anden række */
    repeating-linear-gradient(90deg,
      transparent 0 46px, rgba(0,0,0,.45) 46px 48px),
    /* brættets kanter */
    repeating-linear-gradient(0deg,
      rgba(0,0,0,.38) 0 1px, transparent 1px 13px),
    /* årer */
    repeating-linear-gradient(88deg,
      rgba(255,255,255,.05) 0 1px, transparent 1px 5px),
    linear-gradient(160deg, rgba(255,228,190,.14), rgba(0,0,0,.22));
}
.pv__element--m-flise, .bp__element[data-mat="flise"] {
  background-color: #40444a;
  background-image:
    repeating-linear-gradient(0deg,  rgba(255,255,255,.09) 0 2px, transparent 2px 26px),
    repeating-linear-gradient(90deg, rgba(255,255,255,.09) 0 2px, transparent 2px 26px),
    linear-gradient(150deg, rgba(255,255,255,.08), rgba(0,0,0,.25));
}
.pv__element--m-taeppe, .bp__element[data-mat="taeppe"] {
  background-color: #5a3f4c;
  background-image:
    repeating-linear-gradient(45deg,  rgba(0,0,0,.13) 0 2px, transparent 2px 5px),
    repeating-linear-gradient(-45deg, rgba(255,255,255,.05) 0 2px, transparent 2px 5px);
}
.pv__element--m-graes, .bp__element[data-mat="graes"] {
  background-color: #33562f;
  background-image:
    repeating-linear-gradient(75deg, rgba(255,255,255,.07) 0 1px, transparent 1px 4px),
    repeating-linear-gradient(105deg, rgba(0,0,0,.12) 0 1px, transparent 1px 6px);
}
.pv__element--m-vand, .bp__element[data-mat="vand"] {
  background-color: #24466e;
  background-image:
    repeating-linear-gradient(0deg, rgba(255,255,255,.10) 0 1px, transparent 1px 7px),
    linear-gradient(160deg, rgba(160,210,255,.20), rgba(0,20,50,.35));
}

/* ---------- Væggen og baren ---------- */
.pv__element--m-vaeg, .bp__element[data-mat="vaeg"] {
  background-color: #6a6d74;
  background-image: linear-gradient(180deg, rgba(255,255,255,.22), rgba(0,0,0,.3));
  box-shadow: 0 2px 5px rgba(0,0,0,.5);
}
.pv__element--m-bar, .bp__element[data-mat="bar"] {
  background-color: #6d3a2a;
  background-image:
    repeating-linear-gradient(90deg,
      rgba(0,0,0,.22) 0 1px, transparent 1px 8px),
    /* messingkant langs forkanten — den, gæsten læner sig på */
    linear-gradient(180deg,
      rgba(255,214,150,.5) 0 3px,
      rgba(255,255,255,.10) 3px 6px,
      rgba(0,0,0,.28) 100%);
  box-shadow: inset 0 1px 0 rgba(255,232,190,.55), 0 3px 8px rgba(0,0,0,.5);
}

/* ---------- Sofaen langs væggen ---------- */
/* Læderbænken fra billederne: ryg langs bagkanten, hynder med
   sømme imellem, varm brun med lys ovenfra */
.pv__element--m-sofa, .bp__element[data-mat="sofa"],
.pv__element--sofa, .bp__element--sofa {
  background-color: #8a5334;
  background-image:
    /* sømmene mellem hynderne */
    repeating-linear-gradient(90deg,
      transparent 0 40px,
      rgba(0,0,0,.34) 40px 42px,
      rgba(255,255,255,.07) 42px 44px,
      transparent 44px 46px),
    /* ryglænet langs bagkanten */
    linear-gradient(180deg,
      rgba(0,0,0,.34) 0 26%,
      rgba(255,222,180,.16) 26% 30%,
      transparent 30% 100%),
    linear-gradient(160deg, rgba(255,214,170,.26), rgba(60,26,10,.34));
  border: 1px solid #4d2c19 !important;
  border-radius: 6px 6px 3px 3px;
  box-shadow: inset 0 -3px 6px rgba(0,0,0,.28), 0 3px 8px rgba(0,0,0,.45);
}

/* ---------- Det grønne ---------- */
.pv__element--plante, .bp__element--plante {
  background-color: transparent !important;
  background-image:
    radial-gradient(circle at 50% 62%, #2f7a3e 0 22%, transparent 22%),
    radial-gradient(ellipse 42% 30% at 26% 40%, #3f9950 0 100%, transparent 100%),
    radial-gradient(ellipse 42% 30% at 74% 40%, #35883f 0 100%, transparent 100%),
    radial-gradient(ellipse 30% 44% at 50% 22%, #47a758 0 100%, transparent 100%),
    radial-gradient(ellipse 34% 26% at 50% 78%, #276b34 0 100%, transparent 100%);
  border: none !important;
}
.pv__element--haek, .bp__element--haek {
  background-color: #2e6b38;
  background-image:
    repeating-radial-gradient(circle at 8px 50%,
      rgba(255,255,255,.13) 0 4px, transparent 4px 9px);
  border-radius: 4px;
}
.pv__element--soejle, .bp__element--soejle {
  background-image: linear-gradient(90deg,
    rgba(0,0,0,.45), rgba(255,255,255,.28) 42%, rgba(0,0,0,.45));
  box-shadow: 0 3px 8px rgba(0,0,0,.55);
}
.pv__element--trappe, .bp__element--trappe {
  background-image:
    repeating-linear-gradient(0deg,
      rgba(0,0,0,.42) 0 2px,
      rgba(255,255,255,.10) 2px 4px,
      transparent 4px 14px);
}
.pv__element--vindue, .bp__element--vindue {
  background: linear-gradient(180deg, rgba(150,205,255,.34), rgba(60,110,170,.16)) !important;
  border: 2px solid #7fb2e0 !important;
  box-shadow: 0 0 12px rgba(140,200,255,.32);
}
.pv__element--doer, .bp__element--doer {
  border: 2px dashed #b08a5a !important;
  background: linear-gradient(180deg, rgba(180,140,90,.18), transparent) !important;
}

/* ============================================================
   STOLENE SKAL LIGNE STOLE

   En cirkel med et tal i er en plads i et regneark. En stol har
   et sæde og et ryglæn, og ryglænet vender VÆK fra bordet — det
   er dét, der fortæller, hvilken vej gæsten sidder.

   Ryglænet tegnes med `box-shadow` på den side, der vender ud,
   så det følger stolen, uanset hvor den er trukket hen.
   ============================================================ */
/* Stolene er af træ som bordene — ikke grå knapper */
.pv__stol, .bp__stol {
  background-color: #8a6743;
  background-image: linear-gradient(160deg, rgba(255,226,186,.34), rgba(30,16,6,.34));
  border-color: #4f371f;
  color: #fdf1e2;
  border-radius: 42% 42% 30% 30%;
}
.pv__stol--optaget {
  background-color: #b4762c;
  border-color: var(--accent);
  color: #1a1206;
}
.pv__stol[data-side="nord"], .bp__stol[data-side="nord"] {
  box-shadow: inset 0 3px 0 rgba(0,0,0,.42), 0 1px 3px rgba(0,0,0,.45);
  border-radius: 30% 30% 42% 42%;
}
.pv__stol[data-side="syd"], .bp__stol[data-side="syd"] {
  box-shadow: inset 0 -3px 0 rgba(0,0,0,.42), 0 1px 3px rgba(0,0,0,.45);
}
.pv__stol[data-side="vest"], .bp__stol[data-side="vest"] {
  box-shadow: inset 3px 0 0 rgba(0,0,0,.42), 0 1px 3px rgba(0,0,0,.45);
  border-radius: 30% 42% 42% 30%;
}
.pv__stol[data-side="oest"], .bp__stol[data-side="oest"] {
  box-shadow: inset -3px 0 0 rgba(0,0,0,.42), 0 1px 3px rgba(0,0,0,.45);
  border-radius: 42% 30% 30% 42%;
}

/* Barstolen: høj, smal, drejelig — en ring om et sæde */
.pv__stol--barstol, .bp__stol--barstol {
  border-radius: 50% !important;
  background-image:
    radial-gradient(circle, transparent 0 34%, rgba(0,0,0,.34) 34% 46%, transparent 46%),
    linear-gradient(160deg, rgba(255,255,255,.26), rgba(0,0,0,.3)) !important;
}
/* Bænk og sofa: en hynde, ikke en stol */
.pv__stol--baenk, .bp__stol--baenk,
.pv__stol--sofa,  .bp__stol--sofa {
  border-radius: 5px 5px 3px 3px !important;
  background-color: #8a5334;
  background-image: linear-gradient(160deg, rgba(255,222,180,.3), rgba(50,22,8,.34)) !important;
  border-color: #4d2c19 !important;
  color: #ffe9d5;
}

/* ============================================================
   RUMMET SELV

   Et lokale har lys i midten og mørke hjørner. Det er dét, der
   gør, at planen ligner et sted og ikke et ternet ark.
   ============================================================ */
.pv__plan, .bp__laerred {
  background-image:
    radial-gradient(ellipse 70% 60% at 50% 42%,
      rgba(255,214,160,.055), transparent 70%);
}

/* ============================================================
   ═══  INDRETNINGEN  ═══════════════════════════════════════

   Bordplanen er ikke en teknisk oversigt. Den er 80 % af det,
   personalet kigger på i løbet af en vagt, og den skal ligne
   DET LOKALE, de står i — ikke et skema med firkanter og tal.

   Principperne, læst af den plan Dennis sendte som reference:

     1. GULVET ER VARMT OG LYST. Rummet er det, man ser først;
        møblerne står PÅ noget, ikke i et sort hul.
     2. HVERT MØBEL HAR EN SILHUET. Man skal kunne se på
        afstand, om det er en barstol, en spisestol eller en
        lænestol — uden at læse et ord.
     3. STOLENE KLÆBER TIL BORDET. De ligger tæt på kanten, som
        de gør i virkeligheden, og ryggen vender udad.
     4. ZONER HAR FARVE OG NAVN. Bar, lounge, terrasse og
        personaleområder skal kunne skelnes på et halvt sekund.
     5. DET GRØNNE OG DET BLØDE GØR RUMMET. Planter, tæpper,
        lamper — det er dem, der gør forskellen på "et diagram"
        og "vores café".
     6. ALT ER TEGNET MED GRADIENTER. Ingen billeder: de
        skalerer med gitteret, virker offline, og koster ikke én
        eneste hentning på en håndholdt over husets wifi.
   ============================================================ */

/* ---------- 1 · GULVET ---------- */
.pv__plan, .bp__laerred {
  /* ------------------------------------------------------------
     GULVET SKAL VÆRE LYST

     Første forsøg blev mørkt og mudret: en kraftig vignet oven
     på et mættet tegl gjorde hele lokalet brunt, og møblerne
     forsvandt ned i det. Et cafégulv er LYST — det er dét, der
     gør, at bordene træder frem, og at planen føles indbydende
     i stedet for tung.
     ------------------------------------------------------------ */
  /* `!important` er nødvendig: backend.css indlæses SIDST og
     sætter `--bg-0` på lærredet. Uden den vinder den mørke
     baggrund, og hele gulvet bliver gråbrunt igen. */
  background-color: #e8bfa6 !important;
  background-image:
    /* fugerne mellem klinkerne */
    repeating-linear-gradient(90deg,
      rgba(255,252,247,.62) 0 2px, transparent 2px 36px),
    repeating-linear-gradient(0deg,
      rgba(255,252,247,.62) 0 2px, transparent 2px 36px),
    /* en anelse uro i teglet, så det ikke bliver et regneark */
    repeating-linear-gradient(64deg,
      rgba(198,142,112,.10) 0 10px, transparent 10px 26px),
    /* varmen fra midten af lokalet — let, ikke en tunnel */
    radial-gradient(ellipse 84% 74% at 50% 42%,
      rgba(255,248,232,.5), rgba(206,150,120,.22) 96%) !important;
  box-shadow: inset 0 0 40px rgba(150,96,66,.16);
  border-radius: 6px;
}

/* Gitteret skal kunne ANES, ikke ses. Det er et hjælpemiddel
   under opstilling, ikke en del af lokalet. */
.bp__laerred { background-blend-mode: normal; }
.bp__laerred::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  background-image:
    repeating-linear-gradient(90deg, rgba(90,52,34,.09) 0 1px, transparent 1px 48px),
    repeating-linear-gradient(0deg,  rgba(90,52,34,.09) 0 1px, transparent 1px 48px);
}

/* ---------- 2 · BORDENE ---------- */
.pv__bord, .bp__bord {
  border-radius: 7px !important;
  border-width: 0 !important;
  box-shadow:
    inset 0 2px 0 rgba(255,255,255,.42),
    inset 0 -3px 5px rgba(70,38,18,.34),
    0 4px 9px rgba(60,30,16,.42) !important;
  text-shadow: 0 1px 2px rgba(255,255,255,.35);
  font-weight: 800;
}
.pv__bord--rund, .bp__bord--rund { border-radius: 50% !important; }

/* Højbordet: mindre plade, kraftig fod — det er dét, man ser
   ovenfra, når bordet er højt */
.pv__bord--hoejbord, .bp__bord--hoejbord {
  border-radius: 50% !important;
  box-shadow:
    inset 0 0 0 4px rgba(60,32,16,.30),
    inset 0 2px 0 rgba(255,255,255,.45),
    0 6px 12px rgba(50,24,12,.5) !important;
}
/* Loungebordet er lavt og blødt — aldrig skarpe hjørner */
.pv__bord--lounge, .bp__bord--lounge { border-radius: 40% !important; }
/* Barpladsen er ikke et bord, men en strækning langs disken */
.pv__bord--bar, .bp__bord--bar {
  border-radius: 5px !important;
  border-style: solid !important;
}

/* ---------- 3 · STOLENE ---------- */
/* Almindelig stol: sæde med ryg. Ryggen vender VÆK fra bordet —
   det er dét, der fortæller, hvilken vej gæsten sidder. */
.pv__stol, .bp__stol {
  background-color: #6f4526 !important;
  background-image: linear-gradient(155deg,
    rgba(255,226,186,.42), rgba(30,14,4,.34)) !important;
  border: none !important;
  border-radius: 34% 34% 22% 22% !important;
  color: #fff3e4 !important;
  font-weight: 800;
  box-shadow: 0 2px 4px rgba(50,24,10,.5);
}
.pv__stol[data-side="nord"], .bp__stol[data-side="nord"] {
  border-radius: 22% 22% 34% 34% !important;
  box-shadow: inset 0 4px 0 rgba(255,255,255,.24), 0 2px 4px rgba(50,24,10,.5);
}
.pv__stol[data-side="syd"], .bp__stol[data-side="syd"] {
  box-shadow: inset 0 -4px 0 rgba(255,255,255,.24), 0 2px 4px rgba(50,24,10,.5);
}
.pv__stol[data-side="vest"], .bp__stol[data-side="vest"] {
  border-radius: 22% 34% 34% 22% !important;
  box-shadow: inset 4px 0 0 rgba(255,255,255,.24), 0 2px 4px rgba(50,24,10,.5);
}
.pv__stol[data-side="oest"], .bp__stol[data-side="oest"] {
  border-radius: 34% 22% 22% 34% !important;
  box-shadow: inset -4px 0 0 rgba(255,255,255,.24), 0 2px 4px rgba(50,24,10,.5);
}

/* Barstolen: rund, lys, drejelig — ingen ryg. Den ligner ikke
   en spisestol, og det er hele pointen. */
.pv__stol--barstol, .bp__stol--barstol {
  border-radius: 50% !important;
  background-color: #8fb6d8 !important;
  background-image:
    radial-gradient(circle, rgba(255,255,255,.5) 0 30%,
                    rgba(40,70,100,.34) 32% 48%, transparent 50%),
    linear-gradient(155deg, rgba(255,255,255,.5), rgba(28,54,80,.34)) !important;
  color: #16303f !important;
  box-shadow: inset 0 0 0 2px rgba(255,255,255,.4), 0 2px 5px rgba(20,40,60,.5) !important;
}

/* Bænk og sofa: en polstret hynde med ryg — bred og blød */
.pv__stol--baenk, .bp__stol--baenk,
.pv__stol--sofa,  .bp__stol--sofa {
  border-radius: 6px 6px 3px 3px !important;
  background-color: #a2603a !important;
  background-image:
    repeating-linear-gradient(90deg,
      transparent 0 8px, rgba(0,0,0,.22) 8px 9px),
    linear-gradient(155deg, rgba(255,226,190,.42), rgba(50,20,6,.3)) !important;
  color: #fff1e2 !important;
}

/* Den stol, der er nogen på, skal springe i øjnene */
.pv__stol--optaget {
  background-color: #e0912f !important;
  background-image: linear-gradient(155deg,
    rgba(255,246,225,.55), rgba(120,58,8,.3)) !important;
  color: #241202 !important;
  box-shadow: 0 0 0 2px rgba(255,220,150,.7), 0 3px 7px rgba(60,28,4,.55) !important;
}

/* ---------- 4 · BARDISKEN ---------- */
.pv__element--bardisk, .bp__element--bardisk {
  background-color: #7c4527 !important;
  background-image:
    repeating-linear-gradient(90deg, rgba(0,0,0,.16) 0 1px, transparent 1px 10px),
    /* messingkanten langs forkanten — den, gæsten læner sig på */
    linear-gradient(180deg,
      rgba(255,222,160,.75) 0 4px,
      rgba(255,255,255,.16) 4px 8px,
      rgba(40,18,6,.3) 100%) !important;
  border: none !important;
  border-radius: 8px !important;
  box-shadow:
    inset 0 1px 0 rgba(255,236,200,.7),
    0 5px 12px rgba(40,18,6,.55) !important;
  color: #ffeed9 !important;
  font-weight: 800;
}

/* ---------- 5 · DET BLØDE ---------- */
.pv__element--laenestol, .bp__element--laenestol {
  background-color: #9d5b39 !important;
  background-image:
    /* armlænene */
    linear-gradient(90deg,
      rgba(40,16,4,.4) 0 18%, transparent 18% 82%, rgba(40,16,4,.4) 82% 100%),
    /* ryggen */
    linear-gradient(180deg,
      rgba(40,16,4,.42) 0 24%, transparent 24% 100%),
    linear-gradient(155deg, rgba(255,226,190,.4), rgba(50,20,6,.3)) !important;
  border: none !important;
  border-radius: 40% 40% 22% 22% !important;
  box-shadow: 0 3px 7px rgba(50,22,8,.5) !important;
}
.pv__element--sofahjoerne, .bp__element--sofahjoerne {
  background-color: #9d5b39 !important;
  background-image:
    linear-gradient(135deg,
      rgba(40,16,4,.45) 0 16%, transparent 16% 100%),
    repeating-linear-gradient(45deg,
      transparent 0 22px, rgba(0,0,0,.2) 22px 24px),
    linear-gradient(155deg, rgba(255,226,190,.36), rgba(50,20,6,.3)) !important;
  border: none !important;
  border-radius: 14px 6px 6px 6px !important;
  box-shadow: 0 4px 9px rgba(50,22,8,.5) !important;
}

/* ---------- 6 · DET GRØNNE ---------- */
/* En plante er ikke en grøn firkant. Den har blade. */
.pv__element--plante, .bp__element--plante,
.pv__element--palme,  .bp__element--palme {
  background: none !important;
  background-image:
    radial-gradient(ellipse 46% 34% at 22% 34%, #4e9e57 0 100%, transparent 100%),
    radial-gradient(ellipse 46% 34% at 78% 34%, #3d8a48 0 100%, transparent 100%),
    radial-gradient(ellipse 34% 46% at 50% 16%, #5cb265 0 100%, transparent 100%),
    radial-gradient(ellipse 40% 30% at 26% 72%, #2f7a3c 0 100%, transparent 100%),
    radial-gradient(ellipse 40% 30% at 74% 72%, #368444 0 100%, transparent 100%),
    radial-gradient(circle at 50% 52%, #256b31 0 26%, transparent 27%) !important;
  border: none !important;
  filter: drop-shadow(0 3px 4px rgba(30,50,25,.45));
}
.pv__element--haek, .bp__element--haek {
  background-color: #38793f !important;
  background-image:
    repeating-radial-gradient(circle at 10px 50%,
      rgba(255,255,255,.2) 0 5px, rgba(0,0,0,.10) 5px 11px) !important;
  border: none !important;
  border-radius: 7px !important;
  box-shadow: 0 3px 6px rgba(25,45,22,.45) !important;
}

/* ---------- 7 · ZONER, GANG OG PERSONALE ---------- */
/* Zonefeltet er referencebilledets grønne blokke: et navngivet
   område, man kan se på et halvt sekund */
.pv__element--zone, .bp__element--zone {
  background-color: #7fae4e !important;
  background-image: linear-gradient(160deg,
    rgba(255,255,255,.28), rgba(40,70,20,.24)) !important;
  border: 2px solid rgba(255,255,255,.5) !important;
  border-radius: 6px !important;
  color: #1d3410 !important;
  font-weight: 800 !important;
  box-shadow: 0 3px 7px rgba(30,50,15,.4) !important;
}
/* Gangarealet er dét, man IKKE stiller noget i. Det skal kunne
   ses, men aldrig stjæle billedet. */
.pv__element--gang, .bp__element--gang {
  background: rgba(255,255,255,.16) !important;
  border: 2px dashed rgba(255,255,255,.42) !important;
  border-radius: 6px !important;
  color: rgba(70,38,20,.75) !important;
}
/* Et lille menneske. Det er dét, der gør planen levende — og i
   praksis siger det, hvor der plejer at stå nogen. */
.pv__element--personale, .bp__element--personale {
  background: none !important;
  background-image:
    radial-gradient(circle at 50% 26%, #f2d3b3 0 21%, transparent 22%),
    radial-gradient(ellipse 40% 34% at 50% 72%, #38506e 0 100%, transparent 100%) !important;
  border: none !important;
  filter: drop-shadow(0 2px 3px rgba(20,20,30,.5));
}
.pv__element--vaert, .bp__element--vaert {
  background-color: #6b4326 !important;
  background-image: linear-gradient(180deg,
    rgba(255,226,180,.5) 0 30%, rgba(30,14,4,.3) 100%) !important;
  border: none !important;
  border-radius: 5px !important;
  box-shadow: 0 3px 7px rgba(40,20,8,.5) !important;
  color: #ffeeda !important;
}
.pv__element--reol, .bp__element--reol {
  background-color: #5e3a20 !important;
  background-image: repeating-linear-gradient(90deg,
    rgba(0,0,0,.34) 0 2px, rgba(255,220,170,.14) 2px 12px) !important;
  border: none !important;
  border-radius: 3px !important;
  box-shadow: 0 3px 6px rgba(30,14,4,.5) !important;
}
.pv__element--kaminen, .bp__element--kaminen {
  background-color: #6d6a66 !important;
  background-image:
    radial-gradient(ellipse 50% 60% at 50% 70%, #ff9a3c 0 40%, rgba(255,140,40,.3) 60%, transparent 72%),
    linear-gradient(180deg, rgba(255,255,255,.24), rgba(0,0,0,.3)) !important;
  border: none !important;
  border-radius: 4px !important;
  box-shadow: 0 0 14px rgba(255,150,60,.35), 0 3px 6px rgba(0,0,0,.45) !important;
}
/* Lampen lyser. Det er en detalje, men det er detaljerne, der
   gør, at planen ligner et sted. */
.pv__element--lampe, .bp__element--lampe {
  background: none !important;
  background-image: radial-gradient(circle,
    rgba(255,238,190,.95) 0 26%,
    rgba(255,206,120,.55) 26% 46%,
    rgba(255,190,90,.16) 46% 78%,
    transparent 80%) !important;
  border: none !important;
}

/* ---------- 8 · VÆGGE OG ÅBNINGER ---------- */
.pv__element--vaeg, .bp__element--vaeg {
  background: linear-gradient(180deg, #fbf6ef, #d9cdc0) !important;
  border: none !important;
  border-radius: 2px !important;
  box-shadow: 0 3px 7px rgba(60,34,20,.45) !important;
  color: #6b4a33 !important;
}
.pv__element--soejle, .bp__element--soejle {
  background: radial-gradient(circle at 36% 32%, #fbf6ef, #b09a86) !important;
  border: none !important;
  box-shadow: 0 4px 9px rgba(50,28,16,.5) !important;
}
.pv__element--doer, .bp__element--doer {
  background: rgba(255,255,255,.5) !important;
  border: 2px dashed #a97b4e !important;
  border-radius: 3px !important;
  color: #6b4a33 !important;
}
.pv__element--vindue, .bp__element--vindue {
  background: linear-gradient(180deg,
    rgba(190,228,255,.85), rgba(120,180,225,.5)) !important;
  border: 2px solid #fbf6ef !important;
  border-radius: 2px !important;
  box-shadow: 0 0 14px rgba(170,215,255,.5) !important;
}
.pv__element--trappe, .bp__element--trappe {
  background-color: #cbb9a5 !important;
  background-image: repeating-linear-gradient(0deg,
    rgba(90,58,34,.5) 0 2px, rgba(255,255,255,.4) 2px 5px,
    transparent 5px 16px) !important;
  border: none !important;
  border-radius: 3px !important;
}

/* ---------- 9 · GULVZONER ---------- */
/* Zonerne skal LIGNE gulv, ikke ligge som farvede plader ovenpå */
.pv__element--m-trae, .bp__element[data-mat="trae"] {
  border: none !important;
  border-radius: 5px !important;
  box-shadow: inset 0 0 0 2px rgba(255,255,255,.22) !important;
}
.pv__element--m-taeppe, .bp__element[data-mat="taeppe"] {
  border-radius: 8px !important;
  border: 3px solid rgba(255,255,255,.3) !important;
  box-shadow: inset 0 0 26px rgba(0,0,0,.28) !important;
}

/* Teksten på planen skal kunne læses på et varmt gulv */
.pv__element .pv__navn, .bp__element .bp__navn {
  text-shadow: 0 1px 2px rgba(255,255,255,.5);
  font-weight: 800;
}

/* ============================================================
   MØBLERNE SOM SVG

   Symbolet ligger som en tegning i bunden af feltet. Det kan
   IKKE rammes af musen — hitboxen bliver ved med at være selve
   feltet, ellers ville et hul mellem to palmeblade betyde, at
   man ikke kunne tage fat i planten.
   ============================================================ */
.jcm {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  overflow: visible;
  z-index: 0;
}

/* Har møblet en rigtig tegning, skal den gamle farvede kasse
   forsvinde. To lag oven på hinanden bliver til mudder. */
.pv__element:has(.jcm), .bp__element:has(.jcm),
.pv__stol:has(.jcm),    .bp__stol:has(.jcm),
.pv__bord:has(.jcm),    .bp__bord:has(.jcm) {
  background: none !important;
  background-image: none !important;
  border-color: transparent !important;
  box-shadow: none !important;
  filter: drop-shadow(0 3px 4px rgba(60,32,16,.42));
}

/* ============================================================
   STOLENS TRE TILSTANDE

   ------------------------------------------------------------
   HVAD TJENEREN SPØRGER OM

   Før havde stolen to udseender: «der står varer på den» og
   «alt andet». En gæst, der havde siddet i tyve minutter uden at
   bestille, så derfor ud som en tom stol ved et frit bord — og
   det er præcis den gæst, man skal hen til.

     fri      bordet er frit. Stolen er ledig.
     gaest    der SIDDER en gæst, men intet er bestilt endnu.
     optaget  der står varer for penge på netop den stol.

   Se `planvisning.stoltilstand`.

   ------------------------------------------------------------
   HVORFOR `filter` OG IKKE BAGGRUND

   Reglen lige ovenfor fjerner baggrund, kant og skygge, når
   stolen bærer en rigtig møbeltegning — «to lag oven på hinanden
   bliver til mudder», og den beslutning står ved magt. Derfor
   tegnes tilstanden som et farvet OMRIDS om selve tegningens
   silhuet med `drop-shadow`, ikke som en kasse bagved.

   Målt i browseren, før det her: baggrund og box-shadow blev
   beregnet til `none` på hver eneste stol. Den gamle
   `--optaget`-farve har altså i praksis været usynlig, siden
   møbeltegningerne kom til.
   ============================================================ */

/* LEDIG — bordet er frit. Stolen må ikke stjæle øjet fra de
   borde, hvor der rent faktisk sker noget. */
.pv__stol--fri { opacity: .4; }

/* GÆST UDEN VARER — nogen sidder her og har ikke bestilt.
   Omridset er tyndt: der er ingen penge på stolen endnu. */
/* Farven skrives HELT UD med vilje. `var(--accent)` inde i
   `drop-shadow()` gør værdien ugyldig ved beregningen, og så
   falder hele `filter` tilbage til `none` — målt i browseren:
   omridset forsvandt, og stolen så ud præcis som før. */
.pv__stol--gaest:has(.jcm), .bp__stol--gaest:has(.jcm) {
  filter:
    drop-shadow(1px 0 0 #e0912f) drop-shadow(-1px 0 0 #e0912f)
    drop-shadow(0 1px 0 #e0912f) drop-shadow(0 -1px 0 #e0912f)
    drop-shadow(0 3px 4px rgba(60,32,16,.42));
}

/* MED VARER — der står penge på stolen. Tykkere omrids og et
   svagt skær, så de to tilstande kan skelnes på afstand. */
.pv__stol--optaget:has(.jcm), .bp__stol--optaget:has(.jcm) {
  filter:
    drop-shadow(2px 0 0 #ffd08a) drop-shadow(-2px 0 0 #ffd08a)
    drop-shadow(0 2px 0 #ffd08a) drop-shadow(0 -2px 0 #ffd08a)
    drop-shadow(0 0 6px #e0912f)
    drop-shadow(0 3px 4px rgba(60,32,16,.42));
}

/* Stole UDEN en møbeltegning — den gamle firkant. Her kan en ring
   godt tegnes, for der er ikke en silhuet at følge. */
.pv__stol--gaest:not(:has(.jcm)) {
  box-shadow: 0 0 0 2px #e0912f !important;
}
.pv__stol--optaget:not(:has(.jcm)) {
  box-shadow: 0 0 0 3px #ffd08a, 0 0 6px 1px #e0912f !important;
}

/* ------------------------------------------------------------
   EN SLUKKET UDGANG SKAL KUNNE SES

   «‹ Borde» slukkes, når der står usendte varer på bordet. Den
   må ikke bare være uklikbar — så tror man, skærmen hænger.
   Den skal SE slukket ud, og markøren skal sige det samme.
   ------------------------------------------------------------ */
/* ------------------------------------------------------------
   OVERSTREGET LÆSES SOM «FINDES IKKE»

   «‹ Borde» fik en streg igennem sig, når vejen var spærret
   (F-20 i frontendrevisionen, F-22). Reglen er rigtig — knappen
   SKAL se slukket ud — men skiltet var forkert: en overstreget
   navigationsknap ser ud, som om skærmen er fjernet, ikke som om
   den er utilgængelig lige nu.

   Dæmpningen og markøren siger det samme uden at love det
   forkerte, og `title` bærer grunden.
   ------------------------------------------------------------ */
.btn.is-spaerret,
.btn.is-spaerret:disabled {
  opacity: .45;
  cursor: not-allowed;
}

/* Nummeret skal stå OVEN PÅ møblet og kunne læses */
.pv__stolnr, .bp__stolnr {
  position: relative;
  z-index: 2;
  font-weight: 800;
  color: #fff6e8;
  text-shadow: 0 1px 3px rgba(0,0,0,.85);
}
.pv__stol--gaest .pv__stolnr { color: #ffd9a6; }
.pv__stol--optaget .pv__stolnr { color: #fffdf8; }
.pv__bord .pv__tekst, .bp__bord .bp__tekst { position: relative; z-index: 2; }

/* ============================================================
   TEKSTEN PÅ BORDET — FARVEN ER REGNET, IKKE VALGT HER

   Her stod før `color: #2a1a0c` — én fast mørk farve på ALLE
   borde med en møbeltegning. På en lys egeplade var den rigtig.
   På en mørkeblå plade forsvandt bordnummeret helt, og et
   bordnummer, man ikke kan læse, er det samme som ingen
   bordplan.

   Nu kommer farven fra `--pv-tekst`, som `bordplan.js` regner
   ud af pladens egen farve (eller af husets valg). Den gamle
   værdi står tilbage som fallback: en flade, der endnu ikke
   sætter variablen, ser præcis ud som før.

   `--pv-halo` er den tynde skygge, der løfter bogstavet fri af
   mønstret. Den skal altid være den MODSATTE ende af teksten —
   en hvid halo om hvid tekst er bare uskarphed.
   ============================================================ */
.pv__bord:has(.jcm) .pv__navn, .bp__bord:has(.jcm) .bp__navn {
  color: var(--pv-tekst, #2a1a0c);
  text-shadow: 0 1px 2px var(--pv-halo, rgba(255,255,255,.65));
}

/* Navnet på selskabet læses på den samme plade som nummeret og
   skal derfor have den samme regnede farve. Uden det stod
   «Familien Jensen» i temafarve oven på en egetræsplade. */
.pv__bord:has(.jcm) .pv__bordnavn {
  color: var(--pv-tekst, #2a1a0c);
  text-shadow: 0 1px 2px var(--pv-halo, rgba(255,255,255,.65));
}

/* Nummer, gæsteantal, beløb og tid er ikke pynt — det er dem,
   man aflæser på tværs af lokalet. De skal følge samme farve som
   navnet og ikke stå tilbage i en dæmpet temafarve, som kan være
   valgt til en helt anden baggrund. */
/* `.pv__kursus` kom til senere og stod ikke paa listen. Den fik
   en halo paa 0,35 fra et andet sted — og det er den MINDSTE
   tekst paa figuren, 9,5 px, som altsaa havde den svageste halo
   af dem alle. Maalt 1. september 2026: uden husets egen halo
   kunne den ikke laeses paa et lyst bord. */
.pv__bord .pv__tekst .pv__kursus,
.pv__bord .pv__tekst .pv__pladser,
.pv__bord .pv__tekst .pv__tid,
.pv__bord .pv__tekst .pv__belob,
.pv__bord .pv__tekst .pv__nr,
.pv__bord .pv__tekst .pv__samlet,
.bp__bord .bp__tekst .bp__pladser,
.bp__bord .bp__tekst .bp__nr {
  color: var(--pv-tekst, inherit);
  text-shadow: 0 1px 2px var(--pv-halo, transparent);
}

/* ------------------------------------------------------------
   KONTRASTPLADEN — SIDSTE VÆRN

   Har huset valgt en tekstfarve, der ikke rigtig kan læses på
   pladen, siger designeditoren fra. Men bordplanen ude i lokalet
   skal virke ALLIGEVEL, også mens nogen er ved at rette farven.

   Derfor lægger der sig en diskret, halvgennemsigtig plade bag
   teksten — ikke en etiket. Materialet skal stadig kunne ses
   igennem, ellers har vi byttet et ulæseligt bord ud med et
   bord, man ikke kan genkende.

   Pladen tegnes med ::before på selve teksten, så den følger
   teksten rundt, når bordet drejer.
   ------------------------------------------------------------ */
.pv__bord--kontrastplade .pv__tekst,
.bp__bord--kontrastplade .bp__tekst { isolation: isolate; }

.pv__bord--kontrastplade .pv__tekst::before,
.bp__bord--kontrastplade .bp__tekst::before {
  content: '';
  position: absolute;
  inset: -2px -6px;
  z-index: -1;
  border-radius: 6px;
  background: var(--pv-plade, rgba(12,10,8,.42));
  backdrop-filter: blur(1.5px);
  pointer-events: none;
}
.pv__element:has(.jcm) .pv__navn, .bp__element:has(.jcm) .bp__navn {
  position: relative; z-index: 2;
}

/* Miniaturen i biblioteket er den RIGTIGE tegning i småt */
.bp__bibprove .jcm { position: absolute; inset: 0; }

/* ============================================================
   GULVE OG VÆGGE — RIGTIGE OVERFLADER

   Et gulv er ikke en farve. Sildebensparket har en retning,
   klinker har fuger, mursten har forbandt. Det er dét, der
   afgør, om planen ligner et lokale eller et farvelagt skema.

   Alle mønstre er gradienter, så de skalerer med zoomen og ikke
   koster en hentning på en håndholdt.
   ============================================================ */

/* Sildeben: to sæt skrå planker, forskudt — det er dét, der
   giver fiskebensmønsteret */
[data-mat="sildeben"] {
  background-color: #b5824f !important;
  background-image:
    repeating-linear-gradient(45deg,
      rgba(60,32,12,.34) 0 1px, transparent 1px 11px,
      rgba(255,225,180,.16) 11px 12px, transparent 12px 22px),
    repeating-linear-gradient(-45deg,
      rgba(60,32,12,.34) 0 1px, transparent 1px 11px,
      rgba(255,225,180,.16) 11px 12px, transparent 12px 22px),
    linear-gradient(150deg, rgba(255,236,200,.24), rgba(70,38,14,.16)) !important;
}
[data-mat="planke"] {
  background-color: #bd8b57 !important;
  background-image:
    repeating-linear-gradient(90deg,
      rgba(60,32,12,.3) 0 2px, transparent 2px 54px),
    repeating-linear-gradient(0deg,
      rgba(60,32,12,.22) 0 1px, transparent 1px 15px),
    repeating-linear-gradient(88deg,
      rgba(255,230,190,.12) 0 1px, transparent 1px 6px) !important;
}
[data-mat="moerktgulv"] {
  background-color: #6d4527 !important;
  background-image:
    repeating-linear-gradient(90deg, rgba(20,10,2,.4) 0 2px, transparent 2px 50px),
    repeating-linear-gradient(0deg, rgba(20,10,2,.28) 0 1px, transparent 1px 14px),
    linear-gradient(150deg, rgba(255,220,175,.16), rgba(0,0,0,.2)) !important;
}
[data-mat="lysklinke"] {
  background-color: #e0cbb4 !important;
  background-image:
    repeating-linear-gradient(90deg, rgba(255,255,255,.85) 0 3px, transparent 3px 40px),
    repeating-linear-gradient(0deg,  rgba(255,255,255,.85) 0 3px, transparent 3px 40px),
    linear-gradient(150deg, rgba(255,255,255,.4), rgba(150,120,95,.18)) !important;
}
[data-mat="moerkklinke"] {
  background-color: #6a6560 !important;
  background-image:
    repeating-linear-gradient(90deg, rgba(230,225,218,.5) 0 3px, transparent 3px 40px),
    repeating-linear-gradient(0deg,  rgba(230,225,218,.5) 0 3px, transparent 3px 40px),
    linear-gradient(150deg, rgba(255,255,255,.16), rgba(0,0,0,.26)) !important;
}
/* Dekorative fliser: den grøn-hvide encaustic-slags, man ser i
   caféer — mønsteret på tværs, ikke bare et gitter */
[data-mat="mosaik"] {
  background-color: #7f9e8c !important;
  background-image:
    repeating-linear-gradient(45deg,
      rgba(255,252,244,.5) 0 5px, transparent 5px 22px),
    repeating-linear-gradient(-45deg,
      rgba(255,252,244,.5) 0 5px, transparent 5px 22px),
    repeating-linear-gradient(90deg, rgba(255,255,255,.7) 0 2px, transparent 2px 40px),
    repeating-linear-gradient(0deg,  rgba(255,255,255,.7) 0 2px, transparent 2px 40px) !important;
}
[data-mat="beton"] {
  background-color: #9d9a94 !important;
  background-image:
    repeating-linear-gradient(70deg, rgba(255,255,255,.08) 0 2px, transparent 2px 17px),
    repeating-linear-gradient(0deg, rgba(255,255,255,.4) 0 2px, transparent 2px 90px),
    repeating-linear-gradient(90deg, rgba(255,255,255,.4) 0 2px, transparent 2px 90px),
    linear-gradient(140deg, rgba(255,255,255,.2), rgba(0,0,0,.16)) !important;
}
[data-mat="terrasse"] {
  background-color: #a8814f !important;
  background-image:
    repeating-linear-gradient(0deg,
      rgba(50,28,10,.42) 0 3px, transparent 3px 20px),
    repeating-linear-gradient(0deg,
      rgba(255,230,185,.16) 3px 5px, transparent 5px 20px) !important;
}
/* Dansegulv: mørkt, blankt felt med diskrete lyskegler. De må
   ikke overdøve gulvet — man skal stadig kunne se, hvor der er
   plads at gå. */
[data-mat="dansegulv"] {
  background-color: #35313d !important;
  background-image:
    /* Lyskeglerne skal ANES. Overdøver de gulvet, kan tjeneren
       ikke se bordstatus — og så er planen ubrugelig i drift.
       Tre diskrete kegler, ikke et diskotek. */
    radial-gradient(ellipse 22% 40% at 26% 4%, rgba(150,120,230,.20), transparent 70%),
    radial-gradient(ellipse 22% 40% at 50% 2%, rgba(110,180,230,.18), transparent 70%),
    radial-gradient(ellipse 22% 40% at 74% 4%, rgba(225,130,180,.18), transparent 70%),
    repeating-linear-gradient(90deg, rgba(255,255,255,.10) 0 2px, transparent 2px 46px),
    repeating-linear-gradient(0deg,  rgba(255,255,255,.10) 0 2px, transparent 2px 46px) !important;
  box-shadow: inset 0 0 30px rgba(90,70,150,.18) !important;
}

/* ---------- VÆGGE ---------- */
/* Mursten skal have FORBANDT — hver anden række forskudt. Uden
   det ligner det fliser, og så forsvinder murstensfornemmelsen. */
[data-mat="mursten"] {
  background-color: #a2543f !important;
  background-image:
    repeating-linear-gradient(0deg,
      rgba(240,232,222,.9) 0 3px, transparent 3px 15px),
    repeating-linear-gradient(90deg,
      rgba(240,232,222,.9) 0 3px, transparent 3px 34px),
    linear-gradient(180deg, rgba(255,255,255,.16), rgba(0,0,0,.2)) !important;
  background-size: auto, 34px 30px, auto;
  background-position: 0 0, 0 0, 0 0;
}
[data-mat="moerkmursten"] {
  background-color: #5d3a30 !important;
  background-image:
    repeating-linear-gradient(0deg, rgba(200,188,178,.6) 0 3px, transparent 3px 15px),
    repeating-linear-gradient(90deg, rgba(200,188,178,.6) 0 3px, transparent 3px 34px),
    linear-gradient(180deg, rgba(255,255,255,.1), rgba(0,0,0,.3)) !important;
}
[data-mat="hvidmursten"] {
  background-color: #e9e2d8 !important;
  background-image:
    repeating-linear-gradient(0deg, rgba(160,148,134,.55) 0 3px, transparent 3px 15px),
    repeating-linear-gradient(90deg, rgba(160,148,134,.55) 0 3px, transparent 3px 34px),
    linear-gradient(180deg, rgba(255,255,255,.5), rgba(0,0,0,.08)) !important;
}
[data-mat="vaegflise"] {
  background-color: #8fb0b8 !important;
  background-image:
    repeating-linear-gradient(0deg, rgba(255,255,255,.8) 0 2px, transparent 2px 22px),
    repeating-linear-gradient(90deg, rgba(255,255,255,.8) 0 2px, transparent 2px 22px),
    linear-gradient(180deg, rgba(255,255,255,.35), rgba(0,0,0,.12)) !important;
}
[data-mat="malet"] {
  background-color: #efe8dd !important;
  background-image: linear-gradient(180deg, rgba(255,255,255,.5), rgba(0,0,0,.1)) !important;
}
[data-mat="traepanel"] {
  background-color: #7a512f !important;
  background-image:
    repeating-linear-gradient(90deg,
      rgba(30,14,2,.4) 0 3px, rgba(255,225,180,.14) 3px 5px, transparent 5px 24px),
    linear-gradient(180deg, rgba(255,225,180,.2), rgba(0,0,0,.22)) !important;
}
[data-mat="glasvaeg"] {
  background-color: rgba(170,215,235,.4) !important;
  background-image:
    repeating-linear-gradient(90deg, rgba(255,255,255,.6) 0 3px, transparent 3px 60px),
    linear-gradient(160deg, rgba(255,255,255,.5), rgba(120,180,210,.2)) !important;
  box-shadow: inset 0 0 0 2px rgba(255,255,255,.6) !important;
}


/* ------------------------------------------------------------
   NAVNENE MÅ IKKE OVERDØVE LOKALET

   Hvert element bar sit navn. Med fyrre ting på planen blev det
   til en tekstsuppe, der lå oven på selve indretningen — og så
   kunne man hverken se møblerne eller læse navnene.

   Gulve og zoner beholder deres navn: det er dem, man
   orienterer sig efter. Møbler, planter og pynt kendes på deres
   tegning; de behøver ikke stå med navn.
   ------------------------------------------------------------ */
.pv__element .pv__navn, .bp__element .bp__navn {
  font-size: 10px;
  padding: 1px 5px;
  border-radius: 5px;
  background: rgba(28,20,14,.55);
  color: #ffeeda;
  text-shadow: none;
  white-space: nowrap;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* Pynt og småmøbler siger sig selv */
.bp__element--plante .bp__navn, .pv__element--plante .pv__navn,
.bp__element--palme .bp__navn,  .pv__element--palme .pv__navn,
.bp__element--lampe .bp__navn,  .pv__element--lampe .pv__navn,
.bp__element--personale .bp__navn, .pv__element--personale .pv__navn,
.bp__element--laenestol .bp__navn, .pv__element--laenestol .pv__navn,
.bp__element--sofahjoerne .bp__navn, .pv__element--sofahjoerne .pv__navn,
.bp__element--sofa .bp__navn,   .pv__element--sofa .pv__navn,
.bp__element--soejle .bp__navn, .pv__element--soejle .pv__navn,
.bp__element--vaeg .bp__navn,   .pv__element--vaeg .pv__navn,
.bp__element--doer .bp__navn,   .pv__element--doer .pv__navn,
.bp__element--vindue .bp__navn, .pv__element--vindue .pv__navn,
.bp__element--haek .bp__navn,   .pv__element--haek .pv__navn,
.bp__element--skaerm .bp__navn, .pv__element--skaerm .pv__navn,
.bp__element--reol .bp__navn,   .pv__element--reol .pv__navn,
.bp__element--kaminen .bp__navn, .pv__element--kaminen .pv__navn {
  display: none;
}
/* …men det valgte skal altid kunne identificeres */
.bp__element.is-valgt .bp__navn { display: block !important; }

/* ------------------------------------------------------------
   TRÆSORTER OG FLISEMØNSTRE

   "Trægulv" er ikke ét gulv. Eg er lyst og roligt, valnød er
   mørkt og stribet, skibsplanker har sorte fuger. Det er dét,
   der afgør, om planen ligner huset eller bare et gulv.
   ------------------------------------------------------------ */
[data-mat="eg"] {
  background-color: #d0a875 !important;
  background-image:
    repeating-linear-gradient(90deg, rgba(90,58,26,.22) 0 2px, transparent 2px 62px),
    repeating-linear-gradient(0deg, rgba(90,58,26,.14) 0 1px, transparent 1px 16px),
    repeating-linear-gradient(89deg, rgba(255,240,210,.16) 0 1px, transparent 1px 7px) !important;
}
[data-mat="valnoed"] {
  background-color: #6b4227 !important;
  background-image:
    repeating-linear-gradient(90deg, rgba(20,8,0,.4) 0 2px, transparent 2px 58px),
    repeating-linear-gradient(0deg, rgba(20,8,0,.26) 0 1px, transparent 1px 15px),
    repeating-linear-gradient(91deg, rgba(220,170,120,.18) 0 1px, transparent 1px 5px) !important;
}
[data-mat="ask"] {
  background-color: #e2c9a0 !important;
  background-image:
    repeating-linear-gradient(90deg, rgba(120,90,55,.2) 0 2px, transparent 2px 56px),
    repeating-linear-gradient(0deg, rgba(120,90,55,.12) 0 1px, transparent 1px 14px),
    repeating-linear-gradient(88deg, rgba(255,255,255,.22) 0 1px, transparent 1px 6px) !important;
}
[data-mat="bambus"] {
  background-color: #d8bd85 !important;
  background-image:
    repeating-linear-gradient(90deg, rgba(110,80,35,.3) 0 2px, transparent 2px 22px),
    repeating-linear-gradient(0deg, rgba(110,80,35,.18) 0 2px, transparent 2px 30px) !important;
}
[data-mat="skibsplanke"] {
  background-color: #c49a63 !important;
  background-image:
    repeating-linear-gradient(0deg,
      rgba(25,18,10,.75) 0 3px, transparent 3px 18px),
    repeating-linear-gradient(0deg,
      rgba(255,240,210,.16) 3px 5px, transparent 5px 18px) !important;
}
[data-mat="sildeben_m"] {
  background-color: #74492b !important;
  background-image:
    repeating-linear-gradient(45deg,
      rgba(20,10,2,.4) 0 1px, transparent 1px 11px,
      rgba(230,190,145,.14) 11px 12px, transparent 12px 22px),
    repeating-linear-gradient(-45deg,
      rgba(20,10,2,.4) 0 1px, transparent 1px 11px,
      rgba(230,190,145,.14) 11px 12px, transparent 12px 22px) !important;
}

/* Sekskanter: to sæt skrå linjer plus vandrette giver honeycomb */
[data-mat="sekskant"] {
  background-color: #e8e2d6 !important;
  background-image:
    repeating-linear-gradient(60deg, rgba(140,132,120,.55) 0 2px, transparent 2px 26px),
    repeating-linear-gradient(-60deg, rgba(140,132,120,.55) 0 2px, transparent 2px 26px),
    repeating-linear-gradient(0deg, rgba(140,132,120,.55) 0 2px, transparent 2px 45px) !important;
}
/* Metrofliser: aflange, forskudt hver anden række */
[data-mat="metro"] {
  background-color: #f0ece4 !important;
  background-image:
    repeating-linear-gradient(0deg, rgba(150,142,130,.6) 0 2px, transparent 2px 18px),
    repeating-linear-gradient(90deg, rgba(150,142,130,.6) 0 2px, transparent 2px 40px) !important;
  background-size: auto, 40px 36px;
}
[data-mat="terrazzo"] {
  background-color: #e6e1d7 !important;
  background-image:
    radial-gradient(circle at 12% 22%, rgba(120,110,95,.55) 0 3px, transparent 3px),
    radial-gradient(circle at 63% 14%, rgba(170,90,70,.45) 0 4px, transparent 4px),
    radial-gradient(circle at 34% 68%, rgba(90,120,105,.45) 0 3px, transparent 3px),
    radial-gradient(circle at 82% 74%, rgba(120,110,95,.5) 0 4px, transparent 4px),
    radial-gradient(circle at 48% 40%, rgba(60,60,60,.35) 0 2px, transparent 2px) !important;
  background-size: 46px 46px;
}
/* Skakternet: to farver i skiftevis felter */
[data-mat="skak"] {
  background-color: #f2ece1 !important;
  background-image:
    repeating-conic-gradient(#2b2723 0 25%, transparent 0 50%) !important;
  background-size: 56px 56px;
}
[data-mat="marmorgulv"] {
  background-color: #eceae5 !important;
  background-image:
    linear-gradient(118deg, transparent 0 30%, rgba(130,135,145,.4) 30% 31%, transparent 31%),
    linear-gradient(72deg, transparent 0 62%, rgba(130,135,145,.28) 62% 63%, transparent 63%),
    repeating-linear-gradient(90deg, rgba(170,168,162,.5) 0 2px, transparent 2px 70px),
    repeating-linear-gradient(0deg, rgba(170,168,162,.5) 0 2px, transparent 2px 70px) !important;
}

/* Titlerne kan slås fra, når man vil se lokalet uden tekst */
.bp__laerred.skjul-titler .bp__navn,
.pv__plan.skjul-titler .pv__navn { display: none !important; }

/* ------------------------------------------------------------
   DE SIDSTE MATERIALER UDEN TEGNING

   Syv af dem stod som tomme sorte felter i vælgeren. Man kunne
   læse navnet, men ikke se, hvad man valgte — og et materiale,
   man ikke kan se, vælger man ikke.
   ------------------------------------------------------------ */
[data-mat="sorttrae"] {
  background-color: #35312d !important;
  background-image:
    repeating-linear-gradient(90deg, rgba(0,0,0,.5) 0 2px, transparent 2px 44px),
    repeating-linear-gradient(88deg, rgba(255,255,255,.06) 0 1px, transparent 1px 6px),
    linear-gradient(160deg, rgba(255,255,255,.1), rgba(0,0,0,.35)) !important;
}
[data-mat="metal"] {
  background-color: #9aa1a9 !important;
  background-image:
    repeating-linear-gradient(90deg,
      rgba(255,255,255,.3) 0 1px, rgba(0,0,0,.14) 1px 3px, transparent 3px 6px),
    linear-gradient(140deg, rgba(255,255,255,.5), rgba(60,66,74,.4)) !important;
}
/* Læder: bløde felter med sømme imellem */
[data-mat="laeder"] {
  background-color: #9d5b39 !important;
  background-image:
    repeating-linear-gradient(45deg,
      transparent 0 16px, rgba(60,26,10,.3) 16px 18px),
    repeating-linear-gradient(-45deg,
      transparent 0 16px, rgba(60,26,10,.3) 16px 18px),
    linear-gradient(150deg, rgba(255,214,170,.3), rgba(50,20,6,.28)) !important;
}
/* Stof: væv på kryds og tværs */
[data-mat="stof"] {
  background-color: #6f7a63 !important;
  background-image:
    repeating-linear-gradient(0deg, rgba(255,255,255,.14) 0 1px, transparent 1px 4px),
    repeating-linear-gradient(90deg, rgba(0,0,0,.16) 0 1px, transparent 1px 4px) !important;
}
[data-mat="groen"] {
  background-color: #3f8f4c !important;
  background-image:
    repeating-radial-gradient(circle at 7px 50%,
      rgba(255,255,255,.2) 0 4px, rgba(0,0,0,.12) 4px 9px) !important;
}
[data-mat="moerk"] {
  background-color: #1c1e22 !important;
  background-image: linear-gradient(150deg, rgba(255,255,255,.13), rgba(0,0,0,.5)) !important;
}
/* Gennemsigtig skal LIGNE gennemsigtig — det ternede mønster,
   alle kender fra billedprogrammer */
[data-mat="aaben"] {
  background-color: #cfcfcf !important;
  background-image:
    repeating-conic-gradient(#f2f2f2 0 25%, #bfbfbf 0 50%) !important;
  background-size: 14px 14px;
  opacity: .55;
}
/* TEMAFAST SLUT */

/* ------------------------------------------------------------
   FORMEN PÅ ET ELEMENT

   Et gulv var altid en firkant. Men et loungeområde er tit rundt,
   en scene har afrundede hjørner, og en dansegulvszone kan være
   oval. Formen hører til objektet, ikke til dets type.
   ------------------------------------------------------------ */
[data-form="afrundet"] { border-radius: 14px !important; }
[data-form="rund"]     { border-radius: 50% !important; }
[data-form="oval"]     { border-radius: 50% / 40% !important; }
[data-form="kapsel"]   { border-radius: 999px !important; }
/* Skæv: et hjørne skåret af — til nicher og skrå vægge */
[data-form="skaev"] {
  border-radius: 4px !important;
  clip-path: polygon(0 0, 100% 0, 100% 72%, 72% 100%, 0 100%);
}


/* ------------------------------------------------------------
   HUSETS EGET BILLEDE PÅ ET OBJEKT

   Laget ligger oven på materialet og under navnet, og det kan
   ikke rammes af musen — ellers ville et foto på et gulv stjæle
   trykket fra alt, der står på gulvet.
   ------------------------------------------------------------ */
.bp__foto,
.pv__foto {
  position: absolute;
  inset: 0;
  background-position: center;
  background-repeat: no-repeat;
  border-radius: inherit;
  pointer-events: none;
}

/* ------------------------------------------------------------
   BESKEDEN TIL KØKKENET, ØVERST I LINJENS DIALOG

   Et felt, der ligner et felt. Står der allerede noget, skal det
   kunne læses uden at åbne noget — det er tit dét, man trykkede
   på linjen for at kontrollere.
   ------------------------------------------------------------ */
.linjetekst {
  justify-content: flex-start;
  text-align: left;
  min-height: 46px;
  font-weight: 600;
  color: var(--tx-2);
  border-style: dashed;
  white-space: normal;
}
.linjetekst--sat {
  color: var(--yellow);
  border-style: solid;
  border-color: var(--yellow);
  font-weight: 700;
}

/* ============================================================
   VAREEDITOREN

   Én skærm for alt på en vare. Afsnittene står i den rækkefølge,
   man taler om maden: hvad er der i den, hvad kan lægges på,
   hvad skal køkkenet passe på, og hvad skal der stå på bonnen.

   Store trykflader hele vejen. Det her bruges midt i en
   bestilling, med gæsten ved bordet og en finger på en skærm,
   der ikke altid er ren.
   ============================================================ */
.modal--bred { max-width: 880px; width: 96vw; }

/* Editoren har mange afsnit, og på en lav skærm skal der rulles.
   Luft i bunden, så det sidste afsnit ikke ligger klemt op ad
   knapperne og ser afskåret ud. */
.modal--bred .modal__body { padding-bottom: 28px; }
.ve__afsnit:last-child { padding-bottom: 4px; }

.ve__hoved {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
  padding-bottom: 12px;
  border-bottom: 1px solid var(--line-1);
}
.ve__navn { font-size: 20px; font-weight: 800; }
.ve__total { text-align: right; }
.ve__total__mrk {
  font-size: 11px; font-weight: 700; letter-spacing: .6px;
  text-transform: uppercase; color: var(--tx-2);
}
.ve__total__tal { font-size: 22px; font-weight: 800; font-variant-numeric: tabular-nums; }
.ve__variant { color: var(--tx-2); font-size: 13.5px; margin-top: 6px; }

.ve__afsnit { padding: 14px 0; border-bottom: 1px solid var(--line-1); }
.ve__afsnit:last-child { border-bottom: 0; }
.ve__titel { font-size: 15px; font-weight: 700; margin-bottom: 10px; }

/* ---------- Chips: standard indhold, allergener, beskeder ---------- */
.ve__chips { display: flex; flex-wrap: wrap; gap: 8px; }

.ve__chip {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  min-height: 44px;
  padding: 0 14px;
  border-radius: 999px;
  border: 1.5px solid var(--line-2);
  background: var(--bg-3);
  color: var(--tx-1);
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
}
.ve__chip:active { transform: translateY(1px); }
.ve__chipmaerke { font-weight: 800; }
.ve__chipikon { font-size: 16px; }

/* Ingrediensen er PÅ — grøn med flueben */
.ve__chip--paa {
  border-color: var(--green);
  color: var(--green);
}
/* Ingrediensen er taget AF — slukket og streget */
.ve__chip--fra {
  border-color: var(--line-2);
  background: var(--bg-2);
  color: var(--tx-2);
  text-decoration: line-through;
}

.ve__chip.er-valgt {
  border-color: var(--accent);
  background: var(--accent-soft, var(--bg-4));
  color: var(--accent);
}
.ve__chip--allergi.er-valgt {
  border-color: var(--red);
  color: var(--red);
}
.ve__allergifri { margin-top: 10px; }

/* ---------- Kort med plus og minus ---------- */
.ve__kort {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(158px, 1fr));
  gap: 10px;
}
.ve__kort__felt {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 12px;
  border-radius: var(--r-md);
  border: 1.5px solid var(--line-2);
  background: var(--bg-3);
}
.ve__kort__felt.er-valgt {
  border-color: var(--accent);
  background: var(--bg-4);
}
.ve__kort__felt--tryk { cursor: pointer; -webkit-tap-highlight-color: transparent; }
.ve__kort__felt--tryk:hover { background: var(--bg-4); }
.ve__kort__felt--tryk:active { transform: scale(.985); }
.ve__kort__navn { font-weight: 700; font-size: 14.5px; line-height: 1.25; }
.ve__kort__hjaelp { font-size: 12px; color: var(--tx-2); line-height: 1.35; }
/* ------------------------------------------------------------
   PRISEN STÅR PÅ SIN EGEN LINJE

   Først stod pris og tæller ved siden af hinanden. Så snart man
   trykkede plus, dukkede minus og tallet op, kortet blev ikke
   bredere — og prisen brækkede i tre linjer: "+ / 15,00 / kr."

   Et kort, der skifter facon, når man rører ved det, ser i
   stykker ud. Prisen får derfor sin egen linje, og tælleren sin.
   Så fylder kortet det samme, uanset om der er valgt noget.
   ------------------------------------------------------------ */
.ve__kort__bund {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 8px;
  margin-top: auto;
  padding-top: 8px;
}
.ve__kort__pris {
  font-size: 13px;
  font-weight: 700;
  color: var(--tx-2);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.ve__tal {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 6px;
  /* Fast højde: rækken er der altid, også når der kun er et
     plus. Ellers hopper kortet i højden ved første tryk. */
  min-height: 40px;
}
.ve__tal__vis {
  min-width: 22px;
  text-align: center;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
}
.ve__tal__knap {
  /* 44, ikke 40 — samme regel som kategoristriben, og samme
     grund. Det her er plus og minus paa ANTALLET: den knap, der
     trykkes flest gange i en linjedialog, og den skal rammes med
     en tommelfinger over en tablet, ikke med en mus. Maalt for
     lille paa iPad staaende, iPad liggende og stor tablet
     6. september 2026. */
  width: 44px;
  height: 44px;
  border-radius: var(--r-sm);
  border: 1.5px solid var(--line-2);
  background: var(--bg-2);
  color: var(--tx-1);
  font-size: 19px;
  font-weight: 800;
  line-height: 1;
  cursor: pointer;
}
.ve__tal__knap--plus {
  border-color: var(--accent);
  color: var(--accent);
}
.ve__tal__knap:disabled { opacity: .35; cursor: default; }
.ve__tal__knap:active:not(:disabled) { background: var(--accent); color: var(--accent-tx); }

/* ---------- Beskedfeltet ---------- */
.ve__tekstfelt {
  display: block;
  width: 100%;
  min-height: 52px;
  margin-top: 10px;
  padding: 14px;
  text-align: left;
  border-radius: var(--r-md);
  border: 1.5px dashed var(--line-2);
  background: var(--bg-3);
  color: var(--tx-2);
  font-size: 14.5px;
  font-weight: 600;
  cursor: pointer;
}
.ve__tekstfelt.er-udfyldt {
  border-style: solid;
  border-color: var(--yellow);
  color: var(--yellow);
  font-weight: 700;
}

@container pos (max-width: 700px) {
  .ve__kort { grid-template-columns: repeat(auto-fill, minmax(132px, 1fr)); }
  .ve__chip { min-height: 42px; font-size: 13.5px; }
}

/* ---------- Antal i vareeditoren ---------- */
.ve__antal {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 10px;
}
.ve__antal__knap {
  flex: 0 0 auto;
  width: 84px;
  height: 56px;
  border-radius: var(--r-md);
  border: 1.5px solid var(--line-2);
  background: var(--bg-3);
  color: var(--tx-1);
  font-size: 26px;
  font-weight: 800;
  line-height: 1;
  cursor: pointer;
}
.ve__antal__knap:active { background: var(--accent); color: var(--accent-tx); }
.ve__antal__tal {
  flex: 1 1 auto;
  text-align: center;
  font-size: 34px;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
}

/* En stol mere: stiplet, så den ses som en TILFØJELSE og ikke
   som en stol, der allerede står der */
.ve__chip--tilfoej {
  border-style: dashed;
  color: var(--accent);
  border-color: var(--accent);
}

/* Enten-eller-valg: hele knappen siger, om det er valgt */
.ve__vaelg {
  width: 100%;
  min-height: 40px;
  border-radius: var(--r-sm);
  border: 1.5px solid var(--line-2);
  background: var(--bg-2);
  color: var(--tx-2);
  font-size: 13.5px;
  font-weight: 700;
  cursor: pointer;
}
.ve__vaelg.er-valgt {
  border-color: var(--green);
  background: var(--green);
  color: var(--tx-inv);
}

/* ------------------------------------------------------------
   VALGLISTENS PRISER

   Den samlede pris er det, tjeneren skal sige højt. Den står
   derfor stort og alene til højre. Tillægget er en forklaring,
   ikke et svar — og står som lille grå tekst under.
   ------------------------------------------------------------ */
.valgliste__belob {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 1px;
  margin-left: auto;
}
.valgliste__tillaeg {
  font-size: 12px;
  font-weight: 500;
  color: var(--tx-3);
  line-height: 1.1;
}
.valgliste__grund {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  padding: 6px 14px 10px;
  color: var(--tx-3);
  font-size: 13px;
}
.valgliste__grundbelob {
  font-size: 15px;
  font-weight: 700;
  color: var(--tx-2);
}

/* Prisen på et tilvalgskort: den samlede pris stort, tillægget lille */
.ve__kort__pris { display: flex; flex-direction: column; gap: 1px; }
.ve__kort__ialt { font-size: 15px; font-weight: 700; color: var(--tx-1); }
.ve__kort__tillaeg { font-size: 11.5px; font-weight: 500; color: var(--tx-3); }


/* ============================================================
   Systeminfo — «hvad kører der her?»

   Læses lige så ofte på en håndholdt i en hånd som på kassens
   skærm. Rækkerne står derfor som navn/værdi i to spalter, når
   der er plads, og brydes til to linjer, når der ikke er.
   ============================================================ */
/* ------------------------------------------------------------
   VINDUET MAALER SIG SELV

   Stablingen herunder stod som `@container pos (max-width: 560px)`
   — husets egen flade-container. Men modalen haenger paa `body`,
   ikke i `.app-root` (se den lange note i `modal.js`), saa den
   container findes ikke over den, og reglen fyrede ALDRIG.

   Maalt 11. september 2026: `.sysinfo` var 256 px bred inde i en
   proeveramme paa 428, mens reglen ventede paa 560. Foelgen var
   klemt tekst i hver eneste raekke — «Kategorifaner» stod som
   «I toppe n». Det gaelder ogsaa paa en RIGTIG telefon, ikke kun
   i rammen: modalen ligger samme sted begge steder.

   Vinduet er nu sin egen container. Det er ogsaa det rigtige maal:
   raekken skal stable, naar VINDUET er smalt — ikke naar fladen
   bagved er det.
   ------------------------------------------------------------ */
.sysinfo {
  display: flex; flex-direction: column; gap: var(--sp-3);
  container-type: inline-size;
  container-name: sysinfo;
}

.sysinfo__top {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--sp-2) var(--sp-3);
}
.sysinfo__produkt { font-size: 18px; font-weight: 700; }
.sysinfo__version { font-size: 18px; font-weight: 700; color: var(--orange); }

.sysinfo__miljoe {
  margin-left: auto;
  padding: 2px var(--sp-2);
  border-radius: var(--r-sm);
  border: 1px solid var(--line-2);
  background: var(--bg-3);
  color: var(--tx-2);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .8px;
  white-space: nowrap;
}
.sysinfo__miljoe--production {
  border-color: var(--green); background: var(--green-soft); color: var(--green);
}
.sysinfo__miljoe--test {
  border-color: var(--yellow); background: rgba(232, 192, 32, .16); color: var(--yellow);
}
.sysinfo__miljoe--local {
  border-color: var(--blue); background: rgba(63, 140, 255, .16); color: var(--blue);
}
.sysinfo__miljoe--ukendt {
  border-color: var(--red); background: rgba(229, 72, 77, .16); color: var(--red);
}

/* Advarslen skal ses uden at blive læst. */
.sysinfo__advarsel {
  padding: var(--sp-3);
  border-radius: var(--r-sm);
  border: 1px solid var(--yellow);
  background: rgba(232, 192, 32, .12);
  color: var(--tx-1);
  font-size: 13px;
  line-height: 1.45;
}
.sysinfo__advarsel .strong { display: block; margin-bottom: 2px; color: var(--yellow); }

.sysinfo__blok {
  border: 1px solid var(--line-1);
  border-radius: var(--r-sm);
  background: var(--bg-2);
  overflow: hidden;
}
.sysinfo__raekke {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--sp-2) var(--sp-4);
  padding: var(--sp-2) var(--sp-3);
  border-top: 1px solid var(--line-1);
  font-size: 13px;
}
.sysinfo__raekke:first-child { border-top: 0; }
.sysinfo__raekke--obs { background: rgba(232, 192, 32, .09); }
/* En raekke, der ALTID stabler: navnet over, indholdet under.
   Til raekker med flere knapper, som bliver klemt i hoejre side
   uanset hvor bred skaermen er. */
.sysinfo__raekke--stablet {
  flex-direction: column;
  align-items: stretch;
  gap: var(--sp-2);
}
.sysinfo__raekke--stablet .sysinfo__vaerdi { text-align: left; }

.sysinfo__navn { color: var(--tx-3); flex: 0 0 auto; }
/* ------------------------------------------------------------
   DEN FREMHÆVEDE RÆKKE ER DÉN, DER SKAL LÆSES

   `--obs` lægger ni procent gult over kortet. Det er nok til at
   trække `--tx-3` under kravet — og kun på den række, huset selv
   har markeret som vigtig. «Git» stod fremhævet, fordi træet var
   beskidt, og navnet på rækken var det eneste, der ikke kunne
   læses efter reglen.

   Målt 6. september 2026 med husets egen kontrastmåler, 13 px
   tekst, krav 4,5:

     tema            grund             --tx-3   --tx-2
     mørk (standard) rgb(42, 41, 31)     4,26     7,89
     lyst            rgb(253,249,235)    4,75     8,91
     sort / høj      rgb(33, 29, 15)     8,49    13,24
     blå             rgb(37, 50, 46)     3,89     7,25

   Dæmpningen er rigtig på de almindelige rækker — der er den
   5,08. Den holder bare ikke, når rækken bliver fremhævet.
   ------------------------------------------------------------ */
.sysinfo__raekke--obs .sysinfo__navn { color: var(--tx-2); }
.sysinfo__vaerdi {
  color: var(--tx-1);
  text-align: right;
  min-width: 0;
  overflow-wrap: anywhere;
}
.sysinfo__mono {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 12.5px;
}
/* ------------------------------------------------------------
   EN LÅST KNAP — SYNLIG, MEN IKKE HENDES ENDNU

   Det er husets LEDERHANDLINGER: en tjener bliver ikke stoppet,
   hun får en dialog, og lederen taster sin kode ved bordet.
   Knappen skal derfor SES — den skal bare ikke se ud, som om
   trykket gør det, hun tror.

   Ikke grå: grå betyder «virker ikke», og den her virker. En
   stiplet kant og et lille hængelås-tegn siger «der kommer et
   skridt mere», og `title` siger hvilket.
   ------------------------------------------------------------ */
.btn--laast { position: relative; border-style: dashed; }
.btn--laast::after {
  content: '\1F512';
  position: absolute; top: 2px; right: 5px;
  font-size: 10px; opacity: .75;
}

.sysinfo__note { margin: 0; font-size: 12px; color: var(--tx-3); line-height: 1.45; }

/* ± i «Knapper i højden/bredden». `.btn--sm` er 35 px bred, og
   husets bund er 44. Højden var der i forvejen. */
/* `.btn.` og ikke bare `.sysinfo__tal`: `.btn--sm` saetter selv
   `min-width: 0` og staar senere i arket, saa de to ville have
   samme vaegt og den sidste vinde. Maalt: 35 px blev staaende. */
.btn.sysinfo__tal { min-width: var(--touch-min); }

/* Smalt vindue: navn over værdi, så lange byggenumre ikke klemmes. */
@container sysinfo (max-width: 560px) {
  .sysinfo__raekke { flex-direction: column; align-items: stretch; gap: 1px; }
  .sysinfo__vaerdi { text-align: left; }
  .sysinfo__miljoe { margin-left: 0; }
}

/* ============================================================
   BESKED TIL PRINTER

   Printerne er kort, ikke en rulleliste: der er få af dem, og
   valget skal kunne rammes med en tommelfinger uden at ramme
   naboen. `auto-fill` med et gulv på 180px giver flere i bredden
   på en kasse og én pr. række på en håndholdt — uden et
   mediequery, der skal holdes ved lige ved siden af.
   ============================================================ */
.printergitter {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
  gap: 10px;
}
.printerkort {
  min-height: var(--touch-min);
  padding: 14px;
  text-align: left;
  cursor: pointer;
  border: 1px solid var(--line-2);
  background: var(--bg-3);
}
.printerkort--valgt {
  border-color: var(--accent);
  box-shadow: inset 0 0 0 1px var(--accent);
}

/* Kvitteringen står PÅ skærmen og ikke kun som en toast: en toast
   er væk om tre sekunder, og den, der lige har sendt en besked ud
   i køkkenet, skal kunne se på skærmen at det skete. */
.kvit--ok   { border-left: 3px solid var(--green); }
.kvit--fejl { border-left: 3px solid var(--red); }

/* ============================================================
   LICENSSKÆRMENS AFSLAG SKAL SE UD SOM ET AFSLAG

   `licens__fejl` blev sat tre steder i `src/ui/screens/licens.js`
   og fandtes ikke i nogen stilfil (F-20). Afslaget arvede derfor
   `.muted` og lignede hjælpetekst: «Nøglen kendes ikke» stod med
   samme dæmpede grå som «Nøglen står på licensbeviset».

   Den, der taster forkert klokken syv om morgenen, skal kunne se
   forskel på en vejledning og et nej. Aldrig KUN farve — teksten
   siger det stadig selv, og vægten bærer det for den, der ikke
   ser rødt.
   ============================================================ */
.licens__fejl {
  color: var(--red);
  font-weight: 600;
  opacity: 1;
}

/* ============================================================
   «SKIFT BRUGER» SKAL KUNNE SES

   Knappen bar kun medarbejderens navn. Et tryk på sit eget navn
   logger én ud — det er ikke til at gætte, og et vagtskifte er
   ikke stedet at gætte på noget.
   ============================================================ */
.topbar__skift {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  line-height: 1.15;
  gap: 1px;
}
.topbar__navn { font-weight: 700; }
.topbar__skiftord {
  font-size: 10.5px;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--tx-3);
}

/* ------------------------------------------------------------
   UDSOLGT SKAL KUNNE SES PÅ EN METERS AFSTAND

   En tjener kigger på knapgitteret i et halvt sekund, mens hun
   lytter til gæsten. Er kagen udsolgt, må hun ikke skulle læse
   sig frem til det — knappen skal se anderledes ud, før hun
   overhovedet når at pege.

   Knappen bliver STÅENDE. Forsvandt den, ville hun lede efter
   den og tro, siden var forkert; og i morgen er kagen der igen.
   Den er dæmpet, stregen viser at den er ude af brug, og teksten
   siger hvorfor — «Udsolgt i dag» og «Taget af kortet» er to
   forskellige svar til gæsten.
   ------------------------------------------------------------ */
.gridcell--udsolgt {
  opacity: .55;
  cursor: not-allowed;
}
.gridcell--udsolgt .gridcell__label {
  text-decoration: line-through;
  text-decoration-thickness: 1px;
  /* Grunden skal have plads. Er varen udsolgt, er navnet ikke
     det vigtigste længere — det står overstreget, og det er
     grunden, tjeneren skal kunne sige højt. */
  -webkit-line-clamp: 1;
}
.gridcell__udsolgt {
  color: var(--red-tx);
  font-weight: 600;
  /* ------------------------------------------------------------
     GRUNDEN SKAL KUNNE LÆSES HELE VEJEN

     Den arver `.gridcell__price`, som står på `nowrap`, fordi en
     halv talrække er værre end ingen. Men det her er ikke et tal —
     det er en sætning, en tjener skal kunne sige højt til en gæst.

     Målt 30. august 2026: knappen skrev «Udsolgt i da».
     ------------------------------------------------------------ */
  white-space: normal;
  line-height: 1.05;
  font-size: 10.5px;
  width: 100%;
  text-align: center;
  overflow: hidden;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
}

/* «3 igen» — advarslen, før den bliver til et nej. Den skal
   kunne ses, uden at knappen ser i stykker ud. */
.gridcell__rest {
  position: absolute;
  top: 4px;
  right: 6px;
  font-size: 11px;
  font-weight: 700;
  padding: 1px 6px;
  border-radius: 999px;
  background: var(--orange);
  color: var(--bg-0);
  pointer-events: none;
}

/* ------------------------------------------------------------
   KØKKENETS VARESTYRING

   Samme gitter som bonkortene, så skærmen ikke skifter karakter,
   når kokken går fra den ene fane til den anden. Knapperne er
   store med vilje: det her betjenes med en hånd, der lige har
   holdt en pande.
   ------------------------------------------------------------ */
.kds-varegrid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
  gap: 10px;
}
.kds-vare {
  border: 1px solid var(--line-2);
  border-radius: 10px;
  padding: 12px;
  background: var(--bg-2);
}
.kds-vare--lukket {
  opacity: .7;
  border-color: var(--red-tx);
}
.row.wrap { flex-wrap: wrap; }

/* ------------------------------------------------------------
   ET BORD, DER ER ÅBENT PÅ EN ANDEN KASSE

   Det skal kunne ses på tværs af lokalet, at bordet ER taget —
   men det må ikke ligne ens eget. Tjeneren skal kunne se
   forskel på «det her arbejder jeg på» og «det her har en
   kollega», for det afgør, om hun skal gå derhen eller spørge.

   Den stiplede kant er den samme, huset bruger til «noget
   hører til et andet sted», og navnet på ejeren står i feltet.
   ------------------------------------------------------------ */
.pv__bord--andres {
  outline: 2px dashed var(--at-late);
  outline-offset: -3px;
}
.pv__andres {
  font-size: 9px;
  font-weight: 700;
  letter-spacing: .02em;
  color: var(--at-late);
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ============================================================
   DEN KOMPAKTE FLADE

   Godkendt af Dennis 31. august 2026 — se D-0012 og
   design/pos-kompakt-godkendt.html. Bruges paa alt, man holder i
   haanden; husets faste kasse beholder den klassiske flade.

   Maalene her er dem, skitsen blev godkendt paa, og de er ikke
   tilfaeldige:

     Regningen  fast hoejde med plads til FIRE varer. Den maa
                ikke vokse med indholdet — saelger man ti varer,
                skal produkterne stadig vaere der. Og linjerne maa
                ikke skrumpe: fire og tyve varer skal se ens ud,
                ellers bliver de ulaeselige netop dér, hvor
                regningen er stor.

     Menufelt   mindst 96 px hoejt. Det er et iPad-maal, ikke et
                musemaal.

     Status     farvet kantstribe, ingen tekst. To tekstlinjer pr.
                vare koster 24 px paa HVER linje.
   ============================================================ */
.kompakt {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 10px;
  min-height: 0;
  overflow: hidden;
}

/* ---------- Regning og total ---------- */
.kregnrum {
  /* ------------------------------------------------------------
     HOEJDEN KOMMER FRA MOTOREN, IKKE FRA ET TAL HER

     Her stod `213px` fast — 13 titel + 6 + 4x40 linje + 3x6 + 16
     ramme, altsaa plads til fire varer. Det er rigtigt paa en
     iPad. Paa en telefon paa tvaers er hele fladen 393 px, og de
     213 lod 28 px tilbage til varerne: knapperne stak ud under
     bundbjaelken. Maalt 31. august 2026.

     Motoren kender baade skaermen og hvad baandet skal rumme, og
     den levner altid varefladen sit minimum. Tallet her er kun
     reserven, hvis maalingen ikke er naaet endnu.
     ------------------------------------------------------------ */
  /* ------------------------------------------------------------
     MOTORENS BAAND ER ET GULV — IKKE ET LOFT

     Her stod `flex: 0 0 <baand>`: regningen fik praecis sit baand
     og ikke en px mere. Resten faldt ned i varefladen, som lod den
     ligge, fordi gitteret staar `align-content: start`.

     Maalt 31. august 2026 paa iPad liggende: regningen laast paa
     274 px med plads til FIRE varer, mens bord 1 havde otte — og
     70 px stod ubrugt under knapperne. Staaende var det vaerre.

     Nu er det omvendt: varefladen tager det, dens knapper faktisk
     fylder, og regningen faar resten. Baandet fra motoren er
     gulvet, saa regningen aldrig bliver mindre end det, den skal
     kunne vise.

     Der er ingen sloejfe i det. Kolonnerne kommer fra BREDDEN,
     raekkerne fra knapsidens eget indhold — ingen af delene ser
     paa regningens hoejde. Se ogsaa D-0013: dér blev pladsen
     UNDER knapperne bevaret, fordi husets knapside har tolv
     raekker og en fordeling ville skubbe ANTAL-panelet ud. Her
     fordeles der ikke inde i gitteret; pladsen flyttes til
     regningen, og ANTAL-panelet findes ikke paa denne flade.
     ------------------------------------------------------------ */
  /* ------------------------------------------------------------
     REGNINGEN FYLDER SIT BAAND — HVERKEN MERE ELLER MINDRE

     Et forsoeg gav den al den plads, der var til overs. Det var
     forkert: regningen skal fylde saa lidt som muligt og stadig
     vise vare, antal, pris og status. Bliver den stor, bliver
     varefladen lille, og det er dér fingeren arbejder.

     Pladsen, der bliver til overs, gaar til VAREKNAPPERNE — se
     `.kvarer` og `#screen:has(.kompakt) .buttongrid` nedenfor.
     Stoerre knapper er bedre paa en iPad; en stoerre regning er
     kun bedre, hvis der er noget at vise i den.
     ------------------------------------------------------------ */
  flex: 0 0 var(--pos-regning-hoejde, 213px);
  display: flex;
  gap: 10px;
  min-height: 0;
}
.kompakt--udvidet .kregnrum { flex: 1 1 auto; }
.kompakt--udvidet .kkatstribe,
.kompakt--udvidet .kvarer { display: none; }

.kregning {
  flex: 1 1 auto;
  min-width: 0;
  min-height: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 8px 10px;
  background: var(--bg-1);
  border: 1px solid var(--line-1);
  border-radius: var(--r-md);
  overflow: hidden;
}
/* Bordnummer, stole og beloeb paa EEN linje. Striben er den
   eneste, der maa give sig — chippen og beloebet er tal, der
   ikke kan forkortes. Se noten i `posKompakt.js`. */
.kregning__hoved {
  display: flex; align-items: center; gap: 8px; padding-left: 2px;
  min-width: 0;
}
.kregning__hoved > .kbordchip { flex: 0 0 auto; }
.kregning__hoved > .kregning__total { flex: 0 0 auto; }

/* ------------------------------------------------------------
   DE TO KIG

   De staar foerst i faneraekken — se noten i `floorplan.js`. En
   tynd skillelinje efter dem siger, at de ikke er lokaler:
   husets egne omraader begynder til hoejre for stregen.
   ------------------------------------------------------------ */
.floor__kig {
  display: flex;
  gap: 2px;
  flex: 0 0 auto;
  padding-right: 6px;
  margin-right: 4px;
  border-right: 1px solid var(--line-2);
}

/* ------------------------------------------------------------
   TOPLINJENS BORDNUMMER OG DEN ORDLOESE PRIK
   Se `bordchip` og `salgsklarBadge` i shell.js.
   ------------------------------------------------------------ */
/* ------------------------------------------------------------
   TOPLINJEN PAA EN TELEFON

   Bordnummer til venstre, prik og tjener i midten, beloeb til
   hoejre. Husets navn er vaek — se noten i `shell.js`.
   ------------------------------------------------------------ */
.topbar--kompakt { gap: 8px; }
.topbar__beloeb {
  flex: 0 0 auto;
  margin-left: auto;
  font-size: 17px;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  letter-spacing: -.3px;
  color: var(--tx-1);
  white-space: nowrap;
}
/* Tjenerens navn maa give sig foer bordnummeret og beloebet: det
   er det eneste af de tre, man kan gaette. */
/* ------------------------------------------------------------
   NAVNET MAA GIVE SIG — MEN IKKE UNDER EN FINGER

   `min-width: 0` lod knappen skrumpe uden bund. Naar
   driftsprikken folder sig ud til «Kan ikke sælge — masteren
   svarer ikke», aad advarslen pladsen, og «Jakob» blev 35 px
   bred. Maalt 2. september 2026 paa iPhone staaende i noeddrift:
   35 x 44, hvor kravet er 44.

   Og det sker praecis, naar noget er galt — hvor et vagtskifte
   ofte er dét, der skal ske. Navnet forkortes stadig med
   ellipsis; det er BREDDEN under fingeren, der har en bund.
   Advarslen giver sig i stedet: dens fulde tekst staar i
   dialogen bag trykket.
   ------------------------------------------------------------ */
/* `.topbar > *` saetter `min-width: 0` og er baade senere og mere
   specifik end en enkelt klasse — samme faelde som prikken faldt
   i. Derfor `.topbar >` ogsaa her. */
.topbar > .topbar__skift--kort {
  min-width: var(--touch-min, 44px);
  max-width: 108px;
  padding-left: 8px; padding-right: 8px;
}

/* Advarslen er den, der skal give sig: dens fulde tekst staar i
   dialogen bag trykket, og prikken alene siger allerede, at noget
   er galt. Uden det her aad den navnet i stedet. */
.topbar--kompakt > .chip {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.topbar__skift--kort .topbar__navn {
  font-size: 12.5px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

.topbar__hus {
  flex: 0 0 auto;
  font-size: 13px; font-weight: 800;
  color: var(--tx-2);
  white-space: nowrap;
}

.topbar__bord {
  flex: 0 0 auto;
  padding: 5px 11px;
  border-radius: 999px;
  border: 1px solid var(--orange);
  background: var(--orange-soft, transparent);
  color: var(--orange);
  font-size: 12px; font-weight: 800; letter-spacing: .8px;
  white-space: nowrap;
}

/* ------------------------------------------------------------
   BORDCHIPPEN ER EN KNAP — OG SKAL KUNNE RAMMES

   Den baerer vejen tilbage til bordoversigten; se `bordchip` i
   `shell.js`. En knap, der er 22 px hoej, er ikke en knap paa en
   telefon. `.topbar > *` er baade senere i filen og mere
   specifik end en enkelt klasse — samme laerestreg som prikken
   nedenfor — saa hoejden saettes med `.topbar >`.

   Chevronen staar foer navnet og siger retningen. Den er svagere
   end teksten: det er BORDET man laeser, pilen er kun en
   paamindelse om, at man kan gaa tilbage.
   ------------------------------------------------------------ */
.topbar > .topbar__bord--knap {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  min-height: var(--touch-min, 44px);
  cursor: pointer;
  font-family: inherit;
}
.topbar__beloeb__af {
  display: block;
  font-size: 10.5px;
  font-weight: 600;
  color: var(--tx-3);
  line-height: 1.1;
  text-align: right;
}

.topbar__bordpil {
  font-size: 15px;
  font-weight: 700;
  opacity: .7;
  line-height: 1;
}
.topbar > .topbar__bord--knap:active {
  background: color-mix(in srgb, var(--orange) 18%, transparent);
}
/* ------------------------------------------------------------
   PRIKKEN ALENE — MEN STADIG EN FINGER BRED

   Den baerer nu BEGGE doere: eet tryk aabner drift og version,
   langt tryk aabner skaermvaelgeren. Saa skal den kunne rammes.

   `.topbar > *` saetter `min-width: 0`, saa navnet kan give sig,
   og den regel er baade senere og mere specifik end en enkelt
   klasse. Foerste forsoeg blev derfor 16 px bredt — maalt paa
   iPhone staaende 1. september 2026, og 16 px er en tredjedel af
   husets eget fingermaal. Barnebarnet skal vaere lige saa
   specifikt for at vinde.
   ------------------------------------------------------------ */
.topbar > .chip--kunprik {
  min-width: var(--touch-min);
  height: var(--touch-min);
  padding-left: 0; padding-right: 0;
  justify-content: center;
  font-size: 15px;
  letter-spacing: 0;
}

.kregning__titel {
  font-size: 9.5px; font-weight: 800; letter-spacing: 1.5px; color: var(--tx-3);
}
.kbordchip {
  padding: 3px 10px; border-radius: 999px;
  border: 1px solid var(--orange); background: var(--orange-soft, transparent);
  color: var(--orange); font-size: 11px; font-weight: 800; letter-spacing: .8px;
}
.kregning__liste {
  flex: 1 1 auto; min-height: 0; overflow-y: auto;
  display: flex; flex-direction: column; gap: 6px;
}
.kregning__tom { color: var(--tx-3); font-size: 13.5px; padding: 14px 4px; }

/* ---------- Linjen ---------- */
.kline {
  /* `flex:0 0 auto` er hele pointen: uden den skrumper linjerne,
     naar der kommer flere paa, og til sidst er de ulaeselige. */
  flex: 0 0 auto;
  display: flex; align-items: center; gap: 8px;
  padding: 4px 8px 4px 0;
  background: var(--bg-2); border-radius: 8px;
  position: relative; overflow: hidden; cursor: pointer;
  touch-action: pan-y;
}
.kline::before {
  content: ""; position: absolute; left: 0; top: 4px; bottom: 4px; width: 4px;
  border-radius: 0 3px 3px 0; background: var(--line-2);
}
.kline--unsent::before          { background: var(--orange); }
.kline--sent::before,
.kline--kaldt::before           { background: var(--green); }
.kline--vent::before            { background: var(--yellow); }
.kline--afsendelsesfejl::before { background: var(--red); }
.kline--afsendelsesfejl         { background: var(--red-soft, var(--bg-2)); }
.kline--retur::before           { background: var(--red); }
.kline--void::before            { background: var(--line-strong); }
.kline--void { opacity: .5; text-decoration: line-through; }

.kline__greb {
  flex: 0 0 auto; width: 18px; margin-left: 4px; align-self: stretch;
  cursor: grab; touch-action: none;
  background:
    radial-gradient(circle, var(--tx-3) 1px, transparent 1px) 0 0/6px 6px;
  opacity: .55;
}
/* Sendt vare: grebet BLIVER stående, men usynligt. Fjernedes det,
   ville de sendte linjer stå 18 px forskudt for de usendte, og
   listen ville se ud, som om den var i stykker. */
.kline__greb--laast { visibility: hidden; cursor: default; }

/* ============================================================
   MENS DER TRÆKKES

   To ting skal ses på én gang: hvilken vare der er i hånden, og
   hvor den lander, hvis fingeren slippes nu. Uden det sidste er
   trækket et gæt, og en tjener gætter ikke i en fyldt restaurant.

   Målet vises som en streg i kanten mellem to linjer — ikke som
   en fremhævet linje. En fremhævet linje ville betyde «her»,
   og svaret er «foran her» eller «bagved her».
   ============================================================ */
.kline--traekkes { opacity: .45; cursor: grabbing; }
.kline--traekkes .kline__greb { cursor: grabbing; }
/* Stregen ligger INDE i linjen. `.kline` har `overflow: hidden`
   for at holde på statusstriben, og en markør uden for kanten
   ville blive klippet væk uden at efterlade spor. */
.kline--maal-foer::after,
.kline--maal-efter::after {
  content: ""; position: absolute; left: 0; right: 0; height: 3px;
  background: var(--accent); pointer-events: none;
}
.kline--maal-foer::after  { top: 0; }
.kline--maal-efter::after { bottom: 0; }
.kline__antal {
  flex: 0 0 auto; margin-left: 6px; min-width: 24px;
  font-size: 14px; font-weight: 800; color: var(--tx-2);
  font-variant-numeric: tabular-nums;
}
.kline__krop { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.kline__navn {
  font-size: 14.5px; font-weight: 600;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.kline__tekst {
  font-size: 12px; color: var(--yellow); font-style: italic;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.kline__pris {
  flex: 0 0 auto; font-size: 14.5px; font-weight: 700;
  font-variant-numeric: tabular-nums;
}
/* Plus og minus er mindre her end paa kassen — men aldrig under
   fingermaalet paa hoejden, som er dét, der rammes forkert. */
/* ------------------------------------------------------------
   PLUS OG MINUS ER MINDRE HER — MED VILJE

   Dennis, 31. august 2026: «Minus og plus skal være mindre end
   de er nu, og man skal også kunne swipe på en vare for at ændre
   antal.» Swipet er den store trykflade; knapperne er den
   præcise.

   Men i «Høj kontrast» gælder temaets mål. Det tema findes for
   den, der har svært ved at ramme, og så er en 30 px knap ikke
   en forfinelse — den er den ene ting, temaet ikke hjalp med.

   Målet er derfor en ANDEL af husets fingermål og ikke et fast
   tal: 70 % af 44 er 31, af «Høj kontrast»' 48 er 34. Så følger
   knappen temaet uden at holde op med at være den lille.
   (Et `[data-theme]`-greb ville ikke virke — temaet sætter
   variabler, ikke en attribut på roden.)

   ------------------------------------------------------------
   OG DEN HER REGEL HAR ALDRIG VIRKET

   Noten lukkede to gange: stregen med en afsluttende kommentar
   stod både efter næstsidste OG efter sidste afsnit. De fem linjer
   imellem blev til rå CSS, og en fejl i CSS æder frem til den
   næste tuborgklamme — så prosaen OG vælgeren `.kompakt .linjeknap`
   blev ét ugyldigt navn, og hele reglen blev kasseret.

   Ingen fejl nogen steder. Plus og minus på den håndholdte flade
   har bare aldrig fået den mindre størrelse, Dennis bad om 31.
   august 2026 — og har derfor heller aldrig fulgt «Høj kontrast»'
   større fingermål.

   Fundet 6. september 2026 ved at tælle kommentarernes åbninger mod
   deres lukninger. Der var to af slagsen; den anden havde slugt den
   flade, knap-editoren skulle kunne panoreres på.

   Reglen er nu maalt af `stilarkstest`, saa den ikke kan ske igen.
   ------------------------------------------------------------ */
.kompakt .linjeknap {
  min-width: calc(var(--touch-min, 44px) * 0.78);
  min-height: calc(var(--touch-min, 44px) * 0.7);
  font-size: 16px;
}

/* ---------- Totalen ---------- */
.ktotal {
  flex: 0 0 230px;
  display: flex; flex-direction: column; gap: 8px;
  padding: 10px 12px; min-height: 0;
  background: var(--bg-1); border: 1px solid var(--line-1);
  border-radius: var(--r-md); position: relative; overflow: hidden;
}
.ktotal::before {
  content: ""; position: absolute; left: 0; top: 10px; bottom: 10px; width: 4px;
  border-radius: 0 3px 3px 0; background: var(--orange);
}
.ktotal__greb { flex: 0 0 auto; cursor: pointer; user-select: none; padding: 2px 0 2px 8px; }
/* ------------------------------------------------------------
   TOTAL TIL VENSTRE, MADEN TIL HOEJRE

   Dennis, 8. september 2026: samme gangtaeller som paa kassen,
   men «diskret visning» paa iPhone og iPad. Linjen med TOTAL
   baerer eet kort ord og ellers tom plads; taelleren lever der.
   Ingen raekke bliver hoejere, og ingen knap flytter sig.
   ------------------------------------------------------------ */
/* Gangtaelleren i toplinjen paa en telefon — se `topbeloeb` i
   shell.js. Samme stoerrelse som «af 207,00» ved siden af. */
.topbar__gang {
  display: block; font-size: 9.5px; font-weight: 800; letter-spacing: .4px;
  color: var(--tx-3); white-space: nowrap; line-height: 1.1;
}
.ktotal__hoved { display: flex; align-items: baseline; justify-content: space-between; gap: 6px; }
.ktotal__label { font-size: 9.5px; font-weight: 800; letter-spacing: 1.5px; color: var(--tx-3); }
.ktotal__gang {
  font-size: 9.5px; font-weight: 800; letter-spacing: .4px; color: var(--tx-3);
  white-space: nowrap;
}
.ktotal__tal { font-size: 25px; font-weight: 800; letter-spacing: -.5px; margin-top: 1px; }
.ktotal__hint { font-size: 9.5px; font-weight: 700; color: var(--tx-3); letter-spacing: .6px; margin-top: 2px; }
.kgenveje {
  flex: 1 1 auto; min-height: 0; overflow: auto;
  display: grid; grid-template-columns: 1fr 1fr; gap: 6px;
  /* ------------------------------------------------------------
     GENVEJENE FYLDER TOTALFELTET UD

     `align-content: start` lagde de fire genveje oeverst og lod
     resten staa tom. Maalt 31. august 2026 paa iPad liggende:
     cirka 100 px ubrugt under «Besked» og «Fortryd», inde i et
     felt, der i forvejen er husets mindste.

     De fire er de handlinger, tjeneren bruger oftest uden at
     aabne en menu. Er der plads, skal de have den — en stoerre
     genvej er en, der bliver brugt.

     Loftet holder dem fra at blive plakater paa en hoej iPad, og
     `overflow: auto` gaelder stadig: er der flere genveje end der
     er plads til (udfoldet regning viser ni), ruller de.
     ------------------------------------------------------------ */
  align-content: stretch;
  grid-auto-rows: minmax(max(46px, var(--touch-min, 44px)), 1fr);
}
.kgenvej { max-height: 96px; }

/* ---------- Kategoristriben ---------- */
.kkatstribe {
  flex: 0 0 auto; display: flex; gap: 6px;
  overflow-x: auto; overflow-y: hidden; overscroll-behavior-x: contain;
  padding-bottom: 2px; scrollbar-width: thin;
}
.kkat {
  flex: 0 0 auto; min-height: var(--touch-min, 44px); padding: 0 14px;
  background: var(--bg-3); border: 1px solid var(--line-2);
  border-radius: var(--r-sm); color: var(--tx-1);
  font-size: 13.5px; font-weight: 700; white-space: nowrap; cursor: pointer;
}
.kkat.is-active { background: var(--accent); border-color: var(--accent); color: var(--accent-tx); }
.kkat--hjem { background: var(--bg-2); border-color: var(--line-strong); }

/* ---------- Varefladen ---------- */
/* Varefladen faar resten af hoejden. `min-height: 0` er noedvendig,
   for at den kan rulle, naar knapsiden er stoerre end fladen. */
.kvarer { flex: 1 1 auto; min-height: 0; min-width: 0; display: flex; }
.kvarer > * { flex: 1 1 auto; min-height: 0; }

/* ============================================================
   KNAPPERNE FYLDER FLADEN UD — PAA DEN KOMPAKTE FLADE

   ------------------------------------------------------------
   DET, DER VAR GALT

   Gitteret staar `align-content: start`, saa raekkerne laegger sig
   oeverst og resten bliver staaende tom. Maalt 31. august 2026 paa
   iPad liggende: tretten varer i to raekker a 48 px, og 100 px
   ubrugt under dem. Staaende var det 250 px.

   Paa en iPad er det spild af netop det, der er knapt: plads at
   ramme paa.

   ------------------------------------------------------------
   HVORFOR DET IKKE ER I STRID MED D-0013

   Dér blev `align-content: start` beholdt paa HUSETS KASSE, fordi
   knapsiden har tolv raekker, kun tre med knapper, og ANTAL-panelet
   staar paa raekke tolv: en fordeling ville give de tomme raekker
   del i pladsen og skubbe panelet ud under skaermkanten.

   Den kompakte flade har intet ANTAL-panel — antallet aendres med
   plus, minus og swipe paa linjen — og gitteret her har kun de
   raekker, der faktisk er knapper i. Der er intet at skubbe ud.

   Raekkerne faar et loft, saa fire varer paa en hoej iPad ikke
   bliver fire plakater.
   ============================================================ */
#screen:has(.kompakt) .buttongrid {
  align-content: stretch;
  grid-auto-rows: minmax(var(--pos-knap-hoejde, 52px), 1fr);
}
#screen:has(.kompakt) .gridcell { max-height: 120px; }

/* ---------- Bundbjaelken ---------- */
/* Bjælkens højde er en værdi, andre skal kunne regne med — se
   `.toast-host` ovenfor, der løfter beskeden fri af den. Står
   tallet to steder, går de fra hinanden den dag, knapperne bliver
   højere. */
:root { --kbund-hoejde: 64px; }

.kbund {
  flex: 0 0 auto;
  display: grid; grid-template-columns: repeat(4, 1fr);
  background: var(--bg-1); border: 1px solid var(--line-1);
  border-radius: var(--r-md); overflow: hidden;
}
.kbund__knap {
  position: relative;
  min-height: var(--kbund-hoejde); padding: 12px 8px;
  background: none; border: 0; border-right: 1px solid var(--line-1);
  color: var(--tx-1); font-size: 12.5px; font-weight: 800; letter-spacing: 1.3px;
  cursor: pointer;
}
.kbund__knap:last-child { border-right: 0; }
.kbund__knap:active { background: var(--bg-3); }
.kbund__knap--afslut { background: var(--accent); color: var(--accent-tx); }
/* Tallet i HJØRNET, ikke oven i teksten. `right: calc(50% - 48px)`
   satte det midt over ordet «AFSLUT», og med to cifre laa det hen
   over bogstaverne. Maalt 31. august 2026. */
.kbund__maerke {
  position: absolute; top: 8px; right: 10px;
  min-width: 24px; height: 24px; padding: 0 7px; border-radius: 999px;
  background: var(--bg-0); color: var(--accent);
  font-size: 12.5px; font-weight: 800; line-height: 24px;
}

/* ---------- Menuarket ---------- */
.kmgruppe {
  font-size: 9.5px; font-weight: 800; letter-spacing: 1.5px;
  color: var(--tx-3); margin: 14px 0 8px 2px;
}
/* ------------------------------------------------------------
   MENUGITTERET FØLGER SKÆRMEN

   Her stod `repeat(4, 1fr)` fast. Fire kolonner er rigtigt på en
   iPad. På en telefon i højformat er fladen 393 px: fire felter
   bliver 85 px brede, og «Besked til køkkenet» kan hverken stå
   eller rammes.

   Tallet kommer fra motorens breddeklasse og ikke fra et
   `@media` — så gælder det også, når layoutet regnes på en anden
   flade end vinduets. Se `breddeklasse` i skaermlayout.js.
   ------------------------------------------------------------ */
.kmgitter { display: grid; grid-template-columns: repeat(4, 1fr); gap: 12px; }
:root[data-pos-bredde="mellem"] .kmgitter { grid-template-columns: repeat(3, 1fr); }
:root[data-pos-bredde="smal"]   .kmgitter { grid-template-columns: repeat(2, 1fr); gap: 10px; }

/* På en smal skærm er der ikke plads til at et felt fylder en
   hel række alene — den primære knap bliver i stedet bare høj. */
:root[data-pos-bredde="smal"] .kmfelt--primaer { flex-direction: column; text-align: center; }
.kmfelt {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 6px; min-height: 96px; padding: 12px 10px;
  background: var(--bg-2); border: 1px solid var(--line-2); border-radius: 14px;
  color: var(--tx-1); font-size: 14px; font-weight: 700; line-height: 1.2;
  text-align: center; cursor: pointer;
}
.kmfelt:active { background: var(--bg-4); }
.kmfelt--fra { opacity: .42; cursor: default; }
.kmfelt--fare { border-color: var(--red); }
.kmfelt--fare .kmfelt__navn { color: var(--red-tekst); }

/* ------------------------------------------------------------
   PENGE ER GRØNNE — OGSÅ I MENUEN

   Dennis, 1. september 2026: «betal knappen skal være grøn over
   alt.»

   Betalingsskærmens metoder (Kort, Kontant DKK) er `--green`.
   Stod menufeltet i husets neutrale grå, skiftede betalingen
   kulør undervejs: man trykkede på en grå knap og landede på en
   grøn skærm.

   Feltet er FYLDT og ikke bare kantet. Det er den ene handling
   på arket, der flytter penge, og den skal kunne findes uden at
   læse — samme grund som at «Send bestilling» er orange og
   fylder hele bredden.

   Farverne er husets `.btn--pay` — `--green` med `--tx-inv`
   ovenpå — og ikke en ny variant. Betalingsknappen findes
   allerede, og der skal ikke være to grønne i huset.
   ------------------------------------------------------------ */
.kmfelt--penge {
  background: var(--green);
  border-color: var(--green);
  color: var(--tx-inv);
}
.kmfelt--penge .kmfelt__navn { color: var(--tx-inv); }
/* Underteksten er husets dæmpede tone PÅ den grønne — ikke den
   grå, der er lavet til en mørk flade. */
.kmfelt--penge .kmfelt__under { color: var(--tx-inv); opacity: .78; }
.kmfelt--penge:active { background: var(--green-dk); border-color: var(--green-dk); }
.kmfelt--primaer {
  grid-column: 1 / -1; flex-direction: row; gap: 14px; min-height: 82px;
  background: var(--accent); border-color: var(--accent); color: var(--accent-tx);
  font-size: 18px; text-align: left;
}
/* ------------------------------------------------------------
   BRED OG GRØN PÅ ÉN GANG

   `--primaer` gør feltet bredt og orange; `--penge` gør det
   grønt. Barsalgets «Betal» er begge dele: den er arkets ene
   hovedhandling, OG den flytter penge.

   Reglen står EFTER `--primaer`, så den grønne vinder farven og
   den primære beholder bredden. Rækkefølgen er ikke et tilfælde
   — den er dét, der gør, at de to kan bruges sammen.
   ------------------------------------------------------------ */
.kmfelt--primaer.kmfelt--penge {
  background: var(--green);
  border-color: var(--green);
  color: var(--tx-inv);
}
.kmfelt--primaer.kmfelt--penge .kmfelt__under { color: var(--tx-inv); opacity: .78; }
.kmfelt--primaer.kmfelt--penge:active {
  background: var(--green-dk);
  border-color: var(--green-dk);
}

/* ------------------------------------------------------------
   IKONET OVER NAVNET

   Feltet er en søjle — ikon, navn, undertekst — så ikonet ikke
   stjæler bredde fra teksten på en telefon, hvor felterne står to
   og to. 26 px: stort nok til at kendes på afstand, lille nok til
   at navnet stadig er det, man læser.

   `currentColor` sidder på selve SVG'en, så den arver feltets
   tekstfarve — også når feltet er grønt eller slukket.
   ------------------------------------------------------------ */
.kmfelt__ikon {
  width: 26px;
  height: 26px;
  flex: 0 0 auto;
  display: block;
}
/* På det brede primærfelt står ikon og tekst på række, og så skal
   ikonet være lidt større — der er plads, og feltet er arkets
   hovedhandling. */
.kmfelt--primaer .kmfelt__ikon { width: 30px; height: 30px; }

.kmfelt__navn { display: block; }
.kmfelt__under {
  display: block; margin-top: 3px;
  font-size: 11.5px; font-weight: 600; color: var(--tx-3); line-height: 1.25;
}
.kmfelt--primaer .kmfelt__under { color: var(--accent-tx); opacity: .85; font-size: 13px; }

/* ------------------------------------------------------------
   ÉN NAVIGATION, IKKE TO

   Husets bundnavigation (Borde · Gavekort · Knapper …) og den
   kompakte flades fire doere stod oven paa hinanden. To raekker
   navigation i bunden af en iPad er 130 px, der ikke gaar til
   varerne — og to steder at lede efter det samme.

   De tre punkter er ikke vaek: «Borde» ligger i AFSLUT (tilbage
   til bordoversigten), «Gavekort» i HANDLING (husets egen taste),
   «Knapper» i KONFIG. Dennis, 30. august 2026: «de knapper skal
   fjernes, de skal laegges ind under noget andet, for eksempel
   config».

   Den skjules KUN mens bordvisningen staar der. Paa bordplanen og
   koekkenskaermen er den stadig husets vej rundt, og uden den
   ville man staa fast.
   ------------------------------------------------------------ */
#screen:has(.kompakt) ~ .bottomnav { display: none; }

/* ------------------------------------------------------------
   TOPLINJEN MÅ IKKE SKUBBE SIDEN UD OVER KANTEN

   Målt 31. august 2026 på 393 px (iPhone i højformat): «SKIFT
   BRUGER» stak 7 px ud, og hele siden fik en vandret rullebjælke.
   Syv pixels — men en POS med sidescroll er en POS, hvor en
   knap kan gemme sig, og hvor et swipe på en vare kan komme til
   at flytte hele skærmen i stedet.

   Der gøres ikke bare skrift mindre. Delene får lov at give sig
   (`min-width: 0`), navnet klippes med ellipsis frem for at
   presse, og på de smalleste skærme falder underteksten væk:
   ikonet og navnet siger det samme, og knappen er den samme at
   ramme.
   ------------------------------------------------------------ */
.topbar { min-width: 0; }
.topbar > * { min-width: 0; }
.topbar__skift { min-width: 0; overflow: hidden; }
.topbar__navn {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 100%;
}
.topbar__skiftord { white-space: nowrap; }

/* På en smal skærm er der ikke plads til begge linjer.
   Underteksten er den, der kan undværes — «Sofie» med et
   personikon ved siden af er ikke til at misforstå.

   Klassen kommer fra motoren (`data-pos-bredde`) og ikke fra et
   `@media`: så gælder den også, når layoutet regnes på en anden
   flade end vinduets — og der er ét sted at læse, hvad «smal»
   betyder. Se `breddeklasse` i skaermlayout.js. */
:root[data-pos-bredde="smal"] .topbar__skiftord { display: none; }

.kgenvej {
  /* Følger temaet. «Høj kontrast» hæver `--touch-min` til 48 px,
     netop fordi den findes for den, der har svært ved at ramme —
     og en genvej paa faste 46 px ville saa vaere den ene knap paa
     skaermen, temaet ikke gjaldt for. Maalt 31. august 2026. */
  min-height: max(46px, var(--touch-min, 44px)); padding: 6px 8px;
  background: var(--bg-3); border: 1px solid var(--line-2); border-radius: 9px;
  color: var(--tx-1); font-size: 12.5px; font-weight: 700; line-height: 1.15;
  cursor: pointer;
}
.kgenvej:active { background: var(--bg-4); }
.kgenvej--fra { opacity: .42; cursor: default; }
:root[data-pos-bredde="smal"] .kgenveje { grid-template-columns: 1fr; }
.kompakt--udvidet .kgenvej { min-height: 52px; font-size: 13.5px; }

/* ------------------------------------------------------------
   BETALINGSSPALTEN MÅ GIVE SIG PÅ EN SMAL SKÆRM

   `.ordright` er `flex: 0 0 372px` — regningen skal have plads,
   og den skal ikke skifte bredde, mens man deler en regning.
   Det er rigtigt på en kasse og på en iPad.

   Målt 31. august 2026 på 360 px: de 372 stak 36 px ud over
   fladen, og hele betalingsskærmen fik en vandret rullebjælke.
   Man kunne betale, men beløbet lå halvt uden for kanten.

   Under 560 px (motorens «smal») bliver den en almindelig
   spalte, der giver sig. Der er alligevel ikke to spalter ved
   siden af hinanden på en telefon.
   ------------------------------------------------------------ */
:root[data-pos-bredde="smal"] .ordright {
  flex: 1 1 auto;
  border-left: 0;
  border-top: 1px solid var(--line-1);
}

/* ------------------------------------------------------------
   OG SPALTERNE BLIVER TIL RÆKKER

   Det var ikke nok at lade betalingsspalten give sig: `.ordmain`
   er en RÆKKE, saa regningen og betalingsmaaderne stod stadig
   side om side. Paa 360 px fik regningen 145, og varenavnet 38 —
   «Boef Bearnaise» blev til 28 px. Maalt 31. august 2026.

   Paa en telefon er der ikke to spalter. Regningen faar hele
   bredden, og betalingsmaaderne staar under den.
   ------------------------------------------------------------ */
:root[data-pos-bredde="smal"] .ordmain {
  flex-direction: column;
  overflow-y: auto;
  overscroll-behavior: contain;
}
:root[data-pos-bredde="smal"] .ordmain > * { flex: 0 0 auto; }

/* ------------------------------------------------------------
   OG SÅ ER DER KUN ÉT LODRET RULLEFELT — OGSÅ I EDITOREN

   Knap-editorens flade fik `overflow: auto`, så gitteret kan
   panoreres. På en telefon er `.ordmain` husets ENESTE lodrette
   rullefelt (se reglen ovenfor), og børnene har deres naturlige
   højde. Editorfladen blev derfor et rullefelt, der var højere end
   den kasse, der klipper det — og som ikke rullede: man skulle
   ramme det rigtige af to felter oven i hinanden.

   `skaermscan.doedtRul` fandt den 6. september 2026. Det er den
   samme fejl, `.pay__venstre` havde 1. september.

   Her skal kun BREDDEN rulle. Højden er elementets egen — der er
   ikke noget at klippe — så `hidden` klipper ingenting og fjerner
   det døde rullefelt.
   ------------------------------------------------------------ */
:root[data-pos-bredde="smal"] .editorflade:has(.gridcell--edit) {
  overflow-x: auto;
  overflow-y: hidden;
}

/* ------------------------------------------------------------
   OG SAA ER DER KUN EET RULLEFELT

   Regningsspalten `.pay__venstre` baerer `.scroll-y`. Det er
   rigtigt, naar den staar ved siden af metoderne og har sin egen
   hoejde. Her har den det ikke: `flex: 0 0 auto` ovenfor giver den
   sin naturlige hoejde, og saa er der ingenting at rulle i den.

   Maalt 1. september 2026, iPhone i hoejformat, bord 16:
     .pay__venstre   370 px hoej, scrollHeight 370  →  ruller ikke
     .ordmain        clientHeight 305               →  klipper 65

   De 65 px var «Annullér betaling» paa den nederste betaling.
   Man kunne komme derned — forfaderen rullede — men fingeren
   skulle ramme det rigtige af to rullefelter oven i hinanden, og
   det oeverste af dem var det doede.

   `skaermscan`-reglen `doedtRul` maaler netop det: et rullefelt,
   der er hoejere end den kasse, der klipper det. Den fandt dette
   ene sted paa tvaers af syv skaerme og ti ruter.
   ------------------------------------------------------------ */
/* ------------------------------------------------------------
   OG DEN GAELDER KUN BETALINGSSKAERMEN

   Vaelgeren stod som `.ordmain > .scroll-y` — uden `.pay`. Men
   `.ordmain` er ikke betalingsskaermens; den bruges ogsaa af
   knap-editoren, hvor hoejre spalte er
   `div.ordright.scroll-y.stack-3` med «Dine knapper», sideinfo og
   vaerktoej.

   Paa en smal skaerm slukkede reglen derfor rulningen i editorens
   hoejre spalte. Indholdet var hoejere end spalten og hverken rullede
   eller blev klippet — `skaermscan.spildt` fandt den paa fem skaerme
   i `iphoneknaptest` 6. september 2026.

   Noten ovenfor siger selv, hvad reglen handler om: `.pay__venstre`
   paa betalingsskaermen. Vaelgeren siger det nu ogsaa. Samme
   fejlklasse som den, den skulle rette — et sted, der klipper noget,
   det ikke vidste, det havde.
   ------------------------------------------------------------ */
:root[data-pos-bredde="smal"] .pay .ordmain > .scroll-y { overflow: visible; }

/* ------------------------------------------------------------
   OG KANTEN SIGER, AT DER ER MERE

   Samme blaending som kategoristriben, bare nedad. Uden den blev
   den nederste raekke skaaret over paa midten: en halv knap, der
   ligner en knap, der er gaaet i stykker.

   `.ordmain--alt-synligt` saettes af `JC.rullehint` — baade naar
   der ikke er noget at rulle til, og naar der er rullet helt ud.
   Ellers ville den sidste linje paa regningen staa halvt udvisket,
   mens den er fuldt laesbar.
   ------------------------------------------------------------ */
:root[data-pos-bredde="smal"] .ordmain {
  -webkit-mask-image: linear-gradient(to bottom, currentColor calc(100% - 24px), transparent 100%);
  mask-image: linear-gradient(to bottom, currentColor calc(100% - 24px), transparent 100%);
}
:root[data-pos-bredde="smal"] .ordmain--alt-synligt {
  -webkit-mask-image: none;
  mask-image: none;
}

/* ============================================================
   PÅ EN SMAL SKÆRM STÅR TOTALEN OVER REGNINGEN — IKKE VED SIDEN

   Målt 31. august 2026 på 393 px (iPhone i højformat):
   TOTAL-kortet er 230 px bredt. Af de 393 var der 140 tilbage til
   regningen, og varenavnet blev nul pixels bredt. Skærmen viste
   «2× 70,00» uden at sige hvad det var.

   Dennis, 31. august 2026: «man skal ALTID kunne se, hvad der
   ligger på regningen, antal og pris.» Antal og pris var der.
   Varen var ikke.

   Proben fangede det ikke: navnet har `text-overflow: ellipsis`,
   og et element på nul pixels har ikke noget overløb. Derfor
   måler den nu også, om et varenavn har plads nok til at kunne
   læses.

   På den smalle skærm bliver totalen derfor en smal bjælke
   ØVERST: beløbet i fuld bredde, og genvejene væk — de ligger
   alle i de fire menuer, hvor felterne er 96 px høje og lettere
   at ramme end en genvej på en telefon.
   ============================================================ */
:root[data-pos-bredde="smal"] .kregnrum { flex-direction: column; gap: 8px; }
:root[data-pos-bredde="smal"] .ktotal {
  flex: 0 0 auto;
  flex-direction: row;
  align-items: baseline;
  gap: 10px;
  padding: 8px 12px;
}
:root[data-pos-bredde="smal"] .ktotal__greb {
  flex: 1 1 auto;
  display: flex;
  align-items: baseline;
  gap: 10px;
  padding: 0 0 0 8px;
}
/* Beløbet brækker ikke. Det er tallet, man siger højt til
   gæsten, og «2.494,00 / kr.» over to linjer er ikke ét beløb. */
:root[data-pos-bredde="smal"] .ktotal__tal {
  font-size: 21px; margin-top: 0; white-space: nowrap;
}
/* Hintet er en oplysning, ikke en handling. Det viger, når der
   ikke er plads — dobbelttrykket virker uanset. */
:root[data-pos-bredde="smal"] .ktotal__hint { display: none; }
:root[data-pos-bredde="smal"] .kgenveje { display: none; }
/* ------------------------------------------------------------
   OG PAA EN FLAD SKAERM AF SAMME GRUND

   En telefon paa siden er 393 px hoej. Totalen faar det, der er
   tilbage, og genvejene blev skaaret midt over: maalt 31. august
   2026 stod to halve knapper i bunden af feltet.

   Det er samme situation som «smal» ovenfor, og svaret er husets
   eget: de viger, og de er der igen, naar regningen foldes ud.
   De samme handlinger staar i ORDRE og HANDLING med felter, der
   kan rammes.
   ------------------------------------------------------------ */
:root[data-pos-hoejde="lav"] .kgenveje { display: none; }
:root[data-pos-hoejde="lav"] .kompakt--udvidet .kgenveje { display: grid; }
/* Udfoldet er der plads igen — dér er genvejene med. */
:root[data-pos-bredde="smal"] .kompakt--udvidet .kgenveje {
  display: grid;
  grid-template-columns: 1fr 1fr;
}
:root[data-pos-bredde="smal"] .kompakt--udvidet .ktotal {
  flex-direction: column;
  align-items: stretch;
}

/* ------------------------------------------------------------
   HVEM ER JEG, OG HVAD HEDDER HUSET

   Målt 31. august 2026 på 393 px: toplinjen viste «Jakobs Café»
   og «S…» — tjenerens navn var klippet til ét bogstav, fordi
   statuschippen og vinduesadvarslen tog bredden.

   Vinduesadvarslen er siden fjernet helt (se `shell.js`), saa
   reglen for den er ogsaa vaek. Statuschippen og navnet deler nu
   bredden alene.
   ------------------------------------------------------------ */
:root[data-pos-bredde="smal"] .topbar { gap: 8px; padding: 0 10px; }

/* ------------------------------------------------------------
   BUNDNAVIGATIONEN MÅ IKKE SKUBBE SIDEN UD

   Punkterne er `flex: 1 1 0` og deler bredden. Det holder, så
   længe der er få af dem. En LEDER ser elleve — Borde, Køkken,
   Gavekort, Retur, Kasse, Konti, Arkiv, Knapper, Besked,
   Printere, Udseende — og elleve punkter kan ikke deles ned
   under deres egen tekst.

   Målt 31. august 2026 på 393 px: bjælken var 393 bred med 404
   px indhold, og HELE siden fik en vandret rullebjælke. Det ramte
   hver eneste skærm, ikke kun bordplanen.

   Den ruller nu selv, som kategoristriben. Alle elleve veje er
   der stadig — bjælken holder bare sit overløb for sig selv.
   ------------------------------------------------------------ */
.bottomnav {
  overflow-x: auto;
  overflow-y: hidden;
  overscroll-behavior-x: contain;
  scrollbar-width: none;
}
.bottomnav::-webkit-scrollbar { display: none; }
/* Ruller den, skal punkterne beholde deres bredde — ellers
   klemmes de alligevel, bare inde i rulningen. */
:root[data-pos-bredde="smal"] .bottomnav__item { flex: 0 0 auto; min-width: 84px; }

/* ------------------------------------------------------------
   ARKIVETS FILTRE MÅ IKKE ÆDE LISTEN

   Filtrene står med vilje fast, så de ikke ruller væk, når man
   søger — det er rigtigt på en kasse. På en telefon bryder de
   samme filtre over mange rækker: målt 31. august 2026 på 360 px
   var blokken 433 px af de 523, listen fik NUL, og «Forrige /
   Næste» blev skubbet ned under bundbjælken.

   Filtrene bliver — de får bare deres eget rullefelt på den
   smalle skærm. Alle filtre er der stadig, listen får plads, og
   sidefoden bliver, hvor den skal være.
   ------------------------------------------------------------ */
:root[data-pos-bredde="smal"] .arkiv > .card {
  max-height: 38%;
  overflow-y: auto;
  overscroll-behavior: contain;
}

/* ------------------------------------------------------------
   KNAPSIDEN REDIGERES I SIN RIGTIGE STØRRELSE

   I redigering må gitteret IKKE brydes om: kolonne 9 er præcis
   dét, man står og flytter en knap hen til. Derfor beholder
   editoren husets egne kolonner — se `ombryd` i skaermlayout.js,
   som med vilje ikke rører redigering.

   Men elleve kolonner i 218 px blev 44 px pr. celle, og
   varenavnet fik 28 px: «Fadøl» kunne ikke læses. Målt 31.
   august 2026 på 393 px.

   Cellen får derfor sin læsbare bredde tilbage, og fladen
   panoreres i stedet. En knap, man kan læse og ramme, er mere
   værd end et overblik, man ikke kan bruge — og editoren er et
   opsætningsværktøj, ikke noget man rører midt i en servering.

   Reglen hænger IKKE på en skærmklasse. Elleve kolonner er for
   smalle, så snart fladen er under ~1000 px — også i et panel på
   en stor kasse. Målt på 1024: cellen blev 45 px og navnet 38. Er
   der plads, ændrer reglen ingenting; er der ikke, panorerer man.

   ------------------------------------------------------------
   OG SÅ VAR DER EN AFSLUTTET KOMMENTAR MIDT I NOTEN

   Stregen med en afsluttende kommentar stod efter det næstsidste
   afsnit OG efter det sidste. Noten lukkede altså for tidligt, og de
   fem linjer imellem blev til rå CSS.

   Følgen er den, der er svær at få øje på: en fejl i CSS æder frem
   til den næste tuborgklamme, så prosaen OG vælgeren
   `.gitterflade:has(.gridcell--edit)` blev ét ugyldigt navn, og HELE
   reglen blev kasseret. Ingen fejl nogen steder — den flade, der
   skulle kunne panoreres i redigering, kunne bare ikke.

   `.buttongrid:has(.gridcell--edit)` overlevede, fordi den står
   efter. Så gitteret ER 11 × 92 px bredt, og der var ingenting,
   der rullede. Målt 6. september 2026 af `vandretRul` på seks
   skærme i iphoneknaptest.
   ------------------------------------------------------------ */
.gitterflade:has(.gridcell--edit),
/* Knap-editoren har sin egen flade — den hedder ikke `.gitterflade`,
   men den skal panorere af nøjagtig samme grund. Se `editorflade` i
   layoutEditor.js. */
.editorflade:has(.gridcell--edit) {
  overflow: auto;
  overscroll-behavior: contain;
}
.buttongrid:has(.gridcell--edit) {
  grid-template-columns: repeat(var(--redigeringskolonner, 11), minmax(92px, 1fr)) !important;
  width: max-content;
  min-width: 100%;
}
/* ------------------------------------------------------------
   BREDDEN TILPASSER SIG OGSAA — NAAR HUSET HAR VALGT

   Dennis, 10. september 2026: «Nu mangler vi kun bredden. Hoejden
   er perfekt, den tilpasser sig.»

   Reglen ovenfor giver hver celle mindst 92 px og lader gitteret
   blive saa bredt, det vil (`max-content`), saa man kan panorere
   hen til de hoejre kolonner paa en telefon. Det er rigtigt for
   et gitter, ingen har valgt bredden paa.

   Har huset SAGT otte kolonner, er svaret et andet: de otte skal
   dele den plads, der er — praecis som de tolv raekker goer.
   MAALT samme dag: fladen 1068 px, fanesoejlen 116, og gitteret
   blev alligevel 1048 og stak 114 px ud over kanten.
   ------------------------------------------------------------ */
.editorflade--medfaner > .buttongrid:has(.gridcell--edit) {
  grid-template-columns: repeat(var(--redigeringskolonner, 8), minmax(0, 1fr)) !important;
  width: auto;
  min-width: 0;
  overflow-x: visible;
}

/* ------------------------------------------------------------
   PÅ EN LAV SKÆRM RULLER SKÆRMFELTET

   En telefon på tværs er 393 px høj. Arkivets filtre,
   printerbeskeden og betalingens valg er LISTER — de har mere
   indhold end det, og de har ingen grund til at kunne skrumpe.
   Målt 31. august 2026 på 852 × 393: «Forrige», «Send til
   printer» og «Kontant EUR» laa ned under bundbjælken.

   Bordvisningen er undtaget. Den er ikke en liste, den er en
   flade: dens dele har hver deres højde fra motoren, og den skal
   blive stående, mens man slår ind. Den ruller allerede indeni,
   dér hvor den skal.
   ------------------------------------------------------------ */
:root[data-pos-hoejde="lav"] #screen {
  overflow-y: auto;
  overscroll-behavior-y: contain;
}
:root[data-pos-hoejde="lav"] #screen:has(.kompakt),
:root[data-pos-hoejde="lav"] #screen:has(.kasse) {
  overflow-y: hidden;
}

/* ------------------------------------------------------------
   BORDBESKEDEN I REGNINGEN

   «Nøddeallergi ved plads 3» skal ses af alle, der åbner
   regningen — også ham, der møder ind klokken 18. Den står
   derfor øverst i listen og ikke i et panel, man skal åbne.

   Gul og ikke blå: den er en oplysning om GÆSTEN, ikke en
   besked til en printer. Den går ingen steder hen — den står
   der, indtil nogen fjerner den.
   ------------------------------------------------------------ */
.kbesked {
  flex: 0 0 auto;
  display: flex; align-items: center; gap: 10px;
  /* Raekken AABNER bordinfo — den er en knap, ikke et skilt, og
     skal derfor ramme husets touch-gulv som alt andet, man kan
     trykke paa. Se `--touch-min`. */
  min-height: var(--touch-min);
  padding: 6px 10px 6px 0;
  background: rgba(232, 192, 32, .12);
  border: 1px dashed var(--yellow);
  border-radius: 8px;
  position: relative; cursor: pointer;
}
.kbesked::before {
  content: ""; position: absolute; left: 0; top: 4px; bottom: 4px; width: 4px;
  border-radius: 0 3px 3px 0; background: var(--yellow);
}
.kbesked__maerke {
  flex: 0 0 auto; margin-left: 12px;
  font-size: 10.5px; font-weight: 800; letter-spacing: .9px; color: var(--yellow);
}
.kbesked__tekst {
  flex: 1 1 auto; min-width: 0;
  font-size: 13.5px; line-height: 1.25; color: var(--tx-1);
  /* To linjer, ikke een. «Noeddeallergi ved plads 3» fylder een,
     men «Ingen skaldyr, glutenallergi ved plads 2 og 5» fylder to
     — og det er netop den slags, der ikke maa klippes af. Er der
     mere endnu, klippes der foerst der; hele teksten staar i
     bordinfo, som raekken aabner. */
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2;
  overflow: hidden;
}

/* ============================================================
   TILSTANDSBÅNDET PÅ DEN KOMPAKTE FLADE

   Ét bånd, én linje. Farven kommer fra husets egne bannerklasser
   (`rettebanner`, `returbanner`, `rabatbanner`, `prisbanner`,
   `waitbanner`) — her sættes kun målene, så båndet koster så lidt
   højde som muligt på en skærm, man holder i hånden.
   ============================================================ */
.ktilstand {
  flex: 0 0 auto;
  padding: 6px 12px;
  border-radius: var(--r-sm);
  font-size: 12.5px;
  font-weight: 800;
  letter-spacing: .4px;
  text-align: center;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* Linjen, tilstanden vil ramme, skal kunne ses. */
.kline--rammes { outline: 2px solid var(--accent); outline-offset: -2px; }

/* Statusmærket paa regningslinjen. Smalt med vilje: det skal ikke
   tage plads fra varenavnet, kun sige at der er noget galt. Farven
   foelger stribens, saa de to siger det samme. */
.kline__maerke {
  flex: 0 0 auto;
  width: 14px;
  margin-left: 2px;
  text-align: center;
  font-size: 13px;
  font-weight: 800;
  line-height: 1;
  color: var(--yellow);
}
.kline__maerke--problem { color: var(--red); }

/* ============================================================
   VAREEDITOREN PAA EN IPAD — SAMME INDHOLD, FAERRE RAEKKER

   Skitsen (src/skitse/ipad.html, .ark) laegger navn, stand og
   pris paa EEN linje og lader knapperne staa nederst. Produktet
   brugte tre raekker paa det samme: en titellinje «Rediger:
   Kaffe», et hoved der gentog navnet, og en overskrift «Antal»
   over et trin, hvis tal allerede siger, hvad det er.

   Resultatet var, at «Besked til Bar» — det, man oftest er inde
   efter — laa under kanten paa en iPad i staaende format og
   kraevede et rul, man ikke kunne se var noedvendigt.

   Her hentes pladsen fire steder:
     · standen flytter op i hovedet i stedet for sin egen raekke
     · antal og genveje deler een raekke, uden overskrift
     · allergenerne foldes sammen (aabne af sig selv naar de er sat)
     · afsnittene faar mindre luft paa den kompakte flade

   Intet er fjernet. Alt kan naas.
   ============================================================ */

.ve__stand {
  align-self: center;
  font-size: 10.5px;
  font-weight: 800;
  letter-spacing: 1.2px;
  color: var(--tx-3, var(--tx-2));
  white-space: nowrap;
}

/* Antal: trin til venstre, genveje fylder resten af linjen */
.ve__afsnit--antal {
  display: flex;
  align-items: center;
  gap: 14px;
  flex-wrap: wrap;
}
.ve__afsnit--antal .ve__antal {
  flex: 0 0 auto;
  width: 260px;
  margin-bottom: 0;
}
.ve__afsnit--antal .ve__chips--antal {
  flex: 1 1 200px;
  justify-content: flex-end;
}

/* Folden: overskriften ER knappen, saa den ikke koster en raekke */
.ve__fold {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 0;
  background: none;
  border: 0;
  color: inherit;
  text-align: left;
  cursor: pointer;
  min-height: var(--touch-min, 44px);
}
.ve__fold .ve__titel { margin-bottom: 0; }
.ve__foldmrk {
  flex: 1 1 auto;
  font-size: 12.5px;
  font-weight: 700;
  color: var(--red);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.ve__foldpil { margin-left: auto; color: var(--tx-2); font-size: 13px; }
.ve__fold.er-aaben + .ve__chips,
.ve__fold.er-aaben ~ .ve__chips { margin-top: 10px; }

/* Den kompakte flade har mindst hoejde — der strammes een gang til */
:root[data-pos-flade="kompakt"] .ve__afsnit { padding: 10px 0; }
:root[data-pos-flade="kompakt"] .ve__hoved { padding-bottom: 9px; }
:root[data-pos-flade="kompakt"] .ve__antal__knap { height: 50px; width: 76px; }
:root[data-pos-flade="kompakt"] .ve__antal__tal { font-size: 28px; }
:root[data-pos-flade="kompakt"] .ve__navn { font-size: 18px; }
:root[data-pos-flade="kompakt"] .ve__total__tal { font-size: 19px; }

/* ============================================================
   VENT SOM EN LINJE I REGNINGEN

   Stregen skal kunne ses paa en armslaengdes afstand i et
   halvmoerkt lokale, uden at tage plads fra varerne. Derfor:
   een raekke paa 26px, orange maerke, stedets navn, og en linje
   der loeber ud til kanten.

   Varerne UNDER stregen faar deres eget maerke — se
   `.kline--venter`. Uden det ville en oel, der er tastet efter
   en «Vent koekken», se ud som om den ogsaa ventede.
   ============================================================ */
.kvent {
  display: flex;
  align-items: center;
  gap: 8px;
  min-height: 26px;
  padding: 0 4px;
  margin: 3px 0;
  user-select: none;
}
.kvent__mrk {
  font-size: 10px;
  font-weight: 900;
  letter-spacing: 1.6px;
  color: var(--accent);
  background: var(--accent-svag);
  border: 1px solid var(--accent);
  border-radius: 4px;
  padding: 2px 6px;
  line-height: 1;
}
.kvent__sted {
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 1.4px;
  color: var(--tx-2);
}
.kvent__streg {
  flex: 1 1 auto;
  height: 0;
  border-top: 1px dashed var(--accent);
  opacity: .55;
}

/* Varen bag stregen.

   Navnet er `--senere` og ikke `--venter`: huset har allerede
   `.kline--vent` for en linje, hvis bon ER sendt og staar som
   VENT hos koekkenet. Det her er det modsatte ende af rejsen —
   en vare, der endnu ikke er sendt, og som vil komme med en
   SENERE bon. To ting, der ligner hinanden i navnet, bliver
   rettet forkert en dag.

   Geometrien foelger `.kline::before` praecis, saa striben ikke
   hopper, naar en linje skifter side af stregen. */
.kline--senere::before {
  background: repeating-linear-gradient(
    to bottom,
    var(--orange) 0 5px,
    transparent 5px 10px);
}

/* Taelleren paa en gentaget besked — se `toast.js`. Den skal kunne
   ses, men ikke laese sig selv foerst: teksten er budskabet. */
.toast__antal {
  margin-left: 8px;
  padding: 1px 6px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  background: rgba(255, 255, 255, .16);
}

/* ============================================================
   REGNINGEN SKAL HVILE PAA EN HEL RAEKKE

   Baandet er snappet til hele varelinjer af layoutmotoren (se
   `skaermlayout.js`): fire linjer a 52 px med 6 px imellem er
   praecis 226 px, og kanten staar rent.

   VENT-raekken er 32 px og passer ikke ind i den rytme. Med en
   deling i regningen kunne den nederste linje derfor blive
   skaaret over paa midten.

   Motoren kan ikke bare faa baandet til at vokse: hoejden er sat
   for hele fladen, og et baand, der aendrede sig, mens tjeneren
   taster, ville faa varegitteret til at hoppe under fingeren.

   I stedet snapper RULNINGEN. Listen kan stadig staa med en
   halv linje nederst — det er dét, der fortaeller, at der er
   mere — men saa snart der rulles, lander den paa en hel raekke
   i stedet for et vilkaarligt sted midt i en vare.
   ============================================================ */
.kregning__liste {
  scroll-snap-type: y proximity;
  scroll-padding-top: 2px;
}
.kregning__liste > .kline,
.kregning__liste > .kvent {
  scroll-snap-align: start;
}

/* Den AABNE vent: trykket er sket, men der er ikke tastet noget
   endnu. Den staar nederst, hvor den naeste vare vil lande. */
.kvent--aaben { opacity: .78; }
.kvent__afventer {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: .4px;
  color: var(--tx-3, var(--tx-2));
  white-space: nowrap;
}

/* ============================================================
   ET VALGT MENUKORT

   `.kmfelt` var indtil nu kun en HANDLING: man trykkede, arket
   lukkede, og der skete noget. Naar de samme kort bruges til at
   VAELGE med — annulleringsaarsagen, og senere de andre dialoger
   med samme problem — skal det kunne ses, hvad man har valgt,
   mens dialogen staar aaben.

   Farven er husets accent, den samme som en aktiv genvej og en
   valgt chip. Der er ikke opfundet en ny.
   ============================================================ */
.kmfelt--valgt {
  border-color: var(--accent);
  background: var(--accent-svag);
}
.kmfelt--valgt .kmfelt__navn { color: var(--accent); }

/* Den aabne vent-streg er en KNAP: et tryk fortryder den. Den skal
   se ud som resten af stregerne, saa knapelementets egen bagrund
   og kant tages af. */
button.kvent {
  width: 100%;
  background: none;
  border: 0;
  color: inherit;
  font: inherit;
  cursor: pointer;
  text-align: left;
}
button.kvent:active { opacity: 1; }
.kvent__fortryd {
  font-size: 12px;
  font-weight: 800;
  color: var(--tx-3, var(--tx-2));
  padding: 0 2px;
}
button.kvent:active .kvent__fortryd,
button.kvent:hover .kvent__fortryd { color: var(--accent); }

/* ============================================================
   BORDETS FASE — HVAD DET VENTER PAA

   ------------------------------------------------------------
   FASE OG ALARM ER TO FORSKELLIGE SPOERGSMAAL

   `--haster-gul` og `--haster-roed` ovenfor siger, at der er gaaet
   FOR LANG TID. De bliver staaende praecis som de er, og de vinder
   altid: en ramme, der raaber, maa ikke kunne blive daempet af en
   fase, der siger «alt er normalt».

   Fasen siger noget andet: HVAD bordet venter paa. Et bord, der
   venter paa hovedretten, er ikke et problem — men naar man staar
   i doeren, vil man kunne se, at fem af dem goer det samtidig.

   Derfor er faserne en rolig tone i selve figuren, ikke en kant.
   Kanten er alarmens, og den er der kun, naar der ER noget galt.

   ------------------------------------------------------------
   ALDRIG KUN FARVE

   Samme regel som bookingmaerket: der staar altid et tegn ved
   siden af — F, H, D — saa en tjener, der ikke ser forskel paa
   toneerne, kan laese bordet alligevel.
   ============================================================ */

/* Gaesterne venter paa deres foerste mad. Den roligste af dem —
   det er den normale tilstand i en foerste halve time. */
.pv__bord--fase-venter-mad {
  background-image: linear-gradient(
    to bottom, color-mix(in srgb, var(--green) 10%, transparent), transparent 60%);
}

/* Koekkenet holder naeste ret tilbage. Lilla, samme farve som
   VENT-tilstanden har i regningen. */
.pv__bord--fase-venter-hovedret,
.pv__bord--fase-venter-dessert {
  background-image: linear-gradient(
    to bottom, color-mix(in srgb, var(--purple) 16%, transparent), transparent 60%);
}

/* Ingen har vaeret ved bordet. Ingen tone — her er det ALARMEN,
   der skal ses, og en tone ville kun tage opmaerksomhed fra den. */

/* Betalt og ikke ryddet: bordet kan saelges igen. Det er en
   mulighed, ikke et problem, saa den er lys og ikke roed. */
.pv__bord--fase-betalt {
  background-image: linear-gradient(
    to bottom, color-mix(in srgb, var(--tx-1) 12%, transparent), transparent 55%);
}

/* ------------------------------------------------------------
   KURSUSMAERKET: «2F · 3H»

   Farven kommer fra kontrastsystemet, ikke herfra. Bordpladen
   kan vaere hvilken som helst farve, huset har valgt, og
   `bordplan.js` har allerede regnet ud, hvad der kan laeses paa
   den — `--pv-tekst` og `--pv-plade`. Et maerke med sin egen
   faste farve ville vaere det ene sted i figuren, der ikke fulgte
   den regel, og saa er reglen ingen regel.
   ------------------------------------------------------------ */
.pv__kursus {
  font-size: 9.5px;
  font-weight: 900;
  letter-spacing: .4px;
  line-height: 1.15;
  color: var(--pv-tekst, var(--tx-1));
  opacity: .92;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 100%;
}

/* ============================================================
   EEN RING — BORDETS ENE OPERATIONELLE STATUS

   ------------------------------------------------------------
   HVORFOR DET HER ER EET STED

   Foer skrev fire klasser den samme `box-shadow`: usendte varer,
   afsendelsen, ventetiden og fasen. De kaempede om samme
   egenskab, og hvem der vandt, afhang af raekkefoelgen i denne
   fil — ikke af, hvad der var vigtigst for tjeneren.

   `V.bordstatus` afgoer det nu i domaenet, og der er praecis EEN
   klasse tilbage, der maa tegne ringen.

   ------------------------------------------------------------
   FARVEN ER HASTVAERK — IKKE KATEGORI

     graa      ledigt
     blaa      aktivt bord, kun drikkevarer
     groen     aktivt bord, alt normalt
     lilla     venter paa naeste serveringsrunde
     orange    usendte varer — nogen skal trykke Send
     gul       naermer sig en tidsgraense
     roed      HANDLING KRAEVES. Aldrig noget andet.
     daempet   betalt, skal ryddes

   ------------------------------------------------------------
   RINGEN OG KANTEN ER TO FORSKELLIGE SPROG

   Ringen (inset box-shadow) er DRIFTEN: hvad kraever handling.
   Kanten (border) er RESERVATIONEN: hvem der kommer hvornaar.

   De to kan sagtens vaere sande samtidig — et bord kan baade
   have en forsinket gaest og en overskredet hovedret — og derfor
   maa de ikke dele egenskab. Det er samme fejl som ovenfor, bare
   et niveau hoejere.

   ------------------------------------------------------------
   ALDRIG KUN FARVE

   Hver eneste af dem har et tegn eller et tal ved siden af i
   figuren: minuttallet, kursusmaerket, «N usendte», afsendelsens
   ikon. En tjener med farvesynsproblemer skal kunne laese bordet
   uden at se een eneste af farverne her.
   ============================================================ */

.pv__bord--st-normal  { box-shadow: inset 0 0 0 2px color-mix(in srgb, var(--green) 55%, transparent); }
.pv__bord--st-drikke  { box-shadow: inset 0 0 0 2px color-mix(in srgb, var(--blue) 60%, transparent); }
.pv__bord--st-vent    { box-shadow: inset 0 0 0 2px var(--purple); }
.pv__bord--st-usendt  { box-shadow: inset 0 0 0 2px var(--orange); }
.pv__bord--st-gul     { box-shadow: inset 0 0 0 3px var(--yellow); }
.pv__bord--st-roed    { box-shadow: inset 0 0 0 3px var(--red); }

/* Betalt: ingen ring, men en daempning. Bordet er faerdigt — det
   skal kunne SES, at der ikke er noget at goere, kun at rydde. */
.pv__bord--st-betalt {
  box-shadow: inset 0 0 0 2px color-mix(in srgb, var(--tx-2) 45%, transparent);
  opacity: .72;
}

/* Roed skal kunne ses paa tvaers af et lokale, ogsaa naar
   bordpladen selv er roed. Derfor faar den en ydre kant OGSAA —
   to ringe i hver sin retning kan ikke forsvinde i en flade. */
.pv__bord--st-roed {
  outline: 2px solid color-mix(in srgb, var(--red) 70%, transparent);
  outline-offset: -6px;
}

/* ============================================================
   STATUSBJAELKEN — DET, DER SKAL SES FRA DEN ANDEN SIDE AF RUMMET

   ------------------------------------------------------------
   RINGEN VAR IKKE NOK, OG DET BLEV MAALT

   Foerste udgave gav hver status en `inset box-shadow`. Paa
   skaermen forsvandt den: en to pixel tynd ring inde i en 60x60
   figur med en brun bordplade er ikke noget, man ser paa vej
   gennem et lokale. Bord 5 stod med otteogtredive minutter paa
   hovedretten og saa praecis ud som bord 1.

   Det er en fejl paa det vigtigste punkt af alle: farven skal
   kunne laeses paa et sekund.

   ------------------------------------------------------------
   HVORFOR EN BJAELKE OG IKKE EN FYLDFARVE

   Bordpladen har sin EGEN farve — huset farvekoder bordene, og
   den betydning maa ikke overskrives af driften. En status, der
   fyldte figuren, ville tage husets farve fra dem.

   Bjaelken loeser begge dele: den ligger langs overkanten i fuld
   bredde, den er stor nok til at ses, og den roerer ikke pladen.

   ------------------------------------------------------------
   DEN LIGGER PAA EN MOERK SOKKEL

   En gul bjaelke paa en gul bordplade er ingen bjaelke. Derfor
   har den en moerk baggrund under sig, saa den har sin egen
   kontrast uanset hvad pladen er malet med. Samme princip som
   kontrastpladen bag teksten — se `kontrast.js`.
   ============================================================ */
.pv__bord { position: relative; }

.pv__bord::after {
  content: "";
  position: absolute;
  left: 0; right: 0; top: 0;
  height: 5px;
  border-radius: inherit;
  border-bottom-left-radius: 0;
  border-bottom-right-radius: 0;
  background: transparent;
  pointer-events: none;
  z-index: 3;
}

/* Sokkel + farve. `--st-farve` saettes pr. status nedenfor. */
.pv__bord[class*="pv__bord--st-"]::after {
  background:
    linear-gradient(var(--st-farve, transparent), var(--st-farve, transparent)),
    linear-gradient(rgba(0,0,0,.55), rgba(0,0,0,.55));
}

.pv__bord--st-normal  { --st-farve: color-mix(in srgb, var(--green) 85%, transparent); }
.pv__bord--st-drikke  { --st-farve: var(--blue); }
.pv__bord--st-vent    { --st-farve: var(--purple); }
.pv__bord--st-usendt  { --st-farve: var(--orange); }
.pv__bord--st-gul     { --st-farve: var(--yellow); }
.pv__bord--st-roed    { --st-farve: var(--red); }
.pv__bord--st-betalt  { --st-farve: color-mix(in srgb, var(--tx-2) 70%, transparent); }
.pv__bord--st-ledig   { --st-farve: transparent; }

/* Roed er den eneste, der raaber: hoejere bjaelke og en puls.
   «Handling kraeves» skal kunne ses uden at lede. */
.pv__bord--st-roed::after {
  height: 7px;
  animation: stPuls 1.8s ease-in-out infinite;
}
@keyframes stPuls {
  0%, 100% { opacity: 1; }
  50%      { opacity: .45; }
}

/* Betalt skal ikke blinke og ikke raabe — den skal bare kunne
   ses som «faerdig». */
.pv__bord--st-betalt::after { height: 4px; }

/* ------------------------------------------------------------
   VENT-MAERKET LAA OVEN I TEKSTEN

   Maalt paa bord 5: `.pv__tekst` fyldte 5-56 px, og `.pv__vent`
   laa 47-58. De to stod oven i hinanden i hver sin farve.

   VENT er nu en STATUS med sin egen lilla bjaelke, saa ordet er
   ikke laengere den eneste baerer af betydningen. Det bliver
   staaende for den, der ikke ser farver — men flyttet ned i
   hjoernet, hvor det ikke roerer noget, og daempet, saa det ikke
   konkurrerer med beloebet.
   ------------------------------------------------------------ */
.pv__vent {
  bottom: 1px;
  left: 3px;
  font-size: 8px;
  letter-spacing: .3px;
  opacity: .85;
  pointer-events: none;
}

/* Teksten skal ikke ligge under bjaelken */
.pv__tekst { padding-top: 3px; }

/* ------------------------------------------------------------
   RUNDE BORDE FAAR EN RING, IKKE EN BJAELKE

   Maalt paa bordplanen: paa et rundt bord klippede `border-radius:
   50%` bjaelken til en tynd bue i toppen. Bord 1 stod med en
   groen splint paa fem pixels — mindre synlig end den ring, den
   skulle erstatte.

   Cirklen har sin egen naturlige form til det her: hele kanten.
   Den er stoerre end bjaelken og kan ses fra samme afstand.

   Sokkelen bliver: en gul ring paa en gul plade er ingen ring.
   ------------------------------------------------------------ */
/* ------------------------------------------------------------
   OG DET SKAL VAERE EN KANT — IKKE EN SKYGGE

   Foerste forsoeg brugte stablede `inset box-shadow`. Paa en 60
   px cirkel moedtes de i midten og FYLDTE hele bordet: nummer,
   kursus, tid og beloeb forsvandt bag farven. Maalt i browseren
   paa bord 1, 3 og 7 — praecis det, der aldrig maa ske.

   En `border` kan kun tegne randen. Den kan ikke komme til at
   daekke midten, uanset hvor tyk den bliver.
   ------------------------------------------------------------ */
/* SPECIFICITETEN SKAL MATCHE

   Sokkelreglen ovenfor er `.pv__bord[class*="pv__bord--st-"]::after`
   — en klasse OG en attributvaelger. `.pv__bord--rund::after` er
   kun en klasse og taber derfor, uanset at den staar senere i
   filen. Resultatet var, at den runde ring fik sin kant, men
   BEHOLDT den fyldte baggrund fra sokkelreglen — og cirklen blev
   maalet helt over.

   Maalt i browseren: bord 1, 3 og 7 stod som ensfarvede skiver,
   mens DOM'en paastod, at teksten var der. Den var der ogsaa —
   bag farven. */
.pv__bord--rund[class*="pv__bord--st-"]::after {
  left: 0; right: 0; top: 0; bottom: 0;
  height: auto;
  border-radius: 50%;
  background: none;
  box-sizing: border-box;
  /* Tre pixels, ikke fire. En 60 px cirkel har ikke mere at give:
     med fire klippede ringen beloebet nederst i figuren, maalt paa
     bord 1, 3 og 7. Ringen loeber hele vejen rundt og kan ses paa
     tre — bjaelken paa de firkantede maa gerne vaere tykkere,
     fordi den kun tager fra toppen. */
  border: 3px solid var(--st-farve, transparent);
  /* Sokkelen: en tynd moerk kontur uden om og inden for farven,
     saa ringen kan ses paa en plade i samme farve. */
  box-shadow:
    0 0 0 1px rgba(0, 0, 0, .5) inset,
    0 0 0 1px rgba(0, 0, 0, .5);
}
.pv__bord--rund.pv__bord--st-roed::after { border-width: 4px; }
.pv__bord--rund.pv__bord--st-ledig::after {
  border-color: transparent;
  box-shadow: none;
}
/* Og bjaelkens hoejde/puls maa heller ikke gaelde en cirkel. */
.pv__bord--rund.pv__bord--st-roed::after { height: auto; }

/* ------------------------------------------------------------
   KURSUSMAERKET PAA ET RUNDT BORD

   Det haenger paa cirklens nederste venstre kant — i det hjoerne,
   firkanten omkring cirklen efterlader tomt. Stolene sidder over
   og under, saa siderne er frie.

   Det har sin EGEN moerke sokkel, fordi det halvt ligger uden for
   bordpladen og halvt paa den: to forskellige baggrunde under det
   samme maerke. Uden sokkelen ville halvdelen af teksten kunne
   forsvinde i en lys bordplade.
   ------------------------------------------------------------ */
.pv__kursus--hjoerne {
  position: absolute;
  left: -3px;
  bottom: -3px;
  z-index: 4;
  padding: 1px 4px;
  border-radius: 999px;
  font-size: 8.5px;
  font-weight: 900;
  letter-spacing: .2px;
  line-height: 1.3;
  color: var(--tx-1);
  background: rgba(0, 0, 0, .72);
  box-shadow: 0 0 0 1px rgba(255, 255, 255, .16);
  white-space: nowrap;
  pointer-events: none;
}

/* ============================================================
   FARVEFORKLARINGEN

   Proeverne er de RIGTIGE statusklasser — `.pv__bord--st-*` — og
   ikke en raekke haandmalede firkanter. Aendrer nogen en farve i
   bordplanen, aendrer forklaringen sig med. To steder med hver
   sin roede er praecis den slags, der goer en forklaring
   farligere end ingen forklaring.
   ============================================================ */
.fp__forkl {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 7px 2px;
  border-bottom: 1px solid var(--line-1);
}
.fp__forkl:last-of-type { border-bottom: 0; }

/* Prøven tegnes som et lille bord — samme bjælke, samme sokkel. */
.fp__forkl__proeve {
  position: relative;
  flex: 0 0 auto;
  width: 46px;
  height: 30px;
  border-radius: 7px;
  background: var(--bg-3);
  border: 1px solid var(--line-2);
}
.fp__forkl__proeve::after {
  content: "";
  position: absolute;
  left: 0; right: 0; top: 0;
  height: 5px;
  border-top-left-radius: 6px;
  border-top-right-radius: 6px;
  background:
    linear-gradient(var(--st-farve, transparent), var(--st-farve, transparent)),
    linear-gradient(rgba(0,0,0,.55), rgba(0,0,0,.55));
}
.fp__forkl__hvad { font-weight: 700; font-size: 14px; }
.fp__forkl__naar { font-size: 12.5px; color: var(--tx-2); line-height: 1.35; }
.fp__forkl__tid {
  display: flex; flex-direction: column; gap: 4px;
  font-size: 13px; color: var(--tx-2); line-height: 1.4;
}
.fp__farveknap { flex: 0 0 auto; }

/* Runde borde: taettere linjer, saa baade tid og beloeb kan vaere
   der. Se linjebudgettet i `planvisning.js` — de to skal stemme,
   ellers regner budgettet paa noget andet, end skaermen tegner. */
.pv__bord--rund .pv__tekst { line-height: 1.0; }
.pv__bord--rund .pv__tid,
.pv__bord--rund .pv__belob { font-size: 9.5px; line-height: 10px; }

/* ============================================================
   DE SMAA TEGN

   Erstatter de gamle tekstlinjer «2 usendte» og «? Afsendelse
   ukendt», som tog to af de fire linjer, en firkant har.

   De ligger i underkanten, uden for linjebudgettet, og de har
   deres egen moerke sokkel: de skal kunne ses paa en hvilken som
   helst bordplade, og de skal IKKE laane bordets tekstfarve —
   deres betydning er alarm, ikke oplysning.
   ============================================================ */
.pv__tegn {
  position: absolute;
  right: 2px;
  bottom: 1px;
  display: flex;
  gap: 2px;
  z-index: 4;
  pointer-events: none;
}
.pv__tegn__et {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 11px;
  height: 11px;
  padding: 0 1px;
  border-radius: 999px;
  font-size: 8px;
  font-weight: 900;
  line-height: 1;
  background: rgba(0, 0, 0, .72);
  box-shadow: 0 0 0 1px rgba(255, 255, 255, .18);
}
.pv__tegn__et--usendt     { color: var(--orange); }
.pv__tegn__et--uafklaret  { color: var(--yellow); }
.pv__tegn__et--fejl       { color: var(--red); }

/* De gamle tekstlinjer tegnes ikke mere — reglerne bliver staaende,
   fordi andre skaerme (listen, haandholdt) stadig bruger dem. */

/* ============================================================
   RESTAURANT RADAR

   Staar over planen og svarer paa det, man staar med i doeren:
   hvordan staar det til lige nu. Tallene er knapper — et tryk
   fremhaever de borde, der taeller med.

   Farven paa hvert felt er den SAMME som bordets statusfarve, saa
   der ikke skal laeres to farvesprog. Ordet staar ved siden af
   tallet: farven er et supplement, aldrig den eneste vej ind.
   ============================================================ */
/* Radaren staar INDE i baandet nu — se `oversigtsbaand`. Derfor
   ingen egen polstring og ingen ombrydning: den skal kunne ligge
   paa linje med tallene uden at gøre raekken hoejere. */
.floor__radar {
  display: flex;
  gap: 6px;
  align-items: center;
  flex: 0 1 auto;
  min-width: 0;
  overflow-x: auto;
  scrollbar-width: none;
}
.floor__radar::-webkit-scrollbar { display: none; }
.radar__felt {
  display: inline-flex;
  align-items: baseline;
  gap: 5px;
  padding: 4px 9px;
  flex: 0 0 auto;
  min-height: var(--touch-min, 34px);
  border-radius: 999px;
  border: 1px solid var(--line-2);
  background: var(--bg-2);
  color: var(--tx-2);
  cursor: pointer;
  font-size: 10px;
  font-weight: 800;
  letter-spacing: .8px;
}
.radar__tal {
  font-size: 14px;
  font-weight: 900;
  color: var(--tx-1);
  font-variant-numeric: tabular-nums;
}
.radar__felt:active { transform: translateY(1px); }

/* Den valgte faar sin gruppes farve — samme farve som bordene. */
.radar__felt.er-valgt { color: var(--tx-1); }
.radar__felt--normale.er-valgt { border-color: var(--green);  box-shadow: inset 0 0 0 1px var(--green); }
.radar__felt--usendt.er-valgt  { border-color: var(--orange); box-shadow: inset 0 0 0 1px var(--orange); }
.radar__felt--gul.er-valgt     { border-color: var(--yellow); box-shadow: inset 0 0 0 1px var(--yellow); }
.radar__felt--roed.er-valgt    { border-color: var(--red);    box-shadow: inset 0 0 0 1px var(--red); }
.radar__felt--vent.er-valgt    { border-color: var(--purple); box-shadow: inset 0 0 0 1px var(--purple); }
.radar__felt--betalt.er-valgt  { border-color: var(--tx-2);   box-shadow: inset 0 0 0 1px var(--tx-2); }

/* Et prikkemaerke i gruppens farve, saa feltet kan laeses uden at
   vaere valgt — og uden at vaere afhaengig af farven alene. */
.radar__felt::before {
  content: "";
  width: 8px; height: 8px;
  border-radius: 50%;
  background: var(--line-2);
  align-self: center;
}
.radar__felt--normale::before { background: var(--green); }
.radar__felt--usendt::before  { background: var(--orange); }
.radar__felt--gul::before     { background: var(--yellow); }
.radar__felt--roed::before    { background: var(--red); }
.radar__felt--vent::before    { background: var(--purple); }
.radar__felt--betalt::before  { background: var(--tx-2); }

/* ------------------------------------------------------------
   FREMHAEVNING — DE ANDRE DAEMPES, DE FORSVINDER IKKE

   Et filter, der fjerner borde fra en plan over et lokale, laver
   et lokale, der ikke findes. Tjeneren skal stadig kunne se, at
   der ER et bord dér — det er bare ikke dét, hun leder efter.
   ------------------------------------------------------------ */
.pv__bord--nedtonet { opacity: .28; filter: saturate(.4); }

/* ============================================================
   SIDEPANELET MAA IKKE KUNNE SKUBBE «AABN BORD» UD

   Maalt paa iPad staaende, 1024x1366: tastaturets nederste
   raekke — «,» og ÅBN BORD — laa halvt uden for skaermen, fordi
   «Senest aabnede» voksede med fem knapper under den.

   `overflow-y: auto` ovenfor loeste det ikke: det gav bare en
   rulning i et panel, man ikke skal rulle i. Dennis: «det skal
   vaere der uden man skal bladre paa siden.»

   Derfor: tastaturet og BARSALG er FASTE og kan ikke krympe.
   «Senest aabnede» faar den plads, der bliver til overs — og
   klippes, naar der ikke er nogen. Den er den eneste her, der
   taaler at forsvinde: bordene staar paa planen ved siden af.
   ============================================================ */
/* Panelet er en flexsoejle, og kortet skal FYLDE den. Uden det
   blev kortet kun saa hoejt som sit indhold — der var ingen
   ledig plads at give tastaturet, uanset hvor meget panelet
   havde. Maalt: kort 434, panel 460. */
.floor__side {
  display: flex;
  flex-direction: column;
}
.floor__side > .card {
  display: flex;
  flex-direction: column;
  min-height: 0;
  flex: 1 1 auto;
}
.floor__side .keypad,
.floor__side .floor__barsalg {
  flex: 0 0 auto;
}
.floor__senest {
  flex: 0 1 auto;
  min-height: 0;
  overflow: hidden;
}

/* ------------------------------------------------------------
   ET BETALT BORD, DER IKKE BLIVER RYDDET

   Statussen bliver ved med at vaere «betalt» — radaren og
   forklaringen skal stadig sige, hvad bordet ER. Det er
   NIVEAUET, der stiger, og farven laeser niveauet.

   Efter ti minutter er gaesterne normalt gaaet, og bordet er en
   plads, huset ikke kan saelge. Efter tyve er det ikke laengere
   en paamindelse.
   ------------------------------------------------------------ */
.pv__bord--st-betalt.pv__bord--haster-gul  { --st-farve: var(--yellow); }
.pv__bord--st-betalt.pv__bord--haster-roed { --st-farve: var(--red); }
.pv__bord--st-betalt.pv__bord--haster-gul::after,
.pv__bord--st-betalt.pv__bord--haster-roed::after { height: 5px; }
.pv__bord--st-betalt.pv__bord--haster-gul,
.pv__bord--st-betalt.pv__bord--haster-roed { opacity: 1; }

/* Radarens filter: gruppen SKJULES — bord og stole sammen.
   Se `planvisning.js` for hvorfor det er skjul og ikke daempning:
   filteret nulstilles af sig selv efter tredive sekunder. */
.pv__gruppe--skjult { visibility: hidden; }

/* ------------------------------------------------------------
   ET BORD, DER ER SKUBBET HEN TIL ET ANDET

   Dennis, 9. september 2026: bordene skal saettes sammen «rent
   visuelt», og bordet lander dér, hvor det slippes.

   Overgangen er der, saa flytningen kan SES: uden den hopper
   bordet, og saa er det ikke til at se, hvad der skete. 160 ms
   er kort nok til ikke at staa i vejen for naeste tryk.

   Se `visits.saetMidlertidigPlads` — placeringen ligger paa
   BESOEGET og forsvinder, naar regningen lukkes. Husets egen
   bordplan roeres aldrig.
   ------------------------------------------------------------ */
.pv__gruppe--skubbet {
  transition: left 160ms ease-out, top 160ms ease-out;
}

/* ------------------------------------------------------------
   TASTATURET SKAL KUNNE VAERE DER — OGSAA I 408 PIXELS

   `@container`-reglerne ovenfor maaler HELE fladen. Sidepanelet
   er noget andet: naar omraadefanerne, baandet og radaren har
   taget deres, er der 408 px tilbage paa en iPad i staaende
   format. Maalt — og dér laa «,», ÅBN BORD og BARSALG under
   kanten.

   Panelet ruller ikke laengere. I stedet faar tasterne lov at
   krympe, med en bund paa 40 px, som stadig er over husets
   `--touch-min`. En tast, man kan ramme, er vigtigere end en
   tast, der er stor.
   ------------------------------------------------------------ */
/* SIDSTE UDVEJ, IKKE FOERSTE. Stod paa `hidden`, og saa blev det,
   der ikke kunne vaere der, klippet vaek i stilhed. `auto` ruller
   kun, naar kortet faktisk er hoejere end panelet — altsaa i den
   ene tilstand, hvor der ikke er plads at finde. */
.floor__side { overflow-y: auto; overflow-x: hidden; }
.floor__side > .card { gap: 8px; }
.floor__side .keypad { min-height: 0; }
.floor__side .keypad__grid { min-height: 0; }
/* `flex: 1 1 0` fik tasterne til at VOKSE og fylde panelet — og
   saa laa BARSALG under kanten igen. De maa krympe, ikke vokse. */
/* ------------------------------------------------------------
   TASTERNE FIK PLADSEN TILBAGE

   Foerst skrumpede de til 38 px for at faa BARSALG med. Siden er
   der kommet plads: radaren flyttede op paa baandet (54 px),
   overskriften «Åbn bord direkte» forsvandt (24 px), og
   forklaringen under BARSALG er flyttet ind i knappens `title`
   (34 px).

   Dennis, 1. september 2026: «kan vi saa ikke lave tallene lidt
   hoejre igen? saa det nu passer med hele siden?»

   52 px er over husets `--touch-min` med god margen og passer
   til en finger paa en iPad. `flex: 0 1 auto` staar fast: de maa
   krympe, hvis en lavere skaerm kraever det — men de maa aldrig
   VOKSE og skubbe BARSALG ud igen. Det var fejlen foerste gang.
   ------------------------------------------------------------ */
/* MAALT, IKKE GAETTET

   Med 52 px taster og 7 px mellemrum var kortets indhold 475 px i
   et kort paa 446 — 29 px for meget, og BARSALG laa under kanten
   igen. De 29 er fordelt, saa tasterne beholder naesten hele
   deres hoejde:

     taster       52 -> 50   (5 raekker = 10 px)
     displayet    52 -> 48   (4 px)
     mellemrum     7 ->  6   (6 mellemrum = 6 px)
     BARSALG      56 -> 52   (4 px)
     bundpolstring 16 -> 10  (6 px)

   50 px er stadig langt over husets `--touch-min` paa 34 og over
   de 38, tasterne var skrumpet til. */
/* ------------------------------------------------------------
   TASTERNE FINDER SELV DERES HOEJDE

   Haandjusteringen ramte 11 px ved siden af paa netop denne
   skaerm — og ville ramme et andet sted paa den naeste. En fast
   hoejde er et gaet om en skaerm, man ikke kender.

   `height` er OENSKET, `min-height` er GULVET. Browseren giver
   dem 50 px, naar der er plads, og krymper mod 40, naar der ikke
   er. Under 40 gaar den ikke — dér begynder tasten at vaere svaer
   at ramme, og saa er det noget andet, der skal vige.

   `flex-shrink: 1` er hele pointen. `flex-grow` staar paa 0: de
   maa krympe, aldrig vokse. Det var fejlen foerste gang, hvor de
   fyldte panelet og skubbede BARSALG ud.
   ------------------------------------------------------------ */
/* ------------------------------------------------------------
   DET ER GRIDDET, DER SKAL KRYMPE — IKKE TASTEN

   `.keypad__grid` er et GRID, ikke en flexboks. Alle mine
   `flex`-regler paa `.key` gjorde derfor ingenting, og jeg
   barberede i blinde paa `min-height` i stedet: 38, 52, 50 — og
   ramte 11 px ved siden af hver gang.

   Raekkerne er dét, der har hoejden. `grid-auto-rows:
   minmax(40px, 1fr)` lader dem dele den plads, der er, med et
   gulv paa 40 px — over husets `--touch-min` paa 34. Saa finder
   tastaturet selv sin hoejde paa enhver skaerm i stedet for at
   passe til den ene, jeg maalte paa.
   ------------------------------------------------------------ */
/* Tastaturet skal baade kunne vokse og krympe: det er dét, der
   faar tasterne op paa den hoejde, pladsen tillader. BARSALG
   staar med `0 0 auto` og kan ikke skubbes uanset hvad. */
.floor__side .keypad { min-height: 0; flex: 1 1 auto; }
/* `flex: 1 1 auto` og ikke `0 1 auto`: griddet skal ogsaa FYLDE
   den plads, der er til overs, saa raekkerne bliver saa hoeje,
   pladsen tillader. Med `0 1 auto` krympede de til gulvet paa 40,
   selv om der var plads til mere.

   Det er stadig BARSALG, der bestemmer: den staar med
   `flex: 0 0 auto` og kan ikke skubbes. Griddet faar resten. */
/* ------------------------------------------------------------
   «ÅBN BORD» LAA HEN OVER 0 OG TILBAGE-TASTEN

   MAALT 8. september 2026 i en rigtig browser paa LAN'et,
   1568 x 563 og 1440 x 689:

     gitterets bund      462 px
     fjerde raekkes bund 488 px      <- 26 px UDENFOR
     ÅBN BORD            478-536 px

   «ÅBN BORD» daekkede dermed de nederste 20 px af BAADE «0» og
   «←». Et tryk i bunden af nullet aabnede et bord i stedet for
   at taste cifret — og hvert bordnummer, der ender paa 0, gaar
   den vej.

   Udloeseren er advarselsbanneret. Uden det er overloebet 0;
   med det tager banneret 34 px fra panelet, og saa er der 152
   px til et gitter, hvis fire raekker kraever 178 (4 x 40 + 3 x 6).
   Fejlen viste sig altsaa praecis naar kassen havde noget at
   advare om — «huset er aabent, men denne kasse har ikke taget
   sin skuffe i brug».

   `min-height: 0` var det, der tillod det: flexboksen maatte
   krympe gitterets KASSE under det, raekkerne selv fylder, og
   `overflow: visible` lod dem flyde ud forneden.

   Raekkegulvet kan ikke saenkes for at skaffe pladsen — 40 px
   ligger allerede under husets `--touch-min` paa 44. (Kommentaren
   ovenfor sagde 34; det tal er forældet.)

   Tre ting i stedet, i den raekkefoelge noget skal give:
     1. gitteret maa ALDRIG krympe under sine egne raekker
     2. displayet giver sine 8 px foerst (48 -> 40)
     3. kan panelet stadig ikke rumme kortet, RULLES der

   Det sidste er en aendring af en beslutning: panelet holdt op
   med at rulle, da der var plads at finde et andet sted. Her er
   der ikke, og en knap, man kan rulle til, er bedre end en knap,
   der ligger under en anden.
   ------------------------------------------------------------ */
.floor__side .keypad__grid {
  min-height: min-content;
  flex: 1 1 auto;
  grid-auto-rows: minmax(40px, 1fr);
}
.floor__side .keypad__grid .key {
  min-height: 0;
  height: auto;
  font-size: 22px;
}
.floor__side .keypad__display {
  height: 48px;
  min-height: 40px;
  /* `0 1 auto` og ikke `0 0 auto`: displayet giver sine 8 px, foer
     noget andet i panelet skal vige. Det er det billigste sted at
     tage dem — et tal, der staar 8 px lavere, kan stadig laeses. */
  flex: 0 1 auto;
  font-size: 26px;
}
.floor__side .keypad { gap: 6px; }
.floor__side .keypad__grid { gap: 6px; }
.floor__side .btn--lg { min-height: 52px; font-size: 16px; }
.floor__side > .card { padding-bottom: 10px; }

/* BARSALG er den eneste knap her, der aabner et salg uden bord.
   Den maa aldrig kunne skubbes ud — derfor `flex: 0 0 auto`.

   MEN IKKE `margin-top: auto`. Den stod her for at skubbe
   knappen ned i bunden, og saa opsugede den ALT det ledige rum:
   tastaturet blev staaende paa sit gulv paa 40 px, mens der var
   plads til 56. Maalt — og det var derfor, tasterne ikke ville
   vokse, uanset hvad jeg gjorde ved dem.

   Nu tager griddet pladsen, og BARSALG foelger med nedad. */
.floor__side .floor__barsalg {
  flex: 0 0 auto;
  padding-top: 8px;
}

/* Luften over «Åbn bord direkte» — panelet starter hoejere nu,
   hvor listen under det er væk. */
.floor__side { padding-top: 4px; }
.floor__side > .card { padding-top: 10px; }

/* ============================================================
   BORDLOGGEN

   Tre spalter: hvornaar, hvad, hvem. Tiden staar til venstre,
   fordi loggen laeses lodret ned ad tidslinjen — oejet foelger
   klokkeslættene og stopper der, hvor det leder.
   ============================================================ */
.blog__raekke {
  display: grid;
  grid-template-columns: 78px 1fr auto;
  gap: 12px;
  align-items: baseline;
  padding: 7px 2px;
  border-bottom: 1px solid var(--line-1);
}
.blog__raekke:last-child { border-bottom: 0; }
.blog__klokke {
  font-size: 13.5px; font-weight: 800;
  font-variant-numeric: tabular-nums;
}
.blog__siden { font-size: 11px; color: var(--tx-3, var(--tx-2)); }
.blog__handling { font-size: 14px; font-weight: 700; line-height: 1.25; }
.blog__detalje {
  font-size: 12.5px; color: var(--tx-2); line-height: 1.35;
  overflow-wrap: anywhere;
}
.blog__hvem {
  font-size: 12px; font-weight: 700; color: var(--tx-2);
  white-space: nowrap;
}

/* En haendelse uden dansk navn vises med sit tekniske. Den er
   daempet, saa den kan ses som «endnu ikke doebt» og ikke som en
   fejl — men den er der, for «ALT» betyder alt. */
.blog__raekke--ukendt .blog__handling {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 12px;
  font-weight: 600;
  color: var(--tx-2);
}

.blog__antal {
  margin-left: 7px;
  padding: 1px 6px;
  border-radius: 999px;
  font-size: 10.5px;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  background: var(--bg-3);
  color: var(--tx-2);
}

.blog__top { display: flex; align-items: center; gap: 10px; }

/* Springet siden forrige linje. Det er tallet, man leder efter,
   naar man vil vide, om koekkenet var langsomt — derfor
   fremhaevet frem for «siden nu». */
.blog__spring {
  font-size: 11px;
  font-weight: 800;
  color: var(--orange);
  font-variant-numeric: tabular-nums;
}

/* Maskinens egen bogfoering, naar «Vis alt» er slaaet til. Den
   er daempet, saa menneskets handlinger stadig baerer historien. */
.blog__raekke--maskine .blog__handling,
.blog__raekke--maskine .blog__hvem { color: var(--tx-3, var(--tx-2)); font-weight: 600; }
.blog__raekke--maskine .blog__klokke { opacity: .7; }

/* ============================================================
   STOLESTRIBEN I REGNINGENS HOVED

   Smaa runde felter ved siden af bordnummeret: BORD, 1, 2, 3, +.
   Den aktive er altid fremhaevet — ogsaa «BORD» — fordi et valg,
   man ikke kan se, er en faelde. Se `stolestribe` i
   `posKompakt.js`.

   Tallene alene, ikke «Stol 1»: raekken skal kunne rumme otte
   stole paa en iPad uden at tage plads fra regningen. Ordet
   staar i `title` og i vareeditoren, hvor der er plads.
   ============================================================ */
.kstole {
  display: flex;
  align-items: center;
  gap: 4px;
  /* Den staar i regningens hoved mellem bordnummeret og beloebet.
     `margin-left: auto` skubbede den helt om til hoejre og lagde
     sig oven i prisen. Nu tager den pladsen i midten — og giver
     sig foerst, naar der ikke er mere. */
  flex: 1 1 auto;
  min-width: 0;
  justify-content: center;
  overflow-x: auto;
  scrollbar-width: none;
}
.kstole::-webkit-scrollbar { display: none; }

.kstol {
  flex: 0 0 auto;
  min-width: 26px;
  height: 24px;
  padding: 0 7px;
  border-radius: 999px;
  border: 1px solid var(--line-2);
  background: var(--bg-2);
  color: var(--tx-2);
  font-size: 11px;
  font-weight: 800;
  letter-spacing: .3px;
  cursor: pointer;
  line-height: 1;
}
.kstol:active { transform: translateY(1px); }
.kstol.er-valgt {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--accent-tx);
}
/* Stiplet, saa den ses som en TILFOEJELSE og ikke som en stol,
   der allerede staar der — samme sprog som i vareeditoren. */
.kstol--tilfoej {
  border-style: dashed;
  color: var(--accent);
  border-color: var(--accent);
  background: transparent;
}

/* En stol, hvor kun NOGLE af varerne er valgt. Den maa ikke se
   ud som «valgt» — saa ville knappen paastaa noget, der ikke er
   sandt — og heller ikke som «ikke valgt». Stiplet kant siger
   «delvist» uden at laane en af de to tilstande. */
.pay__stol--delvist {
  border-style: dashed !important;
  border-color: var(--accent) !important;
  color: var(--accent);
}

/* «Uden stol» er ikke en fejl — det er varer, der hoerer til
   bordet. Men de skal kunne ses som noget andet end en gaests. */
.pay__fri { color: var(--at-late, var(--yellow)); }

/* ============================================================
   BETALINGSSKAERMEN — TO RUDER OG EN BJAELKE

   Foer fyldte de fem betalingsknapper hele hoejre side for at
   staa klar til et tryk, der sker EEN gang. Nu staar de i en
   raekke nederst, og pladsen bruges paa det, man har brug for at
   se hele tiden: hvad er valgt, og hvad betaler jeg lige nu.
   ============================================================ */
.ordmain--to {
  display: flex;
  min-height: 0;
}
.ordmain--to .pay__venstre { flex: 1 1 58%; min-width: 0; }

.pay__hoejre {
  flex: 1 1 42%;
  min-width: 0;
  min-height: 0;
  border-left: 1px solid var(--line-1);
  background: var(--bg-1);
}
.pay__hoejre__hoved {
  display: flex;
  align-items: baseline;
  gap: 10px;
  padding: 10px 12px 8px;
  border-bottom: 1px solid var(--line-1);
}
.pay__hoejre__sum {
  margin-left: auto;
  font-size: 20px;
  font-weight: 900;
  font-variant-numeric: tabular-nums;
  color: var(--green);
}

/* En valgt vare er en KNAP: et tryk tager den af igen. Samme
   bevaegelse som at laegge den til, bare den anden vej. */
.pay__valgt {
  width: 100%;
  text-align: left;
  cursor: pointer;
  align-items: center;
}
.pay__valgt__af {
  flex: 0 0 auto;
  font-size: 15px;
  font-weight: 900;
  color: var(--tx-3, var(--tx-2));
  padding: 0 4px;
}
.pay__valgt:active .pay__valgt__af { color: var(--red); }

.pay__tom {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 20px;
}
.pay__ryd { margin: 0 10px 10px; }

/* ------------------------------------------------------------
   BJAELKEN MED BETALINGSMETODERNE

   Een raekke lige over de fire doere. Knapperne er lige brede —
   der er ingen af dem, der er «den rigtige», og en, der fylder
   mere, ville pege paa sig selv.
   ------------------------------------------------------------ */
.paybund {
  border-top: 1px solid var(--line-1);
  background: var(--bg-1);
}
.paybund .paypanel {
  border-top: 0 !important;
  padding: 8px 12px !important;
}
.paybund .paymetoder {
  display: grid !important;
  grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)) !important;
  gap: 8px !important;
}
/* Mindre knapper i bjaelken end i den gamle soejle. De skal kunne
   rammes — 44 px er over husets `--touch-min` — men de skal ikke
   tage plads fra ruderne, hvor man rent faktisk arbejder. */
.paybund .paymetoder .btn { min-height: 44px; font-size: 14px; }
.paybund .paypanel { padding: 6px 12px !important; gap: 6px !important; }

/* ============================================================
   STOLEBRIKKERNE PAA BETALINGSSKAERMEN

   Samme slags valg som `.kstol` paa bestillingsfladen, og derfor
   samme form. De fyldte 120x68 hver — med otte gaester tog de
   hele oeverste halvdel af skaermen.

   Flere kan vaere valgt samtidig: man kan betale for to ud af
   tre stole. Brikkerne udelukker ikke hinanden.
   ============================================================ */
.paystole {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}
.paystol {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1px;
  min-width: 54px;
  min-height: var(--touch-min, 44px);
  padding: 5px 9px;
  border-radius: 14px;
  border: 1px solid var(--line-2);
  background: var(--bg-2);
  color: var(--tx-1);
  cursor: pointer;
  line-height: 1;
}
/* BORD-brikken baerer et ORD, ikke et ciffer. 16 px fed skrift
   paa fire bogstaver ville sprænge brikkens 54 px, saa ordet
   saettes mindre og faar sin egen mindstebredde. Den staar
   foerst i raekken og skal kunne kendes fra stolene uden at
   raabe. */
.paystol--bord { min-width: 66px; }
.paystol--bord .paystol__nr { font-size: 12px; letter-spacing: .04em; }
.paystol__nr { font-size: 16px; font-weight: 900; }
.paystol__kr {
  font-size: 10.5px; font-weight: 700; opacity: .75;
  font-variant-numeric: tabular-nums;
}
.paystol:active { transform: translateY(1px); }

.paystol.er-valgt {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--accent-tx);
}

/* Delvist valgt: hverken det ene eller det andet. Stiplet, saa
   brikken ikke paastaar «valgt» om noget, der ikke er det. */
.paystol.er-delvist {
  border-style: dashed;
  border-color: var(--accent);
  color: var(--accent);
}

.paystol.er-betalt { opacity: .45; cursor: default; }

/* ============================================================
   VARERAEKKERNE PAA BETALINGSSKAERMEN — EEN LINJE

   «produkterne skal samles til en linje, PRODUKTNAVN - Stk pris
   og saa lavere knapper saa linjerne kun er halv hoejde ca..
   men ikke for smaat.»

   36 px i stedet for godt 70. Det er stadig over husets
   `--touch-min` paa 34, saa raekken kan rammes med en finger —
   og det er den, der afgoer bunden. «Ikke for smaat» er ikke en
   smagssag: en raekke, man rammer ved siden af, flytter den
   forkerte vare over paa regningen.
   ============================================================ */
.pay__raekke {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  min-height: 36px;
  padding: 4px 8px;
  text-align: left;
  cursor: pointer;
  touch-action: pan-y;
}
.pay__antal {
  flex: 0 0 auto;
  min-width: 26px;
  font-size: 13px;
  font-weight: 900;
  font-variant-numeric: tabular-nums;
  color: var(--tx-2);
}
.pay__navn {
  flex: 1 1 auto;
  min-width: 0;
  font-size: 14px;
  font-weight: 700;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* Beloebet viger ALDRIG. Navnet klippes; tallet gør ikke. */
.pay__kr {
  flex: 0 0 auto;
  font-size: 13.5px;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
}
.pay__pil {
  flex: 0 0 auto;
  font-size: 15px;
  font-weight: 900;
  color: var(--tx-3, var(--tx-2));
  padding: 0 2px;
}
.pay__pil--venstre { order: -1; }

/* ------------------------------------------------------------
   TRAEKKET

   Spoegelset foelger fingeren, og maalruden lyser op. Uden det
   ville man traekke i blinde og ikke vide, om det landede.
   ------------------------------------------------------------ */
.pay__raekke--traekkes { opacity: .3; }
.pay__spoegelse {
  position: fixed;
  z-index: 9999;
  pointer-events: none;
  width: 220px;
  opacity: .95;
  box-shadow: 0 10px 26px rgba(0, 0, 0, .55);
  border-radius: 8px;
  background: var(--bg-3);
}
.pay__maal--klar {
  box-shadow: inset 0 0 0 2px var(--accent);
  background: color-mix(in srgb, var(--accent) 7%, transparent);
}

/* ============================================================
   BORDPLANENS BJAELKE — SMAL OG LAV FLADE

   Een raekke i stedet for en spalte. Se `skaermlayout
   .bordplanPanel` for hvorfor formen skifter i stedet for
   stoerrelsen: taltastaturet kunne ikke komme under sine egne
   40 px pr. raekke og floed ud af sit panel, saa ÅBN BORD blev
   tegnet oven paa 7-8-9.

   Hoejden er husets fingermaal plus luft — bjaelken er det
   eneste, der staar mellem bordplanen og bundmenuen, og den maa
   ikke tage mere end den ene raekke.
   ============================================================ */
.floor__bjaelke {
  flex: 0 0 auto;
  display: flex;
  gap: 8px;
  padding: 8px 10px;
  border-top: 1px solid var(--line-1);
  background: var(--bg-1);
}
.floor__bjaelke__felt {
  flex: 1 1 auto;
  min-width: 0;
  min-height: var(--touch-min);
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 0 14px;
  border: 1px solid var(--line-2);
  border-radius: 10px;
  background: var(--bg-2);
  color: var(--tx-2);
  font-size: 16px;
  font-weight: 700;
  cursor: pointer;
}
.floor__bjaelke__felt:active { background: var(--bg-3); }
.floor__bjaelke__ik {
  font-size: 17px;
  font-weight: 900;
  color: var(--orange);
}
/* BARSALG maa aldrig skubbes ud af raekken — den er den eneste
   vej til et salg uden bord. Derfor fast bredde og `flex: 0 0`. */
.floor__bjaelke__bar {
  flex: 0 0 auto;
  min-height: var(--touch-min);
  padding: 0 18px;
  font-weight: 800;
  letter-spacing: .04em;
}

/* ============================================================
   OVERSIGTSBAANDET PAA EN SMAL FLADE

   Baandet er een raekke paa en iPad: tre tal, radaren, og de to
   smaa knapper. Maalt 1. september 2026 paa 390 x 844 flød den
   56 px ud af rammen — «Vis som liste» laa uden for skaermen, og
   radarens roede felt laa oven paa begge knapper.

   Den nemme rettelse var at lade den rulle vandret. Den er
   forkert her: tallene er det, man kigger paa i doeren, og et
   tal, man skal rulle hen til, er et tal, ingen ser.

   Derfor bryder baandet i TO raekker paa en smal flade. Oeverst
   det, der er faa og faste — tallene og de to knapper. Nederst
   radaren, som er en liste af vekslende laengde og derfor den
   ene ting her, der GERNE maa rulle.
   ============================================================ */
:root[data-pos-bredde="smal"] .floor__baand,
:root[data-pos-bredde="mellem"] .floor__baand {
  flex-wrap: wrap;
  gap: 8px 16px;
  padding: 6px 10px;
}
/* Afstandsstykket skubber knapperne ud i hoejre side paa en bred
   flade. Naar der brydes, ville det tvinge et raekkeskift midt i
   tallene. */
:root[data-pos-bredde="smal"] .floor__baand .topbar__spacer,
:root[data-pos-bredde="mellem"] .floor__baand .topbar__spacer { display: none; }

:root[data-pos-bredde="smal"] .floor__radar,
:root[data-pos-bredde="mellem"] .floor__radar {
  order: 9;                 /* efter tallene OG efter knapperne */
  flex: 1 0 100%;
  padding-bottom: 2px;
}
/* Knapperne bliver i foerste raekke og skubbes ud til hoejre. */
.floor__baand__knapper { display: flex; gap: 8px; align-items: center; flex: 0 0 auto; }
:root[data-pos-bredde="smal"] .floor__baand__knapper,
:root[data-pos-bredde="mellem"] .floor__baand__knapper { margin-left: auto; }

/* Tallene maa gerne staa taettere, naar der er to raekker. */
:root[data-pos-bredde="smal"] .floor__tal__vaerdi { font-size: 16px; }
:root[data-pos-bredde="smal"] .floor__tal__navn { font-size: 10px; }

/* ============================================================
   LISTEKORTET FOELGER PLANENS FARVER

   Paa en telefon ER listen bordplanen — planen selv er for stor
   til fladen, se `floorplan.valgtVisning`. Saa maa kortet ikke
   have sit eget farvesprog: den, der laerer at roed betyder
   «handling kraeves» paa en iPad, skal kunne det samme paa en
   telefon.

   Farverne er derfor DE SAMME tokens som `.pv__bord--st-*`, og
   den roede har den samme puls. Ordet staar ved siden af tallet
   — farven er et supplement, aldrig den eneste vej ind.
   ============================================================ */
.tablecard--st-normal  { border-color: color-mix(in srgb, var(--green) 55%, transparent); }
.tablecard--st-drikke  { border-color: color-mix(in srgb, var(--blue) 60%, transparent); }
.tablecard--st-vent    { border-color: var(--purple); }
.tablecard--st-usendt  { border-color: var(--orange); }
.tablecard--st-gul     { border-color: var(--yellow); }
.tablecard--st-roed    { border-color: var(--red); animation: critpulse 2s ease-in-out infinite; }
.tablecard--st-betalt  { border-color: color-mix(in srgb, var(--tx-2) 55%, transparent); opacity: .82; }
.tablecard--st-ledig   { border-color: var(--line-1); }

.tablecard__top {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
}
/* Tiden er fasens — den samme, farven regner paa. */
.tablecard__tid {
  font-size: 13px;
  font-weight: 700;
  color: var(--tx-2);
  font-variant-numeric: tabular-nums;
}
.tablecard__total.er-betalt { color: var(--tx-3); font-weight: 600; }

/* ------------------------------------------------------------
   KORTENE PAA EN TELEFON

   To i bredden ved 390 px giver 185 px pr. kort — nok til et
   bordnummer paa 26 px, en tid, en linje om gaesterne og et
   beloeb. Hoejden ned fra 118, fordi kortet ikke laengere baerer
   «Sat kl.» og tjenernavnet: det er oplysninger, man henter ved
   at aabne bordet, ikke noget man scanner efter fra doeren.
   ------------------------------------------------------------ */
:root[data-pos-bredde="smal"] .floor__cards {
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
}
:root[data-pos-bredde="smal"] .tablecard { min-height: 96px; padding: 8px 10px; }
:root[data-pos-bredde="smal"] .tablecard__no { font-size: 22px; }

/* ------------------------------------------------------------
   LISTEN SKAL FYLDE BREDDEN

   `.floor__grid` er `justify-content: safe center` — det er
   rigtigt for PLANEN, som skal staa midt i lokalet, og forkert
   for listen, som skal fylde fladen.

   Maalt 1. september 2026 paa 390 px: kortgitteret blev
   krympet til sin egen mindstebredde, 150 px, og laa som een
   soejle midt i en tom flade. Der var plads til to.
   ------------------------------------------------------------ */
.floor__grid.scroll-y {
  display: block;
  align-items: stretch;
  justify-content: flex-start;
}
.floor__grid.scroll-y > * { width: 100%; }

/* Et maerke tager ikke imod tryk — se «EN STOL PAA 12 PIXELS ER
   IKKE EN KNAP» i planvisning.js. Trykket gaar igennem til
   bordet, som ER stort nok. */
.pv__stol--maerke { pointer-events: none; cursor: default; }

/* ============================================================
   EN TELEFON PAA TVAERS — 390 PIXELS I HOEJDEN

   Maalt 1. september 2026 paa 844 x 390: toplinje 44, omraadefaner
   55 og baandet i TO raekker 90. Det er 189 px chrome af 390, og
   bordene fik 90 px at staa paa — de laa hen over bundmenuen.

   Ombrydningen af baandet er rigtig paa en telefon paa hoejkant,
   hvor hoejden er der og bredden ikke er. Paa tvaers er det
   omvendt: der er 844 px bredde til raadighed og ingen hoejde.
   Derfor gaelder ombrydningen kun, naar fladen IKKE er lav.

   Resten er polstring, ikke skriftstoerrelse. Teksten skal kunne
   laeses lige saa godt paa tvaers som paa hoejkant.
   ============================================================ */
:root[data-pos-hoejde="lav"] .floor__baand {
  flex-wrap: nowrap;
  gap: 14px;
  padding: 4px 10px;
}
:root[data-pos-hoejde="lav"] .floor__radar { order: 0; flex: 0 1 auto; }
:root[data-pos-hoejde="lav"] .floor__baand__knapper { margin-left: 0; }
:root[data-pos-hoejde="lav"] .floor__baand .topbar__spacer { display: block; }
:root[data-pos-hoejde="lav"] .floor__tab { padding-top: 4px; padding-bottom: 4px; }
:root[data-pos-hoejde="lav"] .floor__bjaelke { padding: 5px 10px; }

/* Bordnummerfeltet i baandet — samme sprog som bjaelkens felt,
   men i en knapraekke. Tegnet «#» er det samme, saa de to former
   kan genkendes som den samme ting. */
.floor__baand__felt { font-weight: 700; }

/* ============================================================
   REGNINGENS HOVED PAA EN SMAL ELLER LAV FLADE

   Totalen staar HER i stedet for i sin egen blok — se
   «TOTALEN STAAR I HOVEDET» i posKompakt.js. Blokken kostede
   86 px, og der var plads til een vare af seks.

   Stolestriben er flyttet ned paa sin egen raekke og har faaet
   husets fingermaal. Den stod paa hovedets linje i 26 x 24 px:
   fem knapper under maalet paa den skaerm, hvor man vaelger,
   HVEM man taster til. Rammer man ved siden af, lander oellen
   paa den forkerte gaest — og det opdages foerst ved betalingen.
   ============================================================ */
.kregning__total {
  margin-left: auto;
  /* ------------------------------------------------------------
     DER SKAL VAERE PLADS TIL 99.999,99

     Dennis, 1. september 2026. Beloebet stod med `flex` som alle
     andre og gav sig, naar stolene tog plads — saa blev «690,00
     kr.» til «690,». Et beloeb, der er klippet, er vaerre end
     ingen: det ligner et mindre tal.

     Den giver sig ALDRIG (`flex: 0 0 auto`) og braekker ikke
     (`nowrap`). Bliver linjen for smal, er det stolestriben, der
     ruller — den kan bladres, det kan et tal ikke.
     ------------------------------------------------------------ */
  flex: 0 0 auto;
  white-space: nowrap;
  /* Den er et GREB: dobbelttryk folder regningen ud. Saa skal
     den kunne rammes som alt andet, man trykker paa. */
  min-height: var(--touch-min);
  display: flex;
  align-items: center;
  padding: 2px 6px;
  border: 0;
  background: transparent;
  color: var(--tx-1);
  font-size: 19px;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  letter-spacing: -.3px;
  cursor: pointer;
}

/* Stolene: husets fingermaal, ogsaa paa den store skaerm. */
.kstol {
  min-width: 44px;
  height: var(--touch-min);
  font-size: 13px;
  padding: 0 10px;
}
/* ------------------------------------------------------------
   HOEJDEN ER FAST — BREDDEN MAA GIVE SIG

   Her stod `flex: 0 0 auto`. Grunden var rigtig: paa iPad
   staaende blev striben klemt til 32 px, og saa var de 44 px
   hoeje stole ikke 44 laengere. Et fingermaal, der kun gaelder,
   naar der er plads til overs, er ikke et fingermaal.

   Men striben laa dengang i sin EGEN raekke, hvor `0 0` handlede
   om hoejden. Fra 1. september 2026 staar den i regningens hoved
   ved siden af bordnummeret og beloebet — og dér betyder `0 0`,
   at den naegter at give sig i BREDDEN. Maalt samme dag paa
   428 x 926: hovedet skulle bruge 600 px i en kasse paa 386, og
   «690,00 kr.» stod 69 px uden for kortet.

   Hoejden laases derfor for sig, og bredden slippes fri. To
   forskellige spoergsmaal, to forskellige svar.
   ------------------------------------------------------------ */
.kstole {
  flex: 1 1 auto;
  min-width: 0;
  min-height: var(--touch-min);
  margin-left: 0;
  padding: 2px 0;
  gap: 6px;
}

/* `.kompakt` er `flex-direction: column` — den regel er
   staerkere end klassen `.row`, fordi den staar senere. Derfor
   vendes retningen HER, hvor formen faktisk vaelges. */
.kompakt--side { flex-direction: row; }

/* ============================================================
   DEN KOMPAKTE FLADE MED REGNINGEN I SIDEN

   Kun naar motoren siger det — i praksis en telefon paa tvaers.
   Se «REGNINGEN VED SIDEN AF» i posKompakt.js.

   Bredden er motorens (`--pos-regning-bredde`), ikke et tal her:
   den er regnet ud af, hvad en regningslinje skal kunne baere, og
   hvad varerne skal have tilbage.
   ============================================================ */
.kompakt--side { gap: 8px; min-height: 0; }
.kompakt--side .kompakt__varer { min-width: 0; min-height: 0; gap: 6px; }
.kompakt--side .kregnrum {
  flex: 0 0 var(--pos-regning-bredde, 338px);
  min-width: 0;
  /* I en raekke er baandhoejden ligegyldig — spalten er lige saa
     hoej som fladen. */
  height: auto;
}

/* ============================================================
   BETALINGSSKAERMEN PAA EN SMAL FLADE

   ------------------------------------------------------------
   1. FANERNE MAA IKKE GEMME SIG

   Fem maader — «Hele regningen», «Efter gæst», «Efter varer»,
   «Ligelig deling», «Beløb» — er 560 px paa en flade paa 390.
   De laa i en vandret ruller, og maalt 1. september 2026 stod
   «Ligel…» klippet og «Beløb» helt uden for skaermen. En
   betalingsmaade, man ikke kan se, findes ikke for den, der ikke
   ved, at den er der.

   Paa en smal flade brydes de derfor i to raekker. Det koster
   40 px een gang; det andet kostede en betalingsmaade.

   ------------------------------------------------------------
   2. DEN TOMME RUDE SKAL IKKE FYLDE

   Naar intet er valgt, staar «Intet valgt endnu» i en kasse paa
   omkring 90 px. Paa en iPad er den en spalte ved siden af og
   koster ingenting. Paa en telefon er den en raekke, der skubber
   varerne op — 90 px for at sige, at der ikke er noget.
   Overskriften «BETALES NU 0,00» siger det samme paa een linje.
   ============================================================ */
/* ------------------------------------------------------------
   MEN KUN BETALINGSMAADERNE.

   Foerste udgave skrev `.floor__tabs.scroll-x` — og den klasse
   baerer ogsaa bordplanens omraadefaner, KDS’ stationer,
   ordreskaermens kategorier og layouteditorens sider.

   Maalt 1. september 2026 paa iPhone i hoejformat: bordplanens
   syv omraader brød i TO raekker og tog 108 px af 844. Med et
   omraade mere var det blevet tre. Og lige ovenfor, ved
   `.floor__tabs`, staar husets egen beslutning: OMRAADERNE
   RULLER — SIDEN GOER IKKE.

   Forskellen er ikke smag. Betalingsmaaderne er FEM, de er faste,
   og den femte er «Beløb». Omraaderne er en liste, huset selv
   laegger til i, og en fanerække, der vokser nedad, aeder
   bordplanen. Reglen hoerer derfor til den ene og ikke den anden.
   ------------------------------------------------------------ */
:root[data-pos-bredde="smal"] .paymodes,
:root[data-pos-bredde="smal"] .floor__tabs.paymodefaner {
  flex-wrap: wrap;
  overflow-x: visible;
}
:root[data-pos-bredde="smal"] .floor__tabs.paymodefaner > .floor__tab {
  flex: 1 0 auto;
}

:root[data-pos-bredde="smal"] .pay__tom {
  padding: 6px;
  font-size: 12px;
}

/* ============================================================
   KATEGORISTRIBEN SIGER, AT DER ER MERE

   Striben ruller vandret med vilje — det er husets maade at have
   flere kategorier end skaermbredde, og `haandholdtskaermtest`
   undtager den udtrykkeligt fra reglen om vandret rulning.

   Men den sagde det ikke. Paa 390 px stod «Hovedretter» klippet
   midt over uden noget, der antydede, at der var mere til hoejre.
   Set paa et skaermbillede 1. september 2026: det ligner en fejl,
   ikke en liste.

   En blaending i hoejre kant. Den koster ingen plads, den kan ikke
   trykkes forkert, og den forsvinder af sig selv, naar man har
   rullet til enden — `scroll-timeline` findes ikke overalt, saa
   den staar fast; en blaending over en tom kant er ikke forkert,
   den er bare ligegyldig.
   ============================================================ */
.kkatstribe {
  position: relative;
  /* Maskeringen er selve elementet: sidste 28 px toner ud, saa
     den kategori, der ligger halvt uden for, ser ud som noget,
     der fortsaetter — og ikke som noget, der er hugget af. */
  /* `currentColor` og ikke en farve: en maske laeser ALFA, ikke
     kulør, og huset forbyder haardkodede farver i regler — med
     rette. Den uigennemsigtige ende maa vaere hvad som helst
     ugennemsigtigt. */
  -webkit-mask-image: linear-gradient(to right, currentColor calc(100% - 28px), transparent 100%);
  mask-image: linear-gradient(to right, currentColor calc(100% - 28px), transparent 100%);
}
/* Er der intet at rulle til, skal der heller ikke tones ud. En
   flade med tre kategorier skal ikke se ud, som om den skjuler
   noget. Klassen saettes af `kategoristribe` i posKompakt.js. */
.kkatstribe--alt-synligt {
  -webkit-mask-image: none;
  mask-image: none;
}

/* ============================================================
   HANDLINGSBLOKKENS RAEKKER MAA IKKE SKRUMPE

   `[VENT][Send bon]` staar som en `.row` i kassens
   handlingsblok. En `.row` er `flex: 0 1 auto` — den maa gerne
   skrumpe — men dens knapper er `min-height: 56px` og skrumper
   IKKE. Raekken blev 22 px hoej, og de 56 px hoje knapper laa
   34 px ned over «Send hovedret» under dem.

   Maalt 1. september 2026 paa kasseprofilen, 1440 x 900, af
   `fladetest` — den samme scanner, de kompakte flader maales med.
   Fejlen havde staaet der hele tiden; ingen havde maalt kassen.

   `0 0 auto`: raekken tager den hoejde, dens knapper skal have.
   Er der ikke plads, skal noget ANDET vige — og saa siger
   maalingen det.
   ============================================================ */
.kasse__handlinger > .row { flex: 0 0 auto; }

/* ============================================================
   BETALINGSSKAERMEN PAA EN LAV FLADE

   ------------------------------------------------------------
   TRE PIXELS TIL VARERNE

   Maalt 1. september 2026 paa 844 x 390 — af den nye
   spildt-regel, ikke af et oeje. Toplinje 47, bordhoved 55,
   faner 60, tre totallinjer 80, betalingsknapper 60 og
   bundmenuen 56 er 358 af 390. `.ordmain` fik 3 px, og listen
   over ubetalte varer laa uden for sin egen kasse.

   ------------------------------------------------------------
   TRE LINJER BLIVER TIL EEN

   «Total», «Rest» og «Betales nu» staar under hinanden, fordi
   det er tre forskellige spoergsmaal. Paa en flade med 390 px i
   hoejden er der ikke raad til at stille dem hver for sig — og de
   er korte nok til at staa paa linje. Det er den samme afvejning
   som paa bordplanens baand: faa, faste tal i een raekke.

   Husets egen regel for lave flader staar i `skaermlayout`:
   «fladen har ikke hoejde til en fuld spalte, og skaermen skal
   RULLE lodret i stedet for at flyde over.» Derfor faar
   `.ordmain` ogsaa et gulv: den maa aldrig blive lavere end en
   raekke, og saa ruller den i stedet.
   ============================================================ */
:root[data-pos-hoejde="lav"] .paypanel {
  flex-direction: row;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px 14px;
  padding: 6px 10px;
}
:root[data-pos-hoejde="lav"] .paypanel > .total-line {
  flex: 0 0 auto;
  gap: 6px;
}
:root[data-pos-hoejde="lav"] .paypanel .total-line--grand { font-size: 19px; }
/* Knapperne tager den raekke, de skal have — de er hele
   handlingen paa skaermen. */
/* Specificiteten skal matche `:root[data-pos-flade="kompakt"]
   .pay .paymetoder` laengere oppe, som saetter `flex: 1 1 auto`.
   Ellers deler knapperne raekke med totallinjerne og faar 391 px
   af 844 — og saa bliver fem betalingsmaader til to raekker paa
   en flade, der har rigelig bredde. */
:root[data-pos-hoejde="lav"][data-pos-flade="kompakt"] .pay .paymetoder {
  flex: 1 0 100%;
  max-height: none;
}

/* ------------------------------------------------------------
   PLADSEN TAGES, HVOR DEN ER — IKKE MED ET GULV

   Foerste forsoeg gav `.ordmain` et gulv paa 96 px. Det flyttede
   bare fejlen: soejlen blev 52 px for hoej, og saa laa
   betalingsknapperne under kanten i stedet.

   Et gulv loeser ingenting, naar summen er for stor. Regnestykket
   paa 844 x 390 er:

     390 − 48 toplinje − 66 bundmenu           = 276 til skaermen
     bordhoved 62 + faner 57 + knapper 113     = 232
     tilbage til varerne                       =  44

   De tre dele skal derfor give omkring tres pixels tilbage. De
   giver dem i POLSTRING og ikke i skriftstoerrelse — teksten skal
   kunne laeses lige saa godt paa tvaers som paa hoejkant.
   ------------------------------------------------------------ */
:root[data-pos-hoejde="lav"] .ordhead { padding-top: 4px; padding-bottom: 4px; }
:root[data-pos-hoejde="lav"] .ordhead__sub { display: none; }
:root[data-pos-hoejde="lav"] .floor__tabs .floor__tab {
  padding-top: 6px;
  padding-bottom: 6px;
}
:root[data-pos-hoejde="lav"] .paybund { padding: 2px 0; }
:root[data-pos-hoejde="lav"] .paypanel { padding: 4px 10px; }

/* ------------------------------------------------------------
   BETALINGSKNAPPERNE PAA EEN RAEKKE

   Gitteret er to spalter. Fem betalingsmaader bliver derfor TRE
   raekker — omkring 145 px. Paa en flade, der er 844 px bred og
   390 hoej, er det den forkerte vej at bruge pladsen: der er
   rigelig bredde og ingen hoejde.

   `auto-fit` med et gulv paa 130 px giver fem knapper paa een
   raekke ved 844 og falder selv tilbage til to raekker, hvis
   fladen er smallere. Gulvet er ikke pynt: «Kontant DKK» skal
   kunne staa der.
   ------------------------------------------------------------ */
/* Grundformen — den stod som inline-stil i `payment.js`. */
.paymetoder {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 6px;
  margin-top: 4px;
}
:root[data-pos-hoejde="lav"] .paymetoder { margin-top: 0; }

/* Stolen staar foran noten og i husets accentfarve, saa den kan
   skimtes uden at laeses — noten er gul og kursiv, stolen er
   ikke. To forskellige slags oplysning maa ikke se ens ud. */
.kline__tekst--stol { color: var(--tx-2); font-style: normal; font-weight: 600; }

/* ============================================================
   GENVEJENE MAA IKKE BLIVE PLAKATER

   `grid-auto-rows: minmax(46px, 1fr)` lader dem fylde totalfeltet
   ud, og det er rigtigt i den NORMALE hoejde: fire genveje i et
   felt paa 320 px bliver behageligt store.

   Med regningen foldet ud er feltet 1.050 px hoejt og genvejene
   ti. Maalt 1. september 2026 paa iPad staaende: hver knap blev
   godt hundrede px hoej med hundrede px luft imellem — de saa
   tilfaeldigt placerede ud, og oejet kunne ikke se dem som EEN
   gruppe.

   Loftet er 88 px: rigeligt til to linjers tekst og et fingermaal
   med luft omkring. Resten af hoejden staar som et samlet felt
   nederst i stedet for at blive delt ud mellem knapperne.
   ============================================================ */
.kompakt--udvidet .kgenveje {
  align-content: start;
  grid-auto-rows: minmax(max(46px, var(--touch-min, 44px)), 88px);
}

/* ============================================================
   LINJEDIALOGENS HOVED PAA EN TELEFON

   Varenavnet til venstre, «3 STK · IKKE SENDT» og beloebet til
   hoejre, med 16 px imellem. Paa 390 px — og saerligt paa 360 —
   er der ikke plads til begge, og hovedet floed ud over kanten.
   Fundet af `fladetest` 1. september 2026, da linjedialogen kom
   med i maalingen; den var aldrig blevet maalt foer.

   Navnet maa bryde over to linjer — et varenavn er dét, dialogen
   handler om, og det skal staa helt. Beloebet viger ikke, og
   kan de to ikke vaere paa samme raekke, faar beloebet sin egen.
   ============================================================ */
.ve__navn { min-width: 0; overflow-wrap: anywhere; }
.ve__total { flex: 0 0 auto; }
:root[data-pos-bredde="smal"] .ve__hoved { flex-wrap: wrap; gap: 4px 12px; }
:root[data-pos-bredde="smal"] .ve__total { text-align: left; }

/* ============================================================
   OPSLAGSLISTEN PAA EN SMAL SKAERM

   Raekken er `68px 1fr auto`: varenummer, navn, pris. Paa 360 px
   faar navnet omkring 180, og «Jakobs Cheddarburger» broed til to
   linjer — raekken voksede ud over sin egen kasse, og listen blev
   ujaevn. Fundet af `fladetest` 1. september 2026 paa 360 x 640.

   En liste, man SCANNER, skal have ens raekker. Navnet klippes
   derfor med ellipsis i stedet for at bryde, og varenummeret —
   som man kun bruger, naar man allerede kender det — viger paa
   den smalle flade, saa navnet faar de 68 px.

   Prisen viger aldrig. Det er den, man leder efter.
   ============================================================ */
.opslag__navn {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
:root[data-pos-bredde="smal"] .opslag__rk {
  grid-template-columns: 1fr auto;
  gap: 8px;
}
:root[data-pos-bredde="smal"] .opslag__plu { display: none; }

/* ============================================================
   DEN TOMME VALGRUDE, NAAR RUDERNE ER STABLET

   Paa en bred flade staar «det, der betales nu» som en spalte ved
   siden af varerne, og en tom spalte koster ingenting.

   Paa alt under 820 px stables de. Maalt 1. september 2026 paa
   iPad staaende med ti varer: den TOMME rude tog 350 px af
   hoejden for at skrive «Intet valgt endnu», mens listen over
   varer var klippet efter den syvende. Man kunne ikke se de tre
   sidste — paa den skaerm, hvor man skal vaelge dem.

   Er der intet valgt, er ruden derfor kun sin egen overskrift:
   «BETALES NU · 0,00 kr.» paa een linje. I samme oejeblik der
   vaelges noget, vokser den igen — for saa er der noget at se.
   ============================================================ */
.pay__hoejre--tom {
  flex: 0 0 auto;
}
.pay__hoejre--tom .pay__tom { display: none; }

/* ============================================================
   FIRE TALLINJER PAA EN TELEFON

   «Ligelig deling» og «Beloeb» viser Total, Betalt, Rest og
   «Betales nu» under hinanden — fire raekker, omkring 160 px paa
   en flade paa 844. Maalt 1. september 2026: fordelingskortet,
   som er dét, man skal se i den tilstand, laa under kanten.

   De fire er ikke lige vigtige. «Rest» og «Betales nu» er dem,
   man handler paa; «Total» og «Betalt» er baggrund. De to
   baggrundstal deler derfor raekke paa en smal flade, og de to
   andre beholder deres egen — «Rest» skal kunne ses paa afstand.
   ============================================================ */
:root[data-pos-bredde="smal"] .paypanel {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 2px 14px;
}
:root[data-pos-bredde="smal"] .paypanel > .total-line {
  flex: 1 1 42%;
  gap: 6px;
}
/* De to, man handler paa, faar hver sin raekke. */
:root[data-pos-bredde="smal"] .paypanel > .total-line--grand { flex: 1 0 100%; }
:root[data-pos-bredde="smal"][data-pos-flade="kompakt"] .pay .paymetoder { flex: 1 0 100%; }

/* ============================================================
   ANTAL BETALERE

   Elleve tal fra 2 til 12. Paa en iPad fylder de een raekke; paa
   en telefon blev de TRE raekker a 56 px, og fordelingskortet —
   dét, man skal se, naar man har valgt — laa under kanten.

   Tallene bliver smallere paa en smal flade, ikke lavere: hoejden
   er husets fingermaal, og et tal er let at ramme, naar det er
   hoejt nok. To raekker i stedet for tre.
   ============================================================ */
.paydelere {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(64px, 1fr));
  gap: 6px;
}
:root[data-pos-bredde="smal"] .paydelere {
  grid-template-columns: repeat(auto-fill, minmax(52px, 1fr));
  gap: 5px;
}

/* Hastetegnet paa listekortet — samme tegn som paa figuren, se
   `P.hastetegn`. Det staar FOER tiden, saa oejet moeder det paa
   vej ind i tallet. */
.tablecard__tid { display: flex; align-items: baseline; gap: 5px; }
.tablecard__haste { font-weight: 900; letter-spacing: -.5px; }
/* ------------------------------------------------------------
   HASTEMAERKET ER TEKST — OG SKAL LAESES SOM TEKST

   `--red` er husets FYLDFARVE: den er lavet til hvid skrift oven
   paa sig. Som skriftfarve paa en moerk bund giver den 4,46 mod
   husets krav paa 4,5. Fanget af `skaermscan` 1. september 2026
   paa «!!» — netop det maerke, der skal raabe hoejest.

   `--red-tekst` er den samme roede, blandet mod hvidt, og den er
   der praecis til det her. Se `--red-tekst` i toppen af filen og
   de to andre steder, den allerede bruges.
   ------------------------------------------------------------ */
.tablecard__haste--gul  { color: var(--yellow); }
.tablecard__haste--roed { color: var(--red-tekst); }
/* Og paa figuren. */
.pv__tegn__et--gul  { color: var(--yellow); }
.pv__tegn__et--roed { color: var(--red-tekst); }

/* ============================================================
   GREBET FORSVINDER PAA EN TELEFON

   Grebet er de 18 px prikker i venstre kant, man traekker i for
   at flytte en usendt vare op eller ned i regningen. Paa en iPad
   giver det mening: man ordner listen til social dining, og der
   er plads til at ramme det.

   Paa en telefon er raekken 348 px, og varenavnet faar 93 af dem.
   Maalt 1. september 2026 paa 390 x 844 med «99× Tomatsuppe
   6.435,00». Et navn som «Jakobs Cheddarburger» kan ikke staa der.

   Raekkefoelgen i regningen er ikke noget, man ordner staaende
   ved et bord med en telefon i haanden — det er noget, man goer
   ved kassen eller paa iPad'en. De 18 px gaar til navnet, hvor de
   goer nytte hvert eneste sekund.

   `display: none` og ikke `visibility: hidden`: her skal pladsen
   VAEK, ikke bare indholdet. Alle raekker mister den samtidig, saa
   listen staar stadig lige.
   ============================================================ */
:root[data-pos-bredde="smal"] .kline__greb { display: none; }

/* ============================================================
   «?»-MAERKET SKAL KUNNE LAESES PAA SIN EGEN BAGGRUND

   Maerket siger, at afsendelsen gik galt eller er uafklaret. Det
   er den vigtigste oplysning paa raekken — og det var det mindst
   laesbare paa den.

   Raekken faar `rgba(--red, .14)` som baggrund, netop FORDI der er
   et problem. Maerket stod i `--red` oven paa den. Maalt
   1. september 2026: **4,19:1**. Husets krav er 4,5.

   Farven paa en raekke, der raaber, maa ikke goere raabet
   sværere at hoere. Maerket lysnes derfor 15 % — nok til 4,6:1 —
   og det er stadig tydeligt roedt. Det samme for det gule.

   `color-mix` og ikke en ny haardkodet farve: skifter husets
   `--red`, foelger maerket med.
   ============================================================ */
.kline__maerke { color: color-mix(in srgb, var(--yellow) 88%, white); }
.kline__maerke--problem { color: var(--red-tekst); }

/* ============================================================
   ET ELEMENT UDEN FYLD LIGGER PAA PLANENS EGEN BUND

   Materialet «aaben» betyder, at huset har valgt INGEN fyld:
   elementet er gennemsigtigt, og teksten staar direkte paa
   planens moerke bund.

   Men farven kom stadig fra materialet — den brune, der hoerer
   til en beige vaeg. Maalt 1. september 2026 paa
   «Indgang»: **2,53:1**. En etiket, der skal fortaelle, hvor i
   lokalet man staar, og som ikke kan laeses.

   Uden fyld gaelder fladens egen tekstfarve. `!important` fordi
   materialereglerne selv bruger det; det er den eneste maade at
   svare dem uden at bygge hele materialetabellen om.
   ============================================================ */
.pv__element--m-aaben, .bp__element--m-aaben {
  color: var(--tx-2) !important;
  text-shadow: 0 1px 3px rgba(0, 0, 0, .85) !important;
}

/* ============================================================
   NAVNET PAA ET GULVELEMENT SKAL KUNNE LAESES

   «Indgang», «Bar», «Trappe» — de staar paa planen, saa man kan
   se, hvor i lokalet man er. Teksten var `--tx-3` paa et element,
   der ofte er gennemsigtigt, altsaa paa planens egen moerke
   bund. Maalt 1. september 2026: **2,37:1**, hvor kravet er 4,5.

   En etiket, der skal orientere, og som ikke kan laeses, er en
   etiket, der ikke goer sit arbejde.

   `--tx-2` i stedet for `--tx-3`, og den samme halo, som resten
   af planens tekst bruger — saa den ogsaa holder, naar elementet
   ligger paa noget lyst.
   ============================================================ */
.pv__element, .bp__element {
  color: var(--tx-2);
  text-shadow: 0 1px 2px var(--pv-halo, rgba(0, 0, 0, .55));
}

/* ============================================================
   DE FIRE DOERE SKAL LIGGE OVER HJEMMEINDIKATOREN

   `.app-root` polstrer for sikkerhedsomraadet i top, venstre og
   hoejre — men ikke i bunden. Det var rigtigt, da den KLASSISKE
   bundnavigation var den eneste: `.bottomnav` polstrer sig selv.

   Den kompakte bundbjaelke gjorde ikke. Paa en iPhone med
   hjemmeindikator betyder det, at de nederste ~34 px af ORDRE,
   HANDLING, KONFIG og AFSLUT ligger i systemets eget felt — den
   mest brugte navigation i hele kassen, med foden under vandet.

   Fundet ved at laese 1. september 2026, ikke ved at maale: en
   emuleret viewport har ingen sikkerhedsomraader, saa hverken
   `fladetest` eller et skaermbillede kunne se det. Det ses
   foerst paa en rigtig telefon, og der er det for sent.

   Polstringen ligger INDE i kassen, saa rammen og den afrundede
   kant foelger med ned. Knapperne beholder deres hoejde; det er
   feltet under dem, der vokser.
   ============================================================ */
.kbund { padding-bottom: env(safe-area-inset-bottom); }

/* ============================================================
   «VENT»-MAERKET LAA PAA SIN EGEN FARVE

   Orange tekst paa `--accent-svag`, som er 32 % orange. Maalt
   1. september 2026: **4,15:1** ved 10 px. Kravet er 4,5.

   Samme moenster som `?`-maerket og «Slet»: husets farve brugt
   BAADE som tekst og som fyld under den samme tekst.

   Her tyndes fyldet i stedet for at lysne skriften. Maerket er en
   orange brik med en orange kant — skriften skal blive ved med at
   vaere praecis den samme orange som kanten, ellers ser brikken
   ud som to farver. 20 % giver 4,89:1, og den laeser stadig
   tydeligt som orange.

   Kun her: `--accent-svag` bruges mange steder, og det her er den
   ene, hvor den baerer tekst i sin egen farve.
   ============================================================ */
.kvent__mrk { background: color-mix(in srgb, var(--accent) 20%, transparent); }

/* ============================================================
   ET VARENAVN PAA EN LAV SKAERM FAAR EEN LINJE

   Etiketten klemmes til to linjer — `-webkit-line-clamp: 2` —
   og det passer paa en knap, der er 84 px hoej.

   Paa en telefon paa tvaers er knappen 46 px. Efter polstring og
   prislinjen er der 22 px til navnet, og to linjer paa 12,5 px
   skal bruge 27,5. Maalt 1. september 2026 med «Hjemmebrygget
   paaskebryg fra Jakobs eget bryggeri»: den anden linje blev
   skaaret over paa midten — uden ellipsis, saa man ikke engang
   kunne SE, at der manglede noget.

   Een linje med ellipsis i stedet. Det er husets egen regel fra
   bordfigurerne: en afhugget tekst er vaerre end en forkortet,
   fordi man ikke kan se, at den er hugget af. Hele navnet staar i
   knappens `title`, og prisen viger aldrig.
   ============================================================ */
:root[data-pos-hoejde="lav"] .gridcell__label {
  -webkit-line-clamp: 1;
  line-clamp: 1;
}

/* Gaestetaellerens plus og minus — se «GAESTETAELLEREN SKAL KUNNE
   RAMMES» i bordinfo.js. Husets fingermaal i begge led.

   Selektoren maa matche `.modal__body .btn { min-width: 0 }`
   laengere oppe, som findes for at knapper i et gitter kan
   skrumpe. Den her ene skal ikke skrumpe: den er 44 px, fordi
   det er dét, en finger er. */
.kt__pm,
.modal__body .btn.kt__pm { min-width: var(--touch-min, 44px); }

/* ============================================================
   SIDSTE SALG — TO TAL, LÆST PÅ AFSTAND

   Dennis, 1. september 2026: «Store tal. Meget lidt tekst.»

   Skærmen er et ledelsesværktøj, ikke en rapport. Derfor er der
   ingen tabel: seks tidsrum i et gitter, og under dem tallene i
   en størrelse, der kan læses, mens man går forbi.

   Gitteret vælger selv antal spalter. Tre på en iPad, to på en
   telefon — og det sker i `@container`, ikke på vinduets bredde,
   fordi hele den kompakte flade måler sig selv og ikke browseren.
   ============================================================ */
.sidstesalg {
  display: flex;
  flex-direction: column;
  gap: 16px;
  padding: 16px;
  height: 100%;
  min-height: 0;
  box-sizing: border-box;
}

.sshoved {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  flex: 0 0 auto;
}
.sshoved__titel {
  font-size: 15px;
  font-weight: 800;
  letter-spacing: 0.12em;
  color: var(--tx-2);
}
/* Hvor tallene kommer fra — lille, men til stede. En leder, der
   ser husets tal på kasse 2, skal ikke tro, det er kasse 2's. */
.sshoved__kilde {
  font-size: 12px;
  color: var(--tx-3);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.ssvinduer {
  flex: 0 0 auto;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 8px;
}
.ssvindue {
  min-height: var(--touch);
  padding: 8px 4px;
  border: 1px solid var(--line-1);
  border-radius: var(--r-md);
  background: var(--bg-2);
  color: var(--tx-2);
  font-size: 15px;
  font-weight: 700;
  letter-spacing: 0.04em;
  cursor: pointer;
}
/* Det valgte tidsrum må ikke kendes på farve alene: det er
   fyldt, det har en kraftigere kant, og teksten er husets
   primære. Tre kanaler, så det også kan ses i modlys. */
.ssvindue.is-active {
  background: var(--orange-soft);
  border-color: var(--orange);
  color: var(--tx-1);
}

/* ------------------------------------------------------------
   TAVLEN

   Tallene fylder den plads, der er tilbage, og står midt i den.
   `min-height: 0` så de kan give sig på en lav skærm i stedet
   for at skubbe sig selv ned under kanten.
   ------------------------------------------------------------ */
.sstavle {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 20px;
  text-align: center;
}
.sstal__vaerdi {
  font-weight: 800;
  line-height: 1.02;
  color: var(--tx-1);
  font-variant-numeric: tabular-nums;
}
.sstal__ord {
  margin-top: 4px;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.14em;
  color: var(--tx-3);
}
/* `clamp` og ikke et fast tal: tallet skal være så stort, som
   fladen tillader, og skrumpe af sig selv på en telefon i
   liggende format — uden at nogen skal skrive tre brudpunkter. */
/* `cqw` og ikke `vw`: den kompakte flade maaler sig selv, ikke
   browservinduet. Loftet er hoejt, fordi en iPad i hoejformat
   ellers stod med 400 px tom plads under tallene — og ubrugt
   plads er ogsaa en fejl, naar hele pointen er at kunne laese
   tallet paa afstand. */
.sstal--stor .sstal__vaerdi { font-size: clamp(40px, 13cqw, 108px); }
.sstal--lille .sstal__vaerdi { font-size: clamp(22px, 6cqw, 38px); }
.sstal--lille .sstal__ord { color: var(--tx-3); }

/* ------------------------------------------------------------
   RETNINGEN

   Én linje under tallene. Farven siger det samme som pilen og
   som ordet — tre kanaler, fordi en pil alene forsvinder for
   den, der ser skævt på en skærm i modlys.

   `--green` og `--at-late` er husets egne. Roedt er IKKE brugt:
   en stille time er ikke en fejl, og huset gemmer roedt til
   det, nogen skal handle paa.
   ------------------------------------------------------------ */
.ssforrige {
  flex: 0 0 auto;
  display: flex;
  align-items: baseline;
  justify-content: center;
  gap: 8px;
  font-size: 13px;
  color: var(--tx-3);
}
.ssforrige__pil { font-size: 11px; }
.ssforrige__ord {
  font-weight: 800;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  font-size: 12px;
}
.ssforrige--op .ssforrige__pil,
.ssforrige--op .ssforrige__ord { color: var(--green); }
.ssforrige--ned .ssforrige__pil,
.ssforrige--ned .ssforrige__ord { color: var(--at-late); }

.sstomt {
  flex: 0 0 auto;
  text-align: center;
  font-size: 14px;
  color: var(--tx-3);
  padding-bottom: 8px;
}

/* To spalter, når der ikke er plads til tre. «1½ TIME» er det
   bredeste felt, og ved 44 px pr. bogstavgruppe knækker det
   under omkring 420 px. */
@container pos (max-width: 460px) {
  .ssvinduer { grid-template-columns: repeat(2, 1fr); }
  .sidstesalg { padding: 12px; gap: 12px; }
}

/* På en lav skærm — telefonen i liggende format — er højden det
   knappe. Tidsrummene bliver en enkelt række, og tallene står
   ved siden af hinanden i stedet for over. */
:root[data-pos-hoejde="lav"] .ssvinduer {
  grid-template-columns: repeat(6, 1fr);
}
:root[data-pos-hoejde="lav"] .ssvindue {
  min-height: var(--touch-min);
  font-size: 13px;
}
/* ------------------------------------------------------------
   TRE TAL VED SIDEN AF HINANDEN SKAL KUNNE SKILLES AD

   Målt 1. september 2026 på iPhone i liggende format: «2» og
   «435 kr.» stod med 28 px imellem sig i en skriftstørrelse på
   omkring 100 px. På skærmen læste det som ét tal — «2 435 kr.»
   — og skærmen svarede dermed på noget helt andet, end den blev
   spurgt om.

   Skærmscanneren så ingenting: der var hverken overlap,
   klipning eller for lav kontrast. Det var afstanden i forhold
   til bogstavernes størrelse, der var forkert.

   Hvert tal får derfor sin egen spalte med en skillelinje
   imellem, og skriften får et lavere loft. Ikke «gør det
   mindre, til det passer»: kolonnerne er det, der gør de tre
   tal til tre tal.
   ------------------------------------------------------------ */
:root[data-pos-hoejde="lav"] .sstavle {
  flex-direction: row;
  align-items: stretch;
  gap: 0;
}
:root[data-pos-hoejde="lav"] .sstal {
  flex: 1 1 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 0 16px;
}
:root[data-pos-hoejde="lav"] .sstal + .sstal {
  border-left: 1px solid var(--line-1);
}
:root[data-pos-hoejde="lav"] .sstal--stor .sstal__vaerdi {
  font-size: clamp(32px, 7cqw, 64px);
}
:root[data-pos-hoejde="lav"] .sstal--lille .sstal__vaerdi {
  font-size: clamp(22px, 4cqw, 40px);
}
:root[data-pos-hoejde="lav"] .sidstesalg { padding: 10px 16px; gap: 10px; }

/* ============================================================
   MANGLENDE Z-RAPPORTER

   Dennis, 1. september 2026: «Det skal derfor være umuligt at
   glemme et døgn væk.»

   Bjælken står øverst på kasseskærmen. Den er gul og ikke rød:
   et glemt regnskabsdøgn er ikke en fejl, der er sket — det er
   noget, der mangler at blive gjort. Rødt gemmer huset til det,
   der er gået galt.

   Kun den øverste række har en knap. Døgnene skal lukkes i den
   rækkefølge, de skete, og en knap, der altid ville give et rødt
   afslag, er en dør, der aldrig var åben.
   ============================================================ */
.zmangler {
  flex: 0 0 auto;
  margin: 12px 12px 0;
  border-color: var(--at-soon);
  background: var(--bg-2);
}
.zmangler__titel {
  font-size: 12px;
  font-weight: 800;
  letter-spacing: 0.12em;
  color: var(--at-soon);
  margin-bottom: 10px;
}
.zmangler__liste {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.zmangler__rad {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 8px 10px;
  border-radius: var(--r-sm);
  background: var(--bg-3);
  /* Rækken skal kunne give sig, når navnet er langt — men den
     må ikke blive lavere end knappen inde i den. */
  min-height: var(--touch-min);
}
/* Den, der er tur til. Kanten siger det samme som knappen, så
   det også kan ses, hvis knappen er rullet ud af syne. */
.zmangler__rad--tur {
  border: 1px solid var(--at-soon);
  background: var(--bg-4);
}
.zmangler__dag {
  flex: 1 1 auto;
  min-width: 0;
}
.zmangler__navn {
  font-size: 15px;
  font-weight: 700;
  color: var(--tx-1);
}
/* `--tx-2` og ikke `--tx-3`. Raekken, der er tur til, staar paa
   `--bg-4`, og dér giver den daempede tekstfarve 4,08:1 — under
   husets krav paa 4,5. Maalt af skaermscanneren 1. september 2026.

   Og det er ogsaa den rigtige vaegt: tidsrummet er den ene ting,
   lederen skal kontrollere, foer hun trykker Afslut. Det er ikke
   en bifangst. */
.zmangler__tid {
  font-size: 12px;
  color: var(--tx-2);
}
.zmangler__knap {
  flex: 0 0 auto;
  min-height: var(--touch-min);
  min-width: 96px;
}
.zmangler__venter {
  flex: 0 0 auto;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--tx-3);
}
.zmangler__note {
  margin-top: 10px;
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--tx-3);
}

/* På en telefon står dagen over knappen i stedet for ved siden
   af. «torsdag 27. august» og en knap på 96 px kan ikke begge få
   plads i bredden på 390 px uden at navnet klippes. */
@container pos (max-width: 460px) {
  .zmangler { margin: 8px 8px 0; }
  .zmangler__rad {
    flex-direction: column;
    align-items: stretch;
    gap: 8px;
  }
  .zmangler__knap { width: 100%; }
  .zmangler__venter { text-align: right; }
}

/* ============================================================
   BESKEDVINDUET — DEN SKAL SES

   Dennis, 1. september 2026: «Når en besked modtages, skal den
   være meget synlig.»

   Typen kendes på TRE ting: en farvet stribe i venstre kant, et
   ord i overskriften (BESKED · VIGTIGT · ADVARSEL) og
   afsenderens navn øverst. Farven alene ville forsvinde for den,
   der ser skævt på en skærm i modlys — og for en oplæser.
   ============================================================ */
.beskedvindue {
  display: flex;
  flex-direction: column;
  gap: 12px;
  border-left: 4px solid var(--line-2);
  padding-left: 14px;
}
.beskedvindue--vigtig   { border-left-color: var(--at-late); }
.beskedvindue--advarsel { border-left-color: var(--red); }

.beskedvindue__hoved {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
}
.beskedvindue__afsender {
  font-size: 15px;
  font-weight: 800;
  color: var(--tx-1);
}
.beskedvindue__tid {
  font-size: 13px;
  color: var(--tx-2);
  font-variant-numeric: tabular-nums;
}
/* Selve beskeden er det største på skærmen. Den skal kunne læses
   på en armslængdes afstand, mens man holder en bakke. */
.beskedvindue__tekst {
  font-size: 20px;
  line-height: 1.45;
  color: var(--tx-1);
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}
.beskedvindue__omfang {
  font-size: 12.5px;
  color: var(--tx-3);
}

/* ============================================================
   BESKEDSKÆRMEN — HVEM OG HVOR ER TO SPØRGSMÅL
   ============================================================ */
.bskskaerm {
  display: flex;
  flex-direction: column;
  gap: 14px;
  padding: 12px;
}

.bskblok {
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.bskblok__titel {
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 0.14em;
  color: var(--tx-3);
}

.bskbrikker {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}
/* Brikken er husets touchmål høj. En modtagerliste, man rammer
   ved siden af, sender beskeden til den forkerte. */
.bskbrik {
  min-height: var(--touch-min);
  padding: 8px 14px;
  border: 1px solid var(--line-1);
  border-radius: var(--r-xl);
  background: var(--bg-2);
  color: var(--tx-2);
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
}
/* Valgt kendes på fyld, kant OG tekstfarve — ikke på farve alene. */
.bskbrik.is-active {
  background: var(--orange-soft);
  border-color: var(--orange);
  color: var(--tx-1);
}
/* De brede valg står først og ser anderledes ud end et navn:
   «ALLE» og «Sofie» er ikke to punkter af samme slags. */
.bskbrik--bred {
  font-weight: 800;
  letter-spacing: 0.08em;
  border-style: dashed;
}
.bskbrik--rolle { font-style: italic; }

/* ------------------------------------------------------------
   DEN VIGTIGSTE LINJE

   Den står lige over Send, hvor øjet er, når fingeren er på vej.
   En massebesked er ikke til at kalde tilbage.
   ------------------------------------------------------------ */
.bskomfang {
  flex: 0 0 auto;
  display: flex;
  align-items: baseline;
  gap: 10px;
  padding: 12px 14px;
  border: 1px solid var(--orange);
  border-radius: var(--r-md);
  background: var(--orange-soft);
}
.bskomfang--tom {
  border-color: var(--line-1);
  background: var(--bg-2);
}
.bskomfang__mrk {
  flex: 0 0 auto;
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 0.14em;
  color: var(--tx-3);
}
.bskomfang__tekst {
  flex: 1 1 auto;
  font-size: 15px;
  font-weight: 700;
  color: var(--tx-1);
  overflow-wrap: anywhere;
}
.bskomfang--tom .bskomfang__tekst {
  font-weight: 600;
  color: var(--tx-3);
}

.bsksend {
  flex: 0 0 auto;
  min-height: var(--touch);
  font-size: 16px;
  font-weight: 800;
}

/* ---------- Historikken ---------- */
.bskrad {
  border-left: 3px solid var(--line-2);
}
.bskrad--vigtig   { border-left-color: var(--at-late); }
.bskrad--advarsel { border-left-color: var(--red); }

.bskrad__hoved {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  flex-wrap: wrap;
}
.bskrad__afsender { font-weight: 700; color: var(--tx-1); }
.bskrad__tid { font-size: 12px; color: var(--tx-3); }
.bskrad__tekst {
  margin: 6px 0;
  font-size: 15px;
  line-height: 1.45;
  color: var(--tx-1);
  overflow-wrap: anywhere;
}
.bskrad__fod {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  flex-wrap: wrap;
  font-size: 12px;
}
.bskrad__omfang { color: var(--tx-3); }
/* Egen læsestatus — ikke husets. Se «LÆST ER PR. MENNESKE». */
.bskrad__laest  { color: var(--tx-3); font-weight: 700; }
.bskrad__ulaest { color: var(--orange-tx); font-weight: 800; }

/* ============================================================
   KOBL BORDE SAMMEN

   «Regningen fylder bord 23 + 24» står øverst i dialogen. Uden
   den ville tjeneren tælle på skærmen bag vinduet for at finde
   ud af, hvad hun er ved at koble til.
   ============================================================ */
.koblnu {
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.koblnu__mrk {
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 0.14em;
  color: var(--tx-3);
}
.koblnu__borde {
  font-size: 18px;
  font-weight: 800;
  color: var(--tx-1);
}

.koblliste {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.koblrad {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  min-height: var(--touch);
  padding: 10px 14px;
  border: 1px solid var(--line-1);
  border-radius: var(--r-md);
  background: var(--bg-3);
  color: var(--tx-1);
  font-size: 15px;
  cursor: pointer;
  text-align: left;
}
/* Hovedbordet er ikke bare slået fra — det ser anderledes ud OG
   der står hvorfor ved siden af. En grå knap uden en grund er en
   gåde, og gåder løses ikke midt i en servering. */
.koblrad--hoved {
  background: var(--bg-2);
  border-style: dashed;
  cursor: default;
}
.koblrad__nr { font-weight: 700; }
.koblrad--hoved .koblrad__nr { color: var(--tx-2); }
.koblrad__note {
  font-size: 12px;
  color: var(--tx-3);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-weight: 700;
}

/* ============================================================
   PÅ BORDET ELLER PER STOL

   Ét spørgsmål, to store felter. Det stilles én gang, ved den
   første bon, midt i en servering — der skal kunne svares uden
   at sigte, og underteksten siger konsekvensen, ikke navnet igen.
   ============================================================ */
.regmodeller {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.regmodel {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 4px;
  min-height: 84px;
  padding: 14px 18px;
  border: 1px solid var(--line-2);
  border-radius: var(--r-md);
  background: var(--bg-3);
  cursor: pointer;
  text-align: left;
  width: 100%;
}
.regmodel__navn {
  font-size: 18px;
  font-weight: 800;
  letter-spacing: 0.06em;
  color: var(--tx-1);
}
.regmodel__under {
  font-size: 13px;
  color: var(--tx-2);
}

/* ============================================================
   SAML STOLE

   Store felter, ikke små ikoner. Stolestriben er husets smalleste
   række, og et greb eller et kædeikon dér ville være præcis det,
   briefen advarer imod.
   ============================================================ */
.stolgrupper {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.stolgruppe {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  min-height: var(--touch-min);
  padding: 8px 12px;
  border: 1px solid var(--orange);
  border-radius: var(--r-md);
  background: var(--orange-soft);
}
.stolgruppe__tekst {
  font-size: 15px;
  font-weight: 700;
  color: var(--tx-1);
}
.stolgruppe__ophaev { flex: 0 0 auto; min-height: var(--touch-min); }

.stolvalg {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(76px, 1fr));
  gap: 8px;
}
.stolfelt {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  min-height: 64px;
  border: 1px solid var(--line-1);
  border-radius: var(--r-md);
  background: var(--bg-3);
  color: var(--tx-1);
  cursor: pointer;
}
.stolfelt.er-valgt {
  background: var(--orange-soft);
  border-color: var(--orange);
}
/* Sidder stolen allerede i en gruppe, er kanten stiplet OG der
   står «med 3» på feltet. To kanaler, fordi `samlStole` smelter
   grupper sammen — man skal kunne se det, før man trykker. */
.stolfelt--gruppe { border-style: dashed; border-color: var(--orange); }
.stolfelt__nr { font-size: 20px; font-weight: 800; }
.stolfelt__note {
  font-size: 11px;
  color: var(--tx-2);
  font-weight: 700;
}
.stolsaml {
  min-height: var(--touch);
  font-size: 16px;
  font-weight: 800;
  width: 100%;
}

/* ---------- Stolestriben ----------
   `.kstoleblok` er vaek: striben og gruppesaetningen havde en
   faelles kappe, fordi de laa i en raekke for sig. Fra
   1. september 2026 staar striben i regningens hoved og
   saetningen under det — to steder, ingen kappe. */
/* Grupperne som en SÆTNING. Mærket på selve stolen er lille og
   rundt — det er ikke nok alene. */
.kstolgrupper {
  flex: 0 0 auto;
  font-size: 11.5px;
  font-weight: 700;
  color: var(--tx-2);
  padding: 0 2px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.kstol--gruppe { border-style: dashed; }

/* ------------------------------------------------------------
   EN STOL MED NOGET PAA SER ANDERLEDES UD

   Dennis, 1. september 2026: «knapper som er forskellige om der
   er vare paa stolen / bordet osv».

   Fyldt flade og lys skrift mod tom ramme. Det kan ses paa en
   armslaengde, uden at laese et tal — og det er graat, ikke
   groent eller orange: en stol med varer paa er ikke en handling
   og ikke penge, der flytter sig. Den er bare optaget.
   ------------------------------------------------------------ */
.kstol--fyldt:not(.er-valgt) {
  background: var(--bg-5);
  border-color: var(--line-strong);
  color: var(--tx-1);
}

/* Tallet i hjoernet. `position: absolute` inde i knappen, saa det
   ikke goer knappen bredere — der er 386 px til BORD, fire stole,
   to pile og et plus, og de er brugt. */
.kstol { position: relative; }
.kstol__antal {
  position: absolute;
  top: -3px; right: -3px;
  min-width: 16px; height: 16px;
  padding: 0 3px;
  border-radius: 999px;
  background: var(--accent);
  color: var(--accent-tx);
  font-size: 10px; font-weight: 800; line-height: 16px;
  text-align: center;
  pointer-events: none;
}
/* Paa den valgte stol er flaeden allerede accentfarvet — saa
   vender maerket om, ellers forsvinder det i sin egen baggrund. */
.kstol.er-valgt .kstol__antal {
  background: var(--accent-tx);
  color: var(--accent);
}

.kstol--gruppe { border-style: dashed; }

/* ---------- Bladringen ----------
   Pilene er ikke stole, og de maa ikke ligne nogen. Ingen ramme,
   daempet tekst — de er en retning, ikke et valg om hvem man
   taster til. Ved enden bliver de staaende og gaar ud: en pil,
   der forsvinder, flytter alle de andre knapper under fingeren. */
.kstol--blad {
  border-color: transparent;
  background: transparent;
  color: var(--tx-2);
  /* ------------------------------------------------------------
     PILEN ER OGSAA EN KNAP

     Her stod 22 px. Det var fra dengang beloebet delte linjen med
     striben og der kun var 242 px — men efter beloebet flyttede op
     i toplinjen har striben 386, og saa er der ingen undskyldning.

     `skaermscan` fangede den: «button.kstol.kstol--blad ›, b: 22,
     krav: 44». En bladring er noget, man goer med en tommelfinger
     hen over et bord, og en halv finger bred knap rammer man ved
     siden af — og saa vaelger man en stol i stedet.

     Regnestykket, der holder: BORD (61) + to pile (88) + fire
     stole (176) + mellemrum (36) = 361 af de 386. «+» staar kun
     paa sidste side, hvor hoejrepilen ikke er.
     ------------------------------------------------------------ */
  min-width: var(--touch-min);
  padding: 0;
  font-size: 17px;
}
.kstol--blad.er-slut { color: var(--tx-3); opacity: .35; }
/* Under PER STOL er BORD stadig et valg — bare ikke standarden.
   Den stiplede kant siger «det her er det fælles», så en vare,
   der skal på én stol, ikke havner der ved et uheld. */
.kstol--faelles:not(.er-valgt) {
  border-style: dashed;
  color: var(--tx-3);
}

/* Er stolen i en gruppe, staar «1+3» i selve nummeret — se noten
   i `payment.js`. Tallet bliver laengere, saa det skal kunne give
   sig i stedet for at klippe. */
.paystol--gruppe .paystol__nr {
  font-size: clamp(13px, 3.4cqw, 18px);
  letter-spacing: -0.01em;
}

/* ============================================================
   HVOR SKAL KVITTERINGEN UD?

   Kun på håndholdt. Fem printere i en café, og tjeneren står et
   nyt sted hver gang — så listen skal kunne læses og rammes med
   én finger, mens gæsten står og venter.

   Store felter i én søjle, ikke et gitter: rækkefølgen ER
   informationen (bar, ude, inde — husets egen), og en søjle
   læses i den rækkefølge, øjet allerede går.
   ============================================================ */
.prnvalg {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.prnfelt {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  min-height: var(--touch);
  padding: 12px 16px;
  border: 1px solid var(--line-2);
  border-radius: var(--r-md);
  background: var(--bg-3);
  color: var(--tx-1);
  font-size: 16px;
  font-weight: 700;
  text-align: left;
  cursor: pointer;
  width: 100%;
}
.prnfelt:active { background: var(--bg-4); }
/* «Sidst brugt» er en OPLYSNING, ikke et valg. Den flytter ikke
   printeren op i listen og forvælger ingenting — Dennis:
   «der skal spørges hver gang». Derfor dæmpet og lille: den
   hjælper med at genkende, den peger ikke. */
.prnfelt__navn { flex: 1 1 auto; min-width: 0; }
.prnfelt__sidst {
  flex: 0 0 auto;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--tx-3);
}

/* ------------------------------------------------------------
   DEN SAMME LISTE, NÅR MAN VÆLGER OM EFTER EN FEJL

   `printervalg` spørger «denne printer svarede ikke — hvor så?».
   Det er et andet spørgsmål end «hvor skal den ud?», men det er
   den samme liste af de samme maskiner, og den skal se ens ud.

   Statusteksten er printerens adresse, indtil nogen har prøvet
   den; derefter online eller offline. Aldrig farve alene —
   ordet står der.
   ------------------------------------------------------------ */
.prnfelt__status {
  flex: 0 0 auto;
  font-size: 13px;
  color: var(--tx-3);
  font-weight: 600;
}
.prnfelt__status--online  { color: var(--green); }
.prnfelt__status--offline { color: var(--red-tekst); }

/* ============================================================
   RÆKKEFØLGEN PÅ PRINTERSIDEN

   En håndholdt spørger hver gang, hvor kvitteringen skal ud — og
   tjeneren går rundt i hele caféen. Står printerne i den
   rækkefølge, hun bevæger sig, rammer hun rigtigt uden at læse.

   Pile og ikke et talfelt: et tal skal oversættes i hovedet, en
   pil skal bare trykkes. Og der er ingen at skrive forkert.
   ============================================================ */
.prnraekke {
  display: flex;
  align-items: center;
  gap: 10px;
}
.prnorden {
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.prnorden__pil {
  /* `--touch-min` i højden ville gøre kortet 88 px højt alene af
     to pile. De sidder to og to over hinanden og deler den
     højde — 30 px hver, med hele bredden som ramme. Det er under
     husets fingermål, og det er et bevidst valg: rækkefølgen
     sættes én gang, når huset sættes op, ikke midt i en
     servering. */
  min-height: 30px;
  min-width: 44px;
  padding: 0;
  border: 1px solid var(--line-2);
  border-radius: var(--r-sm);
  background: var(--bg-3);
  color: var(--tx-2);
  font-size: 12px;
  line-height: 1;
  cursor: pointer;
}
.prnorden__pil:active:not(:disabled) { background: var(--bg-4); }
/* En pil, der ikke kan gøre noget, skal kunne SES som slukket —
   ikke opdages ved at trykke. */
.prnorden__pil:disabled { opacity: .3; cursor: default; }


/* ============================================================
   §12 · LOGIN MED BORDPLANEN VED SIDEN AF

   Kun paa kassefladen — se noten i `login.js`. Planen faar
   pladsen, login faar en spalte i husets sædvanlige bredde.
   ============================================================ */
.login--medplan { min-height: 0; }
.login__plan {
  flex: 1 1 auto;
  min-width: 0;
  min-height: 0;
  border-right: 1px solid var(--line-1);
}
.login__side {
  /* 380 px var husets sædvanlige spaltebredde. Dennis, 2.
     september 2026: «et lidt mindre TJENERNUMMER område» — og
     pladsen går til bordplanen, som er dét, man kigger på. */
  flex: 0 0 300px;
  min-height: 0;
  display: flex;
  flex-direction: column;
  gap: var(--sp-4);
  padding: var(--sp-4);
}
/* ------------------------------------------------------------
   TALRAEKKEN FYLDER MINDRE PAA LOGINSKAERMEN

   Fingermaalet holdes — 48 px er over husets `--touch-min` paa
   44 — men tasterne behoever ikke vaere 76 px hoeje her. Det er
   fire cifre, ikke en bestilling.
   ------------------------------------------------------------ */
/* Laeseren skal kunne skrive i feltet — derfor `clip` og ikke
   `display: none`. Et skjult felt kan ikke faa fokus, og saa var
   brikkerne holdt op med at virke. */
.login__rfidskjult {
  position: absolute;
  /* Uden et holdepunkt satte `position: absolute` feltet dér,
     hvor det stod i floedet — og paa 428 px laa det saa langt
     til hoejre, at siden fik en vandret rullebjaelke. MAALT
     12. september 2026: `vandretRul(1): div.login__rfidskjult`
     paa baade login og betaling.

     `left: 0; top: 0` binder det til hjoernet. Det bliver ved
     med at kunne faa fokus — det er hele grunden til `clip-path`
     og ikke `display: none`, for en laeser skal kunne skrive i
     et felt, ingen kan se. */
  left: 0; top: 0;
  width: 1px; height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}
.login__tal .keypad__grid .key { min-height: 46px; font-size: 20px; }
.login__tal .keypad__display { height: 48px; font-size: 24px; }
.login__tal .keypad { gap: var(--sp-2); }
.login__tal .btn--lg { min-height: 52px; }

/* Bordet, der venter paa et navn. Orange som husets egne
   bordmaerker — det er dét bord, der bliver aabnet. */
.login__venter {
  border-color: var(--orange);
  background: var(--orange-soft, transparent);
}

/* ============================================================
   REGNINGSARKIVETS RÆKKE PÅ EN TELEFON

   Rækken har fire kolonner, hvoraf tre har en fast mindstebredde
   (104 + 128 + 96 px). På 428 px er der ikke plads til den
   fjerde, og et `flex: 1`-felt krymper ikke under sit eget
   indhold — så rækken voksede ud over kortet, og arkivet kunne
   skubbes sidelæns.

   Målt 2. september på 428×926 med otte bonner i arkivet:
   `vandretRul`, fire rækker, 17 px overskud hver. Et TOMT arkiv
   viste ingenting — fejlen fandtes først, da der var solgt noget.

   Her ombrydes rækken: nummer, beløb og status står på første
   linje, bordet med tjener og kasse får hele bredden nedenunder.
   `min-width: 0` gør, at en usædvanlig lang tekst klippes med en
   ellipse i stedet for at skubbe.

   KUN på den smalle flade. En kasseskærm har plads til alle fire
   kolonner og er uændret. Se noten ved `raekke()` i
   `regningsarkiv.js`.
   ============================================================ */
:root[data-pos-bredde="smal"] .arkivraekke { flex-wrap: wrap; }
:root[data-pos-bredde="smal"] .arkivraekke > * { order: 1; }
:root[data-pos-bredde="smal"] .arkivraekke__hvem {
  order: 2;
  flex: 1 0 100%;
  min-width: 0;
}
:root[data-pos-bredde="smal"] .arkivraekke__hvem > div {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ============================================================
   TOPRÆKKEN — STOLENE OG SEND-BJÆLKEN DELER LINJEN

   Dennis, 5. september 2026: «have send og vent op over
   regningen, på linje med stolene, men i sit eget felt i samme
   bredde som regningen.»

   Bjælken får nøjagtig regningsspaltens bredde, så den står lige
   over listen, den handler om. Tallet kommer fra `.kasse__side`
   — ét sted, så de to ikke kan komme fra hinanden, når huset
   skifter skærmprofil.

   Bliver skærmen for smal til begge, ruller stolene vandret. Det
   er stolene, der giver sig, ikke bjælken: man kan swipe efter
   stol fire, men «Send bon» skal ligge samme sted hver gang.
   ============================================================ */
.kasse__toprakke {
  align-items: stretch;
  min-width: 0;
  /* Samme indrykning og samme mellemrum som kroppen nedenunder —
     ellers står bjælken ti pixels ude af flugt med spalten, den
     hører til, og det ses med det samme på en mørk flade. */
  padding: 0 10px;
  gap: 10px;
}
.kasse__toprakke > .flex-1 {
  min-width: 0;
  overflow-x: auto;
  scrollbar-width: thin;
}
.kasse__toprakke .panel--gaester {
  min-width: max-content;
}
.kasse__sendbjaelke {
  /* Bjaelken staar nu INDE i regningens spalte (se noten ved
     `kasse__toprakke` i `posScreen.js`), og saa er spaltens egen
     bredde bjaelkens bredde. Foer laa den i en fuldbred raekke og
     skulle selv holde maalet. */
  flex: 0 0 auto;
  width: 100%;
  margin-bottom: 8px;
  align-items: stretch;
}
.kasse__sendbjaelke > .btn { min-height: var(--touch-min, 44px); }

/* Er stolene der ikke, skal bjælken stadig ligge i sin spalte —
   ikke midt på fladen. */
.kasse__toprakke > .flex-1:empty { flex: 1 1 auto; }


/* ============================================================
   NYT OG SENDT — SÅ DET ER TIL AT SE, NÅR ET BORD ÅBNES

   Dennis, 17. oktober 2026: «tydelig markering af produkter der er
   sendt afsted, så når man åbner et bord og bonner nye varer, skal
   man tydeligt kunne se hvad der er nyt og hvad der allerede er
   sendt afsted.»

   Tre ting, der hver for sig er nok, og sammen ikke kan overses:
     1. et NY-mærke på hver vare, der ikke er sendt
     2. en streg med «NYT — ikke sendt endnu» mellem sendt og nyt
     3. en svag orange bund på de nye varer

   Farven står aldrig alene: mærket og stregen har tekst.
   ============================================================ */
.kline__ny {
  flex: 0 0 auto;
  margin-left: 6px;
  font-size: 10px; font-weight: 900; letter-spacing: .8px;
  line-height: 1;
  padding: 3px 5px;
  border-radius: 4px;
  background: var(--orange); color: var(--tx-inv);
}
.kline--unsent { background: var(--orange-soft); }

.knyskel {
  display: flex; align-items: center; gap: 8px;
  min-height: 26px; padding: 0 4px; margin: 6px 0 3px;
  user-select: none;
}
.knyskel__mrk {
  font-size: 10px; font-weight: 900; letter-spacing: 1.6px;
  color: var(--tx-inv); background: var(--orange);
  border-radius: 4px; padding: 2px 6px; line-height: 1;
}
.knyskel__tekst {
  font-size: 10px; font-weight: 800; letter-spacing: 1px;
  text-transform: uppercase; color: var(--orange); white-space: nowrap;
}
.knyskel__streg { flex: 1 1 auto; height: 2px; background: var(--orange); opacity: .6; }

/* ============================================================
   GENÅBNET KØKKENBESTILLING

   Bjælken øverst i regningen. Huset har kun printere, så den siger
   aldrig »på pause« — kun hvad kassen gjorde og hvad printeren
   svarede. Farven står aldrig alene: titlen er tekst.

     gul   afventer afklaring — gå ud og sig det
     rød   STOP-bon IKKE sendt, eller køkkenets tid er gået
     rolig samlet bon / GENOPTAG sendt
   ============================================================ */
.genbar {
  flex: 0 0 auto;
  display: flex; flex-direction: column; gap: 6px;
  padding: 8px 10px;
  border-radius: var(--r-sm);
  border: 1px solid var(--line-1);
  border-left-width: 6px;
  background: var(--bg-3);
  color: var(--tx-1);
  min-width: 0;
}
.genbar--afklaring { border-color: var(--yellow); background: rgba(232, 192, 32, 0.12); }
.genbar--fare      { border-color: var(--red); background: var(--red-soft); }
.genbar--info      { border-color: var(--green); }
.genbar__titel {
  font-size: 11.5px; font-weight: 900; letter-spacing: .8px;
  text-transform: uppercase;
}
.genbar--afklaring .genbar__titel { color: var(--yellow); }
.genbar--fare .genbar__titel { color: var(--tx-neg); }
.genbar--info .genbar__titel { color: var(--tx-pos); }
.genbar__tekst { font-size: 13.5px; font-weight: 600; line-height: 1.4; }
.genbar__advarsel {
  font-size: 13px; font-weight: 800; line-height: 1.4;
  color: var(--orange-tx);
}
.genbar__paamindelse {
  font-size: 13px; font-weight: 800; line-height: 1.4;
  color: var(--tx-neg);
}
.genbar__knapper { display: flex; gap: 8px; flex-wrap: wrap; }
.genbar__knap { flex: 1 1 140px; min-height: 48px; font-size: 14px; white-space: normal; line-height: 1.2; }

/* ------------------------------------------------------------
   QA 17c — regningslisten må ikke fortrænges af notitiekortet (1280 × 800)
   Kortet kan skrumpe og ruller selv; listen holder en mindstehøjde. Fold-knappen
   (kun hvor kaldet beder om den) skjuler teksten, men aldrig knapperne.
   ------------------------------------------------------------ */
.genbar__hoved { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.genbar__hoved .genbar__titel { flex: 1 1 auto; min-width: 0; }
.genbar__fold { flex: 0 0 auto; min-height: 44px; font-size: 12.5px; white-space: nowrap; }
/* Sammenfoldet: titel, knapper og «Mere» på ÉN række (≈ 52 px), teksten er ét tryk væk */
.genbar.is-foldet { flex-direction: row; align-items: center; flex-wrap: nowrap; padding: 4px 8px; gap: 6px; }
.genbar.is-foldet .genbar__hoved { display: contents; }
.genbar.is-foldet .genbar__titel { order: 0; flex: 0 1 28%; font-size: 10.5px; line-height: 1.2; letter-spacing: .4px; }
.genbar.is-foldet .genbar__knapper { order: 1; flex: 1 1 auto; flex-wrap: nowrap; gap: 6px; }
.genbar.is-foldet .genbar__knap { flex: 1 1 0; min-height: 44px; font-size: 12.5px; padding: 2px 6px; }
.genbar.is-foldet .genbar__fold { order: 2; min-width: 56px; padding: 2px 8px; }
.panel--regning > .genbar { flex: 0 1 auto; min-height: 0; overflow-y: auto; }
.panel--regning > .medpile { flex: 1 0 88px; min-height: 88px; }

/* »Genåbn køkkenbestilling« er et langt ord i en lille tast. */
.funk--lang { line-height: 1.1; white-space: normal; }
:root[data-pos-flade="klassisk"][data-pos-funktioner="bund"] .funkblok--lodret > .funk--lang { grid-column: span 2; }

/* ============================================================
   PRINTSIMULERING — OVERLAYET

   Når serveren simulerer print, vises hver udskrift her i stedet
   for på papir (src/ui/components/printsimulering.js). Båndet og
   kortene ligger OVER alt andet i huset — også over modaler og
   toasts (9999 er det højeste ellers).

   Kortets HOVED står uden for papirstrimlen, så «SIMULERET ·
   IKKE PRINTET» aldrig kan forveksles med noget, der står PÅ
   bonnen. Strimlen er hvid med sort tekst, som papir.
   ============================================================ */
/* TEMAFAST — overlayet er en advarsel og et stykke papir: gul/sort og hvidt papir følger ikke temaet */
.psim { position: fixed; inset: 0; z-index: 10050; pointer-events: none; }

/* QA-14b fund 4: båndet er en fuldbredde STRIBE øverst på ALLE skærme (før: en midterstillet flig, der på
   en bred skærm lå oven på kassens egne bannere). Appen holder plads til det (--psim-top). Er testmodus også til,
   står de to side om side i ÉN stribe — se «STATUSBÅNDET» nederst. */
.psim__baand {
  position: fixed; top: env(safe-area-inset-top, 0px); left: 0; right: 0;
  z-index: 10060; box-sizing: border-box;
  padding: 3px 14px;
  background: repeating-linear-gradient(-45deg, #ffd400 0 12px, #f2c200 12px 24px);
  color: var(--tx-inv);
  font: 800 12px/1.5 var(--mono);
  letter-spacing: .6px; text-align: center;
  border: 0; border-bottom: 2px solid #111;
  box-shadow: 0 2px 8px rgba(0,0,0,.5);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  pointer-events: none;
}

/* Print venter, fordi kassen ikke ved, om der simuleres: rødt, ikke gult */
.psim__baand--venter {
  background: repeating-linear-gradient(-45deg, #e5484d 0 12px, #c8363b 12px 24px);
  color: #fff; border-color: #fff;
}

/* C1: den store advarsel, mens printflaget er ukendt og bonner holdes i kø.
   Rødt kort under båndet; rører ikke trykfladen under sig (pointer-events). */
.psim__ukendt {
  position: fixed; top: calc(34px + var(--tm-top, 0px)); left: 50%; transform: translateX(-50%);
  z-index: 10058;
  width: min(560px, calc(100vw - 24px));
  padding: 10px 16px 12px;
  background: #b3262b; color: #fff;
  border: 3px solid #fff; border-radius: 12px;
  box-shadow: 0 6px 22px rgba(0,0,0,.6);
  text-align: center;
  pointer-events: none;
}
.psim__ukendt-titel { font: 800 18px/1.3 var(--font, system-ui, sans-serif); }
.psim__ukendt-tekst { margin-top: 4px; font: 500 13px/1.4 var(--font, system-ui, sans-serif); }

.psim__raekke, .psim__panel { pointer-events: auto; }
.psim__panel {
  position: fixed; left: 12px;
  bottom: calc(env(safe-area-inset-bottom, 0px) + 6px + 44px + 6px);
  width: min(380px, calc(100vw - 24px));
  max-height: calc(100vh - 120px);
  overflow-y: auto; overscroll-behavior: contain;
  z-index: 10055;
}

/* RÆKKEN: én linje, højst 44 px. Dækker ingen knapper i standardtilstanden. */
/* QA-14b fund 5: rækken ligger UNDER bundnavigationen på alle skærme, og appen holder plads til den
   (--psim-reserve-bund). Før svævede den over indholdet på en bred skærm og dækkede «Kontant», «Tilbage»
   og den nederste række varer. */
.psim__raekke {
  position: fixed; left: 12px;
  bottom: calc(env(safe-area-inset-bottom, 0px) + 6px);
  width: min(560px, calc(100vw - 24px));
  height: 44px; box-sizing: border-box;
  display: flex; align-items: center; gap: 8px;
  padding: 1px 6px;
  background: #111; border: 2px solid #ffd400; border-radius: 10px;
  box-shadow: 0 4px 14px rgba(0,0,0,.5);
}
.psim__chips {
  flex: 1 1 auto; min-width: 0; height: 100%;
  display: flex; align-items: center; gap: 6px;
  overflow-x: auto; overflow-y: hidden; scrollbar-width: none;
}
.psim__chips::-webkit-scrollbar { display: none; }
.psim__chip {
  flex: 0 0 auto; display: flex; align-items: stretch;
  height: 38px; box-sizing: border-box; background: #ffd400; color: #111;
  border: 2px solid #111; border-radius: 8px; overflow: hidden;
  font: 700 12px/1 var(--mono);
}
.psim__chip--aaben { background: #fff3a0; border-color: #ffd400; box-shadow: 0 0 0 2px #fff; }
.psim__chip--gamle { padding: 0 10px; align-items: center; cursor: pointer; }
.psim__chipknap {
  display: flex; align-items: center; gap: 8px;
  padding: 0 8px; background: none; border: 0; color: inherit;
  font: inherit; cursor: pointer; min-width: 0; max-width: 300px;
}
.psim__chiptitel { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 150px; font-weight: 900; }
.psim__chipmeta { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 130px; font-weight: 600; }
.psim__pil { font-weight: 900; }
.psim__chipluk {
  width: 32px; background: #111; color: #ffd400; border: 0;
  font: 900 18px/1 var(--mono); cursor: pointer;
}
.psim__antal { flex: 0 0 auto; color: #ffd400; font: 800 11px/1 var(--mono); white-space: nowrap; }
.psim__lukalle, .psim__flere {
  flex: 0 0 auto; height: 38px; padding: 0 10px;
  background: #ffd400; color: #111;
  border: 2px solid #111; border-radius: 8px;
  font: 800 12px/1 var(--mono); cursor: pointer; white-space: nowrap;
}
.psim__flere { background: #111; color: #ffd400; border-color: #ffd400; }

.psim__kort {
  background: #1b1b1b; color: #f2f2f2;
  border: 3px solid #ffd400; border-radius: 12px;
  box-shadow: 0 10px 30px rgba(0,0,0,.6);
  overflow: hidden;
  flex: 0 0 auto;
}
.psim__hoved {
  position: relative;
  padding: 8px 46px 8px 12px;
  background: #ffd400; color: #111;
}
.psim__maerke { font: 900 13px/1.2 var(--mono); letter-spacing: .8px; }
.psim__titel  { font: 800 13px/1.3 var(--mono); margin-top: 3px; overflow-wrap: anywhere; }
.psim__meta   { font: 600 11.5px/1.3 var(--mono); margin-top: 2px; }
.psim__skjul {
  position: absolute; bottom: 4px; right: 6px;
  min-height: 28px; padding: 0 8px;
  background: #111; color: #ffd400; border: 2px solid #111; border-radius: 6px;
  font: 800 11px/1 var(--mono); cursor: pointer;
}
.psim__luk {
  position: absolute; top: 4px; right: 4px;
  width: 40px; height: 40px;
  background: #111; color: #ffd400;
  border: 2px solid #111; border-radius: 8px;
  font: 900 22px/1 var(--mono); cursor: pointer;
}

.psim__papir {
  padding: 10px;
  background: #3a3a3a;
  max-height: 46vh; overflow: auto;
}
.psim__strimmel {
  /* `width: Wch` sættes pr. kort. 12px mono ⇒ én kolonne ≈ 7,2 px. */
  margin: 0 auto;
  box-sizing: content-box;
  padding: 10px 8px 12px;
  background: #fbfbf6; color: #000;
  font: 400 12px/1.25 var(--mono);
  font-variant-ligatures: none;
  box-shadow: 0 0 0 1px rgba(0,0,0,.3), 0 4px 10px rgba(0,0,0,.4);
  max-width: none;
}
.psim__linje { white-space: pre; text-align: left; min-height: 1.25em; }
/* Hver del er et felt af fast størrelse; teksten indeni strækkes (se delNode) */
.psim__del { display: inline-block; vertical-align: top; overflow: visible; white-space: pre; line-height: 1.25; text-align: left; }
.psim__tegn { display: inline-block; transform-origin: 0 0; white-space: pre; }
.psim__linje--midt   { text-align: center; }
.psim__linje--hoejre { text-align: right; }
.psim__klip {
  margin: 8px -8px; border-top: 2px dashed #666;
  text-align: center; font: 600 10.5px/1.6 var(--mono); color: #666;
}
.psim__note {
  pointer-events: none;
  margin: 6px 0; padding: 3px 6px;
  border: 1px dashed #888; border-radius: 4px;
  background: #eef0f6; color: #223;
  font: italic 600 11px/1.4 var(--mono);
  white-space: normal;
}
.psim__note--ukendt { background: #ffe1e1; color: #8a0000; border: 2px solid #c00; font-style: normal; font-weight: 800; }
.psim__advarsel {
  padding: 6px 10px; background: #ffe1e1; color: #8a0000;
  font: 800 12px/1.3 var(--mono);
}
.psim__browser { padding: 10px; background: #fff; color: #000; max-height: 46vh; overflow: auto; }

/* ------------------------------------------------------------
   SMAL SKÆRM (telefon): stakken i fuld bredde nederst

   Samme udseende som på den håndholdte flade (`body.hh`, se
   haandholdt.css), men kendt på BREDDEN: den kompakte kasseflade på
   en telefon har ikke `body.hh`. Den har en bundbjælke, som stakken
   skal ligge over — samme løft som `.toast-host`.
   ------------------------------------------------------------ */
@media (max-width: 640px) {
  .psim__raekke { left: 8px; right: 8px; width: auto; }
  .psim__panel {
    left: 8px; right: 8px; width: auto;
    max-height: calc(100vh - 100px);
  }
  .psim__papir { max-height: 36vh; }
  .psim__baand { font-size: 11px; padding: 2px 10px; }
  .psim__ukendt { top: calc(28px + var(--tm-top, 0px)); padding: 8px 12px 10px; }
  .psim__ukendt-titel { font-size: 15px; }
  .psim__ukendt-tekst { font-size: 12px; }
  .psim__antal { display: none; }
  .psim__chipknap { gap: 5px; padding: 0 6px; }
  .psim__chiptitel { max-width: 78px; }
  .psim__chipmeta { max-width: 104px; }
}

@media print { .psim { display: none !important; } }
/* TEMAFAST SLUT */

/* ============================================================
   BELØBSFLADE — TEKST TIL VENSTRE, ET KOMPAKT TASTATUR TIL HØJRE

   QA-003 (18. oktober 2026): Betal › Beløb og Gavekort › Sælg lod
   tastaturet fylde hele bredden. Tre kolonner à 400 px blev til
   68 px høje taster, og rækken med 0 og knappen under dem lå under
   bundbjælken — felt, taster og knap kunne ikke ses på én gang.

   Tastaturet har nu en fast bredde, og taster og felt har en
   højde, der får hele tastaturet — felt, fire rækker og knappen —
   ind i de ca. 410 px, der er over bundbjælken på 1280 x 800.
   ============================================================ */
.beloebflade {
  display: flex;
  align-items: flex-start;
  gap: var(--sp-5, 24px);
}
.beloebflade__tekst { flex: 1 1 0; min-width: 0; }
.beloebflade > .keypad {
  flex: 0 1 440px;
  width: 440px;
  max-width: 100%;
  gap: var(--sp-2);
}
.beloebflade .keypad__display { height: 54px; font-size: 28px; }
.beloebflade .keypad__msg { min-height: 18px; }
.beloebflade .keypad__grid { gap: 6px; }
.beloebflade .keypad__grid .key { min-height: 52px; font-size: 22px; }
.beloebflade .keypad .key { min-height: 52px; }
.beloebflade .keypad .btn--lg { min-height: 52px; }
@media (max-width: 720px) {
  .beloebflade { flex-direction: column; align-items: stretch; gap: var(--sp-3); }
  .beloebflade > .keypad { flex: none; width: auto; }
}

/* ============================================================
   GAVEKORT › SÆLG — TO KOLONNER (QA-008)

   Type, kortkode og modtager til venstre. Beløb, kompakt tastatur og
   «Sælg gavekort» til højre, så knappen ligger lige under tastaturet
   og kan trykkes uden at scrolle (1280 x 800, 1440 x 900). På smalle
   skærme ligger kolonnerne under hinanden, og knappen er sticky i
   bunden af rullefladen.
   ============================================================ */
.gksalg {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 440px);
  gap: var(--sp-5, 24px);
  align-items: start;
}
.gksalg__venstre, .gksalg__hoejre { min-width: 0; }
.gksalg__hoejre .keypad { gap: var(--sp-2); }
.gksalg__hoejre .keypad__display { height: 54px; font-size: 28px; }
.gksalg__hoejre .keypad__msg { min-height: 18px; }
.gksalg__hoejre .keypad__grid { gap: 6px; }
.gksalg__hoejre .keypad__grid .key,
.gksalg__hoejre .keypad .key { min-height: 52px; font-size: 22px; }
.gksalg__hoejre .keypad .key--fn { font-size: 17px; }
/* Kommaraekken (hideSubmit) behoever ikke en hel tast i hoejden */
.gksalg__hoejre .keypad > .row .key { min-height: 44px; }
/* Knappen staar altid over bundbjaelken, uanset hvor langt der er scrollet */
.gksalg__saelg {
  position: sticky;
  bottom: 0;
  z-index: 2;
}
@media (max-width: 860px) {
  .gksalg { grid-template-columns: minmax(0, 1fr); gap: var(--sp-4); }
}

/* ============================================================
   GAVEKORT › INDLØS — BOGSTAVTASTATUR (QA-007)
   Koder som AAAA-BBBB-CCCC-DDDD kan ikke tastes på et taltastatur.
   ============================================================ */
.kodetastatur { display: flex; flex-direction: column; gap: 6px; max-width: 760px; }
.kodetastatur__raekke { display: flex; gap: 6px; justify-content: center; }
.key--kode { flex: 1 1 0; min-width: 0; min-height: 48px; font-size: 20px; padding: 0; }
.key--kode.key--fn { flex: 1.6 1 0; font-size: 16px; }

/* ============================================================
   LOGINSKÆRMENS NEUTRALE BORDPLAN (QA-005, 18. oktober 2026)

   Kun nummer og ledigt/optaget. Ledigt er tomt og stiplet (som
   altid); optaget er fyldt med husets accentfarve — farven er den
   eneste kanal, så ordet «Optaget» står også på listekortet.
   ============================================================ */
.pv__bord--neutral { cursor: pointer; }
.pv__bord--neutral .pv__navn { font-weight: 700; }
.pv__bord--neutral.pv__bord--optaget {
  background: color-mix(in srgb, var(--accent) 28%, var(--bg-3));
  border-style: solid;
  border-color: var(--accent);
  color: var(--tx-1);
}
.tablecard--neutral { cursor: pointer; }
.tablecard--optaget-neutral {
  background: color-mix(in srgb, var(--accent) 22%, var(--bg-3));
  border-color: var(--accent);
}
.floor__baand--neutral { gap: 12px; }
/* Før husets svar er kommet, er et bord hverken ledigt eller optaget (QA 17c): neutral, stiplet, dæmpet */
.pv__bord--neutral.pv__bord--ukendt,
.tablecard--ukendt-neutral {
  background: var(--bg-1);
  border-style: dotted;
  border-color: var(--line-1);
  color: var(--tx-3);
  opacity: .7;
}

/* ============================================================
   iPHONE-QA (18. oktober 2026) — RETTELSER, DER KUN RAMMER EN TELEFON
   Rapport: docs/qa/mobil-iphone-2026-10-18.md

   Alt herunder er målt i en emuleret iPhone (390 × 844, 390 × 664,
   844 × 390, 320 × 568) og rører hverken domæne, betaling eller
   login — kun mål, afstande og hvem der ligger oven på hvem.
   ============================================================ */

/* ---------- Printsimuleringen tager sin egen plads (M-01, M-02) ----------
   `--psim-top` og `--psim-reserve-bund` sættes af printsimulering.js og er
   0 på en bred skærm og uden simulering. Se begrundelsen dér. */
:root { --psim-top: 0px; --psim-reserve-bund: 0px; --tm-top: 0px; --psim-raekke-plads: 56px; }

.app-root {
  padding-top: calc(env(safe-area-inset-top) + var(--psim-top, 0px) + var(--tm-top, 0px));
  padding-bottom: var(--psim-reserve-bund, 0px);
}
.modal-backdrop {
  padding-top: calc(var(--sp-4) + env(safe-area-inset-top) + var(--psim-top, 0px) + var(--tm-top, 0px));
  padding-bottom: calc(var(--sp-4) + env(safe-area-inset-bottom) + var(--psim-reserve-bund, 0px));
}
@media (max-width: 639px) {
  .modal-backdrop {
    padding-top: calc(8px + env(safe-area-inset-top) + var(--psim-top, 0px) + var(--tm-top, 0px));
    padding-bottom: calc(8px + env(safe-area-inset-bottom) + var(--psim-reserve-bund, 0px));
  }
}
body:has(.modal-backdrop) .toast-host,
:root[data-pos-flade="kompakt"] body:has(.modal-backdrop) .toast-host {
  top: calc(16px + env(safe-area-inset-top) + var(--psim-top, 0px) + var(--tm-top, 0px));
}
:root[data-pos-flade="kompakt"] .toast-host {
  bottom: calc(var(--kbund-hoejde) + var(--sp-4) + env(safe-area-inset-bottom) + var(--psim-reserve-bund, 0px));
}

/* TEMAFAST — simuleringsbåndet er en advarsel: gul/sort følger ikke temaet (som resten af .psim) */
@media (max-width: 640px), (max-height: 500px) {
  .psim__baand {
    padding: 2px 8px;
    font-size: 11px; line-height: 16px; letter-spacing: .3px;
  }
  /* Rækken ligger nederst, UNDER bundmenuen, og appen holder plads til den. */
  :root { --psim-raekke-plads: 68px; }
  .psim__raekke { height: 56px; }
  .psim__chip { height: 48px; }
  .psim__chipknap { min-height: 44px; }
  .psim__chipluk { width: 44px; }
  .psim__lukalle, .psim__flere { height: 44px; min-width: 44px; }
  /* Kortets hoved: × øverst til højre, «Fold sammen» i eget linje under teksten
     (de lå oven på hinanden, da begge blev 44 px). */
  .psim__hoved { padding-right: 60px; }
  .psim__luk { width: 44px; height: 44px; }
  .psim__skjul { position: static; display: block; margin-top: 8px; min-height: 44px; padding: 0 14px; }
  .psim__panel {
    bottom: calc(env(safe-area-inset-bottom, 0px) + 6px + 56px + 6px);
    max-height: calc(100vh - var(--psim-top, 0px) - var(--tm-top, 0px) - env(safe-area-inset-bottom, 0px) - 80px);
    max-height: calc(100dvh - var(--psim-top, 0px) - var(--tm-top, 0px) - env(safe-area-inset-bottom, 0px) - 80px);
  }
  .psim__papir { max-height: 36vh; max-height: 36dvh; }
  /* Under en åben række sidder bundmenuen ikke over hjemmelinjen — rækken gør. */
  .psim-raekke .kbund { padding-bottom: 0; }
}

/* En chip har kun plads til sin titel på en smal skærm; printer og klokkeslæt står på kortet. */
@media (max-width: 640px) {
  .psim__chipmeta { display: none; }
  .psim__chiptitel { max-width: 150px; }
}

/* TEMAFAST SLUT */

/* ---------- Tallet i hjørnet af AFSLUT dækker ikke ordet (M-05) ---------- */
.kbund__maerke {
  top: 3px; right: 3px;
  min-width: 22px; height: 22px; line-height: 22px; padding: 0 6px;
  font-size: 12px;
}

/* ---------- Dialogens fod tager mindre plads på en kort telefonskærm (M-06) ----------
   I en Safari-fane er en iPhone 14 kun 664 px høj. Kontantdialogens fod
   (GENNEMFØR · BEHOLD RESTEN · Annullér, tre knapper under hinanden) tog 215 px, og
   taltastaturet fik 50 px at rulle i. Her står de to sekundære knapper side om side under
   den primære, og hovedet er smallere. Samme knapper, samme rækkefølge, samme mål (≥ 48 px). */
/* QA-14b P1-G: grænsen på 760 px i højden er fjernet — på en iPhone med sikkerhedsområder (844 px) tog de tre bundknapper stadig
   215 px, og taltastaturets række 4-6 blev skåret af. Samme fod på hele den smalle skærm. */
@media (max-width: 639px) {
  :root[data-pos-bredde="smal"] .modal__foot {
    display: grid; grid-template-columns: 1fr 1fr; gap: 8px; padding: 8px 12px;
  }
  :root[data-pos-bredde="smal"] .modal__foot .btn {
    width: auto; min-width: 0 !important; min-height: 48px; padding-top: 6px; padding-bottom: 6px;
  }
  :root[data-pos-bredde="smal"] .modal__foot .btn:last-child { grid-column: 1 / -1; order: -1; }
  :root[data-pos-bredde="smal"] .modal__foot .btn:nth-last-child(2):nth-child(odd) { grid-column: 1 / -1; }
  .modal__head { padding-top: 8px; padding-bottom: 8px; }
}

/* ---------- Et varenavn i regningen må fylde to linjer på en smal skærm (M-07) ----------
   «Friskbrygget k…» og «Jakobs Ched…» var skåret af med «…», så to forskellige varer
   kunne se ens ud. Linjens højde ændres ikke: 2 × 14.5 px × 1.15 ≤ knappernes 44 px. */
@container pos (max-width: 639px) {
  .kline__navn {
    white-space: normal; overflow-wrap: break-word;
    display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2;
    line-height: 1.15;
  }
}
/* 320 px (Playwrights «iPhone SE», den gamle 1. generation): antal, NY-mærke og pris æder navnets plads, så
   «Jakobs» blev brudt til «Jako / bs…». Mærker og mellemrum krymper, så navnet får ~20 px mere. */
@container pos (max-width: 359px) {
  .kline { gap: 4px; }
  .kline__ny { font-size: 9px; padding: 1px 4px; }
  .kline__antal { min-width: 20px; margin-left: 2px; font-size: 13px; }
  .kline__pris { font-size: 13px; }
}

/* ---------- Felter skal være mindst 16 px, ellers zoomer Safari ind ved fokus (M-08) ----------
   Målt: RFID-feltet på loginskærmen (15 px) og printervalgene (14 px). Zoomer iOS ind, er
   siden ikke længere i passform, og man skal knibe sig ud igen midt i en servering. */
@media (max-width: 639px), (max-height: 500px) {
  input:not([type=checkbox]):not([type=radio]):not([type=range]):not([type=color]),
  select, textarea { font-size: 16px !important; } /* !important: skærme sætter fontSize som inline-stil */
}

/* ============================================================
   APP OG SYNKRONISERING + «NY VERSION KLAR» (iPhone/PWA, 18. oktober 2026)
   Se src/ui/screens/appsynk.js. Kun farvetokens — ingen hårdkodede farver.
   ============================================================ */
.opd-baand {
  flex: 0 0 auto; display: flex; align-items: center; justify-content: center;
  width: 100%; min-height: 44px; padding: 8px 12px;
  background: var(--blue); color: var(--tx-inv);
  border: 0; border-bottom: 2px solid var(--line-2);
  font-size: 14px; font-weight: 800; line-height: 1.25; text-align: center;
  cursor: pointer;
}
.opd-baand:active { filter: brightness(1.15); }
.opd-baand--kraever { background: var(--red); color: var(--tx-1); }

/* ============================================================
   LOGIN TIL TEST-ADRESSEN (src/core/proxylogin.js)
   Står alene på skærmen, når Vercel-proxyen kræver login. Kun farvetokens.
   ============================================================ */
.proxylogin {
  flex: 1 1 auto; display: flex; align-items: center; justify-content: center;
  min-height: 100vh; padding: 16px; background: var(--bg-0);
}
.proxylogin__kort {
  display: flex; flex-direction: column; gap: 16px; max-width: 420px; width: 100%;
  padding: 24px; border: 2px solid var(--line-2); border-radius: 12px;
  background: var(--bg-2); color: var(--tx-1);
}
.proxylogin__titel { margin: 0; font-size: 22px; font-weight: 800; line-height: 1.2; }
.proxylogin__tekst { margin: 0; font-size: 16px; line-height: 1.45; color: var(--tx-2); }
.proxylogin__knap { min-height: 56px; font-size: 18px; font-weight: 800; }

.appsynk { display: flex; flex-direction: column; gap: 12px; padding: 12px; overflow-y: auto; min-height: 0; flex: 1 1 auto; }
.appsynk__hoved { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.appsynk__hoved__titel { font-size: 13px; font-weight: 800; letter-spacing: 1.5px; color: var(--tx-3); }
.appsynk__tilbage { min-height: 44px; }
.appsynk__kort { display: flex; flex-direction: column; gap: 8px; padding: 12px; }
.appsynk__titel { font-size: 11px; font-weight: 800; letter-spacing: 1.5px; color: var(--tx-3); }
.appsynk__raekke { display: flex; justify-content: space-between; gap: 12px; align-items: baseline; font-size: 14px; border-bottom: 1px solid var(--line-1); padding: 6px 0; }
.appsynk__navn { color: var(--tx-2); flex: 1 1 auto; min-width: 0; }
.appsynk__vaerdi { color: var(--tx-1); font-weight: 700; text-align: right; flex: 0 1 55%; min-width: 0; overflow-wrap: anywhere; font-variant-numeric: tabular-nums; }
.appsynk__raekke--advarsel .appsynk__vaerdi { color: var(--orange); }
.appsynk__status { padding: 10px 12px; border-radius: var(--r-md); background: var(--bg-3); font-weight: 700; font-size: 14px; }
.appsynk__status--ok { border-left: 4px solid var(--green); }
.appsynk__status--ny { border-left: 4px solid var(--blue); }
.appsynk__status--fejl { border-left: 4px solid var(--red); }
.appsynk__knapper { display: flex; gap: 8px; flex-wrap: wrap; }
.appsynk__knap { flex: 1 1 160px; min-height: 52px; font-size: 15px; padding-left: 8px; padding-right: 8px; }
.appsynk__note { margin: 0; font-size: 12.5px; color: var(--tx-2); line-height: 1.4; }
.appsynk__resultat { padding: 10px 12px; border-radius: var(--r-md); background: var(--bg-3); font-size: 13.5px; display: flex; flex-direction: column; gap: 6px; }
.appsynk__resultat--ok { border-left: 4px solid var(--green); }
.appsynk__resultat--udsat { border-left: 4px solid var(--orange); }
.appsynk__resultat--fejl { border-left: 4px solid var(--red); }
.appsynk__resultat__tekst { font-weight: 700; }
.appsynk__grunde, .appsynk__dele { margin: 0; padding-left: 18px; display: flex; flex-direction: column; gap: 4px; }
.appsynk__dele { list-style: none; padding-left: 0; }
.appsynk__del__ikon { display: inline-block; width: 1.4em; font-weight: 800; }
.appsynk__del__navn { font-weight: 700; }
.appsynk__trin ol { margin: 4px 0 0; padding-left: 20px; display: flex; flex-direction: column; gap: 4px; font-size: 14px; }
.appsynk__trin__hoved { font-weight: 800; font-size: 14px; }

/* ============================================================
   TESTMODUS — BÅNDET (18. oktober 2026)
   Se src/ui/components/testmodus.js og docs/beslutninger/testmodus.md.

   Fuldbredde stribe under statuslinjen på ALLE skærme. Båndets højde skrives
   som `--tm-top` på <html> (0 uden testmodus), og appen, dialogerne og
   printsimuleringens bånd starter under det.
   ============================================================ */
/* TEMAFAST — testmodusbåndet er en advarsel: violet/hvid følger ikke temaet */
.tm__baand {
  position: fixed; top: env(safe-area-inset-top, 0px); left: 0; right: 0;
  z-index: 10065;
  padding: 3px 10px;
  background: repeating-linear-gradient(-45deg, #5b2fc9 0 12px, #4a24a8 12px 24px);
  color: #fff;
  font: 800 12px/16px var(--mono, monospace);
  letter-spacing: .4px; text-align: center;
  border-bottom: 2px solid #fff;
  box-shadow: 0 2px 8px rgba(0,0,0,.5);
  pointer-events: none;
}
@media (max-width: 640px) {
  .tm__baand { font-size: 11px; padding: 2px 8px; letter-spacing: .2px; }
}
@media print { .tm__baand { display: none !important; } }
/* TEMAFAST SLUT */

/* ============================================================
   STATUSBÅNDET — ÉN STRIBE I STEDET FOR TRE BANNERE (QA-14b, fund 4 og 7)

   Rapporten (browser-QA af kandidat-14b): på en telefon stod testmodus, printsimulering og «huset er åbent,
   men denne kasse har ikke taget sin skuffe i brug» som tre bannere oven på hinanden — 154 px af 844 (82 % af
   skærmens højde i liggende) — og på kassen (1280 × 800) lå printsimuleringens flig oven på kassens egne bannere.

   Nu: testmodus og printsimulering deler ÉN stribe på 24 px (side om side, aldrig oven på hinanden), og kassens
   egen lukket-bjælke er ÉN linje. Stribens højde skrives som `--tm-top` (testmodus) hhv. `--psim-top`
   (printsimulering alene), så appen og dialogerne starter under den.
   ============================================================ */
:root { --psim-bredde: 300px; }

html.psim-aktiv.testmodus-aktiv .tm__baand,
html.psim-aktiv.testmodus-aktiv .psim__baand {
  box-sizing: border-box; height: 24px; padding-top: 0; padding-bottom: 0;
  line-height: 22px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
html.psim-aktiv.testmodus-aktiv .tm__baand { right: var(--psim-bredde); }
/* TEMAFAST — printsimuleringsbåndet er en advarsel: gul/sort følger ikke temaet (som resten af .psim) */
html.psim-aktiv.testmodus-aktiv .psim__baand {
  left: auto; width: var(--psim-bredde);
  padding-left: 8px; padding-right: 8px; border-left: 2px solid #111;
}
/* TEMAFAST SLUT */

/* Telefon: de to bånd deler bredden, og hver viser sin korte tekst (den lange står stadig i DOM'en). */
@media (max-width: 640px) {
  :root { --psim-bredde: 40%; }
  html.psim-aktiv.testmodus-aktiv .tm__baand,
  html.psim-aktiv.testmodus-aktiv .psim__baand { height: 22px; font-size: 0; letter-spacing: 0; }
  html.psim-aktiv.testmodus-aktiv .tm__baand::after,
  html.psim-aktiv.testmodus-aktiv .psim__baand::after {
    content: attr(data-kort); font: 800 10.5px/20px var(--mono, monospace); letter-spacing: 0;
  }
}

/* Lukket-bjælken er ÉN linje på en telefon (den lange tekst står stadig i DOM'en). Højden er stadig
   fingermålet (44 px) — den er en knap. */
@media (max-width: 640px), (max-height: 500px) {
  .closed-banner[data-kort] { font-size: 0; letter-spacing: 0; padding: 0 8px; }
  .closed-banner[data-kort]::after {
    content: attr(data-kort); font-size: 11.5px; line-height: 1.2; letter-spacing: .3px;
  }
}

/* En telefon på langs: rækken er lidt lavere, så der bliver mere af de 390 px tilbage til kassen. */
@media (max-height: 500px) and (min-width: 641px) {
  :root { --psim-raekke-plads: 60px; }
  .psim__raekke { height: 52px; bottom: calc(env(safe-area-inset-bottom, 0px) + 4px); }
  .psim__panel { bottom: calc(env(safe-area-inset-bottom, 0px) + 4px + 52px + 6px); }
}

/* ============================================================
   REGNINGEN VED SIDEN AF PÅ EN LAV TELEFON (QA-14b, fund 1)

   På 844 × 390 står regningen i en spalte på ~360 px. Antal, NY-mærke, navn, pris og to knapper skal være der,
   og navnet blev skåret til «Carls…». Her må navnet fylde to linjer, og grebet og mærket er smallere.
   ============================================================ */
.kompakt--side .kline { gap: 6px; }
.kompakt--side .kline__greb { width: 10px; margin-left: 2px; }
.kompakt--side .kline__ny { margin-left: 2px; font-size: 9px; padding: 2px 4px; letter-spacing: .4px; }
.kompakt--side .kline__antal { margin-left: 2px; min-width: 20px; font-size: 13px; }
.kompakt--side .kline__navn {
  white-space: normal; overflow-wrap: anywhere;
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2;
  line-height: 1.15; font-size: 14px;
}
.kompakt--side .kline__pris { font-size: 14px; }

/* En lav, liggende skærm: bundmenuen er 48 px i stedet for 64 (QA-14b fund 1). Fingermålet er stadig mindst 44. */
@media (max-height: 500px) {
  :root { --kbund-hoejde: 48px; }
  .kbund__knap { padding-top: 6px; padding-bottom: 6px; }
}

/* ============================================================
   «AKTUEL REGNING» PÅ KASSEN (QA-14b, fund 2)

   På 1280 × 800 havde listen 143 px — halvanden linje — fordi handlingstasterne tog fire rækker (se
   `grid-template-columns` ovenfor: nu fem kolonner og tre rækker) og navnet «Jakobs Cheddarburger» brækkede
   midt i ordet i en brødtekstspalte på 102 px. Navnet får lidt mindre skrift og linjen lidt mindre luft, så
   ordet står helt; listen er stadig regningsrummets fleksible del og ruller.
   ============================================================ */
:root[data-pos-flade="klassisk"] .ordright .orderline,
:root[data-pos-flade="klassisk"] .medpile__flade .orderline { gap: 5px; }
:root[data-pos-flade="klassisk"] .ordright .orderline__name,
:root[data-pos-flade="klassisk"] .medpile__flade .orderline__name { font-size: 14px; }

/* ============================================================
   RÆKKENS CHIPS KLIPPES IKKE (QA-14b, fund 6)

   «Åbn kasseskuffe · Kasse 1 — kvitte…» stod med en tredje chip skåret over på «Bon», fordi chipsene var
   `flex: 0 0 auto` med en fast bredde på op til 300 px og rækken kun 560 px bred. Nu må en chip give sig
   (titlen får «…», hele titlen står i `title`), rækken er bredere på en bred skærm, og når der er flere
   chips, end der er plads til, ruller rækken og snapper til en chips kant — en chip hviler aldrig skåret.
   ============================================================ */
.psim__raekke { width: min(760px, calc(100vw - 24px)); }
.psim__chips { scroll-snap-type: x proximity; scroll-padding-left: 2px; }
.psim__chip { flex: 0 1 auto; min-width: 118px; scroll-snap-align: start; }
.psim__chipknap { flex: 1 1 auto; min-width: 0; }
.psim__chiptitel { flex: 1 1 auto; min-width: 0; max-width: 190px; }
.psim__chipluk { flex: 0 0 auto; }
@media (max-width: 640px) {
  .psim__raekke { width: auto; }
  .psim__chiptitel { max-width: 150px; }
}

/* ============================================================
   BESKEDEN LÆGGER SIG IKKE OVER BUNDNAVIGATIONEN PÅ KASSEN (QA-14b, fund 11)

   Den klassiske flade har sin elleve-punkters navigation nederst, og beskeden stod 24 px fra kanten — oven på
   «Besked», «Printere» og «Udseende». Den løftes nu fri af navigationen (og af printsimuleringens række, hvis
   den er der). Er en modal åben, står den stadig øverst, og de to ligner hinanden i vægt, så reglen gentages.
   ============================================================ */
body:has(.bottomnav) .toast-host {
  bottom: calc(var(--touch, 52px) + var(--sp-4) + env(safe-area-inset-bottom) + var(--psim-reserve-bund, 0px));
}
body:has(.modal-backdrop) .toast-host,
:root[data-pos-flade="kompakt"] body:has(.modal-backdrop) .toast-host {
  top: calc(16px + env(safe-area-inset-top) + var(--psim-top, 0px) + var(--tm-top, 0px));
  bottom: auto;
}

/* ============================================================
   KONTRAST PÅ USENDTE VARER (QA-14b, fund 14)

   «Ikke sendt» stod i `--tx-3` (#818b9e) på den orange bund, usendte linjer har: 4,01 : 1, og kravet er 4,5
   (`fladetest`, «Kasse · pos»). Under en usendt linje står teksten nu i `--tx-2` (#b6bfcd): 6,3 : 1.
   ============================================================ */
.orderline--unsent .orderline__mods,
.orderline--unsent .orderline__variant { color: var(--tx-2); }

/* ============================================================
   BUNDMENUENS HJØRNER (QA-14b, fund 15)

   Menuen havde afrundede hjørner hele vejen rundt og en kant i bunden: den orange AFSLUT-flade blev klippet af de
   runde nederste hjørner og stod med en tynd stribe af baggrunden uden for sig, hen over hjemmelinjen. Bunden er
   en kant mod skærmens egen kant — kun de øverste hjørner er runde, og der er ingen kant forneden.
   ============================================================ */
.kbund {
  border-radius: var(--r-md) var(--r-md) 0 0;
  border-bottom: 0;
}
.kbund__knap:first-child { border-top-left-radius: var(--r-md); }
.kbund__knap:last-child { border-top-right-radius: var(--r-md); }

/* Driftsprikken: halvprikken «◐» må ikke blive til et emoji-farvebillede i WebKit (QA-14b P1-C) */
.chip--kunprik { font-variant-emoji: text; font-family: system-ui, -apple-system, "Segoe UI", sans-serif; }

/* ============================================================
   BORDLISTENS HOVED PÅ EN SMAL TELEFON (QA-14b, P1-D)

   Områdefaner, tal og knapper tog 165 px af 844 (en fjerdedel), og «ude på bordene» + tre knapper brød over to rækker, så
   kun to rækker borde var synlige. Her står «ledige» og de tre knapper på ÉN række. «Gæster» og «ude på bordene» står ikke
   på rækken i smal højformat (der er ikke bredde til dem på 370 px) — antal og beløb pr. bord står på bordkortene, og
   totalen står i X-rapporten og på bredere skærme.
   Knapperne beholder fingermålet (44 px i højden); kun deres sidepolstring er smallere.
   ============================================================ */
:root[data-pos-bredde="smal"]:not([data-pos-hoejde="lav"]) .floor__baand > .floor__tal:nth-child(n+2) { display: none; }
:root[data-pos-bredde="smal"]:not([data-pos-hoejde="lav"]) .floor__baand { gap: 8px 12px; }
:root[data-pos-bredde="smal"] .floor__baand__knapper { gap: 6px; }
:root[data-pos-bredde="smal"] .floor__baand__knapper .btn { padding-left: 8px; padding-right: 8px; }
:root[data-pos-bredde="smal"] .floor__tabs { padding-top: 3px; padding-bottom: 3px; }
/* Lav og liggende: tallene står på én linje, så «5 ledige» ikke brydes over tre. */
:root[data-pos-hoejde="lav"] .floor__tal__vaerdi { white-space: nowrap; font-size: 15px; }
:root[data-pos-hoejde="lav"] .floor__tal__navn { white-space: nowrap; }

/* ============================================================
   KONTANTDIALOGEN PÅ EN LAV, LIGGENDE SKÆRM (QA-14b, fund 1)

   På 844 × 390 stod «At betale» og hurtigvalgene øverst, og «Modtaget beløb» og taltastaturet lå en hel skærm nede i
   dialogens rulleflade — uden at noget sagde, at der var mere. Nu står de to side om side: beløb og hurtigvalg til
   venstre, feltet og tastaturet til højre. Hoved og fod er lavere (fingermålet på knapperne er stadig 44 px).
   ============================================================ */
@media (max-height: 500px) and (min-width: 641px) {
  .modal .kontantdlg {
    display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    grid-template-rows: auto 1fr; gap: 8px 16px; align-items: start;
  }
  .modal .kontantdlg > :nth-child(3) { grid-column: 2; grid-row: 1 / span 2; }
  .modal .modal__head { padding-top: 4px; padding-bottom: 4px; min-height: 0; }
  .modal .modal__foot { padding-top: 6px; padding-bottom: 6px; }
  .modal .modal__body:has(.kontantdlg) { padding-top: 8px; padding-bottom: 8px; }
  .modal .kontantdlg { row-gap: 6px; }
  .modal .kontantdlg .keypad__display { height: 44px; font-size: 22px; }
  .modal .kontantdlg .keypad__grid .key { min-height: 44px; font-size: 20px; }
}

/* P8: offline-indikatoren (shell.js `offlineChip`) — tydelig, men må ikke skubbe topbaren ud over kanten */
.topbar > .chip--offline {
  min-height: var(--touch-min);
  max-width: 46vw;
  padding-left: 10px; padding-right: 10px;
  font-size: 12px; font-weight: 800; letter-spacing: .3px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* oven-i-net: på en lille telefon klemte topbaren pillen sammen til ~41 px (under fingermålet; teksten blev til «…»). Gulvet er fingermålet — pillen må ikke
   krympe under det, og ellers uændret (en pille, der ikke kan krympe, eller bryder over to linjer, skubbede topbaren ud over kanten: målt). Fuld tekst står i `title`/`aria-label`. */
.topbar > .chip--offline { min-width: var(--touch-min); }

/* ============================================================
   KASSELAYOUT (22. oktober 2026, ejerens krav: «aktuelle regning — man kan ikke se produkterne»)

   Målt i en rigtig Chrome på 1512 × 741 med 12 linjer på regningen: listen fik 155 px og viste 2 linjer, resten af spalten
   var taster (145 px), tællelinjer og titel. Reglerne her ligger SIDST med vilje (den sidste vinder, se fejlklasse 1) og
   gælder kun kassens klassiske flade, regningen i siden.

     · motoren vælger «samlet» (skaermprofiler.js, listeMindst 280; listeGulv 120 afgør, om regningen står i siden) — fire hyppige taster + Slet + «Flere» på ÉN række
     · «AKTUEL REGNING»-titlen og den dobbelte «Sender…»-linje fylder ikke i samlet form (chippen til højre siger det samme)
     · «Ikke sendt» og «Mad» står på én linje; Luk bord og Betal står fast nederst
     · varefladens rækker vokser op til 96 px (buttonGrid.js `raekkeSpor`); navne 14 px
     · kategoristribens rullebjælke har stilarkets farver og ikke browserens hvide
   ============================================================ */
:root[data-pos-flade="klassisk"][data-pos-taethed="samlet"] .kasse__sidetitel { display: none; }
:root[data-pos-flade="klassisk"] .orderline:has(> .orderline__mark) .line__afsend { display: none; }
:root[data-pos-flade="klassisk"][data-pos-taethed="samlet"] .panel--total {
  flex-direction: row; flex-wrap: wrap; align-items: center; column-gap: 14px; row-gap: 4px;
}
:root[data-pos-flade="klassisk"][data-pos-taethed="samlet"] .panel--total > .row,
:root[data-pos-flade="klassisk"][data-pos-taethed="samlet"] .panel--total > .card,
:root[data-pos-flade="klassisk"][data-pos-taethed="samlet"] .panel--total > .btn { flex: 0 0 100%; }
:root[data-pos-flade="klassisk"][data-pos-taethed="samlet"] .panel--total > .total-line { flex: 0 1 auto; gap: 8px; }
:root[data-pos-flade="klassisk"][data-pos-taethed="samlet"] .panel--total > .gangtael { flex: 1 1 auto; justify-content: flex-end; }
:root[data-pos-flade="klassisk"] .katstribe--top { scrollbar-color: var(--line-strong) transparent; }
:root[data-pos-flade="klassisk"] .gitterflade > .buttongrid > .gridcell--vare .gridcell__label,
:root[data-pos-flade="klassisk"] .gitterflade > .buttongrid > .gridcell--page .gridcell__label { font-size: 14px; }
/* Alle faste taster på ÉN række (Rette, Fortryd, Gentag, Retur, Slet, Flere) — uanset hvor mange der er */
:root[data-pos-flade="klassisk"][data-pos-taethed="samlet"] .funkblok--samlet {
  grid-template-columns: none; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr); gap: 4px;
}
:root[data-pos-flade="klassisk"][data-pos-taethed="samlet"] .funkblok--samlet .funk { font-size: 13px; padding: 2px 2px; }
/* En besked ligger ikke oven på Luk bord / Betal: på kassen med regningen i siden står den i varefladens nederste hjørne */
:root[data-pos-flade="klassisk"][data-pos-regning="hoejre"] .toast-host {
  left: 12px; transform: none; width: min(520px, calc(100vw - 560px));
  bottom: calc(76px + env(safe-area-inset-bottom) + var(--psim-reserve-bund, 0px));
}
/* Er en dialog åben, står beskeden øverst (som overalt ellers) — reglen ovenfor må ikke sætte både top og bottom */
:root[data-pos-flade="klassisk"][data-pos-regning="hoejre"] body:has(.modal-backdrop) .toast-host { bottom: auto; }

/* ============================================================
   SKRIFTGULV (22. oktober 2026) — ingen læsbar tekst på kassen under 11 px, mærkater og chips 12 px.
   Målt i en rigtig Chrome (test/kasselayoutbrowsertest.js): chips 10,5 px, «NY» 9-10 px, «fra» 9 px, F-tast 9,5 px.
   Bordplanens egne tal (.pv__*) er skaleret med planens celle og røres ikke.
   ============================================================ */
.chip--sm { height: 22px; font-size: 12px; }
.kline__ny,
.kompakt--side .kline__ny { font-size: 11px; }
.gridcell__fra { font-size: 11px; }
.gridcell__key { font-size: 11px; }
.kstol__antal { font-size: 11px; }
.ve__stand { font-size: 12px; }
.topbar__skiftord { font-size: 11px; }
.radar__navn, [class*="radar__navn"] { font-size: 11px; }
.chip { font-size: 12px; }

/* KDS: kortets knapper (Start · Klar · Bon · Gensend) står altid i skærmen — er bonnen lang, ruller LINJERNE inde i kortet, ikke siden.
   Før: 12 linjer gjorde kortet højere end skærmen, og «Start» lå under bundnavigationen (målt 1512 × 741). */
.kds-card { max-height: max(340px, calc(100dvh - 240px - var(--psim-top, 0px) - var(--tm-top, 0px) - var(--psim-reserve-bund, 0px) - env(safe-area-inset-top, 0px) - env(safe-area-inset-bottom, 0px))); }
.kds-card__lines { overflow-y: auto; overscroll-behavior: contain; }
.ktotal__label, .topbar__gang { font-size: 11px; }

/* VENT AKTIV (og «Send næste runde» / «Kald ventende»): de to store knapper (2 × 56 px) deler ÉN række i samlet form.
   Målt af BT04 på 1280 × 800: listen blev 88 px — en halv linje — så snart VENT var slået til. */
:root[data-pos-flade="klassisk"][data-pos-taethed="samlet"] .kasse__handlinger {
  flex-direction: row; flex-wrap: wrap; align-items: stretch; gap: 6px;
}
:root[data-pos-flade="klassisk"][data-pos-taethed="samlet"] .kasse__handlinger > .btn--block {
  flex: 1 1 calc(50% - 3px); width: auto; min-height: 44px; height: 44px; padding-top: 0; padding-bottom: 0; font-size: 14px;
}
:root[data-pos-flade="klassisk"][data-pos-taethed="samlet"] .kasse__handlinger > .panel--total { flex: 0 0 100%; }
.ktotal__gang, .floor__tal__navn { font-size: 11px; }
/* skriftgulvet gælder også, hvor et tidligere stilark er mere specifikt */
:root .ktotal__hint, :root .ktotal__label, :root .ktotal__gang, :root .floor__tal__navn, :root .topbar__gang { font-size: 11px !important; }
