@charset "utf-8";

/* ==========================================================================
   Rutepapir – designspråk for Klassekart
   1. Palett og variabler   2. Basis   3. Skall og navigasjon   4. Kontroller
   5. Innholdsblokker       6. Rom     7. Klassekart   7b. Onboarding
   7c. Trekking og grupper
   8. Utskrift
   ========================================================================== */

@font-face {
  font-family: 'Quicksand';
  src: url('fonts/Quicksand-Bold.ttf') format('truetype');
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}

/* ---------------------------------------------------------------- 1. Palett */

:root {
  /* lys */
  --l-ground:#F0F3F1; --l-surface:#FFFFFF; --l-surface-2:#F7F9F8;
  --l-line:#D3DCD8; --l-line-soft:#E4EAE7;
  --l-grid:rgba(11,106,95,.09); --l-grid-strong:rgba(11,106,95,.22);
  --l-ink:#0F1C1A; --l-ink-2:#52625F; --l-ink-3:#7C8B88;
  --l-accent:#0B6A5F; --l-accent-ink:#08514A; --l-accent-soft:#DCEFEA; --l-on-accent:#FFFFFF;
  --l-mark:#E0A02A; --l-mark-soft:#FBEBC9;
  --l-warn:#B5402B; --l-warn-soft:#FBE7E2;
  --l-ok:#2E7D4F; --l-ok-soft:#DFF0E4;
  --l-shadow:rgba(15,28,26,.10); --l-shadow-2:rgba(15,28,26,.20);

  /* mørk */
  --d-ground:#0E1614; --d-surface:#16201E; --d-surface-2:#1C2725;
  --d-line:#2C3936; --d-line-soft:#232F2D;
  --d-grid:rgba(88,196,176,.09); --d-grid-strong:rgba(88,196,176,.24);
  --d-ink:#E7EEEB; --d-ink-2:#9EADA9; --d-ink-3:#7A8985;
  --d-accent:#58C4B0; --d-accent-ink:#7FD8C6; --d-accent-soft:#123430; --d-on-accent:#08201C;
  --d-mark:#E8B45C; --d-mark-soft:#3A2E17;
  --d-warn:#F0937C; --d-warn-soft:#3A1F19;
  --d-ok:#6ECB92; --d-ok-soft:#16301F;
  --d-shadow:rgba(0,0,0,.45); --d-shadow-2:rgba(0,0,0,.6);

  --display:'Quicksand', ui-rounded, 'Segoe UI', system-ui, sans-serif;
  --ui:-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
  --mono:ui-monospace, 'SF Mono', Menlo, Consolas, monospace;

  --r-sm:6px; --r-md:10px; --r-lg:14px; --r-xl:20px;
  --tabbar-h:calc(58px + env(safe-area-inset-bottom, 0px));
  --tap:44px;
}

/* lys er standard; mørk når nettleseren ber om det, eller når temaknappen sier det */
:root {
  --ground:var(--l-ground); --surface:var(--l-surface); --surface-2:var(--l-surface-2);
  --line:var(--l-line); --line-soft:var(--l-line-soft);
  --grid:var(--l-grid); --grid-strong:var(--l-grid-strong);
  --ink:var(--l-ink); --ink-2:var(--l-ink-2); --ink-3:var(--l-ink-3);
  --accent:var(--l-accent); --accent-ink:var(--l-accent-ink);
  --accent-soft:var(--l-accent-soft); --on-accent:var(--l-on-accent);
  --mark:var(--l-mark); --mark-soft:var(--l-mark-soft);
  --warn:var(--l-warn); --warn-soft:var(--l-warn-soft);
  --ok:var(--l-ok); --ok-soft:var(--l-ok-soft);
  --shadow:var(--l-shadow); --shadow-2:var(--l-shadow-2);
  color-scheme: light;
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --ground:var(--d-ground); --surface:var(--d-surface); --surface-2:var(--d-surface-2);
    --line:var(--d-line); --line-soft:var(--d-line-soft);
    --grid:var(--d-grid); --grid-strong:var(--d-grid-strong);
    --ink:var(--d-ink); --ink-2:var(--d-ink-2); --ink-3:var(--d-ink-3);
    --accent:var(--d-accent); --accent-ink:var(--d-accent-ink);
    --accent-soft:var(--d-accent-soft); --on-accent:var(--d-on-accent);
    --mark:var(--d-mark); --mark-soft:var(--d-mark-soft);
    --warn:var(--d-warn); --warn-soft:var(--d-warn-soft);
    --ok:var(--d-ok); --ok-soft:var(--d-ok-soft);
    --shadow:var(--d-shadow); --shadow-2:var(--d-shadow-2);
    color-scheme: dark;
  }
}
:root[data-theme="dark"] {
  --ground:var(--d-ground); --surface:var(--d-surface); --surface-2:var(--d-surface-2);
  --line:var(--d-line); --line-soft:var(--d-line-soft);
  --grid:var(--d-grid); --grid-strong:var(--d-grid-strong);
  --ink:var(--d-ink); --ink-2:var(--d-ink-2); --ink-3:var(--d-ink-3);
  --accent:var(--d-accent); --accent-ink:var(--d-accent-ink);
  --accent-soft:var(--d-accent-soft); --on-accent:var(--d-on-accent);
  --mark:var(--d-mark); --mark-soft:var(--d-mark-soft);
  --warn:var(--d-warn); --warn-soft:var(--d-warn-soft);
  --ok:var(--d-ok); --ok-soft:var(--d-ok-soft);
  --shadow:var(--d-shadow); --shadow-2:var(--d-shadow-2);
  color-scheme: dark;
}

/* ------------------------------------------------ Modusfarger

   Appen er to ting: et lærerverktøy, og en flate som står på en storskjerm i
   et rom med tretti elever i. Låsen bytter mellom dem, og fargen sier hvilken
   som gjelder – grønn for lærermodus, lilla for klasseromsmodus. Poenget er at
   det skal kunne ses på et halvt sekund, fra andre siden av rommet: står
   maskina framme mens læreren er ute, skal det være lilla på skjermen.

   Merket ligger på <html>, ikke på #app, fordi dialoger og varsler henger
   utenfor #app og skal skifte farge de også. Bare aksentfargene byttes –
   flate, tekst og linjer er de samme, slik at det er én app i to moduser og
   ikke to ulike apper.

   Lilla er valgt fordi den ikke kolliderer med noe av det som allerede bærer
   mening her: --mark er gul, --warn rød, --ok grønn. Kontrastene er målt mot
   flatene de står på (lys: 6,6:1 hvit på lilla; mørk: 9,4:1 lilla på mørk). */

:root {
  --l-kr-accent:#5B4BC4; --l-kr-accent-ink:#453596;
  --l-kr-accent-soft:#E7E4F8; --l-kr-on-accent:#FFFFFF;
  --l-kr-grid:rgba(91,75,196,.10); --l-kr-grid-strong:rgba(91,75,196,.24);
  --d-kr-accent:#A99BF0; --d-kr-accent-ink:#C4B9F7;
  --d-kr-accent-soft:#241E45; --d-kr-on-accent:#14103A;
  --d-kr-grid:rgba(169,155,240,.10); --d-kr-grid-strong:rgba(169,155,240,.26);
}

:root[data-modus="klasserom"] {
  --accent:var(--l-kr-accent); --accent-ink:var(--l-kr-accent-ink);
  --accent-soft:var(--l-kr-accent-soft); --on-accent:var(--l-kr-on-accent);
  --grid:var(--l-kr-grid); --grid-strong:var(--l-kr-grid-strong);
}
@media (prefers-color-scheme: dark) {
  :root[data-modus="klasserom"]:not([data-theme="light"]) {
    --accent:var(--d-kr-accent); --accent-ink:var(--d-kr-accent-ink);
    --accent-soft:var(--d-kr-accent-soft); --on-accent:var(--d-kr-on-accent);
    --grid:var(--d-kr-grid); --grid-strong:var(--d-kr-grid-strong);
  }
}
:root[data-theme="dark"][data-modus="klasserom"] {
  --accent:var(--d-kr-accent); --accent-ink:var(--d-kr-accent-ink);
  --accent-soft:var(--d-kr-accent-soft); --on-accent:var(--d-kr-on-accent);
  --grid:var(--d-kr-grid); --grid-strong:var(--d-kr-grid-strong);
}

/* ----------------------------------------------------------------- 2. Basis */

* { box-sizing: border-box; margin: 0; padding: 0; }
/* `hidden` skal bety skjult. Uten dette taper nettleserens egen regel mot enhver
   klasse som setter display – f.eks. .btn – og elementet blir stående synlig. */
[hidden] { display: none !important; }
html, body { height: 100%; }
body {
  font-family: var(--ui);
  background: var(--ground);
  color: var(--ink);
  font-size: 15px;
  line-height: 1.5;
  -webkit-text-size-adjust: 100%;
}
h1, h2, h3 { font-family: var(--display); font-weight: 700; line-height: 1.2; }
a { color: var(--accent); }
:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: var(--r-sm);
}
::selection { background: var(--accent-soft); color: var(--accent-ink); }
/* Avkryssingsbokser og radioknapper tegnes av operativsystemet, og kommer
   ellers i systemets blå – midt i et grensesnitt der alt som kan trykkes på
   er den samme blågrønne. Ett sted, så gjelder det også elevliste-modulen. */
input[type=checkbox], input[type=radio] { accent-color: var(--accent); }

/* ------------------------------------------------------------------ Ikoner

   Symbolene i grensesnittet er inline SVG fra site/ikoner.js, ikke emoji.
   Strekene arver `currentColor`, så et ikon i en primærknapp blir hvitt og et
   i brødteksten blir blekksvart – uten en eneste ekstra regel. Størrelsen
   følger skriftstørrelsen (`em`), slik at ikonet i en `.btn-sm` krymper med
   teksten og et ikon i en overskrift vokser med den.

   `vertical-align` trengs bare når ikonet står i løpende tekst; i knapper og
   andre flex-bokser stiller `align-items` det på linje uansett. `flex: none`
   hindrer at ikonet klemmes flatt når knappteksten er lang. */
.ico {
  width: 1.15em; height: 1.15em;
  flex: none;
  vertical-align: -.19em;
}
/* Ikonet i en overskrift eller et stort tall skal ikke dominere teksten */
h1 .ico, h2 .ico, h3 .ico, h4 .ico { width: 1em; height: 1em; vertical-align: -.09em; }
/* Tynnere strek når ikonet er stort, ellers blir det klumpete */
.ico-stor { width: 1.5em; height: 1.5em; stroke-width: 1.75; }

/* Fargene emojiene hadde innebygd. Et ⚠️ var gult og et 🚫 rødt uansett hvor
   de sto; en SVG arver teksten rundt seg, så meningen må sies med en klasse.
   Merk at .ico-advarsel og .ico-sperret bare skiller i alvorlighetsgrad –
   begge skal skille seg ut fra brødteksten. */
.ico-advarsel { color: var(--mark); }
.ico-sperret  { color: var(--warn); }
.ico-ok       { color: var(--ok); }
.ico-tips     { color: var(--mark); }

#app { display: flex; min-height: 100%; }

/* -------------------------------------------------- 3. Skall og navigasjon */

/* `overflow-y: auto` er ikke pynt: menyen er `height: 100vh`, og uten den renner
   innholdet ut UNDER bakgrunnen i stedet for å rulle inni den. Da mister menyen
   flata si nederst i det sida rulles – og foten (eksport, lås, teksten om
   lagring) blir stående på hovedvinduets bakgrunn. Menypunktene er derfor også
   holdt korte nok til at det normalt ikke er noe å rulle: hver `.nav-sub` skal
   få plass på ÉN linje ved 212 px. Skriver du en lengre, tar den to linjer, og
   menyen begynner å rulle på en lærer-PC (768 px høy). */
#sidebar {
  width: 212px; flex-shrink: 0;
  background: var(--surface-2);
  border-right: 1px solid var(--line);
  display: flex; flex-direction: column;
  padding: 16px 12px;
  position: sticky; top: 0; height: 100vh;
  overflow-y: auto; overscroll-behavior: contain;
}
#sidebar h1 {
  font-size: 18px; margin-bottom: 14px; padding: 2px 8px;
  color: var(--ink); display: flex; align-items: center; gap: 8px;
}
.nav-links { display: flex; flex-direction: column; gap: 2px; }
#sidebar a {
  color: var(--ink-2); text-decoration: none;
  padding: 7px 10px; border-radius: var(--r-md);
  font-weight: 600; font-size: 14.5px;
  display: flex; flex-wrap: wrap; align-items: center; column-gap: 8px;
  position: relative;
}
#sidebar .nav-ico { font-size: 16px; line-height: 1; }
#sidebar a:hover { background: var(--surface); color: var(--ink); }
#sidebar a.active { background: var(--accent-soft); color: var(--accent-ink); }
#sidebar a.active::before {
  content: ''; position: absolute; left: -12px; top: 8px; bottom: 8px;
  width: 3px; background: var(--accent); border-radius: 0 3px 3px 0;
}
#sidebar .nav-sub {
  flex-basis: 100%; font-size: 11.5px; font-weight: 400;
  color: var(--ink-3); margin-top: 1px;
}
#sidebar a.active .nav-sub { color: var(--accent-ink); opacity: .8; }

/* Skillet i menyen: alt under det er laget for å stå på storskjermen mens
   klassen ser på, ikke for læreren alene. Det står inni .nav-links og ikke
   mellom to lister, fordi menyen blir én rad med bunnfaner på telefon. */
.nav-sep {
  margin: 10px 8px 2px; padding-top: 10px;
  border-top: 1px solid var(--line);
  font-size: 10.5px; font-weight: 700; letter-spacing: .06em;
  text-transform: uppercase; color: var(--ink-3);
}

.nav-footer {
  margin-top: auto; padding-top: 12px; border-top: 1px solid var(--line);
  display: flex; flex-direction: column; gap: 4px;
}
.nav-footer .btn { justify-content: flex-start; }
.nav-footer .hint { font-size: 11.5px; color: var(--ink-3); padding: 6px 6px 0; line-height: 1.45; }
/* Påminnelsen om sikkerhetskopi. Litt mørkere enn den faste teksten under, så
   den leses først, men fortsatt en hint og ikke et varsel: --mark er gul, ikke
   rød, fordi ingenting er galt – det er bare en stund siden. */
/* Begge selektorene trengs: den ene for foten, der `.nav-footer .hint` er
   sterkere, den andre for «Mer»-dialogen, som bruker den samme linja. */
.nav-footer .backup-hint, .backup-hint { color: var(--ink-2); }
/* Prikken på «Eksporter data». Den sier ingenting til den som ikke ser den, og
   skal ikke gjøre det heller: linja i foten og tittelen på knappen bærer
   beskjeden. Prikken er bare det som får øyet til å finne knappen igjen. */
.btn.paaminn::after {
  content: ''; width: 7px; height: 7px; margin-left: 2px;
  border-radius: 50%; background: var(--mark); flex: none;
}
.nav-more { display: none; }

#main { flex: 1; padding: 22px 26px; min-width: 0; }

/* ------------------------------------------------------------ 4. Kontroller */

.btn {
  font-family: inherit; font-size: 14px; font-weight: 600;
  min-height: 40px; padding: 0 14px;
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  background: var(--surface); color: var(--ink);
  border: 1px solid var(--line); border-radius: var(--r-md);
  cursor: pointer; white-space: nowrap;
  /* `a.btn` finnes flere steder – fanene på klassesida, kortene på forsiden.
     En lenke som ser ut som en knapp, skal ikke ha understrek under teksten. */
  text-decoration: none;
}
.btn:hover { background: var(--surface-2); border-color: var(--ink-3); }
.btn:disabled { opacity: .45; cursor: not-allowed; }
.btn-primary { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
.btn-primary:hover { background: var(--accent-ink); border-color: var(--accent-ink); color: var(--on-accent); }
.btn-danger { color: var(--warn); }
.btn-danger:hover { background: var(--warn-soft); border-color: var(--warn); }
.btn-sm { min-height: 34px; font-size: 13px; padding: 0 10px; }
.btn-ghost { background: transparent; border-color: transparent; color: var(--ink-2); }
.btn-ghost:hover { background: var(--surface); border-color: transparent; color: var(--ink); }
.btn.active { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }

/* Typene listes opp fordi avkryssingsbokser, radioknapper og fargevelgere
   tegnes av operativsystemet og ikke skal ha ramme og luft som et skrivefelt.
   Passordfeltet på låseskjermen og datofeltet på klassen sto lenge utenfor
   lista, og fikk nettleserens egen trange innramming i stedet for appens. */
input[type=text], input[type=number], input[type=password], input[type=date],
select, textarea {
  font-family: inherit; font-size: 15px;
  min-height: 40px; padding: 8px 11px;
  color: var(--ink); background: var(--surface);
  border: 1px solid var(--line); border-radius: var(--r-md);
  max-width: 100%;
}
select { padding-right: 6px; }
input:focus, select:focus, textarea:focus {
  outline: 2px solid var(--accent); outline-offset: -1px; border-color: var(--accent);
}
input::placeholder, textarea::placeholder { color: var(--ink-3); }
label { font-size: 13px; font-weight: 700; color: var(--ink-2); }
kbd {
  font-family: var(--mono); font-size: 11.5px;
  background: var(--surface-2); border: 1px solid var(--line);
  border-radius: var(--r-sm); padding: 1px 5px;
}

/* --------------------------------------------------- 5. Innholdsblokker */

/* Topplinja bryter der det gir mening, ikke midt i en knapperekke: knappene
   ligger i én gruppe som flytter seg samlet ned på egen linje bare når de
   faktisk ikke får plass, og opplysningsteksten kortes av i stedet for å
   skyve dem foran seg. Er gruppa bredere enn hele linja, bryter den innvendig
   – uten wrap ville knappene rent ut av skjermen og blitt utilgjengelige. */
.page-head { display: flex; align-items: center; gap: 8px 12px; margin-bottom: 14px; flex-wrap: wrap; }
.page-head h2 { font-size: 24px; margin-right: auto; }
.page-head input[type=text] { font-family: var(--display); }
/* Opplysningsteksten er den som VIKER. `flex: 1 1 40px` er hele trikset:
   flexbox bestemmer hvem som havner på neste linje ved å måle elementene som
   om de ikke kunne brytes, og med et lite `flex-basis` teller denne teksten
   som 40 px i det regnestykket – ikke som de 430 pikslene «9X · eksempelklasse
   · Eksempelrom (24 pulter) (A102, A103, A104, B204, B205, C301) · 3. sep.
   2026» faktisk er. Uten det dyttet en lang romrekke stjerna, «Lagre som
   bilde» og «Skriv ut / PDF» ned på en linje for seg selv, med et tomrom
   under navnet: toppraden byttet form etter hvor mange romnummer rommet
   tilfeldigvis hadde.
   Etterpå vokser teksten inn i det som er igjen av linja og kappes med
   ellipse. Rekkefølgen klasse · rom · dato er derfor ikke likegyldig – det er
   datoen som ryker først, og den er den vi lettest klarer oss uten. Hele
   teksten står i `title`.
   `margin-right: auto` er borte med vilje: en auto-marg og `flex-grow` er to
   måter å ta den samme ledige plassen på, og da er det ikke lenger opplagt
   hvem som får den. */
.page-head .head-meta {
  color: var(--ink-2); font-size: 13.5px; flex: 1 1 40px;
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* Under ~1200 px blir det som er igjen til teksten så lite at ellipsen spiser
   opp alt som var verdt å lese – ved 1060 px står det «9X · ek…», som er en
   stump og ikke en opplysning. Da får den heller HELE linja under, mens
   knappene blir stående der de var: raden læreren bruker, skifter ikke form.
   `order` og ikke omstokket markup – i kildekoden står teksten der den hører
   hjemme å leses, mellom navnet og knappene. */
@media (max-width: 1199px) {
  .page-head .head-meta { order: 1; flex: 1 1 100%; }
}
/* Knappene til høyre viker SAMLET ned på neste linje når linja er for trang
   (under ~1030 px på kartsida), og står da høyrestilt. De beholder standard
   `flex-shrink: 1` med vilje: er gruppa alene bredere enn linja – tre knapper
   på kartlista ved 740 px – skal den krympe og bryte innvendig, ikke renne ut
   av sida. Samme resonnement som `.tool-group`. */
.page-head .head-actions {
  display: flex; align-items: center; gap: 8px; margin-left: auto;
  flex-wrap: wrap; justify-content: flex-end; min-width: 0;
}
.back { color: var(--ink-2); text-decoration: none; font-size: 14px; font-weight: 600; }
.back:hover { color: var(--ink); }

.card {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r-lg); padding: 18px;
}
.empty-state { text-align: center; color: var(--ink-2); padding: 48px 20px; }
.empty-state p { margin-bottom: 14px; }
.empty-state .btn { margin: 0 4px; }
.page-intro { color: var(--ink-2); font-size: 14px; margin: -4px 0 16px; max-width: 62ch; line-height: 1.5; }
.hint { color: var(--ink-2); }
.hint-inline { font-size: 12.5px; color: var(--ink-2); }

/* Kom i gang-steg */
.steps-card { margin-bottom: 20px; max-width: 780px; }
.steps-card h3 { font-size: 18px; margin-bottom: 4px; }
.steps-intro { color: var(--ink-2); font-size: 14px; margin-bottom: 14px; line-height: 1.5; }
.step {
  display: flex; gap: 13px; align-items: center;
  border: 1px solid var(--line); border-radius: var(--r-md);
  padding: 12px 14px; background: var(--surface); margin-bottom: 8px;
}
.step:last-child { margin-bottom: 0; }
.step.done { background: var(--ok-soft); border-color: transparent; }
.step.locked { opacity: .6; }
.step-num {
  width: 30px; height: 30px; flex-shrink: 0; border-radius: 50%;
  background: var(--mark); color: #2A1E06;
  display: flex; align-items: center; justify-content: center;
  font-family: var(--display); font-weight: 700; font-size: 15px;
}
.step.done .step-num { background: var(--ok); color: #fff; }
.step.locked .step-num { background: var(--ink-3); color: var(--surface); }
.step-body { flex: 1; min-width: 0; }
.step-body p { font-size: 13px; color: var(--ink-2); margin-top: 2px; line-height: 1.45; }
.step-body .step-lock { color: var(--ink-3); font-size: 12.5px; font-weight: 600; }
.step-action { flex-shrink: 0; }

/* Neste steg-banner */
.next-banner {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  background: var(--accent-soft); color: var(--accent-ink);
  border-radius: var(--r-md); padding: 10px 14px; margin-bottom: 14px;
  font-size: 14px; font-weight: 600;
}
.next-banner a { white-space: nowrap; }

/* Hjelp */
.help-item { display: flex; gap: 10px; font-size: 14.5px; line-height: 1.5; align-items: flex-start; }
.help-num {
  width: 24px; height: 24px; flex-shrink: 0; border-radius: 50%;
  background: var(--accent); color: var(--on-accent);
  display: flex; align-items: center; justify-content: center;
  font-family: var(--display); font-weight: 700; font-size: 13px; margin-top: 1px;
}

/* Felles katalog */
.catalog-row {
  display: flex; align-items: center; gap: 10px;
  border: 1px solid var(--line); border-radius: var(--r-md);
  padding: 10px 12px; background: var(--surface-2);
}
.catalog-info { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.catalog-nums { font-size: 13px; color: var(--ink); }
.catalog-meta { font-size: 12px; color: var(--ink-2); }

/* Lister */
table.list {
  width: 100%; border-collapse: collapse; background: var(--surface);
  border-radius: var(--r-lg); overflow: hidden; border: 1px solid var(--line);
}
table.list th, table.list td { text-align: left; padding: 11px 14px; border-bottom: 1px solid var(--line-soft); }
table.list th {
  background: var(--surface-2); font-size: 11.5px; color: var(--ink-3);
  text-transform: uppercase; letter-spacing: .1em; font-weight: 700;
}
table.list tr:last-child td { border-bottom: none; }
table.list td.actions { text-align: right; white-space: nowrap; }
table.list a { color: var(--accent); font-weight: 700; text-decoration: none; }
table.list a:hover { text-decoration: underline; }
.list-wrap { overflow-x: auto; }

/* Bolkene i kartlista (favorittene, så én per klasse). Overskriften er en rad i
   den samme tabellen, slik at kolonnene står under hverandre hele veien ned –
   men den skal leses som en overskrift og ikke som enda en kolonneheader:
   derfor vanlig tekst i vanlig størrelse, ikke den lille versalrekka øverst. */
table.list tr.bolk th {
  background: var(--surface); color: var(--ink);
  font-size: 14px; text-transform: none; letter-spacing: 0;
  padding-top: 20px; padding-bottom: 6px; border-bottom-color: var(--line);
}
table.list tr.bolk .ico {
  width: 15px; height: 15px; vertical-align: -2px;
  color: var(--accent); fill: currentColor;
}
/* Klassen bak navnet i favorittbolken – den ene bolken som blander klasser. */
.rad-bikart { color: var(--ink-3); font-weight: 600; font-size: 13px; }
table.list td.datocelle { white-space: nowrap; color: var(--ink-2); }

/* ---- Favoritter, utløpsdato og arkiv ----

   Stjerna skal se ut som en stjerne, ikke som en knapp med en stjerne i: en
   liste med tjue tomme stjerner må kunne leses forbi. Derfor ingen ramme, og
   fyll bare når den står på. Fargen er aksenten, som resten av det som er
   «slått på» i appen. */

.stjerne {
  display: inline-flex; align-items: center; justify-content: center;
  width: 34px; height: 34px; padding: 0; flex: none;
  border: none; border-radius: var(--r-sm); background: none;
  color: var(--ink-3); cursor: pointer;
}
.stjerne:hover, .stjerne:focus-visible { background: var(--surface-2); color: var(--accent); }
.stjerne.pa { color: var(--accent); }
.stjerne.pa .ico { fill: currentColor; }
table.list th.stjernecelle, table.list td.stjernecelle {
  width: 46px; padding-left: 8px; padding-right: 0;
}

/* Datoen er også knappen som endrer den. Den ser ut som tekst til pekeren er
   over den – ellers ville hver rad i lista hatt en knapp som ropte. */
.datoknapp {
  font: inherit; color: var(--ink); background: none; cursor: pointer;
  padding: 2px 2px; border: none; border-bottom: 1px dashed var(--ink-3);
}
.datoknapp:hover, .datoknapp:focus-visible { color: var(--accent); border-bottom-color: var(--accent); }
table.list td.utlopcelle { white-space: nowrap; }
/* Knapper med ikon og knapper uten har ulik grunnlinje. I en handlingscelle
   står de ved siden av hverandre, og skal stå på samme høyde. */
table.list td.actions .btn { vertical-align: middle; }
table.list tr.rad-utlopt td:first-child { box-shadow: inset 3px 0 0 var(--warn); }

.merke {
  display: inline-block; font-size: 11px; font-weight: 700;
  padding: 2px 8px; border-radius: 999px; margin-left: 6px; white-space: nowrap;
}
.merke .ico { width: 13px; height: 13px; vertical-align: -2px; margin-right: 3px; }
.merke-utlopt { background: var(--warn-soft); color: var(--warn); }
.merke-snart { background: var(--mark-soft); color: var(--ink); }
/* Undervisningsgruppe. Nøytral grå: dette er en opplysning om hva gruppa er,
   ikke en advarsel om noe læreren må gjøre. */
.merke-gruppe { background: var(--surface-2); color: var(--ink-2); }

/* Linja under topplinja på klassesida. Den bytter farge, ikke plass: en klasse
   som har gått ut på dato skal se annerledes ut på ett blikk, men ikke flytte
   på noe av det læreren holder på med. */
.klasse-status {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  margin: 0 0 14px; padding: 9px 12px;
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-md);
}
.klasse-status > .ico { flex: none; color: var(--ink-3); }
.klasse-status.utlopt { border-color: var(--warn); background: var(--warn-soft); }
.klasse-status.snart { border-color: var(--mark); }
.klasse-status.arkivert { border-style: dashed; }
.ks-tekst { display: flex; flex-direction: column; gap: 1px; margin-right: auto; min-width: 0; }
.ks-tekst b { font-size: 14px; }
.ks-tekst small { font-size: 12.5px; color: var(--ink-2); line-height: 1.4; }

/* Arkivet står under klasselista, lukket: det er noe man går til, ikke noe man
   får i fanget hver gang man åpner Klasser. */
.arkiv-liste { margin-top: 24px; }
.arkiv-liste > summary {
  cursor: pointer; font-family: var(--display); font-size: 15px; font-weight: 700;
  color: var(--ink-2); padding: 8px 0;
}
.arkiv-liste[open] > summary { color: var(--ink); }
.arkiv-liste > summary .ico { vertical-align: -4px; margin-right: 6px; }
table.list td.arkiv-rester { color: var(--ink-2); font-size: 13px; }

/* Arkiveringsdialogen: det som forsvinner og det som blir stående, side om
   side. To lister med ord alene ville sett like ut – her er det fargen som
   sier hvilken av dem som er den farlige. */
.arkiv-ingress { font-size: 14px; line-height: 1.5; margin-bottom: 12px; }
.arkiv-ingress .ico { vertical-align: -4px; margin-right: 4px; }
.arkiv-kolonner { display: flex; gap: 10px; flex-wrap: wrap; }
.arkiv-del { flex: 1 1 190px; padding: 10px 12px; border-radius: var(--r-md); }
.arkiv-del b { display: block; font-size: 13px; margin-bottom: 6px; }
.arkiv-del ul { margin: 0; padding-left: 18px; font-size: 13px; color: var(--ink-2); line-height: 1.5; }
.arkiv-bort { background: var(--warn-soft); }
.arkiv-bort b { color: var(--warn); }
.arkiv-blir { background: var(--ok-soft); }
.arkiv-blir b { color: var(--ok); }
.arkiv-ja { margin-top: 14px; font-weight: 700; }

/* Klasselista på liten skjerm. Tabellen har fått to kolonner til, og på en
   telefon er det navnet, datoen og knappene som må være framme: tallene for
   elever og kart står på klassesida uansett. Knappene legger seg under
   hverandre i stedet for å skyve resten ut av skjermkanten. */
@media (max-width: 700px) {
  table.klasseliste th:nth-child(3), table.klasseliste td:nth-child(3),
  table.klasseliste th:nth-child(4), table.klasseliste td:nth-child(4) { display: none; }
  /* Merket legger seg under datoen i stedet for ved siden av: to korte linjer
     tar mindre bredde enn én lang, og bredden er det det står om her. */
  table.klasseliste .merke { display: block; width: fit-content; margin: 5px 0 0; }
}
@media (max-width: 560px) {
  /* Trangere celler: bredden skal gå til navnet, datoen og knappene, ikke til
     luft mellom dem. */
  table.list th, table.list td { padding-left: 8px; padding-right: 8px; }
  table.list td.actions .btn { display: flex; width: 100%; }
  table.list td.actions .btn + .btn { margin-top: 6px; }
}

/* Overskrift bare for skjermleseren: stjernekolonnen har ingen tittel å se på,
   men den trenger et navn å høre. */
.visuelt-skjult {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap;
}

/* ---- Lagene som legger seg over sida ----

   Rekkefølgen er en stige, og den skal leses ovenfra: et lag SKAL ligge over
   alt under seg, og en ny «over sida»-ting hører hjemme et sted i denne lista
   – ikke med et tall plukket fordi det var stort nok.

     700  toastene       – kvitteringen, også på noe som ble gjort i en dialog
     600  dialogene      – det læreren svarer på nå
     520  nedtellingen   – ligger over visningen, men under det man svarer på
     500  lykkehjulet    – helskjerm over visningen
     400  flykortene     – navn på vei til en pult
     250  omvisningen
     200 og lavere       – sida selv

   Dialogen lå under hjulet før «Hvem er med» fantes, og det så ut som om
   knappen ikke virket: dialogen var der, den lå bare bak skiva. Toastene må
   over dialogen igjen, for de kvitterer for noe som skjer inne i den. */
#toasts {
  position: fixed; bottom: 20px; left: 50%; transform: translateX(-50%);
  z-index: 700; display: flex; flex-direction: column; gap: 8px; align-items: center;
  padding: 0 12px; max-width: 100%;
}
.toast {
  background: var(--ink); color: var(--ground);
  padding: 11px 18px; border-radius: var(--r-md); font-size: 14px; font-weight: 600;
  box-shadow: 0 8px 24px var(--shadow-2); max-width: 500px;
  animation: toastIn .18s ease;
}
.toast.warn { background: var(--warn); color: #fff; }
@keyframes toastIn { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; } }

/* Modal */
.modal-overlay {
  position: fixed; inset: 0; background: rgba(8,20,18,.55); z-index: 600;
  display: flex; align-items: center; justify-content: center; padding: 20px;
}
.modal {
  background: var(--surface); color: var(--ink);
  border: 1px solid var(--line); border-radius: var(--r-lg);
  padding: 22px; width: 470px; max-width: 100%; max-height: 90vh; overflow: auto;
  box-shadow: 0 20px 60px var(--shadow-2);
}
/* Ikonet i modaltittelen står ved siden av teksten, ikke oppå den – derfor
   flex her, i stedet for å stole på vertical-align i en overskriftsfont. */
.modal h3 { margin-bottom: 14px; font-size: 19px; display: flex; align-items: center; gap: 9px; }
.modal .modal-body { display: flex; flex-direction: column; gap: 12px; }
.modal .modal-buttons { display: flex; justify-content: flex-end; gap: 8px; margin-top: 18px; flex-wrap: wrap; }
.modal .field { display: flex; flex-direction: column; gap: 5px; }
.modal .checkline {
  display: flex; align-items: center; gap: 9px;
  font-weight: 400; font-size: 14.5px; color: var(--ink); min-height: 32px;
}
.modal .checkline input { min-height: 0; width: 18px; height: 18px; }
/* Valg med forklaring: overskriften sier hva, linja under sier hva det betyr */
.modal .checkline.choice { align-items: flex-start; gap: 10px; padding: 7px 9px; min-height: var(--tap); }
.modal .checkline.choice { border: 1px solid var(--line); border-radius: var(--r-md); background: var(--surface); }
.modal .checkline.choice:has(input:checked) { border-color: var(--accent); background: var(--accent-soft); }
.modal .checkline.choice input { margin-top: 3px; }
.modal .checkline.choice small {
  display: block; font-size: 12.5px; line-height: 1.45; color: var(--ink-2); margin-top: 1px;
}
.modal .checkline.choice.off { opacity: .5; }
/* Flere klasser i samme kart: unntaket, og derfor lukket. Åpner læreren det,
   er det en liste å hake av i – tommelvennlig, med hele linja som treff. */
/* Trekanten fra nettleseren får stå: den sier at det er noe under her, og
   ingen egen ikon i settet sier det bedre. Derfor ingen display-endring – en
   `display: flex` her ville tatt markøren bort. */
.modal .npFlere > summary {
  cursor: pointer; font-weight: 600; font-size: 14px; color: var(--ink-2);
  padding: 7px 0; line-height: 1.4;
}
.modal .npFlere[open] > summary { color: var(--ink); }
.modal .npFlere .hint { font-size: 12.5px; line-height: 1.45; margin: 2px 0 6px; }
.modal .npKlasser {
  display: flex; flex-direction: column;
  border: 1px solid var(--line); border-radius: var(--r-md);
  background: var(--surface); padding: 4px 10px; max-height: 220px; overflow-y: auto;
}
.modal .npKlasser .checkline small { margin-left: 6px; }
.modal .checkline.choice:has(input:checked) small { color: var(--accent-ink); }
.modal textarea { font-family: var(--mono); font-size: 13px; width: 100%; }
.modal hr { border: none; border-top: 1px solid var(--line); }

/* Bilderutenettet: hvem som har bilde, og hvem som mangler, skal ses med ett blikk */
.photo-tools { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.photo-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(104px, 1fr));
  gap: 10px; max-height: 52vh; overflow-y: auto; padding: 2px;
}
.photo-cell { position: relative; }
.photo-card {
  width: 100%; display: flex; flex-direction: column; align-items: center; gap: 7px;
  padding: 10px 6px; min-height: var(--tap);
  border: 1px solid var(--line); border-radius: var(--r-md);
  background: var(--surface); color: var(--ink); font: inherit; cursor: pointer;
}
.photo-card:hover, .photo-card:focus-visible { border-color: var(--accent); }
.photo-card .ph-empty {
  width: 64px; height: 64px; border-radius: 50%; border: 2px dashed var(--line);
  display: grid; place-items: center; font-size: 22px; opacity: .7;
  color: var(--ink-3);
}
.photo-card .ph-empty .ico { width: 26px; height: 26px; stroke-width: 1.75; vertical-align: 0; }
.photo-card .ph-name { font-size: 12.5px; font-weight: 600; line-height: 1.2; overflow-wrap: anywhere; }
.photo-cell .ph-del {
  position: absolute; top: 0; right: 0; background: var(--surface);
  border: 1px solid var(--line); border-radius: 50%; min-width: 26px; min-height: 26px;
  padding: 0; font-size: 12px; line-height: 1;
}

/* Klasseliste */
.class-table-wrap { overflow-x: auto; }
table.class-table {
  border-collapse: collapse; background: var(--surface);
  border: 1px solid var(--line); border-radius: var(--r-md);
}
table.class-table th, table.class-table td { border: 1px solid var(--line-soft); padding: 0; }
table.class-table th { background: var(--surface-2); padding: 6px 8px; min-width: 140px; }
table.class-table th .col-head { display: flex; flex-direction: column; gap: 4px; }
table.class-table th input {
  border: none; background: transparent; font-weight: 700; font-size: 14px;
  width: 100%; padding: 2px 4px; min-height: 30px;
}
table.class-table th select { font-size: 12px; padding: 2px 4px; min-height: 28px; color: var(--ink-2); }
table.class-table td input {
  border: none; width: 100%; padding: 9px; font-size: 14.5px;
  background: transparent; border-radius: 0; min-height: var(--tap);
}
table.class-table td input:focus { background: var(--accent-soft); outline: none; }
table.class-table td.rownum {
  padding: 4px 8px; color: var(--ink-3); font-size: 12.5px; text-align: right;
  background: var(--surface-2); min-width: 34px; font-variant-numeric: tabular-nums;
}
table.class-table td.rowdel { padding: 0 4px; }
table.class-table td.empty-row { padding: 14px; color: var(--ink-2); }
.del-x {
  border: none; background: none; color: var(--ink-3); cursor: pointer;
  font-size: 15px; padding: 6px; border-radius: var(--r-sm); min-width: 32px; min-height: 32px;
}
.del-x:hover { color: var(--warn); background: var(--warn-soft); }

/* Elevtabellen: klassens egne kolonner, der de av dem elevlista har gitt en
   rolle får riktig redigering – nedtrekksliste, fagvelger. Stilene sto før i
   modulens eget ark; de bor her fordi tabellen nå er en del av klassesida. */
table.class-table th.el-sorter {
  cursor: pointer; user-select: none; text-align: left; font-size: 13px; white-space: nowrap;
}
table.class-table th.el-sorter:hover { color: var(--accent-ink); }
table.class-table th.el-sorter.stigende::after { content: ' ▲'; font-size: 9px; }
table.class-table th.el-sorter.synkende::after { content: ' ▼'; font-size: 9px; }
.kol-merke { color: var(--ink-3); font-size: 10px; }
table.class-table td select {
  border: none; width: 100%; padding: 8px 6px; font-size: 14.5px; font-family: inherit;
  background: transparent; color: inherit; min-height: var(--tap); border-radius: 0;
}
table.class-table td select:focus { background: var(--accent-soft); outline: none; }
input.el-gjettet { font-style: italic; color: var(--ink-2); }
/* En fødselsdato appen ikke kjente igjen. Verdien blir stående som læreren
   skrev den – markeringen er en beskjed, ikke en retting. */
input.el-udato { color: var(--warn); font-style: italic; }

/* ---- Bursdagslinja ----
   Står over elevtabellen og over klassekartet, og BARE i lærermodus: se
   «Fødselsdager» i app.js. Den er en opplysning, ikke en handling – derfor
   ingen knapp og ingen farge som roper. */
.bursdag-linje {
  display: flex; align-items: center; gap: 8px;
  background: var(--accent-soft); color: var(--accent-ink);
  border-radius: var(--r-md); padding: 8px 12px; margin-bottom: 8px;
  font-size: 13.5px; font-weight: 700;
}
.bursdag-linje svg { flex: none; }
/* «Neste bursdag om tolv dager» er en opplysning å planlegge etter, ikke et
   varsel om noe som skjer nå. Den skal derfor ikke se ut som ett. */
.bursdag-linje.neste {
  background: none; color: var(--ink-2); font-weight: 500;
  padding: 4px 0 2px; margin-bottom: 4px;
}
.bursdag-linje.neste svg { opacity: .6; }
.bursdag-klasser { display: grid; gap: 2px; margin: 6px 0 10px; }

table.class-table th.el-merk, table.class-table td.el-merk {
  min-width: 30px; width: 30px; text-align: center; padding: 0 4px; vertical-align: middle;
}
/* Haken skal stå midt i raden, ikke på tekstlinja: uten dette arver den
   baseline fra cella og henger et par piksler for høyt. */
table.class-table .el-merk input[type=checkbox] {
  margin: 0; vertical-align: middle; display: block; margin-inline: auto;
}
table.class-table td.rownum { vertical-align: middle; }
.el-radnr {
  border: 0; background: none; padding: 4px 2px; font: inherit; font-size: 12.5px;
  color: var(--ink-3); cursor: pointer; border-radius: var(--r-sm);
  font-variant-numeric: tabular-nums; min-width: 22px;
}
.el-radnr:hover, .el-radnr:focus-visible {
  background: var(--accent-soft); color: var(--accent-ink);
}
table.class-table td.el-bilde { padding: 3px; text-align: center; min-width: 46px; }
.el-bildeknapp {
  border: none; background: none; cursor: pointer; padding: 2px;
  border-radius: var(--r-sm); line-height: 0;
}
.el-bildeknapp:hover { background: var(--surface-2); }
.el-bildeknapp .avatar { width: 34px; height: 34px; border-radius: 50%; object-fit: cover; }
/* Tom bildeplass. Her sto det et kamera i hver eneste rad – tjuefire like
   ikoner nedover én kolonne, ved siden av en overskrift som allerede sier
   «Bilde». En stiplet sirkel i avatarens form sier det samme uten støyen, og
   viser samtidig hvor stort bildet blir. */
.el-ingen-bilde {
  display: inline-block; width: 26px; height: 26px; margin: 4px;
  border: 1.5px dashed var(--line); border-radius: 50%;
}
.el-bildeknapp:hover .el-ingen-bilde { border-color: var(--accent); }

/* Verktøylinja over tabellen, og linja som dukker opp når rader er merket.
   Knappene står i `.tool-group`-er som i klassekartets verktøylinje, og av
   samme grunn – se «Verktøylinje» lenger nede. */
.el-verktoy { display: flex; flex-wrap: wrap; gap: 8px 16px; align-items: center; margin-bottom: 10px; }
/* Siste gruppa er det som går UT av appen – kalenderfila, CSV-en og
   klassefila. Den står for seg til høyre, og er derfor også den som brekker
   ned først når linja blir trang. */
.el-verktoy-hoyre { margin-left: auto; display: inline-flex; align-items: center; gap: 6px; }
.el-bulk {
  display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin-bottom: 10px;
  padding: 8px 10px; border-radius: var(--r-md);
  background: var(--accent-soft); border: 1px solid var(--accent);
}
.el-bulk[hidden] { display: none; }
.el-bulk input, .el-bulk select { min-height: var(--tap); }
.el-bulk input { max-width: 12em; }

/* Programfagcella: merkene med faggruppefarge, og velgeren de åpner */
.el-fagknapp {
  width: 100%; min-height: var(--tap); border: 0; background: transparent;
  padding: 6px 8px; text-align: left; cursor: pointer; font: inherit; color: inherit;
  display: flex; flex-wrap: wrap; gap: 3px; align-items: center;
}
.el-fagknapp:hover { background: var(--surface-2); }
.el-fagmerke {
  font-size: 11px; font-weight: 700; border-radius: var(--r-sm);
  padding: 2px 5px; white-space: nowrap;
}
/* Faget går i flere grupper og eleven er ikke plassert i noen av dem */
.el-fagmerke.el-uplassert { outline: 1.5px dashed var(--warn); outline-offset: 1px; }
/* Fellesfag eleven IKKE har. Gjennomstreket, for merket viser et unntak – de
   andre fellesfagene står ikke i cella i det hele tatt. */
.el-fagmerke.el-fritak {
  background: var(--surface-2); color: var(--ink-2);
  border: 1px solid var(--line); text-decoration: line-through;
}

.el-popover {
  position: absolute; z-index: 60; width: 280px; max-height: 60vh; overflow-y: auto;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r-md); box-shadow: 0 8px 28px var(--shadow-2); padding: 10px;
}
.el-popgruppe { border-top: 1px solid var(--line-soft); padding: 6px 0; position: relative; }
.el-popgruppe:first-child { border-top: 0; }
.el-popfarge { display: block; height: 3px; border-radius: 2px; margin-bottom: 6px; }
.el-popover label {
  display: flex; align-items: baseline; gap: 6px; padding: 5px 4px;
  border-radius: var(--r-sm); cursor: pointer;
}
.el-popover label:hover { background: var(--surface-2); }
.el-popover .hint { font-size: 12px; }
/* Fagraden: selve valget til venstre, gruppa til høyre på fag som går i
   flere. Knappen er både status og vei tilbake til gruppemenyen. */
.el-poprad { display: flex; align-items: center; gap: 4px; }
.el-poprad label { flex: 1 1 auto; min-width: 0; }
.el-gruppeknapp {
  flex: 0 0 auto; max-width: 45%; font-size: 11.5px; padding: 3px 7px;
  border: 1px solid var(--line); border-radius: var(--r-sm);
  background: var(--surface-2); color: var(--ink-2); cursor: pointer;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.el-gruppeknapp:hover { border-color: var(--accent); color: var(--accent-ink); }
.el-gruppeknapp[hidden] { display: none; }
/* Faget er valgt, men eleven er ikke plassert i noen gruppe ennå */
.el-gruppeknapp.el-mangler { border-color: var(--warn); color: var(--warn); border-style: dashed; }
/* Gruppemenyen spretter opp inntil fagraden, ikke under den */
.el-popover-gruppe { width: 220px; }
.el-popover-gruppe label { font-size: 13.5px; }
.el-popover label:focus-within { background: var(--accent-soft); box-shadow: inset 0 0 0 2px var(--accent); }
.el-popbolk { font-size: 11.5px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--ink-3); margin: 4px 0 2px; }
.el-pophjelp { font-size: 11.5px; color: var(--ink-3); border-top: 1px solid var(--line-soft); margin-top: 6px; padding-top: 6px; }

/* Eksport av klasselista. Kolonnene i to spalter når det er plass: en klasse
   med fagvalg har lett et dusin, og en enkeltspaltet liste ville dyttet
   formatvalget og størrelsen under skjermkanten – nettopp det læreren skal se
   FØR hen trykker. */
.el-eksportkol { display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: 8px; }
.el-eksportformat { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.el-eksportformat .hint { font-size: 12.5px; }

/* Tastehjelpen under tabellen */
.class-table-wrap + .hint kbd, .hint kbd {
  font-family: var(--mono); font-size: 12px; background: var(--surface-2);
  border: 1px solid var(--line); border-radius: var(--r-sm); padding: 1px 5px;
}

/* Verktøylinje.

   EN VERKTØYLINJE ER EN SETNING MED KOMMA, IKKE EN POSE MED ORD. Knappene står
   i `.tool-group`-er etter hva de gjør, og linja brytes MELLOM gruppene og
   aldri inni dem. Det er hele poenget med gruppene: en rad med løse knapper
   bryter der den tilfeldigvis går tom for plass, så den samme verktøylinja
   deler seg på hvert sitt sted på lærerens PC, på tavleskjermen og på
   nettbrettet – og knappen læreren så sist står et annet sted i dag. Med
   grupper er bruddet det samme overalt: én gruppe per rad, i rekkefølge.

   Løse knapper rett i linja er derfor unntaket, ikke regelen. Legger du en ny
   knapp, legg den i gruppa den hører til – finnes ikke gruppa, er det verdt å
   spørre hvorfor knappen skal stå der. Det ene skillet mellom gruppene er
   LUFTA: den vannrette avstanden i linja er dobbelt så stor som inni ei
   gruppe. En loddrett strek ville sagt det tydeligere, men bare så lenge den
   ikke havner sist på ei linje – og hvor bruddet lander, er nettopp det ingen
   av oss vet på forhånd. */
.plan-toolbar { display: flex; gap: 8px 16px; flex-wrap: wrap; align-items: center; margin-bottom: 12px; }
/* Underraden («resten») flyter inn på samme rad som hovedknappene når det er
   plass – i romredigeringen er den bare to knapper, og en egen rad ville stått
   halvtom. Er den for bred, flytter den seg samlet ned og bryter innvendig,
   alltid på samme sted: mellom verktøygruppene.
   På telefon ligger hele underraden bak «⋯ Mer». */
.toolbar-rest {
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px 16px;
  flex: 0 1 auto; min-width: 0;
}
/* Gruppa oppfører seg som ÉN knapp i linja: får den ikke plass, flytter den seg
   hel ned på neste linje i stedet for å slippe fra seg den siste knappen.
   Etikett + kontroll («Sett fra: Lærer/Elev») er den samme regelen sett fra den
   andre siden, og trengte den først.

   `flex-wrap: wrap` her ser ut som det motsatte av det som står over, men er
   nødvendig – og skader ikke. Flexbox legger elementene på linjer etter hvor
   brede de er UTEN å bryte, så to grupper som ikke får plass ved siden av
   hverandre havner på hver sin linje; ingen av dem bryter innvendig. Wrappen
   slår først inn når ei gruppe er alene bredere enn linja, og da er det
   virkelig ikke noe alternativ: uten den renner den siste knappen ut av sida
   (og hele sida begynner å rulle sidelengs). `min-width: 0` er det som lar den
   krympe så langt. */
.tool-group { display: inline-flex; flex-wrap: wrap; align-items: center; gap: 8px; min-width: 0; }
/* Knappene i gruppa krymper ikke – gruppa bryter heller. En knapp som er
   presset smalere enn teksten sin, er en knapp læreren ikke kan lese. */
.tool-group > * { flex: 0 0 auto; }
.btn-more-tools { display: none; }

/* --------------------------------------------------------------- 6. Rom */

.room-outer {
  position: relative; overflow: hidden;
  border: 1px solid var(--line); border-radius: var(--r-lg);
  background: var(--surface);
}
.room-inner { position: absolute; top: 0; left: 0; transform-origin: top left; }

/* Ekte rutenett i romredigeringen: tykk linje hver 120 på tvers og 60 nedover
   – nøyaktig én standardpult (= DESK_W × DESK_H) – og en fin strek i hvert
   feste (= SNAP_STEG, en halv pultbredde). Den tykke ruta er målestokken «én
   pult», så læreren kan telle plass i pulter i stedet for i tall, og HVER strek
   er et sted pulten faktisk kan feste seg. Det siste er hele poenget med at den
   fine ruta ble grovere: et rutenett som viser steder pulten ikke kan stå, er
   et rutenett som lyver om hvor presis man må være.
   --scale settes fra JS slik at strekene holder seg på ~1 skjermpiksel. */
.room-editor .room-inner {
  --hair: calc(1px / var(--scale, 1));
  background-image:
    linear-gradient(var(--grid-strong) var(--hair), transparent var(--hair)),
    linear-gradient(90deg, var(--grid-strong) var(--hair), transparent var(--hair)),
    linear-gradient(var(--grid) var(--hair), transparent var(--hair)),
    linear-gradient(90deg, var(--grid) var(--hair), transparent var(--hair));
  background-size: 120px 60px, 120px 60px, 60px 60px, 60px 60px;   /* = SNAP_STEG */
}
.room-editor .room-inner.grid-coarse {
  background-image:
    linear-gradient(var(--grid-strong) var(--hair), transparent var(--hair)),
    linear-gradient(90deg, var(--grid-strong) var(--hair), transparent var(--hair));
  background-size: 120px 60px, 120px 60px;
}
.room-editor .room-inner.grid-off { background-image: none; }

/* Hjelpelinjer under flytting: h = vannrett (lik y), v = loddrett (lik x) */
.align-guide { position: absolute; z-index: 6; pointer-events: none; }
.align-guide.h { left: 0; width: 100%; height: 0; border-top: 2px dashed var(--accent); }
.align-guide.v { top: 0; height: 100%; width: 0; border-left: 2px dashed var(--accent); }

/* Klassekartet beholder bare et svakt spor av rutenettet – nok til å ane
   gulvet. Samme pultrute som i redigeringen, bare i den svake fargen. */
.room-outer:not(.room-editor) .room-inner {
  --hair: calc(1px / var(--scale, 1));
  background-image:
    linear-gradient(var(--grid) var(--hair), transparent var(--hair)),
    linear-gradient(90deg, var(--grid) var(--hair), transparent var(--hair));
  background-size: 120px 60px, 120px 60px;
}

/* Tavlesonen: her kan ingen pult stå */
.board-zone {
  position: absolute; left: 0; right: 0; top: 0; height: 100px;   /* = BOARD_ZONE */
  background: var(--surface-2); border-bottom: 1px dashed var(--line);
}
.board-zone-tag {
  position: absolute; left: 8px; top: 6px; font-size: 11px; font-weight: 700;
  letter-spacing: .08em; text-transform: uppercase; color: var(--ink-3);
}
.board-bar {
  position: absolute; left: 15%; width: 70%; height: 34px;
  background: var(--ink); color: var(--ground); border-radius: var(--r-sm);
  display: flex; align-items: center; justify-content: center;
  font-size: 15px; letter-spacing: .25em; font-weight: 700;
}

.desk {
  position: absolute; border: 2px solid var(--ink-3); border-bottom-width: 4px;
  border-radius: 8px; background: var(--surface);
  display: flex; align-items: center; justify-content: center;
  text-align: center; font-size: 14px; line-height: 1.15; font-weight: 700;
  color: var(--ink);
  user-select: none; touch-action: none; overflow: hidden; padding: 2px;
}
.desk .desk-num { position: absolute; top: 1px; left: 5px; font-size: 10px; color: var(--ink-3); font-weight: 600; }

/* Gruppefarge på pulten. Fargen kommer inn som `--dc`, ikke som ferdig regel,
   fordi den samme fargen må gjøres lysere i mørkt tema for å synes mot den
   mørke flata – og fordi utskriften skal ha nøyaktig samme verdi som skjermen. */
.desk.has-color { background: var(--dc-fill); border-color: var(--dc); }
/* «:not(.warn)» o.l. holder advarsel og markering foran gruppefargen, slik det
   også er i lyst tema – uten det ville den høyere spesifisiteten her vunnet. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .desk.has-color:not(.warn):not(.held):not(.drop-hover),
  :root:not([data-theme="light"]) .hexdesk.has-color:not(.warn) .hex-face {
    border-color: color-mix(in oklab, var(--dc) 68%, #E7EEEB);
    stroke: color-mix(in oklab, var(--dc) 68%, #E7EEEB);
  }
}
:root[data-theme="dark"] .desk.has-color:not(.warn):not(.held):not(.drop-hover),
:root[data-theme="dark"] .hexdesk.has-color:not(.warn) .hex-face {
  border-color: color-mix(in oklab, var(--dc) 68%, #E7EEEB);
  stroke: color-mix(in oklab, var(--dc) 68%, #E7EEEB);
}
.desk.empty {
  border-style: dashed; border-bottom-style: solid;
  border-color: var(--line); border-bottom-color: var(--ink-3);
  color: var(--ink-3); font-weight: 500;
}
/* i romredigeringen er alle pulter «tomme» – der er de møbler, ikke ledige plasser */
.room-editor .desk.empty { border-style: solid; border-color: var(--ink-3); color: var(--ink-3); }
.desk.occupied { cursor: grab; }
.desk.drop-hover { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
.desk.warn { border-color: var(--warn); box-shadow: 0 0 0 2px var(--warn-soft); }
.desk .warn-badge { position: absolute; top: -1px; right: 2px; line-height: 0; }
.desk .warn-badge .ico { width: 13px; height: 13px; vertical-align: 0; }
/* Brikkene på sekskantbord er trangere enn en pult – der står merket rett i teksten */
.seat-chip > .ico { width: 13px; height: 13px; vertical-align: -.12em; }
.desk .stu-dot {
  position: absolute; bottom: 3px; right: 4px; width: 10px; height: 10px;
  border-radius: 50%; border: 1px solid rgba(0,0,0,.25);
}
.desk.paint-target { cursor: crosshair; }
.desk .desk-name { display: block; max-width: 100%; overflow: hidden; }

.room-editor .desk { cursor: grab; }
.room-editor .desk.selected { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
.room-editor .desk.dragging { box-shadow: 0 8px 20px var(--shadow-2), 0 0 0 3px var(--accent-soft); z-index: 5; }

/* Sekskantbord */
.hexdesk { position: absolute; user-select: none; touch-action: none; }
.hexdesk svg { position: absolute; inset: 0; width: 100%; height: 100%; }
.hexdesk .hex-face { fill: var(--surface); stroke: var(--ink-3); stroke-width: 3; }
.hexdesk.has-color .hex-face { fill: var(--dc-fill); stroke: var(--dc); }
.hexdesk.selected .hex-face { stroke: var(--accent); stroke-width: 4; }
.hexdesk.warn .hex-face { stroke: var(--warn); }
.hexdesk .hex-num {
  position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
  font-size: 11px; color: var(--ink-3);
}
.room-editor .hexdesk { cursor: grab; }
/* Målene er SEAT_CHIP_W/H i app.js, som plasserer og dreier lappen – hold dem
   like. Lappen ligger langs kanten eleven sitter ved, og skriften er like stor
   som på en enkel pult: navnet skal kunne leses på tvers av klasserommet, ikke
   bare på skjermen til læreren. */
.seat-chip {
  position: absolute; width: 100px; height: 28px; line-height: 24px; text-align: center;
  border: 1.5px solid var(--line); border-radius: var(--r-sm); background: var(--surface);
  color: var(--ink); font-size: 14px; font-weight: 700; overflow: hidden; white-space: nowrap;
  text-overflow: ellipsis; user-select: none; touch-action: none; padding: 0 3px;
}
.seat-chip.empty { border-style: dashed; background: transparent; color: var(--ink-3); }
.seat-chip.occupied { cursor: grab; }
.seat-chip.warn { border-color: var(--warn); background: var(--warn-soft); box-shadow: 0 0 0 2px var(--warn-soft); }
.seat-chip.drop-hover { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
.seat-chip.paint-target { cursor: crosshair; }
.room-editor .seat-chip { pointer-events: none; }

/* Plassvelgeren for sekskantbordet: bordet i miniatyr, med en knapp på hver
   side. Den står i samme rotasjon som bordet på gulvet, slik at siden læreren
   trykker på her er den siden eleven sitter på der. */
.hex-seats { position: relative; display: inline-block; width: 64px; height: 64px; flex: 0 0 auto; }
.hex-seats svg { position: absolute; inset: 0; width: 100%; height: 100%; }
.hex-seats polygon { fill: var(--surface-2); stroke: var(--ink-3); stroke-width: 2; }
.hex-seat {
  position: absolute; width: 11px; height: 11px; padding: 0; transform: translate(-50%, -50%);
  border: 1.5px dashed var(--ink-3); border-radius: 50%; background: var(--surface);
  cursor: pointer;
}
.hex-seat:hover { border-color: var(--accent); }
.hex-seat.on { border: 1.5px solid var(--accent); background: var(--accent); }
.hex-seat:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.room-editor .room-inner { cursor: crosshair; }
.selection-rect {
  position: absolute; border: 1.5px dashed var(--accent);
  background: var(--accent-soft); opacity: .55; pointer-events: none; z-index: 5;
}

/* ------------------------------------------------------- Elevbilder

   Portrettet er alltid rundt og alltid ved siden av navnet – aldri i stedet
   for det. Ansikter er lette å forveksle, og bildet skal hjelpe deg å kjenne
   igjen eleven, ikke være den eneste opplysningen på pulten. */

.avatar {
  display: block; flex-shrink: 0; width: 40px; height: 40px;
  border-radius: 50%; object-fit: cover;
  background: var(--surface-2); border: 1px solid var(--line-soft);
}
.avatar-lg { width: 64px; height: 64px; }
.avatar-sm { width: 28px; height: 28px; }
.avatar-xs { width: 20px; height: 20px; border-width: 0; }

/* Pulten roteres med rommet, men ansiktet og navnet skal stå oppreist –
   derfor snus hele «forsiden» tilbake, ikke bare navnet. */
.desk-face {
  display: flex; align-items: center; justify-content: center; gap: 5px;
  max-width: 100%; min-width: 0;
}
.desk.has-photo .desk-name { font-size: 12.5px; text-align: left; }
.desk.has-photo .desk-face { justify-content: flex-start; padding-left: 1px; }
/* pult på tvers: bildet over navnet, innenfor pultens smale side */
.desk.face-stacked .desk-face {
  flex-direction: column; justify-content: center; gap: 1px; padding-left: 0;
}
.desk.face-stacked .avatar { width: 30px; height: 30px; }
.desk.face-stacked .desk-name { font-size: 10.5px; text-align: center; line-height: 1.1; }

.seat-chip.has-photo {
  display: flex; align-items: center; gap: 3px;
  padding: 0 3px 0 2px; text-align: left; line-height: 1.1;
}
.seat-chip .chip-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Kolonnene læreren har lagt på pulten (pultInfo i app.js): små linjer under
   navnet, i lærerens kart og på utskriften – aldri på storskjermen. Grå og
   halvfet, så navnet fortsatt er det man ser først på en pult man går forbi.

   `.desk-text` er kolonnen navnet og linjene står i. Den finnes bare når det
   ER linjer: uten dem tegnes navnet rett i `.desk-face`, som før. */
.desk-text { display: flex; flex-direction: column; min-width: 0; max-width: 100%; }
.desk .desk-info {
  font-size: 10px; font-weight: 600; line-height: 1.15; color: var(--ink-2);
  overflow: hidden; margin-top: 1px;
}
/* Lappen på et sekskantbord er 28 px høy og har ikke to linjer å gi bort:
   navnet krymper i stedet, og linja under blir så liten den kan bli og
   fortsatt leses av den som står ved bordet. */
.seat-chip.has-info { display: flex; align-items: center; gap: 3px; line-height: 1.05; }
.seat-chip.has-info .chip-text { min-width: 0; flex: 1; }
.seat-chip.has-info .chip-name { font-size: 12px; display: block; }
.seat-chip .chip-info {
  display: block; font-size: 9px; font-weight: 600; color: var(--ink-2);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* Rollen gruppa har trukket, under navnet på pulten (se «Rollen på pulten» i
   app.js for hvorfor den – og bare den – står på en skjerm klassen ser på).

   Den skal leses som en beskjed og ikke som en del av navnet: aksentfarget,
   litt sperret og i versaler, tydelig mindre enn navnet. Fargen kommer fra
   aksentfamilien og ikke som en fast verdi, slik at den følger med når
   klasseromsmodus bytter aksenten fra grønn til lilla.

   --accent-ink og ikke --accent, og det er et måltall og ikke en smak.
   Pultflata er gruppefargen med 20 % dekkevne, og på de mørkeste
   palettfargene ble --accent for svak i LYST tema: Mørkerød målte 4,2:1 og
   Mørkeblå 4,4:1 mot flata si – under AA for vanlig tekst. --accent-ink er
   mørkere i lyst tema og lysere i mørkt, altså familiens tekstfarge, og løfter
   det laveste av de 52 målingene (13 farger × lyst/mørkt × lærer/klasserom)
   til 6,0:1. Tallene måles i layout-testen, se «Kontrasten på rolleteksten» i
   test/layout/testserver.js – legger noen til en palettfarge, sier den fra. */
.desk-rolle {
  display: block; font-family: var(--display); font-weight: 700;
  font-size: 10px; line-height: 1.1; letter-spacing: .05em; text-transform: uppercase;
  color: var(--accent-ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  margin-top: 1px;
}
.present-room .desk .avatar { width: 42px; height: 42px; }

/* --------------------------------------------------------- 7. Klassekart */

.plan-layout { display: flex; gap: 16px; align-items: flex-start; }
.plan-main { flex: 1; min-width: 0; }
.warn-summary {
  margin: 10px 0 0; font-size: 13.5px; color: var(--warn); background: var(--warn-soft);
  border-radius: var(--r-md); padding: 10px 14px; font-weight: 600;
}
.warn-summary ul { margin: 4px 0 0 18px; font-weight: 400; }

#waitingPanel {
  /* Vokser forsiktig med vinduet: på en bred skjerm er det plass til både
     stort kart og litt romsligere venteliste. */
  width: clamp(216px, 21vw, 300px); flex-shrink: 0; background: var(--surface-2);
  border: 1px solid var(--line); border-radius: var(--r-lg); padding: 14px;
  position: sticky; top: 16px; max-height: calc(100vh - 32px);
  display: flex; flex-direction: column;
}
#waitingPanel h3 { font-size: 16px; margin-bottom: 2px; }
#waitingPanel .sub { font-size: 12.5px; color: var(--ink-2); }
#waitingPanel .wait-help { font-size: 12px; color: var(--ink-2); line-height: 1.45; margin: 6px 0 10px; }
#waitingArea {
  display: flex; flex-direction: column; gap: 6px;
  overflow-y: auto; min-height: 60px; border-radius: var(--r-md);
}
#waitingArea.drop-hover { outline: 2px dashed var(--accent); outline-offset: 3px; }
.wait-empty { color: var(--ink-2); font-size: 13px; padding: 8px 2px; }
/* Er kartet for flere klasser, deles venteområdet i bunker med klassenavnet
   over. Venteområdet skifter retning tre ganger på vei ned i bredde, og
   overskriften må følge med: en linje for seg der lappene ligger under
   hverandre eller bryter, og et skille MELLOM bunkene der de ligger på rad. */
.wait-class {
  font-size: 12px; font-weight: 700; letter-spacing: .04em;
  text-transform: uppercase; color: var(--ink-2);
  padding: 6px 2px 0;
}
.wait-class:first-child { padding-top: 0; }
.sheet-handle { display: none; }

.stu-chip {
  border: 1px solid var(--line); border-radius: var(--r-md);
  border-left: 6px solid var(--line);
  padding: 0 10px; min-height: var(--tap);
  background: var(--surface); color: var(--ink);
  font-size: 14px; font-weight: 600; cursor: grab;
  user-select: none; touch-action: none;
  display: flex; align-items: center; gap: 8px;
}
.stu-chip .stu-dot {
  width: 10px; height: 10px; border-radius: 50%; flex-shrink: 0;
  border: 1px solid rgba(0,0,0,.25);
}
.stu-chip .chip-sub { font-weight: 400; color: var(--ink-3); font-size: 12px; margin-left: auto; }

/* «I hånda»: trykk elev, så pult */
.stu-chip.held, .desk.held, .seat-chip.held {
  border-color: var(--accent); background: var(--accent-soft); color: var(--accent-ink);
  box-shadow: 0 0 0 3px var(--accent-soft);
}
.stu-chip.held { border-left-color: var(--accent); }
.holding .desk.empty { border-color: var(--accent); border-style: dashed; color: var(--accent); }
.holding .seat-chip.empty { border-color: var(--accent); color: var(--accent); }
.hold-bar {
  display: none; align-items: center; gap: 8px;
  background: var(--accent-soft); color: var(--accent-ink);
  border-radius: var(--r-md); padding: 8px 12px; margin-bottom: 8px;
  font-size: 13.5px; font-weight: 700;
}
.hold-bar.on { display: flex; }
.hold-bar .btn { margin-left: auto; }

/* Tretten farger + viskelær = fjorten ruter, og de deler seg i to rader på
   sju. Ikke åtte og seks: to like rader leses som ett felt, en skjev som en
   rad som gikk tom for plass. */
.palette {
  display: flex; gap: 6px; align-items: center; flex-wrap: wrap;
  max-width: 342px;
}
/* Få farger gir plass til større ruter – og en rute man treffer med tommelen */
.swatch {
  width: 42px; height: 42px; border-radius: 10px; flex: 0 0 auto;
  border: 2px solid var(--line); cursor: pointer; padding: 0;
}
.swatch.active { outline: 2px solid var(--ink); outline-offset: 2px; }
.swatch.none {
  background: repeating-linear-gradient(45deg, var(--surface), var(--surface) 4px, var(--line) 4px, var(--line) 8px);
}

.drag-ghost {
  position: fixed; z-index: 400; pointer-events: none; opacity: .9;
  transform: translate(-50%, -50%); box-shadow: 0 8px 24px var(--shadow-2);
  /* dreiningen settes fra JS når skyggen er over en plass ved et sekskantbord –
     den skal svinge på plass, ikke hoppe */
  transition: transform .12s ease;
}
@media (prefers-reduced-motion: reduce) { .drag-ghost { transition: none; } }
.perspective-label { font-size: 13px; color: var(--ink-2); margin-top: 8px; text-align: center; }
/* ---- Hent elever fra klassene ----

   Lista læreren blar gjennom for å sette sammen en undervisningsgruppe. Én
   utslåbar bolk per klasse, én rad per elev, med bildet ved siden av navnet:
   ansiktet er det raskeste å kjenne igjen, og det er nettopp gjenkjenning
   dette skal hjelpe med. Bolkene er høye, så lista får sin egen rulling i
   stedet for å skyve knappene ut av dialogen. */
#heListe { max-height: 46vh; overflow-y: auto; margin-top: 4px; }
.he-klasse { border-bottom: 1px solid var(--line-soft); }
/* Ingen display-overstyring her: en <summary> som ikke er `list-item` mister
   trekanten som sier at den kan åpnes, og den trekanten er hele affordansen. */
.he-klasse > summary { cursor: pointer; padding: 9px 2px; font-weight: 600; }
.he-klasse > summary .hint { margin-left: 8px; font-weight: 400; }
.he-klasse > summary:hover { color: var(--accent-ink); }
.he-klasse > [data-alle] { margin: 0 0 4px 18px; }
.he-elever { padding-bottom: 8px; }
.he-elev {
  display: flex; align-items: center; gap: 9px;
  padding: 4px 6px 4px 18px; border-radius: var(--r-sm); cursor: pointer;
}
.he-elev:hover { background: var(--surface-2); }
/* Allerede i gruppa: haken står på og er låst, og raden trer tilbake */
.he-har { color: var(--ink-2); cursor: default; }
.he-har:hover { background: none; }
.he-bilde { width: 26px; height: 26px; border-radius: 50%; object-fit: cover; flex: 0 0 auto; }
.he-tom { background: var(--surface-2); border: 1px solid var(--line); }
.he-navn { flex: 1 1 auto; min-width: 0; }

/* ---- Skoleklasse eller undervisningsgruppe ----

   To store knapper med forskjellen skrevet på, ikke to ord i en nedtrekksliste:
   spørsmålet er nettopp det mange ikke har tenkt over, og da må svaret kunne
   leses. Brukes både i dialogen for ny klasse og i veiviseren i elevlista, og
   bor derfor her og ikke i elevliste.css. `flex: 1 1 240px` gir dem hver sin
   halvdel på en skjerm og hver sin linje på en telefon, uten et bruddpunkt å
   vedlikeholde. */
.slagvalg { display: flex; flex-wrap: wrap; gap: 10px; margin: 14px 0 4px; }
.slagknapp {
  flex: 1 1 240px;
  /* .btn er en midtstilt linje med nowrap – dette er en tekstblokk */
  display: block; text-align: left; white-space: normal;
  padding: 12px 14px; min-height: 0;
}
.slagknapp b { display: flex; align-items: center; gap: 7px; font-size: 15px; }
.slagknapp span {
  display: block; margin-top: 5px; font-weight: 400; font-size: 12.5px;
  line-height: 1.4; color: var(--ink-2);
}
.slagknapp[aria-pressed="true"] { background: var(--accent-soft); border-color: var(--accent); }

/* En knapperekke som hører sammen – og som `.tool-group` er den ett element i
   verktøylinja: den krymper ikke og brytes ikke midt i. */
.seg-group { display: inline-flex; flex: 0 0 auto; background: var(--surface-2); border: 1px solid var(--line); border-radius: var(--r-md); padding: 3px; gap: 2px; }
.seg-group .btn { border: none; background: none; min-height: 30px; }
.seg-group .btn:hover { background: var(--surface); }
.seg-group .btn.active { background: var(--surface); color: var(--ink); box-shadow: 0 1px 2px var(--shadow); }

.only-mobile { display: none !important; }

/* ------------------------------------------------------- Nettbrett/telefon */

@media (max-width: 1023px) {
  #sidebar { width: 76px; padding: 14px 8px; align-items: stretch; }
  #sidebar h1 { font-size: 0; justify-content: center; margin-bottom: 14px; }
  #sidebar h1 .brand-mark { font-size: 22px; }
  #sidebar a {
    flex-direction: column; align-items: center; row-gap: 3px; column-gap: 0;
    text-align: center; padding: 10px 4px; font-size: 11.5px;
  }
  #sidebar a.active::before { left: -8px; }
  #sidebar .nav-sub { display: none; }
  #sidebar .nav-ico { font-size: 19px; }
  #sidebar .nav-title { font-size: 11.5px; line-height: 1.3; }
  .nav-sep { font-size: 0; margin: 8px 2px 2px; padding-top: 8px; }
  .nav-footer .btn { justify-content: center; font-size: 0; gap: 0; padding: 0; }
  .nav-footer .hint { display: none; }
  #main { padding: 18px 16px; }
  /* align-items styrer bredden når retningen er kolonne: uten stretch krymper
     .plan-main til tekstinnholdet sitt, og lerretet blir en stripe midt på. */
  .plan-layout { flex-direction: column; align-items: stretch; }
  #waitingPanel { width: 100%; position: static; max-height: none; }
  #waitingArea { flex-direction: row; flex-wrap: wrap; }
  .wait-class { flex: 0 0 100%; }
  .stu-chip { flex: 0 1 auto; }
  /* Ingen elever igjen å plassere: venteområdet krymper til en stripe i stedet
     for å legge seg som en tom boks under – eller over – kartet. */
  #waitingPanel.empty { padding: 8px 14px; }
  #waitingPanel.empty .wait-help, #waitingPanel.empty .sub { display: none; }
  #waitingPanel.empty h3 { font-size: 14px; color: var(--ink-2); }
  #waitingPanel.empty .wait-empty { padding: 0; }
}

@media (max-width: 719px) {
  body { font-size: 15px; }
  #app { flex-direction: column; }

  /* Sidemenyen blir bunnfaner */
  #sidebar {
    position: fixed; left: 0; right: 0; bottom: 0; top: auto;
    width: auto; height: auto; flex-direction: row; z-index: 100;
    border-right: none; border-top: 1px solid var(--line);
    background: var(--surface);
    padding: 6px 4px calc(6px + env(safe-area-inset-bottom, 0px));
    gap: 2px;
  }
  #sidebar h1 { display: none; }
  .nav-links { flex-direction: row; flex: 5 1 0; gap: 0; }
  .nav-sep { display: none; }
  #sidebar a {
    flex: 1 1 0; min-width: 0; text-align: center; padding: 6px 2px; min-height: 46px;
    flex-direction: column; align-items: center; justify-content: center;
    row-gap: 2px; font-size: 11px; background: none;
  }
  #sidebar .nav-ico { font-size: 19px; }
  #sidebar a.active { background: none; color: var(--accent); }
  #sidebar a.active::before { display: none; }
  #sidebar .nav-title { font-size: 11px; }
  /* Bunnfanene deler bredden på sju: et langt navn får kortformen sin her
     (`data-kort` i index.html), ellers legger «Vurderingsplan» seg over
     naboen. Teksten byttes og ikke brytes – «Vurderingspl-an» er ikke et ord. */
  #sidebar .nav-title[data-kort] { font-size: 0; }
  #sidebar .nav-title[data-kort]::after { content: attr(data-kort); font-size: 11px; }
  .nav-footer { display: none; }
  .nav-more {
    display: flex; flex: 1 1 0; flex-direction: column; align-items: center; justify-content: center;
    gap: 2px; min-height: 46px; border: none; background: none; color: var(--ink-2);
    font-family: inherit; font-size: 11px; font-weight: 600; cursor: pointer;
  }
  .nav-more span { font-size: 19px; line-height: 1; }

  #main { padding: 14px 14px calc(var(--tabbar-h) + 18px); }
  .page-head { gap: 8px; margin-bottom: 12px; }
  .page-head h2 { font-size: 21px; width: 100%; }
  .page-head input[type=text] { flex: 1 1 100%; }
  /* Knappene deler radbredden likt i stedet for å stå høyrestilt med tomrom
     til venstre – på telefon er hele raden uansett deres. */
  .page-head .head-actions { flex: 1 1 100%; margin-left: 0; gap: 6px; }
  .page-head .head-actions .btn { flex: 1 1 auto; min-width: 0; }
  /* Klassenavnet får sin egen linje i stedet for å presse seg inn ved siden
     av overskriften – på telefon er hele raden uansett dens. */
  .klasserom-head h2 { width: 100%; font-size: 21px; }
  .kr-velger, .kr-klassenavn { margin-left: 0; }
  .plan-toolbar > .btn, .plan-toolbar > .seg-group, .plan-toolbar > .tool-group,
  .toolbar-rest > .btn, .toolbar-rest > .seg-group,
  .toolbar-rest > .tool-group { flex: 1 1 auto; min-width: 0; }
  /* På telefon er linja alltid for smal til at ei gruppe holdes hel, så
     gruppene bryter innvendig (regelen står i `.tool-group`) – og da skal
     knappene dele bredden likt, som resten av linja. */
  .tool-group > .btn { flex: 1 1 auto; }
  .plan-toolbar .seg-group .btn { flex: 1 1 auto; }
  .btn { min-height: 46px; }
  .btn-sm { min-height: 38px; }
  .only-mobile { display: inline-flex !important; }
  .only-desktop { display: none !important; }

  /* Verktøylinje: hovedknapp synlig, resten bak «Mer» */
  .btn-more-tools { display: inline-flex; }
  .toolbar-rest {
    display: none; width: 100%; flex-wrap: wrap; gap: 8px;
    padding: 10px; margin-top: 2px;
    background: var(--surface-2); border: 1px solid var(--line); border-radius: var(--r-md);
  }
  .toolbar-rest.open { display: flex; }

  /* Venteområdet blir et bunnark */
  /* `top` fra sticky-regelen over må nullstilles: med både top og bottom satt
     strekker det faste arket seg over hele skjermen og legger seg oppå kartet. */
  #waitingPanel {
    position: fixed; left: 0; right: 0; top: auto; bottom: var(--tabbar-h); z-index: 90;
    width: auto; border: none; border-top: 1px solid var(--line);
    border-radius: var(--r-xl) var(--r-xl) 0 0;
    padding: 6px 12px 10px; box-shadow: 0 -8px 24px var(--shadow);
    max-height: 42vh;
  }
  #waitingPanel .wait-help { display: none; }
  #waitingPanel h3 { font-size: 15px; }
  .sheet-handle {
    display: block; width: 100%; border: none; background: none; padding: 4px 0 6px; cursor: pointer;
  }
  .sheet-handle::before {
    content: ''; display: block; width: 38px; height: 4px; margin: 0 auto;
    border-radius: 2px; background: var(--line);
  }
  #waitingArea { flex-direction: row; flex-wrap: nowrap; overflow-x: auto; padding-bottom: 4px; }
  #waitingPanel.open { max-height: 70vh; }
  #waitingPanel.open #waitingArea { flex-wrap: wrap; overflow-x: hidden; overflow-y: auto; }
  /* Lukket ligger lappene på én rad som ruller sidelengs; da er klassenavnet
     et skilt mellom bunkene, ikke en overskrift over dem. */
  .wait-class { flex: 0 0 auto; align-self: center; padding: 0 2px; }
  #waitingPanel.open .wait-class { flex: 0 0 100%; align-self: auto; padding: 6px 2px 0; }
  .stu-chip { flex: 0 0 auto; }
  #waitingPanel.empty { padding: 2px 12px 8px; }
  #waitingPanel.empty h3 { display: none; }
  .plan-layout { padding-bottom: 150px; }
  .plan-layout.no-waiting { padding-bottom: 96px; }
  .hold-bar.on { position: sticky; top: 0; z-index: 5; }

  /* Klasselista blir kort.

     Kortet er et rutenett med en egen topplinje: radnummeret (som åpner
     gjennomgangen på eleven), bildeknappen og slett-krysset står side om side
     der, og hver kolonne i klassen får en full linje under. Før lå numrene i
     en egen blokk over kortet og arvet `text-align: right` fra tabellen –
     altså rett under krysset, der de så ut som en feil. Topplinja sparer
     samtidig de to blokkene numrene og bildet hadde hver for seg. */
  .class-table-wrap table.class-table,
  .class-table-wrap tbody { display: block; width: 100%; }
  .class-table-wrap table.class-table { border: none; }
  .class-table-wrap .col-row { display: none; }
  .class-table-wrap tr {
    display: grid; grid-template-columns: auto auto 1fr auto;
    align-items: center; column-gap: 8px;
    border: 1px solid var(--line); border-radius: var(--r-md);
    background: var(--surface); margin-bottom: 10px; padding: 8px 10px 10px; position: relative;
  }
  .class-table-wrap td { display: block; border: none; padding: 0; grid-column: 1 / -1; }
  .class-table-wrap td.rownum { grid-column: 1; grid-row: 1; background: none; padding: 0; }
  .class-table-wrap td.el-bilde { grid-column: 2; grid-row: 1; padding: 0; text-align: left; }
  .class-table-wrap td.rowdel { grid-column: 4; grid-row: 1; }
  /* Nummeret er en knapp, ikke pynt: på telefon får den en flate å treffe */
  .class-table-wrap .el-radnr {
    display: grid; place-items: center;
    min-width: var(--tap); min-height: var(--tap);
    border-radius: var(--r-sm); background: var(--surface-2);
    color: var(--ink-2); font-size: 13.5px; font-weight: 700;
  }
  .class-table-wrap td[data-label]::before {
    content: attr(data-label); display: block;
    font-size: 11.5px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
    color: var(--ink-3); margin: 6px 0 2px;
  }
  /* Bildeknappen står i topplinja med nummeret – der er kameraet etikett nok */
  .class-table-wrap td.el-bilde::before { content: none; }
  .class-table-wrap td input {
    border: 1px solid var(--line); border-radius: var(--r-sm); background: var(--surface);
  }
  /* På telefon er raden et kort: hensyn-knappen får stå med tekst nederst,
     i stedet for å klemmes inn ved siden av slett-krysset. */
  .class-table-wrap td.rowrules { padding: 8px 0 2px; text-align: left; }
  .class-table-wrap .rule-badge { min-height: 40px; font-size: 13.5px; }
  .class-table-wrap td.empty-row { padding: 12px 0; }
  /* Merkeruta er for masseredigering – en skrivebordsjobb; på telefon er
     raden et kort, og haken ville bare tatt plass. */
  .class-table-wrap th.el-merk, .class-table-wrap td.el-merk { display: none; }
  .class-table-wrap td select {
    border: 1px solid var(--line); border-radius: var(--r-sm); background: var(--surface);
  }
  .el-verktoy-hoyre { margin-left: 0; }

  /* Lister med mange kolonner får rulle sidelengs */
  .list-wrap { margin: 0 -14px; padding: 0 14px; }
  table.list { min-width: 520px; }
  /* Kartlista har to datoer og en kolonne mer enn de andre. Presses de inn på
     520px, brekker kartnavnet over tre linjer – da er sidelengs rulling det
     minste onde: navnet er det læreren leter etter. */
  table.list.kartliste { min-width: 620px; }

  /* Modaler som fullskjermark */
  .modal-overlay { padding: 0; align-items: flex-end; }
  .modal {
    width: 100%; max-width: 100%; max-height: 92vh;
    border-radius: var(--r-xl) var(--r-xl) 0 0; border-bottom: none;
    padding: 18px 16px calc(18px + env(safe-area-inset-bottom, 0px));
  }
  .modal .modal-buttons .btn { flex: 1 1 auto; }
  #toasts { bottom: calc(var(--tabbar-h) + 12px); }
}

@media (prefers-reduced-motion: reduce) {
  * { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}
@media (prefers-reduced-motion: no-preference) {
  .btn, #sidebar a, .desk, .stu-chip, .seat-chip {
    transition: background-color .12s ease, border-color .12s ease, color .12s ease, box-shadow .12s ease;
  }
}

/* -------------------------------------------------------------- Hensyn */

/* Innholdet i hensyn-dialogene: modal-body gir bare luft mellom sine egne
   barn, og alt vårt ligger i ett enkelt <div>. Derfor luft her. */
.modal .stack { display: flex; flex-direction: column; gap: 12px; }
.modal .stack > .catalog-row + .catalog-row { margin-top: -4px; }
.modal .stack > .warn-summary { margin: 0; }
.modal .stack > .hint { margin: 0; }
.modal .field > .seg-group { align-self: flex-start; }
.modal .field > .hint-inline { margin-top: 1px; }
/* «Alle er til stede» hører til lista over seg, ikke til dialogen: den skal se
   ut som en snarvei under avkryssingen, ikke som en knapp på linje med
   «Trekk grupper». Derfor står den for seg selv i venstre kant. */
.modal .field > .gruppe-alle { align-self: flex-start; margin-top: 2px; }
/* Dialogen med frammøtekartet trenger bredden til et helt klasserom: pultene
   skal være store nok til å treffe med fingeren og til at navnet er til å lese.
   Uten kart holder den vanlige bredden. */
.modal.modal-vid { width: 860px; }

/* --- Frammøtekartet ved siden av spørsmålene ---

   Gruppeoppsettet spør om tre ting OG viser et helt klasserom. Står alt under
   hverandre, blir dialogen et tårn: på en vanlig lærer-PC (1366 × 768) er det
   omtrent 500 px med spørsmål før kartet begynner, og kartet får da under 200
   px igjen av de 90vh dialogen har. Navnene på pultene blir uleselige, og det
   er kartets eneste jobb.

   Skjermen er bred og lav. Da skal dialogen være det samme: valgene til
   venstre, klassekartet til høyre, med hele dialoghøyden til rådighet.
   Grensa på 900 px er den samme som gjør at frammøtet i det hele tatt starter
   i kartet – en smalere skjerm starter i lista, og der er én spalte riktig.
   Klassen `med-frammote` settes bare når det ER et kart å sette ved siden av;
   uten den står alt under hverandre som før. */
@media (min-width: 900px) {
  .modal .stack.med-frammote {
    display: grid; align-items: start;
    /* Kartspalta er den brede: spørsmålene til venstre er tre korte rader,
       mens kartet er et helt klasserom – og det er BREDDEN som avgjør hvor
       store navnene på pultene blir. Venstre spalte har likevel et gulv, slik
       at «Elever i hver gruppe / Antall grupper» får stå på én linje. */
    grid-template-columns: minmax(250px, 0.8fr) minmax(360px, 1.8fr);
    column-gap: 20px; row-gap: 12px;
  }
  .modal .stack.med-frammote > .frav-felt { grid-column: 2; }
  /* Er skjermen bred nok, får dialogen mer enn de 860 px `modal-vid` gir:
     to spalter deler bredden, og kartet er den ene av dem. `min()` gjør at en
     skjerm på akkurat 900 får den gamle bredden og ikke en dialog som stikker
     ut over kanten. */
  .modal.modal-vid.modal-todelt { width: min(1040px, 100%); }
}
.go-valg { display: flex; flex-direction: column; gap: 12px; min-width: 0; }

/* Overskrifta og kart/liste-bryteren deler linje: bryteren er et valg om
   HVORDAN det under vises, ikke et eget spørsmål. */
.frav-topp { display: flex; align-items: flex-end; justify-content: space-between; gap: 10px; flex-wrap: wrap; }
.frav-topp label { margin: 0; }

.frav-ramme { padding: 10px; }
/* Bredden settes i JS – kartet skaleres til å få plass i høyden også, og blir
   da smalere enn ramma si (se `ledigKartHoyde()`). Derfor `margin: auto`:
   et kart som klumpet seg i venstre kant ville sett ut som en feil. */
.frav-kart { position: relative; width: 100%; margin: 0 auto; }
/* Pultene i miniatyr. Navnet står midt på pulten slik det gjør i den store
   visningen, og skrifta skaleres med rommet – derfor settes font-size i JS. */
.frav-plass {
  position: absolute; display: flex; align-items: center; justify-content: center;
  padding: 0 2px; text-align: center; line-height: 1.05; overflow: hidden;
  border-radius: var(--r-sm); border: 1px solid var(--line);
  background: var(--surface); color: var(--ink);
  font-family: inherit; font-weight: 600;
}
button.frav-plass { cursor: pointer; }
button.frav-plass:hover { border-color: var(--accent); box-shadow: 0 0 0 2px var(--accent-soft); }
button.frav-plass:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
/* En tom pult er en pult ingen har fast plass ved – ikke en som er ledig i dag.
   Den er stiplet og blek, og lar seg ikke trykke på. */
.frav-plass.tom { background: var(--surface-2); border-style: dashed; border-color: var(--line-soft); }
/* Navnet på en pult som ligger på tvers reises med den, og leses nedenfra og
   opp – samme regel som på pulten i den store visningen. */
.frav-plass.staaende { writing-mode: vertical-rl; transform: rotate(180deg); }
/* Borte: pulten står tom i rommet, og skal se tom ut her også. */
.frav-plass.borte {
  background: var(--surface-2); color: var(--ink-3); border-style: dashed;
  text-decoration: line-through; opacity: .7;
}

/* De uten fast plass i kartet har ingen pult å trykke på, og står som navn
   under det. Samme to tilstander som pultene, i pilleform. */
.frav-utenfor { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.frav-chip {
  font-family: inherit; font-size: 13px; font-weight: 600; cursor: pointer;
  min-height: 32px; padding: 0 11px; border-radius: 999px;
  background: var(--surface); color: var(--ink); border: 1px solid var(--line);
}
.frav-chip:hover { border-color: var(--accent); background: var(--accent-soft); }
.frav-chip.borte {
  background: var(--surface-2); color: var(--ink-3); border-style: dashed;
  text-decoration: line-through;
}

/* Rollelista i gruppeoppsettet. Rekkefølgen betyr noe – den avgjør hvilke
   roller en liten gruppe får – så rollene står som en rekke merkelapper i den
   rekkefølgen de deles ut, ikke som en avkryssingsliste uten retning.
   Krysset fjerner én; feltet under legger til bakerst. */
.rolle-boks { margin-top: 8px; padding-left: 27px; }   /* på linje med teksten i avkryssingen */
.rolle-liste { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; margin-bottom: 8px; }
.rolle-chip {
  display: inline-flex; align-items: center; gap: 2px;
  font-size: 13px; font-weight: 600; padding: 0 2px 0 11px;
  min-height: 32px; border-radius: 999px;
  background: var(--accent-soft); color: var(--accent-ink); border: 1px solid var(--accent);
}
.rolle-chip button {
  display: inline-flex; align-items: center; justify-content: center;
  width: 26px; height: 26px; padding: 0; border: 0; border-radius: 50%;
  background: none; color: inherit; cursor: pointer; opacity: .65;
}
.rolle-chip button:hover, .rolle-chip button:focus-visible { opacity: 1; background: var(--surface); }
.rolle-chip .ico { width: 14px; height: 14px; }
.rolle-nytt { display: flex; gap: 8px; flex-wrap: wrap; }
.rolle-nytt input { flex: 1; min-width: 140px; }
.modal .rolle-nytt + .hint { margin-top: 6px; }

/* Hele klasselista skal kunne krysses av uten å rulle gjennom tretti navn, så
   navnene står i så mange spalter som dialogen har plass til. På en telefon
   blir det én, og lista ruller som før. */
.stu-picker.gruppe-elever {
  max-height: 46vh;
  display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); column-gap: 14px;
}

/* Knapp i elevlista: åpner hensynene for eleven */
.rule-badge {
  display: inline-flex; align-items: center; gap: 5px; white-space: nowrap;
  font-family: inherit; font-size: 12.5px; font-weight: 600;
  min-height: 36px; padding: 0 11px; border-radius: 999px; cursor: pointer;
  background: var(--surface); color: var(--ink-2); border: 1px solid var(--line);
  font-variant-numeric: tabular-nums;
}
.rule-badge:hover { border-color: var(--accent); background: var(--accent-soft); color: var(--accent-ink); }
.rule-badge.has { border-color: var(--accent); background: var(--accent-soft); color: var(--accent-ink); }
table.class-table td.rowrules { padding: 4px 8px; text-align: center; }

/* Vekt-merke: Må / Bør / Fint om */
.rule-w {
  display: inline-block; font-size: 11px; font-weight: 700; letter-spacing: .04em;
  text-transform: uppercase; padding: 2px 7px; border-radius: 999px; margin-right: 6px;
  background: var(--surface-2); color: var(--ink-2); border: 1px solid var(--line);
}
.rule-w.maa { background: var(--warn-soft); color: var(--warn); border-color: transparent; }
.rule-w.bor { background: var(--accent-soft); color: var(--accent-ink); border-color: transparent; }
.rule-line { font-size: 13.5px; color: var(--ink); }
.rule-filter {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  font-size: 13.5px; color: var(--ink-2);
}
.warn-summary + .warn-summary { margin-top: 8px; }

/* Relasjonskartet i Hensyn-dialogen (tegnRelasjonsKart i app.js). Dialogen
   blir bredere når kartet er med: ringen er hele poenget, og 470 px gir
   tretti navn for lite plass. */
.modal:has(.rel-kart) { width: 720px; }
.rel-kart { display: flex; flex-direction: column; gap: 8px; }
.rel-verktoy { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.rel-verktoy select { min-height: 36px; }
.rel-status { font-size: 13.5px; color: var(--ink); line-height: 1.45; min-height: 2.9em; }
.rel-sist { font-size: 12.5px; color: var(--ink-2); margin-top: -6px; }
.rel-gjengknapper { display: flex; flex-wrap: wrap; gap: 8px; }
.rel-ring { width: 100%; max-width: 560px; align-self: center; touch-action: manipulation; }
.rel-ring svg { display: block; width: 100%; height: auto; cursor: pointer; user-select: none; -webkit-user-select: none; }
.rel-elev circle { fill: var(--surface); stroke: var(--ink-3); stroke-width: 2; }
.rel-elev text { font: 600 13px var(--ui); fill: var(--ink); }
.rel-elev:focus { outline: none; }
.rel-elev:focus-visible circle { stroke: var(--accent); stroke-width: 4; }
.rel-elev:hover circle { stroke: var(--accent); }
.rel-elev.valgt circle, .rel-elev.merket circle { fill: var(--accent); stroke: var(--accent); }
.rel-elev.valgt text, .rel-elev.merket text { fill: var(--accent-ink); font-weight: 800; }
.rel-elev.knyttet text { font-weight: 800; }
.rel-elev.dim text { fill: var(--ink-3); }
.rel-par path, .rel-par .merke { fill: none; stroke-linecap: round; }
.rel-par.ikke path { stroke: var(--warn); }
.rel-par.sammen path { stroke: var(--ok); }
.rel-par.sammen .merke { fill: var(--ok); stroke: none; }
.rel-par.w-maa path { stroke-width: 3; }
.rel-par.w-bor path { stroke-width: 2; }
.rel-par.w-kjekt path { stroke-width: 2; stroke-dasharray: 5 4; }
.rel-par .merke { stroke-dasharray: none !important; stroke-width: 2.5 !important; }
.rel-par.dim, .rel-gjeng.dim, .rel-gjeng-nr.dim { opacity: .18; }
.rel-gjeng { fill: var(--warn-soft); fill-opacity: .7; stroke: var(--warn); stroke-width: 2; stroke-linejoin: round; }
.rel-gjeng.w-kjekt { stroke-dasharray: 5 4; }
.rel-gjeng.redigeres { stroke-width: 3.5; stroke-dasharray: 2 5; }
.rel-gjeng-nr circle { fill: var(--surface); stroke: var(--warn); stroke-width: 2; }
.rel-gjeng-nr text { font: 800 12px var(--ui); fill: var(--warn); text-anchor: middle; }
.rel-forklaring { display: flex; flex-wrap: wrap; gap: 6px 16px; font-size: 12px; color: var(--ink-2); justify-content: center; }
.rel-forklaring span { display: inline-flex; align-items: center; gap: 6px; }
.rel-forklaring svg { width: 28px; height: 12px; overflow: visible; }
.rel-listetittel { font-size: 14px; margin-top: 6px; }
@media (max-width: 560px) { .rel-elev text { font-size: 15px; } }

.warn-summary.hard { border: 1px solid var(--warn); }

/* Elevvelger i hensyn-dialogen */
.stu-picker {
  max-height: 190px; overflow-y: auto; border: 1px solid var(--line);
  border-radius: var(--r-md); padding: 6px 12px; background: var(--surface-2);
}
.stu-picker .checkline { min-height: 36px; }

/* Miniatyrkart som viser hvilke plasser en sone treffer */
.prev-wrap {
  border: 1px solid var(--line); border-radius: var(--r-md);
  background: var(--surface-2); padding: 8px;
}
.prev-map { position: relative; width: 100%; }
.prev-seat {
  position: absolute; border-radius: var(--r-sm);
  background: var(--surface); border: 1px solid var(--line-soft);
}
.prev-seat.hit { background: var(--accent); border-color: var(--accent); }
.prev-seat.pick { cursor: pointer; }
.prev-seat.pick:hover { border-color: var(--accent); box-shadow: 0 0 0 2px var(--accent-soft); }
.prev-board {
  position: absolute; background: var(--ink-3); color: var(--surface);
  border-radius: var(--r-sm); font-size: 8px; font-weight: 700; letter-spacing: .12em;
  display: flex; align-items: center; justify-content: center; overflow: hidden;
}
.prev-tools { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; margin-top: 6px; }
.prev-tools select { flex: 1 1 140px; }

/* --------------------------------------------------- Sperrede pulter */

/* Sperret = står i rommet, men er ikke i bruk i dette kartet */
.desk.blocked, .seat-chip.blocked {
  background: repeating-linear-gradient(-45deg,
    var(--surface-2), var(--surface-2) 5px, var(--line-soft) 5px, var(--line-soft) 10px);
  border-style: dashed; border-color: var(--line); color: var(--ink-3);
}
.desk.blocked .desk-name, .seat-chip.blocked { font-weight: 600; }
.block-target { cursor: pointer; }
.block-target:hover { border-color: var(--ink-2); box-shadow: 0 0 0 3px var(--line-soft); }

/* Modusrad – den samme formen for sperring, makkerpar og fargelegging.
   Tre moduser som utelukker hverandre skal se like ut: da er raden i seg selv
   svaret på «hvilken hatt har appen på nå». */
.paint-bar, .block-bar, .makker-bar {
  display: none; align-items: center; gap: 10px; flex-wrap: wrap;
  background: var(--surface-2); border: 1px solid var(--line);
  border-radius: var(--r-md); padding: 8px 12px; margin-bottom: 10px;
  font-size: 13.5px; color: var(--ink-2);
}
.paint-bar.on { display: flex; }
/* Hintet skyver «Ferdig» ut til høyre, slik teksten gjør i de to andre radene */
.paint-bar #paintHint { margin-right: auto; }
.paint-bar label { font-weight: 600; }

.block-bar {
  display: none; align-items: center; gap: 10px; flex-wrap: wrap;
  background: var(--surface-2); border: 1px solid var(--line);
  border-radius: var(--r-md); padding: 8px 12px; margin-bottom: 10px;
  font-size: 13.5px; color: var(--ink-2);
}
.block-bar.on { display: flex; }
.block-bar #blockText { margin-right: auto; }

/* ------------------------------------------------------------ Makkerpar */

/* Pilene ligger i ett svg-lag oppå pultene, i romkoordinater. Laget slipper
   trykk gjennom til pultene under; bare selve pila tar imot. */
.makker-lag { position: absolute; inset: 0; pointer-events: none; z-index: 4; }
/* `fill: none`, ikke bare på polyline-regelen under: en trio som ikke står på
   rekke er en polyline med en knekk, og en fylt polyline maler igjen trekanten
   mellom endene. Med `fill` her ville den mer spesifikke regelen vunnet, og
   feilen viser seg BARE når de tre ikke ligger på linje. */
.makker-lag .makker-strek { fill: none; stroke: var(--accent-ink); }
/* Pilspissen skal skifte farge sammen med streken den sitter på. `context-stroke`
   gjør nettopp det; nettlesere som ikke kan det, faller på linja over og får
   spissen i den vanlige fargen. */
.makker-lag #makkerpil path { fill: var(--accent-ink); fill: context-stroke; }
/* Polylinjer: en gruppe på tre er ÉN strek med en knekk, ikke to piler.
   `fill: none` er ikke pynt – uten den fyller nettleseren flata mellom
   endepunktene i en polyline som var det en trekant. */
.makker-lag polyline { fill: none; stroke-linejoin: round; }
.makker-lag .makker-strek { stroke-width: 4; stroke-linecap: round; }
/* Knuten på plassen i midten av en trio: uten den kunne streken leses som to
   par som tilfeldigvis rørte hverandre. */
.makker-lag .makker-knute { fill: var(--accent-ink); stroke: none; }
.makker-modus .makker-lag .makker-pil:hover .makker-knute,
.makker-modus .makker-lag .makker-pil:focus-visible .makker-knute { fill: var(--warn); }
/* Streken under pila, i sidefargen: pila skal leses også der den krysser en
   farget pult eller et navn. */
.makker-lag .makker-halo {
  stroke: var(--surface); stroke-width: 11; stroke-linecap: round; opacity: .85;
}
/* Treffflata er bredere enn pila – den skal kunne trykkes med en finger. Den
   tar bare imot i makkermodus: står pilene framme fordi de skal være med på
   utskriften, er de en tegning og ikke en knapperad. */
.makker-lag .makker-treff { stroke: transparent; stroke-width: 26; pointer-events: none; }
.makker-modus .makker-lag .makker-treff { pointer-events: stroke; cursor: pointer; }
.makker-modus .makker-lag .makker-pil:hover .makker-strek,
.makker-modus .makker-lag .makker-pil:focus-visible .makker-strek { stroke: var(--warn); }
.makker-lag .makker-pil:focus-visible { outline: none; }
.makker-lag .makker-pil:hover .makker-halo { opacity: 1; }

/* I makkermodus er det parene som er saken: pulter uten makker trer fram, og
   pulten som venter på en makker lyser. */
.makker-modus .desk, .makker-modus .seat-chip { cursor: pointer; }
.makker-modus .desk.makker-alene, .makker-modus .seat-chip.makker-alene {
  border-style: dashed; border-color: var(--ink-3);
}
.makker-modus .desk.makker-valgt, .makker-modus .seat-chip.makker-valgt {
  border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft);
}

.makker-bar {
  display: none; align-items: center; gap: 10px; flex-wrap: wrap;
  background: var(--surface-2); border: 1px solid var(--line);
  border-radius: var(--r-md); padding: 8px 12px; margin-bottom: 10px;
  font-size: 13.5px; color: var(--ink-2);
}
.makker-bar.on { display: flex; }
.makker-bar #makkerText { margin-right: auto; }
/* Avkryssing i en modusrad: samme høyde som knappene ved siden av */
.bar-check { display: flex; align-items: center; gap: 7px; cursor: pointer; }
.bar-check input { width: 17px; height: 17px; min-height: 0; }

/* I klasseromsvisningen skal sperrede pulter bare være diskret tomme */
.present-room .desk.unused, .present-room .seat-chip.unused {
  background: none; border-style: dashed; border-color: var(--line-soft); opacity: .45;
}

/* ------------------------------------------------------------------- Lås */

#app.locked #sidebar, #app.presenting #sidebar { display: none; }
#app.locked #main, #app.presenting #main { padding: 0; }

.lock-screen {
  min-height: 100vh; display: flex; align-items: center; justify-content: center; padding: 24px;
}
.lock-card { width: 380px; max-width: 100%; text-align: center; }
.lock-card h2 { font-size: 22px; margin-bottom: 8px; }
.lock-card p { font-size: 14px; color: var(--ink-2); margin-bottom: 14px; }
.lock-card form { display: flex; gap: 8px; }
.lock-card input { flex: 1; min-width: 0; }
.lock-card .lock-err { color: var(--warn); font-weight: 600; margin: 10px 0 0; }
.lock-card .hint { font-size: 12.5px; color: var(--ink-3); margin: 14px 0 0; line-height: 1.45; }

/* ---- Modusmerket ----

   Ett element som gjør to ting: sier at appen står i lærermodus, og låser den
   til klasserommet. Det er derfor det er en knapp og ikke en etikett – en
   lærer som ser at det står feil, skal kunne rette det der hen leser det,
   ikke lete i en meny.

   Den andre veien har ikke noe merke. I klasseromsmodus er det klassen som ser
   skjermen, og da er «du står i klasseromsmodus» noe fargen på sida sier
   bedre enn et banner. Veien tilbake er `.klasserom-laasopp` nederst, som sier
   hva den låser opp. */

.modus-merke {
  display: flex; align-items: center; gap: 12px; width: 100%;
  margin: 16px 0 6px; padding: 12px 14px; cursor: pointer; text-align: left;
  font-family: inherit; font-size: 14px; color: var(--ink);
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-md);
}
.modus-merke:hover, .modus-merke:focus-visible { border-color: var(--accent); }
.modus-merke > .ico { flex: none; color: var(--accent); }
.modus-merke span { display: flex; flex-direction: column; gap: 2px; margin-right: auto; }
.modus-merke b { font-family: var(--display); font-size: 15.5px; }
.modus-merke small { font-size: 12.5px; color: var(--ink-2); line-height: 1.4; }
.modus-merke em {
  flex: none; font-style: normal; font-weight: 600; font-size: 13px;
  padding: 6px 12px; border-radius: var(--r-sm);
  background: var(--accent); color: var(--on-accent);
}

/* Veien tilbake til lærerverktøyet, nederst på klasseromssida. Den er lærerens
   knapp på en skjerm klassen ser på, og skal derfor være lett å finne for den
   som leter etter den – og ellers ligge stille. */
/* Ikke `margin-top: auto`: alene på flata er sida sentrert loddrett, og en
   auto-marg ville spist all luften og dyttet innholdet opp i toppen. */
.klasserom-foten { margin-top: 28px; display: flex; }
.klasserom-laasopp { color: var(--ink-2); }
.klasserom-laasopp:hover, .klasserom-laasopp:focus-visible { color: var(--ink); }

/* Avkryssing med en forklaringslinje under */
.modal .checkline.med-under { align-items: flex-start; }
.modal .checkline.med-under input { margin-top: 3px; }
.modal .checkline.med-under span { display: flex; flex-direction: column; gap: 1px; }
.modal .checkline.med-under small { font-size: 12.5px; line-height: 1.45; color: var(--ink-2); }

/* ---------------------------------------------- Klasserommet

   Forsiden til alt som vises for klassen. Den tegnes to steder: som en vanlig
   side med menyen ved siden av når læreren er logget inn, og alene på flata
   når appen er låst – da er den det eneste som står på storskjermen, og skal
   kunne leses bakerst i rommet. Derfor .alene, som bare gjør den større. */

.klasserom { max-width: 900px; }
.klasserom-head { display: flex; align-items: baseline; gap: 14px; flex-wrap: wrap; }
.klasserom-head h2 { font-size: 24px; display: flex; align-items: center; gap: 9px; }
.kr-velger {
  margin-left: auto; display: flex; align-items: center; gap: 8px;
  font-size: 13.5px; font-weight: 600; color: var(--ink-2);
}
.kr-klassenavn { margin-left: auto; font-family: var(--display); font-size: 20px; font-weight: 700; }
.klasserom-intro { color: var(--ink-2); font-size: 14px; margin: 8px 0 0; max-width: 62ch; }

/* Lufta over kortene hører til KORTENE, ikke til teksten over dem. Den lå på
   `.klasserom-intro` før, og da introen ble tatt bort i klasseromsmodus,
   forsvant avstanden med den: klassevelgeren klistret seg til det første
   kortet. I lærermodus faller de to margene sammen til én, så avstanden der
   er den samme som før. */
.klasserom-verktoy {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(215px, 1fr));
  gap: 14px; margin-top: 20px;
}
.kr-kort {
  display: flex; flex-direction: column; align-items: flex-start; gap: 7px;
  padding: 20px; text-align: left; cursor: pointer;
  background: var(--surface); color: var(--ink);
  border: 1px solid var(--line); border-radius: var(--r-lg);
  box-shadow: 0 1px 2px var(--shadow); font-family: inherit;
}
.kr-kort:hover:not(:disabled), .kr-kort:focus-visible:not(:disabled) {
  border-color: var(--accent); box-shadow: 0 6px 18px var(--shadow);
}
.kr-kort:disabled { opacity: .55; cursor: default; box-shadow: none; }
.kr-ico { font-size: 27px; line-height: 1; color: var(--accent); }
.kr-kort:disabled .kr-ico { color: var(--ink-3); }
.kr-kort b { font-family: var(--display); font-size: 19px; }
.kr-under { font-size: 13px; color: var(--ink-2); line-height: 1.45; }

.klasserom-kart { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-top: 22px; }
.kr-kart-tittel { font-size: 13px; font-weight: 600; color: var(--ink-3); }

.klasserom.alene {
  min-height: 100vh; max-width: 960px; margin: 0 auto; padding: 32px 24px;
  display: flex; flex-direction: column; justify-content: center;
}
.klasserom.alene .klasserom-head h2 { font-size: 30px; }
/* Alt er større her, og da må mellomrommet være det også – ellers ser sida
   trangere ut bakerst i rommet enn den gjør på lærerens skjerm. */
.klasserom.alene .klasserom-verktoy { margin-top: 26px; }
.klasserom.alene .kr-klassenavn { font-size: 24px; }
.klasserom.alene .kr-kort { padding: 26px; }
.klasserom.alene .kr-ico { font-size: 32px; }
.klasserom.alene .kr-kort b { font-size: 21px; }

/* ---------------------------------------------- Klasseromsvisning */

.present { display: flex; flex-direction: column; min-height: 100vh; padding: 12px 16px 16px; gap: 10px; }
.present-bar { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; }
.present-title { display: flex; align-items: baseline; gap: 10px; margin-right: auto; }
.present-title b { font-family: var(--display); font-size: 26px; }
.present-title span { color: var(--ink-2); font-size: 15px; }
/* Som verktøylinjene i lærerdelen: knappene står i `.tool-group`-er, og linja
   brytes mellom gruppene. Her er det ekstra mye verdt – linja står på en
   projektor foran klassen, og læreren finner knappen ved å se, ikke ved å
   lete. Lufta mellom gruppene er dobbel. */
.present-actions { display: flex; gap: 8px 16px; flex-wrap: wrap; align-items: center; }
.present-actions .seg-label { font-size: 13px; color: var(--ink-2); font-weight: 600; }
/* Fullskjerm og Avslutt hører sammen og flytter seg samlet – ellers blir
   «Avslutt» stående alene på en linje når lista brekker. */
.present-exit { display: flex; gap: 8px; align-items: center; }
/* Fire knapper i gruppa er én for mye for en telefon. Da brekker gruppa heller
   enn å skyve den siste ut av vinduet – de to linjene står fortsatt samlet, og
   det var det som var poenget med å holde dem i samme boks. */
@media (max-width: 640px) { .present-exit { flex-wrap: wrap; justify-content: flex-end; } }
/* På en smal skjerm får tittelen sin egen linje, så knappene deler den neste */
@media (max-width: 900px) {
  .present-title { flex: 1 1 100%; margin-right: 0; }
  .present-actions { width: 100%; }
}
.present-draw { font-size: 16px; min-height: 46px; padding: 0 20px; }

/* Under utdelingen skal ingenting stjele oppmerksomhet fra kartet. Hele
   barnet skjules, ikke bare knappene i det: en `.seg-label` som «Sett fra:»
   er ingen knapp, og ble stående alene igjen i linja. */
.present-bar.drawing .present-title { opacity: .5; }
.present-bar.drawing .present-actions > *:not(#pSkip) { display: none; }

/* Fylt vindu: kartet er alt som skal stå på skjermen mens timen går. Knappene
   hentes tilbake fra hjørnet, som er svakt til man ser etter det. */
.present.filled { padding: 4px; gap: 0; justify-content: center; }
.present.filled .present-bar, .present.filled .present-foot { display: none; }
.present-restore {
  position: fixed; top: 10px; right: 10px; z-index: 50;
  min-width: var(--tap); min-height: var(--tap); font-size: 18px; line-height: 1;
  background: var(--surface); color: var(--ink-2);
  border: 1px solid var(--line); border-radius: var(--r-md);
  cursor: pointer; opacity: .35;
}
.present-restore:hover, .present-restore:focus-visible { opacity: 1; color: var(--ink); }

.present #presentCanvas { margin: 0 auto; width: 100%; }
.present-room .desk-name { font-size: 15px; font-weight: 700; }
/* Bakerst i rommet skal rollen kunne leses – men den skal ikke ta plassen
   navnet har. Den er derfor drøyt to tredjedeler av navnet, og pulten har
   høyde til begge: 15 + 12 px står godt innenfor de 60 px pulten er. */
.present-room .desk-rolle { font-size: 12px; }
.present-room .seat-chip { font-size: 14px; font-weight: 700; }
.present-foot { text-align: center; color: var(--ink-2); font-size: 14px; min-height: 20px; }
.present-msg { padding: 40px; text-align: center; display: flex; flex-direction: column; gap: 14px; align-items: center; }

/* Navnekortet som flyr fra midten av skjermen ned på pulten */
.fly-layer { position: fixed; inset: 0; pointer-events: none; z-index: 400; }
.fly-card {
  position: fixed; left: 0; top: 0; transform-origin: 50% 50%;
  background: var(--accent); color: var(--on-accent);
  font-family: var(--display); font-weight: 700; font-size: 46px;
  padding: 18px 34px; border-radius: var(--r-lg); white-space: nowrap;
  display: flex; align-items: center; gap: 20px;
  box-shadow: 0 18px 50px var(--shadow-2);
  animation: cardIn .22s cubic-bezier(.2,1.3,.5,1);
}
@keyframes cardIn {
  from { opacity: 0; transform: translate(50vw, 42vh) translate(-50%, -50%) scale(.5); }
}
.present-room .desk.landed, .present-room .seat-chip.landed { animation: seatPop .45s ease; }
@keyframes seatPop {
  0% { transform: scale(1); }
  35% { box-shadow: 0 0 0 6px var(--accent-soft); }
  100% { transform: scale(1); }
}
/* pulten og navnelappen på et sekskantbord er allerede dreid; skaler derfor
   bare fargepulsen – en skalering her ville nullstilt dreiningen */
.present-room .desk.landed, .present-room .seat-chip.landed { animation-name: seatGlow; }
@keyframes seatGlow {
  0% { box-shadow: 0 0 0 0 var(--accent); }
  30% { box-shadow: 0 0 0 5px var(--accent-soft); }
  100% { box-shadow: 0 0 0 0 rgba(0,0,0,0); }
}

@media (max-width: 720px) {
  .present { padding: 10px 10px 14px; min-height: 100svh; }
  .present-title b { font-size: 19px; }
  .fly-card { font-size: 30px; padding: 12px 22px; }
}

/* --------------------------------------- 7c. Trekking, hjul og grupper

   Verktøyene som kjøres mens klassen ser på. Alt her måles for en storskjerm
   bakerst i rommet: hjulet tar halve flata, vinnernavnet er det største på
   skjermen, og knappene ligger utenfor selve hjulet så ingen dekker det. */

/* Merkelappen over hvert gruppebord. Fargen kommer inn som --dc, som på
   pultene, slik at mørkt tema kan lyse den opp mot den mørke flata. */
.gruppe-merke {
  position: absolute; height: 30px; z-index: 3;
  display: flex; align-items: center; justify-content: center;
  font-family: var(--display); font-weight: 700; font-size: 19px;
  color: var(--dc, var(--ink)); background: var(--dc-fill, transparent);
  border: 2px solid var(--dc, var(--line)); border-radius: var(--r-md);
  white-space: nowrap; overflow: hidden;
}
/* Lappen er også veien til å gi gruppa et eget navn (dobbelttrykk), så den må
   ta imot pekeren. Den ligger i lufta OVER bordet og dekker ingen pult.

   Ingenting av dette vises i hvile: lappen står på en skjerm klassen ser på,
   og en knapp-aktig ting der er noe tretti elever begynner å lure på. Den sier
   fra først når noen er borti den – og da er det læreren. */
.gruppe-merke { cursor: pointer; transition: background-color .12s, box-shadow .12s; }
.gruppe-merke:hover { background: var(--dc-fill, transparent); box-shadow: 0 0 0 3px var(--dc-fill, transparent); }
.gruppe-merke:focus-visible { outline: 2px solid var(--dc, var(--accent)); outline-offset: 2px; }

/* Navnedialogen: én rad per bord, med bordets farge som prikk foran feltet.
   Prikken og ikke et fargelagt felt – læreren skal kjenne igjen bordet på
   skjermen, ikke lese en fargekode. */
.gruppenavn-liste { display: grid; gap: 8px; }
.gruppenavn-rad { display: flex; align-items: center; gap: 10px; }
.gruppenavn-rad input { flex: 1 1 auto; min-width: 0; }
.gruppenavn-prikk {
  flex: 0 0 auto; width: 16px; height: 16px; border-radius: 5px;
  background: var(--dc-fill, transparent); border: 2px solid var(--dc, var(--line));
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .gruppe-merke {
    color: color-mix(in oklab, var(--dc) 68%, #E7EEEB);
    border-color: color-mix(in oklab, var(--dc) 68%, #E7EEEB);
  }
}
:root[data-theme="dark"] .gruppe-merke {
  color: color-mix(in oklab, var(--dc) 68%, #E7EEEB);
  border-color: color-mix(in oklab, var(--dc) 68%, #E7EEEB);
}

/* Raden med gruppevalgene ligger under knappene i visningen og tar hele
   linja: den hører til én tilstand, ikke til verktøylinja ellers. */
.present-groups {
  flex: 1 1 100%; display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding-top: 8px; border-top: 1px solid var(--line-soft);
}
.present-bar.drawing .present-groups { display: none; }

/* --- Lykkehjulet --- */

.hjul-scene {
  position: fixed; inset: 0; z-index: 500; background: var(--ground);
  display: flex; flex-direction: column; padding: 14px 18px 20px; gap: 12px;
}
.hjul-topp { display: flex; align-items: center; gap: 16px; }
.hjul-topp h2 {
  font-family: var(--display); font-size: 24px; margin-right: auto;
  display: flex; align-items: center; gap: 10px;
}
.hjul-topp-knapper { display: flex; align-items: center; gap: 8px; }
.hjul-flate {
  flex: 1; min-height: 0; display: flex; align-items: center; gap: 28px;
  justify-content: center;
}
.hjul-plass { flex: 0 1 auto; min-width: 0; height: 100%; display: flex; align-items: center; }
.hjul-side {
  flex: 0 1 380px; display: flex; flex-direction: column; gap: 14px; align-items: flex-start;
}
.hjul-tomt { color: var(--ink-2); font-size: 18px; }

/* Skiva. Fargene på sektorene er gruppepaletten; alt rundt dem – kanten,
   lysene, nåla, navet – er ett fast, mørkt materiale i begge temaer, slik et
   ekte hjul har en kant som ikke skifter farge med rommet. Vinnerens farge
   kommer inn som --dc, som på pultene, og er det ene som er levende her.
   Skyggen og gløden er egne, RUNDE elementer bak svg-en og ikke et `filter`
   på den: et filter regnes om for hver eneste ramme mens skiva snurrer, og
   det har ikke en Pi som driver en storskjerm råd til. */
.hjul-boks {
  position: relative; height: 100%; aspect-ratio: 1; max-height: 100%;
  --hjul-kant: #1B2523; --hjul-lys-av: rgba(255,255,255,.22); --hjul-lys-paa: #FFD866;
}
/* `touch-action: none`: skiva kan gripes med fingeren, og da skal ikke sida
   rulle under den. Pekeren sier det samme med hånda. */
.hjul {
  width: 100%; height: 100%; display: block; position: relative; z-index: 1;
  touch-action: none; cursor: grab; user-select: none;
}
.hjul-boks.holdes .hjul { cursor: grabbing; }
.hjul-boks.snurrer .hjul { cursor: default; }
.hjul-skygge, .hjul-glod {
  position: absolute; border-radius: 50%; pointer-events: none;
}
/* Skyggen ligger under kanten (r 104,5 av 110 = 95 % av flata) */
.hjul-skygge { inset: 2.5%; box-shadow: 0 10px 34px var(--shadow-2), 0 2px 6px var(--shadow); }
/* Gløden er større enn skiva og får vinnerens farge når den er kåret */
/* `closest-side`: gløden er en glorie UTENFOR kanten (fra skiva og 7 % ut),
   ikke en flekk bak den som ingen ser. */
.hjul-glod {
  inset: -14%; opacity: 0; transition: opacity .6s ease;
  background: radial-gradient(circle closest-side, var(--dc, var(--accent)) 72%, transparent 100%);
}
.hjul-boks.snurrer .hjul-glod { opacity: .22; animation: hjulGlodPuls 1.6s ease-in-out infinite; }
.hjul-boks.kaaret .hjul-glod { opacity: .5; }
@keyframes hjulGlodPuls { 50% { opacity: .1; } }
/* Skiva roteres om sitt eget midtpunkt. Uten transform-box regner nettleseren
   fra brukerrommets origo, og hjulet ville svingt ut av bildet. */
.hjul-skive { transform-box: view-box; transform-origin: 50% 50%; }
.hjul-sektor path, .hjul-sektor circle { stroke: var(--hjul-kant); stroke-width: .6; }
.hjul-glans { pointer-events: none; }
.hjul-ring { fill: none; stroke: var(--hjul-kant); stroke-width: 9; }
.hjul-nav { fill: var(--hjul-kant); stroke: rgba(255,255,255,.35); stroke-width: 1.5; }
.hjul-nav-kjerne { fill: var(--surface); }
/* Pinnene på skiva – det nåla slår mot. Samme mørke materiale som kanten og
   navet, med en lys kant så de står fram mot sektorfargen. De ligger i
   `.hjul-skive` og roterer med den. */
.hjul-pinne { fill: var(--hjul-kant); stroke: rgba(255,255,255,.55); stroke-width: .9; }
/* Lysene på kanten: to lag som blinker i motfase mens skiva går, og alle
   sammen tent når vinneren er kåret. `steps(1)` og bare opacity – ingenting
   som må regnes om per ramme. */
.hjul-lys { fill: var(--hjul-lys-av); }
.hjul-boks.snurrer .hjul-lys-a { animation: hjulLys .34s steps(1) infinite; }
.hjul-boks.snurrer .hjul-lys-b { animation: hjulLys .34s steps(1) .17s infinite; }
.hjul-boks.kaaret .hjul-lys { fill: var(--hjul-lys-paa); animation: hjulLysAlle .28s steps(1) 6; }
@keyframes hjulLys { 0%, 49% { fill: var(--hjul-lys-paa); } 50%, 100% { fill: var(--hjul-lys-av); } }
@keyframes hjulLysAlle { 0%, 49% { fill: var(--hjul-lys-paa); } 50%, 100% { fill: var(--hjul-lys-av); } }

/* Vinneren: sektoren står, resten trekker seg tilbake. Dempingen er
   opacity på gruppa (flate + navn), så navnene på taperne blekner med. */
.hjul-sektor { transition: opacity .55s ease; }
.hjul-boks.kaaret .hjul-sektor:not(.vinner) { opacity: .32; }
.hjul-boks.kaaret .hjul-sektor.vinner path,
.hjul-boks.kaaret .hjul-sektor.vinner circle { stroke: #fff; stroke-width: 2.2; }

/* Nåla står fast klokka 12 og peker inn i hjulet. Den svinger om øyet sitt
   (12/46 ned på svg-en), og svingen settes av `naalNokler()` i trekking.js –
   én animasjon for hele snurren, i takt med lyden. */
.hjul-peker {
  position: absolute; top: -3.5%; left: 50%; width: 8%; aspect-ratio: 30 / 46;
  transform: translateX(-50%); z-index: 3; pointer-events: none;
  filter: drop-shadow(0 3px 4px var(--shadow-2));
}
.hjul-naal { width: 100%; height: 100%; display: block; transform-origin: 50% 26%; }
.hjul-naal-kropp { fill: var(--hjul-kant); stroke: #fff; stroke-width: 1.8; stroke-linejoin: round; }
.hjul-naal-oye { fill: var(--hjul-lys-paa); }

/* Konfettien ligger i et lag over hele skiva, med utspring i pekeren. */
.hjul-konfetti { position: absolute; top: 0; left: 50%; width: 0; height: 0; z-index: 4; pointer-events: none; }
.konfetti-bit {
  position: absolute; left: -5px; top: -5px; width: 10px; height: 14px; border-radius: 2px;
  will-change: transform, opacity;
}
.konfetti-bit.rund { width: 9px; height: 9px; border-radius: 50%; }

.hjul-spinn { font-size: 21px; min-height: 60px; padding: 0 28px; }
.hjul-tips { display: flex; align-items: center; gap: 6px; }
.hjul-valg { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; }
.hjul-vinner { min-height: 76px; display: flex; flex-direction: column; gap: 6px; }
.hjul-vinner-navn {
  font-family: var(--display); font-weight: 700; font-size: clamp(30px, 5.4vw, 68px);
  line-height: 1.05; color: var(--ink);
  border-left: 10px solid var(--dc); padding: 6px 18px 6px 16px;
  background: color-mix(in oklab, var(--dc) 16%, transparent);
  border-radius: 0 var(--r-lg) var(--r-lg) 0;
}
.hjul-vinner-under { color: var(--ink-2); font-size: 16px; line-height: 1.4; padding-left: 26px; }
.hjul-vinner.har-vinner { animation: hjulVinner .6s cubic-bezier(.2,1.4,.4,1); }
@keyframes hjulVinner {
  from { opacity: 0; transform: scale(.6) translateY(12px); }
}

/* Stående skjerm og telefon: hjulet over, teksten under */
@media (max-width: 900px), (orientation: portrait) {
  .hjul-flate { flex-direction: column; gap: 14px; }
  .hjul-plass { height: auto; width: 100%; max-width: 62vh; justify-content: center; }
  .hjul-boks { width: 100%; height: auto; }
  .hjul-side { flex: 0 0 auto; width: 100%; align-items: center; text-align: center; }
  .hjul-vinner { align-items: center; min-height: 60px; }
  .hjul-vinner-navn {
    border-left: 0; border-bottom: 8px solid var(--dc); padding: 4px 14px;
    border-radius: var(--r-lg) var(--r-lg) 0 0;
  }
  .hjul-vinner-under { padding-left: 0; }
}

@media (prefers-reduced-motion: reduce) {
  .hjul-vinner.har-vinner { animation: none; }
  .hjul-boks.snurrer .hjul-lys-a, .hjul-boks.snurrer .hjul-lys-b,
  .hjul-boks.kaaret .hjul-lys, .hjul-boks.snurrer .hjul-glod { animation: none; }
}

/* --- Nedtellingen ---

   Ligger OVER visningen, men i et hjørne: klassen skal se gruppebordene og
   klokka samtidig, og et panel som dekket flata ville tvunget læreren til å
   velge. «Stor» er unntaket – da er det nedtellingen som ER visningen, og den
   fyller skjermen med kartet liggende urørt bak.

   Fargen kommer fra --accent-familien, ikke fra en fast verdi: aksenten er
   lilla i klasseromsmodus, og det er nettopp der klokka står oftest. Når tida
   er ute, byttes den til --warn – én farge, ikke et blink som tar rommet. */

.nedtell {
  position: fixed; right: 16px; bottom: 16px; z-index: 520;
  display: flex; flex-direction: column; align-items: center; gap: 8px;
  padding: 10px 16px 12px;
  max-width: min(94vw, 560px);
  background: var(--surface); border: 2px solid var(--accent);
  border-radius: var(--r-lg); box-shadow: 0 8px 28px var(--shadow-2);
}
.nedtell-ur { line-height: 1; }
.nedtell-tid {
  display: block; font-family: var(--display); font-weight: 700;
  font-variant-numeric: tabular-nums; line-height: 1;
  font-size: clamp(40px, 6.5vw, 82px); color: var(--accent-ink);
}
/* Meldingen til skjermleseren skal ikke ta plass på storskjermen: den sier
   det klokka allerede viser, og bare ved start, pause og slutt. */
.nedtell-sagt {
  position: absolute; width: 1px; height: 1px; margin: -1px;
  padding: 0; border: 0; overflow: hidden; clip-path: inset(50%); white-space: nowrap;
}
.nedtell-valg { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; justify-content: center; }
.nedtell-egen { display: inline-flex; align-items: center; gap: 6px; font-size: 13px; color: var(--ink-2); }
.nedtell-egen input { width: 62px; min-height: 34px; text-align: center; }
.nedtell-knapper { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; justify-content: center; }
.nedtell-liten { padding: 0 10px; }

/* Tida er ute: fargen skifter og klokka markerer seg én gang. Et blink som
   fortsatte, ville stått og blunket gjennom hele neste oppgave. */
.nedtell.ute { border-color: var(--warn); background: var(--warn-soft); }
.nedtell.ute .nedtell-tid { color: var(--warn); animation: nedtellUte 1.6s ease-out 2; }
@keyframes nedtellUte {
  0%, 100% { opacity: 1; }
  50% { opacity: .35; }
}

/* Bare klokka: hele flata, ingenting annet enn tallet og knappene som må til
   for å stoppe den. `overflow: hidden` er ikke pynt – uten den kan et bredt
   tall («1:00:00») gjøre sida rullbar sidelengs på en smal skjerm. */
.nedtell.stor {
  inset: 0; max-width: none; padding: 24px;
  border: 0; border-radius: 0; box-shadow: none;
  background: var(--ground); justify-content: center; gap: 28px; overflow: hidden;
}
.nedtell.stor .nedtell-tid { font-size: min(23vw, 46vh); }
.nedtell.stor .nedtell-valg, .nedtell.stor .nedtell-knapper { opacity: .75; }
.nedtell.stor .nedtell-valg:hover, .nedtell.stor .nedtell-knapper:hover,
.nedtell.stor .nedtell-valg:focus-within, .nedtell.stor .nedtell-knapper:focus-within { opacity: 1; }

/* Telefon og trange skjermer: panelet legger seg langs nedkanten i stedet for
   i hjørnet, slik at knappene får en linje for seg selv. */
@media (max-width: 620px) {
  .nedtell:not(.stor) { right: 8px; left: 8px; bottom: 8px; max-width: none; }
  .nedtell:not(.stor) .nedtell-tid { font-size: clamp(34px, 13vw, 56px); }
}

@media (prefers-reduced-motion: reduce) {
  .nedtell.ute .nedtell-tid { animation: none; }
}

/* --- Plan for timen (site/tidsplan.js) ---

   Planen er en LISTE, ikke en klokke: ingenting i den flytter seg av seg
   selv (hvorfor står øverst i tidsplan.js). Den aktive bolken er løftet
   fram med aksentfargen og en «Nå»-lapp, og bolkene FØR den er dempet – da
   ser klassen hvor langt vi er kommet uten en strek som kryper.

   To drakter: alene på #/vis/tidsplan (`.tidsplan-side` – store bokstaver,
   én kolonne, vinduet kan være smalt) og som spalte i klasseromsvisningen
   (`.present-tidsplan` med `.tp-panel.kompakt`). Skriftene er clamp-et på
   vw, ikke faste: den samme sida står i et 400 px bredt vindu ved siden av
   en presentasjon og på en projektor i 1366, og skal leses begge steder. */

.tidsplan-side { min-height: 100vh; display: flex; flex-direction: column; padding: 12px 16px 16px; gap: 14px; }
.tidsplan-topp { display: flex; gap: 8px 16px; flex-wrap: wrap; align-items: center; }
.tidsplan-topp .present-exit { margin-left: auto; }
.tidsplan-side .tp-panel { flex: 1 1 auto; width: 100%; max-width: 900px; margin: 0 auto; }

.tp-panel { display: flex; flex-direction: column; gap: 12px; }
.tp-hode { display: flex; flex-direction: column; gap: 2px; }
.tp-tittel { font-family: var(--display); font-size: clamp(22px, 3.2vw, 34px); line-height: 1.15; }
.tp-meta { color: var(--ink-2); font-size: clamp(13px, 1.4vw, 16px); }
.tp-liste { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }
.tp-bolk {
  display: grid; grid-template-columns: auto 1fr auto; align-items: center; gap: 14px;
  padding: 12px 16px; border: 2px solid var(--line); border-radius: var(--r-lg);
  background: var(--surface); cursor: pointer;
  transition: border-color .15s, background .15s, opacity .15s;
}
.tp-bolk:hover, .tp-bolk:focus-visible { border-color: var(--accent); }
.tp-bolk:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--accent-soft); }
.tp-tid {
  font-variant-numeric: tabular-nums; font-weight: 700; color: var(--ink-2);
  font-size: clamp(15px, 1.8vw, 22px); min-width: 3.2em;
}
/* Etter en bolk uten minutter er klokkeslettene bare et anslag */
.tp-tid.usikker { opacity: .55; }
/* Tidene er skjult som standard (se «Tidene er skjult» i tidsplan.js), og
   da finnes tidsspalta ikke – ikke en tom spalte på 3,2 em foran hver
   overskrift, som ville sett ut som om noe manglet. */
.tp-panel.uten-tid .tp-bolk { grid-template-columns: 1fr auto; }
.tp-innhold { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.tp-overskrift { font-size: clamp(17px, 2.2vw, 26px); line-height: 1.2; overflow-wrap: anywhere; }
.tp-tekst { font-size: clamp(13px, 1.5vw, 18px); color: var(--ink-2); line-height: 1.35; overflow-wrap: anywhere; }
.tp-naa {
  font-size: 13px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em;
  color: var(--on-accent); background: var(--accent); border-radius: 999px; padding: 4px 10px;
}
.tp-bolk.aktiv { border-color: var(--accent); background: var(--accent-soft); }
.tp-bolk.aktiv .tp-overskrift { color: var(--accent-ink); }
.tp-bolk.ferdig { opacity: .5; }
.tp-tom {
  color: var(--ink-2); padding: 20px; text-align: center;
  border: 1px dashed var(--line); border-radius: var(--r-lg);
}
/* Skjermlesertekst uten plass på skjermen – samme grep som .nedtell-sagt */
.sr-only {
  position: absolute; width: 1px; height: 1px; margin: -1px;
  padding: 0; border: 0; overflow: hidden; clip-path: inset(50%); white-space: nowrap;
}

/* Kompakt: spalta i klasseromsvisningen. Mindre skrift, tettere rader, og
   «Nå» under overskrifta i stedet for i en tredje spalte. */
.tp-panel.kompakt { gap: 8px; }
.tp-panel.kompakt .tp-tittel { font-size: 18px; }
.tp-panel.kompakt .tp-meta { font-size: 12.5px; }
.tp-panel.kompakt .tp-bolk { padding: 8px 10px; gap: 6px 10px; grid-template-columns: auto 1fr; }
.tp-panel.kompakt .tp-tid { font-size: 13px; min-width: 2.8em; }
.tp-panel.kompakt .tp-overskrift { font-size: 15px; }
.tp-panel.kompakt .tp-tekst { font-size: 12.5px; }
.tp-panel.kompakt .tp-naa { grid-column: 2; justify-self: start; font-size: 11px; padding: 2px 8px; }
.tp-panel.kompakt.uten-tid .tp-bolk { grid-template-columns: 1fr; }
.tp-panel.kompakt.uten-tid .tp-naa { grid-column: 1; }

/* Spalta i klasseromsvisningen: fast langs høyre kant, og `.present` får
   luft til høyre så kartet regner om bredden sin (app.js kaller fit()).
   Under 720 px er det ikke plass til to ting side om side – da legger
   spalta seg UNDER kartet i stedet. z-index: under hjulet (500) og
   nedtellingen (520), se stigen over #toasts. */
:root { --tp-bredde: min(320px, 34vw); }
.present.med-tidsplan { padding-right: calc(var(--tp-bredde) + 16px); }
.present-tidsplan {
  position: fixed; top: 0; right: 0; bottom: 0; width: var(--tp-bredde); z-index: 450;
  display: flex; flex-direction: column; gap: 8px; padding: 10px 12px 16px; overflow: auto;
  background: var(--surface); border-left: 1px solid var(--line); box-shadow: -4px 0 18px var(--shadow);
}
.present-tidsplan-topp { display: flex; justify-content: flex-end; }
@media (max-width: 720px) {
  .present.med-tidsplan { padding-right: 10px; }
  .present-tidsplan {
    position: static; width: auto; border-left: 0; border-top: 1px solid var(--line); box-shadow: none;
  }
}

/* Redigeringsdialogen: én rad per bolk – minutter, så overskrift over
   beskrivelse, så grepene. På en telefon får grepene sin egen linje. */
.tp-red-hode { display: flex; gap: 12px; flex-wrap: wrap; }
.tp-red-tittel { flex: 1 1 200px; }
.tp-red-liste { display: flex; flex-direction: column; gap: 8px; }
.tp-red-rad { display: grid; grid-template-columns: 64px 1fr auto; gap: 8px; align-items: start; }
.tp-red-min { text-align: center; }
.tp-red-felt { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.tp-red-grep { display: flex; gap: 4px; }
.tp-red-knapper { display: flex; gap: 8px 16px; flex-wrap: wrap; align-items: center; }
@media (max-width: 520px) {
  .tp-red-rad { grid-template-columns: 56px 1fr; }
  .tp-red-grep { grid-column: 1 / -1; justify-content: flex-end; }
}

/* Hent fra undervisningsplan: øktene gruppert på dag, i dag først */
.tp-hent-dag { display: flex; flex-direction: column; gap: 6px; }
.tp-hent-dato {
  font-size: 12.5px; font-weight: 700; color: var(--ink-3);
  text-transform: uppercase; letter-spacing: .04em;
}
.tp-hent-dato.idag { color: var(--accent-ink); }
.tp-okt {
  display: grid; grid-template-columns: auto 1fr; gap: 12px; align-items: center; text-align: left;
  padding: 10px 12px; border: 1px solid var(--line); border-radius: var(--r-md);
  background: var(--surface); color: var(--ink); cursor: pointer; font-family: inherit;
}
.tp-okt:hover, .tp-okt:focus-visible { border-color: var(--accent); }
.tp-okt-tid { font-variant-numeric: tabular-nums; font-weight: 700; color: var(--ink-2); font-size: 13px; min-width: 6em; }
.tp-okt-tekst { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.tp-okt-tekst b { font-size: 15px; }
.tp-okt-tekst small { font-size: 12.5px; color: var(--ink-2); }
.tp-hent-fot { display: flex; justify-content: flex-end; }

/* «Velg verktøy» i klasserommet */
.verktoyvalg { display: flex; flex-direction: column; gap: 8px; }
.verktoyvalg-rad { display: flex; align-items: center; gap: 10px; font-size: 15px; cursor: pointer; }
.verktoyvalg-ico { color: var(--accent); display: inline-flex; }

/* --- Klasseromsklokka (#/vis/klokke) ---

   Nedtellingen over står i hjørnet ved siden av et klassekart. Denne ER
   skjermen, og har derfor to ting den ikke har: et klokkeslett i storformat og
   en bakgrunn.

   Bakgrunnene er TEGNET, ikke fotografert – CSP-en tillater bare samme opphav,
   og et fotografi i et repo som deles med andre lærere er et lisensspørsmål.
   En gradient og noen polygoner koster null bytes og virker uten nett. Ny
   bakgrunn: én linje i BAKGRUNNER i klokke.js, og én regel her.

   `--klokke-blekk` er tekstfargen OVER bakgrunnen, og er en egenskap ved
   bakgrunnen og ikke ved appens tema: en stjernehimmel har hvit tekst også i
   lyst tema. `data-blekk="tema"` lar appens egne farger gjelde. */
.klokke-scene {
  position: relative; min-height: 100vh; overflow: hidden;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 18px; padding: 20px;
  --klokke-blekk: var(--ink);
  --klokke-blekk-2: var(--ink-2);
  --klokke-flate: var(--surface);
  color: var(--klokke-blekk);
}
.klokke-scene[data-blekk="lys"] {
  --klokke-blekk: #FFFFFF;
  --klokke-blekk-2: rgba(255, 255, 255, .78);
  --klokke-flate: rgba(255, 255, 255, .14);
}
.klokke-bg { position: absolute; inset: 0; z-index: 0; }
.klokke-lag { position: absolute; inset: 0; width: 100%; height: 100%; }
.klokke-lag polygon, .klokke-lag circle { fill: currentColor; }

.klokke-scene[data-bakgrunn="enkel"] { background: var(--ground); }
/* Rutepapiret er appens eget rutenett, i appens egne farger – den bakgrunnen
   som IKKE later som den er et sted. */
.klokke-scene[data-bakgrunn="rutepapir"] {
  background:
    repeating-linear-gradient(var(--grid) 0 1px, transparent 1px 40px),
    repeating-linear-gradient(90deg, var(--grid) 0 1px, transparent 1px 40px),
    var(--ground);
}
.klokke-scene[data-bakgrunn="rolig"] {
  background: linear-gradient(160deg, #123B47 0%, #16554F 55%, #0D2E33 100%);
}
/* Sola er en radial-gradient og ikke en <circle>: en SVG med `slice` skalerer
   etter den STØRSTE av de to kantene, og på en bred skjerm blir en sol som
   skulle stått i horisonten til en flate som dekker halve bildet. `vh` her gir
   en sol av samme størrelse uansett hvor bred skjermen er. */
.klokke-scene[data-bakgrunn="soloppgang"] {
  background:
    radial-gradient(22vh 22vh at 50% 94%, rgba(255, 230, 178, .95) 0%,
      rgba(255, 198, 128, .5) 55%, rgba(255, 176, 110, 0) 100%),
    linear-gradient(180deg, #2B2350 0%, #7C3B63 42%, #D96A4E 78%, #F0A65B 100%);
}
.klokke-scene[data-bakgrunn="fjell"] {
  background: linear-gradient(180deg, #1B2A46 0%, #35507A 60%, #6E85A8 100%);
}
.klokke-scene[data-bakgrunn="fjell"] .klokke-bg { color: #101A2C; }
.klokke-scene[data-bakgrunn="natt"] {
  background: radial-gradient(120% 90% at 50% 0%, #16224A 0%, #0A0F22 70%, #060913 100%);
}
.klokke-scene[data-bakgrunn="natt"] .klokke-bg { color: #FFFFFF; }
.klokke-scene[data-bakgrunn="vinter"] {
  background: linear-gradient(180deg, #24405C 0%, #4A6E8C 55%, #93B2C4 100%);
}
.klokke-scene[data-bakgrunn="vinter"] .klokke-bg { color: #FFFFFF; }

/* Fotografiet – den ene bakgrunnen som ikke er tegnet her. Bildet settes som
   `background-image` på .klokke-bg fra klokke.js, og hentes fra `/api/bilder`,
   altså fra vårt eget opphav; nettleseren snakker aldri med Unsplash. Se
   bakgrunnsbilder.js.

   Sløret over bildet er ikke pynt. Klokkeslettet er hvitt, og et fotografi kan
   være hva som helst – snø i motlys like gjerne som en nattehimmel. Uten en
   fast demping finnes det bilder der tallene rett og slett ikke er der. Det er
   sterkest øverst og nederst, der klokka og panelet står, og svakest på
   midten, der bildet skal få være et bilde. */
.klokke-scene[data-bakgrunn="foto"] { background: #10161C; }
.klokke-scene[data-bakgrunn="foto"] .klokke-bg {
  background-size: cover; background-position: center;
}
.klokke-scene[data-bakgrunn="foto"] .klokke-bg::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(180deg, rgba(8, 12, 16, .62) 0%, rgba(8, 12, 16, .28) 38%,
    rgba(8, 12, 16, .34) 62%, rgba(8, 12, 16, .72) 100%);
}
/* Krediteringen Unsplash krever. Den står nederst til venstre – motsatt hjørne
   av «Fullskjerm»/«Klasserom», så de to aldri legger seg oppå hverandre – og
   er liten med vilje: den skal være lesbar for den som ser etter, og ikke noe
   klassen leser i stedet for bildet. */
.klokke-kreditt {
  position: absolute; left: 14px; bottom: 10px; z-index: 3;
  font-size: 11.5px; color: rgba(255, 255, 255, .72);
  text-shadow: 0 1px 6px rgba(0, 0, 0, .8);
}
.klokke-kreditt a { color: inherit; text-decoration: underline; }
.klokke-kreditt a:hover { color: #fff; }

/* --- «Bare bildet» ---

   Skjermen har to lesere. Panelet, hjørneknappene og spillets knapperad er
   skrevet til LÆREREN; fotografiet, klokka og kartet er det klassen ser på.
   `.bart` tar bort det første.

   Under et gjettespill er det hele poenget: bildet ER oppgaven, og på en
   projektor i 1366×768 ligger kartet nøyaktig oppå den delen av bildet
   klassen skal studere. Ett trykk tar det bort, ett trykk henter det tilbake.

   Krediteringen blir stående. Den er et krav fra Unsplash, ikke pynt. */
/* Sløret over bildet er dimensjonert for et panel som står der. I «Bare
   bildet» gjør det ingen jobb på midten – der er det bare fotografiet – og
   det er nettopp midten klassen skal studere. Derfor slippes den opp, mens
   hjørnene beholder akkurat nok til at klokka og krediteringen står trygt
   også over en snøhvit himmel. */
.klokke-scene.bart[data-bakgrunn="foto"] .klokke-bg::after {
  background: linear-gradient(180deg, rgba(8, 12, 16, .55) 0%, rgba(8, 12, 16, .12) 28%,
    rgba(8, 12, 16, 0) 55%, rgba(8, 12, 16, .32) 100%);
}

/* Spillet står IKKE i denne lista. Det gjorde det før, den gangen kartet var
   en full spalte under klokka; nå er det et lite kort i hjørnet som dekker
   ingenting, og en runde som forsvant idet skjermen ble ryddet, ville vært en
   runde læreren ikke kunne kjøre ryddig. Se `.gjett` lenger nede. */
.klokke-scene.bart .klokke-panel,
.klokke-scene.bart .klokke-topp,
.klokke-scene.bart .klokke-strek { display: none; }

/* Klokka blir stående, men flytter i hjørnet og krymper: «hvor lenge har vi
   igjen» er et spørsmål klassen har mens de ser på bildet, og et tall i et
   hjørne dekker ingenting. `position: absolute` og ikke bare mindre skrift –
   ellers ville den fortsatt tatt en stripe av flata midt på.

   Går det en runde, står klokka i det samme hjørnet enten knappene er framme
   eller ikke: «Vis knappene» skal hente panelet, ikke flytte klokka fra
   hjørnet til midten av bildet og tilbake igjen. */
.klokke-scene.bart .klokke-midt,
.klokke-scene.spiller .klokke-midt {
  position: absolute; top: 14px; right: 18px; z-index: 3;
  align-items: flex-end; text-align: right; gap: 2px;
}
.klokke-scene.bart .klokke-stor,
.klokke-scene.spiller .klokke-stor { font-size: min(6vw, 9vh); text-shadow: 0 2px 16px rgba(0, 0, 0, .55); }
.klokke-scene.bart .klokke-liten,
.klokke-scene.spiller .klokke-liten { font-size: min(2vw, 3vh); }
.klokke-scene.bart .klokke-melding,
.klokke-scene.spiller .klokke-melding {
  font-size: min(2.6vw, 4vh); max-width: 30ch; text-align: right;
}

/* HØYREKANTEN I HJØRNET.

   De fire linjene – beskjeden, nedtellingen, «Slutt 13:10» og klokkeslettet –
   leses som én blokk, og da er den ene rette kanten de har, den høyre. Ute på
   flata er «Slutt» en pille med sin egen flate å stå på; her ville de 22
   pikslene med luft inne i den skjøvet nettopp det tallet 22 px inn, mens de
   tre andre lå helt ute. Det var ikke til å se bort fra: tre av fire tall
   endte på hver sin x.

   Derfor mister pilla flata si i hjørnet. Over et fotografi er det ikke
   flata som gjør tallet lesbart uansett – det er skyggen, og den får alle
   fire nå. `padding: 0` er hele fiksen; resten er at de da må se like ut. */
.klokke-scene.bart .klokke-slutt,
.klokke-scene.spiller .klokke-slutt {
  font-size: min(2.4vw, 3.6vh); padding: 0; background: none;
  text-shadow: 0 2px 16px rgba(0, 0, 0, .55);
}
.klokke-scene.bart .klokke-liten,
.klokke-scene.spiller .klokke-liten,
.klokke-scene.bart .klokke-melding,
.klokke-scene.spiller .klokke-melding { text-shadow: 0 2px 16px rgba(0, 0, 0, .55); }

/* Veien tilbake. Utvasket til noen tar på den: klassen skal se bildet, ikke
   knappen – men den må FINNES, for en modus man bare kommer ut av med Escape
   er en modus noen blir sittende fast i foran klassen. */
.klokke-tilbake {
  position: absolute; right: 16px; bottom: 14px; z-index: 4;
  display: inline-flex; align-items: center; gap: 6px;
  min-height: 34px; padding: 6px 14px; border-radius: 999px;
  border: 1px solid rgba(255, 255, 255, .35);
  background: rgba(12, 20, 24, .55); color: #fff;
  font: inherit; font-size: 13px; cursor: pointer;
  opacity: .28; transition: opacity .18s ease;
}
.klokke-tilbake:hover, .klokke-tilbake:focus-visible { opacity: 1; }

/* På en telefon finnes det ingen peker å holde over noe. Der står veien ut
   framme hele tida – det samme unntaket panelet og hjørneknappene har. */
@media (max-width: 620px) {
  .klokke-tilbake { opacity: 1; }
}

.klokke-stjerner circle { animation: klokkeBlink 5s ease-in-out infinite; }
@keyframes klokkeBlink { 0%, 100% { opacity: .25; } 50% { opacity: 1; } }
/* Snøen faller gjennom hele flata og begynner på nytt. `translateY` på 120
   brukerenheter er hele viewBoxen og litt til, slik at ingen flak popper inn
   eller ut midt på skjermen. */
.klokke-sno circle { animation: klokkeSno 12s linear infinite; }
@keyframes klokkeSno {
  0% { transform: translateY(0); }
  100% { transform: translateY(120px); }
}

.klokke-midt {
  position: relative; z-index: 1;
  display: flex; flex-direction: column; align-items: center; gap: 6px;
  text-align: center; max-width: 100%;
}
.klokke-melding {
  font-family: var(--display); font-size: min(5vw, 8vh); line-height: 1.15;
  max-width: 22ch; text-wrap: balance;
}
/* Tallene er det eneste på skjermen som må leses fra bakerste rad.
   `tabular-nums` hindrer at klokka rykker sidelengs hvert sekund. */
.klokke-stor {
  font-family: var(--display); font-weight: 700; line-height: 1;
  font-size: min(19vw, 34vh);
  font-variant-numeric: tabular-nums; font-feature-settings: "tnum";
  text-shadow: 0 2px 24px rgba(0, 0, 0, .28);
}
.klokke-scene[data-blekk="tema"] .klokke-stor { text-shadow: none; }
.klokke-liten {
  font-size: min(4.5vw, 7vh); color: var(--klokke-blekk-2);
  font-variant-numeric: tabular-nums; font-feature-settings: "tnum";
}
/* «Slutt 13:10» – svaret på det klassen spør om høyt. Den står som en brikke
   og ikke som enda en linje tekst, fordi den skal kunne leses fra bakerste rad
   uten å blandes sammen med klokkeslettet under: nedtellingen er stor, dette
   er ETT tall å huske, og det som står nå er det minste av de tre. */
.klokke-slutt {
  font-size: min(5vw, 7.5vh); font-weight: 700; line-height: 1.1;
  font-variant-numeric: tabular-nums; font-feature-settings: "tnum";
  padding: 2px 22px; border-radius: 999px;
  background: var(--klokke-flate); color: var(--klokke-blekk);
}
/* Hjørneutgaven av «Slutt 13:10» står lenger opp, sammen med de tre andre
   linjene den skal dele høyrekant med – både `.bart` og `.spiller` flytter
   klokka dit. Ha ikke to steder som setter den. */
.klokke-sagt {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap;
}
.klokke-scene.ute .klokke-stor { animation: klokkeUte 1.1s ease-out 3; }
@keyframes klokkeUte {
  0%, 100% { transform: scale(1); }
  35% { transform: scale(1.06) rotate(-1.2deg); }
  70% { transform: scale(1.06) rotate(1.2deg); }
}

/* Framdriftslinja: hvor langt uti oppgaven klassen er, lest uten å regne. */
.klokke-strek {
  position: relative; z-index: 1; width: min(1100px, 86vw); height: 6px;
  border-radius: 999px; background: var(--klokke-flate);
}
.klokke-strek-fylt {
  position: absolute; inset: 0 auto 0 0; width: 0;
  border-radius: 999px; background: var(--klokke-blekk); opacity: .75;
}
.klokke-strek-hode {
  position: absolute; top: 50%; left: 0; width: 18px; height: 18px;
  margin: -9px 0 0 -9px; border-radius: 50%;
  background: var(--klokke-blekk); box-shadow: 0 2px 10px rgba(0, 0, 0, .3);
}

/* Panelet faller tilbake så snart klokka er i BRUK: da er skjermen klassens,
   og knapper de ikke skal trykke på er støy. Før den er startet er den
   lærerens – der er «Start» det man kom for, og en utvasket knapp ser ut som
   den ikke virker. Det forsvinner aldri helt: en lærer som skal legge til ett
   minutt, skal se hvor knappen er uten å lete med musa. */
.klokke-panel {
  position: relative; z-index: 2; width: 100%;
  display: flex; flex-direction: column; align-items: center; gap: 8px;
  opacity: .4; transition: opacity .18s ease;
}
.klokke-scene[data-tilstand="klar"] .klokke-panel { opacity: 1; }
/* ... men står spillet på, er skjermen klassens uansett om det går en
   nedtelling eller ikke. Da er femten knapper under kartet noe klassen leser i
   stedet for å se på bildet. Regelen står ETTER «klar»-regelen med vilje: den
   skal vinne over den. */
.klokke-scene.spiller .klokke-panel { opacity: .4; }
.klokke-panel:hover, .klokke-panel:focus-within { opacity: 1; }
.klokke-rad {
  display: flex; align-items: center; justify-content: center;
  gap: 8px; flex-wrap: wrap;
}
.klokke-rad-2 { font-size: 13px; }
.klokke-felt {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 13px; color: var(--klokke-blekk-2);
}
.klokke-felt input[type="number"] { width: 66px; text-align: center; }
.klokke-felt input[type="text"] { width: 88px; text-align: center; }
.klokke-melding-felt input[type="text"] { width: min(320px, 46vw); text-align: left; }
.klokke-felt input, .klokke-felt select { min-height: 34px; }
.klokke-felt input.feil { border-color: var(--warn); }
/* Over en tegnet bakgrunn må kontrollene ha sin egen flate å stå på – appens
   egne felt- og knappefarger er laget for en side, ikke for en stjernehimmel. */
.klokke-scene[data-blekk="lys"] .klokke-felt input,
.klokke-scene[data-blekk="lys"] .klokke-felt select,
.klokke-scene[data-blekk="lys"] .klokke-panel .btn {
  background: rgba(12, 20, 24, .55); color: #fff; border-color: rgba(255, 255, 255, .35);
}
.klokke-scene[data-blekk="lys"] .klokke-panel .btn.active,
.klokke-scene[data-blekk="lys"] .klokke-panel .btn-primary {
  background: var(--accent); border-color: var(--accent); color: var(--on-accent);
}

/* Veien ut, i hjørnet. Samme falming som panelet: «Klasserom» og «Fullskjerm»
   er knapper klassen ikke skal trykke på. */
.klokke-topp {
  position: absolute; top: 12px; right: 14px; z-index: 3;
  display: flex; gap: 8px; align-items: center;
  opacity: .3; transition: opacity .18s ease;
}
.klokke-topp:hover, .klokke-topp:focus-within { opacity: 1; }
.klokke-scene[data-blekk="lys"] .klokke-topp .btn {
  background: rgba(12, 20, 24, .55); color: #fff; border-color: rgba(255, 255, 255, .35);
}

@media (max-width: 620px) {
  .klokke-stor { font-size: min(26vw, 22vh); }
  .klokke-melding { font-size: min(7vw, 5vh); }
  .klokke-panel, .klokke-topp { opacity: 1; }
  /* En telefon ruller; en storskjerm gjør det ikke. Med spillet oppe har
     panelet flere knapper enn det er plass til på 390 px, og `overflow: hidden`
     på scenen ville KLIPPET den siste raden bort i stedet for å la den nås –
     knappene ville vært der, og likevel umulige å trykke på. Sidelengs står
     klippingen: det er bakgrunnslagene som trenger den.

     Bakgrunnen festes til vinduet. Uten det slutter fotografiet der den første
     skjermhøyden slutter, og resten av sida står på bar flate. */
  .klokke-scene { overflow: hidden auto; }
  .klokke-scene .klokke-bg { position: fixed; }
  /* Krediteringen ligger fast i hjørnet. På en bred skjerm står den for seg
     selv; på en telefon rekker panelet helt ned, og de to legger seg oppå
     hverandre. Litt luft under panelet, så begge er til å lese. */
  .klokke-scene[data-bakgrunn="foto"] { padding-bottom: 34px; }
  /* `order` og ikke DOM-rekkefølge: knappene skal stå ØVERST på en telefon,
     men i hjørnet over alt annet på en storskjerm. */
  .klokke-topp { position: static; justify-content: center; order: -1; }
  .klokke-scene { padding-top: 12px; }
}

@media (prefers-reduced-motion: reduce) {
  .klokke-scene.ute .klokke-stor { animation: none; }
  .klokke-stjerner circle, .klokke-sno circle { animation: none; }
}

/* --- «Gjett stedet» (site/gjettstedet.js) ---

   Kartet er et MINIKART i hjørnet, ikke en spalte under klokka. Det sto som
   et ledd i den samme spalten før, og på en projektor i 1366×768 endte det
   nøyaktig oppå den delen av fotografiet klassen skulle studere – altså oppå
   oppgaven. Nå ligger det nede til høyre, over bildet, og vokser innover fra
   kanten når noen skal bruke det.

   Tre tilstander, og alle tre er nødvendige:
     · lukket   – et lite kart i hjørnet, stort nok til å kjenne igjen
                  verdensdelene på, lite nok til å dekke ingenting.
     · åpen     – hovringen eller tastaturfokus. Går av seg selv.
     · festet   – lærerens eget valg, og den ENESTE som finnes på en
                  tavleskjerm eller et nettbrett. Se `erApen()` i
                  gjettstedet.js: et trykk på det lukkede kartet fester det.

   Bredden er én variabel, og overgangen ligger på den. Da er «kommer inn fra
   siden» én `transition` og ikke fire. */

/* `display: contents` – innpakningen finnes bare for at klokke.js skal ha et
   sted å henge spillet, og skal ikke selv være et ledd i spalten. */
.klokke-spill { display: contents; }

.gjett {
  position: absolute; right: 16px; bottom: 16px; z-index: 5;
  display: flex; flex-direction: column; align-items: flex-end; gap: 6px;
  --gjett-b: 264px;
}
.gjett.apen { --gjett-b: min(720px, 52vw, 96vh); }

/* Knapperaden er LÆRERENS, og holder sin egen bredde: den skal ikke bryte i
   fire linjer fordi kartet under er slått sammen. Den falmer tilbake som
   `.klokke-panel` gjør, og av samme grunn – skjermen er klassens. */
.gjett-linje {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  justify-content: flex-end; font-size: 13px;
  opacity: .45; transition: opacity .18s ease;
}
.gjett:hover .gjett-linje, .gjett:focus-within .gjett-linje { opacity: 1; }
.gjett-hvem { display: inline-flex; align-items: center; gap: 6px; }
.gjett-ferdig { font-weight: 700; }
.gjett-knapper { display: flex; gap: 6px; flex-wrap: wrap; }

/* Brikka er lagets farge med lagnummeret i. Den samme fargen bærer nåla på
   kartet og raden på tavla, og det er hele koblingen mellom de tre. */
.gjett-brikke {
  display: inline-grid; place-items: center;
  width: 22px; height: 22px; border-radius: 50%;
  color: #fff; font-weight: 700; font-size: 12px;
  text-shadow: 0 1px 2px rgba(0, 0, 0, .45);
}

/* Kartet har FAST 2:1-format. Det er ikke en smakssak: `andelAv()` regner om fra
   piksler til en andel av boksen, og `punktGrader()` skalerer den andelen rett
   på viewBoxen – og den regningen stemmer bare så lenge de to har samme
   forhold. Zoomen endrer
   bredden på viewBoxen, aldri forholdet – endrer du `aspect-ratio` her, må
   omregningen dit i stedet.

   `touch-action` er to regler og ikke én. Kartet skal kunne dras og klypes –
   uten det tar nettleseren fingeren og ruller sida i stedet, og panoreringen
   finnes ikke på den ene skjermtypen den betyr mest for. Men i hele verden er
   det ingenting å panorere til: der ville `none` bare betydd at en finger som
   traff kartet ikke fikk rullet sida, og på en telefon er kartet nesten hele
   bredden. `pan-y` slipper derfor rullingen gjennom så lenge kartet står
   uzoomet – og stenger fortsatt for nettleserens egen klyping, som er den vi
   vil ha selv. Er kartet zoomet, eier det fingeren. */
.gjett-kart {
  position: relative;
  aspect-ratio: 2 / 1; width: var(--gjett-b);
  border-radius: var(--r-md); overflow: hidden;
  border: 1px solid rgba(255, 255, 255, .28);
  box-shadow: 0 8px 30px rgba(0, 0, 0, .45);
  cursor: crosshair; touch-action: pan-y;
  transition: width .22s ease;
}
.gjett.zoomet .gjett-kart { cursor: grab; touch-action: none; }
.gjett-avslort .gjett-kart { cursor: default; }
.gjett-svg { display: block; width: 100%; height: 100%; }
.gjett-hav { fill: #16324A; }
/* `non-scaling-stroke` av samme grunn som på fasitstreken, bare den andre
   veien: zoomer læreren inn fjorten ganger, blir en grense tegnet i
   kartkoordinater fjorten ganger så tykk, og Middelhavet får en svart
   ramme rundt seg. Streken skal være like tynn uansett hvor nær man står. */
.gjett-land path {
  fill: #C8D6C4; stroke: #16324A; stroke-width: .8;
  vector-effect: non-scaling-stroke;
}

/* Zoomknappene ligger oppå kartet, der de gjør i et hvilket som helst kart.
   De er små, men ikke mindre enn en finger: 32 px er gulvet på en tavleskjerm.
   Trykkbehandlingen slipper alt som kommer fra en knapp, ellers ville et trykk på «+»
   lagt igjen en nål under den. */
.gjett-verktoy {
  position: absolute; right: 6px; top: 6px;
  display: flex; flex-direction: column; gap: 4px;
}
.gjett-verktoyknapp {
  display: inline-grid; place-items: center;
  width: 32px; height: 32px; padding: 0;
  border-radius: var(--r-sm); border: 1px solid rgba(255, 255, 255, .3);
  background: rgba(12, 20, 24, .62); color: #fff;
  font: inherit; cursor: pointer;
}
.gjett-verktoyknapp:hover { background: rgba(12, 20, 24, .85); }
.gjett-verktoyknapp:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }
.gjett-verktoyknapp:disabled { opacity: .35; cursor: default; }
.gjett-verktoyknapp svg { width: 16px; height: 16px; }
/* På det lukkede kartet er det ingenting å zoome på – det er 264 px bredt, og
   to knapper til der er to knapper som dekker Europa. Bare bryteren som gjør
   kartet stort blir stående, for det er den ene handlingen som gir mening. */
.gjett:not(.apen) [data-g="inn"], .gjett:not(.apen) [data-g="ut"] { display: none; }

/* Vinket står bare på det lukkede kartet, og sier hva et TRYKK gjør. «Hold
   musa over» er et råd til den halvparten av klasserommene som har en mus. */
.gjett-vink {
  position: absolute; left: 0; right: 0; bottom: 0;
  padding: 4px 6px 5px; text-align: center;
  font-size: 12px; color: #fff;
  background: linear-gradient(180deg, rgba(8, 12, 16, 0), rgba(8, 12, 16, .72));
  pointer-events: none;
}

.gjett-naal text {
  fill: #fff; font-size: 13px; font-weight: 700; text-anchor: middle;
  paint-order: stroke; stroke: rgba(0, 0, 0, .35); stroke-width: 2;
}
.gjett-naal circle { stroke: #fff; stroke-width: 2; }
.gjett-strek { stroke-width: 2; stroke-dasharray: 5 4; opacity: .9; }
/* Fasiten er en ring som pulserer én gang – den skal finnes med øynene på en
   skjerm tretti elever ser på samtidig, ikke bare være et punkt til. */
.gjett-fasit .gjett-prikk { fill: #fff; stroke: #111; stroke-width: 2; }
.gjett-fasit .gjett-ring {
  fill: none; stroke: #fff; stroke-width: 3;
  animation: gjettRing 1.4s ease-out 2;
}
@keyframes gjettRing {
  0% { r: 7; opacity: 1; }
  100% { r: 34; opacity: 0; }
}

/* Svaret og tavla holder kartets bredde, og fasiten fester kartet åpent
   (se `fasit()`) – da har de plass til å bli lest fra bakerste rad. */
.gjett-svar, .gjett-tavle { width: var(--gjett-b); transition: width .22s ease; }
.gjett-svar {
  font-size: 15px; text-align: center;
  text-shadow: 0 2px 12px rgba(0, 0, 0, .6);
}
.gjett-svar svg { vertical-align: -2px; }

/* Lenka ut til Google Earth står i fasitlinja, men er en annen slags ting enn
   svaret ved siden av: et tilbud læreren kan ta imot, ikke opplysningen selv.
   Derfor en pille med ramme rundt og ikke understreket tekst – og en ramme
   som er stor nok til å treffes med en finger på en tavleskjerm. */
.gjett-earth {
  display: inline-flex; align-items: center; gap: 5px;
  margin-left: 8px; padding: 2px 10px;
  border: 1px solid rgba(255, 255, 255, .38); border-radius: 999px;
  background: rgba(12, 20, 24, .45);
  color: inherit; text-decoration: none; white-space: nowrap;
  font-size: 13px;
}
.gjett-earth:hover { background: rgba(255, 255, 255, .18); }
.gjett-earth:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }

.gjett-tavle {
  list-style: none; margin: 0; padding: 0;
  display: flex; flex-direction: column; gap: 3px; font-size: 13px;
}
.gjett-rad {
  display: grid; grid-template-columns: 22px 1fr auto auto;
  align-items: center; gap: 8px;
  padding: 2px 8px; border-radius: var(--r-sm);
  background: rgba(12, 20, 24, .55);
}
.gjett-best { background: rgba(255, 255, 255, .26); font-weight: 700; }
.gjett-poeng { font-variant-numeric: tabular-nums; }
.gjett-sum { font-variant-numeric: tabular-nums; opacity: .7; font-size: 12px; }
.gjett-sagt {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap;
}

/* Panelet og minikartet deler den nederste kanten. Panelet er midtstilt på
   en tom skjerm, og en midtstilt rad på 1366 px rekker inn under kortet –
   derfor legges det til venstre så lenge en runde går. Det er bare synlig
   når læreren har hentet knappene fram igjen; runden starter uten dem. */
.klokke-scene.spiller { justify-content: flex-end; padding-bottom: 36px; }
.klokke-scene.spiller .klokke-panel {
  align-self: flex-start; align-items: flex-start; max-width: 52vw;
}
.klokke-scene.spiller .klokke-rad { justify-content: flex-start; }
.klokke-scene.spiller .klokke-strek { align-self: stretch; width: auto; }

/* Klokka og hjørneknappene deler det øverste høyre hjørnet så lenge knappene
   er framme. `.bart` har dem ikke, og da får klokka hele hjørnet. */
.klokke-scene.spiller:not(.bart) .klokke-midt { top: 58px; }

/* Veien ut av «Bare bildet» står nederst til høyre – men det er der kartet
   ligger nå. Under en runde flytter den til det ene hjørnet ingenting annet
   bruker. */
.klokke-scene.spiller .klokke-tilbake {
  top: 14px; left: 16px; right: auto; bottom: auto;
}

/* En telefon ruller, og der er hjørnet ikke noe sted å ha et kart: skjermen
   er smalere enn kortet uansett. Da står spillet i spalten som før, i full
   bredde, og hovringen finnes ikke – `festet` er den eneste veien inn, og
   det er nettopp det et trykk på kartet gjør. */
@media (max-width: 620px) {
  .gjett {
    position: static; width: 100%; align-items: stretch;
    --gjett-b: 100%;
  }
  .gjett.apen { --gjett-b: 100%; }
  .gjett-linje { opacity: 1; justify-content: center; }
  .klokke-scene.spiller .klokke-midt {
    position: static; align-items: center; text-align: center;
  }
  .klokke-scene.spiller .klokke-stor { font-size: min(14vw, 9vh); }
  .klokke-scene.spiller .klokke-melding { text-align: center; }
  .klokke-scene.spiller .klokke-panel {
    align-self: center; align-items: center; max-width: 100%;
  }
  .klokke-scene.spiller .klokke-rad { justify-content: center; }
  .klokke-scene.spiller { justify-content: flex-start; }
}

@media (prefers-reduced-motion: reduce) {
  .gjett-fasit .gjett-ring { animation: none; opacity: .9; }
  .gjett, .gjett-kart, .gjett-svar, .gjett-tavle { transition: none; }
}

/* -------------------------------------------------- 7b. Onboarding

   Velkomstkortet, lyskasteren og hjelpe-oppslagsverket. Lyskasteren er én
   ramme med en svært stor skygge rundt: da blir alt utenfor mørkt uten fire
   egne felt, og rammen kan animeres fra knapp til knapp. */

/* --- Velkomstkortet på forsiden --- */
.velkomst h3 { font-size: 21px; margin-bottom: 8px; }
.velkomst > p { color: var(--ink-2); line-height: 1.55; max-width: 62ch; }
.velkomst > p + p { margin-top: 8px; }
.velkomst-under { color: var(--ink-3); font-size: 13.5px; }
.velkomst-valg { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 18px; }
.velkomst-valg .btn {
  flex: 1 1 210px; min-height: var(--tap);
  display: flex; flex-direction: column; align-items: flex-start; gap: 2px;
  padding: 12px 16px; text-align: left; font-weight: 700;
}
/* Knappen stables loddrett: tittel over undertekst. Tittelen har sitt eget
   element så ikonet står ved siden av teksten og ikke blir en tredje etasje. */
.velkomst-valg .btn b { display: flex; align-items: center; gap: 8px; font-weight: inherit; }
.velkomst-valg .btn span { font-weight: 400; font-size: 12.5px; opacity: .8; }
.velkomst-valg .btn-ghost { border-color: var(--line); }


/* --- Navnebyttet fra «Klassekart» til «Klassen» ---
   Midlertidig, se FLYTT i app.js: hele denne blokka slettes med delen der. */
.flytt-kort { border-color: var(--accent); }
.flytt-kort h3 { display: flex; align-items: center; gap: 8px; font-size: 19px; margin-bottom: 10px; }
.flytt-kort p { color: var(--ink-2); line-height: 1.55; max-width: 62ch; margin-bottom: 8px; }
.flytt-valg { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 16px; }
.flytt-valg .btn { min-height: var(--tap); }
.nav-footer .flytt-hint, .flytt-hint { color: var(--ink-2); }

/* --- Lyskasteren --- */
.tour-overlay { position: fixed; inset: 0; z-index: 250; }
.tour-spot {
  position: fixed; border-radius: 12px;
  border: 2px solid var(--accent);
  box-shadow: 0 0 0 9999px rgba(8, 20, 18, .62);
  pointer-events: none;
  transition: top .2s ease, left .2s ease, width .2s ease, height .2s ease;
}
.tour-spot.tom { border-color: transparent; }
.tour-bubble {
  position: fixed; width: 370px; max-width: calc(100vw - 16px);
  max-height: calc(100vh - 16px); overflow-y: auto;
  background: var(--surface); color: var(--ink);
  border: 1px solid var(--line); border-radius: var(--r-lg);
  padding: 16px 18px 14px; box-shadow: 0 20px 60px var(--shadow-2);
}
.tour-bubble:focus { outline: none; }
.tour-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.tour-count {
  font-size: 12px; font-weight: 700; letter-spacing: .04em;
  text-transform: uppercase; color: var(--ink-3);
}
.tour-x {
  border: 0; background: transparent; color: var(--ink-3); cursor: pointer;
  font-size: 15px; line-height: 1; padding: 6px; margin: -6px -8px -6px 0;
  border-radius: var(--r-sm);
}
.tour-x:hover { background: var(--surface-2); color: var(--ink); }
/* Flex, ikke vertical-align: tittelen i boblen har ikon foran teksten, og
   overskriftsfonten gir for lite luft mellom dem på egen hånd. */
.tour-title {
  font-family: var(--display); font-size: 17px; margin: 2px 0 8px;
  display: flex; align-items: center; gap: 8px;
}
.tour-text { font-size: 14px; line-height: 1.55; color: var(--ink-2); }
.tour-text p { margin: 0 0 8px; }
.tour-text p:last-child { margin-bottom: 0; }
.tour-text b { color: var(--ink); }
.tour-text ol, .tour-text ul { margin: 0 0 8px; padding-left: 20px; }
.tour-hint {
  background: var(--accent-soft); color: var(--ink-2);
  border-radius: var(--r-sm); padding: 8px 10px; font-size: 13px;
}
.tour-nav { display: flex; align-items: center; gap: 8px; margin-top: 14px; }
.tour-nav .tour-next { margin-left: auto; }
.tour-nav .btn { min-height: 36px; }
.tour-dots { display: flex; gap: 5px; }
.tour-dot {
  width: 6px; height: 6px; border-radius: 50%;
  background: var(--line); display: inline-block;
}
.tour-dot.on { background: var(--accent); }

/* --- Hjelp: oppslagsverket --- */
.hjelp { display: flex; flex-direction: column; gap: 14px; }
.hjelp-topp {
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
  background: var(--accent-soft); border-radius: var(--r-md); padding: 14px 16px;
}
.hjelp-topp > div { flex: 1 1 220px; }
.hjelp-topp p { font-size: 13px; color: var(--ink-2); line-height: 1.5; margin-top: 2px; }
.hjelp-topp .btn { min-height: var(--tap); }
.hjelp-intro { font-size: 13px; color: var(--ink-3); margin-bottom: -6px; }
.hjelp-liste { display: flex; flex-direction: column; gap: 6px; }
.hjelp-bolk + .hjelp-bolk { margin-top: 20px; }
.hjelp-bolk h4 {
  font-size: 12px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
  color: var(--ink-3); margin-bottom: 2px;
}
.hjelp-bolk-intro {
  font-size: 12.5px; color: var(--ink-3); line-height: 1.5; margin-bottom: 8px;
  max-width: 64ch;
}
.hjelp-tema { border: 1px solid var(--line-soft); border-radius: var(--r-md); overflow: hidden; }
.hjelp-tema[open] { border-color: var(--line); background: var(--surface-2); }
.hjelp-tema summary {
  cursor: pointer; padding: 11px 14px; min-height: var(--tap);
  display: flex; flex-direction: column; justify-content: center; gap: 1px;
}
.hjelp-tema summary::-webkit-details-marker { display: none; }
.hjelp-tema summary:hover { background: var(--surface-2); }
.hjelp-tittel { font-weight: 700; font-size: 14.5px; }
.hjelp-kort { font-size: 12.5px; color: var(--ink-3); }
.hjelp-tekst {
  padding: 2px 14px 14px; font-size: 13.5px; line-height: 1.55; color: var(--ink-2);
}
.hjelp-tekst p { margin: 0 0 8px; }
.hjelp-tekst ul, .hjelp-tekst ol { margin: 0 0 8px; padding-left: 20px; }
.hjelp-tekst li { margin-bottom: 3px; }
.hjelp-tekst b { color: var(--ink); }
.hjelp-vis { margin-top: 4px; }


/* --- Hjelp for én side ---

   Samme kort som i oppslagsverket, men uten bolkoverskriftene: lista er kort
   nok til at inndelingen bare hadde vært støy. Introen står øverst fordi den
   svarer på «hva er denne sida», som er spørsmålet under halvparten av
   trykkene på knappen. */
.sidehjelp-intro {
  font-size: 14px; line-height: 1.55; color: var(--ink-2); max-width: 62ch;
}
.sidehjelp .hjelp-topp p { margin-top: 2px; }

/* Hjelpeknappen i topplinja. Den er en `.btn` som alle andre og arver derfor
   plasseringen i `.head-actions` – men den er den minst viktige knappen der,
   og skal ikke konkurrere med «+ Ny klasse» om blikket. */
.btn-sidehjelp { color: var(--ink-2); }
.btn-sidehjelp:hover { color: var(--ink); }
/* Under 1200 px er toppraden trang: der får kartsida fire knapper til høyre,
   og ordet «Hjelp» er det som dytter dem ned på en linje for seg selv. Ikonet
   blir stående, og `title`/`aria-label` bærer ordet videre. Grensa er den
   samme som `.head-meta` bruker, og av samme grunn – se «Toppraden» over. */
@media (min-width: 721px) and (max-width: 1199px) {
  .page-head .btn-sidehjelp .btn-ord { display: none; }
  .page-head .btn-sidehjelp { padding: 0 10px; }
}

/* --------------------------------------------------------- Forsiden

   Sida er tre bolker under hverandre, og hver bolk er en overskrift med en
   rad snarveier under. Ingenting her har sin egen tilstand: alt er lenker til
   noe som finnes et annet sted i appen. */
.hjem-hilsen {
  font-family: var(--display); font-size: 17px; color: var(--ink-2);
  margin: -6px 0 18px; text-transform: none;
}
.hjem-bolk { margin-top: 30px; }
.hjem-bolk:first-of-type { margin-top: 22px; }
.hjem-bolk-head {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin-bottom: 12px;
}
.hjem-bolk-head h3 {
  font-size: 17px; display: flex; align-items: center; gap: 8px; margin-right: auto;
}
.hjem-bolk-head h3 svg { color: var(--accent); }
.hjem-bolk-meta { font-size: 13px; color: var(--ink-2); text-decoration: none; }
.hjem-bolk-meta:hover { color: var(--ink); text-decoration: underline; }
.hjem-velger {
  display: flex; align-items: center; gap: 8px;
  font-size: 13.5px; font-weight: 600; color: var(--ink-2);
}

/* Snarveiene er de samme kortene som i klasserommet, bare tettere: her står
   de ved siden av to andre bolker, ikke alene på en storskjerm. Klassen
   gjenbrukes med vilje – to kort som gjør det samme, skal se like ut. */
.hjem-snarveier {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 12px;
}
.hjem-snarveier .kr-kort { padding: 15px; gap: 5px; text-decoration: none; }
.hjem-snarveier .kr-kort b { font-size: 16px; }
.hjem-snarveier .kr-ico { font-size: 23px; }
/* Et kort uten href er ikke en lenke, og skal ikke se ut som en. Samme
   uttrykk som `.kr-kort:disabled`, som er den samme tilstanden på en knapp. */
.hjem-snarveier .kr-kort.av { opacity: .55; cursor: default; box-shadow: none; }
.hjem-snarveier .kr-kort.av .kr-ico { color: var(--ink-3); }

.hjem-klasser {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 12px;
}
.hjem-klasse {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r-lg); padding: 14px 15px;
  display: flex; flex-direction: column; gap: 6px;
}
.hk-topp { display: flex; align-items: center; gap: 6px; }
.hk-navn {
  font-family: var(--display); font-size: 18px; font-weight: 700;
  color: var(--ink); text-decoration: none; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.hk-navn:hover { color: var(--accent); }
.hk-meta { font-size: 12.5px; color: var(--ink-2); margin: 0; }
.hjem-klasse .bursdag-linje { margin: 0; }
.hk-lenker { display: flex; flex-wrap: wrap; gap: 6px; margin-top: auto; padding-top: 6px; }
.hjem-flere { font-size: 13px; margin-top: 10px; }

.hjem-sist {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 10px;
}
.hjem-sist-kort {
  display: flex; flex-direction: column; gap: 2px; padding: 12px 14px;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r-md); text-decoration: none; color: var(--ink);
}
.hjem-sist-kort:hover { border-color: var(--accent); }
.hjem-sist-kort b {
  font-size: 14.5px; display: flex; align-items: center; gap: 5px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.hjem-sist-kort span {
  font-size: 12.5px; color: var(--ink-2);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.hjem-sist-dato { color: var(--ink-3); }

.hjem-igang { display: grid; grid-template-columns: 1fr auto; gap: 10px 14px; align-items: center; }
.hjem-igang p { font-size: 13px; color: var(--ink-2); margin: 2px 0 0; }

.hjem-kopi, .hjem-fot {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  font-size: 13px; margin-top: 26px;
}
.hjem-kopi { margin-top: 26px; }
.hjem-fot { margin-top: 18px; color: var(--ink-3); }

@media (max-width: 720px) {
  .hjem-igang { grid-template-columns: 1fr; }
  .hjem-bolk-head h3 { font-size: 16px; }
}
/* På en telefon blir fem kort i én kolonne en lang rulling for noe som skal
   være en snarvei. To i bredden gjør raden til tre, og kortet er fortsatt
   stort nok til å treffes med tommelen. */
@media (max-width: 560px) {
  .hjem-snarveier { grid-template-columns: repeat(2, 1fr); }
  .hjem-snarveier .kr-kort { padding: 12px; }
  .hjem-snarveier .kr-kort b { font-size: 14.5px; }
  .hjem-snarveier .kr-ico { font-size: 20px; }
  .hjem-snarveier .kr-under { font-size: 11.5px; }
}

/* ----------------------------------------------------------- 8. Utskrift */


/* --------------------------------------------------- Lim inn sitteplan

   Veiviseren viser kartet i miniatyr, og da må dialogen ha litt mer bredde enn
   vanlig: forhåndsvisningen er det læreren faktisk godkjenner. Under 720 px er
   dialogen et bunnark i full bredde, og da skal den ikke bli 660 px bred. */
@media (min-width: 720px) {
  .modal.wide { width: 660px; }
}
/* Kontrollen av et importert bilde er en tabell og ikke en liste: den trenger
   plass i bredden for at alle plassene i en rad skal få stå ved siden av
   hverandre, slik de gjør i klasserommet. */
@media (min-width: 940px) {
  .modal.xwide { width: 900px; }
}
.paste-prev-wrap { display: flex; justify-content: center; }
.paste-prev { margin: 0 auto; }
.paste-prev .desk { border-bottom-width: 3px; }
.paste-prev-note { font-size: 12.5px; color: var(--ink-2); text-align: center; line-height: 1.45; }
.paste-sum { font-size: 13px; color: var(--ink-2); line-height: 1.5; }
.paste-link-list {
  display: flex; flex-direction: column; gap: 8px;
  max-height: 34vh; overflow-y: auto; padding: 2px;
}
.paste-link-row { display: flex; align-items: center; gap: 10px; }
.paste-link-row .pl-name {
  flex: 0 0 38%; min-width: 0; font-weight: 600; font-size: 14px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.paste-link-row select { flex: 1 1 auto; min-width: 0; }

/* Kom tabellen fra et bilde, står bildet ved siden av forhåndsvisningen mens
   læreren svarer på hvilken vei tavla står. De to skal kunne sammenlignes uten
   å rulle, så de deler bredden – og under 720 px legger de seg over hverandre
   med bildet øverst, fordi det er fasiten. */
.paste-prev-rad { display: flex; gap: 14px; align-items: flex-start; justify-content: center; }
.paste-prev-rad .paste-prev-wrap { flex: 1 1 55%; min-width: 0; }
.paste-kilde { flex: 0 1 40%; min-width: 0; margin: 0; }
.paste-kilde img {
  width: 100%; height: auto; display: block;
  border: 1px solid var(--line); border-radius: var(--r-sm);
}
.paste-kilde figcaption {
  font-size: 11.5px; color: var(--ink-2); text-align: center; margin-top: 4px;
}

/* --------------------------------------------------- Importer bilde */

.bi-slipp {
  display: flex; flex-direction: column; align-items: center; gap: 4px;
  border: 2px dashed var(--line); border-radius: var(--r-md);
  padding: 26px 16px; text-align: center; cursor: pointer;
  background: var(--surface-2); color: var(--ink);
}
.bi-slipp:hover, .bi-slipp:focus-visible, .bi-slipp.over {
  border-color: var(--accent); background: var(--accent-soft);
}
.bi-slipp small { font-size: 12.5px; color: var(--ink-2); }
.bi-slipp-ico { width: 30px; height: 30px; color: var(--ink-2); }

.bi-framdrift {
  height: 8px; border-radius: 99px; background: var(--line);
  overflow: hidden; margin: 10px 0;
}
.bi-framdrift > div { height: 100%; width: 0; background: var(--accent); transition: width .15s linear; }

.bi-hjelp { font-size: 13.5px; color: var(--ink-2); line-height: 1.5; }
.bi-sum { font-size: 12.5px; color: var(--ink-2); line-height: 1.5; }
.bi-utvei { font-size: 12.5px; color: var(--ink-2); display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }

/* Bildet det hele kom fra, sammenklappbart. Det er fasit når et navn ser rart
   ut, men det tar plassen fra rutene resten av tiden – så det står åpent bare
   når vi har noe å be læreren se etter. */
.bi-kilde { border: 1px solid var(--line); border-radius: var(--r-sm); padding: 8px 10px; }
.bi-kilde summary { font-size: 12.5px; color: var(--ink-2); cursor: pointer; }
.bi-kilde img {
  display: block; width: 100%; max-height: 26vh; object-fit: contain;
  margin-top: 8px; background: #fff; border-radius: var(--r-sm);
}

/* Kontrollen av det vi leste ut av bildet.

   Første utgave var tabulatortekst i et tekstfelt – samme format som
   innlimingen. Det er lesbart for en maskin og ubrukelig for et menneske:
   kolonnene sklir ut fra hverandre fordi navnene er ulike lange, og skal du
   rette ett navn må du telle deg fram til hvilken pult det er. Her er kartet
   selv kontrollen, i miniatyr, med navnet i et felt du klikker i. */
/* Rutene skal alltid få plass i bredden. En kolonne som havner utenfor
   rullekanten er verre enn en smal kolonne: den er usynlig, og da leser
   læreren korrektur på seks av sju rader uten å vite det. Derfor minmax(0,1fr)
   i markupen og ombrekking i ruta, ikke sidelengs rulling. */
.bi-rutenett-ramme { overflow-x: auto; padding: 2px; margin: 0 -2px; }
.bi-rutenett {
  display: grid; gap: 7px;
  grid-template-columns: repeat(var(--kol), minmax(0, 1fr));
}
.bi-rute {
  display: flex; align-items: stretch; min-height: var(--tap);
  border: 1px solid var(--dc, var(--line)); border-bottom-width: 3px;
  border-radius: var(--r-sm); background: var(--dc-fill, var(--surface));
  padding: 2px; cursor: text;
}
.bi-rute:focus-within { outline: 2px solid var(--accent); outline-offset: 1px; }
.bi-rute .bi-navn {
  width: 100%; min-width: 0; min-height: 0; border: 0; background: none;
  padding: 4px 2px; font-size: 13px; line-height: 1.25; font-weight: 600;
  text-align: center; color: var(--ink); resize: none; overflow: hidden;
  font-family: inherit;
}
.bi-rute .bi-navn:focus { outline: none; overflow: auto; }
/* En tom rute er ikke en pult, den er en midtgang – og skal se ut som et hull */
.bi-rute.tom {
  border-style: dashed; border-bottom-width: 1px; background: none; opacity: .6;
}
.bi-rute.tom .bi-navn { font-weight: 400; }

/* Snarveien nederst i «Kom i gang»: ikke et fjerde steg, men en annen vei inn –
   derfor stiplet kant og ikke noe tall foran. */
.steps-shortcut {
  display: flex; gap: 13px; align-items: center; justify-content: space-between;
  border: 1px dashed var(--line); border-radius: var(--r-md);
  padding: 12px 14px; margin-top: 12px;
}
.steps-shortcut p { font-size: 13px; color: var(--ink-2); margin-top: 2px; line-height: 1.45; }
.steps-shortcut .btn { flex-shrink: 0; }

@media (max-width: 719px) {
  .paste-link-row { flex-direction: column; align-items: stretch; gap: 4px; }
  .paste-link-row .pl-name { flex: 0 0 auto; }
  .steps-shortcut { flex-direction: column; align-items: stretch; }
  .paste-prev-rad { flex-direction: column; align-items: stretch; }
  .paste-kilde, .paste-prev-rad .paste-prev-wrap { flex: 0 0 auto; }
  .paste-kilde img { max-height: 26vh; object-fit: contain; }
  .bi-kilde img { max-height: 20vh; }
  /* På en telefon er det ikke plass til sju pulter ved siden av hverandre uten
     at navnene blir uleselige. Da er det bedre at raden ruller sidelengs, slik
     bildet over den også må gjøre – en rad i klasserommet er en rad, og å
     brekke den om til noe annet ville gjort kontrollen vanskeligere, ikke
     lettere. */
  .bi-rutenett { gap: 5px; grid-template-columns: repeat(var(--kol), minmax(104px, 1fr)); }
  .bi-rutenett-ramme {
    /* kanten som viser at det er mer å se til høyre */
    background: linear-gradient(to left, var(--surface-2), transparent 24px);
    border-radius: var(--r-sm);
  }
}

#printArea { display: none; }
@media print {
  @page { size: A4 landscape; margin: 6mm; }

  /* html/body har height:100% til skjermbruk; beholdes den her, fyller body
     hele arket og bildet dyttes over på en tom side nummer to. */
  html, body {
    height: auto; min-height: 0; margin: 0; padding: 0;
    background: #fff; color: #000;
  }
  body > #app, #toasts, .modal-overlay, .tour-overlay, .drag-ghost { display: none !important; }

  /* Kartet har omtrent samme sideforhold som arket, så det er HØYDEN som
     avgjør. Nettleseren skriver dessuten ut topp- og bunntekst (URL, «1 av 2»,
     dato) som spiser av høyden – derfor duger ikke en fast mm-verdi.
     100vh er den plassen som faktisk er igjen til innhold; taket på 190 mm er
     en sikring for nettlesere som regner vh fra skjermen i stedet. */
  #printArea {
    display: flex; align-items: center; justify-content: center;
    height: 100vh; max-height: 190mm;
    overflow: hidden; break-inside: avoid; break-after: avoid;
  }
  #printArea img {
    width: auto; height: auto;
    max-width: 100%; max-height: 100%;
  }
}

/* --- Vurderingsplan (#/vurderingsplaner, #/vurderingsplan/<id>) ---

   Selve rutenettet ligger i vurderingsplan.css, fordi den delte sida
   (/vp/<id>) tegner det samme uten resten av appen. Her står bare det som er
   appens: verktøylinja, statuslinja for delingen og dialogene. Arket ligger i
   et .card med egen sidelengs rulling – planen er et A4-ark og skal ikke
   brekke kolonnene sine for å få plass i et smalt vindu. */

.vp-toolbar { display: flex; flex-wrap: wrap; gap: 8px 20px; align-items: center; margin-bottom: 10px; }
.vp-tips { font-size: 13px; margin: 0 0 12px; max-width: 80ch; line-height: 1.45; }
.vp-delstatus {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  font-size: 13px; color: var(--ink-2); margin: 0 0 10px;
  padding: 6px 10px; border-radius: var(--r-md); background: var(--surface-2);
}
.vp-delstatus.feil { color: var(--warn); background: var(--warn-soft); }
.vp-ark-kort { padding: 10px; }
.vp-ark-kort .vp-rull { overflow-x: auto; }
.vp-ark-kort .vp-tabell { min-width: 720px; }
.vp-lenkemerke { display: inline-flex; align-items: center; gap: 4px; color: var(--accent-ink); font-weight: 600; font-size: 13px; text-decoration: none; }
.vp-lenkemerke:hover { text-decoration: underline; }

/* Dialogene: radene med hendelser, fag og perioder er små skjemaer på én linje
   som brekker når det er trangt. Tekstfeltet tar det som er igjen. */
.vp-dialog .vp-torad { display: flex; gap: 10px; flex-wrap: wrap; }
.vp-dialog .vp-torad .field { flex: 1 1 160px; }
.vp-hliste, .vp-fliste, .vp-friliste { display: flex; flex-direction: column; gap: 6px; }
.vp-hrad, .vp-frad, .vp-frirad { display: flex; gap: 6px; align-items: center; flex-wrap: wrap; }
.vp-hrad .vp-htekst, .vp-frad .vp-fnavn, .vp-frirad .vp-fritekst { flex: 1 1 180px; min-width: 0; }
.vp-frad .vp-finnhold { flex: 2 1 240px; min-width: 0; }
.vp-hrad select, .vp-frirad input[type=date] { flex: 0 1 auto; max-width: 100%; }
.vp-hrad .checkline, .vp-frad .checkline { display: inline-flex; align-items: center; gap: 5px; font-size: 13px; font-weight: 600; color: var(--ink-2); }
.vp-frad input[type=color] { width: 40px; height: 40px; padding: 2px; border: 1px solid var(--line); border-radius: var(--r-md); background: var(--surface); }
.vp-pd-fasit { font-size: 13.5px; color: var(--ink); background: var(--accent-soft); padding: 8px 10px; border-radius: var(--r-md); margin: 0; }
.vp-dialog input[type=range] { width: 100%; }
.vp-dialog code { font-family: var(--mono); font-size: 12.5px; }
/* Stilvelgeren i Oppsett: fire kort med et frimerke av arket. Radioknappen
   er skjult, kortet er trykkflaten (minst 44 px), og valget vises med kant
   OG ring – ikke bare farge. */
.vp-stiler { border: 0; padding: 0; margin: 0; min-width: 0; display: grid; grid-template-columns: repeat(auto-fill, minmax(210px, 1fr)); gap: 8px; }
.vp-stiler legend { padding: 0; margin-bottom: 6px; font-size: 13px; font-weight: 600; color: var(--ink-2); }
.vp-stilvalg {
  position: relative; display: grid; grid-template-columns: auto minmax(0, 1fr); grid-template-rows: auto auto;
  column-gap: 10px; row-gap: 1px; align-items: center; min-height: 44px; padding: 8px 10px;
  border: 1px solid var(--line); border-radius: var(--r-md); cursor: pointer;
}
.vp-stilvalg input { position: absolute; opacity: 0; pointer-events: none; }
.vp-stilvalg:has(input:checked) { border: 2px solid var(--accent); padding: 7px 9px; background: var(--accent-soft); }
.vp-stilvalg:has(input:focus-visible) { outline: 2px solid var(--accent); outline-offset: 2px; }
.vp-stilnavn { font-weight: 700; font-size: 14px; color: var(--ink); align-self: end; }
.vp-stilom { font-size: 12.5px; font-weight: 400; line-height: 1.3; color: var(--ink-2); align-self: start; }
/* Frimerket er papir i begge temaer, som selve arket. */
.vp-mini {
  grid-row: 1 / 3; width: 66px; height: 46px; display: grid; grid-template-columns: 9px repeat(3, 1fr);
  background: #fff; border: 1px solid #b9c0c6; border-radius: 3px; overflow: hidden;
}
.vp-mini i { border-bottom: 1px solid var(--strek); border-left: 1px solid var(--lodd); }
.vp-mini.liste { display: flex; flex-direction: column; justify-content: center; gap: 7px; padding: 0 7px; }
.vp-mini.liste i { display: flex; align-items: center; gap: 4px; border: 0; }
.vp-mini.liste i::after { content: ''; flex: 1; height: 3px; border-radius: 2px; background: #c9cfd4; }
.vp-mini.liste b { flex: none; width: 7px; height: 7px; border-radius: 2px; }

/* Hjulene i «Hent fra årshjulet»: ett eller flere, med kryss for å ta ut */
.vp-hjulliste { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
.vp-hjul { display: flex; align-items: center; gap: 8px; padding: 6px 10px; border: 1px solid var(--line); border-radius: var(--r-md); background: var(--surface); }
.vp-hjul b { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.vp-hjul .warn-summary { margin: 0; padding: 2px 8px; font-size: 12.5px; }
.vp-hjul-ny { display: flex; gap: 6px; flex-wrap: wrap; }
.vp-hjul-ny input { flex: 1 1 220px; min-width: 0; }

/* --- Timeplan (#/timeplaner, #/timeplan/<id>) ---

   Klassens uke: fem dagkolonner over en tidsakse. Boksene ligger ABSOLUTT,
   i prosent av aksen, og ikke i et rutenett med en rad per økt – en
   dobbelttime er da én boks og ikke to som later som, og pausen mellom
   09:47 og 09:58 er ekte luft. Tegningen (`Timeplan.tilHTML`) er den samme
   som PDF-en er skrevet av, og alt som bestemmer HVA som står i en boks er
   avgjort i timeplan.js.

   Flata er et ARK: hvit bakgrunn og svart tekst i begge temaer, som
   vurderingsplanens rutenett. Fargene på boksene er data (fagets farge) og
   settes inline; det som står her, er form og skrift. */

.tpl {
  --tpl-h: 620px; --tpl-tid: 46px; --tpl-gap: 3px;
  background: #fff; color: #000; border-radius: var(--r-md); padding: 8px;
  font-size: 12px; line-height: 1.25; min-width: 720px;
}
.tpl-hode, .tpl-flate { display: grid; grid-template-columns: var(--tpl-tid) repeat(5, minmax(0, 1fr)); gap: var(--tpl-gap); }
.tpl-daghode {
  background: #eff1f3; border: 1px solid #d5d8dc; border-radius: 3px;
  text-align: center; font-weight: 700; font-size: 13px; padding: 5px 2px;
}
.tpl-flate { height: var(--tpl-h); margin-top: var(--tpl-gap); }
.tpl-tider, .tpl-dag { position: relative; }
.tpl-time { position: absolute; right: 5px; transform: translateY(-50%); font-size: 11px; color: #555; white-space: nowrap; }
.tpl-linje { position: absolute; left: 0; right: 0; border-top: 1px solid #e2e5e8; }
.tpl-dag { border-left: 1px solid #dfe2e6; border-right: 1px solid #dfe2e6; }

/* Boksen fyller bredden av dagen. To fag i den samme timen – 2P ved siden
   av blå blokk – får hvert sitt spor, satt inline av `tilHTML()`. Derfor
   `width` og ikke `right`: satt sammen med `left` er de to i overkant, og
   nettleseren ser bort fra den ene. */
.tpl-boks {
  position: absolute; left: 0; width: 100%; display: flex; overflow: hidden;
  border-radius: 2px; background: var(--fyll); border: 1px solid var(--kant);
}
.tpl-strek { flex: 0 0 4px; background: var(--farge); }
.tpl-boks.slag-stripe .tpl-strek { display: none; }
.tpl-innhold { position: relative; display: flex; flex-direction: column; padding: 3px 5px; min-width: 0; }
.tpl-innhold > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tpl-tid { font-size: 9.5px; color: #555; }
.tpl-tittel { font-size: 12.5px; font-weight: 700; color: var(--blekk); }
.tpl-liten { font-size: 10px; color: #444; }
.tpl-kursiv { font-size: 10px; font-style: italic; color: #333; }
/* Stripeblokka: én stripe per blokkfarge, med en mettet aksent på toppen –
   det er blokken som ikke har én farge, og den skal se ut som alle. */
.tpl-striper { position: absolute; inset: 0; display: flex; }
.tpl-striper i { flex: 1 1 0; }

/* --- byggeren --- */
.tpl-kort { padding: 10px; }
.tpl-rull { overflow-x: auto; }
.tpl-toolbar { display: flex; flex-wrap: wrap; gap: 8px 20px; align-items: center; margin-bottom: 10px; }
.tpl-tips { font-size: 13px; margin: 0 0 12px; max-width: 80ch; line-height: 1.45; }

/* Paletten: brikkene læreren blokklegger med. Den valgte er tydelig merket –
   et trykk i planen betyr noe ANNET for hver brikke, og hvilken som er
   valgt, er det eneste som sier hva. Viskelæret står sist, som i
   fargeleggingen av kartet. */
.tpl-palett { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 10px; }
.tpl-brikke {
  display: inline-flex; align-items: center; gap: 7px; min-height: var(--tap);
  padding: 5px 11px 5px 7px; border: 1px solid var(--line); border-radius: var(--r-md);
  background: var(--surface); color: var(--ink); font: inherit; font-size: 13.5px; font-weight: 600;
  cursor: pointer; max-width: 100%;
}
.tpl-brikke i { flex: 0 0 auto; width: 14px; height: 14px; border-radius: 3px; background: var(--f); border: 1px solid rgba(0, 0, 0, .25); }
.tpl-brikke span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tpl-brikke:hover { border-color: var(--accent); }
.tpl-brikke.valgt { border-color: var(--accent); background: var(--accent-soft); box-shadow: inset 0 0 0 1px var(--accent); }
.tpl-brikke.visk i { background: repeating-linear-gradient(45deg, #fff, #fff 3px, #d9d9d9 3px, #d9d9d9 6px); }
.tpl-brikke:disabled { opacity: .5; cursor: not-allowed; border-color: var(--line); }

/* Cellene ligger OVER boksene og tar imot trykket. De er usynlige til
   pekeren er over dem: arket skal se ut som arket, også mens det bygges. */
.tpl.interaktiv .tpl-celle { position: absolute; left: 0; width: 100%; cursor: pointer; touch-action: none; }
.tpl.interaktiv .tpl-celle:hover { outline: 2px solid #0B6A5F; outline-offset: -2px; background: rgba(11, 106, 95, .10); }
.tpl.interaktiv .tpl-celle:focus-visible { outline: 2px solid #0B6A5F; outline-offset: -2px; }

/* Tegnforklaringen står utenfor arket, på kortets bakgrunn – derfor arver
   den tekstfargen, som vurderingsplanens. */
.tpl-legende { font-size: 12.5px; margin-top: 10px; display: flex; flex-wrap: wrap; gap: 4px 14px; align-items: baseline; color: inherit; }
.tpl-rute { display: inline; }
.tpl-rute i { display: inline-block; width: 11px; height: 11px; border: 1px solid #787878; vertical-align: -1px; margin-right: 4px; }
.tpl-fagnavn { font-weight: 600; white-space: nowrap; }
.tpl-fag { opacity: .8; }

/* Dialogene: én rad per brikke og per økt, som i vurderingsplanen. */
.tpl-liste { display: flex; flex-direction: column; gap: 6px; }
.tpl-rad { display: flex; gap: 6px; align-items: center; flex-wrap: wrap; }
.tpl-rad .tpl-navn { flex: 1 1 150px; min-width: 0; }
.tpl-rad .tpl-ekstra { flex: 2 1 200px; min-width: 0; }
.tpl-rad input[type=color] { width: 40px; height: 40px; padding: 2px; border: 1px solid var(--line); border-radius: var(--r-md); background: var(--surface); }
.tpl-rad input[type=time] { flex: 0 1 auto; }
.tpl-rad select { flex: 0 1 auto; max-width: 100%; }
.tpl-dialog .tpl-torad { display: flex; gap: 10px; flex-wrap: wrap; }
.tpl-dialog .tpl-torad .field { flex: 1 1 160px; }

/* Skolen (velgeren og «Skole: … · Bytt skole» i dialogene som går gjennom
   den – katalogen, delingen og årshjulet). Lista er radioknapper i
   `.checkline.choice`, som ellers i dialogene. */
.skole-liste { display: flex; flex-direction: column; gap: 4px; }
.skole-liste .checkline input[type=radio] { margin-top: 3px; }
.skole-linje { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin: 0 0 8px; }
.skole-linje b { color: var(--ink); }
