/*
 * course-v2.css
 *
 * Kursets eneste stilark.
 *
 * This stylesheet assumes the following <link> tags are present in <head>
 * (do not inline them here):
 *
 *   <!-- Fonts: Fraunces, Plus Jakarta Sans, JetBrains Mono -->
 *   <link rel="preconnect" href="https://fonts.googleapis.com">
 *   <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
 *   <link href="https://fonts.googleapis.com/css2?family=Fraunces:ital,opsz,wght@0,9..144,300..900;1,9..144,300..900&family=Plus+Jakarta+Sans:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
 *
 *   <!-- KaTeX -->
 *   <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/katex.min.css">
 *
 *   <!-- Highlight.js (for static code blocks only) -->
 *   <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.9.0/build/styles/github-dark.min.css">
 */

/* ═══════════════════════════════════════════════════════════════════════
   RESET & CSS CUSTOM PROPERTIES
   ═══════════════════════════════════════════════════════════════════════ */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html {
  scroll-behavior: smooth;
  /* Base type scale. 125% of the browser default (16px) = 20px.
     All rem-based sizing in this file scales with it. */
  font-size: 125%;
  /* Classic scrollbars (mus tilkoblet) tegner ellers en lys grå stripe */
  scrollbar-color: var(--border) var(--bg);
}

:root {
  --bg:              #0d1117;
  --surface:         #161b22;
  --surface-hover:   #1c2128;
  --surface-deep:    #0a0e13;
  --surface-output:  #060a0e;
  --surface-grading: #0d0a14;
  --border:          #30363d;
  --border-muted:    #21262d;
  --text:            #e6edf3;
  --text-2:          #8b949e;
  --text-3:          #484f58;

  --amber:         #d4a017;
  --amber-dim:     rgba(212,160,23,.13);
  --amber-ring:    rgba(212,160,23,.28);
  --blue:          #4493f8;
  --blue-dim:      rgba(68,147,248,.12);
  --blue-ring:     rgba(68,147,248,.28);
  --green:         #3fb950;
  --green-dim:     rgba(63,185,80,.12);
  --green-ring:    rgba(63,185,80,.28);
  --purple:        #a371f7;
  --purple-dim:    rgba(163,113,247,.12);
  --purple-ring:   rgba(163,113,247,.28);
  --purple-wash:   rgba(163,113,247,.06);
  --purple-hover:  rgba(163,113,247,.2);
  --red:           #f85149;
  --red-dim:       rgba(248,81,73,.13);
  --red-ring:      rgba(248,81,73,.28);

  --on-accent: #000;
  --on-green:  #06240f;

  /* Halvgjennomsiktig kortflate på oversikten, ligger over dyphavs-lerretet */
  --surface-glass:  rgba(22,27,34,.62);

  --topbar-bg:      rgba(13,17,23,.93);
  --overlay-bg:     rgba(13,17,23,.82);
  --line-highlight: rgba(255,255,255,.035);
  --example-tint:   rgba(255,255,255,.022);

  --code-keyword:  #ff7b72;
  --code-string:   #a5d6ff;
  --code-number:   #79c0ff;
  --code-def:      #d2a8ff;
  --code-builtin:  #ffa657;
  --code-inline:   #f0883e;
  --code-comment:  #8b949e;
  --code-variable: #e6edf3;

  --font-d: 'Fraunces', Georgia, serif;
  --font-b: 'Plus Jakarta Sans', system-ui, sans-serif;
  --font-m: 'JetBrains Mono', 'Fira Code', monospace;
}

/* ═══════════════════════════════════════════════════════════════════════
   BASE / BODY / TYPOGRAPHY
   ═══════════════════════════════════════════════════════════════════════ */
body {
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-b);
  line-height: 1.72;
}

/* ── BODY TEXT ─────────────────────────────────────────── */

code:not(pre code) {
  font-family: var(--font-m);
  font-size: .875em;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 1px 6px;
  color: var(--code-inline);
}

/* ═══════════════════════════════════════════════════════════════════════
   LAYOUT SHELL (topbar, sidebar nav, main content column)
   ═══════════════════════════════════════════════════════════════════════ */

/* ── TOP BAR ───────────────────────────────────────────── */
.topbar {
  position: sticky;
  top: 0;
  z-index: 200;
  height: 64px;
  background: var(--topbar-bg);
  backdrop-filter: blur(14px);
  border-bottom: 1px solid var(--border-muted);
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 28px;
  gap: 16px;
}

.topbar-brand {
  display: flex;
  align-items: center;
  gap: 10px;
  text-decoration: none;
  color: var(--text);
  font-family: var(--font-d);
  font-size: 1rem;
  font-weight: 700;
  letter-spacing: -.01em;
}

.topbar-tag {
  font-family: var(--font-b);
  font-size: .65rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .09em;
  padding: 2px 8px;
  border-radius: 20px;
  background: var(--amber-dim);
  color: var(--amber);
  border: 1px solid var(--amber-ring);
}

.topbar-right {
  display: flex;
  align-items: center;
  gap: 16px;
}

/* ── LAYOUT ────────────────────────────────────────────── */
.layout {
  display: grid;
  grid-template-columns: 232px 1fr;
  min-height: calc(100vh - 64px);
}

/* ── SIDEBAR ───────────────────────────────────────────── */
.sidebar {
  position: sticky;
  top: 64px;
  height: calc(100vh - 64px);
  overflow-y: auto;
  padding: 36px 16px;
  border-right: 1px solid var(--border-muted);
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.nav-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 7px 12px;
  border-radius: 8px;
  font-size: .85rem;
  font-weight: 500;
  color: var(--text-2);
  text-decoration: none;
  cursor: pointer;
  transition: color .15s, background .15s, border-color .15s;
  border: none;
  border-left: 3px solid transparent;
  background: none;
  width: 100%;
  text-align: left;
}
.nav-item:hover { color: var(--text); background: var(--surface-hover); }

/* Active state: colored left border matching topic */
.nav-item.active { color: var(--text); background: var(--surface); }
.nav-item[data-c="amber"].active  { border-left-color: var(--amber); color: var(--amber); }
.nav-item[data-c="blue"].active   { border-left-color: var(--blue);  color: var(--blue); }
.nav-item[data-c="green"].active  { border-left-color: var(--green); color: var(--green); }
.nav-item[data-c="purple"].active { border-left-color: var(--purple); color: var(--purple); }

.nav-dot {
  width: 8px; height: 8px;
  border-radius: 50%;
  flex-shrink: 0;
  background: var(--text-3);
  transition: background .2s, transform .2s;
}
.nav-item[data-c="amber"]  .nav-dot { background: var(--amber); }
.nav-item[data-c="blue"]   .nav-dot { background: var(--blue); }
.nav-item[data-c="green"]  .nav-dot { background: var(--green); }
.nav-item[data-c="purple"] .nav-dot { background: var(--purple); }
.nav-item.active .nav-dot { transform: scale(1.3); }

.nav-sub {
  margin-left: 18px;
  display: flex;
  flex-direction: column;
  gap: 1px;
  overflow: hidden;
  max-height: 0;
  transition: max-height .3s ease;
}
.nav-sub.open { max-height: 40em; }

.nav-sub-item {
  padding: 4px 12px;
  font-size: .78rem;
  color: var(--text-3);
  border-radius: 6px;
  text-decoration: none;
  transition: color .15s;
}
.nav-sub-item:hover { color: var(--text-2); }

/* ── MAIN AREA ─────────────────────────────────────────── */
.main { min-width: 0; }

/* ═══════════════════════════════════════════════════════════════════════
   TOPIC SECTIONS
   ═══════════════════════════════════════════════════════════════════════ */
.topic {
  padding: 60px 52px 48px;
  border-bottom: 1px solid var(--border-muted);
  position: relative;
  overflow: hidden;
}

.topic-bg-num {
  position: absolute;
  top: 16px; right: 40px;
  font-family: var(--font-d);
  font-size: 9rem;
  font-weight: 900;
  line-height: 1;
  opacity: .04;
  pointer-events: none;
  user-select: none;
}

.topic-eyebrow {
  font-size: .68rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .12em;
  margin-bottom: 8px;
}

.topic-title {
  font-family: var(--font-d);
  font-size: 2.4rem;
  font-weight: 800;
  line-height: 1.08;
  letter-spacing: -.02em;
  margin-bottom: 32px;
}

.topic[data-c="amber"] .topic-eyebrow,
.topic[data-c="amber"] .topic-title,
.topic[data-c="amber"] .topic-bg-num { color: var(--amber); }

.topic[data-c="blue"] .topic-eyebrow,
.topic[data-c="blue"] .topic-title,
.topic[data-c="blue"] .topic-bg-num { color: var(--blue); }

.topic[data-c="green"] .topic-eyebrow,
.topic[data-c="green"] .topic-title,
.topic[data-c="green"] .topic-bg-num { color: var(--green); }

.topic[data-c="purple"] .topic-eyebrow,
.topic[data-c="purple"] .topic-title,
.topic[data-c="purple"] .topic-bg-num { color: var(--purple); }

/* ═══════════════════════════════════════════════════════════════════════
   PILL DIVIDERS
   ═══════════════════════════════════════════════════════════════════════ */
.pill-divider {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 28px 0 20px;
}
.pill-divider::before, .pill-divider::after {
  content: '';
  flex: 1;
  height: 1px;
  background: var(--border-muted);
}

.pill-label {
  font-size: .95rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .1em;
  padding: 3px 10px;
  border-radius: 20px;
  white-space: nowrap;
}
.pill-intro     { background: var(--amber-dim);   color: var(--amber);  border: 1px solid var(--amber-ring); }
.pill-teori     { background: var(--surface);      color: var(--text-3); border: 1px solid var(--border-muted); }
.pill-eksempel  { background: var(--surface);      color: var(--text-3); border: 1px solid var(--border-muted); }
.pill-prov-selv { background: var(--green-dim);    color: var(--green);  border: 1px solid var(--green-ring); }
.pill-utforsk   { background: var(--purple-dim);   color: var(--purple); border: 1px solid var(--purple-ring); }

/* ═══════════════════════════════════════════════════════════════════════
   CODE BLOCKS (static code, editor chrome, output panes, mac-style dots,
   main.py filename bar)
   ═══════════════════════════════════════════════════════════════════════ */

/* ── STATIC CODE BLOCK ─────────────────────────────────── */
/* JetBrains Mono binder `==` sammen til ett langt likhetstegn, `!=` til ≠ og
   `<=` til ≤. Pent i en IDE, men her skal eleven se nøyaktig de tegnene hen
   selv skal taste, og modul 8 handler om akkurat de tegnene. Ligaturene slås
   derfor av overalt koden vises. */
code, pre, .cm-editor, .output-area, .code-lang-tag, .editor-file {
  font-variant-ligatures: none;
  font-feature-settings: "liga" 0, "calt" 0;
}

.code-block {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 10px;
  overflow: hidden;
  margin: 16px 0;
}

/* Blokker som viser kode som ikke virker. Rød merkelapp, så eleven ikke
   kopierer den i god tro. */
.code-block-static .code-lang-tag { color: var(--red); }

.code-block-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 8px 16px;
  border-bottom: 1px solid var(--border);
  background: var(--surface-hover);
}

.code-lang-tag {
  font-family: var(--font-m);
  font-size: .68rem;
  color: var(--text-2);
  text-transform: uppercase;
  letter-spacing: .08em;
}

/* overflow-x her, ikke på .code-block: wrapperen har overflow:hidden for
   rundingen, så uten dette blir en lang kodelinje klippet uten scrollbar.
   width:max-content på <code> gjør at høyre padding overlever helt ut i
   scroll-enden i stedet for å kollapse. */
.code-block pre { border: none; border-radius: 0; margin: 0; background: transparent; overflow-x: auto; }
.code-block pre code {
  background: transparent !important;
  font-family: var(--font-m);
  font-size: .82rem;
  line-height: 1.65;
  display: block;
  width: max-content;
  min-width: 100%;
  padding: 18px 20px;
}

/* ── MATH BLOCK ────────────────────────────────────────── */
.math-block {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 22px;
  text-align: center;
  margin: 16px 0;
  overflow-x: auto;
}
.math-label {
  font-size: .7rem;
  color: var(--text-3);
  text-transform: uppercase;
  letter-spacing: .08em;
  margin-bottom: 12px;
}
.math-render { display: inline-block; }

/* ── STATIC CODE SYNTAX (highlight.js) ──────────────────────────────────
   The CDN's github-dark.min.css sets these colours from literals, so a theme
   could not reach them. Repeating the selectors here against the --code-*
   tokens hands them to the cascade instead. No !important needed: same
   specificity, and this file loads after the CDN sheet in every page's <head>.
   Selector groups mirror github-dark.min.css v11.11.1. */
.hljs { color: var(--code-variable); }
.hljs-doctag, .hljs-keyword, .hljs-meta .hljs-keyword, .hljs-template-tag,
.hljs-template-variable, .hljs-type, .hljs-variable.language_ { color: var(--code-keyword); }
.hljs-title, .hljs-title.class_, .hljs-title.class_.inherited__,
.hljs-title.function_ { color: var(--code-def); }
.hljs-attr, .hljs-attribute, .hljs-literal, .hljs-meta, .hljs-number,
.hljs-operator, .hljs-selector-attr, .hljs-selector-class, .hljs-selector-id,
.hljs-variable { color: var(--code-number); }
.hljs-meta .hljs-string, .hljs-regexp, .hljs-string { color: var(--code-string); }
.hljs-built_in, .hljs-symbol { color: var(--code-builtin); }
.hljs-code, .hljs-comment, .hljs-formula { color: var(--code-comment); }

/* ── EDITOR WRAPPER ────────────────────────────────────── */
.editor-wrap {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 10px;
  overflow: hidden;
  margin-top: 8px;
}

.editor-topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 8px 14px;
  background: var(--surface-hover);
  border-bottom: 1px solid var(--border);
}

.editor-dots { display: flex; gap: 5px; }
.editor-dot { width: 10px; height: 10px; border-radius: 50%; }
.editor-dot:nth-child(1) { background: var(--red); }
.editor-dot:nth-child(2) { background: var(--amber); }
.editor-dot:nth-child(3) { background: var(--green); }
/* Den røde prikken er en knapp: stopper kjøring og nullstiller koden. */
button.editor-dot-reset { padding: 0; border: 0; cursor: pointer; transition: transform .12s, box-shadow .12s; }
button.editor-dot-reset:hover,
button.editor-dot-reset:focus-visible { transform: scale(1.25); box-shadow: 0 0 0 2px color-mix(in srgb, var(--red) 45%, transparent); outline: none; }

/* Kjør-knappen mens koden kjører. */
.btn-stopp.btn-primary { background: var(--red); border-color: var(--red); color: #fff; }
.btn-stopp.btn-primary:hover { filter: brightness(1.1); }

/* Infoboks (første while-løkke): samme panel som feiringen, roligere innhold. */
.info-panel { text-align: left; max-width: 460px; }
.info-panel .celebration-headline { font-size: 1.3rem; margin-bottom: 10px; }
.info-panel p { color: var(--text); line-height: 1.6; margin: 0 0 10px; }
.info-panel ul { margin: 0 0 18px 1.2em; padding: 0; color: var(--text); line-height: 1.6; }
.info-panel li { margin-bottom: 6px; }

/* Banner øverst når serveren ikke svarer ved lasting. */
.server-banner {
  background: color-mix(in srgb, var(--red) 18%, var(--surface));
  border-bottom: 1px solid var(--red);
  color: var(--text);
  font-size: .88rem;
  padding: 8px 16px;
  text-align: center;
}
.editor-file { font-family: var(--font-m); font-size: .7rem; color: var(--text-3); }

.editor-footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 8px 14px;
  border-top: 1px solid var(--border);
  background: var(--surface-hover);
  gap: 8px;
}

.editor-footer-right { display: flex; align-items: center; gap: 8px; }

.btn-check {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 7px 16px;
  background: var(--purple-dim);
  color: var(--purple);
  font-family: var(--font-b);
  font-size: .8rem;
  font-weight: 600;
  border: 1px solid var(--purple-ring);
  border-radius: 6px;
  cursor: pointer;
  transition: opacity .15s, background .15s;
}
.btn-check:hover:not(:disabled) { background: var(--purple-hover); }
.btn-check:disabled { opacity: .35; cursor: not-allowed; }

.pyodide-status {
  font-size: .73rem;
  color: var(--text-3);
  font-family: var(--font-m);
}
.pyodide-status.ready { color: var(--green); }
.pyodide-status.error-state { color: var(--red); }

.output-area {
  display: none;
  background: var(--surface-output);
  border-top: 1px solid var(--border);
  padding: 14px 20px;
  font-family: var(--font-m);
  font-size: .78rem;
  line-height: 1.65;
  white-space: pre-wrap;
  color: var(--text);
  max-height: 220px;
  overflow-y: auto;
}
.output-area.show { display: block; }
.output-area.is-error { color: var(--red); }

/* ═══════════════════════════════════════════════════════════════════════
   TABS (.ex-tabs, .ex-tab, .ex-panel)
   ═══════════════════════════════════════════════════════════════════════ */
/* Segmentkontroll, ikke understreket tekst. Understrekvarianten leste som en
   overskriftslinje: fire grå ord på rad ga ingen beskjed om at det var knapper,
   eller om hvor mange faner som fantes. Nå rammer boksen inn valget, og aktiv
   fane bruker samme dim+ring-språk som pillene ellers i designet. */
.ex-tabs {
  --tab-accent:      var(--green);
  --tab-accent-dim:  var(--green-dim);
  --tab-accent-ring: var(--green-ring);

  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  width: fit-content;
  max-width: 100%;
  padding: 4px;
  margin-bottom: 20px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 12px;
}
.ex-tab {
  display: inline-flex;
  align-items: center;
  gap: 0;
  padding: 7px 15px;
  font-family: var(--font-b);
  font-size: .82rem;
  font-weight: 600;
  color: var(--text-2);
  background: none;
  border: 1px solid transparent;
  border-radius: 8px;
  cursor: pointer;
  transition: color .15s, background .15s, border-color .15s;
}
.ex-tab:hover { color: var(--text); background: var(--surface-hover); }
.ex-tab:focus-visible { outline: 2px solid var(--tab-accent); outline-offset: 2px; }
.ex-tab.active {
  color: var(--tab-accent);
  background: var(--tab-accent-dim);
  border-color: var(--tab-accent-ring);
}

/* Prikken sier «her er det mer å se», og forsvinner når fanen har vært åpen.
   Den er et ekte element, ikke ::before, og krymper til null bredde i stedet
   for bare å bli usynlig — ellers står den aktive fanens tekst igjen med
   13px skjev venstremarg. */
.ex-tab-dot {
  width: 6px;
  height: 6px;
  flex: none;
  margin-right: 7px;
  border-radius: 50%;
  background: var(--tab-accent);
  opacity: .6;
  transition: width .2s, margin-right .2s, opacity .15s;
}
.ex-tab.sett .ex-tab-dot { width: 0; margin-right: 0; opacity: 0; }

/* Nivåfanene i innleveringen ligger i det lilla panelet og skal følge det.
   De beholder segmentformen over: de står allerede i et kort, og trenger
   derfor ingen egen ramme slik modulfanene under gjør. */
.ex-tabs.asgn-levels {
  --tab-accent:      var(--purple);
  --tab-accent-dim:  var(--purple-dim);
  --tab-accent-ring: var(--purple-ring);
}

.ex-panel { display: none; }
.ex-panel.active { display: block; }

/* ── Modulfanene: rammen ──────────────────────────────────────────────────
   Uten ramme var det uklart hvor langt en fane rakk — cellene under fløt
   fritt i brødteksten. Nå er .course-tabs et kort: fanelinja er hodet, og
   den aktive fanen deler bakgrunn med kroppen og skjærer gjennom hodets
   underkant. Da er det arkfane-metaforen som forteller hva som hører sammen,
   ikke bare nærhet. */
.course-tabs {
  margin: 18px 0 22px;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 14px;
}
.course-tabs > .ex-tabs {
  width: auto;
  gap: 3px;
  padding: 7px 8px 0;
  margin-bottom: 0;
  background: var(--surface);
  border: none;
  border-bottom: 1px solid var(--border);
  border-radius: 13px 13px 0 0;
}
.course-tabs > .ex-tabs > .ex-tab {
  border-bottom: none;
  border-radius: 9px 9px 0 0;
  /* Trekker fanen 1px ned over hodets underkant, slik at den aktive fanens
     bakgrunn dekker streken og «åpner» ned i innholdet. */
  margin-bottom: -1px;
  padding-bottom: 8px;
}
.course-tabs > .ex-tabs > .ex-tab.active {
  color: var(--tab-accent);
  background: var(--bg);
  border-color: var(--border);
  /* Aksentkanten er innskygget, ikke en ekte border: en 2px topplinje ville
     gjort den aktive fanen 1px høyere enn de andre og flyttet teksten. */
  box-shadow: inset 0 2px 0 var(--tab-accent);
}
.course-tabs > .ex-panel.active { padding: 18px 20px 4px; }
/* Cellene har allerede rammen rundt seg nå, så gruppens egen kantlinje ble
   ramme-i-ramme. Tonen blir igjen, den er det som binder kode og output. */
.course-tabs > .ex-panel > .example-group {
  border-color: transparent;
  padding: 0;
  background: none;
}
.course-tabs > .ex-panel > .example-group > .code-block { margin: 0; }

/* ═══════════════════════════════════════════════════════════════════════
   HINT ACCORDION
   ═══════════════════════════════════════════════════════════════════════ */
.hint-accordion {
  margin-top: 12px;
  border: 1px solid var(--border);
  border-radius: 8px;
  overflow: hidden;
}
.hint-toggle {
  display: flex;
  align-items: center;
  gap: 6px;
  width: 100%;
  padding: 10px 14px;
  background: var(--surface);
  border: none;
  color: var(--text-2);
  font-family: var(--font-b);
  font-size: .8rem;
  font-weight: 600;
  cursor: pointer;
  transition: color .15s, background .15s;
}
.hint-toggle:hover { color: var(--text); background: var(--surface-hover); }
.hint-toggle .hint-arrow { transition: transform .2s; }
.hint-accordion.open .hint-toggle .hint-arrow { transform: rotate(90deg); }
.hint-body {
  display: none;
  padding: 12px 14px;
  font-size: .85rem;
  color: var(--text-2);
  line-height: 1.65;
  border-top: 1px solid var(--border);
  background: var(--bg);
}
.hint-accordion.open .hint-body { display: block; }

@keyframes spin { to { transform: rotate(360deg); } }

/* ═══════════════════════════════════════════════════════════════════════
   REVEAL/SCROLL ANIMATIONS & REMAINING UTILITIES
   ═══════════════════════════════════════════════════════════════════════ */

/* ── SCROLL FADE-IN ────────────────────────────────────── */
.reveal {
  opacity: 0;
  transform: translateY(18px);
  transition: opacity .55s ease, transform .55s ease;
}
.reveal.visible { opacity: 1; transform: none; }

/* ── MOBILE ────────────────────────────────────────────── */
@media (max-width: 820px) {
  .main { max-width: 100%; }
  .layout { grid-template-columns: 1fr; }
  .sidebar {
    position: static;
    height: auto;
    border-right: none;
    border-bottom: 1px solid var(--border-muted);
    flex-direction: row;
    flex-wrap: wrap;
    padding: 10px 20px;
    gap: 4px;
  }
  .sidebar-group-label { display: none; }
  .nav-sub { display: none; }
  .topic, .innlevering { padding: 40px 24px; }
  .topic-title, .innlevering-title { font-size: 1.9rem; }
  .topic-bg-num { display: none; }
  .grading-body { grid-template-columns: 1fr; }
  .grading-gauge-col { border-right: none; border-bottom: 1px solid var(--border-muted); padding-right: 0; padding-bottom: 16px; }
  .grading-right-col { padding-left: 0; padding-top: 16px; }
}

/* ═══════════════════════════════════════════════════════════════════════
   PRE-GENERATED EXAMPLE OUTPUT
   Static output panes for course examples. Values are produced and checked
   against real execution by scripts/verify_outputs.py.
   ═══════════════════════════════════════════════════════════════════════ */
.code-block-output { margin-top: -6px; }
.code-block-output .code-lang-tag { color: var(--green); }
.code-block-output pre {
  margin: 0;
  padding: 14px 16px;
  font-family: var(--font-m);
  font-size: .78rem;
  line-height: 1.6;
  color: var(--text-2);
  white-space: pre-wrap;
  overflow-x: auto;
}

/* Top-bar nav links (course pages only) */
.topbar-nav { display: flex; gap: 18px; margin-left: 20px; }
.topbar-nav a {
  color: var(--text-2);
  text-decoration: none;
  font-size: .85rem;
  transition: color .15s;
}
.topbar-nav a:hover { color: var(--text); }

/* Locked modules in the sidebar */
.nav-item.locked { opacity: .35; cursor: not-allowed; }

/* ═══════════════════════════════════════════════════════════════════════
   INLINE CODE EDITOR (CodeMirror 6) + INNLEVERINGER ASSIGNMENT PANELS
   ─────────────────────────────────────────────────────────────────────
   Class names below match the DOM built by js/components/courseViewer.js,
   js/components/assignmentPanel.js and js/components/gradingResult.js.
   ═══════════════════════════════════════════════════════════════════════ */

/* .output-area above is display:none until .show is set. The components
   write straight into .inline-output without toggling .show, so this
   variant is always visible. */
.output-area.inline-output {
  display: block;
  width: 100%;
  border: 1px solid var(--border);
  border-radius: 10px;
}
.output-area.inline-output:empty::before {
  content: 'Output vises her når du trykker Kjør.';
  color: var(--text-2);
  font-style: italic;
}
.output-area.error,
.output-area .error {
  color: var(--red);
}

/* ── BUTTONS ─────────────────────────────────────────────────────────── */
.btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 7px 16px;
  font-family: var(--font-b);
  font-size: .8rem;
  font-weight: 600;
  border: 1px solid transparent;
  border-radius: 6px;
  cursor: pointer;
  transition: opacity .15s, background .15s, border-color .15s, transform .1s;
}
.btn:disabled { opacity: .38; cursor: not-allowed; }
.btn-sm { padding: 9px 18px; font-size: .8rem; }

.sjekk-hint {
  font-size: .78rem;
  color: var(--text-2);
}

/* "Kjør" */
.btn-primary {
  background: var(--amber);
  color: var(--on-accent);
}
.btn-primary:hover:not(:disabled) { opacity: .88; transform: translateY(-1px); }

/* "Sjekk" — same recipe as .btn-check above (kept untouched; unused by
   the actual JS, which emits .btn-accent for this action instead) */
.btn-accent {
  background: var(--purple-dim);
  color: var(--purple);
  border-color: var(--purple-ring);
}
.btn-accent:hover:not(:disabled) { background: var(--purple-hover); }

.btn-secondary {
  background: var(--surface-hover);
  color: var(--text-2);
  border-color: var(--border);
}
.btn-secondary:hover:not(:disabled) { color: var(--text); border-color: var(--text-3); }

.btn-success {
  background: var(--green);
  color: var(--on-green);
}
.btn-success:hover:not(:disabled) { opacity: .88; transform: translateY(-1px); }

/* ── EDITOR SHELLS ───────────────────────────────────────────────────────
   courseViewer.js "Prøv selv" editor: .code-standalone-editor wraps
   [.inline-editor-container, button.btn, .output-area] as flat siblings.
   assignmentPanel.js "Innlevering" editor: .assignment-col-right wraps
   [.assignment-editor-container, Kjør-button, .output-area, Sjekk-button].
   Neither has the dots/filename header chrome, so the panel look comes from the editor mount + output pane, with plain pill buttons
   in between. */
.code-standalone-editor,
.assignment-col-right {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 10px;
  margin: 16px 0;
}

/* Editor shell chrome (mac-dots + main.py + footer) around the CM6 mount.
   The nested containers drop their own frame; the shell provides it. */
.editor-wrap { width: 100%; margin-top: 0; }
.editor-wrap .inline-editor-container,
.editor-wrap .assignment-editor-container {
  border: none;
  border-radius: 0;
}
.editor-wrap .output-area.inline-output {
  border: none;
  border-top: 1px solid var(--border);
  border-radius: 0;
}

.inline-editor-container,
.assignment-editor-container {
  width: 100%;
  background: var(--surface-deep);
  border: 1px solid var(--border);
  border-radius: 10px;
  overflow: hidden;
}
.inline-editor-container { min-height: 140px; }
.assignment-editor-container { min-height: 180px; }

/* ── CODEMIRROR 6 CHROME ─────────────────────────────────────────────── */
.inline-editor-container .cm-editor,
.assignment-editor-container .cm-editor {
  min-height: inherit;
  background: transparent;
  color: var(--text);
}
.inline-editor-container .cm-editor.cm-focused,
.assignment-editor-container .cm-editor.cm-focused {
  outline: none;
}
.inline-editor-container .cm-scroller,
.assignment-editor-container .cm-scroller {
  font-family: var(--font-m);
}
.inline-editor-container .cm-content,
.assignment-editor-container .cm-content {
  padding: 14px 16px;
  caret-color: var(--amber);
}
.inline-editor-container .cm-gutters,
.assignment-editor-container .cm-gutters {
  background: var(--surface);
  border-right: 1px solid var(--border);
  color: var(--text-3);
}
.inline-editor-container .cm-activeLineGutter,
.assignment-editor-container .cm-activeLineGutter {
  background: var(--surface-hover);
  color: var(--text-2);
}
.inline-editor-container .cm-activeLine,
.assignment-editor-container .cm-activeLine {
  background: var(--line-highlight);
}
.inline-editor-container .cm-selectionBackground,
.assignment-editor-container .cm-selectionBackground {
  background: var(--blue-ring) !important;
}
.inline-editor-container .cm-cursor,
.assignment-editor-container .cm-cursor {
  border-left-color: var(--amber);
}

/* ── ASSIGNMENTS SECTION ("Innleveringer") ──────────────────────────────
   Appended by assignmentPanel.js directly after the markdown's .topic
   sections — not wrapped in one — so it needs its own horizontal padding
   to line up with the topic content above it. */
/* Innleveringene bryter ut av .main sin 70 %-kolonne og bruker 80 % av
   vinduet: to kolonner med krav og editor side om side trenger mer plass
   enn brødteksten. Et tydelig skille markerer overgangen fra teori. */
.assignments-section {
  width: 80vw;
  position: relative;
  left: 50%;
  margin-left: -40vw;
  padding: 60px 24px 80px;
  border-top: 1px solid var(--border);
  margin-top: 48px;
}
.assignments-section > h2 {
  font-family: var(--font-d);
  font-size: 2rem;
  font-weight: 800;
  letter-spacing: -.02em;
  color: var(--purple);
  margin-bottom: 24px;
}

.assignment-panel {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 28px;
  margin-bottom: 24px;
}
.assignment-panel:last-child { margin-bottom: 0; }

.assignment-header {
  font-family: var(--font-d);
  font-size: 1.35rem;
  font-weight: 700;
  color: var(--purple);
  margin-bottom: 12px;
}

.assignment-description p { color: var(--text); line-height: 1.7; }
.assignment-task ul { list-style: none; margin: .5em 0 0; }
/* Luft mellom avsnitt. Oppgavetekstene hadde lenge ett avsnitt hver, så
   dette manglet uten at det syntes; med flere avsnitt rant de sammen. */
.assignment-task p + p,
.assignment-task ul + p { margin-top: .8em; }
.assignment-task li {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 4px 0;
  color: var(--text);
  line-height: 1.6;
  max-width: 36rem;
}
.assignment-task li::before {
  content: '';
  flex-shrink: 0;
  width: 6px;
  height: 6px;
  margin-top: .62em;
  border-radius: 50%;
  background: var(--purple);
}
.assignment-figure {
  margin: 0 0 14px;
  max-width: 340px;
}
.assignment-image {
  display: block;
  width: 100%;
  height: auto;
  border: 1px solid var(--border);
  border-radius: 8px;
}
.assignment-figure figcaption {
  margin-top: 6px;
  font-size: .76rem;
  color: var(--text-3);
  line-height: 1.4;
}

/* Pseudokode i oppgaveteksten. Monospace for innrykkets skyld, men bevisst
   uten syntaksfarger: dette er ikke Python, og skal ikke se kopierbart ut. */
.assignment-pseudo {
  margin: 12px 0;
  padding: 12px 14px;
  max-width: 36rem;
  overflow-x: auto;
  border-left: 2px solid var(--border);
  background: var(--surface);
  border-radius: 0 8px 8px 0;
  font-family: var(--font-m);
  font-size: .8rem;
  line-height: 1.6;
  color: var(--text-2);
  white-space: pre;
}

/* Hjelpekode i innleveringen: lukket til eleven trenger den, og markering er
   slått av så den leses i stedet for å limes inn. Copy-hendelsen stoppes i
   assignmentPanel.js — user-select alene stopper ikke Cmd+A over hele siden. */
.assignment-help {
  margin-top: 14px;
  max-width: 36rem;
  border: 1px dashed var(--border);
  border-radius: 10px;
  background: var(--surface);
}
.assignment-help > summary {
  padding: 9px 14px;
  cursor: pointer;
  font-family: var(--font-b);
  font-size: .84rem;
  color: var(--text-2);
  list-style: none;
}
.assignment-help > summary::-webkit-details-marker { display: none; }
.assignment-help > summary::before {
  content: '›';
  display: inline-block;
  width: 1em;
  color: var(--purple);
  transition: transform .15s;
}
.assignment-help[open] > summary::before { transform: rotate(90deg); }
.assignment-help > summary:hover { color: var(--text); }
.assignment-help .code-block {
  margin: 0 10px 10px;
  user-select: none;
  -webkit-user-select: none;
}

.assignment-columns {
  display: grid;
  grid-template-columns: 1fr 1.3fr;
  gap: 28px;
  align-items: start;
  margin-top: 20px;
}

/* Krav / Bør ha — rendered as two plain <ul>s; the KRAV / BØR HA pill is
   added via ::before since there is no per-item type markup to hook,
   distinguishing the lists by their DOM order instead. */
.assignment-col-left ul { list-style: none; }
.assignment-col-left li {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  padding: 6px 0;
  font-size: .86rem;
  line-height: 1.5;
  color: var(--text-2);
  border-bottom: 1px solid var(--border-muted);
}
.assignment-col-left li:last-child { border-bottom: none; }
.assignment-col-left li::before {
  flex-shrink: 0;
  margin-top: 1px;
  font-size: .6rem;
  font-weight: 700;
  letter-spacing: .06em;
  padding: 2px 6px;
  border-radius: 4px;
}
.assignment-col-left ul:first-of-type li::before {
  content: 'KRAV';
  background: var(--amber-dim);
  color: var(--amber);
  border: 1px solid var(--amber-ring);
}
.assignment-col-left ul:nth-of-type(2) li::before {
  content: 'BØR HA';
  background: var(--blue-dim);
  color: var(--blue);
  border: 1px solid var(--blue-ring);
}

/* ── AI GRADING RESULT (js/components/gradingResult.js) ─────────────────
   Its own DOM: .grading-result > .grading-bar-section (score bar with a
   90%-threshold marker, auto-plays its reveal on render) + .grading-summary
   (highlighted comment) + .grading-cards (three flip-cards: korrekt svar /
   format / kodestil). */
.assignment-grading-result:empty { display: none; }
.assignment-grading-result:not(:empty) {
  margin-top: 20px;
  padding-top: 20px;
  border-top: 1px solid var(--border);
}

.grading-bar-section { display: flex; flex-direction: column; gap: 8px; }
.grading-bar-readout {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
}
.grading-percent { font-family: var(--font-d); font-size: 2rem; font-weight: 700; }
.grading-tier-label { font-family: var(--font-b); font-size: .85rem; color: var(--text-2); }

.grading-bar-track {
  position: relative;
  height: 32px;
  border-radius: 999px;
  background: var(--surface-hover);
  border: 1px solid var(--border-muted);
}
.grading-bar-fill {
  position: absolute;
  top: 0; left: 0; bottom: 0;
  width: 0%;
  border-radius: 999px;
  transition: background-color .2s ease;
}
.grading-bar-threshold {
  position: absolute;
  left: 90%;
  top: -4px; bottom: -4px;
  border-left: 2px dashed var(--purple);
}
.grading-bar-fill.tier-red    { background: var(--red); }
.grading-bar-fill.tier-amber  { background: var(--amber); }
.grading-bar-fill.tier-blue   { background: var(--blue); }
.grading-bar-fill.tier-green  { background: var(--green); }
.grading-bar-fill.tier-purple { background: var(--purple); }
.grading-percent.tier-red    { color: var(--red); }
.grading-percent.tier-amber  { color: var(--amber); }
.grading-percent.tier-blue   { color: var(--blue); }
.grading-percent.tier-green  { color: var(--green); }
.grading-percent.tier-purple { color: var(--purple); }

@keyframes gradingThresholdPulse {
  0%, 100% { box-shadow: 0 0 0 0 var(--purple-ring); }
  50%      { box-shadow: 0 0 0 6px var(--purple-ring); }
}
.grading-bar-track.threshold-hit { animation: gradingThresholdPulse .7s ease; }

.grading-summary {
  font-size: .88rem;
  color: var(--text);
  line-height: 1.65;
  padding: 12px 14px;
  background: var(--purple-wash);
  border-left: 3px solid var(--purple);
  border-radius: 0 6px 6px 0;
  margin-top: 16px;
}

/* Bør ha-lista under oppsummeringen: ett punkt per linje, huket av eller
   ikke. Trekket står i overskriften bare når noe mangler. */
.grading-borha {
  margin-top: 12px;
  font-size: .85rem;
  color: var(--text-2);
}
.grading-borha-head { font-weight: 600; color: var(--text); margin-bottom: 4px; }
.grading-borha ul { list-style: none; margin: 0; padding: 0; }
.grading-borha li { display: flex; gap: 8px; align-items: baseline; line-height: 1.5; }
.grading-borha li::before { content: '✓'; color: var(--green); font-weight: 700; flex: none; }
.grading-borha li[data-oppfylt="false"]::before { content: '✗'; color: var(--red); }
.grading-borha li[data-oppfylt="false"] { color: var(--text); }

.grading-cards {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 16px;
  margin-top: 20px;
}
/* Two wide cards beat three cramped ones once the column gets narrow */
@media (max-width: 1150px) {
  .grading-cards { grid-template-columns: repeat(2, 1fr); }
}
.flip-card {
  position: relative;
  /* Room for two or three lines of feedback plus a short code suggestion.
     The faces are absolutely positioned for the 3D flip, so this has to be a
     fixed height rather than growing with content; the back scrolls if a
     model answer runs long. */
  height: 300px;
  perspective: 1000px;
  cursor: pointer;
}
.flip-card:focus-visible { outline: 2px solid var(--purple-ring); outline-offset: 3px; }
.flip-card-inner {
  position: relative;
  width: 100%;
  height: 100%;
  transition: transform .5s;
  transform-style: preserve-3d;
}
.flip-card.flipped .flip-card-inner { transform: rotateY(180deg); }
.flip-card-face {
  position: absolute;
  inset: 0;
  backface-visibility: hidden;
  border: 1px solid var(--border-muted);
  border-radius: 10px;
  background: var(--bg);
  padding: 14px 16px;
  display: flex;
  flex-direction: column;
}
.flip-card-front { align-items: center; justify-content: center; gap: 10px; text-align: center; }
.flip-card-back { transform: rotateY(180deg); overflow-y: auto; gap: 8px; }
/* The back is already the detail view; the "flip back" hint just eats the room
   the feedback needs. The card stays clickable. */
.flip-card-back .flip-card-hint { display: none; }
.flip-card-label {
  font-size: .74rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--text-3);
}
.flip-card-stars { display: flex; gap: 4px; font-size: 1.3rem; }
.fc-star {
  color: var(--text-3);
  opacity: 0;
  transform: scale(.4);
  transition: opacity .25s, transform .25s;
}
.fc-star.revealed { opacity: 1; transform: scale(1); }
.fc-star[data-filled="true"] { color: var(--amber); }
.flip-card-hint { font-size: .68rem; color: var(--text-3); }
.flip-card-feedback { font-size: .82rem; color: var(--text-2); line-height: 1.5; }
.flip-card-improve strong { display: block; font-size: .72rem; color: var(--purple); margin-bottom: 4px; }
.flip-card-improve pre {
  background: var(--surface);
  border-radius: 6px;
  padding: 8px 10px;
  font-size: .74rem;
  overflow-x: auto;
  /* Wrap rather than run off the card: the box is narrow and the model
     sometimes returns a line longer than it. */
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}
.flip-card-feedback code {
  font-family: var(--font-m);
  font-size: .92em;
  overflow-wrap: anywhere;
}

.grading-loading {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 12px 0;
  color: var(--text-2);
  font-family: var(--font-m);
  font-size: .82rem;
}
.grading-loading::before {
  content: '';
  width: 10px; height: 10px;
  flex-shrink: 0;
  border: 2px solid var(--purple-ring);
  border-top-color: var(--purple);
  border-radius: 50%;
  animation: spin .7s linear infinite; /* @keyframes spin defined above */
}
.grading-error {
  padding: 12px 0;
  color: var(--red);
  font-size: .85rem;
}

/* ── REFLECTION + SEND INN (js/components/moduleDelivery.js) ────────────
   One reflection question + "Lever inn" per module, shown once every
   assignment scores >= 90, appended below the assignment panels. */
.module-delivery:empty { display: none; }
.module-delivery-form {
  margin-top: 20px;
  padding-top: 20px;
  border-top: 1px solid var(--border);
}
.module-delivery-question {
  font-size: .95rem;
  font-weight: 600;
  color: var(--text);
  margin-bottom: 12px;
}
.module-delivery-textarea {
  width: 100%;
  padding: 10px 12px;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 8px;
  color: var(--text);
  font-family: var(--font-b);
  font-size: .88rem;
  line-height: 1.5;
  resize: vertical;
}
.module-delivery-textarea:focus {
  outline: none;
  border-color: var(--purple-ring);
}
.module-delivery-actions { margin-top: 10px; }
.module-delivery-confirm {
  margin-top: 20px;
  padding: 14px 16px;
  border-radius: 8px;
  background: var(--green-dim);
  border: 1px solid var(--green-ring);
  color: var(--green);
  font-weight: 600;
  font-size: .9rem;
}

/* ── COMPLETION CELEBRATION (js/components/moduleDelivery.js) ───────────
   Full-screen overlay shown right after a successful "Lever inn". Reuses
   .module-card/.module-card-badge markup from the menu (course.html) so
   the two module cards read identically to the real overview grid. */
.celebration-overlay {
  position: fixed;
  inset: 0;
  z-index: 500;
  background: var(--overlay-bg);
  backdrop-filter: blur(4px);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  animation: celebrationFade .2s ease;
}
@keyframes celebrationFade { from { opacity: 0; } to { opacity: 1; } }
.celebration-panel {
  position: relative;
  width: min(680px, 100%);
  max-height: 90vh;
  overflow-y: auto;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 14px;
  padding: 40px 32px 32px;
  text-align: center;
}
.celebration-close {
  position: absolute;
  top: 12px;
  right: 12px;
  width: 28px;
  height: 28px;
  border-radius: 6px;
  background: none;
  border: none;
  color: var(--text-2);
  font-size: 1rem;
  cursor: pointer;
}
.celebration-close:hover { color: var(--text); background: var(--surface-hover); }
.celebration-headline {
  font-family: var(--font-d);
  font-size: 1.8rem;
  font-weight: 700;
  color: var(--text);
}
.celebration-subtitle { margin-top: 6px; color: var(--text-2); font-size: .9rem; }
.celebration-burst {
  position: relative;
  height: 0;
}
.celebration-star {
  position: absolute;
  top: 0; left: 50%;
  color: var(--amber);
  font-size: 1.1rem;
  opacity: 0;
  animation: celebrationStar .8s ease-out forwards;
}
@keyframes celebrationStar {
  0%   { opacity: 1; transform: translate(-50%, 0) scale(.6); }
  100% { opacity: 0; transform: translate(calc(-50% + var(--dx)), var(--dy)) scale(1); }
}
.celebration-cards {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 16px;
  margin-top: 28px;
}
.celebration-cards .module-card { width: 230px; cursor: default; }
.celebration-arrow { color: var(--text-3); font-size: 1.4rem; }
.celebration-cards .celebration-next-card { cursor: pointer; }
@keyframes celebrationGlowAmber  { 0%,100% { box-shadow: 0 0 0 0 var(--amber-ring); }  50% { box-shadow: 0 0 14px 4px var(--amber-ring); } }
@keyframes celebrationGlowBlue   { 0%,100% { box-shadow: 0 0 0 0 var(--blue-ring); }   50% { box-shadow: 0 0 14px 4px var(--blue-ring); } }
@keyframes celebrationGlowGreen  { 0%,100% { box-shadow: 0 0 0 0 var(--green-ring); }  50% { box-shadow: 0 0 14px 4px var(--green-ring); } }
@keyframes celebrationGlowPurple { 0%,100% { box-shadow: 0 0 0 0 var(--purple-ring); } 50% { box-shadow: 0 0 14px 4px var(--purple-ring); } }
.celebration-next-card[data-c="amber"]  { animation: celebrationGlowAmber 2.2s ease-in-out infinite; }
.celebration-next-card[data-c="blue"]   { animation: celebrationGlowBlue 2.2s ease-in-out infinite; }
.celebration-next-card[data-c="green"]  { animation: celebrationGlowGreen 2.2s ease-in-out infinite; }
.celebration-next-card[data-c="purple"] { animation: celebrationGlowPurple 2.2s ease-in-out infinite; }
.celebration-hint { margin-top: 16px; font-size: .8rem; color: var(--text-3); }
.celebration-finished {
  margin-top: 24px;
  font-size: 1.05rem;
  color: var(--text);
  line-height: 1.5;
}
.celebration-menu-link {
  display: inline-block;
  margin-top: 20px;
  background: none;
  border: none;
  color: var(--text-2);
  font-family: var(--font-b);
  font-size: .85rem;
  cursor: pointer;
}
.celebration-menu-link:hover { color: var(--text); text-decoration: underline; }

/* Steg 2 i feiringen: temaet eleven nettopp låste opp. Knappene bytter tema
   med én gang, så belønningen vises i stedet for å beskrives. */
.tema-belonning {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 8px;
  margin-top: 20px;
}
.tema-belonning-valg {
  padding: 9px 18px;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--surface);
  color: var(--text);
  font-family: var(--font-b);
  font-size: .92rem;
  cursor: pointer;
}
.tema-belonning-valg:hover { background: var(--surface-hover); border-color: var(--text-3); }
.tema-belonning-valg[aria-pressed="true"] {
  border-color: var(--amber-ring);
  background: var(--amber-dim);
  color: var(--text);
}
.celebration-videre {
  display: block;
  margin: 16px auto 0;
  padding: 10px 26px;
  border: none;
  border-radius: 10px;
  background: var(--amber);
  color: var(--on-accent);
  font-family: var(--font-b);
  font-size: .92rem;
  font-weight: 600;
  cursor: pointer;
}
.celebration-videre:hover { filter: brightness(1.08); }

@media (max-width: 820px) {
  .assignments-section {
    width: auto;
    left: auto;
    margin-left: 0;
    padding: 40px 24px;
  }
  .assignment-columns { grid-template-columns: 1fr; }
  .grading-cards { grid-template-columns: 1fr; }
  /* «Formatering av tall» alene er bredere enn halve mobilskjermen, så to
     faner på rad går ikke opp. Da er en full stabel ryddigere enn brekte
     rader: hvert segment tar hele bredden. */
  .ex-tabs { width: 100%; }
  .ex-tab { flex: 1 1 auto; justify-content: flex-start; }
  /* Arkfane-metaforen faller når fanene står i stabel — bare den nederste
     ville ligget inntil innholdet. Da gir vi hodet segmenter i stedet, og
     lar rammen alene fortelle hva som hører til. */
  .course-tabs > .ex-tabs { padding: 6px; gap: 3px; }
  .course-tabs > .ex-tabs > .ex-tab {
    border-radius: 8px;
    border-bottom: 1px solid transparent;
    margin-bottom: 0;
  }
  .course-tabs > .ex-tabs > .ex-tab.active {
    background: var(--tab-accent-dim);
    border-color: var(--tab-accent-ring);
    box-shadow: none;
  }
  .course-tabs > .ex-panel.active { padding: 16px 14px 4px; }
  .celebration-cards { flex-direction: column; }
  .celebration-arrow { transform: rotate(90deg); }
}

@media (prefers-reduced-motion: reduce) {
  .celebration-overlay { animation: none; }
  .celebration-star { display: none; }
  .celebration-next-card[data-c] { animation: none; }
  .grading-bar-track.threshold-hit { animation: none; }
}

/* Version stamp in the top bar. Updated by hand on every course change. */
.build-stamp {
  font-family: var(--font-m);
  font-size: .62rem;
  color: var(--text-3);
  white-space: nowrap;
  margin-left: 18px;
}
@media (max-width: 900px) { .build-stamp { display: none; } }

/* Figures in a module (matematiske illustrasjoner og lignende) */
.topic-figure {
  display: block;
  width: 100%;
  max-width: 560px;
  height: auto;
  margin: 18px 0;
  border: 1px solid var(--border-muted);
  border-radius: 10px;
}

/* Module headings inside the theory section */
.topic h3 {
  font-family: var(--font-d);
  font-size: 1.25rem;
  font-weight: 600;
  color: var(--text);
  margin: 30px 0 10px;
}
.topic h3:first-of-type { margin-top: 14px; }

/* Body copy inside a module. Module Markdown renders straight into .topic.
   Prose gets a reading measure (~72 tegn). */
.topic p, .topic ul, .topic ol, .assignment-description p { max-width: 36rem; }

/* Kodeblokkene hadde ingen makslinje, så de vokste med vinduet mens brødteksten
   stod på 36rem. På en bred skjerm ble kodeblokken tre ganger så bred som
   teksten ved siden av, og så ut til å renne ut av siden. 44rem er bredere enn
   brødteksten (kode trenger det) og treffer omtrent der de allerede lå på en
   vanlig laptop, så smale skjermer endrer seg ikke. */
.topic > .code-block,
.topic > .example-group,
.topic > .code-block-output,
.topic > .math-block,
.topic > .course-tabs,
.topic > .hint-accordion,
/* Skillelinja er ikke innhold, men den rammer inn innholdet. Uten samme
   makslinje strakk den seg 74px lenger ut enn den bredeste kodeblokken. */
.topic > .pill-divider { max-width: 44rem; }
.topic p { margin-bottom: .7em; }
.topic p:last-child { margin-bottom: 0; }
.topic ul, .topic ol { margin: 0 0 .9em 1.3em; }
.topic li { margin-bottom: .3em; }
.topic li::marker { color: var(--text-3); }
.topic strong { color: var(--text); font-weight: 600; }

.topic table { border-collapse: collapse; margin: 4px 0 14px; }
.topic th, .topic td { text-align: left; padding: 4px 8px 4px 0; }
.topic th:last-child, .topic td:last-child { padding-left: 28px; }
.topic th { color: var(--text-2); font-weight: 600; border-bottom: 1px solid var(--border-muted); }

/* ═══════════════════════════════════════════════════════════════════════
   EXAMPLE GROUPS, HIDDEN OUTPUT, AUTO-HIDING SIDEBAR
   ═══════════════════════════════════════════════════════════════════════ */

/* One example = one code cell + its output, tinted so the pair reads as a unit */
.example-group {
  background: var(--example-tint);
  border: 1px solid var(--border-muted);
  border-radius: 12px;
  padding: 10px 12px;
  margin: 18px 0;
}
.example-group .code-block { margin: 0; }
.example-group .code-block-output { margin-top: 8px; }

/* Example answers stay blurred until the first hover (or tap), so there is a
   moment to think first; after that they stay visible. Module examples only:
   an assignment's sample output is part of the task, not a spoiler. */
.course-tabs .example-group .code-block-output pre {
  filter: blur(7px);
  transition: filter .18s ease;
  cursor: pointer;
  user-select: none;
}
.course-tabs .example-group .code-block-output.revealed pre {
  filter: none;
  cursor: auto;
  user-select: auto;
}
.course-tabs .example-group .code-block-output .code-block-header::after {
  content: 'hold musepekeren over for å se svaret';
  font-size: .72rem;
  color: var(--text-2);
  letter-spacing: .02em;
  transition: opacity .18s ease;
}
.course-tabs .example-group .code-block-output.revealed .code-block-header::after { opacity: 0; }

/* .hide-code groups (marked via <div class="course-reveal"> in the markdown)
   keep the code pane blurred too, and reveal code + output together. Krever
   KLIKK, ikke hover som output-avsløringen over: dette er «stopp og tenk»-
   varianten, og en musepeker som streifer forbi skal ikke røpe svaret. Ikke
   scoped til .course-tabs: .hide-code er en eksplisitt opt-in-markør. */
.example-group.hide-code .code-block pre {
  filter: blur(7px);
  transition: filter .18s ease;
  cursor: pointer;
  user-select: none;
}
.example-group.hide-code.revealed .code-block pre {
  filter: none;
  cursor: auto;
  user-select: auto;
}
.example-group.hide-code .code-block-header::after {
  content: 'tenk gjennom svaret, klikk for å se koden';
  font-size: .72rem;
  color: var(--text-2);
  letter-spacing: .02em;
  transition: opacity .18s ease;
}
.example-group.hide-code.revealed .code-block-header::after { opacity: 0; }
.example-group.hide-code .code-block-output pre { filter: blur(7px); cursor: pointer; user-select: none; }
.example-group.hide-code.revealed .code-block-output pre { filter: none; cursor: auto; user-select: auto; }
.example-group.hide-code .code-block-output .code-block-header::after { content: none; }

/* Sidebar slides away and returns on hover, giving the content the full page.
   A thin rail stays visible at the left edge as the hover target. */
.layout { display: block; }

.sidebar {
  position: fixed;
  top: 64px;
  left: 0;
  width: 250px;
  height: calc(100vh - 64px);
  background: var(--bg);
  border-right: 1px solid var(--border);
  transform: translateX(-100%);
  transition: transform .22s ease;
  z-index: 150;
}
.sidebar:hover,
.sidebar:focus-within { transform: translateX(0); }

/* The hover target lives outside the sidebar: the sidebar scrolls, and an
   overflow other than visible would clip a pseudo-element placed beside it. */
.sidebar-hint {
  position: fixed;
  left: 0;
  top: 64px;
  width: 20px;
  height: calc(100vh - 64px);
  z-index: 151;
  cursor: pointer;
}
/* Thin colour rail so it is discoverable */
.sidebar-hint::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0;
  width: 3px;
  height: 100%;
  background: linear-gradient(180deg, var(--amber), var(--blue), var(--green), var(--purple));
  opacity: .55;
  transition: opacity .22s ease;
}
body:has(.sidebar-hint:hover) .sidebar-hint::before { opacity: 0; }
body:has(.sidebar-hint:hover) .sidebar { transform: translateX(0); }

/* Hamburger in the top bar: same sidebar, but reachable by click, keyboard
   and touch — hover alone is invisible on iPads. */
.topbar-left { display: flex; align-items: center; gap: 12px; }
.sidebar-toggle {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  background: none;
  border: none;
  border-radius: 8px;
  color: var(--text-2);
  cursor: pointer;
  transition: color .15s, background .15s;
}
.sidebar-toggle:hover { color: var(--text); background: var(--surface-hover); }
body.sidebar-open .sidebar { transform: translateX(0); }
body.sidebar-open .sidebar-hint::before { opacity: 0; }

/* Content column: a share of the viewport, not a pixel width, so it adapts to
   whatever resolution the student is on. Centred, with the hidden sidebar
   overlaying it rather than pushing it. */
.main {
  max-width: 70%;
  margin: 0 auto;
}

/* Self-checking exercise: shown when the output matches data-forventet */
.course-check-praise {
  margin-top: 12px;
  padding: 12px 16px;
  border-radius: 10px;
  background: var(--green-dim);
  border: 1px solid var(--green-ring);
  color: var(--green);
  font-weight: 600;
  font-size: .95rem;
}
.course-check-praise.show { animation: praisePop .35s ease; }
@keyframes praisePop {
  from { opacity: 0; transform: translateY(-6px); }
  to   { opacity: 1; transform: none; }
}

/* Krav-liste i Prøv selv: samme KRAV-merke som i innleveringene */
.krav-list ul { list-style: none; margin: 0 0 4px; }
.krav-list li {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  padding: 6px 0;
  font-size: .86rem;
  line-height: 1.5;
  color: var(--text-2);
  border-bottom: 1px solid var(--border-muted);
  margin-bottom: 0;
}
.krav-list li:last-child { border-bottom: none; }
.krav-list li::before {
  content: 'KRAV';
  flex-shrink: 0;
  margin-top: 1px;
  font-size: .6rem;
  font-weight: 700;
  letter-spacing: .06em;
  padding: 2px 6px;
  border-radius: 4px;
  background: var(--amber-dim);
  color: var(--amber);
  border: 1px solid var(--amber-ring);
}

/* Stor og tydelig hovedregel, som «Bruk alltid f-streng ...» i modul 1 */
.callout-rule {
  margin: 22px 0;
  padding: 18px 22px;
  background: var(--amber-dim);
  border: 1px solid var(--amber-ring);
  border-left: 4px solid var(--amber);
  border-radius: 10px;
  color: var(--text);
  font-size: 1.15rem;
  font-weight: 700;
  line-height: 1.5;
}
.callout-rule p { margin: 0; max-width: none; }

/* Figur i modulinnholdet. Bildet er en illustrasjon, ikke en skjermdump, så
   det får ikke ramme slik oppgavebildet gjør — kanten ville lest som en boks
   ved siden av alle de andre boksene på sida. `max-width` i piksler, ikke
   prosent: bilda er laget i én bredde, og et diagram som strekkes forbi den
   blir bare uskarpt. */
.course-figure {
  margin: 22px 0;
  max-width: 560px;
}
.course-figure img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: 10px;
}
.course-figure figcaption {
  margin-top: 8px;
  font-size: .82rem;
  color: var(--text-3);
  line-height: 1.5;
}

/* Hint after a couple of unsuccessful runs */
.course-check-hint {
  margin-top: 12px;
  padding: 12px 16px;
  border-radius: 10px;
  background: var(--amber-dim);
  border: 1px solid var(--amber-ring);
  color: var(--amber);
  font-size: .9rem;
}

/* ── Gate: resten av modulen holdes skjult til selvsjekken er kjørt riktig ──
   Innleveringsseksjonen legges til containeren etter at dette stilarket er
   brukt, så skjuling på klasse virker uansett rekkefølge. */
.is-locked .gated-content,
.is-locked .assignments-section { display: none; }

.gate-note { display: none; }
.is-locked .gate-note {
  display: block;
  margin: 22px 0 8px;
  padding: 14px 18px;
  border: 1px dashed var(--border);
  border-radius: 10px;
  color: var(--text-2);
  font-size: .92rem;
}

/* ── Tastedrill: ett felt per tegn, med ansikt som snur når begge sitter ──
   Ingen lås. Innholdet under ligger dimmet og lyses opp, så eleven ser at
   noe venter uten å bli stoppet av det. */
.course-keys-rad {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 18px 0 4px;
}

.course-keys-ansikt {
  font-size: 1.5rem;
  line-height: 1;
  margin-right: 2px;
  transition: transform .25s ease;
}
.course-keys.ferdig .course-keys-ansikt { transform: scale(1.15); }

.course-keys-felt {
  width: 52px;
  height: 52px;
  text-align: center;
  font-family: var(--font-m);
  font-size: 1.5rem;
  color: var(--text);
  background: var(--surface);
  border: 2px solid var(--border);
  border-radius: 10px;
  transition: border-color .15s ease, background .15s ease, color .15s ease;
}
.course-keys-felt:focus {
  outline: none;
  border-color: var(--blue-ring);
}
.course-keys-felt[data-tilstand="riktig"] {
  border-color: var(--green);
  background: var(--green-dim);
  color: var(--green);
}
.course-keys-felt[data-tilstand="feil"] {
  border-color: var(--red);
  background: var(--red-dim);
  color: var(--red);
}

.course-keys-melding {
  margin: 10px 0 0;
  padding: 10px 14px;
  border-radius: 10px;
  font-size: .9rem;
}
.course-keys-melding[data-tilstand="hint"] {
  background: var(--amber-dim);
  border: 1px solid var(--amber-ring);
  color: var(--amber);
}
.course-keys-melding[data-tilstand="ok"] {
  background: var(--green-dim);
  border: 1px solid var(--green);
  color: var(--green);
}

.course-keys-dimmet {
  opacity: .3;
  transition: opacity .6s ease;
}
.course-keys.ferdig .course-keys-dimmet { opacity: 1; }

/* Editable cells match the static example cells */
.inline-editor-container .cm-editor,
.assignment-editor-container .cm-editor,
.inline-editor-container .cm-content,
.assignment-editor-container .cm-content { font-size: .82rem; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .reveal { opacity: 1; transform: none; transition: none; }
  .course-check-praise.show, .grading-wrap { animation: none; }
  .sidebar { transition: none; }
}

/* Norsk forklaring under Pythons engelske feilmelding (js/constants/feilhjelp.js).
   Den engelske meldingen blir stående — elevene skal lære å lese ekte
   feilmeldinger — så hjelpelinja må se ut som en fotnote, ikke som en del av
   tracebacken: egen farge, egen linje, litt luft over. */
.output-hjelp {
  display: block;
  margin-top: .6rem;
  padding-left: .75rem;
  border-left: 2px solid var(--blue-ring, var(--border));
  color: var(--text-2);
  white-space: pre-wrap;
}
.output-area.error .output-hjelp,
.output-area .error + .output-hjelp { color: var(--text-2); }

/* Antall oppgaver i innleveringen, og hva nivåfanene betyr.
   Begge er svar på at eleven ikke så hva som fantes: oppgave 2 ligger forbi
   vurderingsboksen til oppgave 1, og ★★ sa aldri om det var forventet. */
.assignments-antall {
  margin: -.35rem 0 1.1rem;
  color: var(--text-2);
  font-size: .95rem;
}
.asgn-nivaa-hjelp {
  margin: 0 0 .5rem;
  color: var(--text-2);
  font-size: .9rem;
}

/* Prøv selv mot innlevering.
   Haiku i kursgjennomgangen limte prøv selv-koden sin inn i innleveringens
   oppgave 2 og fikk 0 %. Vurderingen var korrekt, men de to flatene lignet
   for mye på hverandre til at hun så at hun hadde byttet kontekst.
   Innleveringen får derfor en egen, litt lilla bunn — samme aksentfarge som
   overskriften og nivåfanene allerede bruker — så den leses som et annet
   sted. color-mix mot --surface, ikke en ny token, så alle 17 temaene får
   nyansen gratis uten at KONTRAKT.md må utvides. */
.assignments-section {
  background: color-mix(in srgb, var(--purple) 6%, var(--surface-deep));
  border: 1px solid color-mix(in srgb, var(--purple) 22%, var(--border));
  border-radius: 16px;
  padding: 24px 24px 28px;
  margin-top: 32px;
}
.assignments-section .assignment-panel {
  background: color-mix(in srgb, var(--purple) 4%, var(--surface));
}

/* Merkelapp under hver taste-rute.
   Rutene sto umerket, så eleven måtte gjette hvilken som var `{` og hvilken
   som var `}` ut fra rekkefølgen i teksten over. `aria-hidden` fordi feltet
   allerede har et aria-label som sier det samme. */
.course-keys-boks {
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
}
.course-keys-lapp {
  font-family: var(--font-m);
  font-size: .8rem;
  line-height: 1;
  color: var(--text-3);
}

/* KaTeX kopieres som rot: nettleseren tar med både MathML-laget (skjult, men
   markerbart) og det synlige HTML-laget, så «E_k = ½mv²» ble til
   «Ek=12mv2E_k = \frac{1}{2}mv^2Ek​=21​mv2» når en elev limte den inn i notatene
   sine. MathML-laget er der for skjermlesere og skal bli der; det trenger bare
   ikke være med i en markering. Da kopieres den synlige formelen alene. */
.katex-mathml { user-select: none; -webkit-user-select: none; }
